extern "C" void Java_java_math_NativeBN_BN_1mul(JNIEnv* env, jclass, jlong r, jlong a, jlong b) {
  if (!threeValidHandles(env, r, a, b)) return;
  Unique_BN_CTX ctx(BN_CTX_new());
  BN_mul(toBigNum(r), toBigNum(a), toBigNum(b), ctx.get());
  throwExceptionIfNecessary(env);
}
RSA *RSA_generate_key(int bits, unsigned long e_value,
	     void (*callback)(int,int,void *), void *cb_arg)
	{
	RSA *rsa=NULL;
	BIGNUM *r0=NULL,*r1=NULL,*r2=NULL,*r3=NULL,*tmp;
	int bitsp,bitsq,ok= -1,n=0;
	unsigned i;
	BN_CTX *ctx=NULL,*ctx2=NULL;

	ctx=BN_CTX_new();
	if (ctx == NULL) goto err;
	ctx2=BN_CTX_new();
	if (ctx2 == NULL) goto err;
	BN_CTX_start(ctx);
	r0 = BN_CTX_get(ctx);
	r1 = BN_CTX_get(ctx);
	r2 = BN_CTX_get(ctx);
	r3 = BN_CTX_get(ctx);
	if (r3 == NULL) goto err;

	bitsp=(bits+1)/2;
	bitsq=bits-bitsp;
	rsa=RSA_new();
	if (rsa == NULL) goto err;

	/* set e */ 
	rsa->e=BN_new();
	if (rsa->e == NULL) goto err;

#if 1
	/* The problem is when building with 8, 16, or 32 BN_ULONG,
	 * unsigned long can be larger */
	for (i=0; i<sizeof(unsigned long)*8; i++)
		{
		if (e_value & (((unsigned long)1)<<i))
			BN_set_bit(rsa->e,i);
		}
#else
	if (!BN_set_word(rsa->e,e_value)) goto err;
#endif

	/* generate p and q */
	for (;;)
		{
		rsa->p=BN_generate_prime(NULL,bitsp,0,NULL,NULL,callback,cb_arg);
		if (rsa->p == NULL) goto err;
		if (!BN_sub(r2,rsa->p,BN_value_one())) goto err;
		if (!BN_gcd(r1,r2,rsa->e,ctx)) goto err;
		if (BN_is_one(r1)) break;
		if (callback != NULL) callback(2,n++,cb_arg);
		BN_free(rsa->p);
		}
	if (callback != NULL) callback(3,0,cb_arg);
	for (;;)
		{
		rsa->q=BN_generate_prime(NULL,bitsq,0,NULL,NULL,callback,cb_arg);
		if (rsa->q == NULL) goto err;
		if (!BN_sub(r2,rsa->q,BN_value_one())) goto err;
		if (!BN_gcd(r1,r2,rsa->e,ctx)) goto err;
		if (BN_is_one(r1) && (BN_cmp(rsa->p,rsa->q) != 0))
			break;
		if (callback != NULL) callback(2,n++,cb_arg);
		BN_free(rsa->q);
		}
	if (callback != NULL) callback(3,1,cb_arg);
	if (BN_cmp(rsa->p,rsa->q) < 0)
		{
		tmp=rsa->p;
		rsa->p=rsa->q;
		rsa->q=tmp;
		}

	/* calculate n */
	rsa->n=BN_new();
	if (rsa->n == NULL) goto err;
	if (!BN_mul(rsa->n,rsa->p,rsa->q,ctx)) goto err;

	/* calculate d */
	if (!BN_sub(r1,rsa->p,BN_value_one())) goto err;	/* p-1 */
	if (!BN_sub(r2,rsa->q,BN_value_one())) goto err;	/* q-1 */
	if (!BN_mul(r0,r1,r2,ctx)) goto err;	/* (p-1)(q-1) */

/* should not be needed, since gcd(p-1,e) == 1 and gcd(q-1,e) == 1 */
/*	for (;;)
		{
		if (!BN_gcd(r3,r0,rsa->e,ctx)) goto err;
		if (BN_is_one(r3)) break;

		if (1)
			{
			if (!BN_add_word(rsa->e,2L)) goto err;
			continue;
			}
		RSAerr(RSA_F_RSA_GENERATE_KEY,RSA_R_BAD_E_VALUE);
		goto err;
		}
*/
	rsa->d=BN_mod_inverse(NULL,rsa->e,r0,ctx2);	/* d */
	if (rsa->d == NULL) goto err;

	/* calculate d mod (p-1) */
	rsa->dmp1=BN_new();
	if (rsa->dmp1 == NULL) goto err;
	if (!BN_mod(rsa->dmp1,rsa->d,r1,ctx)) goto err;

	/* calculate d mod (q-1) */
	rsa->dmq1=BN_new();
	if (rsa->dmq1 == NULL) goto err;
	if (!BN_mod(rsa->dmq1,rsa->d,r2,ctx)) goto err;

	/* calculate inverse of q mod p */
	rsa->iqmp=BN_mod_inverse(NULL,rsa->q,rsa->p,ctx2);
	if (rsa->iqmp == NULL) goto err;

	ok=1;
err:
	if (ok == -1)
		{
		RSAerr(RSA_F_RSA_GENERATE_KEY,ERR_LIB_BN);
		ok=0;
		}
	BN_CTX_end(ctx);
	BN_CTX_free(ctx);
	BN_CTX_free(ctx2);
	
	if (!ok)
		{
		if (rsa != NULL) RSA_free(rsa);
		return(NULL);
		}
	else
		return(rsa);
	}
Example #3
0
/**
 * public static native int BN_mul(int, int, int, int)
 */
static jboolean NativeBN_BN_mul(JNIEnv* env, jclass cls, BIGNUM* r, BIGNUM* a, BIGNUM* b, BN_CTX* ctx) {
    if (!threeValidHandles(env, r, a, b)) return FALSE;
    return BN_mul(r, a, b, ctx);
}
Example #4
0
int RSA_recover_crt_params(RSA *rsa) {
  BN_CTX *ctx;
  BIGNUM *totient, *rem, *multiple, *p_plus_q, *p_minus_q;
  int ok = 0;

  if (rsa->n == NULL || rsa->e == NULL || rsa->d == NULL) {
    OPENSSL_PUT_ERROR(RSA, RSA_R_EMPTY_PUBLIC_KEY);
    return 0;
  }

  if (rsa->p || rsa->q || rsa->dmp1 || rsa->dmq1 || rsa->iqmp) {
    OPENSSL_PUT_ERROR(RSA, RSA_R_CRT_PARAMS_ALREADY_GIVEN);
    return 0;
  }

  if (rsa->additional_primes != NULL) {
    OPENSSL_PUT_ERROR(RSA, RSA_R_CANNOT_RECOVER_MULTI_PRIME_KEY);
    return 0;
  }

  /* This uses the algorithm from section 9B of the RSA paper:
   * http://people.csail.mit.edu/rivest/Rsapaper.pdf */

  ctx = BN_CTX_new();
  if (ctx == NULL) {
    OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
    return 0;
  }

  BN_CTX_start(ctx);
  totient = BN_CTX_get(ctx);
  rem = BN_CTX_get(ctx);
  multiple = BN_CTX_get(ctx);
  p_plus_q = BN_CTX_get(ctx);
  p_minus_q = BN_CTX_get(ctx);

  if (totient == NULL || rem == NULL || multiple == NULL || p_plus_q == NULL ||
      p_minus_q == NULL) {
    OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
    goto err;
  }

  /* ed-1 is a small multiple of φ(n). */
  if (!BN_mul(totient, rsa->e, rsa->d, ctx) ||
      !BN_sub_word(totient, 1) ||
      /* φ(n) =
       * pq - p - q + 1 =
       * n - (p + q) + 1
       *
       * Thus n is a reasonable estimate for φ(n). So, (ed-1)/n will be very
       * close. But, when we calculate the quotient, we'll be truncating it
       * because we discard the remainder. Thus (ed-1)/multiple will be >= n,
       * which the totient cannot be. So we add one to the estimate.
       *
       * Consider ed-1 as:
       *
       * multiple * (n - (p+q) + 1) =
       * multiple*n - multiple*(p+q) + multiple
       *
       * When we divide by n, the first term becomes multiple and, since
       * multiple and p+q is tiny compared to n, the second and third terms can
       * be ignored. Thus I claim that subtracting one from the estimate is
       * sufficient. */
      !BN_div(multiple, NULL, totient, rsa->n, ctx) ||
      !BN_add_word(multiple, 1) ||
      !BN_div(totient, rem, totient, multiple, ctx)) {
    OPENSSL_PUT_ERROR(RSA, ERR_R_BN_LIB);
    goto err;
  }

  if (!BN_is_zero(rem)) {
    OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_RSA_PARAMETERS);
    goto err;
  }

  rsa->p = BN_new();
  rsa->q = BN_new();
  rsa->dmp1 = BN_new();
  rsa->dmq1 = BN_new();
  rsa->iqmp = BN_new();
  if (rsa->p == NULL || rsa->q == NULL || rsa->dmp1 == NULL || rsa->dmq1 ==
      NULL || rsa->iqmp == NULL) {
    OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
    goto err;
  }

  /* φ(n) = n - (p + q) + 1 =>
   * n - totient + 1 = p + q */
  if (!BN_sub(p_plus_q, rsa->n, totient) ||
      !BN_add_word(p_plus_q, 1) ||
      /* p - q = sqrt((p+q)^2 - 4n) */
      !BN_sqr(rem, p_plus_q, ctx) ||
      !BN_lshift(multiple, rsa->n, 2) ||
      !BN_sub(rem, rem, multiple) ||
      !BN_sqrt(p_minus_q, rem, ctx) ||
      /* q is 1/2 (p+q)-(p-q) */
      !BN_sub(rsa->q, p_plus_q, p_minus_q) ||
      !BN_rshift1(rsa->q, rsa->q) ||
      !BN_div(rsa->p, NULL, rsa->n, rsa->q, ctx) ||
      !BN_mul(multiple, rsa->p, rsa->q, ctx)) {
    OPENSSL_PUT_ERROR(RSA, ERR_R_BN_LIB);
    goto err;
  }

  if (BN_cmp(multiple, rsa->n) != 0) {
    OPENSSL_PUT_ERROR(RSA, RSA_R_INTERNAL_ERROR);
    goto err;
  }

  if (!BN_sub(rem, rsa->p, BN_value_one()) ||
      !BN_mod(rsa->dmp1, rsa->d, rem, ctx) ||
      !BN_sub(rem, rsa->q, BN_value_one()) ||
      !BN_mod(rsa->dmq1, rsa->d, rem, ctx) ||
      !BN_mod_inverse(rsa->iqmp, rsa->q, rsa->p, ctx)) {
    OPENSSL_PUT_ERROR(RSA, ERR_R_BN_LIB);
    goto err;
  }

  ok = 1;

err:
  BN_CTX_end(ctx);
  BN_CTX_free(ctx);
  if (!ok) {
    bn_free_and_null(&rsa->p);
    bn_free_and_null(&rsa->q);
    bn_free_and_null(&rsa->dmp1);
    bn_free_and_null(&rsa->dmq1);
    bn_free_and_null(&rsa->iqmp);
  }
  return ok;
}
Example #5
0
/*
 * Find the bignum ranges that produce a given prefix.
 */
