summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authortb <>2023-09-24 07:58:31 +0000
committertb <>2023-09-24 07:58:31 +0000
commit4111be207f8fb552e058c9b65c82d9721cc1aebf (patch)
treea351aaa8d69dfcf6c70d2bf45af2fd2db1078ada /src
parent234cca4ed3a01d575f5e8abd395b332e99390f7a (diff)
downloadopenbsd-4111be207f8fb552e058c9b65c82d9721cc1aebf.tar.gz
openbsd-4111be207f8fb552e058c9b65c82d9721cc1aebf.tar.bz2
openbsd-4111be207f8fb552e058c9b65c82d9721cc1aebf.zip
Refactor eckey_{param2type,type2param}()
EC key parameters can be determined by an OID or they can be explicitly encoded. The confusingly named eckey_{param2type,type2param}() decode a new EC key from either form of parameters, or they encode a given key's parameters in the proper way. Signature and semantics are all over the place. It also features an inlined version of EC_KEY_new_by_curve_name(). This commit brings some order into this mess. Parameters are given by a pair (ptype, pval), where the ptype is either V_ASN1_OBJECT for OID encoding or V_ASN1_SEQUENCE for explicit encoding. Accordingly, the void pointer pval is an ASN1_OBJECT or an ASN1_STRING. These pairs are abstracted away in the X509_ALGOR object. The library decides whether a given EC key uses OID or explicit parameter encoding using the asn1_flag on the EC key's internal EC_GROUP, i.e., the object representing its curve. If this flag is set, the OID is determined by the nid returned by EC_GROUP_get_curve_name(). Add 'mutually inverse' pairs of functions eckey_{to,from}_params() which wrap eckey_{to,from}_object() and eckey_{to,from}_explicit_params(). This way the EC ameth pub and priv key de/encoding functions can transparently translate from/to an X509_ALGOR object. Of course, this is just an intermediate step and if you look closely you notice const weirdness (due to the fact that the carefully planned and executed const rampage missed the ECParameters API) and all sorts of other things that need to be fixed. Who would bat an eye lid? It wouldn't be visible amid all the twitching anyway. ok jsing
Diffstat (limited to 'src')
-rw-r--r--src/lib/libcrypto/ec/ec_ameth.c231
1 files changed, 139 insertions, 92 deletions
diff --git a/src/lib/libcrypto/ec/ec_ameth.c b/src/lib/libcrypto/ec/ec_ameth.c
index f2ad5f60c6..258daec127 100644
--- a/src/lib/libcrypto/ec/ec_ameth.c
+++ b/src/lib/libcrypto/ec/ec_ameth.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ec_ameth.c,v 1.43 2023/08/21 09:52:30 tb Exp $ */ 1/* $OpenBSD: ec_ameth.c,v 1.44 2023/09/24 07:58:31 tb Exp $ */
2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 * project 2006. 3 * project 2006.
4 */ 4 */
@@ -87,38 +87,136 @@ eckey_param_free(int ptype, void *pval)
87} 87}
88 88
89static int 89static int
90eckey_param2type(int *pptype, void **ppval, EC_KEY *ec_key) 90eckey_get_curve_name(const EC_KEY *eckey, int *nid)
91{ 91{
92 const EC_GROUP *group; 92 const EC_GROUP *group;
93 int nid; 93
94 if (ec_key == NULL || (group = EC_KEY_get0_group(ec_key)) == NULL) { 94 *nid = NID_undef;
95
96 if ((group = EC_KEY_get0_group(eckey)) == NULL) {
95 ECerror(EC_R_MISSING_PARAMETERS); 97 ECerror(EC_R_MISSING_PARAMETERS);
96 return 0; 98 return 0;
97 } 99 }
98 if (EC_GROUP_get_asn1_flag(group) && 100 if (EC_GROUP_get_asn1_flag(group) != 0)
99 (nid = EC_GROUP_get_curve_name(group))) { 101 *nid = EC_GROUP_get_curve_name(group);
100 /* we have a 'named curve' => just set the OID */ 102
101 *ppval = OBJ_nid2obj(nid); 103 return 1;
102 *pptype = V_ASN1_OBJECT; 104}
103 } else { 105
104 /* explicit parameters */ 106static int
105 ASN1_STRING *pstr = NULL; 107eckey_to_explicit_params(EC_KEY *eckey, void **out_val)
106 pstr = ASN1_STRING_new(); 108{
107 if (!pstr) 109 ASN1_STRING *astr = NULL;
108 return 0; 110 unsigned char *params = NULL;
109 pstr->length = i2d_ECParameters(ec_key, &pstr->data); 111 int params_len = 0;
110 if (pstr->length <= 0) { 112 int ret = 0;
111 ASN1_STRING_free(pstr); 113
112 ECerror(ERR_R_EC_LIB); 114 *out_val = NULL;
113 return 0; 115
114 } 116 if ((params_len = i2d_ECParameters(eckey, &params)) <= 0) {
115 *ppval = pstr; 117 ECerror(ERR_R_EC_LIB);
116 *pptype = V_ASN1_SEQUENCE; 118 params_len = 0;
119 goto err;
120 }
121
122 if ((astr = ASN1_STRING_new()) == NULL)
123 goto err;
124 ASN1_STRING_set0(astr, params, params_len);
125 params = NULL;
126 params_len = 0;
127
128 *out_val = astr;
129 astr = NULL;
130
131 ret = 1;
132
133 err:
134 freezero(params, params_len);
135 ASN1_STRING_free(astr);
136
137 return ret;
138}
139
140static int
141eckey_from_explicit_params(const ASN1_STRING *astr, EC_KEY **out_eckey)
142{
143 const unsigned char *params = astr->data;
144 int params_len = astr->length;
145
146 EC_KEY_free(*out_eckey);
147 if ((*out_eckey = d2i_ECParameters(NULL, &params, params_len)) == NULL) {
148 ECerror(EC_R_DECODE_ERROR);
149 return 0;
117 } 150 }
151
152 return 1;
153}
154
155static int
156eckey_to_object(const EC_KEY *eckey, void **out_val)
157{
158 int nid = NID_undef;
159
160 *out_val = NULL;
161
162 if (!eckey_get_curve_name(eckey, &nid))
163 return 0;
164 if ((*out_val = OBJ_nid2obj(nid)) == NULL)
165 return 0;
166
118 return 1; 167 return 1;
119} 168}
120 169
121static int 170static int
171eckey_from_object(const ASN1_OBJECT *aobj, EC_KEY **out_eckey)
172{
173 int nid;
174
175 *out_eckey = NULL;
176
177 if ((nid = OBJ_obj2nid(aobj)) == NID_undef)
178 return 0;
179 if ((*out_eckey = EC_KEY_new_by_curve_name(nid)) == NULL)
180 return 0;
181
182 return 1;
183}
184
185static int
186eckey_to_params(EC_KEY *eckey, int *out_type, void **out_val)
187{
188 int nid;
189
190 *out_type = NID_undef;
191 *out_val = NULL;
192
193 if (!eckey_get_curve_name(eckey, &nid))
194 return 0;
195
196 if (nid == NID_undef) {
197 *out_type = V_ASN1_SEQUENCE;
198 return eckey_to_explicit_params(eckey, out_val);
199 } else {
200 *out_type = V_ASN1_OBJECT;
201 return eckey_to_object(eckey, out_val);
202 }
203}
204
205static int
206eckey_from_params(int ptype, const void *pval, EC_KEY **out_eckey)
207{
208 *out_eckey = NULL;
209
210 if (ptype == V_ASN1_SEQUENCE)
211 return eckey_from_explicit_params(pval, out_eckey);
212 if (ptype == V_ASN1_OBJECT)
213 return eckey_from_object(pval, out_eckey);
214
215 ECerror(EC_R_DECODE_ERROR);
216 return 0;
217}
218
219static int
122eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) 220eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
123{ 221{
124 EC_KEY *eckey = pkey->pkey.ec; 222 EC_KEY *eckey = pkey->pkey.ec;
@@ -129,7 +227,7 @@ eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
129 int key_len = 0; 227 int key_len = 0;
130 int ret = 0; 228 int ret = 0;
131 229
132 if (!eckey_param2type(&ptype, &pval, eckey)) { 230 if (!eckey_to_params(eckey, &ptype, &pval)) {
133 ECerror(ERR_R_EC_LIB); 231 ECerror(ERR_R_EC_LIB);
134 goto err; 232 goto err;
135 } 233 }
@@ -154,54 +252,6 @@ eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
154 return ret; 252 return ret;
155} 253}
156 254
157static EC_KEY *
158eckey_type2param(int ptype, const void *pval)
159{
160 EC_GROUP *group = NULL;
161 EC_KEY *eckey = NULL;
162
163 if (ptype == V_ASN1_SEQUENCE) {
164 const ASN1_STRING *pstr = pval;
165 const unsigned char *pm = NULL;
166 int pmlen;
167
168 pm = pstr->data;
169 pmlen = pstr->length;
170 if (!(eckey = d2i_ECParameters(NULL, &pm, pmlen))) {
171 ECerror(EC_R_DECODE_ERROR);
172 goto ecerr;
173 }
174 } else if (ptype == V_ASN1_OBJECT) {
175 const ASN1_OBJECT *poid = pval;
176
177 /*
178 * type == V_ASN1_OBJECT => the parameters are given by an
179 * asn1 OID
180 */
181 if ((eckey = EC_KEY_new()) == NULL) {
182 ECerror(ERR_R_MALLOC_FAILURE);
183 goto ecerr;
184 }
185 group = EC_GROUP_new_by_curve_name(OBJ_obj2nid(poid));
186 if (group == NULL)
187 goto ecerr;
188 EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
189 if (EC_KEY_set_group(eckey, group) == 0)
190 goto ecerr;
191 } else {
192 ECerror(EC_R_DECODE_ERROR);
193 goto ecerr;
194 }
195
196 EC_GROUP_free(group);
197 return eckey;
198
199 ecerr:
200 EC_KEY_free(eckey);
201 EC_GROUP_free(group);
202 return NULL;
203}
204
205static int 255static int
206eckey_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) 256eckey_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
207{ 257{
@@ -210,29 +260,29 @@ eckey_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
210 int ptype, pklen; 260 int ptype, pklen;
211 EC_KEY *eckey = NULL; 261 EC_KEY *eckey = NULL;
212 X509_ALGOR *palg; 262 X509_ALGOR *palg;
263 int ret = 0;
213 264
214 if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey)) 265 if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
215 return 0; 266 goto err;
216 X509_ALGOR_get0(NULL, &ptype, &pval, palg); 267 X509_ALGOR_get0(NULL, &ptype, &pval, palg);
217 268
218 eckey = eckey_type2param(ptype, pval); 269 if (!eckey_from_params(ptype, pval, &eckey))
270 goto err;
219 271
220 if (!eckey) {
221 ECerror(ERR_R_EC_LIB);
222 return 0;
223 }
224 /* We have parameters now set public key */
225 if (!o2i_ECPublicKey(&eckey, &p, pklen)) { 272 if (!o2i_ECPublicKey(&eckey, &p, pklen)) {
226 ECerror(EC_R_DECODE_ERROR); 273 ECerror(EC_R_DECODE_ERROR);
227 goto ecerr; 274 goto err;
228 } 275 }
229 EVP_PKEY_assign_EC_KEY(pkey, eckey); 276 if (!EVP_PKEY_assign_EC_KEY(pkey, eckey))
230 return 1; 277 goto err;
278 eckey = NULL;
231 279
232 ecerr: 280 ret = 1;
233 if (eckey) 281
234 EC_KEY_free(eckey); 282 err:
235 return 0; 283 EC_KEY_free(eckey);
284
285 return ret;
236} 286}
237 287
238static int 288static int
@@ -263,9 +313,7 @@ eckey_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8)
263 return 0; 313 return 0;
264 X509_ALGOR_get0(NULL, &ptype, &pval, palg); 314 X509_ALGOR_get0(NULL, &ptype, &pval, palg);
265 315
266 eckey = eckey_type2param(ptype, pval); 316 if (!eckey_from_params(ptype, pval, &eckey))
267
268 if (!eckey)
269 goto ecliberr; 317 goto ecliberr;
270 318
271 /* We have parameters now set private key */ 319 /* We have parameters now set private key */
@@ -331,7 +379,7 @@ eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
331 379
332 flags = EC_KEY_get_enc_flags(eckey); 380 flags = EC_KEY_get_enc_flags(eckey);
333 381
334 if (!eckey_param2type(&ptype, &pval, eckey)) { 382 if (!eckey_to_params(eckey, &ptype, &pval)) {
335 ECerror(EC_R_DECODE_ERROR); 383 ECerror(EC_R_DECODE_ERROR);
336 goto err; 384 goto err;
337 } 385 }
@@ -685,8 +733,7 @@ ecdh_cms_set_peerkey(EVP_PKEY_CTX *pctx, X509_ALGOR *alg,
685 if (!EC_KEY_set_group(ecpeer, grp)) 733 if (!EC_KEY_set_group(ecpeer, grp))
686 goto err; 734 goto err;
687 } else { 735 } else {
688 ecpeer = eckey_type2param(atype, aval); 736 if (!eckey_from_params(atype, aval, &ecpeer))
689 if (!ecpeer)
690 goto err; 737 goto err;
691 } 738 }
692 739