summaryrefslogtreecommitdiff
path: root/lib/libcrypto/bn
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libcrypto/bn')
-rw-r--r--lib/libcrypto/bn/arch/amd64/bn_arch.h27
-rw-r--r--lib/libcrypto/bn/arch/i386/bn_arch.h27
-rw-r--r--lib/libcrypto/bn/bn_div.c85
-rw-r--r--lib/libcrypto/bn/bn_local.h10
-rw-r--r--lib/libcrypto/bn/bn_word.c5
5 files changed, 87 insertions, 67 deletions
diff --git a/lib/libcrypto/bn/arch/amd64/bn_arch.h b/lib/libcrypto/bn/arch/amd64/bn_arch.h
index 065f6b1c3b4..6b7eaf5eee7 100644
--- a/lib/libcrypto/bn/arch/amd64/bn_arch.h
+++ b/lib/libcrypto/bn/arch/amd64/bn_arch.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bn_arch.h,v 1.7 2023/01/23 12:17:57 jsing Exp $ */
+/* $OpenBSD: bn_arch.h,v 1.8 2023/01/28 16:33:34 jsing Exp $ */
/*
* Copyright (c) 2023 Joel Sing <jsing@openbsd.org>
*
@@ -15,6 +15,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <openssl/bn.h>
+
#ifndef HEADER_BN_ARCH_H
#define HEADER_BN_ARCH_H
@@ -36,5 +38,28 @@
#define HAVE_BN_SUB_WORDS
+#if defined(__GNUC__)
+#define HAVE_BN_DIV_REM_WORDS_INLINE
+
+static inline void
+bn_div_rem_words_inline(BN_ULONG h, BN_ULONG l, BN_ULONG d, BN_ULONG *out_q,
+ BN_ULONG *out_r)
+{
+ BN_ULONG q, r;
+
+ /*
+ * Unsigned division of %rdx:%rax by d with quotient being stored in
+ * %rax and remainder in %rdx.
+ */
+ __asm__ volatile ("divq %4"
+ : "=a"(q), "=d"(r)
+ : "d"(h), "a"(l), "rm"(d)
+ : "cc");
+
+ *out_q = q;
+ *out_r = r;
+}
+#endif /* __GNUC__ */
+
#endif
#endif
diff --git a/lib/libcrypto/bn/arch/i386/bn_arch.h b/lib/libcrypto/bn/arch/i386/bn_arch.h
index 681c2090a70..e2b4957efc2 100644
--- a/lib/libcrypto/bn/arch/i386/bn_arch.h
+++ b/lib/libcrypto/bn/arch/i386/bn_arch.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bn_arch.h,v 1.6 2023/01/23 12:17:57 jsing Exp $ */
+/* $OpenBSD: bn_arch.h,v 1.7 2023/01/28 16:33:34 jsing Exp $ */
/*
* Copyright (c) 2023 Joel Sing <jsing@openbsd.org>
*
@@ -15,6 +15,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <openssl/bn.h>
+
#ifndef HEADER_BN_ARCH_H
#define HEADER_BN_ARCH_H
@@ -35,5 +37,28 @@
#define HAVE_BN_SUB_WORDS
+#if defined(__GNUC__)
+#define HAVE_BN_DIV_REM_WORDS_INLINE
+
+static inline void
+bn_div_rem_words_inline(BN_ULONG h, BN_ULONG l, BN_ULONG d, BN_ULONG *out_q,
+ BN_ULONG *out_r)
+{
+ BN_ULONG q, r;
+
+ /*
+ * Unsigned division of %edx:%eax by d with quotient being stored in
+ * %eax and remainder in %edx.
+ */
+ __asm__ volatile ("divl %4"
+ : "=a"(q), "=d"(r)
+ : "a"(l), "d"(h), "rm"(d)
+ : "cc");
+
+ *out_q = q;
+ *out_r = r;
+}
+#endif /* __GNUC__ */
+
#endif
#endif
diff --git a/lib/libcrypto/bn/bn_div.c b/lib/libcrypto/bn/bn_div.c
index 8ec2e01831b..e60fb84062c 100644
--- a/lib/libcrypto/bn/bn_div.c
+++ b/lib/libcrypto/bn/bn_div.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bn_div.c,v 1.33 2023/01/23 12:02:48 jsing Exp $ */
+/* $OpenBSD: bn_div.c,v 1.34 2023/01/28 16:33:34 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -150,49 +150,30 @@ bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d)
#endif /* !defined(BN_LLONG) && defined(BN_DIV2W) */
#endif
-#ifndef HAVE_BN_DIV_3_WORDS
+/*
+ * Divide 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.
+ */
+#ifndef HAVE_BN_DIV_REM_WORDS
+#ifndef HAVE_BN_DIV_REM_WORDS_INLINE
+static inline
+bn_div_rem_words_inline(BN_ULONG h, BN_ULONG l, BN_ULONG d, BN_ULONG *out_q,
+ BN_ULONG *out_r)
+{
+ *q = bn_div_words(h, l, d);
+ *r = (l - q * d) & BN_MASK2;
+}
+#endif
-#if !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
-# if defined(__GNUC__) && __GNUC__>=2
-# if defined(__i386) || defined (__i386__)
- /*
- * There were two reasons for implementing this template:
- * - GNU C generates a call to a function (__udivdi3 to be exact)
- * in reply to ((((BN_ULLONG)n0)<<BN_BITS2)|n1)/d0 (I fail to
- * understand why...);
- * - divl doesn't only calculate quotient, but also leaves
- * remainder in %edx which we can definitely use here:-)
- *
- * <appro@fy.chalmers.se>
- */
-#undef bn_div_words
-# define bn_div_words(n0,n1,d0) \
- ({ asm volatile ( \
- "divl %4" \
- : "=a"(q), "=d"(rem) \
- : "a"(n1), "d"(n0), "g"(d0) \
- : "cc"); \
- q; \
- })
-# define REMAINDER_IS_ALREADY_CALCULATED
-# elif defined(__x86_64)
- /*
- * Same story here, but it's 128-bit by 64-bit division. Wow!
- * <appro@fy.chalmers.se>
- */
-# undef bn_div_words
-# define bn_div_words(n0,n1,d0) \
- ({ asm volatile ( \
- "divq %4" \
- : "=a"(q), "=d"(rem) \
- : "a"(n1), "d"(n0), "g"(d0) \
- : "cc"); \
- q; \
- })
-# define REMAINDER_IS_ALREADY_CALCULATED
-# endif /* __<cpu> */
-# endif /* __GNUC__ */
-#endif /* OPENSSL_NO_ASM */
+void
+bn_div_rem_words(BN_ULONG h, BN_ULONG l, BN_ULONG d, BN_ULONG *out_q,
+ BN_ULONG *out_r)
+{
+ bn_div_rem_words_inline(h, l, d, out_q, out_r);
+}
+#endif
+
+#ifndef HAVE_BN_DIV_3_WORDS
/*
* 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)
#ifdef BN_LLONG
BN_ULLONG t2;
-#if defined(BN_DIV2W) && !defined(bn_div_words)
- q = (BN_ULONG)((((BN_ULLONG)n0 << BN_BITS2) | n1) / d0);
-#else
- q = bn_div_words(n0, n1, d0);
-#endif
+ bn_div_rem_words(n0, n1, d0, &q, &rem);
-#ifndef REMAINDER_IS_ALREADY_CALCULATED
- /*
- * rem doesn't have to be BN_ULLONG. The least we
- * know it's less that d0, isn't it?
- */
- rem = (n1 - q * d0) & BN_MASK2;
-#endif
t2 = (BN_ULLONG)d1 * q;
for (;;) {
@@ -245,10 +215,7 @@ bn_div_3_words(const BN_ULONG *m, BN_ULONG d1, BN_ULONG d0)
#else /* !BN_LLONG */
BN_ULONG t2l, t2h;
- q = bn_div_words(n0, n1, d0);
-#ifndef REMAINDER_IS_ALREADY_CALCULATED
- rem = (n1 - q * d0) & BN_MASK2;
-#endif
+ bn_div_rem_words(n0, n1, d0, &q, &rem);
#if defined(BN_UMULT_LOHI)
BN_UMULT_LOHI(t2l, t2h, d1, q);
diff --git a/lib/libcrypto/bn/bn_local.h b/lib/libcrypto/bn/bn_local.h
index 74e158d6fd7..bcd6fa27329 100644
--- a/lib/libcrypto/bn/bn_local.h
+++ b/lib/libcrypto/bn/bn_local.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bn_local.h,v 1.5 2023/01/20 17:26:03 jsing Exp $ */
+/* $OpenBSD: bn_local.h,v 1.6 2023/01/28 16:33:34 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -657,12 +657,16 @@ void bn_correct_top(BIGNUM *a);
int bn_expand(BIGNUM *a, int bits);
int bn_wexpand(BIGNUM *a, int words);
+BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
+ int num);
+BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
+ int num);
BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);
BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);
void bn_sqr_words(BN_ULONG *rp, const BN_ULONG *ap, int num);
BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d);
-BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, int num);
-BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, int num);
+void bn_div_rem_words(BN_ULONG h, BN_ULONG l, BN_ULONG d, BN_ULONG *out_q,
+ BN_ULONG *out_r);
int BN_bntest_rand(BIGNUM *rnd, int bits, int top, int bottom);
int bn_rand_interval(BIGNUM *rnd, const BIGNUM *lower_inc, const BIGNUM *upper_exc);
diff --git a/lib/libcrypto/bn/bn_word.c b/lib/libcrypto/bn/bn_word.c
index 4663237b055..7077d3ad7af 100644
--- a/lib/libcrypto/bn/bn_word.c
+++ b/lib/libcrypto/bn/bn_word.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bn_word.c,v 1.16 2022/11/26 16:08:51 tb Exp $ */
+/* $OpenBSD: bn_word.c,v 1.17 2023/01/28 16:33:34 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -125,8 +125,7 @@ BN_div_word(BIGNUM *a, BN_ULONG w)
BN_ULONG l, d;
l = a->d[i];
- d = bn_div_words(ret, l, w);
- ret = (l - ((d*w)&BN_MASK2))&BN_MASK2;
+ bn_div_rem_words(ret, l, w, &d, &ret);
a->d[i] = d;
}
if ((a->top > 0) && (a->d[a->top - 1] == 0))