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