-/* $OpenBSD: bn_arch.c,v 1.2 2023/01/29 14:00:41 jsing Exp $ */
+/* $OpenBSD: bn_arch.c,v 1.3 2023/02/02 18:39:26 jsing Exp $ */
/*
* Copyright (c) 2023 Joel Sing <jsing@openbsd.org>
*
#include "bn_local.h"
#include "s2n_bignum.h"
+#ifdef HAVE_BN_ADD
+BN_ULONG
+bn_add(BIGNUM *r, int rn, const BIGNUM *a, const BIGNUM *b)
+{
+ return bignum_add(rn, (uint64_t *)r->d, a->top, (uint64_t *)a->d,
+ b->top, (uint64_t *)b->d);
+}
+#endif
+
#ifdef HAVE_BN_ADD_WORDS
BN_ULONG
bn_add_words(BN_ULONG *rd, const BN_ULONG *ad, const BN_ULONG *bd, int n)
}
#endif
+#ifdef HAVE_BN_SUB
+BN_ULONG
+bn_sub(BIGNUM *r, int rn, const BIGNUM *a, const BIGNUM *b)
+{
+ return bignum_sub(rn, (uint64_t *)r->d, a->top, (uint64_t *)a->d,
+ b->top, (uint64_t *)b->d);
+}
+#endif
+
#ifdef HAVE_BN_SUB_WORDS
BN_ULONG
bn_sub_words(BN_ULONG *rd, const BN_ULONG *ad, const BN_ULONG *bd, int n)
-/* $OpenBSD: bn_add.c,v 1.20 2023/01/31 05:16:52 jsing Exp $ */
+/* $OpenBSD: bn_add.c,v 1.21 2023/02/02 18:39:26 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
*/
#include <assert.h>
+#include <limits.h>
#include <stdio.h>
#include <openssl/err.h>
#include "bn_arch.h"
#include "bn_local.h"
+BN_ULONG bn_add(BIGNUM *r, int rn, const BIGNUM *a, const BIGNUM *b);
+BN_ULONG bn_sub(BIGNUM *r, int rn, const BIGNUM *a, const BIGNUM *b);
+
#ifndef HAVE_BN_ADD_WORDS
#ifdef BN_LLONG
BN_ULONG
}
#endif
-int
-BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
+#ifndef HAVE_BN_ADD
+/*
+ * bn_add() computes a + b, storing the result in r (which may be the same as a
+ * or b). The caller must ensure that r has been expanded to max(a->top, b->top)
+ * words. Any carry resulting from the addition is returned.
+ */
+BN_ULONG
+bn_add(BIGNUM *r, int rn, const BIGNUM *a, const BIGNUM *b)
{
- int max, min, dif;
- const BN_ULONG *ap, *bp;
BN_ULONG *rp, carry, t1, t2;
-
+ const BN_ULONG *ap, *bp;
+ int max, min, dif;
if (a->top < b->top) {
const BIGNUM *tmp;
min = b->top;
dif = max - min;
- if (!bn_wexpand(r, max + 1))
- return 0;
-
- r->top = max;
-
ap = a->d;
bp = b->d;
rp = r->d;
*(rp++) = t2;
carry &= (t2 == 0);
}
- *rp = carry;
- r->top += carry;
- r->neg = 0;
- return 1;
+ return carry;
}
+#endif
-int
-BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
+#ifndef HAVE_BN_SUB
+/*
+ * bn_sub() computes a - b, storing the result in r (which may be the same as a
+ * or b). The caller must ensure that the number of words in a is greater than
+ * or equal to the number of words in b and that r has been expanded to
+ * a->top words. Any borrow resulting from the subtraction is returned.
+ */
+BN_ULONG
+bn_sub(BIGNUM *r, int rn, const BIGNUM *a, const BIGNUM *b)
{
- int max, min, dif;
- const BN_ULONG *ap, *bp;
BN_ULONG t1, t2, borrow, *rp;
-
+ const BN_ULONG *ap, *bp;
+ int max, min, dif;
max = a->top;
min = b->top;
dif = max - min;
- if (dif < 0) {
- BNerror(BN_R_ARG2_LT_ARG3);
- return 0;
- }
-
- if (!bn_wexpand(r, max))
- return 0;
-
ap = a->d;
bp = b->d;
rp = r->d;
borrow = bn_sub_words(rp, ap, bp, min);
- if (dif == 0 && borrow > 0) {
- BNerror(BN_R_ARG2_LT_ARG3);
- return 0;
- }
ap += min;
rp += min;
borrow &= (t1 == 0);
}
- while (max > 0 && *--rp == 0)
- max--;
+ return borrow;
+}
+#endif
+
+int
+BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
+{
+ BN_ULONG carry;
+ int rn;
+
+ if ((rn = a->top) < b->top)
+ rn = b->top;
+ if (rn == INT_MAX)
+ return 0;
+ if (!bn_wexpand(r, rn + 1))
+ return 0;
+
+ carry = bn_add(r, rn, a, b);
+ r->d[rn] = carry;
+
+ r->top = rn + (carry & 1);
+ r->neg = 0;
+
+ return 1;
+}
+
+int
+BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
+{
+ BN_ULONG borrow;
+ int rn;
+
+ if (a->top < b->top) {
+ BNerror(BN_R_ARG2_LT_ARG3);
+ return 0;
+ }
+ rn = a->top;
+
+ if (!bn_wexpand(r, rn))
+ return 0;
- r->top = max;
+ borrow = bn_sub(r, rn, a, b);
+ if (borrow > 0) {
+ BNerror(BN_R_ARG2_LT_ARG3);
+ return 0;
+ }
+
+ r->top = rn;
r->neg = 0;
+
bn_correct_top(r);
+
return 1;
}
{
int ret, r_neg;
-
if (a->neg == b->neg) {
r_neg = a->neg;
ret = BN_uadd(r, a, b);
{
int ret, r_neg;
-
if (a->neg != b->neg) {
r_neg = a->neg;
ret = BN_uadd(r, a, b);