static int
get_prefix_ranges(int addrtype, const char *pfx, BIGNUM **result,
		  BN_CTX *bnctx)
{
	int i, p, c;
	int zero_prefix = 0;
	int check_upper = 0;
	int b58pow, b58ceil, b58top = 0;
	int ret = -1;

	BIGNUM bntarg, bnceil, bnfloor;
	BIGNUM bnbase;
	BIGNUM *bnap, *bnbp, *bntp;
	BIGNUM *bnhigh = NULL, *bnlow = NULL, *bnhigh2 = NULL, *bnlow2 = NULL;
	BIGNUM bntmp, bntmp2;

	BN_init(&bntarg);
	BN_init(&bnceil);
	BN_init(&bnfloor);
	BN_init(&bnbase);
	BN_init(&bntmp);
	BN_init(&bntmp2);

	BN_set_word(&bnbase, 58);

	p = strlen(pfx);

	for (i = 0; i < p; i++) {
		c = vg_b58_reverse_map[(int)pfx[i]];
		if (c == -1) {
			fprintf(stderr,
				"Invalid character '%c' in prefix '%s'\n",
				pfx[i], pfx);
			goto out;
		}
		if (i == zero_prefix) {
			if (c == 0) {
				/* Add another zero prefix */
				zero_prefix++;
				if (zero_prefix > 19) {
					fprintf(stderr,
						"Prefix '%s' is too long\n",
						pfx);
					goto out;
				}
				continue;
			}

			/* First non-zero character */
			b58top = c;
			BN_set_word(&bntarg, c);

		} else {
			BN_set_word(&bntmp2, c);
			BN_mul(&bntmp, &bntarg, &bnbase, bnctx);
			BN_add(&bntarg, &bntmp, &bntmp2);
		}
	}

	/* Power-of-two ceiling and floor values based on leading 1s */
	BN_clear(&bntmp);
	BN_set_bit(&bntmp, 200 - (zero_prefix * 8));
	BN_sub(&bnceil, &bntmp, BN_value_one());
	BN_set_bit(&bnfloor, 192 - (zero_prefix * 8));

	bnlow = BN_new();
	bnhigh = BN_new();

	if (b58top) {
		/*
		 * If a non-zero was given in the prefix, find the
		 * numeric boundaries of the prefix.
		 */

		BN_copy(&bntmp, &bnceil);
		bnap = &bntmp;
		bnbp = &bntmp2;
		b58pow = 0;
		while (BN_cmp(bnap, &bnbase) > 0) {
			b58pow++;
			BN_div(bnbp, NULL, bnap, &bnbase, bnctx);
			bntp = bnap;
			bnap = bnbp;
			bnbp = bntp;
		}
		b58ceil = BN_get_word(bnap);

		if ((b58pow - (p - zero_prefix)) < 6) {
			/*
			 * Do not allow the prefix to constrain the
			 * check value, this is ridiculous.
			 */
			fprintf(stderr, "Prefix '%s' is too long\n", pfx);
			goto out;
		}

		BN_set_word(&bntmp2, b58pow - (p - zero_prefix));
		BN_exp(&bntmp, &bnbase, &bntmp2, bnctx);
		BN_mul(bnlow, &bntmp, &bntarg, bnctx);
		BN_sub(&bntmp2, &bntmp, BN_value_one());
		BN_add(bnhigh, bnlow, &bntmp2);

		if (b58top <= b58ceil) {
			/* Fill out the upper range too */
			check_upper = 1;
			bnlow2 = BN_new();
			bnhigh2 = BN_new();

			BN_mul(bnlow2, bnlow, &bnbase, bnctx);
			BN_mul(&bntmp2, bnhigh, &bnbase, bnctx);
			BN_set_word(&bntmp, 57);
			BN_add(bnhigh2, &bntmp2, &bntmp);

			/*
			 * Addresses above the ceiling will have one
			 * fewer "1" prefix in front than we require.
			 */
			if (BN_cmp(&bnceil, bnlow2) < 0) {
				/* High prefix is above the ceiling */
				check_upper = 0;
				BN_free(bnhigh2);
				bnhigh2 = NULL;
				BN_free(bnlow2);
				bnlow2 = NULL;
			}
			else if (BN_cmp(&bnceil, bnhigh2) < 0)
				/* High prefix is partly above the ceiling */
				BN_copy(bnhigh2, &bnceil);

			/*
			 * Addresses below the floor will have another
			 * "1" prefix in front instead of our target.
			 */
			if (BN_cmp(&bnfloor, bnhigh) >= 0) {
				/* Low prefix is completely below the floor */
				assert(check_upper);
				check_upper = 0;
				BN_free(bnhigh);
				bnhigh = bnhigh2;
				bnhigh2 = NULL;
				BN_free(bnlow);
				bnlow = bnlow2;
				bnlow2 = NULL;
			}			
			else if (BN_cmp(&bnfloor, bnlow) > 0) {
				/* Low prefix is partly below the floor */
				BN_copy(bnlow, &bnfloor);
			}
		}

	} else {
		BN_copy(bnhigh, &bnceil);
		BN_clear(bnlow);
	}

	/* Limit the prefix to the address type */
	BN_clear(&bntmp);
	BN_set_word(&bntmp, addrtype);
	BN_lshift(&bntmp2, &bntmp, 192);

	if (check_upper) {
		if (BN_cmp(&bntmp2, bnhigh2) > 0) {
			check_upper = 0;
			BN_free(bnhigh2);
			bnhigh2 = NULL;
			BN_free(bnlow2);
			bnlow2 = NULL;
		}
		else if (BN_cmp(&bntmp2, bnlow2) > 0)
			BN_copy(bnlow2, &bntmp2);
	}

	if (BN_cmp(&bntmp2, bnhigh) > 0) {
		if (!check_upper)
			goto not_possible;
		check_upper = 0;
		BN_free(bnhigh);
		bnhigh = bnhigh2;
		bnhigh2 = NULL;
		BN_free(bnlow);
		bnlow = bnlow2;
		bnlow2 = NULL;
	}
	else if (BN_cmp(&bntmp2, bnlow) > 0) {
		BN_copy(bnlow, &bntmp2);
	}

	BN_set_word(&bntmp, addrtype + 1);
	BN_lshift(&bntmp2, &bntmp, 192);

	if (check_upper) {
		if (BN_cmp(&bntmp2, bnlow2) < 0) {
			check_upper = 0;
			BN_free(bnhigh2);
			bnhigh2 = NULL;
			BN_free(bnlow2);
			bnlow2 = NULL;
		}
		else if (BN_cmp(&bntmp2, bnhigh2) < 0)
			BN_copy(bnlow2, &bntmp2);
	}

	if (BN_cmp(&bntmp2, bnlow) < 0) {
		if (!check_upper)
			goto not_possible;
		check_upper = 0;
		BN_free(bnhigh);
		bnhigh = bnhigh2;
		bnhigh2 = NULL;
		BN_free(bnlow);
		bnlow = bnlow2;
		bnlow2 = NULL;
	}
	else if (BN_cmp(&bntmp2, bnhigh) < 0) {
		BN_copy(bnhigh, &bntmp2);
	}

	/* Address ranges are complete */
	assert(check_upper || ((bnlow2 == NULL) && (bnhigh2 == NULL)));
	result[0] = bnlow;
	result[1] = bnhigh;
	result[2] = bnlow2;
	result[3] = bnhigh2;
	bnlow = NULL;
	bnhigh = NULL;
	bnlow2 = NULL;
	bnhigh2 = NULL;
	ret = 0;

	if (0) {
	not_possible:
		ret = -2;
	}

out:
	BN_clear_free(&bntarg);
	BN_clear_free(&bnceil);
	BN_clear_free(&bnfloor);
	BN_clear_free(&bnbase);
	BN_clear_free(&bntmp);
	BN_clear_free(&bntmp2);
	if (bnhigh)
		BN_free(bnhigh);
	if (bnlow)
		BN_free(bnlow);
	if (bnhigh2)
		BN_free(bnhigh2);
	if (bnlow2)
		BN_free(bnlow2);

	return ret;
}
static jboolean NativeBN_BN_mul(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* b) {
    if (!threeValidHandles(env, r, a, b)) return JNI_FALSE;
    Unique_BN_CTX ctx(BN_CTX_new());
    return BN_mul(r, a, b, ctx.get());
}
Example #7
0
/* solves ax == 1 (mod n) */
BIGNUM *BN_mod_inverse(BIGNUM *in,
	const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx)
	{
	BIGNUM *A,*B,*X,*Y,*M,*D,*T,*R=NULL;
	BIGNUM *ret=NULL;
	int sign;

	bn_check_top(a);
	bn_check_top(n);

	BN_CTX_start(ctx);
	A = BN_CTX_get(ctx);
	B = BN_CTX_get(ctx);
	X = BN_CTX_get(ctx);
	D = BN_CTX_get(ctx);
	M = BN_CTX_get(ctx);
	Y = BN_CTX_get(ctx);
	T = BN_CTX_get(ctx);
	if (T == NULL) goto err;

	if (in == NULL)
		R=BN_new();
	else
		R=in;
	if (R == NULL) goto err;

	BN_one(X);
	BN_zero(Y);
	if (BN_copy(B,a) == NULL) goto err;
	if (BN_copy(A,n) == NULL) goto err;
	A->neg = 0;
	if (B->neg || (BN_ucmp(B, A) >= 0))
		{
		if (!BN_nnmod(B, B, A, ctx)) goto err;
		}
	sign = -1;
	/* From  B = a mod |n|,  A = |n|  it follows that
	 *
	 *      0 <= B < A,
	 *     -sign*X*a  ==  B   (mod |n|),
	 *      sign*Y*a  ==  A   (mod |n|).
	 */

	if (BN_is_odd(n) && (BN_num_bits(n) <= (BN_BITS <= 32 ? 450 : 2048)))
		{
		/* Binary inversion algorithm; requires odd modulus.
		 * This is faster than the general algorithm if the modulus
		 * is sufficiently small (about 400 .. 500 bits on 32-bit
		 * sytems, but much more on 64-bit systems) */
		int shift;

		while (!BN_is_zero(B))
			{
			/*
			 *      0 < B < |n|,
			 *      0 < A <= |n|,
			 * (1) -sign*X*a  ==  B   (mod |n|),
			 * (2)  sign*Y*a  ==  A   (mod |n|)
			 */

			/* Now divide  B  by the maximum possible power of two in the integers,
			 * and divide  X  by the same value mod |n|.
			 * When we're done, (1) still holds. */
			shift = 0;
			while (!BN_is_bit_set(B, shift)) /* note that 0 < B */
				{
				shift++;

				if (BN_is_odd(X))
					{
					if (!BN_uadd(X, X, n)) goto err;
					}
				/* now X is even, so we can easily divide it by two */
				if (!BN_rshift1(X, X)) goto err;
				}
			if (shift > 0)
				{
				if (!BN_rshift(B, B, shift)) goto err;
				}


			/* Same for  A  and  Y.  Afterwards, (2) still holds. */
			shift = 0;
			while (!BN_is_bit_set(A, shift)) /* note that 0 < A */
				{
				shift++;

				if (BN_is_odd(Y))
					{
					if (!BN_uadd(Y, Y, n)) goto err;
					}
				/* now Y is even */
				if (!BN_rshift1(Y, Y)) goto err;
				}
			if (shift > 0)
				{
				if (!BN_rshift(A, A, shift)) goto err;
				}


			/* We still have (1) and (2).
			 * Both  A  and  B  are odd.
			 * The following computations ensure that
			 *
			 *     0 <= B < |n|,
			 *      0 < A < |n|,
			 * (1) -sign*X*a  ==  B   (mod |n|),
			 * (2)  sign*Y*a  ==  A   (mod |n|),
			 *
			 * and that either  A  or  B  is even in the next iteration.
			 */
			if (BN_ucmp(B, A) >= 0)
				{
				/* -sign*(X + Y)*a == B - A  (mod |n|) */
				if (!BN_uadd(X, X, Y)) goto err;
				/* NB: we could use BN_mod_add_quick(X, X, Y, n), but that
				 * actually makes the algorithm slower */
				if (!BN_usub(B, B, A)) goto err;
				}
			else
				{
				/*  sign*(X + Y)*a == A - B  (mod |n|) */
				if (!BN_uadd(Y, Y, X)) goto err;
				/* as above, BN_mod_add_quick(Y, Y, X, n) would slow things down */
				if (!BN_usub(A, A, B)) goto err;
				}
			}
		}
	else
		{
		/* general inversion algorithm */

		while (!BN_is_zero(B))
			{
			BIGNUM *tmp;

			/*
			 *      0 < B < A,
			 * (*) -sign*X*a  ==  B   (mod |n|),
			 *      sign*Y*a  ==  A   (mod |n|)
			 */

			/* (D, M) := (A/B, A%B) ... */
			if (BN_num_bits(A) == BN_num_bits(B))
				{
				if (!BN_one(D)) goto err;
				if (!BN_sub(M,A,B)) goto err;
				}
			else if (BN_num_bits(A) == BN_num_bits(B) + 1)
				{
				/* A/B is 1, 2, or 3 */
				if (!BN_lshift1(T,B)) goto err;
				if (BN_ucmp(A,T) < 0)
					{
					/* A < 2*B, so D=1 */
					if (!BN_one(D)) goto err;
					if (!BN_sub(M,A,B)) goto err;
					}
				else
					{
					/* A >= 2*B, so D=2 or D=3 */
					if (!BN_sub(M,A,T)) goto err;
					if (!BN_add(D,T,B)) goto err; /* use D (:= 3*B) as temp */
					if (BN_ucmp(A,D) < 0)
						{
						/* A < 3*B, so D=2 */
						if (!BN_set_word(D,2)) goto err;
						/* M (= A - 2*B) already has the correct value */
						}
					else
						{
						/* only D=3 remains */
						if (!BN_set_word(D,3)) goto err;
						/* currently  M = A - 2*B,  but we need  M = A - 3*B */
						if (!BN_sub(M,M,B)) goto err;
						}
					}
				}
			else
				{
				if (!BN_div(D,M,A,B,ctx)) goto err;
				}

			/* Now
			 *      A = D*B + M;
			 * thus we have
			 * (**)  sign*Y*a  ==  D*B + M   (mod |n|).
			 */

			tmp=A; /* keep the BIGNUM object, the value does not matter */

			/* (A, B) := (B, A mod B) ... */
			A=B;
			B=M;
			/* ... so we have  0 <= B < A  again */

			/* Since the former  M  is now  B  and the former  B  is now  A,
			 * (**) translates into
			 *       sign*Y*a  ==  D*A + B    (mod |n|),
			 * i.e.
			 *       sign*Y*a - D*A  ==  B    (mod |n|).
			 * Similarly, (*) translates into
			 *      -sign*X*a  ==  A          (mod |n|).
			 *
			 * Thus,
			 *   sign*Y*a + D*sign*X*a  ==  B  (mod |n|),
			 * i.e.
			 *        sign*(Y + D*X)*a  ==  B  (mod |n|).
			 *
			 * So if we set  (X, Y, sign) := (Y + D*X, X, -sign),  we arrive back at
			 *      -sign*X*a  ==  B   (mod |n|),
			 *       sign*Y*a  ==  A   (mod |n|).
			 * Note that  X  and  Y  stay non-negative all the time.
			 */

			/* most of the time D is very small, so we can optimize tmp := D*X+Y */
			if (BN_is_one(D))
				{
				if (!BN_add(tmp,X,Y)) goto err;
				}
			else
				{
				if (BN_is_word(D,2))
					{
					if (!BN_lshift1(tmp,X)) goto err;
					}
				else if (BN_is_word(D,4))
					{
					if (!BN_lshift(tmp,X,2)) goto err;
					}
				else if (D->top == 1)
					{
					if (!BN_copy(tmp,X)) goto err;
					if (!BN_mul_word(tmp,D->d[0])) goto err;
					}
				else
					{
					if (!BN_mul(tmp,D,X,ctx)) goto err;
					}
				if (!BN_add(tmp,tmp,Y)) goto err;
				}

			M=Y; /* keep the BIGNUM object, the value does not matter */
			Y=X;
			X=tmp;
			sign = -sign;
			}
		}

	/*
	 * The while loop (Euclid's algorithm) ends when
	 *      A == gcd(a,n);
	 * we have
	 *       sign*Y*a  ==  A  (mod |n|),
	 * where  Y  is non-negative.
	 */

	if (sign < 0)
		{
		if (!BN_sub(Y,n,Y)) goto err;
		}
	/* Now  Y*a  ==  A  (mod |n|).  */


	if (BN_is_one(A))
		{
		/* Y*a == 1  (mod |n|) */
		if (!Y->neg && BN_ucmp(Y,n) < 0)
			{
			if (!BN_copy(R,Y)) goto err;
			}
		else
			{
			if (!BN_nnmod(R,Y,n,ctx)) goto err;
			}
		}
	else
		{
		BNerr(BN_F_BN_MOD_INVERSE,BN_R_NO_INVERSE);
		goto err;
		}
	ret=R;
err:
	if ((ret == NULL) && (in == NULL)) BN_free(R);
	BN_CTX_end(ctx);
	return(ret);
	}
