summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/ecdh/ecdh.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/ecdh/ecdh.c')
-rw-r--r--src/lib/libcrypto/ecdh/ecdh.c86
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. */
149int 148int
150ecdh_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, EC_KEY *ecdh, 149ecdh_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
242int 226int
243ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, 227ECDH_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}
253LCRYPTO_ALIAS(ECDH_compute_key); 277LCRYPTO_ALIAS(ECDH_compute_key);
254 278