diff options
Diffstat (limited to 'src/lib/libcrypto/ecdh/ecdh.c')
-rw-r--r-- | src/lib/libcrypto/ecdh/ecdh.c | 86 |
1 files changed, 55 insertions, 31 deletions
diff --git a/src/lib/libcrypto/ecdh/ecdh.c b/src/lib/libcrypto/ecdh/ecdh.c index 6ab4ff8382..034bd84a49 100644 --- a/src/lib/libcrypto/ecdh/ecdh.c +++ b/src/lib/libcrypto/ecdh/ecdh.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ecdh.c,v 1.6 2023/07/24 17:08:53 tb Exp $ */ | 1 | /* $OpenBSD: ecdh.c,v 1.7 2023/07/28 09:28:37 tb Exp $ */ |
2 | /* ==================================================================== | 2 | /* ==================================================================== |
3 | * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. | 3 | * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. |
4 | * | 4 | * |
@@ -145,10 +145,9 @@ ecdh_KDF_X9_63(unsigned char *out, size_t outlen, const unsigned char *Z, | |||
145 | /* | 145 | /* |
146 | * Based on the ECKAS-DH1 and ECSVDP-DH primitives in the IEEE 1363 standard. | 146 | * Based on the ECKAS-DH1 and ECSVDP-DH primitives in the IEEE 1363 standard. |
147 | */ | 147 | */ |
148 | /* XXX - KDF handling moved to ECDH_compute_key(). See OpenSSL e2285d87. */ | ||
149 | int | 148 | int |
150 | ecdh_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, EC_KEY *ecdh, | 149 | ecdh_compute_key(unsigned char **out, size_t *out_len, const EC_POINT *pub_key, |
151 | void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen)) | 150 | const EC_KEY *ecdh) |
152 | { | 151 | { |
153 | BN_CTX *ctx; | 152 | BN_CTX *ctx; |
154 | BIGNUM *x; | 153 | BIGNUM *x; |
@@ -157,13 +156,10 @@ ecdh_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, EC_KEY *ecdh | |||
157 | EC_POINT *point = NULL; | 156 | EC_POINT *point = NULL; |
158 | unsigned char *buf = NULL; | 157 | unsigned char *buf = NULL; |
159 | int buflen; | 158 | int buflen; |
160 | int ret = -1; | 159 | int ret = 0; |
161 | 160 | ||
162 | if (outlen > INT_MAX) { | 161 | *out = NULL; |
163 | /* Sort of, anyway. */ | 162 | *out_len = 0; |
164 | ECerror(ERR_R_MALLOC_FAILURE); | ||
165 | return -1; | ||
166 | } | ||
167 | 163 | ||
168 | if ((ctx = BN_CTX_new()) == NULL) | 164 | if ((ctx = BN_CTX_new()) == NULL) |
169 | goto err; | 165 | goto err; |
@@ -203,11 +199,6 @@ ecdh_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, EC_KEY *ecdh | |||
203 | ECerror(ERR_R_INTERNAL_ERROR); | 199 | ECerror(ERR_R_INTERNAL_ERROR); |
204 | goto err; | 200 | goto err; |
205 | } | 201 | } |
206 | if (KDF == NULL && outlen < buflen) { | ||
207 | /* The resulting key would be truncated. */ | ||
208 | ECerror(EC_R_KEY_TRUNCATION); | ||
209 | goto err; | ||
210 | } | ||
211 | if ((buf = malloc(buflen)) == NULL) { | 202 | if ((buf = malloc(buflen)) == NULL) { |
212 | ECerror(ERR_R_MALLOC_FAILURE); | 203 | ECerror(ERR_R_MALLOC_FAILURE); |
213 | goto err; | 204 | goto err; |
@@ -217,19 +208,12 @@ ecdh_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, EC_KEY *ecdh | |||
217 | goto err; | 208 | goto err; |
218 | } | 209 | } |
219 | 210 | ||
220 | if (KDF != NULL) { | 211 | *out = buf; |
221 | if (KDF(buf, buflen, out, &outlen) == NULL) { | 212 | *out_len = buflen; |
222 | ECerror(EC_R_KDF_FAILED); | 213 | buf = NULL; |
223 | goto err; | 214 | |
224 | } | 215 | ret = 1; |
225 | } else { | ||
226 | memset(out, 0, outlen); | ||
227 | if (outlen > buflen) | ||
228 | outlen = buflen; | ||
229 | memcpy(out, buf, outlen); | ||
230 | } | ||
231 | 216 | ||
232 | ret = outlen; | ||
233 | err: | 217 | err: |
234 | EC_POINT_free(point); | 218 | EC_POINT_free(point); |
235 | BN_CTX_end(ctx); | 219 | BN_CTX_end(ctx); |
@@ -240,15 +224,55 @@ ecdh_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, EC_KEY *ecdh | |||
240 | } | 224 | } |
241 | 225 | ||
242 | int | 226 | int |
243 | ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, | 227 | ECDH_compute_key(void *out, size_t out_len, const EC_POINT *pub_key, |
244 | EC_KEY *eckey, | 228 | EC_KEY *eckey, |
245 | void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen)) | 229 | void *(*KDF)(const void *in, size_t inlen, void *out, size_t *out_len)) |
246 | { | 230 | { |
231 | unsigned char *secret = NULL; | ||
232 | size_t secret_len = 0; | ||
233 | int ret = 0; | ||
234 | |||
247 | if (eckey->meth->compute_key == NULL) { | 235 | if (eckey->meth->compute_key == NULL) { |
248 | ECerror(EC_R_NOT_IMPLEMENTED); | 236 | ECerror(EC_R_NOT_IMPLEMENTED); |
249 | return 0; | 237 | goto err; |
238 | } | ||
239 | |||
240 | if (out_len > INT_MAX) { | ||
241 | ECerror(EC_R_INVALID_OUTPUT_LENGTH); | ||
242 | goto err; | ||
243 | } | ||
244 | |||
245 | if (!eckey->meth->compute_key(&secret, &secret_len, pub_key, eckey)) | ||
246 | goto err; | ||
247 | |||
248 | if (KDF != NULL) { | ||
249 | if (KDF(secret, secret_len, out, &out_len) == NULL) { | ||
250 | ECerror(EC_R_KDF_FAILED); | ||
251 | goto err; | ||
252 | } | ||
253 | } else { | ||
254 | memset(out, 0, out_len); | ||
255 | if (out_len < secret_len) { | ||
256 | /* The resulting key would be truncated. */ | ||
257 | ECerror(EC_R_KEY_TRUNCATION); | ||
258 | goto err; | ||
259 | } | ||
260 | if (out_len > secret_len) | ||
261 | out_len = secret_len; | ||
262 | memcpy(out, secret, out_len); | ||
250 | } | 263 | } |
251 | return eckey->meth->compute_key(out, outlen, pub_key, eckey, KDF); | 264 | |
265 | if (out_len > INT_MAX) { | ||
266 | ECerror(EC_R_INVALID_OUTPUT_LENGTH); | ||
267 | goto err; | ||
268 | } | ||
269 | |||
270 | ret = out_len; | ||
271 | |||
272 | err: | ||
273 | freezero(secret, secret_len); | ||
274 | |||
275 | return ret; | ||
252 | } | 276 | } |
253 | LCRYPTO_ALIAS(ECDH_compute_key); | 277 | LCRYPTO_ALIAS(ECDH_compute_key); |
254 | 278 | ||