Example #8
0
int generateRingSignatureAB(data_chunk &keyImage, uint256 &txnHash, int nRingSize, int nSecretOffset, ec_secret secret, const uint8_t *pPubkeys, data_chunk &sigC, uint8_t *pSigS)
{
    // https://bitcointalk.org/index.php?topic=972541.msg10619684

    if (fDebugRingSig)
        LogPrintf("%s: Ring size %d.\n", __func__, nRingSize);

    assert(nRingSize < 200);

    RandAddSeedPerfmon();

    memset(pSigS, 0, EC_SECRET_SIZE * nRingSize);

    int rv = 0;
    int nBytes;

    uint256 tmpPkHash;
    uint256 tmpHash;

    uint8_t tempData[66]; // hold raw point data to hash
    ec_secret sAlpha;

    if (0 != GenerateRandomSecret(sAlpha))
        return errorN(1, "%s: GenerateRandomSecret failed.", __func__);

    CHashWriter ssPkHash(SER_GETHASH, PROTOCOL_VERSION);
    CHashWriter ssCjHash(SER_GETHASH, PROTOCOL_VERSION);

    uint256 test;
    for (int i = 0; i < nRingSize; ++i)
    {
        ssPkHash.write((const char*)&pPubkeys[i * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE);

        if (i == nSecretOffset)
            continue;

        int k;
        // NOTE: necessary to clamp?
        for (k = 0; k < 32; ++k)
        {
            if (1 != RAND_bytes(&pSigS[i * EC_SECRET_SIZE], 32))
                return errorN(1, "%s: RAND_bytes ERR_get_error %u.", __func__, ERR_get_error());

            memcpy(test.begin(), &pSigS[i * EC_SECRET_SIZE], 32);
            if (test > MIN_SECRET && test < MAX_SECRET)
                break;
        };

        if (k > 31)
            return errorN(1, "%s: Failed to generate a valid key.", __func__);
    };

    tmpPkHash = ssPkHash.GetHash();

    BN_CTX_start(bnCtx);
    BIGNUM   *bnT  = BN_CTX_get(bnCtx);
    BIGNUM   *bnT2 = BN_CTX_get(bnCtx);
    BIGNUM   *bnS  = BN_CTX_get(bnCtx);
    BIGNUM   *bnC  = BN_CTX_get(bnCtx);
    BIGNUM   *bnCj = BN_CTX_get(bnCtx);
    BIGNUM   *bnA  = BN_CTX_get(bnCtx);
    EC_POINT *ptKi = NULL;
    EC_POINT *ptPk = NULL;
    EC_POINT *ptT1 = NULL;
    EC_POINT *ptT2 = NULL;
    EC_POINT *ptT3 = NULL;
    EC_POINT *ptT4 = NULL;

    if (   !(ptKi = EC_POINT_new(ecGrp))
        || !(ptPk = EC_POINT_new(ecGrp))
        || !(ptT1 = EC_POINT_new(ecGrp))
        || !(ptT2 = EC_POINT_new(ecGrp))
        || !(ptT3 = EC_POINT_new(ecGrp))
        || !(ptT4 = EC_POINT_new(ecGrp)))
    {
        LogPrintf("%s: EC_POINT_new failed.\n", __func__);
        rv = 1; goto End;
    };

    // get keyimage as point
    if (!EC_POINT_oct2point(ecGrp, ptKi, &keyImage[0], EC_COMPRESSED_SIZE, bnCtx))
    {
        LogPrintf("%s: extract ptKi failed.\n", __func__);
        rv = 1; goto End;
    };

    // c_{j+1} = h(P_1,...,P_n,alpha*G,alpha*H(P_j))
    if (!bnA || !(BN_bin2bn(&sAlpha.e[0], EC_SECRET_SIZE, bnA)))
    {
        LogPrintf("%s: BN_bin2bn failed.\n", __func__);
        rv = 1; goto End;
    };

    // ptT1 = alpha * G
    if (!EC_POINT_mul(ecGrp, ptT1, bnA, NULL, NULL, bnCtx))
    {
        LogPrintf("%s: EC_POINT_mul failed.\n", __func__);
        rv = 1; goto End;
    };

    // ptT3 = H(Pj)

    if (hashToEC(&pPubkeys[nSecretOffset * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnT2, ptT3) != 0)
    {
        LogPrintf("%s: hashToEC failed.\n", __func__);
        rv = 1; goto End;
    };

    ssCjHash.write((const char*)tmpPkHash.begin(), 32);

    // ptT2 = alpha * H(P_j)
    // ptT2 = alpha * ptT3
    if (!EC_POINT_mul(ecGrp, ptT2, NULL, ptT3, bnA, bnCtx))
    {
        LogPrintf("%s: EC_POINT_mul failed.\n", __func__);
        rv = 1; goto End;
    };

    if (   !(EC_POINT_point2oct(ecGrp, ptT1, POINT_CONVERSION_COMPRESSED, &tempData[0],  33, bnCtx) == (int) EC_COMPRESSED_SIZE)
        || !(EC_POINT_point2oct(ecGrp, ptT2, POINT_CONVERSION_COMPRESSED, &tempData[33], 33, bnCtx) == (int) EC_COMPRESSED_SIZE))
    {
        LogPrintf("%s: extract ptL and ptR failed.\n", __func__);
        rv = 1; goto End;
    };

    ssCjHash.write((const char*)&tempData[0], 66);
    tmpHash = ssCjHash.GetHash();

    if (!bnC || !(BN_bin2bn(tmpHash.begin(), EC_SECRET_SIZE, bnC)) // bnC lags i by 1
        || !BN_mod(bnC, bnC, bnOrder, bnCtx))
    {
        LogPrintf("%s: hash -> bnC failed.\n", __func__);
        rv = 1; goto End;
    };


    // c_{j+2} = h(P_1,...,P_n,s_{j+1}*G+c_{j+1}*P_{j+1},s_{j+1}*H(P_{j+1})+c_{j+1}*I_j)
    for (int k = 0, ib = (nSecretOffset + 1) % nRingSize, i = (nSecretOffset + 2) % nRingSize;
        k < nRingSize;
        ++k, ib=i, i=(i+1) % nRingSize)
    {
        if (k == nRingSize - 1)
        {
            // s_j = alpha - c_j*x_j mod n.
            if (!bnT || !BN_bin2bn(&secret.e[0], EC_SECRET_SIZE, bnT))
            {
                LogPrintf("%s: BN_bin2bn failed.\n", __func__);
                rv = 1; goto End;
            };

            if (!BN_mul(bnT2, bnCj, bnT, bnCtx))
            {
                LogPrintf("%s: BN_mul failed.\n", __func__);
                rv = 1; goto End;
            };

            if (!BN_mod_sub(bnS, bnA, bnT2, bnOrder, bnCtx))
            {
                LogPrintf("%s: BN_mod_sub failed.\n", __func__);
                rv = 1; goto End;
            };

            if (!bnS || (nBytes = BN_num_bytes(bnS)) > (int) EC_SECRET_SIZE
                || BN_bn2bin(bnS, &pSigS[nSecretOffset * EC_SECRET_SIZE + (EC_SECRET_SIZE-nBytes)]) != nBytes)
            {
                LogPrintf("%s: bnS -> pSigS failed.\n", __func__);
                rv = 1; goto End;
            };

            if (nSecretOffset != nRingSize - 1)
                break;
        };

        if (!bnS || !(BN_bin2bn(&pSigS[ib * EC_SECRET_SIZE], EC_SECRET_SIZE, bnS)))
        {
            LogPrintf("%s: BN_bin2bn failed.\n", __func__);
            rv = 1; goto End;
        };

        // bnC is from last round (ib)
        if (!EC_POINT_oct2point(ecGrp, ptPk, &pPubkeys[ib * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnCtx))
        {
            LogPrintf("%s: EC_POINT_oct2point failed.\n", __func__);
            rv = 1; goto End;
        };

        // ptT1 = s_{j+1}*G+c_{j+1}*P_{j+1}
        if (!EC_POINT_mul(ecGrp, ptT1, bnS, ptPk, bnC, bnCtx))
        {
            LogPrintf("%s: EC_POINT_mul failed.\n", __func__);
            rv = 1; goto End;
        };

        //s_{j+1}*H(P_{j+1})+c_{j+1}*I_j

        if (hashToEC(&pPubkeys[ib * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnT2, ptT2) != 0)
        {
            LogPrintf("%s: hashToEC failed.\n", __func__);
            rv = 1; goto End;
        };

        // ptT3 = s_{j+1}*H(P_{j+1})
        if (!EC_POINT_mul(ecGrp, ptT3, NULL, ptT2, bnS, bnCtx))
        {
            LogPrintf("%s: EC_POINT_mul failed.\n", __func__);
            rv = 1; goto End;
        };

        // ptT4 = c_{j+1}*I_j
        if (!EC_POINT_mul(ecGrp, ptT4, NULL, ptKi, bnC, bnCtx))
        {
            LogPrintf("%s: EC_POINT_mul failed.\n", __func__);
            rv = 1; goto End;
        };

        // ptT2 = ptT3 + ptT4
        if (!EC_POINT_add(ecGrp, ptT2, ptT3, ptT4, bnCtx))
        {
            LogPrintf("%s: EC_POINT_add failed.\n", __func__);
            rv = 1; goto End;
        };

        if (   !(EC_POINT_point2oct(ecGrp, ptT1, POINT_CONVERSION_COMPRESSED, &tempData[0],  33, bnCtx) == (int) EC_COMPRESSED_SIZE)
            || !(EC_POINT_point2oct(ecGrp, ptT2, POINT_CONVERSION_COMPRESSED, &tempData[33], 33, bnCtx) == (int) EC_COMPRESSED_SIZE))
        {
            LogPrintf("%s: extract ptL and ptR failed.\n", __func__);
            rv = 1; goto End;
        };

        CHashWriter ssCHash(SER_GETHASH, PROTOCOL_VERSION);
        ssCHash.write((const char*)tmpPkHash.begin(), 32);
        ssCHash.write((const char*)&tempData[0], 66);
        tmpHash = ssCHash.GetHash();

        if (!bnC || !(BN_bin2bn(tmpHash.begin(), EC_SECRET_SIZE, bnC)) // bnC lags i by 1
            || !BN_mod(bnC, bnC, bnOrder, bnCtx))
        {
            LogPrintf("%s: hash -> bnC failed.\n", __func__);
            rv = 1; goto End;
        };

        if (i == nSecretOffset
            && !BN_copy(bnCj, bnC))
        {
            LogPrintf("%s: BN_copy failed.\n", __func__);
            rv = 1; goto End;
        };

        if (i == 0)
        {
            memset(tempData, 0, EC_SECRET_SIZE);
            if ((nBytes = BN_num_bytes(bnC)) > (int) EC_SECRET_SIZE
                || BN_bn2bin(bnC, &tempData[0 + (EC_SECRET_SIZE-nBytes)]) != nBytes)
            {
                LogPrintf("%s: bnC -> sigC failed.\n", __func__);
                rv = 1; goto End;
            };
            try { sigC.resize(32); } catch (std::exception& e)
            {
                LogPrintf("%s: sigC.resize failed.\n", __func__);
                rv = 1; goto End;
            };
            memcpy(&sigC[0], tempData, EC_SECRET_SIZE);
        };
    };

    End:
    EC_POINT_free(ptKi);
    EC_POINT_free(ptPk);
    EC_POINT_free(ptT1);
    EC_POINT_free(ptT2);
    EC_POINT_free(ptT3);
    EC_POINT_free(ptT4);

    BN_CTX_end(bnCtx);

    return rv;
};
Example #9
0
bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, int nHashType)
{
    CAutoBN_CTX pctx;
    CScript::const_iterator pc = script.begin();
    CScript::const_iterator pend = script.end();
    CScript::const_iterator pbegincodehash = script.begin();
    opcodetype opcode;
    valtype vchPushValue;
    vector<bool> vfExec;
    vector<valtype> altstack;
    if (script.size() > 10000)
        return false;
    int nOpCount = 0;


    try
    {
        while (pc < pend)
        {
            bool fExec = !count(vfExec.begin(), vfExec.end(), false);

            //
            // Read instruction
            //
            if (!script.GetOp(pc, opcode, vchPushValue))
                return false;
            if (vchPushValue.size() > 520)
                return false;
            if (opcode > OP_16 && ++nOpCount > 201)
                return false;

            if (opcode == OP_CAT ||
                opcode == OP_SUBSTR ||
                opcode == OP_LEFT ||
                opcode == OP_RIGHT ||
                opcode == OP_INVERT ||
                opcode == OP_AND ||
                opcode == OP_OR ||
                opcode == OP_XOR ||
                opcode == OP_2MUL ||
                opcode == OP_2DIV ||
                opcode == OP_MUL ||
                opcode == OP_DIV ||
                opcode == OP_MOD ||
                opcode == OP_LSHIFT ||
                opcode == OP_RSHIFT)
                return false;

            if (fExec && 0 <= opcode && opcode <= OP_PUSHDATA4)
                stack.push_back(vchPushValue);
            else if (fExec || (OP_IF <= opcode && opcode <= OP_ENDIF))
            switch (opcode)
            {
                //
                // Push value
                //
                case OP_1NEGATE:
                case OP_1:
                case OP_2:
                case OP_3:
                case OP_4:
                case OP_5:
                case OP_6:
                case OP_7:
                case OP_8:
                case OP_9:
                case OP_10:
                case OP_11:
                case OP_12:
                case OP_13:
                case OP_14:
                case OP_15:
                case OP_16:
                {
                    // ( -- value)
                    CBigNum bn((int)opcode - (int)(OP_1 - 1));
                    stack.push_back(bn.getvch());
                }
                break;


                //
                // Control
                //
                case OP_NOP:
                case OP_NOP1: case OP_NOP2: case OP_NOP3: case OP_NOP4: case OP_NOP5:
                case OP_NOP6: case OP_NOP7: case OP_NOP8: case OP_NOP9: case OP_NOP10:
                break;

                case OP_IF:
                case OP_NOTIF:
                {
                    // <expression> if [statements] [else [statements]] endif
                    bool fValue = false;
                    if (fExec)
                    {
                        if (stack.size() < 1)
                            return false;
                        valtype& vch = stacktop(-1);
                        fValue = CastToBool(vch);
                        if (opcode == OP_NOTIF)
                            fValue = !fValue;
                        popstack(stack);
                    }
                    vfExec.push_back(fValue);
                }
                break;

                case OP_ELSE:
                {
                    if (vfExec.empty())
                        return false;
                    vfExec.back() = !vfExec.back();
                }
                break;

                case OP_ENDIF:
                {
                    if (vfExec.empty())
                        return false;
                    vfExec.pop_back();
                }
                break;

                case OP_VERIFY:
                {
                    // (true -- ) or
                    // (false -- false) and return
                    if (stack.size() < 1)
                        return false;
                    bool fValue = CastToBool(stacktop(-1));
                    if (fValue)
                        popstack(stack);
                    else
                        return false;
                }
                break;

                case OP_RETURN:
                {
                    return false;
                }
                break;


                //
                // Stack ops
                //
                case OP_TOALTSTACK:
                {
                    if (stack.size() < 1)
                        return false;
                    altstack.push_back(stacktop(-1));
                    popstack(stack);
                }
                break;

                case OP_FROMALTSTACK:
                {
                    if (altstack.size() < 1)
                        return false;
                    stack.push_back(altstacktop(-1));
                    popstack(altstack);
                }
                break;

                case OP_2DROP:
                {
                    // (x1 x2 -- )
                    if (stack.size() < 2)
                        return false;
                    popstack(stack);
                    popstack(stack);
                }
                break;

                case OP_2DUP:
                {
                    // (x1 x2 -- x1 x2 x1 x2)
                    if (stack.size() < 2)
                        return false;
                    valtype vch1 = stacktop(-2);
                    valtype vch2 = stacktop(-1);
                    stack.push_back(vch1);
                    stack.push_back(vch2);
                }
                break;

                case OP_3DUP:
                {
                    // (x1 x2 x3 -- x1 x2 x3 x1 x2 x3)
                    if (stack.size() < 3)
                        return false;
                    valtype vch1 = stacktop(-3);
                    valtype vch2 = stacktop(-2);
                    valtype vch3 = stacktop(-1);
                    stack.push_back(vch1);
                    stack.push_back(vch2);
                    stack.push_back(vch3);
                }
                break;

                case OP_2OVER:
                {
                    // (x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2)
                    if (stack.size() < 4)
                        return false;
                    valtype vch1 = stacktop(-4);
                    valtype vch2 = stacktop(-3);
                    stack.push_back(vch1);
                    stack.push_back(vch2);
                }
                break;

                case OP_2ROT:
                {
                    // (x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2)
                    if (stack.size() < 6)
                        return false;
                    valtype vch1 = stacktop(-6);
                    valtype vch2 = stacktop(-5);
                    stack.erase(stack.end()-6, stack.end()-4);
                    stack.push_back(vch1);
                    stack.push_back(vch2);
                }
                break;

                case OP_2SWAP:
                {
                    // (x1 x2 x3 x4 -- x3 x4 x1 x2)
                    if (stack.size() < 4)
                        return false;
                    swap(stacktop(-4), stacktop(-2));
                    swap(stacktop(-3), stacktop(-1));
                }
                break;

                case OP_IFDUP:
                {
                    // (x - 0 | x x)
                    if (stack.size() < 1)
                        return false;
                    valtype vch = stacktop(-1);
                    if (CastToBool(vch))
                        stack.push_back(vch);
                }
                break;

                case OP_DEPTH:
                {
                    // -- stacksize
                    CBigNum bn(stack.size());
                    stack.push_back(bn.getvch());
                }
                break;

                case OP_DROP:
                {
                    // (x -- )
                    if (stack.size() < 1)
                        return false;
                    popstack(stack);
                }
                break;

                case OP_DUP:
                {
                    // (x -- x x)
                    if (stack.size() < 1)
                        return false;
                    valtype vch = stacktop(-1);
                    stack.push_back(vch);
                }
                break;

                case OP_NIP:
                {
                    // (x1 x2 -- x2)
                    if (stack.size() < 2)
                        return false;
                    stack.erase(stack.end() - 2);
                }
                break;

                case OP_OVER:
                {
                    // (x1 x2 -- x1 x2 x1)
                    if (stack.size() < 2)
                        return false;
                    valtype vch = stacktop(-2);
                    stack.push_back(vch);
                }
                break;

                case OP_PICK:
                case OP_ROLL:
                {
                    // (xn ... x2 x1 x0 n - xn ... x2 x1 x0 xn)
                    // (xn ... x2 x1 x0 n - ... x2 x1 x0 xn)
                    if (stack.size() < 2)
                        return false;
                    int n = CastToBigNum(stacktop(-1)).getint();
                    popstack(stack);
                    if (n < 0 || n >= stack.size())
                        return false;
                    valtype vch = stacktop(-n-1);
                    if (opcode == OP_ROLL)
                        stack.erase(stack.end()-n-1);
                    stack.push_back(vch);
                }
                break;

                case OP_ROT:
                {
                    // (x1 x2 x3 -- x2 x3 x1)
                    //  x2 x1 x3  after first swap
                    //  x2 x3 x1  after second swap
                    if (stack.size() < 3)
                        return false;
                    swap(stacktop(-3), stacktop(-2));
                    swap(stacktop(-2), stacktop(-1));
                }
                break;

                case OP_SWAP:
                {
                    // (x1 x2 -- x2 x1)
                    if (stack.size() < 2)
                        return false;
                    swap(stacktop(-2), stacktop(-1));
                }
                break;

                case OP_TUCK:
                {
                    // (x1 x2 -- x2 x1 x2)
                    if (stack.size() < 2)
                        return false;
                    valtype vch = stacktop(-1);
                    stack.insert(stack.end()-2, vch);
                }
                break;


                //
                // Splice ops
                //
                case OP_CAT:
                {
                    // (x1 x2 -- out)
                    if (stack.size() < 2)
                        return false;
                    valtype& vch1 = stacktop(-2);
                    valtype& vch2 = stacktop(-1);
                    vch1.insert(vch1.end(), vch2.begin(), vch2.end());
                    popstack(stack);
                    if (stacktop(-1).size() > 520)
                        return false;
                }
                break;

                case OP_SUBSTR:
                {
                    // (in begin size -- out)
                    if (stack.size() < 3)
                        return false;
                    valtype& vch = stacktop(-3);
                    int nBegin = CastToBigNum(stacktop(-2)).getint();
                    int nEnd = nBegin + CastToBigNum(stacktop(-1)).getint();
                    if (nBegin < 0 || nEnd < nBegin)
                        return false;
                    if (nBegin > vch.size())
                        nBegin = vch.size();
                    if (nEnd > vch.size())
                        nEnd = vch.size();
                    vch.erase(vch.begin() + nEnd, vch.end());
                    vch.erase(vch.begin(), vch.begin() + nBegin);
                    popstack(stack);
                    popstack(stack);
                }
                break;

                case OP_LEFT:
                case OP_RIGHT:
                {
                    // (in size -- out)
                    if (stack.size() < 2)
                        return false;
                    valtype& vch = stacktop(-2);
                    int nSize = CastToBigNum(stacktop(-1)).getint();
                    if (nSize < 0)
                        return false;
                    if (nSize > vch.size())
                        nSize = vch.size();
                    if (opcode == OP_LEFT)
                        vch.erase(vch.begin() + nSize, vch.end());
                    else
                        vch.erase(vch.begin(), vch.end() - nSize);
                    popstack(stack);
                }
                break;

                case OP_SIZE:
                {
                    // (in -- in size)
                    if (stack.size() < 1)
                        return false;
                    CBigNum bn(stacktop(-1).size());
                    stack.push_back(bn.getvch());
                }
                break;


                //
                // Bitwise logic
                //
                case OP_INVERT:
                {
                    // (in - out)
                    if (stack.size() < 1)
                        return false;
                    valtype& vch = stacktop(-1);
                    for (int i = 0; i < vch.size(); i++)
                        vch[i] = ~vch[i];
                }
                break;

                case OP_AND:
                case OP_OR:
                case OP_XOR:
                {
                    // (x1 x2 - out)
                    if (stack.size() < 2)
                        return false;
                    valtype& vch1 = stacktop(-2);
                    valtype& vch2 = stacktop(-1);
                    MakeSameSize(vch1, vch2);
                    if (opcode == OP_AND)
                    {
                        for (int i = 0; i < vch1.size(); i++)
                            vch1[i] &= vch2[i];
                    }
                    else if (opcode == OP_OR)
                    {
                        for (int i = 0; i < vch1.size(); i++)
                            vch1[i] |= vch2[i];
                    }
                    else if (opcode == OP_XOR)
                    {
                        for (int i = 0; i < vch1.size(); i++)
                            vch1[i] ^= vch2[i];
                    }
                    popstack(stack);
                }
                break;

                case OP_EQUAL:
                case OP_EQUALVERIFY:
                //case OP_NOTEQUAL: // use OP_NUMNOTEQUAL
                {
                    // (x1 x2 - bool)
                    if (stack.size() < 2)
                        return false;
                    valtype& vch1 = stacktop(-2);
                    valtype& vch2 = stacktop(-1);
                    bool fEqual = (vch1 == vch2);
                    // OP_NOTEQUAL is disabled because it would be too easy to say
                    // something like n != 1 and have some wiseguy pass in 1 with extra
                    // zero bytes after it (numerically, 0x01 == 0x0001 == 0x000001)
                    //if (opcode == OP_NOTEQUAL)
                    //    fEqual = !fEqual;
                    popstack(stack);
                    popstack(stack);
                    stack.push_back(fEqual ? vchTrue : vchFalse);
                    if (opcode == OP_EQUALVERIFY)
                    {
                        if (fEqual)
                            popstack(stack);
                        else
                            return false;
                    }
                }
                break;


                //
                // Numeric
                //
                case OP_1ADD:
                case OP_1SUB:
                case OP_2MUL:
                case OP_2DIV:
                case OP_NEGATE:
                case OP_ABS:
                case OP_NOT:
                case OP_0NOTEQUAL:
                {
                    // (in -- out)
                    if (stack.size() < 1)
                        return false;
                    CBigNum bn = CastToBigNum(stacktop(-1));
                    switch (opcode)
                    {
                    case OP_1ADD:       bn += bnOne; break;
                    case OP_1SUB:       bn -= bnOne; break;
                    case OP_2MUL:       bn <<= 1; break;
                    case OP_2DIV:       bn >>= 1; break;
                    case OP_NEGATE:     bn = -bn; break;
                    case OP_ABS:        if (bn < bnZero) bn = -bn; break;
                    case OP_NOT:        bn = (bn == bnZero); break;
                    case OP_0NOTEQUAL:  bn = (bn != bnZero); break;
                    }
                    popstack(stack);
                    stack.push_back(bn.getvch());
                }
                break;

                case OP_ADD:
                case OP_SUB:
                case OP_MUL:
                case OP_DIV:
                case OP_MOD:
                case OP_LSHIFT:
                case OP_RSHIFT:
                case OP_BOOLAND:
                case OP_BOOLOR:
                case OP_NUMEQUAL:
                case OP_NUMEQUALVERIFY:
                case OP_NUMNOTEQUAL:
                case OP_LESSTHAN:
                case OP_GREATERTHAN:
                case OP_LESSTHANOREQUAL:
                case OP_GREATERTHANOREQUAL:
                case OP_MIN:
                case OP_MAX:
                {
                    // (x1 x2 -- out)
                    if (stack.size() < 2)
                        return false;
                    CBigNum bn1 = CastToBigNum(stacktop(-2));
                    CBigNum bn2 = CastToBigNum(stacktop(-1));
                    CBigNum bn;
                    switch (opcode)
                    {
                    case OP_ADD:
                        bn = bn1 + bn2;
                        break;

                    case OP_SUB:
                        bn = bn1 - bn2;
                        break;

                    case OP_MUL:
                        if (!BN_mul(&bn, &bn1, &bn2, pctx))
                            return false;
                        break;

                    case OP_DIV:
                        if (!BN_div(&bn, NULL, &bn1, &bn2, pctx))
                            return false;
                        break;

                    case OP_MOD:
                        if (!BN_mod(&bn, &bn1, &bn2, pctx))
                            return false;
                        break;

                    case OP_LSHIFT:
                        if (bn2 < bnZero || bn2 > CBigNum(2048))
                            return false;
                        bn = bn1 << bn2.getulong();
                        break;

                    case OP_RSHIFT:
                        if (bn2 < bnZero || bn2 > CBigNum(2048))
                            return false;
                        bn = bn1 >> bn2.getulong();
                        break;

                    case OP_BOOLAND:             bn = (bn1 != bnZero && bn2 != bnZero); break;
                    case OP_BOOLOR:              bn = (bn1 != bnZero || bn2 != bnZero); break;
                    case OP_NUMEQUAL:            bn = (bn1 == bn2); break;
                    case OP_NUMEQUALVERIFY:      bn = (bn1 == bn2); break;
                    case OP_NUMNOTEQUAL:         bn = (bn1 != bn2); break;
                    case OP_LESSTHAN:            bn = (bn1 < bn2); break;
                    case OP_GREATERTHAN:         bn = (bn1 > bn2); break;
                    case OP_LESSTHANOREQUAL:     bn = (bn1 <= bn2); break;
                    case OP_GREATERTHANOREQUAL:  bn = (bn1 >= bn2); break;
                    case OP_MIN:                 bn = (bn1 < bn2 ? bn1 : bn2); break;
                    case OP_MAX:                 bn = (bn1 > bn2 ? bn1 : bn2); break;
                    }
                    popstack(stack);
                    popstack(stack);
                    stack.push_back(bn.getvch());

                    if (opcode == OP_NUMEQUALVERIFY)
                    {
                        if (CastToBool(stacktop(-1)))
                            popstack(stack);
                        else
                            return false;
                    }
                }
                break;

                case OP_WITHIN:
                {
                    // (x min max -- out)
                    if (stack.size() < 3)
                        return false;
                    CBigNum bn1 = CastToBigNum(stacktop(-3));
                    CBigNum bn2 = CastToBigNum(stacktop(-2));
                    CBigNum bn3 = CastToBigNum(stacktop(-1));
                    bool fValue = (bn2 <= bn1 && bn1 < bn3);
                    popstack(stack);
                    popstack(stack);
                    popstack(stack);
                    stack.push_back(fValue ? vchTrue : vchFalse);
                }
                break;


                //
                // Crypto
                //
                case OP_RIPEMD160:
                case OP_SHA1:
                case OP_SHA256:
                case OP_HASH160:
                case OP_HASH256:
                {
                    // (in -- hash)
                    if (stack.size() < 1)
                        return false;
                    valtype& vch = stacktop(-1);
                    valtype vchHash((opcode == OP_RIPEMD160 || opcode == OP_SHA1 || opcode == OP_HASH160) ? 20 : 32);
                    if (opcode == OP_RIPEMD160)
                        RIPEMD160(&vch[0], vch.size(), &vchHash[0]);
                    else if (opcode == OP_SHA1)
                        SHA1(&vch[0], vch.size(), &vchHash[0]);
                    else if (opcode == OP_SHA256)
                        SHA256(&vch[0], vch.size(), &vchHash[0]);
                    else if (opcode == OP_HASH160)
                    {
                        uint160 hash160 = Hash160(vch);
                        memcpy(&vchHash[0], &hash160, sizeof(hash160));
                    }
                    else if (opcode == OP_HASH256)
                    {
                        uint256 hash = Hash(vch.begin(), vch.end());
                        memcpy(&vchHash[0], &hash, sizeof(hash));
                    }
                    popstack(stack);
                    stack.push_back(vchHash);
                }
                break;

                case OP_CODESEPARATOR:
                {
                    // Hash starts after the code separator
                    pbegincodehash = pc;
                }
                break;

                case OP_CHECKSIG:
                case OP_CHECKSIGVERIFY:
                {
                    // (sig pubkey -- bool)
                    if (stack.size() < 2)
                        return false;

                    valtype& vchSig    = stacktop(-2);
                    valtype& vchPubKey = stacktop(-1);

                    ////// debug print
                    //PrintHex(vchSig.begin(), vchSig.end(), "sig: %s\n");
                    //PrintHex(vchPubKey.begin(), vchPubKey.end(), "pubkey: %s\n");

                    // Subset of script starting at the most recent codeseparator
                    CScript scriptCode(pbegincodehash, pend);

                    // Drop the signature, since there's no way for a signature to sign itself
                    scriptCode.FindAndDelete(CScript(vchSig));

                    bool fSuccess = CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType);

                    popstack(stack);
                    popstack(stack);
                    stack.push_back(fSuccess ? vchTrue : vchFalse);
                    if (opcode == OP_CHECKSIGVERIFY)
                    {
                        if (fSuccess)
                            popstack(stack);
                        else
                            return false;
                    }
                }
                break;

                case OP_CHECKMULTISIG:
                case OP_CHECKMULTISIGVERIFY:
                {
                    // ([sig ...] num_of_signatures [pubkey ...] num_of_pubkeys -- bool)

                    int i = 1;
                    if (stack.size() < i)
                        return false;

                    int nKeysCount = CastToBigNum(stacktop(-i)).getint();
                    if (nKeysCount < 0 || nKeysCount > 20)
                        return false;
                    nOpCount += nKeysCount;
                    if (nOpCount > 201)
                        return false;
                    int ikey = ++i;
                    i += nKeysCount;
                    if (stack.size() < i)
                        return false;

                    int nSigsCount = CastToBigNum(stacktop(-i)).getint();
                    if (nSigsCount < 0 || nSigsCount > nKeysCount)
                        return false;
                    int isig = ++i;
                    i += nSigsCount;
                    if (stack.size() < i)
                        return false;

                    // Subset of script starting at the most recent codeseparator
                    CScript scriptCode(pbegincodehash, pend);

                    // Drop the signatures, since there's no way for a signature to sign itself
                    for (int k = 0; k < nSigsCount; k++)
                    {
                        valtype& vchSig = stacktop(-isig-k);
                        scriptCode.FindAndDelete(CScript(vchSig));
                    }

                    bool fSuccess = true;
                    while (fSuccess && nSigsCount > 0)
                    {
                        valtype& vchSig    = stacktop(-isig);
                        valtype& vchPubKey = stacktop(-ikey);

                        // Check signature
                        if (CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType))
                        {
                            isig++;
                            nSigsCount--;
                        }
                        ikey++;
                        nKeysCount--;

                        // If there are more signatures left than keys left,
                        // then too many signatures have failed
                        if (nSigsCount > nKeysCount)
                            fSuccess = false;
                    }

                    while (i-- > 0)
                        popstack(stack);
                    stack.push_back(fSuccess ? vchTrue : vchFalse);

                    if (opcode == OP_CHECKMULTISIGVERIFY)
                    {
                        if (fSuccess)
                            popstack(stack);
                        else
                            return false;
                    }
                }
                break;

                default:
                    return false;
            }

            // Size limits
            if (stack.size() + altstack.size() > 1000)
                return false;
        }
    }
    catch (...)
    {
        return false;
    }


    if (!vfExec.empty())
        return false;

    return true;
}
Example #10
0
/**
 * Reconstruct secret using the provided shares
 *
 * @param shares Shares used to reconstruct secret (should contain t entries)
 * @param t Threshold used to reconstruct the secret
 * @param prime Prime for finite field arithmetic
 * @param s Pointer for storage of calculated secred
 */
static int reconstructSecret(secret_share_t *shares, unsigned char t, const BIGNUM prime, BIGNUM *s)
{
	unsigned char i;
	unsigned char j;

	// Array representing the polynomial a(x) = s + a_1 * x + ... + a_n-1 * x^n-1 mod p
	BIGNUM **bValue = malloc(t * sizeof(BIGNUM *));
	BIGNUM **pbValue;
	BIGNUM numerator;
	BIGNUM denominator;
	BIGNUM temp;
	secret_share_t *sp_i;
	secret_share_t *sp_j;
	BN_CTX *ctx;

	// Initialize
	pbValue = bValue;
	for (i = 0; i < t; i++) {
		*pbValue = BN_new();
		BN_init(*pbValue);
		pbValue++;
	}

	BN_init(&numerator);
	BN_init(&denominator);
	BN_init(&temp);

	// Create context for temporary variables of engine
	ctx = BN_CTX_new();
	BN_CTX_init(ctx);

	pbValue = bValue;
	sp_i = shares;
	for (i = 0; i < t; i++) {

		BN_one(&numerator);
		BN_one(&denominator);

		sp_j = shares;

		for (j = 0; j < t; j++) {

			if (i == j) {
				sp_j++;
				continue;
			}

			BN_mul(&numerator, &numerator, &(sp_j->x), ctx);
			BN_sub(&temp, &(sp_j->x), &(sp_i->x));
			BN_mul(&denominator, &denominator, &temp, ctx);

			sp_j++;
		}

		/*
		 * Use the modular inverse value of the denominator for the
		 * multiplication
		 */
		if (BN_mod_inverse(&denominator, &denominator, &prime, ctx) == NULL ) {
			free(bValue);
			return -1;
		}

		BN_mod_mul(*pbValue, &numerator, &denominator, &prime, ctx);

		pbValue++;
		sp_i++;
	}

	/*
	 * Calculate the secret by multiplying all y-values with their
	 * corresponding intermediate values
	 */
	pbValue = bValue;
	sp_i = shares;
	BN_zero(s);
	for (i = 0; i < t; i++) {

		BN_mul(&temp, &(sp_i->y), *pbValue, ctx);
		BN_add(s, s, &temp);
		pbValue++;
		sp_i++;
	}

	// Perform modulo operation and copy result
	BN_nnmod(&temp, s, &prime, ctx);
	BN_copy(s, &temp);

	BN_clear_free(&numerator);
	BN_clear_free(&denominator);
	BN_clear_free(&temp);

	BN_CTX_free(ctx);

	// Deallocate the resource of the polynomial
	pbValue = bValue;
	for (i = 0; i < t; i++) {
		BN_clear_free(*pbValue);
		pbValue++;
	}

	free(bValue);

	return 0;
}
Example #11
0
int generateRingSignature(data_chunk &keyImage, uint256 &txnHash, int nRingSize, int nSecretOffset, ec_secret secret, const uint8_t *pPubkeys, uint8_t *pSigc, uint8_t *pSigr)
{
    if (fDebugRingSig)
        LogPrintf("%s: Ring size %d.\n", __func__, nRingSize);

    int rv = 0;
    int nBytes;

    BN_CTX_start(bnCtx);

    BIGNUM   *bnKS  = BN_CTX_get(bnCtx);
    BIGNUM   *bnK1  = BN_CTX_get(bnCtx);
    BIGNUM   *bnK2  = BN_CTX_get(bnCtx);
    BIGNUM   *bnT   = BN_CTX_get(bnCtx);
    BIGNUM   *bnH   = BN_CTX_get(bnCtx);
    BIGNUM   *bnSum = BN_CTX_get(bnCtx);
    EC_POINT *ptT1  = NULL;
    EC_POINT *ptT2  = NULL;
    EC_POINT *ptT3  = NULL;
    EC_POINT *ptPk  = NULL;
    EC_POINT *ptKi  = NULL;
    EC_POINT *ptL   = NULL;
    EC_POINT *ptR   = NULL;

    uint8_t tempData[66]; // hold raw point data to hash
    uint256 commitHash;
    ec_secret scData1, scData2;

    CHashWriter ssCommitHash(SER_GETHASH, PROTOCOL_VERSION);

    ssCommitHash << txnHash;

    // zero signature
    memset(pSigc, 0, EC_SECRET_SIZE * nRingSize);
    memset(pSigr, 0, EC_SECRET_SIZE * nRingSize);


    // ks = random 256 bit int mod P
    if (GenerateRandomSecret(scData1)
    && (rv = errorN(1, "%s: GenerateRandomSecret failed.", __func__)))
        goto End;

    if (!bnKS || !(BN_bin2bn(&scData1.e[0], EC_SECRET_SIZE, bnKS)))
    {
        LogPrintf("%s: BN_bin2bn failed.\n", __func__);
        rv = 1; goto End;
    };

    // zero sum
    if (!bnSum || !(BN_zero(bnSum)))
    {
        LogPrintf("%s: BN_zero failed.\n", __func__);
        rv = 1; goto End;
    };

    if (   !(ptT1 = EC_POINT_new(ecGrp))
        || !(ptT2 = EC_POINT_new(ecGrp))
        || !(ptT3 = EC_POINT_new(ecGrp))
        || !(ptPk = EC_POINT_new(ecGrp))
        || !(ptKi = EC_POINT_new(ecGrp))
        || !(ptL  = EC_POINT_new(ecGrp))
        || !(ptR  = EC_POINT_new(ecGrp)))
    {
        LogPrintf("%s: EC_POINT_new failed.\n", __func__);
        rv = 1; goto End;
    };

    // get keyimage as point
    if (!(bnT = BN_bin2bn(&keyImage[0], EC_COMPRESSED_SIZE, bnT))
        || !(ptKi) || !(ptKi = EC_POINT_bn2point(ecGrp, bnT, ptKi, bnCtx)))
    {
        LogPrintf("%s: extract ptKi failed.\n", __func__);
        rv = 1; goto End;
    };

    for (int i = 0; i < nRingSize; ++i)
    {
        if (i == nSecretOffset)
        {
            // k = random 256 bit int mod P
            // L = k * G
            // R = k * HashToEC(PKi)

            if (!EC_POINT_mul(ecGrp, ptL, bnKS, NULL, NULL, bnCtx))
            {
                LogPrintf("%s: EC_POINT_mul failed.\n", __func__);
                rv = 1; goto End;
            };

            if (hashToEC(&pPubkeys[i * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnT, ptT1) != 0)
            {
                LogPrintf("%s: hashToEC failed.\n", __func__);
                rv = 1; goto End;
            };

            if (!EC_POINT_mul(ecGrp, ptR, NULL, ptT1, bnKS, bnCtx))
            {
                LogPrintf("%s: EC_POINT_mul failed.\n", __func__);
                rv = 1; goto End;
            };

        } else
        {
            // k1 = random 256 bit int mod P
            // k2 = random 256 bit int mod P
            // Li = k1 * Pi + k2 * G
            // Ri = k1 * I + k2 * Hp(Pi)
            // ci = k1
            // ri = k2

            if (GenerateRandomSecret(scData1) != 0
                || !bnK1 || !(BN_bin2bn(&scData1.e[0], EC_SECRET_SIZE, bnK1))
                || GenerateRandomSecret(scData2) != 0
                || !bnK2 || !(BN_bin2bn(&scData2.e[0], EC_SECRET_SIZE, bnK2)))
            {
                LogPrintf("%s: k1 and k2 failed.\n", __func__);
                rv = 1; goto End;
            };

            // get Pk i as point
            if (!(bnT = BN_bin2bn(&pPubkeys[i * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnT))
                || !(ptPk) || !(ptPk = EC_POINT_bn2point(ecGrp, bnT, ptPk, bnCtx)))
            {
                LogPrintf("%s: extract ptPk failed.\n", __func__);
                rv = 1; goto End;
            };

            // ptT1 = k1 * Pi
            if (!EC_POINT_mul(ecGrp, ptT1, NULL, ptPk, bnK1, bnCtx))
            {
                LogPrintf("%s: EC_POINT_mul failed.\n", __func__);
                rv = 1; goto End;
            };

            // ptT2 = k2 * G
            if (!EC_POINT_mul(ecGrp, ptT2, bnK2, NULL, NULL, bnCtx))
            {
                LogPrintf("%s: EC_POINT_mul failed.\n", __func__);
                rv = 1; goto End;
            };

            // ptL = ptT1 + ptT2
            if (!EC_POINT_add(ecGrp, ptL, ptT1, ptT2, bnCtx))
            {
                LogPrintf("%s: EC_POINT_add failed.\n", __func__);
                rv = 1; goto End;
            };

            // ptT3 = Hp(Pi)
            if (hashToEC(&pPubkeys[i * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnT, ptT3) != 0)
            {
                LogPrintf("%s: hashToEC failed.\n", __func__);
                rv = 1; goto End;
            };

            // ptT1 = k1 * I
            if (!EC_POINT_mul(ecGrp, ptT1, NULL, ptKi, bnK1, bnCtx))
            {
                LogPrintf("%s: EC_POINT_mul failed.\n", __func__);
                rv = 1; goto End;
            };

            // ptT2 = k2 * ptT3
            if (!EC_POINT_mul(ecGrp, ptT2, NULL, ptT3, bnK2, bnCtx))
            {
                LogPrintf("%s: EC_POINT_mul failed.\n", __func__);
                rv = 1; goto End;
            };

            // ptR = ptT1 + ptT2
            if (!EC_POINT_add(ecGrp, ptR, ptT1, ptT2, bnCtx))
            {
                LogPrintf("%s: EC_POINT_add failed.\n", __func__);
                rv = 1; goto End;
            };

            memcpy(&pSigc[i * EC_SECRET_SIZE], &scData1.e[0], EC_SECRET_SIZE);
            memcpy(&pSigr[i * EC_SECRET_SIZE], &scData2.e[0], EC_SECRET_SIZE);

            // sum = (sum + sigc) % N , sigc == bnK1
            if (!BN_mod_add(bnSum, bnSum, bnK1, bnOrder, bnCtx))
            {
                LogPrintf("%s: BN_mod_add failed.\n", __func__);
                rv = 1; goto End;
            };
        };

        // -- add ptL and ptR to hash
        if (   !(EC_POINT_point2oct(ecGrp, ptL, POINT_CONVERSION_COMPRESSED, &tempData[0],  33, bnCtx) == (int) EC_COMPRESSED_SIZE)
            || !(EC_POINT_point2oct(ecGrp, ptR, POINT_CONVERSION_COMPRESSED, &tempData[33], 33, bnCtx) == (int) EC_COMPRESSED_SIZE))
        {
            LogPrintf("%s: extract ptL and ptR failed.\n", __func__);
            rv = 1; goto End;
        };

        ssCommitHash.write((const char*)&tempData[0], 66);
    };

    commitHash = ssCommitHash.GetHash();

    if (!(bnH) || !(bnH = BN_bin2bn(commitHash.begin(), EC_SECRET_SIZE, bnH)))
    {
        LogPrintf("%s: commitHash -> bnH failed.\n", __func__);
        rv = 1; goto End;
    };


    if (!BN_mod(bnH, bnH, bnOrder, bnCtx)) // this is necessary
    {
        LogPrintf("%s: BN_mod failed.\n", __func__);
        rv = 1; goto End;
    };

    // sigc[nSecretOffset] = (bnH - bnSum) % N
    if (!BN_mod_sub(bnT, bnH, bnSum, bnOrder, bnCtx))
    {
        LogPrintf("%s: BN_mod_sub failed.\n", __func__);
        rv = 1; goto End;
    };

    if ((nBytes = BN_num_bytes(bnT)) > (int)EC_SECRET_SIZE
        || BN_bn2bin(bnT, &pSigc[nSecretOffset * EC_SECRET_SIZE + (EC_SECRET_SIZE-nBytes)]) != nBytes)
    {
        LogPrintf("%s: bnT -> pSigc failed.\n", __func__);
        rv = 1; goto End;
    };

    // sigr[nSecretOffset] = (bnKS - sigc[nSecretOffset] * bnSecret) % N
    // reuse bnH for bnSecret
    if (!bnH || !(BN_bin2bn(&secret.e[0], EC_SECRET_SIZE, bnH)))
    {
        LogPrintf("%s: BN_bin2bn failed.\n", __func__);
        rv = 1; goto End;
    };

    // bnT = sigc[nSecretOffset] * bnSecret , TODO: mod N ?
    if (!BN_mul(bnT, bnT, bnH, bnCtx))
    {
        LogPrintf("%s: BN_mul failed.\n", __func__);
        rv = 1; goto End;
    };

    if (!BN_mod_sub(bnT, bnKS, bnT, bnOrder, bnCtx))
    {
        LogPrintf("%s: BN_mod_sub failed.\n", __func__);
        rv = 1; goto End;
    };

    if ((nBytes = BN_num_bytes(bnT)) > (int) EC_SECRET_SIZE
        || BN_bn2bin(bnT, &pSigr[nSecretOffset * EC_SECRET_SIZE + (EC_SECRET_SIZE-nBytes)]) != nBytes)
    {
        LogPrintf("%s: bnT -> pSigr failed.\n", __func__);
        rv = 1; goto End;
    };

    End:
    EC_POINT_free(ptT1);
    EC_POINT_free(ptT2);
    EC_POINT_free(ptT3);
    EC_POINT_free(ptPk);
    EC_POINT_free(ptKi);
    EC_POINT_free(ptL);
    EC_POINT_free(ptR);

    BN_CTX_end(bnCtx);

    return rv;
};
Example #12
0
int BN_div_recp(BIGNUM *dv, BIGNUM *rem, BIGNUM *m, BN_RECP_CTX *recp,
	     BN_CTX *ctx)
	{
	int i,j,ret=0;
	BIGNUM *a,*b,*d,*r;

	BN_CTX_start(ctx);
	a=BN_CTX_get(ctx);
	b=BN_CTX_get(ctx);
	if (dv != NULL)
		d=dv;
	else
		d=BN_CTX_get(ctx);
	if (rem != NULL)
		r=rem;
	else
		r=BN_CTX_get(ctx);
	if (a == NULL || b == NULL || d == NULL || r == NULL) goto err;

	if (BN_ucmp(m,&(recp->N)) < 0)
		{
		BN_zero(d);
		BN_copy(r,m);
		BN_CTX_end(ctx);
		return(1);
		}

	/* We want the remainder
	 * Given input of ABCDEF / ab
	 * we need multiply ABCDEF by 3 digests of the reciprocal of ab
	 *
	 */
	i=BN_num_bits(m);

	j=recp->num_bits<<1;
	if (j>i) i=j;
	j>>=1;

	if (i != recp->shift)
		recp->shift=BN_reciprocal(&(recp->Nr),&(recp->N),
			i,ctx);

	if (!BN_rshift(a,m,j)) goto err;
	if (!BN_mul(b,a,&(recp->Nr),ctx)) goto err;
	if (!BN_rshift(d,b,i-j)) goto err;
	d->neg=0;
	if (!BN_mul(b,&(recp->N),d,ctx)) goto err;
	if (!BN_usub(r,m,b)) goto err;
	r->neg=0;

#if 1
	j=0;
	while (BN_ucmp(r,&(recp->N)) >= 0)
		{
		if (j++ > 2)
			{
			BNerr(BN_F_BN_MOD_MUL_RECIPROCAL,BN_R_BAD_RECIPROCAL);
			goto err;
			}
		if (!BN_usub(r,r,&(recp->N))) goto err;
		if (!BN_add_word(d,1)) goto err;
		}
#endif

	r->neg=BN_is_zero(r)?0:m->neg;
	d->neg=m->neg^recp->N.neg;
	ret=1;
err:
	BN_CTX_end(ctx);
	return(ret);
	} 
Example #13
0
int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont,
	     BN_CTX *ctx)
	{
	int retn=0;

#ifdef MONT_WORD
	BIGNUM *n,*r;
	BN_ULONG *ap,*np,*rp,n0,v,*nrp;
	int al,nl,max,i,x,ri;

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

	if (!BN_copy(r,a)) goto err;
	n= &(mont->N);

	ap=a->d;
	/* mont->ri is the size of mont->N in bits (rounded up
	   to the word size) */
	al=ri=mont->ri/BN_BITS2;
	
	nl=n->top;
	if ((al == 0) || (nl == 0)) { r->top=0; return(1); }

	max=(nl+al+1); /* allow for overflow (no?) XXX */
	if (bn_wexpand(r,max) == NULL) goto err;
	if (bn_wexpand(ret,max) == NULL) goto err;

	r->neg=a->neg^n->neg;
	np=n->d;
	rp=r->d;
	nrp= &(r->d[nl]);

	/* clear the top words of T */
#if 1
	for (i=r->top; i<max; i++) /* memset? XXX */
		r->d[i]=0;
#else
	memset(&(r->d[r->top]),0,(max-r->top)*sizeof(BN_ULONG)); 
#endif

	r->top=max;
	n0=mont->n0;

#ifdef BN_COUNT
	fprintf(stderr,"word BN_from_montgomery %d * %d\n",nl,nl);
#endif
	for (i=0; i<nl; i++)
		{
#ifdef __TANDEM
                {
                   long long t1;
                   long long t2;
                   long long t3;
                   t1 = rp[0] * (n0 & 0177777);
                   t2 = 037777600000l;
                   t2 = n0 & t2;
                   t3 = rp[0] & 0177777;
                   t2 = (t3 * t2) & BN_MASK2;
                   t1 = t1 + t2;
                   v=bn_mul_add_words(rp,np,nl,(BN_ULONG) t1);
                }
#else
		v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2);
#endif
		nrp++;
		rp++;
		if (((nrp[-1]+=v)&BN_MASK2) >= v)
			continue;
		else
			{
			if (((++nrp[0])&BN_MASK2) != 0) continue;
			if (((++nrp[1])&BN_MASK2) != 0) continue;
			for (x=2; (((++nrp[x])&BN_MASK2) == 0); x++) ;
			}
		}
	bn_correct_top(r);
	
	/* mont->ri will be a multiple of the word size */
#if 0
	BN_rshift(ret,r,mont->ri);
#else
	ret->neg = r->neg;
	x=ri;
	rp=ret->d;
	ap= &(r->d[x]);
	if (r->top < x)
		al=0;
	else
		al=r->top-x;
	ret->top=al;
	al-=4;
	for (i=0; i<al; i+=4)
		{
		BN_ULONG t1,t2,t3,t4;
		
		t1=ap[i+0];
		t2=ap[i+1];
		t3=ap[i+2];
		t4=ap[i+3];
		rp[i+0]=t1;
		rp[i+1]=t2;
		rp[i+2]=t3;
		rp[i+3]=t4;
		}
	al+=4;
	for (; i<al; i++)
		rp[i]=ap[i];
#endif
#else /* !MONT_WORD */ 
	BIGNUM *t1,*t2;

	BN_CTX_start(ctx);
	t1 = BN_CTX_get(ctx);
	t2 = BN_CTX_get(ctx);
	if (t1 == NULL || t2 == NULL) goto err;
	
	if (!BN_copy(t1,a)) goto err;
	BN_mask_bits(t1,mont->ri);

	if (!BN_mul(t2,t1,&mont->Ni,ctx)) goto err;
	BN_mask_bits(t2,mont->ri);

	if (!BN_mul(t1,t2,&mont->N,ctx)) goto err;
	if (!BN_add(t2,a,t1)) goto err;
	if (!BN_rshift(ret,t2,mont->ri)) goto err;
#endif /* MONT_WORD */

	if (BN_ucmp(ret, &(mont->N)) >= 0)
		{
		if (!BN_usub(ret,ret,&(mont->N))) goto err;
		}
	retn=1;
	bn_check_top(ret);
 err:
	BN_CTX_end(ctx);
	return(retn);
	}
Example #14
0
int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont,
	     BN_CTX *ctx)
	{
	int retn=0;

#ifdef MONT_WORD
	BIGNUM *n,*r;
	BN_ULONG *ap,*np,*rp,n0,v,*nrp;
	int al,nl,max,i,x,ri;

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

	if (!BN_copy(r,a)) goto err;
	n= &(mont->N);

	ap=a->d;
	/* mont->ri is the size of mont->N in bits (rounded up
	   to the word size) */
	al=ri=mont->ri/BN_BITS2;
	
	nl=n->top;
	if ((al == 0) || (nl == 0)) { r->top=0; return(1); }

	max=(nl+al+1); /* allow for overflow (no?) XXX */
	if (bn_wexpand(r,max) == NULL) goto err;

	r->neg=a->neg^n->neg;
	np=n->d;
	rp=r->d;
	nrp= &(r->d[nl]);

	/* clear the top words of T */
#if 1
	for (i=r->top; i<max; i++) /* memset? XXX */
		r->d[i]=0;
#else
	memset(&(r->d[r->top]),0,(max-r->top)*sizeof(BN_ULONG)); 
#endif

	r->top=max;
	n0=mont->n0;

#ifdef BN_COUNT
	fprintf(stderr,"word BN_from_montgomery %d * %d\n",nl,nl);
#endif
	for (i=0; i<nl; i++)
		{
#ifdef __TANDEM
                {
                   long long t1;
                   long long t2;
                   long long t3;
                   t1 = rp[0] * (n0 & 0177777);
                   t2 = 037777600000l;
                   t2 = n0 & t2;
                   t3 = rp[0] & 0177777;
                   t2 = (t3 * t2) & BN_MASK2;
                   t1 = t1 + t2;
                   v=bn_mul_add_words(rp,np,nl,(BN_ULONG) t1);
                }
#else
		v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2);
#endif
		nrp++;
		rp++;
		if (((nrp[-1]+=v)&BN_MASK2) >= v)
			continue;
		else
			{
			if (((++nrp[0])&BN_MASK2) != 0) continue;
			if (((++nrp[1])&BN_MASK2) != 0) continue;
			for (x=2; (((++nrp[x])&BN_MASK2) == 0); x++) ;
			}
		}
	bn_correct_top(r);
	
	/* mont->ri will be a multiple of the word size and below code
	 * is kind of BN_rshift(ret,r,mont->ri) equivalent */
	if (r->top <= ri)
		{
		ret->top=0;
		retn=1;
		goto err;
		}
	al=r->top-ri;

# define BRANCH_FREE 1
# if BRANCH_FREE
	if (bn_wexpand(ret,ri) == NULL) goto err;
	x=0-(((al-ri)>>(sizeof(al)*8-1))&1);
	ret->top=x=(ri&~x)|(al&x);	/* min(ri,al) */
	ret->neg=r->neg;

	rp=ret->d;
	ap=&(r->d[ri]);

	{
	size_t m1,m2;

	v=bn_sub_words(rp,ap,np,ri);
	/* this ----------------^^ works even in al<ri case
	 * thanks to zealous zeroing of top of the vector in the
	 * beginning. */

	/* if (al==ri && !v) || al>ri) nrp=rp; else nrp=ap; */
	/* in other words if subtraction result is real, then
	 * trick unconditional memcpy below to perform in-place
	 * "refresh" instead of actual copy. */
	m1=0-(size_t)(((al-ri)>>(sizeof(al)*8-1))&1);	/* al<ri */
	m2=0-(size_t)(((ri-al)>>(sizeof(al)*8-1))&1);	/* al>ri */
	m1|=m2;			/* (al!=ri) */
	m1|=(0-(size_t)v);	/* (al!=ri || v) */
	m1&=~m2;		/* (al!=ri || v) && !al>ri */
	nrp=(BN_ULONG *)(((size_t)rp&~m1)|((size_t)ap&m1));
	}

	/* 'i<ri' is chosen to eliminate dependency on input data, even
	 * though it results in redundant copy in al<ri case. */
	for (i=0,ri-=4; i<ri; i+=4)
		{
		BN_ULONG t1,t2,t3,t4;
		
		t1=nrp[i+0];
		t2=nrp[i+1];
		t3=nrp[i+2];	ap[i+0]=0;
		t4=nrp[i+3];	ap[i+1]=0;
		rp[i+0]=t1;	ap[i+2]=0;
		rp[i+1]=t2;	ap[i+3]=0;
		rp[i+2]=t3;
		rp[i+3]=t4;
		}
	for (ri+=4; i<ri; i++)
		rp[i]=nrp[i], ap[i]=0;
	bn_correct_top(r);
	bn_correct_top(ret);
# else
	if (bn_wexpand(ret,al) == NULL) goto err;
	ret->top=al;
	ret->neg=r->neg;

	rp=ret->d;
	ap=&(r->d[ri]);
	al-=4;
	for (i=0; i<al; i+=4)
		{
		BN_ULONG t1,t2,t3,t4;
		
		t1=ap[i+0];
		t2=ap[i+1];
		t3=ap[i+2];
		t4=ap[i+3];
		rp[i+0]=t1;
		rp[i+1]=t2;
		rp[i+2]=t3;
		rp[i+3]=t4;
		}
	al+=4;
	for (; i<al; i++)
		rp[i]=ap[i];
# endif
#else /* !MONT_WORD */ 
	BIGNUM *t1,*t2;

	BN_CTX_start(ctx);
	t1 = BN_CTX_get(ctx);
	t2 = BN_CTX_get(ctx);
	if (t1 == NULL || t2 == NULL) goto err;
	
	if (!BN_copy(t1,a)) goto err;
	BN_mask_bits(t1,mont->ri);

	if (!BN_mul(t2,t1,&mont->Ni,ctx)) goto err;
	BN_mask_bits(t2,mont->ri);

	if (!BN_mul(t1,t2,&mont->N,ctx)) goto err;
	if (!BN_add(t2,a,t1)) goto err;
	if (!BN_rshift(ret,t2,mont->ri)) goto err;
#endif /* MONT_WORD */

#if !defined(BRANCH_FREE) || BRANCH_FREE==0
	if (BN_ucmp(ret, &(mont->N)) >= 0)
		{
		if (!BN_usub(ret,ret,&(mont->N))) goto err;
		}
#endif
	retn=1;
	bn_check_top(ret);
 err:
	BN_CTX_end(ctx);
	return(retn);
	}
