summaryrefslogtreecommitdiffstats
path: root/crypto/bn/bn_mod.c
diff options
context:
space:
mode:
authorBodo Möller <bodo@openssl.org>2000-11-26 18:31:32 +0000
committerBodo Möller <bodo@openssl.org>2000-11-26 18:31:32 +0000
commit5acaa49504153ecdd9734ac80aeb9153fde94e48 (patch)
tree3be1e2178b83713e43bdd6f4d0ea55d9f48c0478 /crypto/bn/bn_mod.c
parent535b9b5724e08f27c722982bbf775a862134a22d (diff)
More BN_mod_... functions.
Diffstat (limited to 'crypto/bn/bn_mod.c')
-rw-r--r--crypto/bn/bn_mod.c153
1 files changed, 132 insertions, 21 deletions
diff --git a/crypto/bn/bn_mod.c b/crypto/bn/bn_mod.c
index 72f09c2c2f..92fe11684c 100644
--- a/crypto/bn/bn_mod.c
+++ b/crypto/bn/bn_mod.c
@@ -124,40 +124,62 @@ int BN_mod(BIGNUM *rem, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx)
#endif
-int BN_nnmod(BIGNUM *rem, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx)
+int BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx)
{
/* like BN_mod, but returns non-negative remainder
- * (i.e., 0 <= rem < |d| always holds) */
+ * (i.e., 0 <= r < |d| always holds) */
- if (!(BN_mod(rem,m,d,ctx)))
+ if (!(BN_mod(r,m,d,ctx)))
return 0;
- if (!rem->neg)
+ if (!r->neg)
return 1;
- /* now -|d| < rem < 0, so we have to set rem := rem + |d| */
- return (d->neg ? BN_sub : BN_add)(rem, rem, d);
+ /* now -|d| < r < 0, so we have to set r := r + |d| */
+ return (d->neg ? BN_sub : BN_add)(r, r, d);
}
-int BN_mod_add(BIGNUM *ret, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx)
+int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx)
{
- if (!BN_add(ret, a, b)) return 0;
- return BN_nnmod(ret, ret, m, ctx);
+ if (!BN_add(r, a, b)) return 0;
+ return BN_nnmod(r, r, m, ctx);
}
-int BN_mod_sub(BIGNUM *ret, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx)
+/* BN_mod_add variant that may be used if both a and b are non-negative
+ * and less than m */
+int BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m)
{
- if (!BN_sub(ret, a, b)) return 0;
- return BN_nnmod(ret, ret, m, ctx);
+ if (!BN_add(r, a, b)) return 0;
+ if (BN_cmp(r, m) >= 0)
+ return BN_sub(r, r, m);
+ return 1;
+ }
+
+
+int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx)
+ {
+ if (!BN_sub(r, a, b)) return 0;
+ return BN_nnmod(r, r, m, ctx);
+ }
+
+
+/* BN_mod_sub variant that may be used if both a and b are non-negative
+ * and less than m */
+int BN_mod_sub_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m)
+ {
+ if (!BN_sub(r, a, b)) return 0;
+ if (r->neg)
+ return BN_add(r, r, m);
+ return 1;
}
/* slow but works */
-int BN_mod_mul(BIGNUM *ret, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
+int BN_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
BN_CTX *ctx)
{
BIGNUM *t;
- int r=0;
+ int ret=0;
bn_check_top(a);
bn_check_top(b);
@@ -169,17 +191,106 @@ int BN_mod_mul(BIGNUM *ret, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
{ if (!BN_sqr(t,a,ctx)) goto err; }
else
{ if (!BN_mul(t,a,b,ctx)) goto err; }
- if (!BN_nnmod(ret,t,m,ctx)) goto err;
- r=1;
+ if (!BN_nnmod(r,t,m,ctx)) goto err;
+ ret=1;
err:
BN_CTX_end(ctx);
- return(r);
+ return(ret);
}
-int BN_mod_sqr(BIGNUM *ret, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx)
+int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx)
{
- if (!BN_sqr(ret, a, ctx)) return 0;
- /* ret->neg == 0, thus we don't need BN_nnmod */
- return BN_mod(ret, ret, m, ctx);
+ if (!BN_sqr(r, a, ctx)) return 0;
+ /* r->neg == 0, thus we don't need BN_nnmod */
+ return BN_mod(r, r, m, ctx);
+ }
+
+
+int BN_mod_lshift1(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx)
+ {
+ if (!BN_lshift1(r, a)) return 0;
+ return BN_nnmod(r, r, m, ctx);
+ }
+
+
+/* BN_mod_lshift1 variant that may be used if a is non-negative
+ * and less than m */
+int BN_mod_lshift1_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *m)
+ {
+ if (!BN_lshift1(r, a)) return 0;
+ if (BN_cmp(r, m) >= 0)
+ return BN_sub(r, r, m);
+ return 1;
+ }
+
+
+int BN_mod_lshift(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m, BN_CTX *ctx)
+ {
+ BIGNUM *abs_m = NULL;
+ int ret;
+
+ if (!BN_nnmod(r, a, m, ctx)) return 0;
+
+ if (m->neg)
+ {
+ abs_m = BN_dup(m);
+ if (abs_m == NULL) return 0;
+ abs_m->neg = 0;
+ }
+
+ ret = BN_mod_lshift_quick(r, r, n, (abs_m ? abs_m : m));
+
+ if (abs_m)
+ BN_free(abs_m);
+ return ret;
+ }
+
+
+/* BN_mod_lshift variant that may be used if a is non-negative
+ * and less than m */
+int BN_mod_lshift_quick(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m)
+ {
+ if (r != a)
+ {
+ if (BN_copy(r, a) == NULL) return 0;
+ }
+
+ while (n > 0)
+ {
+ int max_shift;
+
+ /* 0 < r < m */
+ max_shift = BN_num_bits(m) - BN_num_bits(r);
+ /* max_shift >= 0 */
+
+ if (max_shift < 0)
+ {
+ BNerr(BN_F_BN_MOD_LSHIFT_QUICK, BN_R_INPUT_NOT_REDUCED);
+ return 0;
+ }
+
+ if (max_shift > n)
+ max_shift = n;
+
+ if (max_shift)
+ {
+ if (!BN_lshift(r, r, max_shift)) return 0;
+ n -= max_shift;
+ }
+ else
+ {
+ if (!BN_lshift1(r, r)) return 0;
+ --n;
+ }
+
+ /* BN_num_bits(r) <= BN_num_bits(m) */
+
+ if (BN_cmp(r, m) >= 0)
+ {
+ if (!BN_sub(r, r, m)) return 0;
+ }
+ }
+
+ return 1;
}