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