Mercurial > dropbear
comparison keyimport.c @ 806:71e7d31f7671 ecc
hackish ECC import code from OpenSSH
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Thu, 23 May 2013 22:18:33 +0800 |
parents | 70625eed40c9 |
children | 75509065db53 |
comparison
equal
deleted
inserted
replaced
805:724c3e0c8734 | 806:71e7d31f7671 |
---|---|
34 | 34 |
35 #include "keyimport.h" | 35 #include "keyimport.h" |
36 #include "bignum.h" | 36 #include "bignum.h" |
37 #include "buffer.h" | 37 #include "buffer.h" |
38 #include "dbutil.h" | 38 #include "dbutil.h" |
39 #include "ecc.h" | |
40 | |
41 const unsigned char OID_SEC256R1_BLOB[] = {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07}; | |
42 const unsigned char OID_SEC384R1_BLOB[] = {0x2b, 0x81, 0x04, 0x00, 0x22}; | |
43 const unsigned char OID_SEC521R1_BLOB[] = {0x2b, 0x81, 0x04, 0x00, 0x23}; | |
39 | 44 |
40 #define PUT_32BIT(cp, value) do { \ | 45 #define PUT_32BIT(cp, value) do { \ |
41 (cp)[3] = (unsigned char)(value); \ | 46 (cp)[3] = (unsigned char)(value); \ |
42 (cp)[2] = (unsigned char)((value) >> 8); \ | 47 (cp)[2] = (unsigned char)((value) >> 8); \ |
43 (cp)[1] = (unsigned char)((value) >> 16); \ | 48 (cp)[1] = (unsigned char)((value) >> 16); \ |
156 keytype = DROPBEAR_SIGNKEY_DSS; | 161 keytype = DROPBEAR_SIGNKEY_DSS; |
157 } | 162 } |
158 #endif | 163 #endif |
159 | 164 |
160 buf = buf_new(MAX_PRIVKEY_SIZE); | 165 buf = buf_new(MAX_PRIVKEY_SIZE); |
161 buf_put_priv_key(buf, key, keytype); | 166 buf_put_priv_key(buf, key, key->type); |
162 | 167 |
163 fp = fopen(filename, "w"); | 168 fp = fopen(filename, "w"); |
164 if (!fp) { | 169 if (!fp) { |
165 ret = 0; | 170 ret = 0; |
166 goto out; | 171 goto out; |
521 int type; | 526 int type; |
522 | 527 |
523 sign_key *retkey; | 528 sign_key *retkey; |
524 buffer * blobbuf = NULL; | 529 buffer * blobbuf = NULL; |
525 | 530 |
531 retkey = new_sign_key(); | |
532 | |
526 key = load_openssh_key(filename); | 533 key = load_openssh_key(filename); |
527 | 534 |
528 if (!key) | 535 if (!key) |
529 return NULL; | 536 return NULL; |
530 | 537 |
597 /* Expect a load of INTEGERs. */ | 604 /* Expect a load of INTEGERs. */ |
598 if (key->type == OSSH_RSA) | 605 if (key->type == OSSH_RSA) |
599 num_integers = 9; | 606 num_integers = 9; |
600 else if (key->type == OSSH_DSA) | 607 else if (key->type == OSSH_DSA) |
601 num_integers = 6; | 608 num_integers = 6; |
609 else if (key->type == OSSH_EC) | |
610 num_integers = 1; | |
602 | 611 |
603 /* | 612 /* |
604 * Space to create key blob in. | 613 * Space to create key blob in. |
605 */ | 614 */ |
606 blobbuf = buf_new(3000); | 615 blobbuf = buf_new(3000); |
620 errmsg = "ASN.1 decoding failure"; | 629 errmsg = "ASN.1 decoding failure"; |
621 goto error; | 630 goto error; |
622 } | 631 } |
623 | 632 |
624 if (i == 0) { | 633 if (i == 0) { |
625 /* | 634 /* First integer is a version indicator */ |
626 * The first integer should be zero always (I think | 635 int expected; |
627 * this is some sort of version indication). | 636 switch (key->type) { |
628 */ | 637 case OSSH_RSA: |
629 if (len != 1 || p[0] != 0) { | 638 case OSSH_DSA: |
639 expected = 0; | |
640 break; | |
641 case OSSH_EC: | |
642 expected = 1; | |
643 break; | |
644 } | |
645 if (len != 1 || p[0] != expected) { | |
630 errmsg = "Version number mismatch"; | 646 errmsg = "Version number mismatch"; |
631 goto error; | 647 goto error; |
632 } | 648 } |
633 } else if (key->type == OSSH_RSA) { | 649 } else if (key->type == OSSH_RSA) { |
634 /* | 650 /* |
655 | 671 |
656 /* Skip past the number. */ | 672 /* Skip past the number. */ |
657 p += len; | 673 p += len; |
658 } | 674 } |
659 | 675 |
676 #ifdef DROPBEAR_ECDSA | |
677 if (key->type == OSSH_EC) { | |
678 const char* ecdsa_name; | |
679 unsigned char* private_key_bytes = NULL; | |
680 int private_key_len = 0; | |
681 unsigned char* public_key_bytes = NULL; | |
682 int public_key_len = 0; | |
683 ecc_key *ecc; | |
684 const struct dropbear_ecc_curve *curve = NULL; | |
685 | |
686 // See SEC1 v2, Appendix C.4 | |
687 // OpenSSL (so OpenSSH) seems to include the optional parts. | |
688 | |
689 // privateKey OCTET STRING, | |
690 ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, | |
691 &id, &len, &flags); | |
692 p += ret; | |
693 // id==4 for octet string | |
694 if (ret < 0 || id != 4 || | |
695 key->keyblob+key->keyblob_len-p < len) { | |
696 errmsg = "ASN.1 decoding failure"; | |
697 goto error; | |
698 } | |
699 private_key_bytes = p; | |
700 private_key_len = len; | |
701 p += len; | |
702 | |
703 // parameters [0] ECDomainParameters {{ SECGCurveNames }} OPTIONAL, | |
704 ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, | |
705 &id, &len, &flags); | |
706 p += ret; | |
707 // id==0 | |
708 if (ret < 0 || id != 0) { | |
709 errmsg = "ASN.1 decoding failure"; | |
710 goto error; | |
711 } | |
712 | |
713 ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, | |
714 &id, &len, &flags); | |
715 p += ret; | |
716 // id==6 for object | |
717 if (ret < 0 || id != 6 || | |
718 key->keyblob+key->keyblob_len-p < len) { | |
719 errmsg = "ASN.1 decoding failure"; | |
720 goto error; | |
721 } | |
722 | |
723 if (len == sizeof(OID_SEC256R1_BLOB) | |
724 && memcmp(p, OID_SEC256R1_BLOB, len) == 0) { | |
725 retkey->type = DROPBEAR_SIGNKEY_ECDSA_NISTP256; | |
726 curve = &ecc_curve_nistp256; | |
727 } else if (len == sizeof(OID_SEC384R1_BLOB) | |
728 && memcmp(p, OID_SEC384R1_BLOB, len) == 0) { | |
729 retkey->type = DROPBEAR_SIGNKEY_ECDSA_NISTP384; | |
730 curve = &ecc_curve_nistp384; | |
731 } else if (len == sizeof(OID_SEC521R1_BLOB) | |
732 && memcmp(p, OID_SEC521R1_BLOB, len) == 0) { | |
733 retkey->type = DROPBEAR_SIGNKEY_ECDSA_NISTP521; | |
734 curve = &ecc_curve_nistp521; | |
735 } else { | |
736 errmsg = "Unknown ECC key type"; | |
737 goto error; | |
738 } | |
739 p += len; | |
740 | |
741 // publicKey [1] BIT STRING OPTIONAL | |
742 ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, | |
743 &id, &len, &flags); | |
744 p += ret; | |
745 // id==1 | |
746 if (ret < 0 || id != 1) { | |
747 errmsg = "ASN.1 decoding failure"; | |
748 goto error; | |
749 } | |
750 | |
751 ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, | |
752 &id, &len, &flags); | |
753 p += ret; | |
754 // id==3 for bit string | |
755 if (ret < 0 || id != 3 || | |
756 key->keyblob+key->keyblob_len-p < len) { | |
757 errmsg = "ASN.1 decoding failure"; | |
758 goto error; | |
759 } | |
760 public_key_bytes = p+1; | |
761 public_key_len = len-1; | |
762 p += len; | |
763 | |
764 buf_putbytes(blobbuf, public_key_bytes, public_key_len); | |
765 ecc = buf_get_ecc_raw_pubkey(blobbuf, curve); | |
766 if (!ecc) { | |
767 errmsg = "Error parsing ECC key"; | |
768 goto error; | |
769 } | |
770 m_mp_alloc_init_multi((mp_int**)&ecc->k, NULL); | |
771 if (mp_read_unsigned_bin(ecc->k, private_key_bytes, private_key_len) | |
772 != MP_OKAY) { | |
773 errmsg = "Error parsing ECC key"; | |
774 goto error; | |
775 } | |
776 | |
777 retkey->ecckey = ecc; | |
778 } | |
779 #endif // DROPBEAR_ECDSA | |
780 | |
660 /* | 781 /* |
661 * Now put together the actual key. Simplest way to do this is | 782 * Now put together the actual key. Simplest way to do this is |
662 * to assemble our own key blobs and feed them to the createkey | 783 * to assemble our own key blobs and feed them to the createkey |
663 * functions; this is a bit faffy but it does mean we get all | 784 * functions; this is a bit faffy but it does mean we get all |
664 * the sanity checks for free. | 785 * the sanity checks for free. |
665 */ | 786 */ |
666 retkey = new_sign_key(); | 787 if (key->type == OSSH_RSA || key->type == OSSH_DSA) { |
667 buf_setpos(blobbuf, 0); | 788 buf_setpos(blobbuf, 0); |
668 type = DROPBEAR_SIGNKEY_ANY; | 789 type = DROPBEAR_SIGNKEY_ANY; |
669 if (buf_get_priv_key(blobbuf, retkey, &type) | 790 if (buf_get_priv_key(blobbuf, retkey, &type) |
670 != DROPBEAR_SUCCESS) { | 791 != DROPBEAR_SUCCESS) { |
671 errmsg = "unable to create key structure"; | 792 errmsg = "unable to create key structure"; |
672 sign_key_free(retkey); | 793 sign_key_free(retkey); |
673 retkey = NULL; | 794 retkey = NULL; |
674 goto error; | 795 goto error; |
796 } | |
675 } | 797 } |
676 | 798 |
677 errmsg = NULL; /* no error */ | 799 errmsg = NULL; /* no error */ |
678 retval = retkey; | 800 retval = retkey; |
679 | 801 |