Example #15
0
static int keygen_multiprime(RSA *rsa, int bits, int num_primes,
                             BIGNUM *e_value, BN_GENCB *cb) {
  BIGNUM *r0 = NULL, *r1 = NULL, *r2 = NULL, *r3 = NULL, *tmp;
  BIGNUM local_r0, local_d, local_p;
  BIGNUM *pr0, *d, *p;
  int prime_bits, ok = -1, n = 0, i, j;
  BN_CTX *ctx = NULL;
  STACK_OF(RSA_additional_prime) *additional_primes = NULL;

  if (num_primes < 2) {
    ok = 0; /* we set our own err */
    OPENSSL_PUT_ERROR(RSA, RSA_R_MUST_HAVE_AT_LEAST_TWO_PRIMES);
    goto err;
  }

  ctx = BN_CTX_new();
  if (ctx == NULL) {
    goto err;
  }
  BN_CTX_start(ctx);
  r0 = BN_CTX_get(ctx);
  r1 = BN_CTX_get(ctx);
  r2 = BN_CTX_get(ctx);
  r3 = BN_CTX_get(ctx);
  if (r0 == NULL || r1 == NULL || r2 == NULL || r3 == NULL) {
    goto err;
  }

  if (num_primes > 2) {
    additional_primes = sk_RSA_additional_prime_new_null();
    if (additional_primes == NULL) {
      goto err;
    }
  }

  for (i = 2; i < num_primes; i++) {
    RSA_additional_prime *ap = OPENSSL_malloc(sizeof(RSA_additional_prime));
    if (ap == NULL) {
      goto err;
    }
    memset(ap, 0, sizeof(RSA_additional_prime));
    ap->prime = BN_new();
    ap->exp = BN_new();
    ap->coeff = BN_new();
    ap->r = BN_new();
    if (ap->prime == NULL ||
        ap->exp == NULL ||
        ap->coeff == NULL ||
        ap->r == NULL ||
        !sk_RSA_additional_prime_push(additional_primes, ap)) {
      RSA_additional_prime_free(ap);
      goto err;
    }
  }

  /* We need the RSA components non-NULL */
  if (!rsa->n && ((rsa->n = BN_new()) == NULL)) {
    goto err;
  }
  if (!rsa->d && ((rsa->d = BN_new()) == NULL)) {
    goto err;
  }
  if (!rsa->e && ((rsa->e = BN_new()) == NULL)) {
    goto err;
  }
  if (!rsa->p && ((rsa->p = BN_new()) == NULL)) {
    goto err;
  }
  if (!rsa->q && ((rsa->q = BN_new()) == NULL)) {
    goto err;
  }
  if (!rsa->dmp1 && ((rsa->dmp1 = BN_new()) == NULL)) {
    goto err;
  }
  if (!rsa->dmq1 && ((rsa->dmq1 = BN_new()) == NULL)) {
    goto err;
  }
  if (!rsa->iqmp && ((rsa->iqmp = BN_new()) == NULL)) {
    goto err;
  }

  if (!BN_copy(rsa->e, e_value)) {
    goto err;
  }

  /* generate p and q */
  prime_bits = (bits + (num_primes - 1)) / num_primes;
  for (;;) {
    if (!BN_generate_prime_ex(rsa->p, prime_bits, 0, NULL, NULL, cb) ||
        !BN_sub(r2, rsa->p, BN_value_one()) ||
        !BN_gcd(r1, r2, rsa->e, ctx)) {
      goto err;
    }
    if (BN_is_one(r1)) {
      break;
    }
    if (!BN_GENCB_call(cb, 2, n++)) {
      goto err;
    }
  }
  if (!BN_GENCB_call(cb, 3, 0)) {
    goto err;
  }
  prime_bits = ((bits - prime_bits) + (num_primes - 2)) / (num_primes - 1);
  for (;;) {
    /* When generating ridiculously small keys, we can get stuck
     * continually regenerating the same prime values. Check for
     * this and bail if it happens 3 times. */
    unsigned int degenerate = 0;
    do {
      if (!BN_generate_prime_ex(rsa->q, prime_bits, 0, NULL, NULL, cb)) {
        goto err;
      }
    } while ((BN_cmp(rsa->p, rsa->q) == 0) && (++degenerate < 3));
    if (degenerate == 3) {
      ok = 0; /* we set our own err */
      OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
      goto err;
    }
    if (!BN_sub(r2, rsa->q, BN_value_one()) ||
        !BN_gcd(r1, r2, rsa->e, ctx)) {
      goto err;
    }
    if (BN_is_one(r1)) {
      break;
    }
    if (!BN_GENCB_call(cb, 2, n++)) {
      goto err;
    }
  }

  if (!BN_GENCB_call(cb, 3, 1) ||
      !BN_mul(rsa->n, rsa->p, rsa->q, ctx)) {
    goto err;
  }

  for (i = 2; i < num_primes; i++) {
    RSA_additional_prime *ap =
        sk_RSA_additional_prime_value(additional_primes, i - 2);
    prime_bits = ((bits - BN_num_bits(rsa->n)) + (num_primes - (i + 1))) /
                 (num_primes - i);

    for (;;) {
      if (!BN_generate_prime_ex(ap->prime, prime_bits, 0, NULL, NULL, cb)) {
        goto err;
      }
      if (BN_cmp(rsa->p, ap->prime) == 0 ||
          BN_cmp(rsa->q, ap->prime) == 0) {
        continue;
      }

      for (j = 0; j < i - 2; j++) {
        if (BN_cmp(sk_RSA_additional_prime_value(additional_primes, j)->prime,
                   ap->prime) == 0) {
          break;
        }
      }
      if (j != i - 2) {
        continue;
      }

      if (!BN_sub(r2, ap->prime, BN_value_one()) ||
          !BN_gcd(r1, r2, rsa->e, ctx)) {
        goto err;
      }

      if (!BN_is_one(r1)) {
        continue;
      }
      if (i != num_primes - 1) {
        break;
      }

      /* For the last prime we'll check that it makes n large enough. In the
       * two prime case this isn't a problem because we generate primes with
       * the top two bits set and so the product is always of the expected
       * size. In the multi prime case, this doesn't follow. */
      if (!BN_mul(r1, rsa->n, ap->prime, ctx)) {
        goto err;
      }
      if (BN_num_bits(r1) == bits) {
        break;
      }

      if (!BN_GENCB_call(cb, 2, n++)) {
        goto err;
      }
    }

    /* ap->r is is the product of all the primes prior to the current one
     * (including p and q). */
    if (!BN_copy(ap->r, rsa->n)) {
      goto err;
    }
    if (i == num_primes - 1) {
      /* In the case of the last prime, we calculated n as |r1| in the loop
       * above. */
      if (!BN_copy(rsa->n, r1)) {
        goto err;
      }
    } else if (!BN_mul(rsa->n, rsa->n, ap->prime, ctx)) {
      goto err;
    }

    if (!BN_GENCB_call(cb, 3, 1)) {
      goto err;
    }
  }

  if (BN_cmp(rsa->p, rsa->q) < 0) {
    tmp = rsa->p;
    rsa->p = rsa->q;
    rsa->q = tmp;
  }

  /* calculate d */
  if (!BN_sub(r1, rsa->p, BN_value_one())) {
    goto err; /* p-1 */
  }
  if (!BN_sub(r2, rsa->q, BN_value_one())) {
    goto err; /* q-1 */
  }
  if (!BN_mul(r0, r1, r2, ctx)) {
    goto err; /* (p-1)(q-1) */
  }
  for (i = 2; i < num_primes; i++) {
    RSA_additional_prime *ap =
        sk_RSA_additional_prime_value(additional_primes, i - 2);
    if (!BN_sub(r3, ap->prime, BN_value_one()) ||
        !BN_mul(r0, r0, r3, ctx)) {
      goto err;
    }
  }
  pr0 = &local_r0;
  BN_with_flags(pr0, r0, BN_FLG_CONSTTIME);
  if (!BN_mod_inverse(rsa->d, rsa->e, pr0, ctx)) {
    goto err; /* d */
  }

  /* set up d for correct BN_FLG_CONSTTIME flag */
  d = &local_d;
  BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);

  /* calculate d mod (p-1) */
  if (!BN_mod(rsa->dmp1, d, r1, ctx)) {
    goto err;
  }

  /* calculate d mod (q-1) */
  if (!BN_mod(rsa->dmq1, d, r2, ctx)) {
    goto err;
  }

  /* calculate inverse of q mod p */
  p = &local_p;
  BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME);

  if (!BN_mod_inverse(rsa->iqmp, rsa->q, p, ctx)) {
    goto err;
  }

  for (i = 2; i < num_primes; i++) {
    RSA_additional_prime *ap =
        sk_RSA_additional_prime_value(additional_primes, i - 2);
    if (!BN_sub(ap->exp, ap->prime, BN_value_one()) ||
        !BN_mod(ap->exp, rsa->d, ap->exp, ctx) ||
        !BN_mod_inverse(ap->coeff, ap->r, ap->prime, ctx)) {
      goto err;
    }
  }

  ok = 1;
  rsa->additional_primes = additional_primes;
  additional_primes = NULL;

