1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4
5 #ifdef LTC_MECC
6
s_ecc_import_x509_with_oid(const unsigned char * in,unsigned long inlen,ecc_key * key)7 static int s_ecc_import_x509_with_oid(const unsigned char *in, unsigned long inlen, ecc_key *key)
8 {
9 unsigned char bin_xy[2*ECC_MAXSIZE+2];
10 unsigned long curveoid[16];
11 unsigned long len_xy, len_oid, len;
12 char OID[256];
13 const ltc_ecc_curve *curve;
14 int err;
15
16 len_xy = sizeof(bin_xy);
17 len_oid = 16;
18 err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_EC, bin_xy, &len_xy,
19 LTC_ASN1_OBJECT_IDENTIFIER, (void *)curveoid, &len_oid);
20 if (err == CRYPT_OK) {
21 /* load curve parameters for given curve OID */
22 len = sizeof(OID);
23 if ((err = pk_oid_num_to_str(curveoid, len_oid, OID, &len)) != CRYPT_OK) { goto error; }
24 if ((err = ecc_find_curve(OID, &curve)) != CRYPT_OK) { goto error; }
25 if ((err = ecc_set_curve(curve, key)) != CRYPT_OK) { goto error; }
26 /* load public key */
27 err = ecc_set_key(bin_xy, len_xy, PK_PUBLIC, key);
28 }
29 error:
30 return err;
31 }
32
s_ecc_import_x509_with_curve(const unsigned char * in,unsigned long inlen,ecc_key * key)33 static int s_ecc_import_x509_with_curve(const unsigned char *in, unsigned long inlen, ecc_key *key)
34 {
35 void *prime, *order, *a, *b, *gx, *gy;
36 ltc_asn1_list seq_fieldid[2], seq_curve[3], seq_ecparams[6];
37 unsigned char bin_a[ECC_MAXSIZE], bin_b[ECC_MAXSIZE];
38 unsigned char bin_g[2*ECC_MAXSIZE+1], bin_xy[2*ECC_MAXSIZE+2], bin_seed[128];
39 unsigned long len_a, len_b, len_g, len_xy, len;
40 unsigned long cofactor = 0, ecver = 0, tmpoid[16];
41 int err;
42
43 if ((err = mp_init_multi(&prime, &order, &a, &b, &gx, &gy, LTC_NULL)) != CRYPT_OK) {
44 return err;
45 }
46
47 /* ECParameters SEQUENCE */
48 LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &ecver, 1UL);
49 LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL);
50 LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 3UL);
51 LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, sizeof(bin_g));
52 LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL);
53 LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL);
54 seq_ecparams[5].optional = 1;
55 /* FieldID SEQUENCE */
56 LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, 16UL);
57 LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL);
58 /* Curve SEQUENCE */
59 LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, sizeof(bin_a));
60 LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, sizeof(bin_b));
61 LTC_SET_ASN1(seq_curve, 2, LTC_ASN1_RAW_BIT_STRING, bin_seed, 8u*sizeof(bin_seed));
62 seq_curve[2].optional = 1;
63 /* try to load public key */
64 len_xy = sizeof(bin_xy);
65 len = 6;
66 err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_EC, bin_xy, &len_xy, LTC_ASN1_SEQUENCE, seq_ecparams, &len);
67
68 if (err == CRYPT_OK) {
69 len_a = seq_curve[0].size;
70 len_b = seq_curve[1].size;
71 len_g = seq_ecparams[3].size;
72 /* create bignums */
73 if ((err = mp_read_unsigned_bin(a, bin_a, len_a)) != CRYPT_OK) { goto error; }
74 if ((err = mp_read_unsigned_bin(b, bin_b, len_b)) != CRYPT_OK) { goto error; }
75 if ((err = ltc_ecc_import_point(bin_g, len_g, prime, a, b, gx, gy)) != CRYPT_OK) { goto error; }
76 /* load curve parameters */
77 if ((err = ecc_set_curve_from_mpis(a, b, prime, order, gx, gy, cofactor, key)) != CRYPT_OK) { goto error; }
78 /* load public key */
79 err = ecc_set_key(bin_xy, len_xy, PK_PUBLIC, key);
80 }
81 error:
82 mp_clear_multi(prime, order, a, b, gx, gy, LTC_NULL);
83 return err;
84 }
85
ecc_import_subject_public_key_info(const unsigned char * in,unsigned long inlen,ecc_key * key)86 int ecc_import_subject_public_key_info(const unsigned char *in, unsigned long inlen, ecc_key *key)
87 {
88 int err;
89
90 if ((err = s_ecc_import_x509_with_oid(in, inlen, key)) == CRYPT_OK) {
91 goto success;
92 }
93
94 err = s_ecc_import_x509_with_curve(in, inlen, key);
95
96 success:
97 return err;
98 }
99
100 /**
101 Import an ECC key from a X.509 certificate
102 @param in The packet to import from
103 @param inlen It's length (octets)
104 @param key [out] Destination for newly imported key
105 @return CRYPT_OK if successful, upon error allocated memory is freed
106 */
ecc_import_x509(const unsigned char * in,unsigned long inlen,ecc_key * key)107 int ecc_import_x509(const unsigned char *in, unsigned long inlen, ecc_key *key)
108 {
109 return x509_decode_public_key_from_certificate(in, inlen,
110 LTC_OID_EC,
111 LTC_ASN1_EOL, NULL, NULL,
112 (public_key_decode_cb)ecc_import_subject_public_key_info, key);
113 }
114
115 #endif /* LTC_MECC */
116
117