diff options
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); |