err:
  if (ok == -1) {
    OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN);
    ok = 0;
  }
  if (ctx != NULL) {
    BN_CTX_end(ctx);
    BN_CTX_free(ctx);
  }
  sk_RSA_additional_prime_pop_free(additional_primes,
                                   RSA_additional_prime_free);
  return ok;
}
Example #16
0
static int keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) {
  BIGNUM *r0 = NULL, *r1 = NULL, *r2 = NULL, *r3 = NULL, *tmp;
  BIGNUM local_r0, local_d, local_p;
  BIGNUM *pr0, *d, *p;
  int bitsp, bitsq, ok = -1, n = 0;
  BN_CTX *ctx = NULL;

  ctx = BN_CTX_new();
  if (ctx == NULL) {
    goto err;
  }
  BN_CTX_start(ctx);
  r0 = BN_CTX_get(ctx);
  r1 = BN_CTX_get(ctx);
  r2 = BN_CTX_get(ctx);
  r3 = BN_CTX_get(ctx);
  if (r3 == NULL) {
    goto err;
  }

  bitsp = (bits + 1) / 2;
  bitsq = bits - bitsp;

  /* We need the RSA components non-NULL */
  if (!rsa->n && ((rsa->n = BN_new()) == NULL))
    goto err;
  if (!rsa->d && ((rsa->d = BN_new()) == NULL))
    goto err;
  if (!rsa->e && ((rsa->e = BN_new()) == NULL))
    goto err;
  if (!rsa->p && ((rsa->p = BN_new()) == NULL))
    goto err;
  if (!rsa->q && ((rsa->q = BN_new()) == NULL))
    goto err;
  if (!rsa->dmp1 && ((rsa->dmp1 = BN_new()) == NULL))
    goto err;
  if (!rsa->dmq1 && ((rsa->dmq1 = BN_new()) == NULL))
    goto err;
  if (!rsa->iqmp && ((rsa->iqmp = BN_new()) == NULL))
    goto err;

  BN_copy(rsa->e, e_value);

  /* generate p and q */
  for (;;) {
    if (!BN_generate_prime_ex(rsa->p, bitsp, 0, NULL, NULL, cb))
      goto err;
    if (!BN_sub(r2, rsa->p, BN_value_one()))
      goto err;
    if (!BN_gcd(r1, r2, rsa->e, ctx))
      goto err;
    if (BN_is_one(r1))
      break;
    if (!BN_GENCB_call(cb, 2, n++))
      goto err;
  }
  if (!BN_GENCB_call(cb, 3, 0))
    goto err;
  for (;;) {
    /* When generating ridiculously small keys, we can get stuck
     * continually regenerating the same prime values. Check for
     * this and bail if it happens 3 times. */
    unsigned int degenerate = 0;
    do {
      if (!BN_generate_prime_ex(rsa->q, bitsq, 0, NULL, NULL, cb))
        goto err;
    } while ((BN_cmp(rsa->p, rsa->q) == 0) && (++degenerate < 3));
    if (degenerate == 3) {
      ok = 0; /* we set our own err */
      OPENSSL_PUT_ERROR(RSA, keygen, RSA_R_KEY_SIZE_TOO_SMALL);
      goto err;
    }
    if (!BN_sub(r2, rsa->q, BN_value_one()))
      goto err;
    if (!BN_gcd(r1, r2, rsa->e, ctx))
      goto err;
    if (BN_is_one(r1))
      break;
    if (!BN_GENCB_call(cb, 2, n++))
      goto err;
  }
  if (!BN_GENCB_call(cb, 3, 1))
    goto err;
  if (BN_cmp(rsa->p, rsa->q) < 0) {
    tmp = rsa->p;
    rsa->p = rsa->q;
    rsa->q = tmp;
  }

  /* calculate n */
  if (!BN_mul(rsa->n, rsa->p, rsa->q, ctx))
    goto err;

  /* calculate d */
  if (!BN_sub(r1, rsa->p, BN_value_one()))
    goto err; /* p-1 */
  if (!BN_sub(r2, rsa->q, BN_value_one()))
    goto err; /* q-1 */
  if (!BN_mul(r0, r1, r2, ctx))
    goto err; /* (p-1)(q-1) */
  pr0 = &local_r0;
  BN_with_flags(pr0, r0, BN_FLG_CONSTTIME);
  if (!BN_mod_inverse(rsa->d, rsa->e, pr0, ctx))
    goto err; /* d */

  /* set up d for correct BN_FLG_CONSTTIME flag */
  d = &local_d;
  BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);

  /* calculate d mod (p-1) */
  if (!BN_mod(rsa->dmp1, d, r1, ctx))
    goto err;

  /* calculate d mod (q-1) */
  if (!BN_mod(rsa->dmq1, d, r2, ctx))
    goto err;

  /* calculate inverse of q mod p */
  p = &local_p;
  BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME);

  if (!BN_mod_inverse(rsa->iqmp, rsa->q, p, ctx))
    goto err;

  ok = 1;

