예제 #1
0
int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
			  BN_MONT_CTX *mont, BN_CTX *ctx)
	{
	BIGNUM *tmp;
	int ret=0;

	BN_CTX_start(ctx);
	tmp = BN_CTX_get(ctx);
	if (tmp == NULL) goto err;

	bn_check_top(tmp);
	if (a == b)
		{
		if (!BN_sqr(tmp,a,ctx)) goto err;
		}
	else
		{
		if (!BN_mul(tmp,a,b,ctx)) goto err;
		}
	/* reduce from aRR to aR */
	if (!BN_from_montgomery(r,tmp,mont,ctx)) goto err;
	bn_check_top(r);
	ret=1;
err:
	BN_CTX_end(ctx);
	return(ret);
	}
예제 #2
0
// mod_montgomery sets |r| to |I| mod |p|. |I| must already be fully reduced
// modulo |p| times |q|. It returns one on success and zero on error.
static int mod_montgomery(BIGNUM *r, const BIGNUM *I, const BIGNUM *p,
                          const BN_MONT_CTX *mont_p, const BIGNUM *q,
                          BN_CTX *ctx) {
  // Reducing in constant-time with Montgomery reduction requires I <= p * R. We
  // have I < p * q, so this follows if q < R. In particular, this always holds
  // if p and q are the same size, which is true for any RSA keys we or anyone
  // sane generates. For other keys, we fall back to |BN_mod|.
  if (!bn_less_than_montgomery_R(q, mont_p)) {
    return BN_mod(r, I, p, ctx);
  }

  if (// Reduce mod p with Montgomery reduction. This computes I * R^-1 mod p.
      !BN_from_montgomery(r, I, mont_p, ctx) ||
      // Multiply by R^2 and do another Montgomery reduction to compute
      // I * R^-1 * R^2 * R^-1 = I mod p.
      !BN_to_montgomery(r, r, mont_p, ctx)) {
    return 0;
  }

  // By precomputing R^3 mod p (normally |BN_MONT_CTX| only uses R^2 mod p) and
  // adjusting the API for |BN_mod_exp_mont_consttime|, we could instead compute
  // I * R mod p here and save a reduction per prime. But this would require
  // changing the RSAZ code and may not be worth it. Note that the RSAZ code
  // uses a different radix, so it uses R' = 2^1044. There we'd actually want
  // R^2 * R', and would futher benefit from a precomputed R'^2. It currently
  // converts |mont_p->RR| to R'^2.
  return 1;
}
예제 #3
0
int ec_GFp_mont_field_decode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
                             BN_CTX *ctx) {
  if (group->field_data1 == NULL) {
    OPENSSL_PUT_ERROR(EC, ec_GFp_mont_field_decode, EC_R_NOT_INITIALIZED);
    return 0;
  }

  return BN_from_montgomery(r, a, group->field_data1, ctx);
}
예제 #4
0
int ec_GFp_mont_field_decode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
	{
	if (group->field_data1 == NULL)
		{
		ECerr(EC_F_EC_GFP_MONT_FIELD_DECODE, EC_R_NOT_INITIALIZED);
		return 0;
		}

	return BN_from_montgomery(r, a, group->field_data1, ctx);
	}
