diff --git a/src/ltc/headers/tomcrypt_private.h b/src/ltc/headers/tomcrypt_private.h index 865b7ad..eeabfc2 100644 --- a/src/ltc/headers/tomcrypt_private.h +++ b/src/ltc/headers/tomcrypt_private.h @@ -195,6 +195,7 @@ int ecc_set_dp_from_mpis(void *a, void *b, void *prime, void *order, void *gx, void *gy, unsigned long cofactor, ecc_key *key); int ecc_copy_dp(const ecc_key *srckey, ecc_key *key); int ecc_set_dp_by_size(int size, ecc_key *key); +int ecc_import_subject_public_key_info(const unsigned char *in, unsigned long inlen, ecc_key *key); /* low level functions */ ecc_point *ltc_ecc_new_point(void); diff --git a/src/ltc/pk/ecc/ecc_import_openssl.c b/src/ltc/pk/ecc/ecc_import_openssl.c index bf34c08..4282058 100644 --- a/src/ltc/pk/ecc/ecc_import_openssl.c +++ b/src/ltc/pk/ecc/ecc_import_openssl.c @@ -11,84 +11,22 @@ #ifdef LTC_MECC -int ecc_import_openssl(const unsigned char *in, unsigned long inlen, ecc_key *key) +static int _ecc_import_private_with_oid(const unsigned char *in, unsigned long inlen, ecc_key *key) { - void *prime, *order, *a, *b, *gx, *gy; - ltc_asn1_list seq_fieldid[2], seq_curve[3], seq_ecparams[6], seq_priv[4], custom[2]; - unsigned char bin_a[ECC_MAXSIZE], bin_b[ECC_MAXSIZE], bin_k[ECC_MAXSIZE]; - unsigned char bin_g[2*ECC_MAXSIZE+1], bin_xy[2*ECC_MAXSIZE+2], bin_seed[128]; - unsigned long len_a, len_b, len_k, len_g, len_xy, len_oid, len; - unsigned long cofactor = 0, ecver = 0, pkver = 0, tmpoid[16], curveoid[16]; + ltc_asn1_list seq_priv[4], custom[2]; + unsigned char bin_xy[2*ECC_MAXSIZE+2], bin_k[ECC_MAXSIZE]; + unsigned long len, pkver = 0, curveoid[16]; char OID[256]; const ltc_ecc_curve *curve; int err; - if ((err = mp_init_multi(&prime, &order, &a, &b, &gx, &gy, NULL)) != CRYPT_OK) { - return err; - } - - /* ### 1. try to load public key - no curve parameters just curve OID */ - - len_xy = sizeof(bin_xy); - len_oid = 16; - err = x509_decode_subject_public_key_info(in, inlen, PKA_EC, bin_xy, &len_xy, - LTC_ASN1_OBJECT_IDENTIFIER, (void *)curveoid, &len_oid); - if (err == CRYPT_OK) { - /* load curve parameters for given curve OID */ - len = sizeof(OID); - if ((err = pk_oid_num_to_str(curveoid, len_oid, OID, &len)) != CRYPT_OK) { goto error; } - if ((err = ecc_get_curve(OID, &curve)) != CRYPT_OK) { goto error; } - if ((err = ecc_set_dp(curve, key)) != CRYPT_OK) { goto error; } - /* load public key */ - if ((err = ecc_set_key(bin_xy, len_xy, PK_PUBLIC, key)) != CRYPT_OK) { goto error; } - goto success; - } - - /* ### 2. try to load public key - curve parameters included */ - - /* ECParameters SEQUENCE */ - LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &ecver, 1UL); - LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL); - LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 3UL); - LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, (unsigned long)2*ECC_MAXSIZE+1); - LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL); - LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL); - seq_ecparams[5].optional = 1; - /* FieldID SEQUENCE */ - LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, 16UL); - LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL); - /* Curve SEQUENCE */ - LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, (unsigned long)ECC_MAXSIZE); - LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, (unsigned long)ECC_MAXSIZE); - LTC_SET_ASN1(seq_curve, 2, LTC_ASN1_RAW_BIT_STRING, bin_seed, (unsigned long)8*128); - seq_curve[2].optional = 1; - /* try to load public key */ - len_xy = sizeof(bin_xy); - len = 6; - err = x509_decode_subject_public_key_info(in, inlen, PKA_EC, bin_xy, &len_xy, LTC_ASN1_SEQUENCE, seq_ecparams, &len); - - if (err == CRYPT_OK) { - len_a = seq_curve[0].size; - len_b = seq_curve[1].size; - len_g = seq_ecparams[3].size; - /* create bignums */ - if ((err = mp_read_unsigned_bin(a, bin_a, len_a)) != CRYPT_OK) { goto error; } - if ((err = mp_read_unsigned_bin(b, bin_b, len_b)) != CRYPT_OK) { goto error; } - if ((err = ltc_ecc_import_point(bin_g, len_g, prime, a, b, gx, gy)) != CRYPT_OK) { goto error; } - /* load curve parameters */ - if ((err = ecc_set_dp_from_mpis(a, b, prime, order, gx, gy, cofactor, key)) != CRYPT_OK) { goto error; } - /* load public key */ - if ((err = ecc_set_key(bin_xy, len_xy, PK_PUBLIC, key)) != CRYPT_OK) { goto error; } - goto success; - } - - /* ### 3. try to load private key - no curve parameters just curve OID */ + /* ### try to load private key - no curve parameters just curve OID */ /* ECPrivateKey SEQUENCE */ LTC_SET_ASN1(custom, 0, LTC_ASN1_OBJECT_IDENTIFIER, curveoid, 16UL); - LTC_SET_ASN1(custom, 1, LTC_ASN1_RAW_BIT_STRING, bin_xy, (unsigned long)8*(2*ECC_MAXSIZE+2)); + LTC_SET_ASN1(custom, 1, LTC_ASN1_RAW_BIT_STRING, bin_xy, 8u*sizeof(bin_xy)); LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &pkver, 1UL); - LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, (unsigned long)ECC_MAXSIZE); + LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, sizeof(bin_k)); LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 2, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0, custom); /* context specific 0 */ LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 3, LTC_ASN1_CL_CONTEXT_SPECIFIC, 1, custom + 1); /* context specific 1 */ @@ -101,24 +39,40 @@ if ((err = ecc_get_curve(OID, &curve)) != CRYPT_OK) { goto error; } if ((err = ecc_set_dp(curve, key)) != CRYPT_OK) { goto error; } /* load private+public key */ - if ((err = ecc_set_key(bin_k, seq_priv[1].size, PK_PRIVATE, key)) != CRYPT_OK) { goto error; } - goto success; + err = ecc_set_key(bin_k, seq_priv[1].size, PK_PRIVATE, key); + } +error: + return err; +} + +static int _ecc_import_private_with_curve(const unsigned char *in, unsigned long inlen, ecc_key *key) +{ + void *prime, *order, *a, *b, *gx, *gy; + ltc_asn1_list seq_fieldid[2], seq_curve[3], seq_ecparams[6], seq_priv[4], custom[2]; + unsigned char bin_a[ECC_MAXSIZE], bin_b[ECC_MAXSIZE], bin_k[ECC_MAXSIZE]; + unsigned char bin_g[2*ECC_MAXSIZE+1], bin_xy[2*ECC_MAXSIZE+2], bin_seed[128]; + unsigned long len_a, len_b, len_k, len_g; + unsigned long cofactor = 0, ecver = 0, pkver = 0, tmpoid[16]; + int err; + + if ((err = mp_init_multi(&prime, &order, &a, &b, &gx, &gy, NULL)) != CRYPT_OK) { + return err; } - /* ### 4. try to load private key - curve parameters included */ + /* ### try to load private key - curve parameters included */ /* ECPrivateKey SEQUENCE */ LTC_SET_ASN1(custom, 0, LTC_ASN1_SEQUENCE, seq_ecparams, 6UL); - LTC_SET_ASN1(custom, 1, LTC_ASN1_RAW_BIT_STRING, bin_xy, (unsigned long)8*(2*ECC_MAXSIZE+2)); + LTC_SET_ASN1(custom, 1, LTC_ASN1_RAW_BIT_STRING, bin_xy, 8u*sizeof(bin_xy)); LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &pkver, 1UL); - LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, (unsigned long)ECC_MAXSIZE); + LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, sizeof(bin_k)); LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 2, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0, custom); /* context specific 0 */ LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 3, LTC_ASN1_CL_CONTEXT_SPECIFIC, 1, custom + 1); /* context specific 1 */ /* ECParameters SEQUENCE */ LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &ecver, 1UL); LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL); LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 3UL); - LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, (unsigned long)2*ECC_MAXSIZE+1); + LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, sizeof(bin_g)); LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL); LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL); seq_ecparams[5].optional = 1; @@ -126,14 +80,13 @@ LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, 16UL); LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL); /* Curve SEQUENCE */ - LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, (unsigned long)ECC_MAXSIZE); - LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, (unsigned long)ECC_MAXSIZE); - LTC_SET_ASN1(seq_curve, 2, LTC_ASN1_RAW_BIT_STRING, bin_seed, (unsigned long)8*128); + LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, sizeof(bin_a)); + LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, sizeof(bin_b)); + LTC_SET_ASN1(seq_curve, 2, LTC_ASN1_RAW_BIT_STRING, bin_seed, sizeof(bin_seed)); seq_curve[2].optional = 1; /* try to load private key */ err = der_decode_sequence(in, inlen, seq_priv, 4); if (err == CRYPT_OK) { - len_xy = custom[1].size; len_k = seq_priv[1].size; len_a = seq_curve[0].size; len_b = seq_curve[1].size; @@ -145,17 +98,28 @@ /* load curve parameters */ if ((err = ecc_set_dp_from_mpis(a, b, prime, order, gx, gy, cofactor, key)) != CRYPT_OK) { goto error; } /* load private+public key */ - if ((err = ecc_set_key(bin_k, len_k, PK_PRIVATE, key)) != CRYPT_OK) { goto error; } + err = ecc_set_key(bin_k, len_k, PK_PRIVATE, key); + } +error: + mp_clear_multi(prime, order, a, b, gx, gy, NULL); + return err; +} + +int ecc_import_openssl(const unsigned char *in, unsigned long inlen, ecc_key *key) +{ + int err; + + if ((err = ecc_import_subject_public_key_info(in, inlen, key)) == CRYPT_OK) { goto success; } - /* ### 5. all attempts failed */ - goto error; + if ((err = _ecc_import_private_with_oid(in, inlen, key)) == CRYPT_OK) { + goto success; + } + + err = _ecc_import_private_with_curve(in, inlen, key); success: - err = CRYPT_OK; -error: - mp_clear_multi(prime, order, a, b, gx, gy, NULL); return err; } diff --git a/src/ltc/pk/ecc/ecc_import_x509.c b/src/ltc/pk/ecc/ecc_import_x509.c index 786e095..2e7eb10 100644 --- a/src/ltc/pk/ecc/ecc_import_x509.c +++ b/src/ltc/pk/ecc/ecc_import_x509.c @@ -9,6 +9,99 @@ #include "tomcrypt_private.h" #ifdef LTC_MECC + +static int _ecc_import_x509_with_oid(const unsigned char *in, unsigned long inlen, ecc_key *key) +{ + unsigned char bin_xy[2*ECC_MAXSIZE+2]; + unsigned long curveoid[16]; + unsigned long len_xy, len_oid, len; + char OID[256]; + const ltc_ecc_curve *curve; + int err; + + len_xy = sizeof(bin_xy); + len_oid = 16; + err = x509_decode_subject_public_key_info(in, inlen, PKA_EC, bin_xy, &len_xy, + LTC_ASN1_OBJECT_IDENTIFIER, (void *)curveoid, &len_oid); + if (err == CRYPT_OK) { + /* load curve parameters for given curve OID */ + len = sizeof(OID); + if ((err = pk_oid_num_to_str(curveoid, len_oid, OID, &len)) != CRYPT_OK) { goto error; } + if ((err = ecc_get_curve(OID, &curve)) != CRYPT_OK) { goto error; } + if ((err = ecc_set_dp(curve, key)) != CRYPT_OK) { goto error; } + /* load public key */ + err = ecc_set_key(bin_xy, len_xy, PK_PUBLIC, key); + } +error: + return err; +} + +static int _ecc_import_x509_with_curve(const unsigned char *in, unsigned long inlen, ecc_key *key) +{ + void *prime, *order, *a, *b, *gx, *gy; + ltc_asn1_list seq_fieldid[2], seq_curve[3], seq_ecparams[6]; + unsigned char bin_a[ECC_MAXSIZE], bin_b[ECC_MAXSIZE]; + unsigned char bin_g[2*ECC_MAXSIZE+1], bin_xy[2*ECC_MAXSIZE+2], bin_seed[128]; + unsigned long len_a, len_b, len_g, len_xy, len; + unsigned long cofactor = 0, ecver = 0, tmpoid[16]; + int err; + + if ((err = mp_init_multi(&prime, &order, &a, &b, &gx, &gy, NULL)) != CRYPT_OK) { + return err; + } + + /* ECParameters SEQUENCE */ + LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &ecver, 1UL); + LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL); + LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 3UL); + LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, sizeof(bin_g)); + LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL); + LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL); + seq_ecparams[5].optional = 1; + /* FieldID SEQUENCE */ + LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, 16UL); + LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL); + /* Curve SEQUENCE */ + LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, sizeof(bin_a)); + LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, sizeof(bin_b)); + LTC_SET_ASN1(seq_curve, 2, LTC_ASN1_RAW_BIT_STRING, bin_seed, 8u*sizeof(bin_seed)); + seq_curve[2].optional = 1; + /* try to load public key */ + len_xy = sizeof(bin_xy); + len = 6; + err = x509_decode_subject_public_key_info(in, inlen, PKA_EC, bin_xy, &len_xy, LTC_ASN1_SEQUENCE, seq_ecparams, &len); + + if (err == CRYPT_OK) { + len_a = seq_curve[0].size; + len_b = seq_curve[1].size; + len_g = seq_ecparams[3].size; + /* create bignums */ + if ((err = mp_read_unsigned_bin(a, bin_a, len_a)) != CRYPT_OK) { goto error; } + if ((err = mp_read_unsigned_bin(b, bin_b, len_b)) != CRYPT_OK) { goto error; } + if ((err = ltc_ecc_import_point(bin_g, len_g, prime, a, b, gx, gy)) != CRYPT_OK) { goto error; } + /* load curve parameters */ + if ((err = ecc_set_dp_from_mpis(a, b, prime, order, gx, gy, cofactor, key)) != CRYPT_OK) { goto error; } + /* load public key */ + err = ecc_set_key(bin_xy, len_xy, PK_PUBLIC, key); + } +error: + mp_clear_multi(prime, order, a, b, gx, gy, NULL); + return err; +} + +int ecc_import_subject_public_key_info(const unsigned char *in, unsigned long inlen, ecc_key *key) +{ + int err; + + if ((err = _ecc_import_x509_with_oid(in, inlen, key)) == CRYPT_OK) { + goto success; + } + + err = _ecc_import_x509_with_curve(in, inlen, key); + +success: + return err; +} /** Import an ECC key from a X.509 certificate @@ -38,7 +131,7 @@ l->child && l->child->type == LTC_ASN1_SEQUENCE && l->child->child && l->child->child->type == LTC_ASN1_OBJECT_IDENTIFIER && l->child->next && l->child->next->type == LTC_ASN1_BIT_STRING) { - err = ecc_import_openssl(l->data, l->size, key); + err = ecc_import_subject_public_key_info(l->data, l->size, key); goto LBL_DONE; } l = l->next;