err:
  if (ok == -1) {
    OPENSSL_PUT_ERROR(RSA, keygen, ERR_LIB_BN);
    ok = 0;
  }
  if (ctx != NULL) {
    BN_CTX_end(ctx);
    BN_CTX_free(ctx);
  }

  return ok;
}
Example #17
0
int BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m,
	BN_RECP_CTX *recp, BN_CTX *ctx)
	{
	int i,j,ret=0;
	BIGNUM *a,*b,*d,*r;

	BN_CTX_start(ctx);
	a=BN_CTX_get(ctx);
	b=BN_CTX_get(ctx);
	if (dv != NULL)
		d=dv;
	else
		d=BN_CTX_get(ctx);
	if (rem != NULL)
		r=rem;
	else
		r=BN_CTX_get(ctx);
	if (a == NULL || b == NULL || d == NULL || r == NULL) goto err;

	if (BN_ucmp(m,&(recp->N)) < 0)
		{
		if (!BN_zero(d)) return 0;
		if (!BN_copy(r,m)) return 0;
		BN_CTX_end(ctx);
		return(1);
		}

	/* We want the remainder
	 * Given input of ABCDEF / ab
	 * we need multiply ABCDEF by 3 digests of the reciprocal of ab
	 *
	 */

	/* i := max(BN_num_bits(m), 2*BN_num_bits(N)) */
	i=BN_num_bits(m);
	j=recp->num_bits<<1;
	if (j>i) i=j;

	/* Nr := round(2^i / N) */
	if (i != recp->shift)
		recp->shift=BN_reciprocal(&(recp->Nr),&(recp->N),
			i,ctx); /* BN_reciprocal returns i, or -1 for an error */
	if (recp->shift == -1) goto err;

	/* d := |round(round(m / 2^BN_num_bits(N)) * recp->Nr / 2^(i - BN_num_bits(N)))|
	 *    = |round(round(m / 2^BN_num_bits(N)) * round(2^i / N) / 2^(i - BN_num_bits(N)))|
	 *   <= |(m / 2^BN_num_bits(N)) * (2^i / N) * (2^BN_num_bits(N) / 2^i)|
	 *    = |m/N|
	 */
	if (!BN_rshift(a,m,recp->num_bits)) goto err;
	if (!BN_mul(b,a,&(recp->Nr),ctx)) goto err;
	if (!BN_rshift(d,b,i-recp->num_bits)) goto err;
	d->neg=0;

	if (!BN_mul(b,&(recp->N),d,ctx)) goto err;
	if (!BN_usub(r,m,b)) goto err;
	r->neg=0;

#if 1
	j=0;
	while (BN_ucmp(r,&(recp->N)) >= 0)
		{
		if (j++ > 2)
			{
			BNerr(BN_F_BN_MOD_MUL_RECIPROCAL,BN_R_BAD_RECIPROCAL);
			goto err;
			}
		if (!BN_usub(r,r,&(recp->N))) goto err;
		if (!BN_add_word(d,1)) goto err;
		}
#endif

	r->neg=BN_is_zero(r)?0:m->neg;
	d->neg=m->neg^recp->N.neg;
	ret=1;
err:
	BN_CTX_end(ctx);
	return(ret);
	}
Example #18
0
/* BN_mod_inverse_no_branch is a special version of BN_mod_inverse. 
 * It does not contain branches that may leak sensitive information.
 */
static BIGNUM *BN_mod_inverse_no_branch(BIGNUM *in,
	const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx)
	{
	BIGNUM *A,*B,*X,*Y,*M,*D,*T,*R=NULL;
	BIGNUM local_A, local_B;
	BIGNUM *pA, *pB;
	BIGNUM *ret=NULL;
	int sign;

	bn_check_top(a);
	bn_check_top(n);

	BN_CTX_start(ctx);
	A = BN_CTX_get(ctx);
	B = BN_CTX_get(ctx);
	X = BN_CTX_get(ctx);
	D = BN_CTX_get(ctx);
	M = BN_CTX_get(ctx);
	Y = BN_CTX_get(ctx);
	T = BN_CTX_get(ctx);
	if (T == NULL) goto err;

	if (in == NULL)
		R=BN_new();
	else
		R=in;
	if (R == NULL) goto err;

	BN_one(X);
	BN_zero(Y);
	if (BN_copy(B,a) == NULL) goto err;
	if (BN_copy(A,n) == NULL) goto err;
	A->neg = 0;

	if (B->neg || (BN_ucmp(B, A) >= 0))
		{
		/* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked,
	 	 * BN_div_no_branch will be called eventually.
	 	 */
		pB = &local_B;
		BN_with_flags(pB, B, BN_FLG_CONSTTIME);	
		if (!BN_nnmod(B, pB, A, ctx)) goto err;
		}
	sign = -1;
	/* From  B = a mod |n|,  A = |n|  it follows that
	 *
	 *      0 <= B < A,
	 *     -sign*X*a  ==  B   (mod |n|),
	 *      sign*Y*a  ==  A   (mod |n|).
	 */

	while (!BN_is_zero(B))
		{
		BIGNUM *tmp;
		
		/*
		 *      0 < B < A,
		 * (*) -sign*X*a  ==  B   (mod |n|),
		 *      sign*Y*a  ==  A   (mod |n|)
		 */

		/* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked,
	 	 * BN_div_no_branch will be called eventually.
	 	 */
		pA = &local_A;
		BN_with_flags(pA, A, BN_FLG_CONSTTIME);	
		
		/* (D, M) := (A/B, A%B) ... */		
		if (!BN_div(D,M,pA,B,ctx)) goto err;
		
		/* Now
		 *      A = D*B + M;
		 * thus we have
		 * (**)  sign*Y*a  ==  D*B + M   (mod |n|).
		 */
		
		tmp=A; /* keep the BIGNUM object, the value does not matter */
		
		/* (A, B) := (B, A mod B) ... */
		A=B;
		B=M;
		/* ... so we have  0 <= B < A  again */
		
		/* Since the former  M  is now  B  and the former  B  is now  A,
		 * (**) translates into
		 *       sign*Y*a  ==  D*A + B    (mod |n|),
		 * i.e.
		 *       sign*Y*a - D*A  ==  B    (mod |n|).
		 * Similarly, (*) translates into
		 *      -sign*X*a  ==  A          (mod |n|).
		 *
		 * Thus,
		 *   sign*Y*a + D*sign*X*a  ==  B  (mod |n|),
		 * i.e.
		 *        sign*(Y + D*X)*a  ==  B  (mod |n|).
		 *
		 * So if we set  (X, Y, sign) := (Y + D*X, X, -sign),  we arrive back at
		 *      -sign*X*a  ==  B   (mod |n|),
		 *       sign*Y*a  ==  A   (mod |n|).
		 * Note that  X  and  Y  stay non-negative all the time.
		 */
			
		if (!BN_mul(tmp,D,X,ctx)) goto err;
		if (!BN_add(tmp,tmp,Y)) goto err;

		M=Y; /* keep the BIGNUM object, the value does not matter */
		Y=X;
		X=tmp;
		sign = -sign;
		}
		
	/*
	 * The while loop (Euclid's algorithm) ends when
	 *      A == gcd(a,n);
	 * we have
	 *       sign*Y*a  ==  A  (mod |n|),
	 * where  Y  is non-negative.
	 */

	if (sign < 0)
		{
		if (!BN_sub(Y,n,Y)) goto err;
		}
	/* Now  Y*a  ==  A  (mod |n|).  */

	if (BN_is_one(A))
		{
		/* Y*a == 1  (mod |n|) */
		if (!Y->neg && BN_ucmp(Y,n) < 0)
			{
			if (!BN_copy(R,Y)) goto err;
			}
		else
			{
			if (!BN_nnmod(R,Y,n,ctx)) goto err;
			}
		}
	else
		{
		BNerr(BN_F_BN_MOD_INVERSE_NO_BRANCH,BN_R_NO_INVERSE);
		goto err;
		}
	ret=R;
err:
	if ((ret == NULL) && (in == NULL)) BN_free(R);
	BN_CTX_end(ctx);
	bn_check_top(ret);
	return(ret);
	}
Example #19
0
int RSA_check_key(const RSA *key)
	{
	BIGNUM *i, *j, *k, *l, *m;
	BN_CTX *ctx;
	int r;
	int ret=1;

	if (!key->p || !key->q || !key->n || !key->e || !key->d)
		{
		RSAerr(RSA_F_RSA_CHECK_KEY, RSA_R_VALUE_MISSING);
		return 0;
		}
	
	i = BN_new();
	j = BN_new();
	k = BN_new();
	l = BN_new();
	m = BN_new();
	ctx = BN_CTX_new();
	if (i == NULL || j == NULL || k == NULL || l == NULL ||
		m == NULL || ctx == NULL)
		{
		ret = -1;
		RSAerr(RSA_F_RSA_CHECK_KEY, ERR_R_MALLOC_FAILURE);
		goto err;
		}
	
	/* p prime? */
	r = BN_is_prime_ex(key->p, BN_prime_checks, NULL, NULL);
	if (r != 1)
		{
		ret = r;
		if (r != 0)
			goto err;
		RSAerr(RSA_F_RSA_CHECK_KEY, RSA_R_P_NOT_PRIME);
		}
	
	/* q prime? */
	r = BN_is_prime_ex(key->q, BN_prime_checks, NULL, NULL);
	if (r != 1)
		{
		ret = r;
		if (r != 0)
			goto err;
		RSAerr(RSA_F_RSA_CHECK_KEY, RSA_R_Q_NOT_PRIME);
		}
	
	/* n = p*q? */
	r = BN_mul(i, key->p, key->q, ctx);
	if (!r) { ret = -1; goto err; }
	
	if (BN_cmp(i, key->n) != 0)
		{
		ret = 0;
		RSAerr(RSA_F_RSA_CHECK_KEY, RSA_R_N_DOES_NOT_EQUAL_P_Q);
		}
	
	/* d*e = 1  mod lcm(p-1,q-1)? */

	r = BN_sub(i, key->p, BN_value_one());
	if (!r) { ret = -1; goto err; }
	r = BN_sub(j, key->q, BN_value_one());
	if (!r) { ret = -1; goto err; }

	/* now compute k = lcm(i,j) */
	r = BN_mul(l, i, j, ctx);
	if (!r) { ret = -1; goto err; }
	r = BN_gcd(m, i, j, ctx);
	if (!r) { ret = -1; goto err; }
	r = BN_div(k, NULL, l, m, ctx); /* remainder is 0 */
	if (!r) { ret = -1; goto err; }

	r = BN_mod_mul(i, key->d, key->e, k, ctx);
	if (!r) { ret = -1; goto err; }

	if (!BN_is_one(i))
		{
		ret = 0;
		RSAerr(RSA_F_RSA_CHECK_KEY, RSA_R_D_E_NOT_CONGRUENT_TO_1);
		}
	
	if (key->dmp1 != NULL && key->dmq1 != NULL && key->iqmp != NULL)
		{
		/* dmp1 = d mod (p-1)? */
		r = BN_sub(i, key->p, BN_value_one());
		if (!r) { ret = -1; goto err; }

		r = BN_mod(j, key->d, i, ctx);
		if (!r) { ret = -1; goto err; }

		if (BN_cmp(j, key->dmp1) != 0)
			{
			ret = 0;
			RSAerr(RSA_F_RSA_CHECK_KEY,
				RSA_R_DMP1_NOT_CONGRUENT_TO_D);
			}
	
		/* dmq1 = d mod (q-1)? */    
		r = BN_sub(i, key->q, BN_value_one());
		if (!r) { ret = -1; goto err; }
	
		r = BN_mod(j, key->d, i, ctx);
		if (!r) { ret = -1; goto err; }

		if (BN_cmp(j, key->dmq1) != 0)
			{
			ret = 0;
			RSAerr(RSA_F_RSA_CHECK_KEY,
				RSA_R_DMQ1_NOT_CONGRUENT_TO_D);
			}
	
		/* iqmp = q^-1 mod p? */
		if(!BN_mod_inverse(i, key->q, key->p, ctx))
			{
			ret = -1;
			goto err;
			}

		if (BN_cmp(i, key->iqmp) != 0)
			{
			ret = 0;
			RSAerr(RSA_F_RSA_CHECK_KEY,
				RSA_R_IQMP_NOT_INVERSE_OF_Q);
			}
		}

 err:
	if (i != NULL) BN_free(i);
	if (j != NULL) BN_free(j);
	if (k != NULL) BN_free(k);
	if (l != NULL) BN_free(l);
	if (m != NULL) BN_free(m);
	if (ctx != NULL) BN_CTX_free(ctx);
	return (ret);
	}
Example #20
0
static int RSA_eay_mod_exp(BIGNUM *r0, BIGNUM *I, RSA *rsa)
	{
	BIGNUM r1,m1;
	int ret=0;
	BN_CTX *ctx;

	if ((ctx=BN_CTX_new()) == NULL) goto err;
	BN_init(&m1);
	BN_init(&r1);

	if (rsa->flags & RSA_FLAG_CACHE_PRIVATE)
		{
		if (rsa->_method_mod_p == NULL)
			{
			if ((rsa->_method_mod_p=BN_MONT_CTX_new()) != NULL)
				if (!BN_MONT_CTX_set(rsa->_method_mod_p,rsa->p,
						     ctx))
					goto err;
			}
		if (rsa->_method_mod_q == NULL)
			{
			if ((rsa->_method_mod_q=BN_MONT_CTX_new()) != NULL)
				if (!BN_MONT_CTX_set(rsa->_method_mod_q,rsa->q,
						     ctx))
					goto err;
			}
		}

	if (!BN_mod(&r1,I,rsa->q,ctx)) goto err;
	if (!rsa->meth->bn_mod_exp(&m1,&r1,rsa->dmq1,rsa->q,ctx,
		rsa->_method_mod_q)) goto err;

	if (!BN_mod(&r1,I,rsa->p,ctx)) goto err;
	if (!rsa->meth->bn_mod_exp(r0,&r1,rsa->dmp1,rsa->p,ctx,
		rsa->_method_mod_p)) goto err;

	if (!BN_sub(r0,r0,&m1)) goto err;
	/* This will help stop the size of r0 increasing, which does
	 * affect the multiply if it optimised for a power of 2 size */
	if (r0->neg)
		if (!BN_add(r0,r0,rsa->p)) goto err;

	if (!BN_mul(&r1,r0,rsa->iqmp,ctx)) goto err;
	if (!BN_mod(r0,&r1,rsa->p,ctx)) goto err;
	/* If p < q it is occasionally possible for the correction of
         * adding 'p' if r0 is negative above to leave the result still
	 * negative. This can break the private key operations: the following
	 * second correction should *always* correct this rare occurrence.
	 * This will *never* happen with OpenSSL generated keys because
         * they ensure p > q [steve]
         */
	if (r0->neg)
		if (!BN_add(r0,r0,rsa->p)) goto err;
	if (!BN_mul(&r1,r0,rsa->q,ctx)) goto err;
	if (!BN_add(r0,&r1,&m1)) goto err;

	ret=1;
err:
	BN_clear_free(&m1);
	BN_clear_free(&r1);
	BN_CTX_free(ctx);
	return(ret);
	}
