diff options
author | tb <> | 2023-08-21 09:52:30 +0000 |
---|---|---|
committer | tb <> | 2023-08-21 09:52:30 +0000 |
commit | d3ac126cef693adbcc7de565f3cb40e700cc0e5d (patch) | |
tree | 9bde0b5077ca4bfd1588eafeaa0cffd8572151fe | |
parent | 1fad85be488e3d1aa8280c0510baf46c4157fb18 (diff) | |
download | openbsd-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.c | 129 |
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); | |||
75 | static int ecdh_cms_encrypt(CMS_RecipientInfo *ri); | 75 | static int ecdh_cms_encrypt(CMS_RecipientInfo *ri); |
76 | #endif | 76 | #endif |
77 | 77 | ||
78 | static void | ||
79 | eckey_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 | |||
78 | static int | 89 | static int |
79 | eckey_param2type(int *pptype, void **ppval, EC_KEY *ec_key) | 90 | eckey_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) | |||
110 | static int | 121 | static int |
111 | eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) | 122 | eckey_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 | ||
145 | static EC_KEY * | 157 | static EC_KEY * |
@@ -308,54 +320,47 @@ eckey_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8) | |||
308 | static int | 320 | static int |
309 | eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) | 321 | eckey_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 | ||
361 | static int | 366 | static int |