예제 #5
0
int bn_mul_mont_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
                          BN_MONT_CTX *mont, BN_CTX *ctx)
{
    BIGNUM *tmp;
    int ret = 0;
    int num = mont->N.top;

#if defined(OPENSSL_BN_ASM_MONT) && defined(MONT_WORD)
    if (num > 1 && a->top == num && b->top == num) {
        if (bn_wexpand(r, num) == NULL)
            return (0);
        if (bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) {
            r->neg = a->neg ^ b->neg;
            r->top = num;
            r->flags |= BN_FLG_FIXED_TOP;
            return (1);
        }
    }
#endif

    if ((a->top + b->top) > 2 * num)
        return 0;

    BN_CTX_start(ctx);
    tmp = BN_CTX_get(ctx);
    if (tmp == NULL)
        goto err;

    bn_check_top(tmp);
    if (a == b) {
        if (!BN_sqr(tmp, a, ctx))
            goto err;
    } else {
        if (!BN_mul(tmp, a, b, ctx))
            goto err;
    }
    /* reduce from aRR to aR */
#ifdef MONT_WORD
    if (!bn_from_montgomery_word(r, tmp, mont))
        goto err;
#else
    if (!BN_from_montgomery(r, tmp, mont, ctx))
        goto err;
#endif
    ret = 1;
 err:
    BN_CTX_end(ctx);
    return (ret);
}
예제 #6
0
파일: blinding.c 프로젝트: Ms2ger/ring
static int bn_blinding_create_param(BN_BLINDING *b, const RSA *rsa, BN_CTX *ctx) {
  int retry_counter = 32;

  do {
    if (!BN_rand_range(b->A, rsa->n)) {
      OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
      return 0;
    }

    /* `BN_from_montgomery` + `BN_mod_inverse_no_branch` is equivalent to, but
     * more efficient than, `BN_mod_inverse_no_branch` + `BN_to_montgomery`. */

    if (!BN_from_montgomery(b->Ai, b->A, rsa->mont_n, ctx)) {
      return 0;
    }

    assert(BN_get_flags(b->A, BN_FLG_CONSTTIME));
    int no_inverse;
    if (BN_mod_inverse_no_branch(b->Ai, &no_inverse, b->Ai, rsa->n, ctx) ==
        NULL) {
      /* this should almost never happen for good RSA keys */
      if (no_inverse) {
        if (retry_counter-- == 0) {
          OPENSSL_PUT_ERROR(RSA, RSA_R_TOO_MANY_ITERATIONS);
          return 0;
        }
        ERR_clear_error();
      } else {
        OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
        return 0;
      }
    } else {
      break;
    }
  } while (1);

  if (!BN_mod_exp_mont(b->A, b->A, rsa->e, rsa->n, ctx, rsa->mont_n)) {
    OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
    return 0;
  }

  if (!BN_to_montgomery(b->A, b->A, rsa->mont_n, ctx)) {
    OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
    return 0;
  }
  return 1;
}
예제 #7
0
int test_mont(BIO *bp, BN_CTX *ctx)
	{
	BIGNUM a,b,c,d,A,B;
	BIGNUM n;
	int i;
	BN_MONT_CTX *mont;

	BN_init(&a);
	BN_init(&b);
	BN_init(&c);
	BN_init(&d);
	BN_init(&A);
	BN_init(&B);
	BN_init(&n);

	mont=BN_MONT_CTX_new();

	BN_bntest_rand(&a,100,0,0); /**/
	BN_bntest_rand(&b,100,0,0); /**/
	for (i=0; i<num2; i++)
		{
		int bits = (200*(i+1))/num2;

		if (bits == 0)
			continue;
		BN_bntest_rand(&n,bits,0,1);
		BN_MONT_CTX_set(mont,&n,ctx);

		BN_nnmod(&a,&a,&n,ctx);
		BN_nnmod(&b,&b,&n,ctx);

		BN_to_montgomery(&A,&a,mont,ctx);
		BN_to_montgomery(&B,&b,mont,ctx);

		BN_mod_mul_montgomery(&c,&A,&B,mont,ctx);/**/
		BN_from_montgomery(&A,&c,mont,ctx);/**/
		if (bp != NULL)
			{
			if (!results)
				{
#ifdef undef
fprintf(stderr,"%d * %d %% %d\n",
BN_num_bits(&a),
BN_num_bits(&b),
BN_num_bits(mont->N));
#endif
				BN_print(bp,&a);
				BIO_puts(bp," * ");
				BN_print(bp,&b);
				BIO_puts(bp," % ");
				BN_print(bp,&(mont->N));
				BIO_puts(bp," - ");
				}
			BN_print(bp,&A);
			BIO_puts(bp,"\n");
			}
		BN_mod_mul(&d,&a,&b,&n,ctx);
		BN_sub(&d,&d,&A);
		if(!BN_is_zero(&d))
		    {
		    fprintf(stderr,"Montgomery multiplication test failed!\n");
		    return 0;
		    }
		}
	BN_MONT_CTX_free(mont);
	BN_free(&a);
	BN_free(&b);
	BN_free(&c);
	BN_free(&d);
	BN_free(&A);
	BN_free(&B);
	BN_free(&n);
	return(1);
	}