Example #21
0
int RSA_check_key(const RSA *key) {
  BIGNUM n, pm1, qm1, lcm, gcd, de, dmp1, dmq1, iqmp;
  BN_CTX *ctx;
  int ok = 0, has_crt_values;

  if (RSA_is_opaque(key)) {
    /* Opaque keys can't be checked. */
    return 1;
  }

  if ((key->p != NULL) != (key->q != NULL)) {
    OPENSSL_PUT_ERROR(RSA, RSA_R_ONLY_ONE_OF_P_Q_GIVEN);
    return 0;
  }

  if (!key->n || !key->e) {
    OPENSSL_PUT_ERROR(RSA, RSA_R_VALUE_MISSING);
    return 0;
  }

  if (!key->d || !key->p) {
    /* For a public key, or without p and q, there's nothing that can be
     * checked. */
    return 1;
  }

  ctx = BN_CTX_new();
  if (ctx == NULL) {
    OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
    return 0;
  }

  BN_init(&n);
  BN_init(&pm1);
  BN_init(&qm1);
  BN_init(&lcm);
  BN_init(&gcd);
  BN_init(&de);
  BN_init(&dmp1);
  BN_init(&dmq1);
  BN_init(&iqmp);

  if (!BN_mul(&n, key->p, key->q, ctx) ||
      /* lcm = lcm(prime-1, for all primes) */
      !BN_sub(&pm1, key->p, BN_value_one()) ||
      !BN_sub(&qm1, key->q, BN_value_one()) ||
      !BN_mul(&lcm, &pm1, &qm1, ctx) ||
      !BN_gcd(&gcd, &pm1, &qm1, ctx)) {
    OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN);
    goto out;
  }

  size_t num_additional_primes = 0;
  if (key->additional_primes != NULL) {
    num_additional_primes = sk_RSA_additional_prime_num(key->additional_primes);
  }

  size_t i;
  for (i = 0; i < num_additional_primes; i++) {
    const RSA_additional_prime *ap =
        sk_RSA_additional_prime_value(key->additional_primes, i);
    if (!BN_mul(&n, &n, ap->prime, ctx) ||
        !BN_sub(&pm1, ap->prime, BN_value_one()) ||
        !BN_mul(&lcm, &lcm, &pm1, ctx) ||
        !BN_gcd(&gcd, &gcd, &pm1, ctx)) {
      OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN);
      goto out;
    }
  }

  if (!BN_div(&lcm, NULL, &lcm, &gcd, ctx) ||
      !BN_gcd(&gcd, &pm1, &qm1, ctx) ||
      /* de = d*e mod lcm(prime-1, for all primes). */
      !BN_mod_mul(&de, key->d, key->e, &lcm, ctx)) {
    OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN);
    goto out;
  }

  if (BN_cmp(&n, key->n) != 0) {
    OPENSSL_PUT_ERROR(RSA, RSA_R_N_NOT_EQUAL_P_Q);
    goto out;
  }

  if (!BN_is_one(&de)) {
    OPENSSL_PUT_ERROR(RSA, RSA_R_D_E_NOT_CONGRUENT_TO_1);
    goto out;
  }

  has_crt_values = key->dmp1 != NULL;
  if (has_crt_values != (key->dmq1 != NULL) ||
      has_crt_values != (key->iqmp != NULL)) {
    OPENSSL_PUT_ERROR(RSA, RSA_R_INCONSISTENT_SET_OF_CRT_VALUES);
    goto out;
  }

  if (has_crt_values && num_additional_primes == 0) {
    if (/* dmp1 = d mod (p-1) */
        !BN_mod(&dmp1, key->d, &pm1, ctx) ||
        /* dmq1 = d mod (q-1) */
        !BN_mod(&dmq1, key->d, &qm1, ctx) ||
        /* iqmp = q^-1 mod p */
        !BN_mod_inverse(&iqmp, key->q, key->p, ctx)) {
      OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN);
      goto out;
    }

    if (BN_cmp(&dmp1, key->dmp1) != 0 ||
        BN_cmp(&dmq1, key->dmq1) != 0 ||
        BN_cmp(&iqmp, key->iqmp) != 0) {
      OPENSSL_PUT_ERROR(RSA, RSA_R_CRT_VALUES_INCORRECT);
      goto out;
    }
  }

  ok = 1;

out:
  BN_free(&n);
  BN_free(&pm1);
  BN_free(&qm1);
  BN_free(&lcm);
  BN_free(&gcd);
  BN_free(&de);
  BN_free(&dmp1);
  BN_free(&dmq1);
  BN_free(&iqmp);
  BN_CTX_free(ctx);

  return ok;
}
/*
 * rsa_get_params(): - Get the important parameters of an RSA public key
 */
int rsa_get_params(RSA *key, uint32_t *n0_invp, BIGNUM **modulusp,
		   BIGNUM **r_squaredp)
{
	BIGNUM *big1, *big2, *big32, *big2_32;
	BIGNUM *n, *r, *r_squared, *tmp;
	BN_CTX *bn_ctx = BN_CTX_new();
	int ret = 0;

	/* Initialize BIGNUMs */
	big1 = BN_new();
	big2 = BN_new();
	big32 = BN_new();
	r = BN_new();
	r_squared = BN_new();
	tmp = BN_new();
	big2_32 = BN_new();
	n = BN_new();
	if (!big1 || !big2 || !big32 || !r || !r_squared || !tmp || !big2_32 ||
	    !n) {
		fprintf(stderr, "Out of memory (bignum)\n");
		return -ENOMEM;
	}

	if (!BN_copy(n, key->n) || !BN_set_word(big1, 1L) ||
	    !BN_set_word(big2, 2L) || !BN_set_word(big32, 32L))
		ret = -1;

	/* big2_32 = 2^32 */
	if (!BN_exp(big2_32, big2, big32, bn_ctx))
		ret = -1;

	/* Calculate n0_inv = -1 / n[0] mod 2^32 */
	if (!BN_mod_inverse(tmp, n, big2_32, bn_ctx) ||
	    !BN_sub(tmp, big2_32, tmp))
		ret = -1;
	*n0_invp = BN_get_word(tmp);

	/* Calculate R = 2^(# of key bits) */
	if (!BN_set_word(tmp, BN_num_bits(n)) ||
	    !BN_exp(r, big2, tmp, bn_ctx))
		ret = -1;

	/* Calculate r_squared = R^2 mod n */
	if (!BN_copy(r_squared, r) ||
	    !BN_mul(tmp, r_squared, r, bn_ctx) ||
	    !BN_mod(r_squared, tmp, n, bn_ctx))
		ret = -1;

	*modulusp = n;
	*r_squaredp = r_squared;

	BN_free(big1);
	BN_free(big2);
	BN_free(big32);
	BN_free(r);
	BN_free(tmp);
	BN_free(big2_32);
	if (ret) {
		fprintf(stderr, "Bignum operations failed\n");
		return -ENOMEM;
	}

	return ret;
}
Example #23
0
/*-
 * This implementation is based on the following primitives in the IEEE 1363 standard:
 *  - ECKAS-DH1
 *  - ECSVDP-DH
 * Finally an optional KDF is applied.
 */
int ossl_ecdh_compute_key(void *out, size_t outlen, const EC_POINT *pub_key,
                          const EC_KEY *ecdh,
                          void *(*KDF) (const void *in, size_t inlen,
                                        void *out, size_t *outlen))
{
    BN_CTX *ctx;
    EC_POINT *tmp = NULL;
    BIGNUM *x = NULL, *y = NULL;
    const BIGNUM *priv_key;
    const EC_GROUP *group;
    int ret = -1;
    size_t buflen, len;
    unsigned char *buf = NULL;

    if (outlen > INT_MAX) {
        ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); /* sort of,
                                                                 * anyway */
        return -1;
    }

    if (ecdh->group->meth->ecdh_compute_key != 0)
        return ecdh->group->meth->ecdh_compute_key(out, outlen, pub_key, ecdh,
                                                   KDF);

    if ((ctx = BN_CTX_new()) == NULL)
        goto err;
    BN_CTX_start(ctx);
    x = BN_CTX_get(ctx);
    y = BN_CTX_get(ctx);

    priv_key = EC_KEY_get0_private_key(ecdh);
    if (priv_key == NULL) {
        ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, EC_R_NO_PRIVATE_VALUE);
        goto err;
    }

    group = EC_KEY_get0_group(ecdh);

    if (EC_KEY_get_flags(ecdh) & EC_FLAG_COFACTOR_ECDH) {
        if (!EC_GROUP_get_cofactor(group, x, NULL) ||
            !BN_mul(x, x, priv_key, ctx)) {
            ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, ERR_R_MALLOC_FAILURE);
            goto err;
        }
        priv_key = x;
    }

    if ((tmp = EC_POINT_new(group)) == NULL) {
        ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, ERR_R_MALLOC_FAILURE);
        goto err;
    }

    if (!EC_POINT_mul(group, tmp, NULL, pub_key, priv_key, ctx)) {
        ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, EC_R_POINT_ARITHMETIC_FAILURE);
        goto err;
    }

    if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) ==
        NID_X9_62_prime_field) {
        if (!EC_POINT_get_affine_coordinates_GFp(group, tmp, x, y, ctx)) {
            ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, EC_R_POINT_ARITHMETIC_FAILURE);
            goto err;
        }
    }
#ifndef OPENSSL_NO_EC2M
    else {
        if (!EC_POINT_get_affine_coordinates_GF2m(group, tmp, x, y, ctx)) {
            ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, EC_R_POINT_ARITHMETIC_FAILURE);
            goto err;
        }
    }
#endif

    buflen = (EC_GROUP_get_degree(group) + 7) / 8;
    len = BN_num_bytes(x);
    if (len > buflen) {
        ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, ERR_R_INTERNAL_ERROR);
        goto err;
    }
    if ((buf = OPENSSL_malloc(buflen)) == NULL) {
        ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, ERR_R_MALLOC_FAILURE);
        goto err;
    }

    memset(buf, 0, buflen - len);
    if (len != (size_t)BN_bn2bin(x, buf + buflen - len)) {
        ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, ERR_R_BN_LIB);
        goto err;
    }

    if (KDF != 0) {
        if (KDF(buf, buflen, out, &outlen) == NULL) {
            ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, EC_R_KDF_FAILED);
            goto err;
        }
        ret = outlen;
    } else {
        /* no KDF, just copy as much as we can */
        if (outlen > buflen)
            outlen = buflen;
        memcpy(out, buf, outlen);
        ret = outlen;
    }

 err:
    EC_POINT_free(tmp);
    if (ctx)
        BN_CTX_end(ctx);
    BN_CTX_free(ctx);
    OPENSSL_free(buf);
    return (ret);
}
Example #24
0
static int RSA_eay_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
{
    BIGNUM *r1, *m1, *vrfy;
    BIGNUM local_dmp1, local_dmq1, local_c, local_r1;
    BIGNUM *dmp1, *dmq1, *c, *pr1;
    int ret = 0;

    BN_CTX_start(ctx);
    r1 = BN_CTX_get(ctx);
    m1 = BN_CTX_get(ctx);
    vrfy = BN_CTX_get(ctx);

    {
        BIGNUM local_p, local_q;
        BIGNUM *p = NULL, *q = NULL;

        /*
         * Make sure BN_mod_inverse in Montgomery intialization uses the
         * BN_FLG_CONSTTIME flag (unless RSA_FLAG_NO_CONSTTIME is set)
         */
        if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
            BN_init(&local_p);
            p = &local_p;
            BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME);

            BN_init(&local_q);
            q = &local_q;
            BN_with_flags(q, rsa->q, BN_FLG_CONSTTIME);
        } else {
            p = rsa->p;
            q = rsa->q;
        }

        if (rsa->flags & RSA_FLAG_CACHE_PRIVATE) {
            if (!BN_MONT_CTX_set_locked
                (&rsa->_method_mod_p, CRYPTO_LOCK_RSA, p, ctx))
                goto err;
            if (!BN_MONT_CTX_set_locked
                (&rsa->_method_mod_q, CRYPTO_LOCK_RSA, q, ctx))
                goto err;
        }
    }

    if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
        if (!BN_MONT_CTX_set_locked
            (&rsa->_method_mod_n, CRYPTO_LOCK_RSA, rsa->n, ctx))
            goto err;

    /* compute I mod q */
    if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
        c = &local_c;
        BN_with_flags(c, I, BN_FLG_CONSTTIME);
        if (!BN_mod(r1, c, rsa->q, ctx))
            goto err;
    } else {
        if (!BN_mod(r1, I, rsa->q, ctx))
            goto err;
    }

    /* compute r1^dmq1 mod q */
    if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
        dmq1 = &local_dmq1;
        BN_with_flags(dmq1, rsa->dmq1, BN_FLG_CONSTTIME);
    } else
        dmq1 = rsa->dmq1;
    if (!rsa->meth->bn_mod_exp(m1, r1, dmq1, rsa->q, ctx, rsa->_method_mod_q))
        goto err;

    /* compute I mod p */
    if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
        c = &local_c;
        BN_with_flags(c, I, BN_FLG_CONSTTIME);
        if (!BN_mod(r1, c, rsa->p, ctx))
            goto err;
    } else {
        if (!BN_mod(r1, I, rsa->p, ctx))
            goto err;
    }

    /* compute r1^dmp1 mod p */
    if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
        dmp1 = &local_dmp1;
        BN_with_flags(dmp1, rsa->dmp1, BN_FLG_CONSTTIME);
    } else
        dmp1 = rsa->dmp1;
    if (!rsa->meth->bn_mod_exp(r0, r1, dmp1, rsa->p, ctx, rsa->_method_mod_p))
        goto err;

    if (!BN_sub(r0, r0, m1))
        goto err;
    /*
     * This will help stop the size of r0 increasing, which does affect the
     * multiply if it optimised for a power of 2 size
     */
    if (BN_is_negative(r0))
        if (!BN_add(r0, r0, rsa->p))
            goto err;

    if (!BN_mul(r1, r0, rsa->iqmp, ctx))
        goto err;

    /* Turn BN_FLG_CONSTTIME flag on before division operation */
    if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
        pr1 = &local_r1;
        BN_with_flags(pr1, r1, BN_FLG_CONSTTIME);
    } else
        pr1 = r1;
    if (!BN_mod(r0, pr1, rsa->p, ctx))
        goto err;

    /*
     * If p < q it is occasionally possible for the correction of adding 'p'
     * if r0 is negative above to leave the result still negative. This can
     * break the private key operations: the following second correction
     * should *always* correct this rare occurrence. This will *never* happen
     * with OpenSSL generated keys because they ensure p > q [steve]
     */
    if (BN_is_negative(r0))
        if (!BN_add(r0, r0, rsa->p))
            goto err;
    if (!BN_mul(r1, r0, rsa->q, ctx))
        goto err;
    if (!BN_add(r0, r1, m1))
        goto err;

    if (rsa->e && rsa->n) {
        if (!rsa->meth->bn_mod_exp(vrfy, r0, rsa->e, rsa->n, ctx,
                                   rsa->_method_mod_n))
            goto err;
        /*
         * If 'I' was greater than (or equal to) rsa->n, the operation will
         * be equivalent to using 'I mod n'. However, the result of the
         * verify will *always* be less than 'n' so we don't check for
         * absolute equality, just congruency.
         */
        if (!BN_sub(vrfy, vrfy, I))
            goto err;
        if (!BN_mod(vrfy, vrfy, rsa->n, ctx))
            goto err;
        if (BN_is_negative(vrfy))
            if (!BN_add(vrfy, vrfy, rsa->n))
                goto err;
        if (!BN_is_zero(vrfy)) {
            /*
             * 'I' and 'vrfy' aren't congruent mod n. Don't leak
             * miscalculated CRT output, just do a raw (slower) mod_exp and
             * return that instead.
             */

            BIGNUM local_d;
            BIGNUM *d = NULL;

            if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
                d = &local_d;
                BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
            } else
                d = rsa->d;
            if (!rsa->meth->bn_mod_exp(r0, I, d, rsa->n, ctx,
                                       rsa->_method_mod_n))
                goto err;
        }
    }
    ret = 1;
 err:
    BN_CTX_end(ctx);
    return (ret);
}
Example #25
0
int vb_keyb_from_rsa(struct rsa_st *rsa_private_key,
		     uint8_t **keyb_data, uint32_t *keyb_size)
{
	uint32_t i, nwords;
	BIGNUM *N = NULL;
	BIGNUM *Big1 = NULL, *Big2 = NULL, *Big32 = NULL, *BigMinus1 = NULL;
	BIGNUM *B = NULL;
	BIGNUM *N0inv = NULL, *R = NULL, *RR = NULL;
	BIGNUM *RRTemp = NULL, *NnumBits = NULL;
	BIGNUM *n = NULL, *rr = NULL;
	BN_CTX *bn_ctx = BN_CTX_new();
	uint32_t n0invout;
	uint32_t bufsize;
	uint32_t *outbuf;
	int retval = 1;

	/* Size of RSA key in 32-bit words */
	nwords = BN_num_bits(rsa_private_key->n) / 32;

	bufsize = (2 + nwords + nwords) * sizeof(uint32_t);
	outbuf = malloc(bufsize);
	if (!outbuf)
		goto done;

	*keyb_data = (uint8_t *)outbuf;
	*keyb_size = bufsize;

	*outbuf++ = nwords;

	/* Initialize BIGNUMs */
#define NEW_BIGNUM(x) do { x = BN_new(); if (!x) goto done; } while (0)
	NEW_BIGNUM(N);
	NEW_BIGNUM(Big1);
	NEW_BIGNUM(Big2);
	NEW_BIGNUM(Big32);
	NEW_BIGNUM(BigMinus1);
	NEW_BIGNUM(N0inv);
	NEW_BIGNUM(R);
	NEW_BIGNUM(RR);
	NEW_BIGNUM(RRTemp);
	NEW_BIGNUM(NnumBits);
	NEW_BIGNUM(n);
	NEW_BIGNUM(rr);
	NEW_BIGNUM(B);
#undef NEW_BIGNUM

	BN_copy(N, rsa_private_key->n);
	BN_set_word(Big1, 1L);
	BN_set_word(Big2, 2L);
	BN_set_word(Big32, 32L);
	BN_sub(BigMinus1, Big1, Big2);

	BN_exp(B, Big2, Big32, bn_ctx); /* B = 2^32 */

	/* Calculate and output N0inv = -1 / N[0] mod 2^32 */
	BN_mod_inverse(N0inv, N, B, bn_ctx);
	BN_sub(N0inv, B, N0inv);
	n0invout = BN_get_word(N0inv);

	*outbuf++ = n0invout;

	/* Calculate R = 2^(# of key bits) */
	BN_set_word(NnumBits, BN_num_bits(N));
	BN_exp(R, Big2, NnumBits, bn_ctx);

	/* Calculate RR = R^2 mod N */
	BN_copy(RR, R);
	BN_mul(RRTemp, RR, R, bn_ctx);
	BN_mod(RR, RRTemp, N, bn_ctx);


	/* Write out modulus as little endian array of integers. */
	for (i = 0; i < nwords; ++i) {
		uint32_t nout;

		BN_mod(n, N, B, bn_ctx); /* n = N mod B */
		nout = BN_get_word(n);
		*outbuf++ = nout;

		BN_rshift(N, N, 32); /*  N = N/B */
	}

	/* Write R^2 as little endian array of integers. */
	for (i = 0; i < nwords; ++i) {
		uint32_t rrout;

		BN_mod(rr, RR, B, bn_ctx); /* rr = RR mod B */
		rrout = BN_get_word(rr);
		*outbuf++ = rrout;

		BN_rshift(RR, RR, 32); /* RR = RR/B */
	}

	outbuf = NULL;
	retval = 0;

done:
	free(outbuf);
	/* Free BIGNUMs. */
	BN_free(Big1);
	BN_free(Big2);
	BN_free(Big32);
	BN_free(BigMinus1);
	BN_free(N0inv);
	BN_free(R);
	BN_free(RRTemp);
	BN_free(NnumBits);
	BN_free(n);
	BN_free(rr);

	return retval;
}
Example #26
0
int
ecdh_im_compute_key(PACE_CTX * ctx, const BUF_MEM * s, const BUF_MEM * in,
        BN_CTX *bn_ctx)
{
    int ret = 0;
    BUF_MEM * x_mem = NULL;
    BIGNUM * a = NULL, *b = NULL, *p = NULL;
    BIGNUM * x = NULL, *y = NULL, *v = NULL, *u = NULL;
    BIGNUM * tmp = NULL, *tmp2 = NULL, *bn_inv = NULL;
    BIGNUM * two = NULL, *three = NULL, *four = NULL, *six = NULL;
    BIGNUM * twentyseven = NULL;
    EC_KEY *static_key = NULL, *ephemeral_key = NULL;
    EC_POINT *g = NULL;

    BN_CTX_start(bn_ctx);

    check((ctx && ctx->static_key && s && ctx->ka_ctx), "Invalid arguments"); 

    static_key = EVP_PKEY_get1_EC_KEY(ctx->static_key);
    if (!static_key)
        goto err;

    /* Setup all the variables*/
    a = BN_CTX_get(bn_ctx);
    b = BN_CTX_get(bn_ctx);
    p = BN_CTX_get(bn_ctx);
    x = BN_CTX_get(bn_ctx);
    y = BN_CTX_get(bn_ctx);
    v = BN_CTX_get(bn_ctx);
    two = BN_CTX_get(bn_ctx);
    three = BN_CTX_get(bn_ctx);
    four = BN_CTX_get(bn_ctx);
    six = BN_CTX_get(bn_ctx);
    twentyseven = BN_CTX_get(bn_ctx);
    tmp = BN_CTX_get(bn_ctx);
    tmp2 = BN_CTX_get(bn_ctx);
    bn_inv = BN_CTX_get(bn_ctx);
    if (!bn_inv)
        goto err;

    /* Encrypt the Nonce using the symmetric key in */
    x_mem = cipher_no_pad(ctx->ka_ctx, NULL, in, s, 1);
    if (!x_mem)
        goto err;

    /* Fetch the curve parameters */
    if (!EC_GROUP_get_curve_GFp(EC_KEY_get0_group(static_key), p, a, b, bn_ctx))
        goto err;

    /* Assign constants */
    if (    !BN_set_word(two,2)||
            !BN_set_word(three,3)||
            !BN_set_word(four,4)||
            !BN_set_word(six,6)||
            !BN_set_word(twentyseven,27)
            ) goto err;

    /* Check prerequisites for curve parameters */
    check(
            /* p > 3;*/
           (BN_cmp(p, three) == 1) &&
           /* p mod 3 = 2; (p has the form p=q^n, q prime) */
           BN_nnmod(tmp, p, three, bn_ctx) &&
           (BN_cmp(tmp, two) == 0),
        "Unsuited curve");

    /* Convert encrypted nonce to BIGNUM */
    u = BN_bin2bn((unsigned char *) x_mem->data, x_mem->length, u);
    if (!u)
        goto err;

    if ( /* v = (3a - u^4) / 6u mod p */
            !BN_mod_mul(tmp, three, a, p, bn_ctx) ||
            !BN_mod_exp(tmp2, u, four, p, bn_ctx) ||
            !BN_mod_sub(v, tmp, tmp2, p, bn_ctx) ||
            !BN_mod_mul(tmp, u, six, p, bn_ctx) ||
            /* For division within a galois field we need to compute
             * the multiplicative inverse of a number */
            !BN_mod_inverse(bn_inv, tmp, p, bn_ctx) ||
            !BN_mod_mul(v, v, bn_inv, p, bn_ctx) ||

            /* x = (v^2 - b - ((u^6)/27)) */
            !BN_mod_sqr(tmp, v, p, bn_ctx) ||
            !BN_mod_sub(tmp2, tmp, b, p, bn_ctx) ||
            !BN_mod_exp(tmp, u, six, p, bn_ctx) ||
            !BN_mod_inverse(bn_inv, twentyseven, p, bn_ctx) ||
            !BN_mod_mul(tmp, tmp, bn_inv, p, bn_ctx) ||
            !BN_mod_sub(x, tmp2, tmp, p, bn_ctx) ||

            /* x -> x^(1/3) = x^((2p^n -1)/3) */
            !BN_mul(tmp, two, p, bn_ctx) ||
            !BN_sub(tmp, tmp, BN_value_one()) ||

            /* Division is defined, because p^n = 2 mod 3 */
            !BN_div(tmp, y, tmp, three, bn_ctx) ||
            !BN_mod_exp(tmp2, x, tmp, p, bn_ctx) ||
            !BN_copy(x, tmp2) ||

            /* x += (u^2)/3 */
            !BN_mod_sqr(tmp, u, p, bn_ctx) ||
            !BN_mod_inverse(bn_inv, three, p, bn_ctx) ||
            !BN_mod_mul(tmp2, tmp, bn_inv, p, bn_ctx) ||
            !BN_mod_add(tmp, x, tmp2, p, bn_ctx) ||
            !BN_copy(x, tmp) ||

            /* y = ux + v */
            !BN_mod_mul(y, u, x, p, bn_ctx) ||
            !BN_mod_add(tmp, y, v, p, bn_ctx) ||
            !BN_copy(y, tmp)
            )
        goto err;

    /* Initialize ephemeral parameters with parameters from the static key */
    ephemeral_key = EC_KEY_dup(static_key);
    if (!ephemeral_key)
        goto err;
    EVP_PKEY_set1_EC_KEY(ctx->ka_ctx->key, ephemeral_key);

    /* configure the new EC_KEY */
    g = EC_POINT_new(EC_KEY_get0_group(ephemeral_key));
    if (!g)
        goto err;
    if (!EC_POINT_set_affine_coordinates_GFp(EC_KEY_get0_group(ephemeral_key), g,
            x, y, bn_ctx))
        goto err;

    ret = 1;

err:
    if (x_mem)
        BUF_MEM_free(x_mem);
    if (u)
        BN_free(u);
    BN_CTX_end(bn_ctx);
    if (g)
        EC_POINT_clear_free(g);
    /* Decrement reference count, keys are still available via PACE_CTX */
    if (static_key)
        EC_KEY_free(static_key);
    if (ephemeral_key)
        EC_KEY_free(ephemeral_key);

    return ret;
}
int test_div(BIO *bp, BN_CTX *ctx)
	{
	BIGNUM a,b,c,d,e;
	int i;

	BN_init(&a);
	BN_init(&b);
	BN_init(&c);
	BN_init(&d);
	BN_init(&e);

	for (i=0; i<num0+num1; i++)
		{
		if (i < num1)
			{
			BN_bntest_rand(&a,400,0,0);
			BN_copy(&b,&a);
			BN_lshift(&a,&a,i);
			BN_add_word(&a,i);
			}
		else
			BN_bntest_rand(&b,50+3*(i-num1),0,0);
		a.neg=rand_neg();
		b.neg=rand_neg();
		BN_div(&d,&c,&a,&b,ctx);
		if (bp != NULL)
			{
			if (!results)
				{
				BN_print(bp,&a);
				BIO_puts(bp," / ");
				BN_print(bp,&b);
				BIO_puts(bp," - ");
				}
			BN_print(bp,&d);
			BIO_puts(bp,"\n");

			if (!results)
				{
				BN_print(bp,&a);
				BIO_puts(bp," % ");
				BN_print(bp,&b);
				BIO_puts(bp," - ");
				}
			BN_print(bp,&c);
			BIO_puts(bp,"\n");
			}
		BN_mul(&e,&d,&b,ctx);
		BN_add(&d,&e,&c);
		BN_sub(&d,&d,&a);
		if(!BN_is_zero(&d))
		    {
		    fprintf(stderr,"Division test failed!\n");
		    return 0;
		    }
		}
	BN_free(&a);
	BN_free(&b);
	BN_free(&c);
	BN_free(&d);
	BN_free(&e);
	return(1);
	}
