| // SPDX-License-Identifier: BSD-2-Clause |
| /* LibTomCrypt, modular cryptographic library -- Tom St Denis |
| * |
| * LibTomCrypt is a library that provides various cryptographic |
| * algorithms in a highly modular and flexible manner. |
| * |
| * The library is free for all purposes without any express |
| * guarantee it works. |
| */ |
| #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_find_curve(OID, &curve)) != CRYPT_OK) { goto error; } |
| if ((err = ecc_set_curve(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_curve_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 |
| @param in The packet to import from |
| @param inlen It's length (octets) |
| @param key [out] Destination for newly imported key |
| @return CRYPT_OK if successful, upon error allocated memory is freed |
| */ |
| int ecc_import_x509(const unsigned char *in, unsigned long inlen, ecc_key *key) |
| { |
| return x509_decode_public_key_from_certificate(in, inlen, PKA_EC, LTC_ASN1_EOL, NULL, NULL, NULL, key); |
| } |
| |
| #endif /* LTC_MECC */ |
| |
| |
| /* ref: $Format:%D$ */ |
| /* git commit: $Format:%H$ */ |
| /* commit time: $Format:%ai$ */ |