diff options
| author | tb <> | 2023-07-28 09:28:37 +0000 |
|---|---|---|
| committer | tb <> | 2023-07-28 09:28:37 +0000 |
| commit | c043ade63ba3d45eacfb953347c00f0988397d9a (patch) | |
| tree | 7caeb4b66ea3545dbbf75224b3b77f6e29ea4f22 /src/lib/libcrypto/ecdh/ecdh.c | |
| parent | 2d27f5ba745b8f5de6e3e827829699607f11a54f (diff) | |
| download | openbsd-c043ade63ba3d45eacfb953347c00f0988397d9a.tar.gz openbsd-c043ade63ba3d45eacfb953347c00f0988397d9a.tar.bz2 openbsd-c043ade63ba3d45eacfb953347c00f0988397d9a.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
Diffstat (limited to '')
| -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 | ||