예제 #8
0
static int ec_GFp_mont_point_get_affine_coordinates(const EC_GROUP *group,
                                                    const EC_POINT *point,
                                                    BIGNUM *x, BIGNUM *y,
                                                    BN_CTX *ctx) {
  if (EC_POINT_is_at_infinity(group, point)) {
    OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY);
    return 0;
  }

  BN_CTX *new_ctx = NULL;
  if (ctx == NULL) {
    ctx = new_ctx = BN_CTX_new();
    if (ctx == NULL) {
      return 0;
    }
  }

  int ret = 0;

  BN_CTX_start(ctx);

  if (BN_cmp(&point->Z, &group->one) == 0) {
    /* |point| is already affine. */
    if (x != NULL && !BN_from_montgomery(x, &point->X, &group->mont, ctx)) {
      goto err;
    }
    if (y != NULL && !BN_from_montgomery(y, &point->Y, &group->mont, ctx)) {
      goto err;
    }
  } else {
    /* transform  (X, Y, Z)  into  (x, y) := (X/Z^2, Y/Z^3) */

    BIGNUM *Z_1 = BN_CTX_get(ctx);
    BIGNUM *Z_2 = BN_CTX_get(ctx);
    BIGNUM *Z_3 = BN_CTX_get(ctx);
    if (Z_1 == NULL ||
        Z_2 == NULL ||
        Z_3 == NULL) {
      goto err;
    }

    /* The straightforward way to calculate the inverse of a Montgomery-encoded
     * value where the result is Montgomery-encoded is:
     *
     *    |BN_from_montgomery| + |BN_mod_inverse| + |BN_to_montgomery|.
     *
     * This is equivalent, but more efficient, because |BN_from_montgomery|
     * is more efficient (at least in theory) than |BN_to_montgomery|, since it
     * doesn't have to do the multiplication before the reduction. */
    if (!BN_from_montgomery(Z_1, &point->Z, &group->mont, ctx) ||
        !BN_from_montgomery(Z_1, Z_1, &group->mont, ctx) ||
        !BN_mod_inverse(Z_1, Z_1, &group->field, ctx)) {
      goto err;
    }

    if (!BN_mod_mul_montgomery(Z_2, Z_1, Z_1, &group->mont, ctx)) {
      goto err;
    }

    /* Instead of using |BN_from_montgomery| to convert the |x| coordinate
     * and then calling |BN_from_montgomery| again to convert the |y|
     * coordinate below, convert the common factor |Z_2| once now, saving one
     * reduction. */
    if (!BN_from_montgomery(Z_2, Z_2, &group->mont, ctx)) {
      goto err;
    }

    if (x != NULL) {
      if (!BN_mod_mul_montgomery(x, &point->X, Z_2, &group->mont, ctx)) {
        goto err;
      }
    }

    if (y != NULL) {
      if (!BN_mod_mul_montgomery(Z_3, Z_2, Z_1, &group->mont, ctx) ||
          !BN_mod_mul_montgomery(y, &point->Y, Z_3, &group->mont, ctx)) {
        goto err;
      }
    }
  }

  ret = 1;

