summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortb <>2023-07-28 09:28:37 +0000
committertb <>2023-07-28 09:28:37 +0000
commit33dbb14462f6ae315b78289dc98d9434aff69e79 (patch)
tree7caeb4b66ea3545dbbf75224b3b77f6e29ea4f22
parentcf0c598c9887e5bc98b6596c5e1e0dda9848b88d (diff)
downloadopenbsd-33dbb14462f6ae315b78289dc98d9434aff69e79.tar.gz
openbsd-33dbb14462f6ae315b78289dc98d9434aff69e79.tar.bz2
openbsd-33dbb14462f6ae315b78289dc98d9434aff69e79.zip
Move KDF handling to ECDH_compute_key()
In OpenSSL e2285d87, the KDF handling was moved from the compute_key() method into the public API. A consequence of this change is that the ECDH_compute_key() API no longer returns -1 for some errors. Existing checks for <= 0 are safe as are those checking for the exact length as return value, which is all what the ecosystem seems to be doing. ok jsing
-rw-r--r--src/lib/libcrypto/ec/ec.h11
-rw-r--r--src/lib/libcrypto/ec/ec_err.c3
-rw-r--r--src/lib/libcrypto/ec/ec_kmeth.c10
-rw-r--r--src/lib/libcrypto/ec/ec_local.h10
-rw-r--r--src/lib/libcrypto/ecdh/ecdh.c86
5 files changed, 73 insertions, 47 deletions
diff --git a/src/lib/libcrypto/ec/ec.h b/src/lib/libcrypto/ec/ec.h
index 686f018a9d..85951f0b97 100644
--- a/src/lib/libcrypto/ec/ec.h
+++ b/src/lib/libcrypto/ec/ec.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: ec.h,v 1.44 2023/07/28 09:25:12 tb Exp $ */ 1/* $OpenBSD: ec.h,v 1.45 2023/07/28 09:28:37 tb Exp $ */
2/* 2/*
3 * Originally written by Bodo Moeller for the OpenSSL project. 3 * Originally written by Bodo Moeller for the OpenSSL project.
4 */ 4 */
@@ -368,8 +368,8 @@ void EC_KEY_METHOD_set_init(EC_KEY_METHOD *meth,
368void EC_KEY_METHOD_set_keygen(EC_KEY_METHOD *meth, 368void EC_KEY_METHOD_set_keygen(EC_KEY_METHOD *meth,
369 int (*keygen)(EC_KEY *key)); 369 int (*keygen)(EC_KEY *key));
370void EC_KEY_METHOD_set_compute_key(EC_KEY_METHOD *meth, 370void EC_KEY_METHOD_set_compute_key(EC_KEY_METHOD *meth,
371 int (*ckey)(void *out, size_t outlen, const EC_POINT *pub_key, EC_KEY *ecdh, 371 int (*ckey)(unsigned char **out, size_t *out_len, const EC_POINT *pub_key,
372 void *(*KDF) (const void *in, size_t inlen, void *out, size_t *outlen))); 372 const EC_KEY *ecdh));
373void EC_KEY_METHOD_set_sign(EC_KEY_METHOD *meth, 373void EC_KEY_METHOD_set_sign(EC_KEY_METHOD *meth,
374 int (*sign)(int type, const unsigned char *digest, int digest_len, 374 int (*sign)(int type, const unsigned char *digest, int digest_len,
375 unsigned char *signature, unsigned int *signature_len, 375 unsigned char *signature, unsigned int *signature_len,
@@ -392,8 +392,8 @@ void EC_KEY_METHOD_get_init(const EC_KEY_METHOD *meth,
392void EC_KEY_METHOD_get_keygen(const EC_KEY_METHOD *meth, 392void EC_KEY_METHOD_get_keygen(const EC_KEY_METHOD *meth,
393 int (**pkeygen)(EC_KEY *key)); 393 int (**pkeygen)(EC_KEY *key));
394void EC_KEY_METHOD_get_compute_key(const EC_KEY_METHOD *meth, 394void EC_KEY_METHOD_get_compute_key(const EC_KEY_METHOD *meth,
395 int (**pck)(void *out, size_t outlen, const EC_POINT *pub_key, EC_KEY *ecdh, 395 int (**pck)(unsigned char **out, size_t *out_len, const EC_POINT *pub_key,
396 void *(*KDF) (const void *in, size_t inlen, void *out, size_t *outlen))); 396 const EC_KEY *ecdh));
397void EC_KEY_METHOD_get_sign(const EC_KEY_METHOD *meth, 397void EC_KEY_METHOD_get_sign(const EC_KEY_METHOD *meth,
398 int (**psign)(int type, const unsigned char *digest, int digest_len, 398 int (**psign)(int type, const unsigned char *digest, int digest_len,
399 unsigned char *signature, unsigned int *signature_len, 399 unsigned char *signature, unsigned int *signature_len,
@@ -684,6 +684,7 @@ void ERR_load_EC_strings(void);
684#define EC_R_INVALID_FORM 104 684#define EC_R_INVALID_FORM 104
685#define EC_R_INVALID_GROUP_ORDER 122 685#define EC_R_INVALID_GROUP_ORDER 122
686#define EC_R_INVALID_KEY 165 686#define EC_R_INVALID_KEY 165
687#define EC_R_INVALID_OUTPUT_LENGTH 171
687#define EC_R_INVALID_PEER_KEY 152 688#define EC_R_INVALID_PEER_KEY 152
688#define EC_R_INVALID_PENTANOMIAL_BASIS 132 689#define EC_R_INVALID_PENTANOMIAL_BASIS 132
689#define EC_R_INVALID_PRIVATE_KEY 123 690#define EC_R_INVALID_PRIVATE_KEY 123
diff --git a/src/lib/libcrypto/ec/ec_err.c b/src/lib/libcrypto/ec/ec_err.c
index d797b937c2..9f2253dddd 100644
--- a/src/lib/libcrypto/ec/ec_err.c
+++ b/src/lib/libcrypto/ec/ec_err.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ec_err.c,v 1.17 2023/07/07 13:54:45 beck Exp $ */ 1/* $OpenBSD: ec_err.c,v 1.18 2023/07/28 09:28:37 tb Exp $ */
2/* ==================================================================== 2/* ====================================================================
3 * Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved. 3 * Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved.
4 * 4 *
@@ -98,6 +98,7 @@ static ERR_STRING_DATA EC_str_reasons[] =
98 {ERR_REASON(EC_R_INVALID_FORM), "invalid form"}, 98 {ERR_REASON(EC_R_INVALID_FORM), "invalid form"},
99 {ERR_REASON(EC_R_INVALID_GROUP_ORDER), "invalid group order"}, 99 {ERR_REASON(EC_R_INVALID_GROUP_ORDER), "invalid group order"},
100 {ERR_REASON(EC_R_INVALID_KEY), "invalid key"}, 100 {ERR_REASON(EC_R_INVALID_KEY), "invalid key"},
101 {ERR_REASON(EC_R_INVALID_OUTPUT_LENGTH), "invalid output length"},
101 {ERR_REASON(EC_R_INVALID_PEER_KEY), "invalid peer key"}, 102 {ERR_REASON(EC_R_INVALID_PEER_KEY), "invalid peer key"},
102 {ERR_REASON(EC_R_INVALID_PENTANOMIAL_BASIS), "invalid pentanomial basis"}, 103 {ERR_REASON(EC_R_INVALID_PENTANOMIAL_BASIS), "invalid pentanomial basis"},
103 {ERR_REASON(EC_R_INVALID_PRIVATE_KEY), "invalid private key"}, 104 {ERR_REASON(EC_R_INVALID_PRIVATE_KEY), "invalid private key"},
diff --git a/src/lib/libcrypto/ec/ec_kmeth.c b/src/lib/libcrypto/ec/ec_kmeth.c
index 3e997f8a5e..38aca0028e 100644
--- a/src/lib/libcrypto/ec/ec_kmeth.c
+++ b/src/lib/libcrypto/ec/ec_kmeth.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ec_kmeth.c,v 1.11 2023/07/07 13:54:45 beck Exp $ */ 1/* $OpenBSD: ec_kmeth.c,v 1.12 2023/07/28 09:28:37 tb Exp $ */
2/* 2/*
3 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 3 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
4 * project. 4 * project.
@@ -238,8 +238,8 @@ LCRYPTO_ALIAS(EC_KEY_METHOD_set_keygen);
238 238
239void 239void
240EC_KEY_METHOD_set_compute_key(EC_KEY_METHOD *meth, 240EC_KEY_METHOD_set_compute_key(EC_KEY_METHOD *meth,
241 int (*ckey)(void *out, size_t outlen, const EC_POINT *pub_key, EC_KEY *ecdh, 241 int (*ckey)(unsigned char **out, size_t *out_len, const EC_POINT *pub_key,
242 void *(*KDF) (const void *in, size_t inlen, void *out, size_t *outlen))) 242 const EC_KEY *ecdh))
243{ 243{
244 meth->compute_key = ckey; 244 meth->compute_key = ckey;
245} 245}
@@ -310,8 +310,8 @@ LCRYPTO_ALIAS(EC_KEY_METHOD_get_keygen);
310 310
311void 311void
312EC_KEY_METHOD_get_compute_key(const EC_KEY_METHOD *meth, 312EC_KEY_METHOD_get_compute_key(const EC_KEY_METHOD *meth,
313 int (**pck)(void *out, size_t outlen, const EC_POINT *pub_key, EC_KEY *ecdh, 313 int (**pck)(unsigned char **out, size_t *out_len, const EC_POINT *pub_key,
314 void *(*KDF) (const void *in, size_t inlen, void *out, size_t *outlen))) 314 const EC_KEY *ecdh))
315{ 315{
316 if (pck != NULL) 316 if (pck != NULL)
317 *pck = meth->compute_key; 317 *pck = meth->compute_key;
diff --git a/src/lib/libcrypto/ec/ec_local.h b/src/lib/libcrypto/ec/ec_local.h
index 7a1f90886d..8153d4a96a 100644
--- a/src/lib/libcrypto/ec/ec_local.h
+++ b/src/lib/libcrypto/ec/ec_local.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: ec_local.h,v 1.24 2023/07/05 08:39:40 tb Exp $ */ 1/* $OpenBSD: ec_local.h,v 1.25 2023/07/28 09:28:37 tb Exp $ */
2/* 2/*
3 * Originally written by Bodo Moeller for the OpenSSL project. 3 * Originally written by Bodo Moeller for the OpenSSL project.
4 */ 4 */
@@ -323,8 +323,8 @@ struct ec_key_method_st {
323 int (*set_private)(EC_KEY *key, const BIGNUM *priv_key); 323 int (*set_private)(EC_KEY *key, const BIGNUM *priv_key);
324 int (*set_public)(EC_KEY *key, const EC_POINT *pub_key); 324 int (*set_public)(EC_KEY *key, const EC_POINT *pub_key);
325 int (*keygen)(EC_KEY *key); 325 int (*keygen)(EC_KEY *key);
326 int (*compute_key)(void *out, size_t outlen, const EC_POINT *pub_key, EC_KEY *ecdh, 326 int (*compute_key)(unsigned char **out, size_t *out_len,
327 void *(*KDF) (const void *in, size_t inlen, void *out, size_t *outlen)); 327 const EC_POINT *pub_key, const EC_KEY *ecdh);
328 int (*sign)(int type, const unsigned char *dgst, int dlen, unsigned char 328 int (*sign)(int type, const unsigned char *dgst, int dlen, unsigned char
329 *sig, unsigned int *siglen, const BIGNUM *kinv, 329 *sig, unsigned int *siglen, const BIGNUM *kinv,
330 const BIGNUM *r, EC_KEY *eckey); 330 const BIGNUM *r, EC_KEY *eckey);
@@ -342,8 +342,8 @@ struct ec_key_method_st {
342#define EC_KEY_METHOD_DYNAMIC 1 342#define EC_KEY_METHOD_DYNAMIC 1
343 343
344int ec_key_gen(EC_KEY *eckey); 344int ec_key_gen(EC_KEY *eckey);
345int ecdh_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, EC_KEY *ecdh, 345int ecdh_compute_key(unsigned char **out, size_t *out_len,
346 void *(*KDF) (const void *in, size_t inlen, void *out, size_t *outlen)); 346 const EC_POINT *pub_key, const EC_KEY *ecdh);
347int ecdsa_verify(int type, const unsigned char *dgst, int dgst_len, 347int ecdsa_verify(int type, const unsigned char *dgst, int dgst_len,
348 const unsigned char *sigbuf, int sig_len, EC_KEY *eckey); 348 const unsigned char *sigbuf, int sig_len, EC_KEY *eckey);
349int ecdsa_verify_sig(const unsigned char *dgst, int dgst_len, 349int ecdsa_verify_sig(const unsigned char *dgst, int dgst_len,
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