summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjsing <>2023-01-28 16:33:34 +0000
committerjsing <>2023-01-28 16:33:34 +0000
commitd63f41446c0a5c6fb98126ac39bea7d011911bf2 (patch)
tree77285c9d112391ced3ea1c6ee831bf186ff9316b /src
parent6738561f9181a99b8aa084f27caeea50afddc836 (diff)
downloadopenbsd-d63f41446c0a5c6fb98126ac39bea7d011911bf2.tar.gz
openbsd-d63f41446c0a5c6fb98126ac39bea7d011911bf2.tar.bz2
openbsd-d63f41446c0a5c6fb98126ac39bea7d011911bf2.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')
-rw-r--r--src/lib/libcrypto/bn/arch/amd64/bn_arch.h27
-rw-r--r--src/lib/libcrypto/bn/arch/i386/bn_arch.h27
-rw-r--r--src/lib/libcrypto/bn/bn_div.c85
-rw-r--r--src/lib/libcrypto/bn/bn_local.h10
-rw-r--r--src/lib/libcrypto/bn/bn_word.c5
5 files changed, 87 insertions, 67 deletions
diff --git a/src/lib/libcrypto/bn/arch/amd64/bn_arch.h b/src/lib/libcrypto/bn/arch/amd64/bn_arch.h
index 065f6b1c3b..6b7eaf5eee 100644
--- a/src/lib/libcrypto/bn/arch/amd64/bn_arch.h
+++ b/src/lib/libcrypto/bn/arch/amd64/bn_arch.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: bn_arch.h,v 1.7 2023/01/23 12:17:57 jsing Exp $ */ 1/* $OpenBSD: bn_arch.h,v 1.8 2023/01/28 16:33:34 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2023 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2023 Joel Sing <jsing@openbsd.org>
4 * 4 *
@@ -15,6 +15,8 @@
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */ 16 */
17 17
18#include <openssl/bn.h>
19
18#ifndef HEADER_BN_ARCH_H 20#ifndef HEADER_BN_ARCH_H
19#define HEADER_BN_ARCH_H 21#define HEADER_BN_ARCH_H
20 22
@@ -36,5 +38,28 @@
36 38
37#define HAVE_BN_SUB_WORDS 39#define HAVE_BN_SUB_WORDS
38 40
41#if defined(__GNUC__)
42#define HAVE_BN_DIV_REM_WORDS_INLINE
43
44static inline void
45bn_div_rem_words_inline(BN_ULONG h, BN_ULONG l, BN_ULONG d, BN_ULONG *out_q,
46 BN_ULONG *out_r)
47{
48 BN_ULONG q, r;
49
50 /*
51 * Unsigned division of %rdx:%rax by d with quotient being stored in
52 * %rax and remainder in %rdx.
53 */
54 __asm__ volatile ("divq %4"
55 : "=a"(q), "=d"(r)
56 : "d"(h), "a"(l), "rm"(d)
57 : "cc");
58
59 *out_q = q;
60 *out_r = r;
61}
62#endif /* __GNUC__ */
63
39#endif 64#endif
40#endif 65#endif
diff --git a/src/lib/libcrypto/bn/arch/i386/bn_arch.h b/src/lib/libcrypto/bn/arch/i386/bn_arch.h
index 681c2090a7..e2b4957efc 100644
--- a/src/lib/libcrypto/bn/arch/i386/bn_arch.h
+++ b/src/lib/libcrypto/bn/arch/i386/bn_arch.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: bn_arch.h,v 1.6 2023/01/23 12:17:57 jsing Exp $ */ 1/* $OpenBSD: bn_arch.h,v 1.7 2023/01/28 16:33:34 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2023 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2023 Joel Sing <jsing@openbsd.org>
4 * 4 *
@@ -15,6 +15,8 @@
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */ 16 */
17 17
18#include <openssl/bn.h>
19
18#ifndef HEADER_BN_ARCH_H 20#ifndef HEADER_BN_ARCH_H
19#define HEADER_BN_ARCH_H 21#define HEADER_BN_ARCH_H
20 22
@@ -35,5 +37,28 @@
35 37
36#define HAVE_BN_SUB_WORDS 38#define HAVE_BN_SUB_WORDS
37 39
40#if defined(__GNUC__)
41#define HAVE_BN_DIV_REM_WORDS_INLINE
42
43static inline void
44bn_div_rem_words_inline(BN_ULONG h, BN_ULONG l, BN_ULONG d, BN_ULONG *out_q,
45 BN_ULONG *out_r)
46{
47 BN_ULONG q, r;
48
49 /*
50 * Unsigned division of %edx:%eax by d with quotient being stored in
51 * %eax and remainder in %edx.
52 */
53 __asm__ volatile ("divl %4"
54 : "=a"(q), "=d"(r)
55 : "a"(l), "d"(h), "rm"(d)
56 : "cc");
57
58 *out_q = q;
59 *out_r = r;
60}
61#endif /* __GNUC__ */
62
38#endif 63#endif
39#endif 64#endif
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
159static inline
160bn_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) 168void
156# if defined(__GNUC__) && __GNUC__>=2 169bn_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);
diff --git a/src/lib/libcrypto/bn/bn_local.h b/src/lib/libcrypto/bn/bn_local.h
index 74e158d6fd..bcd6fa2732 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.5 2023/01/20 17:26:03 jsing Exp $ */ 1/* $OpenBSD: bn_local.h,v 1.6 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 *
@@ -657,12 +657,16 @@ void bn_correct_top(BIGNUM *a);
657int bn_expand(BIGNUM *a, int bits); 657int bn_expand(BIGNUM *a, int bits);
658int bn_wexpand(BIGNUM *a, int words); 658int bn_wexpand(BIGNUM *a, int words);
659 659
660BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
661 int num);
662BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
663 int num);
660BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w); 664BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);
661BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w); 665BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);
662void bn_sqr_words(BN_ULONG *rp, const BN_ULONG *ap, int num); 666void bn_sqr_words(BN_ULONG *rp, const BN_ULONG *ap, int num);
663BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d); 667BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d);
664BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, int num); 668void bn_div_rem_words(BN_ULONG h, BN_ULONG l, BN_ULONG d, BN_ULONG *out_q,
665BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, int num); 669 BN_ULONG *out_r);
666 670
667int BN_bntest_rand(BIGNUM *rnd, int bits, int top, int bottom); 671int BN_bntest_rand(BIGNUM *rnd, int bits, int top, int bottom);
668int bn_rand_interval(BIGNUM *rnd, const BIGNUM *lower_inc, const BIGNUM *upper_exc); 672int bn_rand_interval(BIGNUM *rnd, const BIGNUM *lower_inc, const BIGNUM *upper_exc);
diff --git a/src/lib/libcrypto/bn/bn_word.c b/src/lib/libcrypto/bn/bn_word.c
index 4663237b05..7077d3ad7a 100644
--- a/src/lib/libcrypto/bn/bn_word.c
+++ b/src/lib/libcrypto/bn/bn_word.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: bn_word.c,v 1.16 2022/11/26 16:08:51 tb Exp $ */ 1/* $OpenBSD: bn_word.c,v 1.17 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 *
@@ -125,8 +125,7 @@ BN_div_word(BIGNUM *a, BN_ULONG w)
125 BN_ULONG l, d; 125 BN_ULONG l, d;
126 126
127 l = a->d[i]; 127 l = a->d[i];
128 d = bn_div_words(ret, l, w); 128 bn_div_rem_words(ret, l, w, &d, &ret);
129 ret = (l - ((d*w)&BN_MASK2))&BN_MASK2;
130 a->d[i] = d; 129 a->d[i] = d;
131 } 130 }
132 if ((a->top > 0) && (a->d[a->top - 1] == 0)) 131 if ((a->top > 0) && (a->d[a->top - 1] == 0))