diff options
| author | tb <> | 2023-07-04 07:38:31 +0000 |
|---|---|---|
| committer | tb <> | 2023-07-04 07:38:31 +0000 |
| commit | 2d46bf17610e19f84282d080d97de3351d957036 (patch) | |
| tree | 086fbae4747cedb9ba7652be2ec888d5fd4cb5db /src/lib/libc | |
| parent | f18142237b5f1c1ef068e17d45912d99c3daf77d (diff) | |
| download | openbsd-2d46bf17610e19f84282d080d97de3351d957036.tar.gz openbsd-2d46bf17610e19f84282d080d97de3351d957036.tar.bz2 openbsd-2d46bf17610e19f84282d080d97de3351d957036.zip | |
Factor the computation of ECDSA s into a function
ossl_ecdsa_sign_sig() is already complicated enough. The math bit is
entirely self contained and does not need to obfuscate control flow
and logic.
with feedback from and ok jsing
Diffstat (limited to '')
| -rw-r--r-- | src/lib/libcrypto/ecdsa/ecs_ossl.c | 157 |
1 files changed, 88 insertions, 69 deletions
diff --git a/src/lib/libcrypto/ecdsa/ecs_ossl.c b/src/lib/libcrypto/ecdsa/ecs_ossl.c index 2140f8a8e1..5b5013d631 100644 --- a/src/lib/libcrypto/ecdsa/ecs_ossl.c +++ b/src/lib/libcrypto/ecdsa/ecs_ossl.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: ecs_ossl.c,v 1.61 2023/07/03 14:51:09 tb Exp $ */ | 1 | /* $OpenBSD: ecs_ossl.c,v 1.62 2023/07/04 07:38:31 tb Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Written by Nils Larsch for the OpenSSL project | 3 | * Written by Nils Larsch for the OpenSSL project |
| 4 | */ | 4 | */ |
| @@ -260,6 +260,88 @@ ossl_ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *in_ctx, BIGNUM **out_kinv, | |||
| 260 | } | 260 | } |
| 261 | 261 | ||
| 262 | /* | 262 | /* |
| 263 | * FIPS 186-5, section 6.4.1, step 9: compute s = inv(k)(m + xr) mod order. | ||
| 264 | * In order to reduce the possibility of a side-channel attack, the following | ||
| 265 | * is calculated using a random blinding value b in [1, order): | ||
| 266 | * s = inv(b)(bm + bxr)inv(k) mod order. | ||
| 267 | */ | ||
| 268 | |||
| 269 | static int | ||
| 270 | ecdsa_compute_s(BIGNUM **out_s, const BIGNUM *m, const BIGNUM *kinv, | ||
| 271 | const BIGNUM *r, const BIGNUM *priv_key, const BIGNUM *order, BN_CTX *ctx) | ||
| 272 | { | ||
| 273 | BIGNUM *b, *binv, *bm, *bxr; | ||
| 274 | BIGNUM *s = NULL; | ||
| 275 | int ret = 0; | ||
| 276 | |||
| 277 | *out_s = NULL; | ||
| 278 | |||
| 279 | BN_CTX_start(ctx); | ||
| 280 | |||
| 281 | if ((b = BN_CTX_get(ctx)) == NULL) | ||
| 282 | goto err; | ||
| 283 | if ((binv = BN_CTX_get(ctx)) == NULL) | ||
| 284 | goto err; | ||
| 285 | if ((bm = BN_CTX_get(ctx)) == NULL) | ||
| 286 | goto err; | ||
| 287 | if ((bxr = BN_CTX_get(ctx)) == NULL) | ||
| 288 | goto err; | ||
| 289 | |||
| 290 | if ((s = BN_new()) == NULL) | ||
| 291 | goto err; | ||
| 292 | |||
| 293 | if (!bn_rand_interval(b, BN_value_one(), order)) { | ||
| 294 | ECDSAerror(ERR_R_BN_LIB); | ||
| 295 | goto err; | ||
| 296 | } | ||
| 297 | |||
| 298 | if (BN_mod_inverse_ct(binv, b, order, ctx) == NULL) { | ||
| 299 | ECDSAerror(ERR_R_BN_LIB); | ||
| 300 | goto err; | ||
| 301 | } | ||
| 302 | |||
| 303 | if (!BN_mod_mul(bxr, b, priv_key, order, ctx)) { | ||
| 304 | ECDSAerror(ERR_R_BN_LIB); | ||
| 305 | goto err; | ||
| 306 | } | ||
| 307 | if (!BN_mod_mul(bxr, bxr, r, order, ctx)) { | ||
| 308 | ECDSAerror(ERR_R_BN_LIB); | ||
| 309 | goto err; | ||
| 310 | } | ||
| 311 | if (!BN_mod_mul(bm, b, m, order, ctx)) { | ||
| 312 | ECDSAerror(ERR_R_BN_LIB); | ||
| 313 | goto err; | ||
| 314 | } | ||
| 315 | if (!BN_mod_add(s, bm, bxr, order, ctx)) { | ||
| 316 | ECDSAerror(ERR_R_BN_LIB); | ||
| 317 | goto err; | ||
| 318 | } | ||
| 319 | /* s = b(m + xr)k^-1 */ | ||
| 320 | if (!BN_mod_mul(s, s, kinv, order, ctx)) { | ||
| 321 | ECDSAerror(ERR_R_BN_LIB); | ||
| 322 | goto err; | ||
| 323 | } | ||
| 324 | /* s = (m + xr)k^-1 */ | ||
| 325 | if (!BN_mod_mul(s, s, binv, order, ctx)) { | ||
| 326 | ECDSAerror(ERR_R_BN_LIB); | ||
| 327 | goto err; | ||
| 328 | } | ||
| 329 | |||
| 330 | if (!BN_is_zero(s)) { | ||
| 331 | *out_s = s; | ||
| 332 | s = NULL; | ||
| 333 | } | ||
| 334 | |||
| 335 | ret = 1; | ||
| 336 | |||
| 337 | err: | ||
| 338 | BN_CTX_end(ctx); | ||
| 339 | BN_free(s); | ||
| 340 | |||
| 341 | return ret; | ||
| 342 | } | ||
| 343 | |||
| 344 | /* | ||
| 263 | * It is too expensive to check curve parameters on every sign operation. | 345 | * It is too expensive to check curve parameters on every sign operation. |
| 264 | * Instead, cap the number of retries. A single retry is very unlikely, so | 346 | * Instead, cap the number of retries. A single retry is very unlikely, so |
| 265 | * allowing 32 retries is amply enough. | 347 | * allowing 32 retries is amply enough. |
| @@ -273,7 +355,7 @@ ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len, | |||
| 273 | const EC_GROUP *group; | 355 | const EC_GROUP *group; |
| 274 | BN_CTX *ctx = NULL; | 356 | BN_CTX *ctx = NULL; |
| 275 | BIGNUM *kinv = NULL, *r = NULL, *s = NULL; | 357 | BIGNUM *kinv = NULL, *r = NULL, *s = NULL; |
| 276 | BIGNUM *b, *binv, *bm, *bxr, *m; | 358 | BIGNUM *m; |
| 277 | const BIGNUM *order, *priv_key; | 359 | const BIGNUM *order, *priv_key; |
| 278 | int caller_supplied_values = 0; | 360 | int caller_supplied_values = 0; |
| 279 | int attempts = 0; | 361 | int attempts = 0; |
| @@ -288,15 +370,6 @@ ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len, | |||
| 288 | goto err; | 370 | goto err; |
| 289 | } | 371 | } |
| 290 | 372 | ||
| 291 | if ((r = BN_new()) == NULL) { | ||
| 292 | ECDSAerror(ERR_R_MALLOC_FAILURE); | ||
| 293 | goto err; | ||
| 294 | } | ||
| 295 | if ((s = BN_new()) == NULL) { | ||
| 296 | ECDSAerror(ERR_R_MALLOC_FAILURE); | ||
| 297 | goto err; | ||
| 298 | } | ||
| 299 | |||
| 300 | if ((ctx = BN_CTX_new()) == NULL) { | 373 | if ((ctx = BN_CTX_new()) == NULL) { |
| 301 | ECDSAerror(ERR_R_MALLOC_FAILURE); | 374 | ECDSAerror(ERR_R_MALLOC_FAILURE); |
| 302 | goto err; | 375 | goto err; |
| @@ -304,14 +377,6 @@ ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len, | |||
| 304 | 377 | ||
| 305 | BN_CTX_start(ctx); | 378 | BN_CTX_start(ctx); |
| 306 | 379 | ||
| 307 | if ((b = BN_CTX_get(ctx)) == NULL) | ||
| 308 | goto err; | ||
| 309 | if ((binv = BN_CTX_get(ctx)) == NULL) | ||
| 310 | goto err; | ||
| 311 | if ((bm = BN_CTX_get(ctx)) == NULL) | ||
| 312 | goto err; | ||
| 313 | if ((bxr = BN_CTX_get(ctx)) == NULL) | ||
| 314 | goto err; | ||
| 315 | if ((m = BN_CTX_get(ctx)) == NULL) | 380 | if ((m = BN_CTX_get(ctx)) == NULL) |
| 316 | goto err; | 381 | goto err; |
| 317 | 382 | ||
| @@ -335,7 +400,7 @@ ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len, | |||
| 335 | ECDSAerror(ERR_R_MALLOC_FAILURE); | 400 | ECDSAerror(ERR_R_MALLOC_FAILURE); |
| 336 | goto err; | 401 | goto err; |
| 337 | } | 402 | } |
| 338 | if (!bn_copy(r, in_r)) { | 403 | if ((r = BN_dup(in_r)) == NULL) { |
| 339 | ECDSAerror(ERR_R_MALLOC_FAILURE); | 404 | ECDSAerror(ERR_R_MALLOC_FAILURE); |
| 340 | goto err; | 405 | goto err; |
| 341 | } | 406 | } |
| @@ -349,56 +414,10 @@ ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len, | |||
| 349 | } | 414 | } |
| 350 | } | 415 | } |
| 351 | 416 | ||
| 352 | /* | 417 | /* If s is non-NULL, we have a valid signature. */ |
| 353 | * Compute: | 418 | if (!ecdsa_compute_s(&s, m, kinv, r, priv_key, order, ctx)) |
| 354 | * | ||
| 355 | * s = inv(k)(m + xr) mod order | ||
| 356 | * | ||
| 357 | * In order to reduce the possibility of a side-channel attack, | ||
| 358 | * the following is calculated using a blinding value: | ||
| 359 | * | ||
| 360 | * s = inv(b)(bm + bxr)inv(k) mod order | ||
| 361 | * | ||
| 362 | * where b is a random value in the range [1, order). | ||
| 363 | */ | ||
| 364 | |||
| 365 | if (!bn_rand_interval(b, BN_value_one(), order)) { | ||
| 366 | ECDSAerror(ERR_R_BN_LIB); | ||
| 367 | goto err; | ||
| 368 | } | ||
| 369 | |||
| 370 | if (BN_mod_inverse_ct(binv, b, order, ctx) == NULL) { | ||
| 371 | ECDSAerror(ERR_R_BN_LIB); | ||
| 372 | goto err; | ||
| 373 | } | ||
| 374 | |||
| 375 | if (!BN_mod_mul(bxr, b, priv_key, order, ctx)) { /* bx */ | ||
| 376 | ECDSAerror(ERR_R_BN_LIB); | ||
| 377 | goto err; | ||
| 378 | } | ||
| 379 | if (!BN_mod_mul(bxr, bxr, r, order, ctx)) { /* bxr */ | ||
| 380 | ECDSAerror(ERR_R_BN_LIB); | ||
| 381 | goto err; | ||
| 382 | } | ||
| 383 | if (!BN_mod_mul(bm, b, m, order, ctx)) { /* bm */ | ||
| 384 | ECDSAerror(ERR_R_BN_LIB); | ||
| 385 | goto err; | 419 | goto err; |
| 386 | } | 420 | if (s != NULL) |
| 387 | if (!BN_mod_add(s, bm, bxr, order, ctx)) { /* s = bm + bxr */ | ||
| 388 | ECDSAerror(ERR_R_BN_LIB); | ||
| 389 | goto err; | ||
| 390 | } | ||
| 391 | if (!BN_mod_mul(s, s, kinv, order, ctx)) { /* s = b(m + xr)k^-1 */ | ||
| 392 | ECDSAerror(ERR_R_BN_LIB); | ||
| 393 | goto err; | ||
| 394 | } | ||
| 395 | if (!BN_mod_mul(s, s, binv, order, ctx)) { /* s = (m + xr)k^-1 */ | ||
| 396 | ECDSAerror(ERR_R_BN_LIB); | ||
| 397 | goto err; | ||
| 398 | } | ||
| 399 | |||
| 400 | /* If s is non-zero, we have a valid signature. */ | ||
| 401 | if (!BN_is_zero(s)) | ||
| 402 | break; | 421 | break; |
| 403 | 422 | ||
| 404 | if (caller_supplied_values) { | 423 | if (caller_supplied_values) { |
