summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortb <>2023-08-21 09:52:30 +0000
committertb <>2023-08-21 09:52:30 +0000
commitd3ac126cef693adbcc7de565f3cb40e700cc0e5d (patch)
tree9bde0b5077ca4bfd1588eafeaa0cffd8572151fe
parent1fad85be488e3d1aa8280c0510baf46c4157fb18 (diff)
downloadopenbsd-d3ac126cef693adbcc7de565f3cb40e700cc0e5d.tar.gz
openbsd-d3ac126cef693adbcc7de565f3cb40e700cc0e5d.tar.bz2
openbsd-d3ac126cef693adbcc7de565f3cb40e700cc0e5d.zip
ec_ameth: clean up eckey_{pub,priv}_encode()
Factor eckey_param_free() out of eckey_pub_encode(). ASN1_OBJECT_free() is not actually needed. This will be addressed later. i2o_ECPublicKey() allocates internally if *out == NULL, so no need to do the two-call dance. Its return value is documented to be <= 0 on error, which is wrong in the sense that only 0 is returned. Keep using the same check for <= 0 as everywhere else. Set of EC_PKEY_NO_PARAMETERS after the poorly named eckey_param2type() to avoid potential underhanded side effects. In eckey_priv_encode(), error exits would leak pval was leaked a few times. Avoid this and simplify using i2d's internal allocation. Reinstate the flags in a single error path. ok jsing
-rw-r--r--src/lib/libcrypto/ec/ec_ameth.c129
1 files changed, 67 insertions, 62 deletions
diff --git a/src/lib/libcrypto/ec/ec_ameth.c b/src/lib/libcrypto/ec/ec_ameth.c
index 6adf7ce671..f2ad5f60c6 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.42 2023/08/12 08:07:35 tb Exp $ */ 1/* $OpenBSD: ec_ameth.c,v 1.43 2023/08/21 09:52:30 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 */
@@ -75,6 +75,17 @@ static int ecdh_cms_decrypt(CMS_RecipientInfo *ri);
75static int ecdh_cms_encrypt(CMS_RecipientInfo *ri); 75static int ecdh_cms_encrypt(CMS_RecipientInfo *ri);
76#endif 76#endif
77 77
78static void
79eckey_param_free(int ptype, void *pval)
80{
81 if (pval == NULL)
82 return;
83 if (ptype == V_ASN1_OBJECT)
84 ASN1_OBJECT_free(pval); /* XXX - really necessary? */
85 else
86 ASN1_STRING_free(pval);
87}
88
78static int 89static int
79eckey_param2type(int *pptype, void **ppval, EC_KEY *ec_key) 90eckey_param2type(int *pptype, void **ppval, EC_KEY *ec_key)
80{ 91{
@@ -110,36 +121,37 @@ eckey_param2type(int *pptype, void **ppval, EC_KEY *ec_key)
110static int 121static int
111eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) 122eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
112{ 123{
113 EC_KEY *ec_key = pkey->pkey.ec; 124 EC_KEY *eckey = pkey->pkey.ec;
125 int ptype = V_ASN1_UNDEF;
114 void *pval = NULL; 126 void *pval = NULL;
115 int ptype; 127 ASN1_OBJECT *aobj;
116 unsigned char *penc = NULL, *p; 128 unsigned char *key = NULL;
117 int penclen; 129 int key_len = 0;
130 int ret = 0;
118 131
119 if (!eckey_param2type(&ptype, &pval, ec_key)) { 132 if (!eckey_param2type(&ptype, &pval, eckey)) {
120 ECerror(ERR_R_EC_LIB); 133 ECerror(ERR_R_EC_LIB);
121 return 0; 134 goto err;
122 } 135 }
123 penclen = i2o_ECPublicKey(ec_key, NULL); 136 if ((key_len = i2o_ECPublicKey(eckey, &key)) <= 0) {
124 if (penclen <= 0) 137 key_len = 0;
125 goto err; 138 goto err;
126 penc = malloc(penclen); 139 }
127 if (!penc) 140 if ((aobj = OBJ_nid2obj(EVP_PKEY_EC)) == NULL)
128 goto err; 141 goto err;
129 p = penc; 142 if (!X509_PUBKEY_set0_param(pk, aobj, ptype, pval, key, key_len))
130 penclen = i2o_ECPublicKey(ec_key, &p);
131 if (penclen <= 0)
132 goto err; 143 goto err;
133 if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_EC), 144 pval = NULL;
134 ptype, pval, penc, penclen)) 145 key = NULL;
135 return 1; 146 key_len = 0;
147
148 ret = 1;
149
136 err: 150 err:
137 if (ptype == V_ASN1_OBJECT) 151 eckey_param_free(ptype, pval);
138 ASN1_OBJECT_free(pval); 152 freezero(key, key_len);
139 else 153
140 ASN1_STRING_free(pval); 154 return ret;
141 free(penc);
142 return 0;
143} 155}
144 156
145static EC_KEY * 157static EC_KEY *
@@ -308,54 +320,47 @@ eckey_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8)
308static int 320static int
309eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) 321eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
310{ 322{
311 EC_KEY *ec_key; 323 EC_KEY *eckey = pkey->pkey.ec;
312 unsigned char *ep, *p; 324 void *pval = NULL;
313 int eplen, ptype; 325 int ptype = V_ASN1_UNDEF;
314 void *pval; 326 ASN1_OBJECT *aobj;
315 unsigned int tmp_flags, old_flags; 327 unsigned char *key = NULL;
328 int key_len = 0;
329 unsigned int flags;
330 int ret = 0;
316 331
317 ec_key = pkey->pkey.ec; 332 flags = EC_KEY_get_enc_flags(eckey);
318 333
319 if (!eckey_param2type(&ptype, &pval, ec_key)) { 334 if (!eckey_param2type(&ptype, &pval, eckey)) {
320 ECerror(EC_R_DECODE_ERROR); 335 ECerror(EC_R_DECODE_ERROR);
321 return 0; 336 goto err;
322 } 337 }
323 /* set the private key */
324 338
325 /* 339 /* PKCS#11 12.11: don't include parameters in the SEC1 private key. */
326 * do not include the parameters in the SEC1 private key see PKCS#11 340 EC_KEY_set_enc_flags(eckey, flags | EC_PKEY_NO_PARAMETERS);
327 * 12.11 341
328 */ 342 if ((key_len = i2d_ECPrivateKey(eckey, &key)) <= 0) {
329 old_flags = EC_KEY_get_enc_flags(ec_key);
330 tmp_flags = old_flags | EC_PKEY_NO_PARAMETERS;
331 EC_KEY_set_enc_flags(ec_key, tmp_flags);
332 eplen = i2d_ECPrivateKey(ec_key, NULL);
333 if (!eplen) {
334 EC_KEY_set_enc_flags(ec_key, old_flags);
335 ECerror(ERR_R_EC_LIB);
336 return 0;
337 }
338 ep = malloc(eplen);
339 if (!ep) {
340 EC_KEY_set_enc_flags(ec_key, old_flags);
341 ECerror(ERR_R_MALLOC_FAILURE);
342 return 0;
343 }
344 p = ep;
345 if (!i2d_ECPrivateKey(ec_key, &p)) {
346 EC_KEY_set_enc_flags(ec_key, old_flags);
347 free(ep);
348 ECerror(ERR_R_EC_LIB); 343 ECerror(ERR_R_EC_LIB);
349 return 0; 344 key_len = 0;
345 goto err;
350 } 346 }
351 /* restore old encoding flags */ 347 if ((aobj = OBJ_nid2obj(NID_X9_62_id_ecPublicKey)) == NULL)
352 EC_KEY_set_enc_flags(ec_key, old_flags); 348 goto err;
349 if (!PKCS8_pkey_set0(p8, aobj, 0, ptype, pval, key, key_len))
350 goto err;
351 pval = NULL;
352 key = NULL;
353 key_len = 0;
353 354
354 if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), 0, 355 ret = 1;
355 ptype, pval, ep, eplen))
356 return 0;
357 356
358 return 1; 357 err:
358 eckey_param_free(ptype, pval);
359 freezero(key, key_len);
360
361 EC_KEY_set_enc_flags(eckey, flags);
362
363 return ret;
359} 364}
360 365
361static int 366static int