Commit 5acaa495 authored by Bodo Möller's avatar Bodo Möller
Browse files

More BN_mod_... functions.

parent 535b9b57
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -20,13 +20,26 @@
     (except for exponentation, which stays in crypto/bn/bn_exp.c,
     and BN_mod_mul_reciprocal, which stays in crypto/bn/bn_recp.c)
     and add new functions:

          BN_nnmod
          BN_mod_sqr
          BN_mod_add
          BN_mod_add_quick
          BN_mod_sub
          BN_mod_sub_quick
          BN_mod_lshift1
          BN_mod_lshift1_quick
          BN_mod_lshift
          BN_mod_lshift_quick

     These functions always generate non-negative results.

     BN_nnmod otherwise is like BN_mod (if BN_mod computes a remainder  r
     such that  |m| < r < 0,  BN_nnmod will output  rem + |m|  instead).

     BN_mod_XXX_quick(r, a, [b,] m) generates the same result as
     BN_mod_XXX(r, a, [b,] m, ctx), but requires that  a  [and  b]
     be reduced modulo  m.
     [Lenka Fibikova <fibikova@exp-math.uni-essen.de>, Bodo Moeller]

  *) Remove a few calls to bn_wexpand() in BN_sqr() (the one in there
+18 −2
Original line number Diff line number Diff line
@@ -341,12 +341,22 @@ int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
int	BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
int	BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
int	BN_sqr(BIGNUM *r, const BIGNUM *a,BN_CTX *ctx);

int	BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d,
	BN_CTX *ctx);
#define BN_mod(rem,m,d,ctx) BN_div(NULL,(rem),(m),(d),(ctx))
int	BN_nnmod(BIGNUM *rem, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx);
int	BN_mod_mul(BIGNUM *ret, const BIGNUM *a, const BIGNUM *b,
int	BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx);
int	BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx);
int	BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m);
int	BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx);
int	BN_mod_sub_quick(BIGNUM *r, 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);
int	BN_mod_lshift1(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);
int	BN_mod_lshift1_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *m);
int	BN_mod_lshift(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m, BN_CTX *ctx);
int	BN_mod_lshift_quick(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m);

BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w);
BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w);
int	BN_mul_word(BIGNUM *a, BN_ULONG w);
@@ -354,12 +364,14 @@ int BN_add_word(BIGNUM *a, BN_ULONG w);
int	BN_sub_word(BIGNUM *a, BN_ULONG w);
int	BN_set_word(BIGNUM *a, BN_ULONG w);
BN_ULONG BN_get_word(const BIGNUM *a);

int	BN_cmp(const BIGNUM *a, const BIGNUM *b);
void	BN_free(BIGNUM *a);
int	BN_is_bit_set(const BIGNUM *a, int n);
int	BN_lshift(BIGNUM *r, const BIGNUM *a, int n);
int	BN_lshift1(BIGNUM *r, const BIGNUM *a);
int	BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,BN_CTX *ctx);

int	BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
	const BIGNUM *m,BN_CTX *ctx);
int	BN_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
@@ -371,6 +383,7 @@ int BN_mod_exp2_mont(BIGNUM *r, const BIGNUM *a1, const BIGNUM *p1,
	BN_CTX *ctx,BN_MONT_CTX *m_ctx);
int	BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
	const BIGNUM *m,BN_CTX *ctx);

int	BN_mask_bits(BIGNUM *a,int n);
#ifndef NO_FP_API
int	BN_print_fp(FILE *fp, const BIGNUM *a);
@@ -495,6 +508,7 @@ void bn_dump1(FILE *o, const char *a, const BN_ULONG *b,int n);
#define BN_F_BN_MOD_EXP_MONT				 109
#define BN_F_BN_MOD_EXP_MONT_WORD			 117
#define BN_F_BN_MOD_INVERSE				 110
#define BN_F_BN_MOD_LSHIFT_QUICK			 119
#define BN_F_BN_MOD_MUL_RECIPROCAL			 111
#define BN_F_BN_MPI2BN					 112
#define BN_F_BN_NEW					 113
@@ -508,6 +522,7 @@ void bn_dump1(FILE *o, const char *a, const BN_ULONG *b,int n);
#define BN_R_DIV_BY_ZERO				 103
#define BN_R_ENCODING_ERROR				 104
#define BN_R_EXPAND_ON_STATIC_BIGNUM_DATA		 105
#define BN_R_INPUT_NOT_REDUCED				 110
#define BN_R_INVALID_LENGTH				 106
#define BN_R_NOT_INITIALIZED				 107
#define BN_R_NO_INVERSE					 108
@@ -517,3 +532,4 @@ void bn_dump1(FILE *o, const char *a, const BN_ULONG *b,int n);
}
#endif
#endif
+2 −0
Original line number Diff line number Diff line
@@ -80,6 +80,7 @@ static ERR_STRING_DATA BN_str_functs[]=
{ERR_PACK(0,BN_F_BN_MOD_EXP_MONT,0),	"BN_mod_exp_mont"},
{ERR_PACK(0,BN_F_BN_MOD_EXP_MONT_WORD,0),	"BN_mod_exp_mont_word"},
{ERR_PACK(0,BN_F_BN_MOD_INVERSE,0),	"BN_mod_inverse"},
{ERR_PACK(0,BN_F_BN_MOD_LSHIFT_QUICK,0),	"BN_mod_lshift_quick"},
{ERR_PACK(0,BN_F_BN_MOD_MUL_RECIPROCAL,0),	"BN_mod_mul_reciprocal"},
{ERR_PACK(0,BN_F_BN_MPI2BN,0),	"BN_mpi2bn"},
{ERR_PACK(0,BN_F_BN_NEW,0),	"BN_new"},
@@ -96,6 +97,7 @@ static ERR_STRING_DATA BN_str_reasons[]=
{BN_R_DIV_BY_ZERO                        ,"div by zero"},
{BN_R_ENCODING_ERROR                     ,"encoding error"},
{BN_R_EXPAND_ON_STATIC_BIGNUM_DATA       ,"expand on static bignum data"},
{BN_R_INPUT_NOT_REDUCED                  ,"input not reduced"},
{BN_R_INVALID_LENGTH                     ,"invalid length"},
{BN_R_NOT_INITIALIZED                    ,"not initialized"},
{BN_R_NO_INVERSE                         ,"no inverse"},
+132 −21
Original line number Diff line number Diff line
@@ -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 *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *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) */

int BN_mod_sqr(BIGNUM *ret, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx)
		if (BN_cmp(r, m) >= 0) 
			{
	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_sub(r, r, m)) return 0;
			}
		}
	
	return 1;
	}
+22 −22
Original line number Diff line number Diff line
@@ -13,7 +13,7 @@
#define HEADER_BN_MODFS_H


#include "bn.h"
#include <openssl/bn.h>


int BN_legendre(BIGNUM *a, BIGNUM *p, BN_CTX *ctx);
Loading