diff options
| author | jsing <> | 2023-01-28 16:33:34 +0000 |
|---|---|---|
| committer | jsing <> | 2023-01-28 16:33:34 +0000 |
| commit | 636918f6cfde69d37b71f6ff3da1a6eb6cf4ad65 (patch) | |
| tree | 77285c9d112391ced3ea1c6ee831bf186ff9316b /src/lib/libcrypto/bn/bn_div.c | |
| parent | 971c759a469620704a18f7c93e7d71fbae75e7c2 (diff) | |
| download | openbsd-636918f6cfde69d37b71f6ff3da1a6eb6cf4ad65.tar.gz openbsd-636918f6cfde69d37b71f6ff3da1a6eb6cf4ad65.tar.bz2 openbsd-636918f6cfde69d37b71f6ff3da1a6eb6cf4ad65.zip | |
Provide bn_div_rem_words() and make use of it.
Provide a function that divides a double word (h:l) by d, returning the
quotient q and the remainder r, such that q * d + r is equal to the
numerator. Call this from the three places that currently implement this
themselves.
This is implemented with some slight indirection, which allows for per
architecture implementations, replacing the define/macro tangle, which
messes with variables that are not passed to it.
Also remove a duplicate of bn_div_words() for the BN_ULLONG && BN_DIV2W
case - this is already handled.
ok tb@
Diffstat (limited to 'src/lib/libcrypto/bn/bn_div.c')
| -rw-r--r-- | src/lib/libcrypto/bn/bn_div.c | 85 |
1 files changed, 26 insertions, 59 deletions
diff --git a/src/lib/libcrypto/bn/bn_div.c b/src/lib/libcrypto/bn/bn_div.c index 8ec2e01831..e60fb84062 100644 --- a/src/lib/libcrypto/bn/bn_div.c +++ b/src/lib/libcrypto/bn/bn_div.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: bn_div.c,v 1.33 2023/01/23 12:02:48 jsing Exp $ */ | 1 | /* $OpenBSD: bn_div.c,v 1.34 2023/01/28 16:33:34 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 | * |
| @@ -150,49 +150,30 @@ bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) | |||
| 150 | #endif /* !defined(BN_LLONG) && defined(BN_DIV2W) */ | 150 | #endif /* !defined(BN_LLONG) && defined(BN_DIV2W) */ |
| 151 | #endif | 151 | #endif |
| 152 | 152 | ||
| 153 | #ifndef HAVE_BN_DIV_3_WORDS | 153 | /* |
| 154 | * Divide a double word (h:l) by d, returning the quotient q and the remainder | ||
| 155 | * r, such that q * d + r is equal to the numerator. | ||
| 156 | */ | ||
| 157 | #ifndef HAVE_BN_DIV_REM_WORDS | ||
| 158 | #ifndef HAVE_BN_DIV_REM_WORDS_INLINE | ||
| 159 | static inline | ||
| 160 | bn_div_rem_words_inline(BN_ULONG h, BN_ULONG l, BN_ULONG d, BN_ULONG *out_q, | ||
| 161 | BN_ULONG *out_r) | ||
| 162 | { | ||
| 163 | *q = bn_div_words(h, l, d); | ||
| 164 | *r = (l - q * d) & BN_MASK2; | ||
| 165 | } | ||
| 166 | #endif | ||
| 154 | 167 | ||
| 155 | #if !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) | 168 | void |
| 156 | # if defined(__GNUC__) && __GNUC__>=2 | 169 | bn_div_rem_words(BN_ULONG h, BN_ULONG l, BN_ULONG d, BN_ULONG *out_q, |
| 157 | # if defined(__i386) || defined (__i386__) | 170 | BN_ULONG *out_r) |
| 158 | /* | 171 | { |
| 159 | * There were two reasons for implementing this template: | 172 | bn_div_rem_words_inline(h, l, d, out_q, out_r); |
| 160 | * - GNU C generates a call to a function (__udivdi3 to be exact) | 173 | } |
| 161 | * in reply to ((((BN_ULLONG)n0)<<BN_BITS2)|n1)/d0 (I fail to | 174 | #endif |
| 162 | * understand why...); | 175 | |
| 163 | * - divl doesn't only calculate quotient, but also leaves | 176 | #ifndef HAVE_BN_DIV_3_WORDS |
| 164 | * remainder in %edx which we can definitely use here:-) | ||
| 165 | * | ||
| 166 | * <appro@fy.chalmers.se> | ||
| 167 | */ | ||
| 168 | #undef bn_div_words | ||
| 169 | # define bn_div_words(n0,n1,d0) \ | ||
| 170 | ({ asm volatile ( \ | ||
| 171 | "divl %4" \ | ||
| 172 | : "=a"(q), "=d"(rem) \ | ||
| 173 | : "a"(n1), "d"(n0), "g"(d0) \ | ||
| 174 | : "cc"); \ | ||
| 175 | q; \ | ||
| 176 | }) | ||
| 177 | # define REMAINDER_IS_ALREADY_CALCULATED | ||
| 178 | # elif defined(__x86_64) | ||
| 179 | /* | ||
| 180 | * Same story here, but it's 128-bit by 64-bit division. Wow! | ||
| 181 | * <appro@fy.chalmers.se> | ||
| 182 | */ | ||
| 183 | # undef bn_div_words | ||
| 184 | # define bn_div_words(n0,n1,d0) \ | ||
| 185 | ({ asm volatile ( \ | ||
| 186 | "divq %4" \ | ||
| 187 | : "=a"(q), "=d"(rem) \ | ||
| 188 | : "a"(n1), "d"(n0), "g"(d0) \ | ||
| 189 | : "cc"); \ | ||
| 190 | q; \ | ||
| 191 | }) | ||
| 192 | # define REMAINDER_IS_ALREADY_CALCULATED | ||
| 193 | # endif /* __<cpu> */ | ||
| 194 | # endif /* __GNUC__ */ | ||
| 195 | #endif /* OPENSSL_NO_ASM */ | ||
| 196 | 177 | ||
| 197 | /* | 178 | /* |
| 198 | * Interface is somewhat quirky, |m| is pointer to most significant limb, | 179 | * Interface is somewhat quirky, |m| is pointer to most significant limb, |
| @@ -219,19 +200,8 @@ bn_div_3_words(const BN_ULONG *m, BN_ULONG d1, BN_ULONG d0) | |||
| 219 | #ifdef BN_LLONG | 200 | #ifdef BN_LLONG |
| 220 | BN_ULLONG t2; | 201 | BN_ULLONG t2; |
| 221 | 202 | ||
| 222 | #if defined(BN_DIV2W) && !defined(bn_div_words) | 203 | bn_div_rem_words(n0, n1, d0, &q, &rem); |
| 223 | q = (BN_ULONG)((((BN_ULLONG)n0 << BN_BITS2) | n1) / d0); | ||
| 224 | #else | ||
| 225 | q = bn_div_words(n0, n1, d0); | ||
| 226 | #endif | ||
| 227 | 204 | ||
| 228 | #ifndef REMAINDER_IS_ALREADY_CALCULATED | ||
| 229 | /* | ||
| 230 | * rem doesn't have to be BN_ULLONG. The least we | ||
| 231 | * know it's less that d0, isn't it? | ||
| 232 | */ | ||
| 233 | rem = (n1 - q * d0) & BN_MASK2; | ||
| 234 | #endif | ||
| 235 | t2 = (BN_ULLONG)d1 * q; | 205 | t2 = (BN_ULLONG)d1 * q; |
| 236 | 206 | ||
| 237 | for (;;) { | 207 | for (;;) { |
| @@ -245,10 +215,7 @@ bn_div_3_words(const BN_ULONG *m, BN_ULONG d1, BN_ULONG d0) | |||
| 245 | #else /* !BN_LLONG */ | 215 | #else /* !BN_LLONG */ |
| 246 | BN_ULONG t2l, t2h; | 216 | BN_ULONG t2l, t2h; |
| 247 | 217 | ||
| 248 | q = bn_div_words(n0, n1, d0); | 218 | bn_div_rem_words(n0, n1, d0, &q, &rem); |
| 249 | #ifndef REMAINDER_IS_ALREADY_CALCULATED | ||
| 250 | rem = (n1 - q * d0) & BN_MASK2; | ||
| 251 | #endif | ||
| 252 | 219 | ||
| 253 | #if defined(BN_UMULT_LOHI) | 220 | #if defined(BN_UMULT_LOHI) |
| 254 | BN_UMULT_LOHI(t2l, t2h, d1, q); | 221 | BN_UMULT_LOHI(t2l, t2h, d1, q); |