Example #28
0
static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) {
  BIGNUM *r1, *m1, *vrfy;
  BIGNUM local_dmp1, local_dmq1, local_c, local_r1;
  BIGNUM *dmp1, *dmq1, *c, *pr1;
  int ret = 0;
  size_t i, num_additional_primes = 0;

  if (rsa->additional_primes != NULL) {
    num_additional_primes = sk_RSA_additional_prime_num(rsa->additional_primes);
  }

  BN_CTX_start(ctx);
  r1 = BN_CTX_get(ctx);
  m1 = BN_CTX_get(ctx);
  vrfy = BN_CTX_get(ctx);

  {
    BIGNUM local_p, local_q;
    BIGNUM *p = NULL, *q = NULL;

    /* Make sure BN_mod_inverse in Montgomery intialization uses the
     * BN_FLG_CONSTTIME flag (unless RSA_FLAG_NO_CONSTTIME is set) */
    BN_init(&local_p);
    p = &local_p;
    BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME);

    BN_init(&local_q);
    q = &local_q;
    BN_with_flags(q, rsa->q, BN_FLG_CONSTTIME);

    if (rsa->flags & RSA_FLAG_CACHE_PRIVATE) {
      if (BN_MONT_CTX_set_locked(&rsa->_method_mod_p, &rsa->lock, p, ctx) ==
          NULL) {
        goto err;
      }
      if (BN_MONT_CTX_set_locked(&rsa->_method_mod_q, &rsa->lock, q, ctx) ==
          NULL) {
        goto err;
      }
    }
  }

  if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) {
    if (BN_MONT_CTX_set_locked(&rsa->_method_mod_n, &rsa->lock, rsa->n, ctx) ==
        NULL) {
      goto err;
    }
  }

  /* compute I mod q */
  c = &local_c;
  BN_with_flags(c, I, BN_FLG_CONSTTIME);
  if (!BN_mod(r1, c, rsa->q, ctx)) {
    goto err;
  }

  /* compute r1^dmq1 mod q */
  dmq1 = &local_dmq1;
  BN_with_flags(dmq1, rsa->dmq1, BN_FLG_CONSTTIME);
  if (!rsa->meth->bn_mod_exp(m1, r1, dmq1, rsa->q, ctx, rsa->_method_mod_q)) {
    goto err;
  }

  /* compute I mod p */
  c = &local_c;
  BN_with_flags(c, I, BN_FLG_CONSTTIME);
  if (!BN_mod(r1, c, rsa->p, ctx)) {
    goto err;
  }

  /* compute r1^dmp1 mod p */
  dmp1 = &local_dmp1;
  BN_with_flags(dmp1, rsa->dmp1, BN_FLG_CONSTTIME);
  if (!rsa->meth->bn_mod_exp(r0, r1, dmp1, rsa->p, ctx, rsa->_method_mod_p)) {
    goto err;
  }

  if (!BN_sub(r0, r0, m1)) {
    goto err;
  }
  /* This will help stop the size of r0 increasing, which does
   * affect the multiply if it optimised for a power of 2 size */
  if (BN_is_negative(r0)) {
    if (!BN_add(r0, r0, rsa->p)) {
      goto err;
    }
  }

  if (!BN_mul(r1, r0, rsa->iqmp, ctx)) {
    goto err;
  }

  /* Turn BN_FLG_CONSTTIME flag on before division operation */
  pr1 = &local_r1;
  BN_with_flags(pr1, r1, BN_FLG_CONSTTIME);

  if (!BN_mod(r0, pr1, rsa->p, ctx)) {
    goto err;
  }

  /* If p < q it is occasionally possible for the correction of
   * adding 'p' if r0 is negative above to leave the result still
   * negative. This can break the private key operations: the following
   * second correction should *always* correct this rare occurrence.
   * This will *never* happen with OpenSSL generated keys because
   * they ensure p > q [steve] */
  if (BN_is_negative(r0)) {
    if (!BN_add(r0, r0, rsa->p)) {
      goto err;
    }
  }
  if (!BN_mul(r1, r0, rsa->q, ctx)) {
    goto err;
  }
  if (!BN_add(r0, r1, m1)) {
    goto err;
  }

  for (i = 0; i < num_additional_primes; i++) {
    /* multi-prime RSA. */
    BIGNUM local_exp, local_prime;
    BIGNUM *exp = &local_exp, *prime = &local_prime;
    RSA_additional_prime *ap =
        sk_RSA_additional_prime_value(rsa->additional_primes, i);

    BN_with_flags(exp, ap->exp, BN_FLG_CONSTTIME);
    BN_with_flags(prime, ap->prime, BN_FLG_CONSTTIME);

    /* c will already point to a BIGNUM with the correct flags. */
    if (!BN_mod(r1, c, prime, ctx)) {
      goto err;
    }

    if ((rsa->flags & RSA_FLAG_CACHE_PRIVATE) &&
        !BN_MONT_CTX_set_locked(&ap->method_mod, &rsa->lock, prime, ctx)) {
      goto err;
    }

    if (!rsa->meth->bn_mod_exp(m1, r1, exp, prime, ctx, ap->method_mod)) {
      goto err;
    }

    BN_set_flags(m1, BN_FLG_CONSTTIME);

    if (!BN_sub(m1, m1, r0) ||
        !BN_mul(m1, m1, ap->coeff, ctx) ||
        !BN_mod(m1, m1, prime, ctx) ||
        (BN_is_negative(m1) && !BN_add(m1, m1, prime)) ||
        !BN_mul(m1, m1, ap->r, ctx) ||
        !BN_add(r0, r0, m1)) {
      goto err;
    }
  }

  if (rsa->e && rsa->n) {
    if (!rsa->meth->bn_mod_exp(vrfy, r0, rsa->e, rsa->n, ctx,
                               rsa->_method_mod_n)) {
      goto err;
    }
    /* If 'I' was greater than (or equal to) rsa->n, the operation
     * will be equivalent to using 'I mod n'. However, the result of
     * the verify will *always* be less than 'n' so we don't check
     * for absolute equality, just congruency. */
    if (!BN_sub(vrfy, vrfy, I)) {
      goto err;
    }
    if (!BN_mod(vrfy, vrfy, rsa->n, ctx)) {
      goto err;
    }
    if (BN_is_negative(vrfy)) {
      if (!BN_add(vrfy, vrfy, rsa->n)) {
        goto err;
      }
    }
    if (!BN_is_zero(vrfy)) {
      /* 'I' and 'vrfy' aren't congruent mod n. Don't leak
       * miscalculated CRT output, just do a raw (slower)
       * mod_exp and return that instead. */

      BIGNUM local_d;
      BIGNUM *d = NULL;

      d = &local_d;
      BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
      if (!rsa->meth->bn_mod_exp(r0, I, d, rsa->n, ctx, rsa->_method_mod_n)) {
        goto err;
      }
    }
  }
  ret = 1;

err:
  BN_CTX_end(ctx);
  return ret;
}
Example #29
0
int BN_X931_derive_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2,
			const BIGNUM *Xp, const BIGNUM *Xp1, const BIGNUM *Xp2,
			const BIGNUM *e, BN_CTX *ctx, BN_GENCB *cb)
	{
	int ret = 0;

	BIGNUM *t, *p1p2, *pm1;

	/* Only even e supported */
	if (!BN_is_odd(e))
		return 0;

	BN_CTX_start(ctx);
	if (!p1)
		p1 = BN_CTX_get(ctx);

	if (!p2)
		p2 = BN_CTX_get(ctx);

	t = BN_CTX_get(ctx);

	p1p2 = BN_CTX_get(ctx);

	pm1 = BN_CTX_get(ctx);

	if (!bn_x931_derive_pi(p1, Xp1, ctx, cb))
		goto err;

	if (!bn_x931_derive_pi(p2, Xp2, ctx, cb))
		goto err;

	if (!BN_mul(p1p2, p1, p2, ctx))
		goto err;

	/* First set p to value of Rp */

	if (!BN_mod_inverse(p, p2, p1, ctx))
		goto err;

	if (!BN_mul(p, p, p2, ctx))
		goto err;

	if (!BN_mod_inverse(t, p1, p2, ctx))
		goto err;

	if (!BN_mul(t, t, p1, ctx))
		goto err;

	if (!BN_sub(p, p, t))
		goto err;

	if (p->neg && !BN_add(p, p, p1p2))
		goto err;

	/* p now equals Rp */

	if (!BN_mod_sub(p, p, Xp, p1p2, ctx))
		goto err;

	if (!BN_add(p, p, Xp))
		goto err;

	/* p now equals Yp0 */

	for (;;)
		{
		int i = 1;
		BN_GENCB_call(cb, 0, i++);
		if (!BN_copy(pm1, p))
			goto err;
		if (!BN_sub_word(pm1, 1))
			goto err;
		if (!BN_gcd(t, pm1, e, ctx))
			goto err;
		if (BN_is_one(t)
		/* X9.31 specifies 8 MR and 1 Lucas test or any prime test
		 * offering similar or better guarantees 50 MR is considerably 
		 * better.
		 */
			&& BN_is_prime_fasttest_ex(p, 50, ctx, 1, cb))
			break;
		if (!BN_add(p, p, p1p2))
			goto err;
		}

	BN_GENCB_call(cb, 3, 0);

	ret = 1;

	err:

	BN_CTX_end(ctx);

	return ret;
	}
Example #30
0
/* Shared parts of key derivation and confirmation calculation */
void
jpake_key_confirm(struct modp_group *grp, BIGNUM *s, BIGNUM *step2_val,
    BIGNUM *mypriv2, BIGNUM *mypub1, BIGNUM *mypub2,
    BIGNUM *theirpub1, BIGNUM *theirpub2,
    const u_char *my_id, u_int my_id_len,
    const u_char *their_id, u_int their_id_len,
    const u_char *sess_id, u_int sess_id_len,
    const u_char *theirpriv2_s_proof, u_int theirpriv2_s_proof_len,
    BIGNUM **k,
    u_char **confirm_hash, u_int *confirm_hash_len)
{
	BN_CTX *bn_ctx;
	BIGNUM *tmp;

	if ((bn_ctx = BN_CTX_new()) == NULL)
		fatal("%s: BN_CTX_new", __func__);
	if ((tmp = BN_new()) == NULL ||
	    (*k = BN_new()) == NULL)
		fatal("%s: BN_new", __func__);

	/* Validate step 2 values */
	if (BN_cmp(step2_val, BN_value_one()) <= 0)
		fatal("%s: step2_val <= 1", __func__);
	if (BN_cmp(step2_val, grp->p) >= 0)
		fatal("%s: step2_val >= p", __func__);

	/*
	 * theirpriv2_s_proof is calculated with a different generator:
	 * tmp = g^(mypriv1+mypriv2+theirpub1) = g^mypub1*g^mypub2*g^theirpub1
	 * Calculate it here so we can check the signature.
	 */
	if (BN_mod_mul(tmp, mypub1, mypub2, grp->p, bn_ctx) != 1)
		fatal("%s: BN_mod_mul (tmp = mypub1 * mypub2 mod p)", __func__);
	if (BN_mod_mul(tmp, tmp, theirpub1, grp->p, bn_ctx) != 1)
		fatal("%s: BN_mod_mul (tmp = tmp * theirpub1 mod p)", __func__);

	JPAKE_DEBUG_BN((tmp, "%s: tmp = ", __func__));

	if (schnorr_verify_buf(grp->p, grp->q, tmp, step2_val, 
	    their_id, their_id_len,
	    theirpriv2_s_proof, theirpriv2_s_proof_len) != 1)
		fatal("%s: schnorr_verify theirpriv2_s_proof failed", __func__);

	/*
	 * Derive shared key:
	 *     client: k = (b / g^(x2*x4*s))^x2 = g^((x1+x3)*x2*x4*s)
	 *     server: k = (a / g^(x2*x4*s))^x4 = g^((x1+x3)*x2*x4*s)
	 *
	 * Computed as:
	 *     client: k = (g_x4^(q - (x2 * s)) * b)^x2 mod p
	 *     server: k = (g_x2^(q - (x4 * s)) * b)^x4 mod p
	 */
	if (BN_mul(tmp, mypriv2, s, bn_ctx) != 1)
		fatal("%s: BN_mul (tmp = mypriv2 * s)", __func__);
	if (BN_mod_sub(tmp, grp->q, tmp, grp->q, bn_ctx) != 1)
		fatal("%s: BN_mod_sub (tmp = q - tmp mod q)", __func__);
	if (BN_mod_exp(tmp, theirpub2, tmp, grp->p, bn_ctx) != 1)
		fatal("%s: BN_mod_exp (tmp = theirpub2^tmp) mod p", __func__);
	if (BN_mod_mul(tmp, tmp, step2_val, grp->p, bn_ctx) != 1)
		fatal("%s: BN_mod_mul (tmp = tmp * step2_val) mod p", __func__);
	if (BN_mod_exp(*k, tmp, mypriv2, grp->p, bn_ctx) != 1)
		fatal("%s: BN_mod_exp (k = tmp^mypriv2) mod p", __func__);
	
	BN_CTX_free(bn_ctx);
	BN_clear_free(tmp);

	jpake_confirm_hash(*k, my_id, my_id_len, sess_id, sess_id_len,
	    confirm_hash, confirm_hash_len);
}