diff options
| author | jsing <> | 2025-05-25 05:12:05 +0000 |
|---|---|---|
| committer | jsing <> | 2025-05-25 05:12:05 +0000 |
| commit | 2f7bf75477a5741ad76c3c793c7ed887b41fcceb (patch) | |
| tree | d2a89424948ea33ced8fe1bb82297f1988893a57 /src/lib/libcrypto/bn | |
| parent | aada760c0a63cc97f8def7686fe6d76d3a3cc4d9 (diff) | |
| download | openbsd-2f7bf75477a5741ad76c3c793c7ed887b41fcceb.tar.gz openbsd-2f7bf75477a5741ad76c3c793c7ed887b41fcceb.tar.bz2 openbsd-2f7bf75477a5741ad76c3c793c7ed887b41fcceb.zip | |
Implement EC field element operations.
Provide EC_FIELD_ELEMENT and EC_FIELD_MODULUS, which allow for operations
on fixed width fields in constant time. These can in turn be used to
implement Elliptic Curve cryptography for prime fields, without needing
to use BN. This will improve the code, reduces timing leaks and enable
further optimisation.
ok beck@ tb@
Diffstat (limited to 'src/lib/libcrypto/bn')
| -rw-r--r-- | src/lib/libcrypto/bn/bn_internal.h | 4 | ||||
| -rw-r--r-- | src/lib/libcrypto/bn/bn_mont.c | 71 |
2 files changed, 45 insertions, 30 deletions
diff --git a/src/lib/libcrypto/bn/bn_internal.h b/src/lib/libcrypto/bn/bn_internal.h index b6e903553f..a1f1515b57 100644 --- a/src/lib/libcrypto/bn/bn_internal.h +++ b/src/lib/libcrypto/bn/bn_internal.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: bn_internal.h,v 1.18 2025/05/25 04:58:32 jsing Exp $ */ | 1 | /* $OpenBSD: bn_internal.h,v 1.19 2025/05/25 05:12:05 jsing Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2023 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2023 Joel Sing <jsing@openbsd.org> |
| 4 | * | 4 | * |
| @@ -45,6 +45,8 @@ void bn_mod_mul_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, | |||
| 45 | void bn_montgomery_multiply_words(BN_ULONG *rp, const BN_ULONG *ap, | 45 | void bn_montgomery_multiply_words(BN_ULONG *rp, const BN_ULONG *ap, |
| 46 | const BN_ULONG *bp, const BN_ULONG *np, BN_ULONG *tp, BN_ULONG n0, | 46 | const BN_ULONG *bp, const BN_ULONG *np, BN_ULONG *tp, BN_ULONG n0, |
| 47 | int n_len); | 47 | int n_len); |
| 48 | void bn_montgomery_reduce_words(BN_ULONG *r, BN_ULONG *a, const BN_ULONG *n, | ||
| 49 | BN_ULONG n0, int n_len); | ||
| 48 | 50 | ||
| 49 | #ifndef HAVE_BN_CT_NE_ZERO | 51 | #ifndef HAVE_BN_CT_NE_ZERO |
| 50 | static inline int | 52 | static inline int |
diff --git a/src/lib/libcrypto/bn/bn_mont.c b/src/lib/libcrypto/bn/bn_mont.c index ce88b23ca9..950846fa5b 100644 --- a/src/lib/libcrypto/bn/bn_mont.c +++ b/src/lib/libcrypto/bn/bn_mont.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: bn_mont.c,v 1.67 2025/05/25 04:58:32 jsing Exp $ */ | 1 | /* $OpenBSD: bn_mont.c,v 1.68 2025/05/25 05:12:05 jsing Exp $ */ |
| 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
| 3 | * All rights reserved. | 3 | * All rights reserved. |
| 4 | * | 4 | * |
| @@ -316,6 +316,44 @@ BN_MONT_CTX_set_locked(BN_MONT_CTX **pmctx, int lock, const BIGNUM *mod, | |||
| 316 | LCRYPTO_ALIAS(BN_MONT_CTX_set_locked); | 316 | LCRYPTO_ALIAS(BN_MONT_CTX_set_locked); |
| 317 | 317 | ||
| 318 | /* | 318 | /* |
| 319 | * bn_montgomery_reduce_words() performs Montgomery reduction, reducing the input | ||
| 320 | * from its Montgomery form aR to a, returning the result in r. a must be twice | ||
| 321 | * the length of the modulus. Note that the input is mutated in the process of | ||
| 322 | * performing the reduction. | ||
| 323 | */ | ||
| 324 | void | ||
| 325 | bn_montgomery_reduce_words(BN_ULONG *r, BN_ULONG *a, const BN_ULONG *n, | ||
| 326 | BN_ULONG n0, int n_len) | ||
| 327 | { | ||
| 328 | BN_ULONG v, mask; | ||
| 329 | BN_ULONG carry = 0; | ||
| 330 | int i; | ||
| 331 | |||
| 332 | /* Add multiples of the modulus, so that it becomes divisible by R. */ | ||
| 333 | for (i = 0; i < n_len; i++) { | ||
| 334 | v = bn_mul_add_words(&a[i], n, n_len, a[i] * n0); | ||
| 335 | bn_addw_addw(v, a[i + n_len], carry, &carry, &a[i + n_len]); | ||
| 336 | } | ||
| 337 | |||
| 338 | /* Divide by R (this is the equivalent of right shifting by n_len). */ | ||
| 339 | a = &a[n_len]; | ||
| 340 | |||
| 341 | /* | ||
| 342 | * The output is now in the range of [0, 2N). Attempt to reduce once by | ||
| 343 | * subtracting the modulus. If the reduction was necessary then the | ||
| 344 | * result is already in r, otherwise copy the value prior to reduction | ||
| 345 | * from the top half of a. | ||
| 346 | */ | ||
| 347 | mask = carry - bn_sub_words(r, a, n, n_len); | ||
| 348 | |||
| 349 | for (i = 0; i < n_len; i++) { | ||
| 350 | *r = (*r & ~mask) | (*a & mask); | ||
| 351 | r++; | ||
| 352 | a++; | ||
| 353 | } | ||
| 354 | } | ||
| 355 | |||
| 356 | /* | ||
| 319 | * bn_montgomery_reduce() performs Montgomery reduction, reducing the input | 357 | * bn_montgomery_reduce() performs Montgomery reduction, reducing the input |
| 320 | * from its Montgomery form aR to a, returning the result in r. Note that the | 358 | * from its Montgomery form aR to a, returning the result in r. Note that the |
| 321 | * input is mutated in the process of performing the reduction, destroying its | 359 | * input is mutated in the process of performing the reduction, destroying its |
| @@ -325,7 +363,6 @@ static int | |||
| 325 | bn_montgomery_reduce(BIGNUM *r, BIGNUM *a, BN_MONT_CTX *mctx) | 363 | bn_montgomery_reduce(BIGNUM *r, BIGNUM *a, BN_MONT_CTX *mctx) |
| 326 | { | 364 | { |
| 327 | BIGNUM *n; | 365 | BIGNUM *n; |
| 328 | BN_ULONG *ap, *rp, n0, v, carry, mask; | ||
| 329 | int i, max, n_len; | 366 | int i, max, n_len; |
| 330 | 367 | ||
| 331 | n = &mctx->N; | 368 | n = &mctx->N; |
| @@ -341,7 +378,8 @@ bn_montgomery_reduce(BIGNUM *r, BIGNUM *a, BN_MONT_CTX *mctx) | |||
| 341 | 378 | ||
| 342 | /* | 379 | /* |
| 343 | * Expand a to twice the length of the modulus, zero if necessary. | 380 | * Expand a to twice the length of the modulus, zero if necessary. |
| 344 | * XXX - make this a requirement of the caller. | 381 | * XXX - make this a requirement of the caller or use a temporary |
| 382 | * allocation. | ||
| 345 | */ | 383 | */ |
| 346 | if ((max = 2 * n_len) < n_len) | 384 | if ((max = 2 * n_len) < n_len) |
| 347 | return 0; | 385 | return 0; |
| @@ -350,33 +388,8 @@ bn_montgomery_reduce(BIGNUM *r, BIGNUM *a, BN_MONT_CTX *mctx) | |||
| 350 | for (i = a->top; i < max; i++) | 388 | for (i = a->top; i < max; i++) |
| 351 | a->d[i] = 0; | 389 | a->d[i] = 0; |
| 352 | 390 | ||
| 353 | carry = 0; | 391 | bn_montgomery_reduce_words(r->d, a->d, n->d, mctx->n0[0], n_len); |
| 354 | n0 = mctx->n0[0]; | ||
| 355 | |||
| 356 | /* Add multiples of the modulus, so that it becomes divisible by R. */ | ||
| 357 | for (i = 0; i < n_len; i++) { | ||
| 358 | v = bn_mul_add_words(&a->d[i], n->d, n_len, a->d[i] * n0); | ||
| 359 | bn_addw_addw(v, a->d[i + n_len], carry, &carry, | ||
| 360 | &a->d[i + n_len]); | ||
| 361 | } | ||
| 362 | |||
| 363 | /* Divide by R (this is the equivalent of right shifting by n_len). */ | ||
| 364 | ap = &a->d[n_len]; | ||
| 365 | |||
| 366 | /* | ||
| 367 | * The output is now in the range of [0, 2N). Attempt to reduce once by | ||
| 368 | * subtracting the modulus. If the reduction was necessary then the | ||
| 369 | * result is already in r, otherwise copy the value prior to reduction | ||
| 370 | * from the top half of a. | ||
| 371 | */ | ||
| 372 | mask = carry - bn_sub_words(r->d, ap, n->d, n_len); | ||
| 373 | 392 | ||
| 374 | rp = r->d; | ||
| 375 | for (i = 0; i < n_len; i++) { | ||
| 376 | *rp = (*rp & ~mask) | (*ap & mask); | ||
| 377 | rp++; | ||
| 378 | ap++; | ||
| 379 | } | ||
| 380 | r->top = n_len; | 393 | r->top = n_len; |
| 381 | 394 | ||
| 382 | bn_correct_top(r); | 395 | bn_correct_top(r); |