err:
  BN_CTX_end(ctx);
  BN_CTX_free(new_ctx);
  return ret;
}
예제 #9
0
int ec_GFp_mont_field_decode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
                             BN_CTX *ctx) {
  return BN_from_montgomery(r, a, &group->mont, ctx);
}
예제 #10
0
int BN_mod_exp2_mont(BIGNUM *rr, BIGNUM *a1, BIGNUM *p1, BIGNUM *a2,
	     BIGNUM *p2, BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont)
	{
	int i,j,k,bits,bits1,bits2,ret=0,wstart,wend,window,xvalue,yvalue;
	int start=1,ts=0,x,y;
	BIGNUM *d,*aa1,*aa2,*r;
	BIGNUM val[EXP2_TABLE_SIZE][EXP2_TABLE_SIZE];
	BN_MONT_CTX *mont=NULL;

	bn_check_top(a1);
	bn_check_top(p1);
	bn_check_top(a2);
	bn_check_top(p2);
	bn_check_top(m);

	if (!(m->d[0] & 1))
		{
		BNerr(BN_F_BN_MOD_EXP_MONT,BN_R_CALLED_WITH_EVEN_MODULUS);
		return(0);
		}
	bits1=BN_num_bits(p1);
	bits2=BN_num_bits(p2);
	if ((bits1 == 0) && (bits2 == 0))
		{
		BN_one(rr);
		return(1);
		}

	BN_CTX_start(ctx);
	d = BN_CTX_get(ctx);
	r = BN_CTX_get(ctx);
	if (d == NULL || r == NULL) goto err;

	bits=(bits1 > bits2)?bits1:bits2;

	/* If this is not done, things will break in the montgomery
	 * part */

	if (in_mont != NULL)
		mont=in_mont;
	else
		{
		if ((mont=BN_MONT_CTX_new()) == NULL) goto err;
		if (!BN_MONT_CTX_set(mont,m,ctx)) goto err;
		}

	BN_init(&(val[0][0]));
	BN_init(&(val[1][1]));
	BN_init(&(val[0][1]));
	BN_init(&(val[1][0]));
	ts=1;
	if (BN_ucmp(a1,m) >= 0)
		{
		BN_mod(&(val[1][0]),a1,m,ctx);
		aa1= &(val[1][0]);
		}
	else
		aa1=a1;
	if (BN_ucmp(a2,m) >= 0)
		{
		BN_mod(&(val[0][1]),a2,m,ctx);
		aa2= &(val[0][1]);
		}
	else
		aa2=a2;
	if (!BN_to_montgomery(&(val[1][0]),aa1,mont,ctx)) goto err;
	if (!BN_to_montgomery(&(val[0][1]),aa2,mont,ctx)) goto err;
	if (!BN_mod_mul_montgomery(&(val[1][1]),
		&(val[1][0]),&(val[0][1]),mont,ctx))
		goto err;

#if 0
	if (bits <= 20) /* This is probably 3 or 0x10001, so just do singles */
		window=1;
	else if (bits > 250)
		window=5;	/* max size of window */
	else if (bits >= 120)
		window=4;
	else
		window=3;
#else
	window=EXP2_TABLE_BITS;
#endif

	k=1<<window;
	for (x=0; x<k; x++)
		{
		if (x >= 2)
			{
			BN_init(&(val[x][0]));
			BN_init(&(val[x][1]));
			if (!BN_mod_mul_montgomery(&(val[x][0]),
				&(val[1][0]),&(val[x-1][0]),mont,ctx)) goto err;
			if (!BN_mod_mul_montgomery(&(val[x][1]),
				&(val[1][0]),&(val[x-1][1]),mont,ctx)) goto err;
			}
		for (y=2; y<k; y++)
			{
			BN_init(&(val[x][y]));
			if (!BN_mod_mul_montgomery(&(val[x][y]),
				&(val[x][y-1]),&(val[0][1]),mont,ctx))
				goto err;
			}
		}
	ts=k;

	start=1;	/* This is used to avoid multiplication etc
			 * when there is only the value '1' in the
			 * buffer. */
	xvalue=0;	/* The 'x value' of the window */
	yvalue=0;	/* The 'y value' of the window */
	wstart=bits-1;	/* The top bit of the window */
	wend=0;		/* The bottom bit of the window */

        if (!BN_to_montgomery(r,BN_value_one(),mont,ctx)) goto err;
	for (;;)
		{
		xvalue=BN_is_bit_set(p1,wstart);
		yvalue=BN_is_bit_set(p2,wstart);
		if (!(xvalue || yvalue))
			{
			if (!start)
				{
				if (!BN_mod_mul_montgomery(r,r,r,mont,ctx))
					goto err;
				}
			wstart--;
			if (wstart < 0) break;
			continue;
			}
		/* We now have wstart on a 'set' bit, we now need to work out
		 * how bit a window to do.  To do this we need to scan
		 * forward until the last set bit before the end of the
		 * window */
		j=wstart;
		/* xvalue=BN_is_bit_set(p1,wstart); already set */
		/* yvalue=BN_is_bit_set(p1,wstart); already set */
		wend=0;
		for (i=1; i<window; i++)
			{
			if (wstart-i < 0) break;
			xvalue+=xvalue;
			xvalue|=BN_is_bit_set(p1,wstart-i);
			yvalue+=yvalue;
			yvalue|=BN_is_bit_set(p2,wstart-i);
			}

		/* i is the size of the current window */
		/* add the 'bytes above' */
		if (!start)
			for (j=0; j<i; j++)
				{
				if (!BN_mod_mul_montgomery(r,r,r,mont,ctx))
					goto err;
				}
		
		/* wvalue will be an odd number < 2^window */
		if (xvalue || yvalue)
			{
			if (!BN_mod_mul_montgomery(r,r,&(val[xvalue][yvalue]),
				mont,ctx)) goto err;
			}

		/* move the 'window' down further */
		wstart-=i;
		start=0;
		if (wstart < 0) break;
		}
	BN_from_montgomery(rr,r,mont,ctx);
	ret=1;
err:
	if ((in_mont == NULL) && (mont != NULL)) BN_MONT_CTX_free(mont);
	BN_CTX_end(ctx);
	for (i=0; i<ts; i++)
		{
		for (j=0; j<ts; j++)
			{
			BN_clear_free(&(val[i][j]));
			}
		}
	return(ret);
	}