diff options
| author | jsing <> | 2023-02-22 05:25:47 +0000 |
|---|---|---|
| committer | jsing <> | 2023-02-22 05:25:47 +0000 |
| commit | 12aca8f870a07f30e989b326c4371746b668dc5f (patch) | |
| tree | 5f5afd57f49d799d6b6009aa89d682b6e78ee6a2 /src | |
| parent | d8461c9d54c6b42b4f063da326afcf700ebcbe4f (diff) | |
| download | openbsd-12aca8f870a07f30e989b326c4371746b668dc5f.tar.gz openbsd-12aca8f870a07f30e989b326c4371746b668dc5f.tar.bz2 openbsd-12aca8f870a07f30e989b326c4371746b668dc5f.zip | |
Rewrite and simplify BN_MONT_CTX_set()
OpenSSL commit 4d524040bc8 changed BN_MONT_CTX_set() so that it computed
a 64 bit N^-1 on both BN_BITS2 == 32 and BN_BITS2 == 64 platforms. However,
the way in which this was done was to duplicate half the code and wrap it
in #ifdef.
Rewrite this code to use a single code path on all platforms, with #ifdef
being limited to setting an additional word in the temporary N and storing
the result on BN_BITS2 == 32 platforms. Also remove stack based BIGNUM in
favour of using the already present BN_CTX.
ok tb@
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/libcrypto/bn/bn_local.h | 15 | ||||
| -rw-r--r-- | src/lib/libcrypto/bn/bn_mont.c | 159 |
2 files changed, 76 insertions, 98 deletions
diff --git a/src/lib/libcrypto/bn/bn_local.h b/src/lib/libcrypto/bn/bn_local.h index c763890695..35e9073e2d 100644 --- a/src/lib/libcrypto/bn/bn_local.h +++ b/src/lib/libcrypto/bn/bn_local.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: bn_local.h,v 1.14 2023/02/21 05:58:08 jsing Exp $ */ | 1 | /* $OpenBSD: bn_local.h,v 1.15 2023/02/22 05:25:47 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 | * |
| @@ -127,13 +127,14 @@ struct bignum_st { | |||
| 127 | int flags; | 127 | int flags; |
| 128 | }; | 128 | }; |
| 129 | 129 | ||
| 130 | /* Used for montgomery multiplication */ | ||
| 131 | struct bn_mont_ctx_st { | 130 | struct bn_mont_ctx_st { |
| 132 | int ri; /* number of bits in R */ | 131 | int ri; /* Number of bits in R */ |
| 133 | BIGNUM RR; /* used to convert to montgomery form */ | 132 | BIGNUM RR; /* Used to convert to Montgomery form */ |
| 134 | BIGNUM N; /* The modulus */ | 133 | BIGNUM N; /* Modulus */ |
| 135 | BN_ULONG n0[2];/* least significant word(s) of Ni; R*(1/R mod N) - N*Ni = 1 | 134 | |
| 136 | (type changed with 0.9.9, was "BN_ULONG n0;" before) */ | 135 | /* Least significant word(s) of Ni; R*(1/R mod N) - N*Ni = 1 */ |
| 136 | BN_ULONG n0[2]; | ||
| 137 | |||
| 137 | int flags; | 138 | int flags; |
| 138 | }; | 139 | }; |
| 139 | 140 | ||
diff --git a/src/lib/libcrypto/bn/bn_mont.c b/src/lib/libcrypto/bn/bn_mont.c index a54355ca37..559811b975 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.44 2023/02/21 12:20:22 bcook Exp $ */ | 1 | /* $OpenBSD: bn_mont.c,v 1.45 2023/02/22 05:25:47 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 | * |
| @@ -120,6 +120,7 @@ | |||
| 120 | #include <stdint.h> | 120 | #include <stdint.h> |
| 121 | #include <string.h> | 121 | #include <string.h> |
| 122 | 122 | ||
| 123 | #include "bn_internal.h" | ||
| 123 | #include "bn_local.h" | 124 | #include "bn_local.h" |
| 124 | 125 | ||
| 125 | BN_MONT_CTX * | 126 | BN_MONT_CTX * |
| @@ -180,114 +181,89 @@ BN_MONT_CTX_copy(BN_MONT_CTX *dst, BN_MONT_CTX *src) | |||
| 180 | int | 181 | int |
| 181 | BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) | 182 | BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) |
| 182 | { | 183 | { |
| 184 | BIGNUM *N, *Ninv, *Rinv, *R; | ||
| 183 | int ret = 0; | 185 | int ret = 0; |
| 184 | BIGNUM *Ri, *R; | ||
| 185 | |||
| 186 | if (BN_is_zero(mod)) | ||
| 187 | return 0; | ||
| 188 | 186 | ||
| 189 | BN_CTX_start(ctx); | 187 | BN_CTX_start(ctx); |
| 190 | if ((Ri = BN_CTX_get(ctx)) == NULL) | 188 | |
| 189 | if ((N = BN_CTX_get(ctx)) == NULL) | ||
| 190 | goto err; | ||
| 191 | if ((Ninv = BN_CTX_get(ctx)) == NULL) | ||
| 192 | goto err; | ||
| 193 | if ((R = BN_CTX_get(ctx)) == NULL) | ||
| 194 | goto err; | ||
| 195 | if ((Rinv = BN_CTX_get(ctx)) == NULL) | ||
| 191 | goto err; | 196 | goto err; |
| 192 | R = &(mont->RR); /* grab RR as a temp */ | ||
| 193 | if (!BN_copy(&(mont->N), mod)) | ||
| 194 | goto err; /* Set N */ | ||
| 195 | mont->N.neg = 0; | ||
| 196 | 197 | ||
| 197 | { | 198 | /* Save modulus and determine length of R. */ |
| 198 | BIGNUM tmod; | 199 | if (BN_is_zero(mod)) |
| 199 | BN_ULONG buf[2]; | 200 | goto err; |
| 201 | if (!BN_copy(&mont->N, mod)) | ||
| 202 | goto err; | ||
| 203 | mont->N.neg = 0; | ||
| 204 | mont->ri = (BN_num_bits(mod) + (BN_BITS2 - 1)) / BN_BITS2 * BN_BITS2; | ||
| 205 | if (mont->ri * 2 < mont->ri) | ||
| 206 | goto err; | ||
| 200 | 207 | ||
| 201 | BN_init(&tmod); | 208 | /* |
| 202 | tmod.d = buf; | 209 | * Compute Ninv = (R * Rinv - 1)/N mod R, for R = 2^64. This provides |
| 203 | tmod.dmax = 2; | 210 | * a single or double word result (dependent on BN word size), that is |
| 204 | tmod.neg = 0; | 211 | * later used to implement Montgomery reduction. |
| 212 | */ | ||
| 213 | BN_zero(R); | ||
| 214 | if (!BN_set_bit(R, 64)) | ||
| 215 | goto err; | ||
| 205 | 216 | ||
| 206 | mont->ri = (BN_num_bits(mod) + | 217 | /* N = N mod R. */ |
| 207 | (BN_BITS2 - 1)) / BN_BITS2 * BN_BITS2; | 218 | if (!bn_wexpand(N, 2)) |
| 219 | goto err; | ||
| 220 | if (!BN_set_word(N, mod->d[0])) | ||
| 221 | goto err; | ||
| 222 | #if BN_BITS2 == 32 | ||
| 223 | if (mod->top > 1) { | ||
| 224 | N->d[1] = mod->d[1]; | ||
| 225 | N->top += bn_ct_ne_zero(N->d[1]); | ||
| 226 | } | ||
| 227 | #endif | ||
| 208 | 228 | ||
| 209 | #if defined(OPENSSL_BN_ASM_MONT) && (BN_BITS2<=32) | 229 | /* Rinv = R^-1 mod N */ |
| 210 | /* Only certain BN_BITS2<=32 platforms actually make use of | 230 | if ((BN_mod_inverse_ct(Rinv, R, N, ctx)) == NULL) |
| 211 | * n0[1], and we could use the #else case (with a shorter R | 231 | goto err; |
| 212 | * value) for the others. However, currently only the assembler | ||
| 213 | * files do know which is which. */ | ||
| 214 | 232 | ||
| 215 | BN_zero(R); | 233 | /* Ninv = (R * Rinv - 1) / N */ |
| 216 | if (!(BN_set_bit(R, 2 * BN_BITS2))) | 234 | if (!BN_lshift(Ninv, Rinv, 64)) |
| 235 | goto err; | ||
| 236 | if (BN_is_zero(Ninv)) { | ||
| 237 | /* R * Rinv == 0, set to R so that R * Rinv - 1 is mod R. */ | ||
| 238 | if (!BN_set_bit(Ninv, 64)) | ||
| 217 | goto err; | 239 | goto err; |
| 240 | } | ||
| 241 | if (!BN_sub_word(Ninv, 1)) | ||
| 242 | goto err; | ||
| 243 | if (!BN_div_ct(Ninv, NULL, Ninv, N, ctx)) | ||
| 244 | goto err; | ||
| 218 | 245 | ||
| 219 | tmod.top = 0; | 246 | /* Store least significant word(s) of Ninv. */ |
| 220 | if ((buf[0] = mod->d[0])) | 247 | mont->n0[0] = mont->n0[1] = 0; |
| 221 | tmod.top = 1; | 248 | if (Ninv->top > 0) |
| 222 | if ((buf[1] = mod->top > 1 ? mod->d[1] : 0)) | 249 | mont->n0[0] = Ninv->d[0]; |
| 223 | tmod.top = 2; | 250 | #if BN_BITS2 == 32 |
| 224 | 251 | /* Some BN_BITS2 == 32 platforms (namely parisc) use two words of Ninv. */ | |
| 225 | if ((BN_mod_inverse_ct(Ri, R, &tmod, ctx)) == NULL) | 252 | if (Ninv->top > 1) |
| 226 | goto err; | 253 | mont->n0[1] = Ninv->d[1]; |
| 227 | if (!BN_lshift(Ri, Ri, 2 * BN_BITS2)) | ||
| 228 | goto err; /* R*Ri */ | ||
| 229 | if (!BN_is_zero(Ri)) { | ||
| 230 | if (!BN_sub_word(Ri, 1)) | ||
| 231 | goto err; | ||
| 232 | } | ||
| 233 | else /* if N mod word size == 1 */ | ||
| 234 | { | ||
| 235 | if (!bn_wexpand(Ri, 2)) | ||
| 236 | goto err; | ||
| 237 | /* Ri-- (mod double word size) */ | ||
| 238 | Ri->neg = 0; | ||
| 239 | Ri->d[0] = BN_MASK2; | ||
| 240 | Ri->d[1] = BN_MASK2; | ||
| 241 | Ri->top = 2; | ||
| 242 | } | ||
| 243 | if (!BN_div_ct(Ri, NULL, Ri, &tmod, ctx)) | ||
| 244 | goto err; | ||
| 245 | /* Ni = (R*Ri-1)/N, | ||
| 246 | * keep only couple of least significant words: */ | ||
| 247 | mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0; | ||
| 248 | mont->n0[1] = (Ri->top > 1) ? Ri->d[1] : 0; | ||
| 249 | #else | ||
| 250 | BN_zero(R); | ||
| 251 | if (!(BN_set_bit(R, BN_BITS2))) | ||
| 252 | goto err; /* R */ | ||
| 253 | |||
| 254 | buf[0] = mod->d[0]; /* tmod = N mod word size */ | ||
| 255 | buf[1] = 0; | ||
| 256 | tmod.top = buf[0] != 0 ? 1 : 0; | ||
| 257 | /* Ri = R^-1 mod N*/ | ||
| 258 | if ((BN_mod_inverse_ct(Ri, R, &tmod, ctx)) == NULL) | ||
| 259 | goto err; | ||
| 260 | if (!BN_lshift(Ri, Ri, BN_BITS2)) | ||
| 261 | goto err; /* R*Ri */ | ||
| 262 | if (!BN_is_zero(Ri)) { | ||
| 263 | if (!BN_sub_word(Ri, 1)) | ||
| 264 | goto err; | ||
| 265 | } | ||
| 266 | else /* if N mod word size == 1 */ | ||
| 267 | { | ||
| 268 | if (!BN_set_word(Ri, BN_MASK2)) | ||
| 269 | goto err; /* Ri-- (mod word size) */ | ||
| 270 | } | ||
| 271 | if (!BN_div_ct(Ri, NULL, Ri, &tmod, ctx)) | ||
| 272 | goto err; | ||
| 273 | /* Ni = (R*Ri-1)/N, | ||
| 274 | * keep only least significant word: */ | ||
| 275 | mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0; | ||
| 276 | mont->n0[1] = 0; | ||
| 277 | #endif | 254 | #endif |
| 278 | } | ||
| 279 | 255 | ||
| 280 | /* setup RR for conversions */ | 256 | /* Compute RR = R * R mod N, for use when converting to Montgomery form. */ |
| 281 | BN_zero(&(mont->RR)); | 257 | BN_zero(&mont->RR); |
| 282 | if (!BN_set_bit(&(mont->RR), mont->ri*2)) | 258 | if (!BN_set_bit(&mont->RR, mont->ri * 2)) |
| 283 | goto err; | 259 | goto err; |
| 284 | if (!BN_mod_ct(&(mont->RR), &(mont->RR), &(mont->N), ctx)) | 260 | if (!BN_mod_ct(&mont->RR, &mont->RR, &mont->N, ctx)) |
| 285 | goto err; | 261 | goto err; |
| 286 | 262 | ||
| 287 | ret = 1; | 263 | ret = 1; |
| 288 | 264 | err: | |
| 289 | err: | ||
| 290 | BN_CTX_end(ctx); | 265 | BN_CTX_end(ctx); |
| 266 | |||
| 291 | return ret; | 267 | return ret; |
| 292 | } | 268 | } |
| 293 | 269 | ||
| @@ -427,6 +403,7 @@ err: | |||
| 427 | int | 403 | int |
| 428 | BN_to_montgomery(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont, BN_CTX *ctx) | 404 | BN_to_montgomery(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont, BN_CTX *ctx) |
| 429 | { | 405 | { |
| 406 | /* Compute r = a * R * R * R^-1 mod N = aR mod N */ | ||
| 430 | return BN_mod_mul_montgomery(r, a, &mont->RR, mont, ctx); | 407 | return BN_mod_mul_montgomery(r, a, &mont->RR, mont, ctx); |
| 431 | } | 408 | } |
| 432 | 409 | ||
