1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3
4 #include "tomcrypt_private.h"
5
6 #ifdef LTC_MECC
7
8 typedef struct {
9 ltc_asn1_type t;
10 ltc_asn1_list **pp;
11 } der_flexi_check;
12
13 #define LTC_SET_DER_FLEXI_CHECK(list, index, Type, P) \
14 do { \
15 int LTC_SDFC_temp##__LINE__ = (index); \
16 list[LTC_SDFC_temp##__LINE__].t = Type; \
17 list[LTC_SDFC_temp##__LINE__].pp = P; \
18 } while (0)
19
s_der_flexi_sequence_cmp(const ltc_asn1_list * flexi,der_flexi_check * check)20 static int s_der_flexi_sequence_cmp(const ltc_asn1_list *flexi, der_flexi_check *check)
21 {
22 const ltc_asn1_list *cur;
23 if (flexi->type != LTC_ASN1_SEQUENCE) {
24 return CRYPT_INVALID_PACKET;
25 }
26 cur = flexi->child;
27 while(check->t != LTC_ASN1_EOL) {
28 if (!LTC_ASN1_IS_TYPE(cur, check->t)) {
29 return CRYPT_INVALID_PACKET;
30 }
31 if (check->pp != NULL) *check->pp = (ltc_asn1_list*)cur;
32 cur = cur->next;
33 check++;
34 }
35 return CRYPT_OK;
36 }
37
38 /* NOTE: s_der_decode_pkcs8_flexi & related stuff can be shared with rsa_import_pkcs8() */
39
ecc_import_pkcs8(const unsigned char * in,unsigned long inlen,const void * pwd,unsigned long pwdlen,ecc_key * key)40 int ecc_import_pkcs8(const unsigned char *in, unsigned long inlen,
41 const void *pwd, unsigned long pwdlen,
42 ecc_key *key)
43 {
44 void *a, *b, *gx, *gy;
45 unsigned long len, cofactor, n;
46 const char *pka_ec_oid;
47 int err;
48 char OID[256];
49 const ltc_ecc_curve *curve;
50 ltc_asn1_list *p = NULL, *l = NULL;
51 der_flexi_check flexi_should[7];
52 ltc_asn1_list *seq, *priv_key;
53
54 LTC_ARGCHK(in != NULL);
55 LTC_ARGCHK(key != NULL);
56 LTC_ARGCHK(ltc_mp.name != NULL);
57
58 /* get EC alg oid */
59 err = pk_get_oid(LTC_OID_EC, &pka_ec_oid);
60 if (err != CRYPT_OK) return err;
61
62 /* init key */
63 err = mp_init_multi(&a, &b, &gx, &gy, LTC_NULL);
64 if (err != CRYPT_OK) return err;
65
66
67 if ((err = pkcs8_decode_flexi(in, inlen, pwd, pwdlen, &l)) == CRYPT_OK) {
68
69 /* Setup for basic structure */
70 n=0;
71 LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_INTEGER, NULL);
72 LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_SEQUENCE, &seq);
73 LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_OCTET_STRING, &priv_key);
74 LTC_SET_DER_FLEXI_CHECK(flexi_should, n, LTC_ASN1_EOL, NULL);
75
76 if (((err = s_der_flexi_sequence_cmp(l, flexi_should)) == CRYPT_OK) &&
77 (pk_oid_cmp_with_asn1(pka_ec_oid, seq->child) == CRYPT_OK)) {
78 ltc_asn1_list *version, *field, *point, *point_g, *order, *p_cofactor;
79
80 /* Setup for CASE 2 */
81 n=0;
82 LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_INTEGER, &version);
83 LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_SEQUENCE, &field);
84 LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_SEQUENCE, &point);
85 LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_OCTET_STRING, &point_g);
86 LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_INTEGER, &order);
87 LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_INTEGER, &p_cofactor);
88 LTC_SET_DER_FLEXI_CHECK(flexi_should, n, LTC_ASN1_EOL, NULL);
89
90 if (LTC_ASN1_IS_TYPE(seq->child->next, LTC_ASN1_OBJECT_IDENTIFIER)) {
91 /* CASE 1: curve by OID (AKA short variant):
92 * 0:d=0 hl=2 l= 100 cons: SEQUENCE
93 * 2:d=1 hl=2 l= 1 prim: INTEGER :00
94 * 5:d=1 hl=2 l= 16 cons: SEQUENCE (== *seq)
95 * 7:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey
96 * 16:d=2 hl=2 l= 5 prim: OBJECT :(== *curve_oid (e.g. secp256k1 (== 1.3.132.0.10)))
97 * 23:d=1 hl=2 l= 77 prim: OCTET STRING :bytes (== *priv_key)
98 */
99 ltc_asn1_list *curve_oid = seq->child->next;
100 len = sizeof(OID);
101 if ((err = pk_oid_num_to_str(curve_oid->data, curve_oid->size, OID, &len)) != CRYPT_OK) { goto LBL_DONE; }
102 if ((err = ecc_find_curve(OID, &curve)) != CRYPT_OK) { goto LBL_DONE; }
103 if ((err = ecc_set_curve(curve, key)) != CRYPT_OK) { goto LBL_DONE; }
104 }
105 else if ((err = s_der_flexi_sequence_cmp(seq->child->next, flexi_should)) == CRYPT_OK) {
106 /* CASE 2: explicit curve parameters (AKA long variant):
107 * 0:d=0 hl=3 l= 227 cons: SEQUENCE
108 * 3:d=1 hl=2 l= 1 prim: INTEGER :00
109 * 6:d=1 hl=3 l= 142 cons: SEQUENCE (== *seq)
110 * 9:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey
111 * 18:d=2 hl=3 l= 130 cons: SEQUENCE
112 * 21:d=3 hl=2 l= 1 prim: INTEGER :01
113 * 24:d=3 hl=2 l= 44 cons: SEQUENCE (== *field)
114 * 26:d=4 hl=2 l= 7 prim: OBJECT :prime-field
115 * 35:d=4 hl=2 l= 33 prim: INTEGER :(== *prime / curve.prime)
116 * 70:d=3 hl=2 l= 6 cons: SEQUENCE (== *point)
117 * 72:d=4 hl=2 l= 1 prim: OCTET STRING :bytes (== curve.A)
118 * 75:d=4 hl=2 l= 1 prim: OCTET STRING :bytes (== curve.B)
119 * 78:d=3 hl=2 l= 33 prim: OCTET STRING :bytes (== *g_point / curve.G-point)
120 * 113:d=3 hl=2 l= 33 prim: INTEGER :(== *order / curve.order)
121 * 148:d=3 hl=2 l= 1 prim: INTEGER :(== curve.cofactor)
122 * 151:d=1 hl=2 l= 77 prim: OCTET STRING :bytes (== *priv_key)
123 */
124
125 if (mp_get_int(version->data) != 1) {
126 goto LBL_DONE;
127 }
128 cofactor = mp_get_int(p_cofactor->data);
129
130 if (LTC_ASN1_IS_TYPE(field->child, LTC_ASN1_OBJECT_IDENTIFIER) &&
131 LTC_ASN1_IS_TYPE(field->child->next, LTC_ASN1_INTEGER) &&
132 LTC_ASN1_IS_TYPE(point->child, LTC_ASN1_OCTET_STRING) &&
133 LTC_ASN1_IS_TYPE(point->child->next, LTC_ASN1_OCTET_STRING)) {
134
135 ltc_asn1_list *prime = field->child->next;
136 if ((err = mp_read_unsigned_bin(a, point->child->data, point->child->size)) != CRYPT_OK) {
137 goto LBL_DONE;
138 }
139 if ((err = mp_read_unsigned_bin(b, point->child->next->data, point->child->next->size)) != CRYPT_OK) {
140 goto LBL_DONE;
141 }
142 if ((err = ltc_ecc_import_point(point_g->data, point_g->size, prime->data, a, b, gx, gy)) != CRYPT_OK) {
143 goto LBL_DONE;
144 }
145 if ((err = ecc_set_curve_from_mpis(a, b, prime->data, order->data, gx, gy, cofactor, key)) != CRYPT_OK) {
146 goto LBL_DONE;
147 }
148 }
149 }
150 else {
151 err = CRYPT_INVALID_PACKET;
152 goto LBL_DONE;
153 }
154
155 /* load private key value 'k' */
156 len = priv_key->size;
157 if ((err = der_decode_sequence_flexi(priv_key->data, &len, &p)) == CRYPT_OK) {
158 if (p->type == LTC_ASN1_SEQUENCE &&
159 LTC_ASN1_IS_TYPE(p->child, LTC_ASN1_INTEGER) &&
160 LTC_ASN1_IS_TYPE(p->child->next, LTC_ASN1_OCTET_STRING)) {
161 ltc_asn1_list *lk = p->child->next;
162 if (mp_cmp_d(p->child->data, 1) != LTC_MP_EQ) {
163 err = CRYPT_INVALID_PACKET;
164 goto LBL_ECCFREE;
165 }
166 if ((err = ecc_set_key(lk->data, lk->size, PK_PRIVATE, key)) != CRYPT_OK) {
167 goto LBL_ECCFREE;
168 }
169 goto LBL_DONE; /* success */
170 }
171 }
172 }
173 }
174 err = CRYPT_INVALID_PACKET;
175 goto LBL_DONE;
176
177 LBL_ECCFREE:
178 ecc_free(key);
179 LBL_DONE:
180 mp_clear_multi(a, b, gx, gy, LTC_NULL);
181 if (l) der_free_sequence_flexi(l);
182 if (p) der_free_sequence_flexi(p);
183 return err;
184 }
185
186 #endif
187