예제 #1
0
int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret)
{
    int ok = 0;
    BIGNUM *q = NULL;

    *ret = 0;
    q = BN_new();
    if (q == NULL)
        goto err;
    BN_set_word(q, 1);
    if (BN_cmp(pub_key, q) <= 0)
        *ret |= DH_CHECK_PUBKEY_TOO_SMALL;
    BN_copy(q, dh->p);
    BN_sub_word(q, 1);
    if (BN_cmp(pub_key, q) >= 0)
        *ret |= DH_CHECK_PUBKEY_TOO_LARGE;

    ok = 1;
 err:
    if (q != NULL)
        BN_free(q);
    return (ok);
}
예제 #2
0
파일: p_rsa.c 프로젝트: randombit/hacrypto
static int pkey_rsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) {
  RSA *rsa = NULL;
  RSA_PKEY_CTX *rctx = ctx->data;

  if (!rctx->pub_exp) {
    rctx->pub_exp = BN_new();
    if (!rctx->pub_exp || !BN_set_word(rctx->pub_exp, RSA_F4)) {
      return 0;
    }
  }
  rsa = RSA_new();
  if (!rsa) {
    return 0;
  }

  if (!RSA_generate_key_ex(rsa, rctx->nbits, rctx->pub_exp, NULL)) {
    RSA_free(rsa);
    return 0;
  }

  EVP_PKEY_assign_RSA(pkey, rsa);
  return 1;
}
예제 #3
0
EVP_PKEY *genKey() {
	EVP_PKEY *keypair = EVP_PKEY_new();
	int keylen;
	char *pem_key;
	//BN_GENCB cb = { }
	BIGNUM          *bne = BN_new();
	RSA *rsa = RSA_new();
	int ret;
	ret = BN_set_word( bne, kExp );
	if( ret != 1 ) {
		BN_free( bne );
		RSA_free( rsa );
		EVP_PKEY_free( keypair );
		return NULL;
	}
	RSA_generate_key_ex( rsa, kBits, bne, NULL );
	EVP_PKEY_set1_RSA( keypair, rsa );

	BN_free( bne );
	RSA_free( rsa );

	return keypair;
}
예제 #4
0
/** Generate a <b>bits</b>-bit new public/private keypair in <b>env</b>.
 * Return 0 on success, -1 on failure.
 */
int crypto_pk_generate_key_with_bits(crypto_pk_t *env, int bits)
{
    if (env->key)
        RSA_free(env->key);

    {
        BIGNUM *e = BN_new();

        RSA *r = NULL;
        if (!e)
            goto done;
        if (! BN_set_word(e, 65537))
            goto done;

        r = RSA_new();
        if (!r)
            goto done;

        if (RSA_generate_key_ex(r, bits, e, NULL) == -1)
            goto done;

        env->key = r;
        r = NULL;
done:
        if (e)
            BN_clear_free(e);
        if (r)
            RSA_free(r);
    }

    if (!env->key) {
        sgx_puts("generate RSA key");
        return -1;
    }

    return 0;
}
예제 #5
0
int main(int argc, char const *argv[])
{
	RSA *rsa;
	int modulelen = 1024;
	int ret, i;
	unsigned int len;
	unsigned long e  = RSA_3;

	BIGNUM *bn;
	unsigned char from[128];
	unsigned char to[128];

	bn = BN_new();
	ret = BN_set_word(bn, e);
	rsa  = RSA_new();
	ret = RSA_generate_key_ex(rsa, modulelen, bn, NULL);
	if(ret != 1)
	{
		printf("ERROR in RSA_generate_key_ex\n");
		goto finally;
	}

	for (i = 0; i < 100; ++i)
	{
		memset(&from[i], i, 1);

		/* code */
	}
	ret = RSA_sign(NID_sha1, from ,100, to, &len, rsa);
	printf("ret = %d, len = %d\n", ret, len);

	ret = RSA_verify(NID_sha1, to, 100, from, len, rsa);
	printf("ret = %d, len = %d\n",ret, len );
	finally:
	RSA_free(rsa);
	return 0;
}
예제 #6
0
static int pkey_rsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
{
    RSA *rsa = NULL;
    RSA_PKEY_CTX *rctx = ctx->data;
    BN_GENCB *pcb;
    int ret;

    if (rctx->pub_exp == NULL) {
        rctx->pub_exp = BN_new();
        if (rctx->pub_exp == NULL || !BN_set_word(rctx->pub_exp, RSA_F4))
            return 0;
    }
    rsa = RSA_new();
    if (rsa == NULL)
        return 0;
    if (ctx->pkey_gencb) {
        pcb = BN_GENCB_new();
        if (pcb == NULL) {
            RSA_free(rsa);
            return 0;
        }
        evp_pkey_set_cb_translate(pcb, ctx);
    } else {
        pcb = NULL;
    }
    ret = RSA_generate_key_ex(rsa, rctx->nbits, rctx->pub_exp, pcb);
    BN_GENCB_free(pcb);
    if (ret > 0 && !rsa_set_pss_param(rsa, ctx)) {
        RSA_free(rsa);
        return 0;
    }
    if (ret > 0)
        EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, rsa);
    else
        RSA_free(rsa);
    return ret;
}
예제 #7
0
파일: dh_check.c 프로젝트: 03050903/godot
int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret)
{
    int ok = 0;
    BIGNUM *tmp = NULL;
    BN_CTX *ctx = NULL;

    *ret = 0;
    ctx = BN_CTX_new();
    if (ctx == NULL)
        goto err;
    BN_CTX_start(ctx);
    tmp = BN_CTX_get(ctx);
    if (tmp == NULL || !BN_set_word(tmp, 1))
        goto err;
    if (BN_cmp(pub_key, tmp) <= 0)
        *ret |= DH_CHECK_PUBKEY_TOO_SMALL;
    if (BN_copy(tmp, dh->p) == NULL || !BN_sub_word(tmp, 1))
        goto err;
    if (BN_cmp(pub_key, tmp) >= 0)
        *ret |= DH_CHECK_PUBKEY_TOO_LARGE;

    if (dh->q != NULL) {
        /* Check pub_key^q == 1 mod p */
        if (!BN_mod_exp(tmp, pub_key, dh->q, dh->p, ctx))
            goto err;
        if (!BN_is_one(tmp))
            *ret |= DH_CHECK_PUBKEY_INVALID;
    }

    ok = 1;
 err:
    if (ctx != NULL) {
        BN_CTX_end(ctx);
        BN_CTX_free(ctx);
    }
    return (ok);
}
예제 #8
0
static void
push_scale(void)
{
	struct number *n;
	struct value *value;
	u_int scale = 0;

	value = pop();
	if (value != NULL) {
		switch (value->type) {
		case BCODE_NONE:
			return;
		case BCODE_NUMBER:
			scale = value->u.num->scale;
			break;
		case BCODE_STRING:
			break;
		}
		stack_free_value(value);
		n = new_number();
		bn_check(BN_set_word(n->number, scale));
		push_number(n);
	}
}
예제 #9
0
/* Zeroize
*/
static int Zeroize()
{
    RSA *key;
    BIGNUM *bn;
    unsigned char userkey[16] =
    { 0x48, 0x50, 0xf0, 0xa3, 0x3a, 0xed, 0xd3, 0xaf, 0x6e, 0x47, 0x7f, 0x83, 0x02, 0xb1, 0x09, 0x68 };
    size_t i;
    int n;

    key = FIPS_rsa_new();
    bn = BN_new();
    if (!key || !bn)
        return 0;
    BN_set_word(bn, 65537);
    if (!RSA_generate_key_ex(key, 1024,bn,NULL))
        return 0;
    BN_free(bn);

    n = BN_num_bytes(key->d);
    printf(" Generated %d byte RSA private key\n", n);
    printf("\tBN key before overwriting:\n");
    do_bn_print(stdout, key->d);
    BN_rand(key->d,n*8,-1,0);
    printf("\tBN key after overwriting:\n");
    do_bn_print(stdout, key->d);

    printf("\tchar buffer key before overwriting: \n\t\t");
    for(i = 0; i < sizeof(userkey); i++) printf("%02x", userkey[i]);
    printf("\n");
    RAND_bytes(userkey, sizeof userkey);
    printf("\tchar buffer key after overwriting: \n\t\t");
    for(i = 0; i < sizeof(userkey); i++) printf("%02x", userkey[i]);
    printf("\n");

    return 1;
}
예제 #10
0
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;

	if ((BN_get_flags(a, BN_FLG_CONSTTIME) != 0) || (BN_get_flags(n, BN_FLG_CONSTTIME) != 0))
		{
		return BN_mod_inverse_no_branch(in, a, n, ctx);
		}

	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);
	bn_check_top(ret);
	return(ret);
	}
예제 #11
0
int
a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num)
{
	int i, first, len = 0, c, use_bn;
	char ftmp[24], *tmp = ftmp;
	int tmpsize = sizeof ftmp;
	const char *p;
	unsigned long l;
	BIGNUM *bl = NULL;

	if (num == 0)
		return (0);
	else if (num == -1)
		num = strlen(buf);

	p = buf;
	c = *(p++);
	num--;
	if ((c >= '0') && (c <= '2')) {
		first= c-'0';
	} else {
		ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_FIRST_NUM_TOO_LARGE);
		goto err;
	}

	if (num <= 0) {
		ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_MISSING_SECOND_NUMBER);
		goto err;
	}
	c = *(p++);
	num--;
	for (;;) {
		if (num <= 0)
			break;
		if ((c != '.') && (c != ' ')) {
			ASN1err(ASN1_F_A2D_ASN1_OBJECT,
			    ASN1_R_INVALID_SEPARATOR);
			goto err;
		}
		l = 0;
		use_bn = 0;
		for (;;) {
			if (num <= 0)
				break;
			num--;
			c = *(p++);
			if ((c == ' ') || (c == '.'))
				break;
			if ((c < '0') || (c > '9')) {
				ASN1err(ASN1_F_A2D_ASN1_OBJECT,
				    ASN1_R_INVALID_DIGIT);
				goto err;
			}
			if (!use_bn && l >= ((ULONG_MAX - 80) / 10L)) {
				use_bn = 1;
				if (!bl)
					bl = BN_new();
				if (!bl || !BN_set_word(bl, l))
					goto err;
			}
			if (use_bn) {
				if (!BN_mul_word(bl, 10L) ||
				    !BN_add_word(bl, c-'0'))
					goto err;
			} else
				l = l * 10L + (long)(c - '0');
		}
		if (len == 0) {
			if ((first < 2) && (l >= 40)) {
				ASN1err(ASN1_F_A2D_ASN1_OBJECT,
				    ASN1_R_SECOND_NUMBER_TOO_LARGE);
				goto err;
			}
			if (use_bn) {
				if (!BN_add_word(bl, first * 40))
					goto err;
			} else
				l += (long)first * 40;
		}
		i = 0;
		if (use_bn) {
			int blsize;
			blsize = BN_num_bits(bl);
			blsize = (blsize + 6) / 7;
			if (blsize > tmpsize) {
				if (tmp != ftmp)
					free(tmp);
				tmpsize = blsize + 32;
				tmp = malloc(tmpsize);
				if (!tmp)
					goto err;
			}
			while (blsize--)
				tmp[i++] = (unsigned char)BN_div_word(bl, 0x80L);
		} else {

			for (;;) {
				tmp[i++] = (unsigned char)l & 0x7f;
				l >>= 7L;
				if (l == 0L)
					break;
			}

		}
		if (out != NULL) {
			if (len + i > olen) {
				ASN1err(ASN1_F_A2D_ASN1_OBJECT,
				    ASN1_R_BUFFER_TOO_SMALL);
				goto err;
			}
			while (--i > 0)
				out[len++] = tmp[i]|0x80;
			out[len++] = tmp[0];
		} else
			len += i;
	}
	if (tmp != ftmp)
		free(tmp);
	BN_free(bl);
	return (len);

err:
	if (tmp != ftmp)
		free(tmp);
	BN_free(bl);
	return (0);
}
예제 #12
0
void BigNumber::SetDword(uint32 val)
{
    BN_set_word(_bn, val);
}
예제 #13
0
파일: keys.c 프로젝트: matja/bitcoin-tool
static EC_GROUP *ec_group_new_from_data(const EC_CURVE_DATA *data)
{
	EC_GROUP *group = NULL;
	EC_POINT *P = NULL;
	BN_CTX *ctx = NULL;
	BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL, *order = NULL;
	int ok = 0;
	int seed_len = 0;
	int param_len = 0;
	const unsigned char *params = NULL;

	ctx = BN_CTX_new();
	if (ctx == NULL) {
		ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_MALLOC_FAILURE);
		goto err;
	}

	seed_len = data->seed_len;
	param_len = data->param_len;
	params = (const unsigned char *)(data+1); /* skip header */
	params += seed_len; /* skip seed   */

	if (
		   !(p = BN_bin2bn(params+0*param_len, param_len, NULL))
		|| !(a = BN_bin2bn(params+1*param_len, param_len, NULL))
		|| !(b = BN_bin2bn(params+2*param_len, param_len, NULL))
	) {
		ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB);
		goto err;
	}

	if ((group = EC_GROUP_new_curve_GFp(p, a, b, ctx)) == NULL) {
		ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
		goto err;
	}

	if ((P = EC_POINT_new(group)) == NULL) {
		ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
	goto err;
	}

	if (
		   !(x = BN_bin2bn(params+3*param_len, param_len, NULL))
		|| !(y = BN_bin2bn(params+4*param_len, param_len, NULL))
	) {
		ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB);
		goto err;
	}

	if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) {
		ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
		goto err;
	}

	if (
		!(order = BN_bin2bn(params+5*param_len, param_len, NULL))
		|| !BN_set_word(x, (BN_ULONG)data->cofactor)
	) {
		ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB);
		goto err;
	}

	if (!EC_GROUP_set_generator(group, P, order, x)) {
		ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
		goto err;
	}

	if (seed_len) {
		if (!EC_GROUP_set_seed(group, params-seed_len, seed_len)) {
			ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
			goto err;
		}
	}

	ok = 1;
err:
	if (!ok) {
		EC_GROUP_free(group);
		group = NULL;
	}

	if (P) { EC_POINT_free(P); }
	if (ctx) { BN_CTX_free(ctx); }
	if (p) { BN_free(p); }
	if (a) { BN_free(a); }
	if (b) { BN_free(b); }
	if (order) { BN_free(order);}
	if (x) { BN_free(x); }
	if (y) { BN_free(y); }
	return group;
}
예제 #14
0
/* Actually there is no reason to insist that 'generator' be a generator.
 * It's just as OK (and in some sense better) to use a generator of the
 * order-q subgroup.
 */
static int dh_builtin_genparams(DH *ret, int prime_len, int generator, BN_GENCB *cb)
	{
	BIGNUM *t1,*t2;
	int g,ok= -1;
	BN_CTX *ctx=NULL;

	ctx=BN_CTX_new();
	if (ctx == NULL) goto err;
	BN_CTX_start(ctx);
	t1 = BN_CTX_get(ctx);
	t2 = BN_CTX_get(ctx);
	if (t1 == NULL || t2 == NULL) goto err;

	/* Make sure 'ret' has the necessary elements */
	if(!ret->p && ((ret->p = BN_new()) == NULL)) goto err;
	if(!ret->g && ((ret->g = BN_new()) == NULL)) goto err;
	
	if (generator <= 1)
		{
		DHerr(DH_F_DH_BUILTIN_GENPARAMS, DH_R_BAD_GENERATOR);
		goto err;
		}
	if (generator == DH_GENERATOR_2)
		{
		if (!BN_set_word(t1,24)) goto err;
		if (!BN_set_word(t2,11)) goto err;
		g=2;
		}
#if 0 /* does not work for safe primes */
	else if (generator == DH_GENERATOR_3)
		{
		if (!BN_set_word(t1,12)) goto err;
		if (!BN_set_word(t2,5)) goto err;
		g=3;
		}
#endif
	else if (generator == DH_GENERATOR_5)
		{
		if (!BN_set_word(t1,10)) goto err;
		if (!BN_set_word(t2,3)) goto err;
		/* BN_set_word(t3,7); just have to miss
		 * out on these ones :-( */
		g=5;
		}
	else
		{
		/* in the general case, don't worry if 'generator' is a
		 * generator or not: since we are using safe primes,
		 * it will generate either an order-q or an order-2q group,
		 * which both is OK */
		if (!BN_set_word(t1,2)) goto err;
		if (!BN_set_word(t2,1)) goto err;
		g=generator;
		}
	
	if(!BN_generate_prime_ex(ret->p,prime_len,1,t1,t2,cb)) goto err;
	if(!BN_GENCB_call(cb, 3, 0)) goto err;
	if (!BN_set_word(ret->g,g)) goto err;
	ok=1;
err:
	if (ok == -1)
		{
		DHerr(DH_F_DH_BUILTIN_GENPARAMS,ERR_R_BN_LIB);
		ok=0;
		}

	if (ctx != NULL)
		{
		BN_CTX_end(ctx);
		BN_CTX_free(ctx);
		}
	return ok;
	}
예제 #15
0
BigNumber::BigNumber(uint32 val)
    : _bn(BN_new())
{
    BN_set_word(_bn, val);
}
예제 #16
0
void
printnumber(FILE *f, const struct number *b, u_int base)
{
	struct number	*int_part, *fract_part;
	int		digits;
	char		buf[11];
	size_t		sz;
	int		i;
	struct stack	stack;
	char		*p;

	charcount = 0;
	lastchar = -1;
	if (BN_is_zero(b->number))
		putcharwrap(f, '0');

	int_part = new_number();
	fract_part = new_number();
	fract_part->scale = b->scale;

	if (base <= 16)
		digits = 1;
	else {
		digits = snprintf(buf, sizeof(buf), "%u", base-1);
	}
	split_number(b, int_part->number, fract_part->number);

	i = 0;
	stack_init(&stack);
	while (!BN_is_zero(int_part->number)) {
		BN_ULONG rem = BN_div_word(int_part->number, base);
		stack_pushstring(&stack, get_digit(rem, digits, base));
		i++;
	}
	sz = i;
	if (BN_cmp(b->number, &zero) < 0)
		putcharwrap(f, '-');
	for (i = 0; i < sz; i++) {
		p = stack_popstring(&stack);
		if (base > 16)
			putcharwrap(f, ' ');
		printwrap(f, p);
		free(p);
	}
	stack_clear(&stack);
	if (b->scale > 0) {
		struct number	*num_base;
		BIGNUM		mult, stop;

		putcharwrap(f, '.');
		num_base = new_number();
		BN_set_word(num_base->number, base);
		BN_init(&mult);
		BN_one(&mult);
		BN_init(&stop);
		BN_one(&stop);
		scale_number(&stop, b->scale);

		i = 0;
		while (BN_cmp(&mult, &stop) < 0) {
			u_long	rem;

			if (i && base > 16)
				putcharwrap(f, ' ');
			i = 1;

			bmul_number(fract_part, fract_part, num_base);
			split_number(fract_part, int_part->number, NULL);
			rem = BN_get_word(int_part->number);
			p = get_digit(rem, digits, base);
			int_part->scale = 0;
			normalize(int_part, fract_part->scale);
			BN_sub(fract_part->number, fract_part->number,
			    int_part->number);
			printwrap(f, p);
			free(p);
			BN_mul_word(&mult, base);
		}
		free_number(num_base);
		BN_free(&mult);
		BN_free(&stop);
	}
	flushwrap(f);
	free_number(int_part);
	free_number(fract_part);
}
예제 #17
0
파일: dh.c 프로젝트: Henauxg/minix
int
DH_check_pubkey(const DH *dh, const BIGNUM *pub_key, int *codes)
{
    BIGNUM *bn = NULL, *sum = NULL;
    int ret = 0;

    *codes = 0;

    /**
     * Checks that the function performs are:
     * - pub_key is not negative
     */

    if (BN_is_negative(pub_key))
	goto out;

    /**
     * - pub_key > 1    and    pub_key < p - 1,
     *    to avoid small subgroups attack.
     */

    bn = BN_new();
    if (bn == NULL)
	goto out;

    if (!BN_set_word(bn, 1))
	goto out;

    if (BN_cmp(bn, pub_key) >= 0)
	*codes |= DH_CHECK_PUBKEY_TOO_SMALL;

    sum = BN_new();
    if (sum == NULL)
	goto out;

    BN_uadd(sum, pub_key, bn);

    if (BN_cmp(sum, dh->p) >= 0)
	*codes |= DH_CHECK_PUBKEY_TOO_LARGE;

    /**
     * - if g == 2, pub_key have more then one bit set,
     *   if bits set is 1, log_2(pub_key) is trival
     */

    if (!BN_set_word(bn, 2))
	goto out;

    if (BN_cmp(bn, dh->g) == 0) {
	unsigned i, n = BN_num_bits(pub_key);
	unsigned bits = 0;

	for (i = 0; i <= n; i++)
	    if (BN_is_bit_set(pub_key, i))
		bits++;

	if (bits < 2) {
	    *codes |= DH_CHECK_PUBKEY_TOO_SMALL;
	    goto out;
	}
    }

    ret = 1;
out:
    if (bn)
	BN_free(bn);
    if (sum)
	BN_free(sum);

    return ret;
}
예제 #18
0
/* ------------------------------------------------------------------ */
char *eg_encode (char *s, int length, char *public_key)
{
    // we use NULL-with-random padding. this allows to pass
    // NULL-terminated strings without any additional processing.
    // if you want to exchange binary data, define your own padding in
    // your application or pass the data length somehow

    BIGNUM         message, gamma, delta, k, temp;
    BIGNUM         *p=NULL, *g=NULL, *key=NULL;
    int            i, nl, nc, no, pc, rc1, rc2, rc3, index;
    unsigned char  *buf = NULL;
    BN_CTX         *ctx = NULL;
    char           *p1, *p2, *p3, *output;

    // setup key (p, g, key)
    p1 = strdup (public_key);
    p2 = strchr (p1, ':');
    if (p2 == NULL) {free (p1); return NULL;}
    *p2 = '\0';
    p3 = strchr (p1, ',');
    if (p3 == NULL)
    {
        index = atoi (p1);
        if (index > sizeof(precomp)/sizeof(precomp[0])-1) return NULL;
        p = NULL;
        rc1 = BN_hex2bn (&p, precomp[index].prime);
        if (rc1 == 0) return NULL;
        g = BN_new ();
        if (g == NULL) return NULL;
        BN_set_word (g, precomp[index].generator);
    }
    else
    {
        rc1 = BN_hex2bn (&p, p1);
        rc2 = BN_hex2bn (&g, p3+1);
        if (rc1 == 0 || rc2 == 0) return NULL;
    }
    rc3 = BN_hex2bn (&key, p2+1);
    free (p1);
    if (rc3 == 0) return NULL;
                 
    // initialize temp variables
    BN_init (&message);
    BN_init (&gamma);
    BN_init (&delta);
    BN_init (&k);
    BN_init (&temp);
    ctx = BN_CTX_new ();
    if (ctx == NULL) return NULL;

    // number of bytes in p. this is the amount of bytes
    // we can convert in one gulp
    nl = BN_num_bytes (p);
    buf = malloc (nl);
    if (buf == NULL) return NULL;

    // compute the 'nc', the number of cycles (gulps)
    nc = length/nl;
    if (length % nl) nc++;
    
    // preallocate output buffer: nl*2 -- bin->hex conversion,
    // nl*2*2 + 1 -- each gulp consists of two bignums and comma
    // between them, nl*2*2+1+1 -- spaces between gulps in the output
    no = nc * (nl*2*2+1+1) + 1;
    output = malloc (no);
    if (output == NULL) return NULL;
    output[0] = '\0';

    // cycle by pieces of input, each piece is 'nl' bytes long
    // (except the last one)
    for (i=0; i<nc; i++)
    {
        // compute piece length
        pc = (i == nc-1) ? length % nl : nl;
        memcpy (buf, s+i*nl, pc);
        // do NULL+random padding if necessary
        if (pc != nl)
        {
            buf[pc] = '\0';
            if (nl-pc-1 > 0)
                rand_bytes (buf+pc+1, nl-pc-1);
        }
        // convert to bignum
        BN_bin2bn (buf, nl, &message);
        // ElGamal: get random k, gamma = g^k mod p, delta = message * key^k mod p
        BN_rand (&k, BN_num_bits (p)-1, 0, 0);
        BN_mod_exp (&gamma, g,   &k, p, ctx);
        BN_mod_exp (&temp,  key, &k, p, ctx);
        BN_mod_mul (&delta, &temp, &message, p, ctx);
        // convert into hex
        p1 = BN_bn2hex (&gamma);
        p2 = BN_bn2hex (&delta);
        // copy result to output buffer and add delimiting space
        // fairly ineffective at the moment
        strcat (output, p1);
        strcat (output, ",");
        strcat (output, p2);
        if (i != nc-1) strcat (output, " ");
        free (p1);
        free (p2);
    }
    
    BN_CTX_free (ctx);
    BN_clear_free (p);
    BN_clear_free (g);
    BN_clear_free (key);
    memset (buf, 0, nl);
    free(buf);

    return output;
}
예제 #19
0
int main(int argc, char* argv[]){
  
  // Local Variable definitions
  int i, j, k;
  size_t ret;
  int rsa_byte_size = RSA_KEY_SIZE/8;

  // buffer used to seed the PRNG
  unsigned char seed[rsa_byte_size];
  //unsigned char *keybuff;
  unsigned char *priv;
  unsigned char *pub;
  unsigned char *mod;
  size_t keybuff_len=0;

  // File pointers
  FILE *urand;
  FILE *pubkeyfile;
  FILE *privkeyfile;

  // RSA Struct used to store Priv/Pub key vals
  RSA *key = RSA_new();

  // Set the exponent size, e, to be used by RSA.
  BIGNUM *e = BN_new();

  // Open the public keyfile
  pubkeyfile = fopen("./publickey.txt","w+");
  if(pubkeyfile == NULL){
      fprintf(stderr, "ERROR: Unable to open publickey.txt for writing!\n");
      exit(-1);
  }

  // Open the private keyfile
  privkeyfile = fopen("./secretkey.txt","w+");
  if(privkeyfile == NULL){
      fprintf(stderr, "ERROR: Unable to open privatekey.txt for writing!\n");
      exit(-1);
  }

  // Open dev rand to seed our random data.
  urand = fopen("/dev/urandom","r");
  if(urand == NULL){
      fprintf(stderr, "ERROR: Unable to open /dev/urandom for reading!\n");
      exit(-1);
  }

  // Read the rand data from /dev/urandom
  ret = fread(&seed, sizeof(char), RSA_KEY_SIZE/8, urand);
  if(ret < RSA_KEY_SIZE/8){
      fprintf(stderr, "ERROR: Unable to obtain random seed from /dev/urandom!\n");
      exit(-1);
  }
  
  // Seed the PRNG
  RAND_seed(&seed, RSA_KEY_SIZE/8);

  // Setup our BIGNUM, this acts as the exponent e and will be stored with the pub/priv keys struct
  // read the BN_rand description to see why the last two args are 1.
  //ret = BN_generate_prime_ex(e, RSA_KEY_SIZE, 1, NULL, NULL, NULL);
  ret = BN_set_word(e, 0x10001); // 65537
  if(!ret){
    fprintf(stderr, "ERROR: There was a problem generating the mod 'e'\n");
    exit(-1);
  }


  // NOTE: As per the OpenSSL docs, RSA_generate_key(...) is deprecated.
  // int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
  // Generate the RSA keys
  ret = RSA_generate_key_ex(key, RSA_KEY_SIZE, e, NULL);

  /* Currently, the OpenSSL doc does not detail the return value of RSA_generate_key_ex :-( */
  if(!ret){
    fprintf(stderr, "ERROR: There was a problem generating RSA key!\n");
    exit(-1);
  }

/*
  printf("DBG: Public Key - ");
  char * n_val = BN_bn2hex(key->n);
  for(i = 0; i < 256; i++){
    printf("%c", n_val[i]);
  }
  printf("\n");
*/


  if(!PEM_write_RSAPublicKey(pubkeyfile, key)){
    fprintf(stderr, "ERROR: There was a problem writing the Public RSA key!\n");
    exit(-1);
  }
  if(!PEM_write_RSAPrivateKey(privkeyfile, key, NULL, NULL, 0, NULL, NULL)){
    fprintf(stderr, "ERROR: There was a problem writing the Private RSA key!\n");
    exit(-1);
  }

/*
  // Write the public and private key values out to disk respectively
  //i = BN_num_bytes(key->e);
  //j = BN_num_bits(key->e);
  //keybuff = BN_bn2hex(key->e);
  priv = BN_bn2hex(key->d);
  pub  = BN_bn2hex(key->e);
  mod  = BN_bn2hex(key->n);

  // Write out the public modulus, n
  j = BN_num_bytes(key->e);
  for(i = 0; i < j; i++){
    fprintf(pubkeyfile, "%c", mod[i]);
    fprintf(privkeyfile, "%c", mod[i]);
  }
  fprintf(pubkeyfile,"\n");
  fprintf(privkeyfile,"\n");

  // Write out the public key
  j = BN_num_bytes(key->e);
  for(i = 0; i < j; i++){
    fprintf(pubkeyfile, "%c", pub[i]);
  }

  // Write out the private key
  j = BN_num_bytes(key->d);
  for(i = 0; i < j; i++){
    fprintf(privkeyfile, "%c", priv[i]);
  }
*/

  //printf("DBG: Number of bytes in e - %d\n", i);
  //DBG: Number of bytes in e - 256
  //printf("DBG: Number of bits in e - %d\n", j);
  //DBG: Number of bits in e - 2048

  /*
  printf("DBG: Print e:\n");
  for(k = 0; k < i; k++){
    printf("%c",keybuff[k]);
  }
  printf("\nDone.\n");

  // Note, the below is 256 characters, or 2048 bits worth of data.

  DBG: Print e:
  DF61CD9DCFF8B60F8302098EEA099F1B9ECED5C5AD3C98E129D380121A765BE089D6FAFEBACF272B5A87FC98995
  A259D6F9D069805436F0B93AFBB02ABAD2C19DD767F25DC25226DA99B24C92727A0F583FE8CAD4C60702A1F4EDB
  7F8E3A872519A8515DCBB963E676939FDCC2DFFD40C970137952FADB5048F7DAB4632646C8
  Done.

  */


  // Free allocated memory
  fclose(urand);
  fclose(pubkeyfile);
  fclose(privkeyfile);

  // Free the allocated RSA structures.
  RSA_free(key);
  BN_free(e);

  return 1;
}
예제 #20
0
/* ------------------------------------------------------------------ */
int eg_decode (char *s, char *private_key, char **result)
{
    // there is no any padding processing in the decoding routine
    //  (see comment in rsa_encode)

    BIGNUM         message, *gamma, *delta, k, temp1, temp2, one;
    BIGNUM         *p=NULL, *g=NULL, *key=NULL;
    int            i, nl, nc, rc1, rc2, rc3, length, index;
    unsigned char  *buf = NULL;
    BN_CTX         *ctx = NULL;
    char           *p1, *p2, *p3;

    // setup key (p, g, key)
    p1 = strdup (private_key);
    p2 = strchr (p1, ':');
    if (p2 == NULL) {free (p1); return -1;}
    *p2 = '\0';
    p3 = strchr (p1, ',');
    if (p3 == NULL)
    {
        index = atoi (p1);
        if (index > sizeof(precomp)/sizeof(precomp[0])-1) return -1;
        p = NULL;
        rc1 = BN_hex2bn (&p, precomp[index].prime);
        if (rc1 == 0) return -1;
        g = BN_new ();
        if (g == NULL) return -1;
        BN_set_word (g, precomp[index].generator);
    }
    else
    {
        rc1 = BN_hex2bn (&p, p1);
        rc2 = BN_hex2bn (&g, p3+1);
        if (rc1 == 0 || rc2 == 0) return -1;
    }
    rc3 = BN_hex2bn (&key, p2+1);
    free (p1);
    if (rc3 == 0) return -1;

    // initialize temp variables
    BN_init (&message);
    BN_init (&k);
    BN_init (&temp1);
    BN_init (&temp2);
    BN_init (&one);
    BN_one (&one);
    gamma = BN_new ();
    if (gamma == NULL) return -1;
    delta = BN_new ();
    if (delta == NULL) return -1;
    ctx = BN_CTX_new ();
    if (ctx == NULL) return -1;

    // number of bytes in the modulus. this is the amount of bytes
    // we can convert in one gulp and should expect to be in one
    // group
    nl = BN_num_bytes (p);
    buf = malloc (nl);
    if (buf == NULL) return -1;

    // find the number of pieces in the encrypted message (the last
    // piece is not terminated with space)
    nc = str_numchars (s, ' ') + 1;
    
    // preallocate output buffer
    length = nc * nl;
    *result = malloc (length);
    if (*result == NULL) return -1;

    // cycle by pieces of input, each piece is 'nl' bytes long
    // (except the last one)
    p1 = s;
    for (i=0; i<nc; i++)
    {
        // extract next piece
        p2 = strchr (p1, ' ');
        if (p2 == NULL)
        {
            if (i != nc-1) return -1;
        }
        else
        {
            *p2 = '\0';
        }
        p3 = strchr (p1, ',');
        if (p3 == NULL) return -1;
        *p3++ = '\0';
        // convert to bignum
        rc1 = BN_hex2bn (&gamma, p1);
        if (rc1 == 0) return -1;
        rc1 = BN_hex2bn (&delta, p3);
        if (rc1 == 0) return -1;
        // ElGamal
        BN_sub (&temp1, p, &one);
        BN_sub (&temp2, &temp1, key);
        BN_mod_exp (&temp1, gamma, &temp2, p, ctx);
        BN_mod_mul (&message, &temp1, delta, p, ctx);
        // convert into binary output
        BN_bn2bin (&message, (unsigned char *)(*result+i*nl));
        // advance pointer to prepare search for next piece
        p1 = p2 + 1;
    }
    
    BN_CTX_free (ctx);
    memset (buf, 0, nl);
    free(buf);

    return length;
}
예제 #21
0
파일: dtls.c 프로젝트: cahlbin/rtpengine
static int cert_init() {
	X509 *x509 = NULL;
	EVP_PKEY *pkey = NULL;
	BIGNUM *exponent = NULL, *serial_number = NULL;
	RSA *rsa = NULL;
	ASN1_INTEGER *asn1_serial_number;
	X509_NAME *name;
	struct dtls_cert *new_cert;

	ilog(LOG_INFO, "Generating new DTLS certificate");

	/* objects */

	pkey = EVP_PKEY_new();
	exponent = BN_new();
	rsa = RSA_new();
	serial_number = BN_new();
	name = X509_NAME_new();
	x509 = X509_new();
	if (!exponent || !pkey || !rsa || !serial_number || !name || !x509)
		goto err;

	/* key */

	if (!BN_set_word(exponent, 0x10001))
		goto err;

	if (!RSA_generate_key_ex(rsa, 1024, exponent, NULL))
		goto err;

	if (!EVP_PKEY_assign_RSA(pkey, rsa))
		goto err;

	/* x509 cert */

	if (!X509_set_pubkey(x509, pkey))
		goto err;

	/* serial */

	if (!BN_pseudo_rand(serial_number, 64, 0, 0))
		goto err;

	asn1_serial_number = X509_get_serialNumber(x509);
	if (!asn1_serial_number)
		goto err;

	if (!BN_to_ASN1_INTEGER(serial_number, asn1_serial_number))
		goto err;

	/* version 1 */

	if (!X509_set_version(x509, 0L))
		goto err;

	/* common name */

	if (!X509_NAME_add_entry_by_NID(name, NID_commonName, MBSTRING_UTF8,
				(unsigned char *) "rtpengine", -1, -1, 0))
		goto err;

	if (!X509_set_subject_name(x509, name))
		goto err;

	if (!X509_set_issuer_name(x509, name))
		goto err;

	/* cert lifetime */

	if (!X509_gmtime_adj(X509_get_notBefore(x509), -60*60*24))
		goto err;

	if (!X509_gmtime_adj(X509_get_notAfter(x509), CERT_EXPIRY_TIME))
		goto err;

	/* sign it */

	if (!X509_sign(x509, pkey, EVP_sha1()))
		goto err;

	/* digest */

	new_cert = obj_alloc0("dtls_cert", sizeof(*new_cert), cert_free);
	new_cert->fingerprint.hash_func = &hash_funcs[0];
	dtls_fingerprint_hash(&new_cert->fingerprint, x509);

	new_cert->x509 = x509;
	new_cert->pkey = pkey;
	new_cert->expires = time(NULL) + CERT_EXPIRY_TIME;

	dump_cert(new_cert);

	/* swap out certs */

	rwlock_lock_w(&__dtls_cert_lock);

	if (__dtls_cert)
		obj_put(__dtls_cert);
	__dtls_cert = new_cert;

	rwlock_unlock_w(&__dtls_cert_lock);

	/* cleanup */

	BN_free(exponent);
	BN_free(serial_number);
	X509_NAME_free(name);

	return 0;

err:
	ilog(LOG_ERROR, "Failed to generate DTLS certificate");

	if (pkey)
		EVP_PKEY_free(pkey);
	if (exponent)
		BN_free(exponent);
	if (rsa)
		RSA_free(rsa);
	if (x509)
		X509_free(x509);
	if (serial_number)
		BN_free(serial_number);

	return -1;
}
예제 #22
0
파일: test_bn.c 프로젝트: Henauxg/minix
static int
test_BN_uadd(void)
{
    BIGNUM *a, *b, *c;
    char *p;

    a = BN_new();
    b = BN_new();
    c = BN_new();

    BN_set_word(a, 1);
    BN_set_word(b, 2);

    BN_uadd(c, a, b);

    if (BN_get_word(c) != 3)
	return 1;

    BN_uadd(c, b, a);

    if (BN_get_word(c) != 3)
	return 1;

    BN_set_word(b, 0xff);

    BN_uadd(c, a, b);
    if (BN_get_word(c) != 0x100)
	return 1;

    BN_uadd(c, b, a);
    if (BN_get_word(c) != 0x100)
	return 1;

    BN_set_word(a, 0xff);

    BN_uadd(c, a, b);
    if (BN_get_word(c) != 0x1fe)
	return 1;

    BN_uadd(c, b, a);
    if (BN_get_word(c) != 0x1fe)
	return 1;


    BN_free(a);
    BN_free(b);

    BN_hex2bn(&a, "50212A3B611D46642C825A16A354CE0FD4D85DD2");
    BN_hex2bn(&b, "84B6C7E8D28ACA1614954DA");

    BN_uadd(c, b, a);
    p = BN_bn2hex(c);
    if (strcmp(p, "50212A3B611D466434CDC695307D7AB13621B2AC") != 0) {
	free(p);
	return 1;
    }
    free(p);

    BN_uadd(c, a, b);
    p = BN_bn2hex(c);
    if (strcmp(p, "50212A3B611D466434CDC695307D7AB13621B2AC") != 0) {
	free(p);
	return 1;
    }
    free(p);

    BN_free(a);
    BN_free(b);
    BN_free(c);

    return 0;
}
예제 #23
0
BigNumber::BigNumber(uint32 val)
{
    _bn = BN_new();
    BN_set_word(_bn, val);
    _array = NULL;
}
예제 #24
0
파일: test_bn.c 프로젝트: Henauxg/minix
static int
test_BN_bit(void)
{
    BIGNUM *bn;
    int ret = 0;

    bn = BN_new();

    /* test setting and getting of "word" */
    if (!BN_set_word(bn, 1))
	return 1;
    if (!BN_is_bit_set(bn, 0))
	ret += 1;
    if (!BN_is_bit_set(bn, 0))
	ret += 1;

    if (!BN_set_word(bn, 2))
	return 1;
    if (!BN_is_bit_set(bn, 1))
	ret += 1;

    if (!BN_set_word(bn, 3))
	return 1;
    if (!BN_is_bit_set(bn, 0))
	ret += 1;
    if (!BN_is_bit_set(bn, 1))
	ret += 1;

    if (!BN_set_word(bn, 0x100))
	return 1;
    if (!BN_is_bit_set(bn, 8))
	ret += 1;

    if (!BN_set_word(bn, 0x1000))
	return 1;
    if (!BN_is_bit_set(bn, 12))
	ret += 1;

    /* test bitsetting */
    if (!BN_set_word(bn, 1))
	return 1;
    if (!BN_set_bit(bn, 1))
	return 1;
    if (BN_get_word(bn) != 3)
	return 1;
    if (!BN_clear_bit(bn, 0))
	return 1;
    if (BN_get_word(bn) != 2)
	return 1;

    /* test bitsetting past end of current end */
    BN_clear(bn);
    if (!BN_set_bit(bn, 12))
	return 1;
    if (BN_get_word(bn) != 0x1000)
	return 1;

    /* test bit and byte counting functions */
    if (BN_num_bits(bn) != 13)
	return 1;
    if (BN_num_bytes(bn) != 2)
	return 1;

    BN_free(bn);
    return ret;
}
예제 #25
0
static EVP_PKEY *capi_get_pkey(ENGINE *eng, CAPI_KEY *key)
	{
	unsigned char *pubkey = NULL;
	DWORD len;
	BLOBHEADER *bh;
	RSA *rkey = NULL;
	DSA *dkey = NULL;
	EVP_PKEY *ret = NULL;
	if (!CryptExportKey(key->key, 0, PUBLICKEYBLOB, 0, NULL, &len))
		{
		CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_PUBKEY_EXPORT_LENGTH_ERROR);
		capi_addlasterror();
		return NULL;
		}

	pubkey = OPENSSL_malloc(len);

	if (!pubkey)
		goto memerr;

	if (!CryptExportKey(key->key, 0, PUBLICKEYBLOB, 0, pubkey, &len))
		{
		CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_PUBKEY_EXPORT_ERROR);
		capi_addlasterror();
		goto err;
		}

	bh = (BLOBHEADER *)pubkey;
	if (bh->bType != PUBLICKEYBLOB)
		{
		CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_INVALID_PUBLIC_KEY_BLOB);
		goto err;
		}
	if (bh->aiKeyAlg == CALG_RSA_SIGN || bh->aiKeyAlg == CALG_RSA_KEYX)
		{
		RSAPUBKEY *rp;
		DWORD rsa_modlen;
		unsigned char *rsa_modulus;
		rp = (RSAPUBKEY *)(bh + 1);
		if (rp->magic != 0x31415352)
			{
			char magstr[10];
			BIO_snprintf(magstr, 10, "%lx", rp->magic);
			CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_INVALID_RSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER);
			ERR_add_error_data(2, "magic=0x", magstr);
			goto err;
			}
		rsa_modulus = (unsigned char *)(rp + 1);
		rkey = RSA_new_method(eng);
		if (!rkey)
			goto memerr;

		rkey->e = BN_new();
		rkey->n = BN_new();

		if (!rkey->e || !rkey->n)
			goto memerr;

		if (!BN_set_word(rkey->e, rp->pubexp))
			goto memerr;

		rsa_modlen = rp->bitlen / 8;
		if (!lend_tobn(rkey->n, rsa_modulus, rsa_modlen))
			goto memerr;

		RSA_set_ex_data(rkey, rsa_capi_idx, key);

		if (!(ret = EVP_PKEY_new()))
			goto memerr;

		EVP_PKEY_assign_RSA(ret, rkey);
		rkey = NULL;

		}
	else if (bh->aiKeyAlg == CALG_DSS_SIGN)
		{
		DSSPUBKEY *dp;
		DWORD dsa_plen;
		unsigned char *btmp;
		dp = (DSSPUBKEY *)(bh + 1);
		if (dp->magic != 0x31535344)
			{
			char magstr[10];
			BIO_snprintf(magstr, 10, "%lx", dp->magic);
			CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_INVALID_DSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER);
			ERR_add_error_data(2, "magic=0x", magstr);
			goto err;
			}
		dsa_plen = dp->bitlen / 8;
		btmp = (unsigned char *)(dp + 1);
		dkey = DSA_new_method(eng);
		if (!dkey)
			goto memerr;
		dkey->p = BN_new();
		dkey->q = BN_new();
		dkey->g = BN_new();
		dkey->pub_key = BN_new();
		if (!dkey->p || !dkey->q || !dkey->g || !dkey->pub_key)
			goto memerr;
		if (!lend_tobn(dkey->p, btmp, dsa_plen))
			goto memerr;
		btmp += dsa_plen;
		if (!lend_tobn(dkey->q, btmp, 20))
			goto memerr;
		btmp += 20;
		if (!lend_tobn(dkey->g, btmp, dsa_plen))
			goto memerr;
		btmp += dsa_plen;
		if (!lend_tobn(dkey->pub_key, btmp, dsa_plen))
			goto memerr;
		btmp += dsa_plen;

		DSA_set_ex_data(dkey, dsa_capi_idx, key);

		if (!(ret = EVP_PKEY_new()))
			goto memerr;

		EVP_PKEY_assign_DSA(ret, dkey);
		dkey = NULL;
		}
	else
		{
		char algstr[10];
		BIO_snprintf(algstr, 10, "%lx", bh->aiKeyAlg);
		CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_UNSUPPORTED_PUBLIC_KEY_ALGORITHM);
		ERR_add_error_data(2, "aiKeyAlg=0x", algstr);
		goto err;
		}


	err:
	if (pubkey)
		OPENSSL_free(pubkey);
	if (!ret)
		{
		if (rkey)
			RSA_free(rkey);
		if (dkey)
			DSA_free(dkey);
		}

	return ret;

memerr:
	CAPIerr(CAPI_F_CAPI_GET_PKEY, ERR_R_MALLOC_FAILURE);
	goto err;

	}
예제 #26
0
파일: ec.c 프로젝트: luocn99/tgw-boringssl
static EC_GROUP *ec_group_new_from_data(const struct built_in_curve *curve) {
  EC_GROUP *group = NULL;
  EC_POINT *P = NULL;
  BN_CTX *ctx = NULL;
  BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL, *order = NULL;
  int ok = 0;
  unsigned param_len;
  const EC_METHOD *meth;
  const struct curve_data *data;
  const uint8_t *params;

  if ((ctx = BN_CTX_new()) == NULL) {
    OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
    goto err;
  }

  data = curve->data;
  param_len = data->param_len;
  params = data->data;

  if (!(p = BN_bin2bn(params + 0 * param_len, param_len, NULL)) ||
      !(a = BN_bin2bn(params + 1 * param_len, param_len, NULL)) ||
      !(b = BN_bin2bn(params + 2 * param_len, param_len, NULL))) {
    OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
    goto err;
  }

  if (curve->method != 0) {
    meth = curve->method();
    if (((group = ec_group_new(meth)) == NULL) ||
        (!(group->meth->group_set_curve(group, p, a, b, ctx)))) {
      OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
      goto err;
    }
  } else {
    if ((group = EC_GROUP_new_curve_GFp(p, a, b, ctx)) == NULL) {
      OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
      goto err;
    }
  }

  if ((P = EC_POINT_new(group)) == NULL) {
    OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
    goto err;
  }

  if (!(x = BN_bin2bn(params + 3 * param_len, param_len, NULL)) ||
      !(y = BN_bin2bn(params + 4 * param_len, param_len, NULL))) {
    OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
    goto err;
  }

  if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) {
    OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
    goto err;
  }
  if (!(order = BN_bin2bn(params + 5 * param_len, param_len, NULL)) ||
      !BN_set_word(x, (BN_ULONG)data->cofactor)) {
    OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
    goto err;
  }

  group->generator = P;
  P = NULL;
  if (!BN_copy(&group->order, order) ||
      !BN_set_word(&group->cofactor, (BN_ULONG)data->cofactor)) {
    OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
    goto err;
  }

  ok = 1;

err:
  if (!ok) {
    EC_GROUP_free(group);
    group = NULL;
  }
  EC_POINT_free(P);
  BN_CTX_free(ctx);
  BN_free(p);
  BN_free(a);
  BN_free(b);
  BN_free(order);
  BN_free(x);
  BN_free(y);
  return group;
}
예제 #27
0
int MAIN(int argc, char **argv)
	{
	BN_GENCB cb;
#ifndef OPENSSL_NO_ENGINE
	ENGINE *e = NULL;
#endif
	int ret=1;
	int i,num=DEFBITS;
	long l;
	const EVP_CIPHER *enc=NULL;
	unsigned long f4=RSA_F4;
	char *outfile=NULL;
	char *passargout = NULL, *passout = NULL;
#ifndef OPENSSL_NO_ENGINE
	char *engine=NULL;
#endif
	char *inrand=NULL;
	BIO *out=NULL;
	BIGNUM *bn = BN_new();
	RSA *rsa = NULL;

	if(!bn) goto err;

	apps_startup();
	BN_GENCB_set(&cb, genrsa_cb, bio_err);

	if (bio_err == NULL)
		if ((bio_err=BIO_new(BIO_s_file())) != NULL)
			BIO_set_fp(bio_err,OPENSSL_TYPE__FILE_STDERR,BIO_NOCLOSE|BIO_FP_TEXT);

	if (!load_config(bio_err, NULL))
		goto err;
	if ((out=BIO_new(BIO_s_file())) == NULL)
		{
		BIO_printf(bio_err,"unable to create BIO for output\n");
		goto err;
		}

	argv++;
	argc--;
	for (;;)
		{
		if (argc <= 0) break;
		if (TINYCLR_SSL_STRCMP(*argv,"-out") == 0)
			{
			if (--argc < 1) goto bad;
			outfile= *(++argv);
			}
		else if (TINYCLR_SSL_STRCMP(*argv,"-3") == 0)
			f4=3;
		else if (TINYCLR_SSL_STRCMP(*argv,"-F4") == 0 || TINYCLR_SSL_STRCMP(*argv,"-f4") == 0)
			f4=RSA_F4;
#ifndef OPENSSL_NO_ENGINE
		else if (TINYCLR_SSL_STRCMP(*argv,"-engine") == 0)
			{
			if (--argc < 1) goto bad;
			engine= *(++argv);
			}
#endif
		else if (TINYCLR_SSL_STRCMP(*argv,"-rand") == 0)
			{
			if (--argc < 1) goto bad;
			inrand= *(++argv);
			}
#ifndef OPENSSL_NO_DES
		else if (TINYCLR_SSL_STRCMP(*argv,"-des") == 0)
			enc=EVP_des_cbc();
		else if (TINYCLR_SSL_STRCMP(*argv,"-des3") == 0)
			enc=EVP_des_ede3_cbc();
#endif
#ifndef OPENSSL_NO_IDEA
		else if (TINYCLR_SSL_STRCMP(*argv,"-idea") == 0)
			enc=EVP_idea_cbc();
#endif
#ifndef OPENSSL_NO_SEED
		else if (TINYCLR_SSL_STRCMP(*argv,"-seed") == 0)
			enc=EVP_seed_cbc();
#endif
#ifndef OPENSSL_NO_AES
		else if (TINYCLR_SSL_STRCMP(*argv,"-aes128") == 0)
			enc=EVP_aes_128_cbc();
		else if (TINYCLR_SSL_STRCMP(*argv,"-aes192") == 0)
			enc=EVP_aes_192_cbc();
		else if (TINYCLR_SSL_STRCMP(*argv,"-aes256") == 0)
			enc=EVP_aes_256_cbc();
#endif
#ifndef OPENSSL_NO_CAMELLIA
		else if (TINYCLR_SSL_STRCMP(*argv,"-camellia128") == 0)
			enc=EVP_camellia_128_cbc();
		else if (TINYCLR_SSL_STRCMP(*argv,"-camellia192") == 0)
			enc=EVP_camellia_192_cbc();
		else if (TINYCLR_SSL_STRCMP(*argv,"-camellia256") == 0)
			enc=EVP_camellia_256_cbc();
#endif
		else if (TINYCLR_SSL_STRCMP(*argv,"-passout") == 0)
			{
			if (--argc < 1) goto bad;
			passargout= *(++argv);
			}
		else
			break;
		argv++;
		argc--;
		}
	if ((argc >= 1) && ((sscanf(*argv,"%d",&num) == 0) || (num < 0)))
		{
bad:
		BIO_printf(bio_err,"usage: genrsa [args] [numbits]\n");
		BIO_printf(bio_err," -des            encrypt the generated key with DES in cbc mode\n");
		BIO_printf(bio_err," -des3           encrypt the generated key with DES in ede cbc mode (168 bit key)\n");
#ifndef OPENSSL_NO_IDEA
		BIO_printf(bio_err," -idea           encrypt the generated key with IDEA in cbc mode\n");
#endif
#ifndef OPENSSL_NO_SEED
		BIO_printf(bio_err," -seed\n");
		BIO_printf(bio_err,"                 encrypt PEM output with cbc seed\n");
#endif
#ifndef OPENSSL_NO_AES
		BIO_printf(bio_err," -aes128, -aes192, -aes256\n");
		BIO_printf(bio_err,"                 encrypt PEM output with cbc aes\n");
#endif
#ifndef OPENSSL_NO_CAMELLIA
		BIO_printf(bio_err," -camellia128, -camellia192, -camellia256\n");
		BIO_printf(bio_err,"                 encrypt PEM output with cbc camellia\n");
#endif
		BIO_printf(bio_err," -out file       output the key to 'file\n");
		BIO_printf(bio_err," -passout arg    output file pass phrase source\n");
		BIO_printf(bio_err," -f4             use F4 (0x10001) for the E value\n");
		BIO_printf(bio_err," -3              use 3 for the E value\n");
#ifndef OPENSSL_NO_ENGINE
		BIO_printf(bio_err," -engine e       use engine e, possibly a hardware device.\n");
#endif
		BIO_printf(bio_err," -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
		BIO_printf(bio_err,"                 load the file (or the files in the directory) into\n");
		BIO_printf(bio_err,"                 the random number generator\n");
		goto err;
		}
		
	ERR_load_crypto_strings();

	if(!app_passwd(bio_err, NULL, passargout, NULL, &passout)) {
		BIO_printf(bio_err, "Error getting password\n");
		goto err;
	}

#ifndef OPENSSL_NO_ENGINE
        e = setup_engine(bio_err, engine, 0);
#endif

	if (outfile == NULL)
		{
		BIO_set_fp(out,OPENSSL_TYPE__FILE_STDOUT,BIO_NOCLOSE);
#ifdef OPENSSL_SYS_VMS
		{
		BIO *tmpbio = BIO_new(BIO_f_linebuffer());
		out = BIO_push(tmpbio, out);
		}
#endif
		}
	else
		{
		if (BIO_write_filename(out,outfile) <= 0)
			{
			TINYCLR_SSL_PERROR(outfile);
			goto err;
			}
		}

	if (!app_RAND_load_file(NULL, bio_err, 1) && inrand == NULL
		&& !RAND_status())
		{
		BIO_printf(bio_err,"warning, not much extra random data, consider using the -rand option\n");
		}
	if (inrand != NULL)
		BIO_printf(bio_err,"%ld semi-random bytes loaded\n",
			app_RAND_load_files(inrand));

	BIO_printf(bio_err,"Generating RSA private key, %d bit long modulus\n",
		num);
#ifdef OPENSSL_NO_ENGINE
	rsa = RSA_new();
#else
	rsa = RSA_new_method(e);
#endif
	if (!rsa)
		goto err;

	if(!BN_set_word(bn, f4) || !RSA_generate_key_ex(rsa, num, bn, &cb))
		goto err;
		
	app_RAND_write_file(NULL, bio_err);

	/* We need to do the following for when the base number size is <
	 * long, esp windows 3.1 :-(. */
	l=0L;
	for (i=0; i<rsa->e->top; i++)
		{
#ifndef SIXTY_FOUR_BIT
		l<<=BN_BITS4;
		l<<=BN_BITS4;
#endif
		l+=rsa->e->d[i];
		}
	BIO_printf(bio_err,"e is %ld (0x%lX)\n",l,l);
	{
	PW_CB_DATA cb_data;
	cb_data.password = passout;
	cb_data.prompt_info = outfile;
	if (!PEM_write_bio_RSAPrivateKey(out,rsa,enc,NULL,0,
		(pem_password_cb *)password_callback,&cb_data))
		goto err;
	}

	ret=0;
err:
	if (bn) BN_free(bn);
	if (rsa) RSA_free(rsa);
	if (out) BIO_free_all(out);
	if(passout) OPENSSL_free(passout);
	if (ret != 0)
		ERR_print_errors(bio_err);
	apps_shutdown();
	OPENSSL_EXIT(ret);
	}
예제 #28
0
int
BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx)
{
	int ret = 0;
	BIGNUM *Ri, *R;

	BN_CTX_start(ctx);
	if ((Ri = BN_CTX_get(ctx)) == NULL)
		goto err;
	R = &(mont->RR);				/* grab RR as a temp */
	if (!BN_copy(&(mont->N), mod))
		 goto err;				/* Set N */
	mont->N.neg = 0;

#ifdef MONT_WORD
	{
		BIGNUM tmod;
		BN_ULONG buf[2];

		BN_init(&tmod);
		tmod.d = buf;
		tmod.dmax = 2;
		tmod.neg = 0;

		mont->ri = (BN_num_bits(mod) +
		    (BN_BITS2 - 1)) / BN_BITS2 * BN_BITS2;

#if defined(OPENSSL_BN_ASM_MONT) && (BN_BITS2<=32)
		/* Only certain BN_BITS2<=32 platforms actually make use of
		 * n0[1], and we could use the #else case (with a shorter R
		 * value) for the others.  However, currently only the assembler
		 * files do know which is which. */

		BN_zero(R);
		if (!(BN_set_bit(R, 2 * BN_BITS2)))
			goto err;

		tmod.top = 0;
		if ((buf[0] = mod->d[0]))
			tmod.top = 1;
		if ((buf[1] = mod->top > 1 ? mod->d[1] : 0))
			tmod.top = 2;

		if ((BN_mod_inverse_ct(Ri, R, &tmod, ctx)) == NULL)
			goto err;
		if (!BN_lshift(Ri, Ri, 2 * BN_BITS2))
			goto err; /* R*Ri */
		if (!BN_is_zero(Ri)) {
			if (!BN_sub_word(Ri, 1))
				goto err;
		}
		else /* if N mod word size == 1 */
		{
			if (bn_expand(Ri, (int)sizeof(BN_ULONG) * 2) == NULL)
				goto err;
			/* Ri-- (mod double word size) */
			Ri->neg = 0;
			Ri->d[0] = BN_MASK2;
			Ri->d[1] = BN_MASK2;
			Ri->top = 2;
		}
		if (!BN_div_ct(Ri, NULL, Ri, &tmod, ctx))
			goto err;
		/* Ni = (R*Ri-1)/N,
		 * keep only couple of least significant words: */
		mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0;
		mont->n0[1] = (Ri->top > 1) ? Ri->d[1] : 0;
#else
		BN_zero(R);
		if (!(BN_set_bit(R, BN_BITS2)))
			goto err;	/* R */

		buf[0] = mod->d[0]; /* tmod = N mod word size */
		buf[1] = 0;
		tmod.top = buf[0] != 0 ? 1 : 0;
		/* Ri = R^-1 mod N*/
		if ((BN_mod_inverse_ct(Ri, R, &tmod, ctx)) == NULL)
			goto err;
		if (!BN_lshift(Ri, Ri, BN_BITS2))
			goto err; /* R*Ri */
		if (!BN_is_zero(Ri)) {
			if (!BN_sub_word(Ri, 1))
				goto err;
		}
		else /* if N mod word size == 1 */
		{
			if (!BN_set_word(Ri, BN_MASK2))
				goto err;  /* Ri-- (mod word size) */
		}
		if (!BN_div_ct(Ri, NULL, Ri, &tmod, ctx))
			goto err;
		/* Ni = (R*Ri-1)/N,
		 * keep only least significant word: */
		mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0;
		mont->n0[1] = 0;
#endif
	}
#else /* !MONT_WORD */
	{ /* bignum version */
		mont->ri = BN_num_bits(&mont->N);
		BN_zero(R);
		if (!BN_set_bit(R, mont->ri))
			goto err;  /* R = 2^ri */
		/* Ri = R^-1 mod N*/
		if ((BN_mod_inverse_ct(Ri, R, &mont->N, ctx)) == NULL)
			goto err;
		if (!BN_lshift(Ri, Ri, mont->ri))
			goto err; /* R*Ri */
		if (!BN_sub_word(Ri, 1))
			goto err;
		/* Ni = (R*Ri-1) / N */
		if (!BN_div_ct(&(mont->Ni), NULL, Ri, &mont->N, ctx))
			goto err;
	}
#endif

	/* setup RR for conversions */
	BN_zero(&(mont->RR));
	if (!BN_set_bit(&(mont->RR), mont->ri*2))
		goto err;
	if (!BN_mod_ct(&(mont->RR), &(mont->RR), &(mont->N), ctx))
		goto err;

	ret = 1;

err:
	BN_CTX_end(ctx);
	return ret;
}
예제 #29
0
int
dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits, const EVP_MD *evpmd,
    const unsigned char *seed_in, size_t seed_len, unsigned char *seed_out,
    int *counter_ret, unsigned long *h_ret, BN_GENCB *cb)
{
	int ok = 0;
	unsigned char seed[SHA256_DIGEST_LENGTH];
	unsigned char md[SHA256_DIGEST_LENGTH];
	unsigned char buf[SHA256_DIGEST_LENGTH], buf2[SHA256_DIGEST_LENGTH];
	BIGNUM *r0, *W, *X, *c, *test;
	BIGNUM *g = NULL, *q = NULL, *p = NULL;
	BN_MONT_CTX *mont = NULL;
	int i, k, n = 0, m = 0, qsize = qbits >> 3;
	int counter = 0;
	int r = 0;
	BN_CTX *ctx = NULL;
	unsigned int h = 2;

	if (qsize != SHA_DIGEST_LENGTH && qsize != SHA224_DIGEST_LENGTH &&
	    qsize != SHA256_DIGEST_LENGTH)
		/* invalid q size */
		return 0;

	if (evpmd == NULL)
		/* use SHA1 as default */
		evpmd = EVP_sha1();

	if (bits < 512)
		bits = 512;

	bits = (bits + 63) / 64 * 64;

	/*
	 * NB: seed_len == 0 is special case: copy generated seed to
 	 * seed_in if it is not NULL.
 	 */
	if (seed_len && seed_len < (size_t)qsize)
		seed_in = NULL;		/* seed buffer too small -- ignore */
	/*
	 * App. 2.2 of FIPS PUB 186 allows larger SEED,
	 * but our internal buffers are restricted to 160 bits
	 */
	if (seed_len > (size_t)qsize) 
		seed_len = qsize;
	if (seed_in != NULL)
		memcpy(seed, seed_in, seed_len);

	if ((ctx=BN_CTX_new()) == NULL)
		goto err;

	if ((mont=BN_MONT_CTX_new()) == NULL)
		goto err;

	BN_CTX_start(ctx);
	r0 = BN_CTX_get(ctx);
	g = BN_CTX_get(ctx);
	W = BN_CTX_get(ctx);
	q = BN_CTX_get(ctx);
	X = BN_CTX_get(ctx);
	c = BN_CTX_get(ctx);
	p = BN_CTX_get(ctx);
	test = BN_CTX_get(ctx);

	if (!BN_lshift(test, BN_value_one(), bits - 1))
		goto err;

	for (;;) {
		for (;;) { /* find q */
			int seed_is_random;

			/* step 1 */
			if (!BN_GENCB_call(cb, 0, m++))
				goto err;

			if (!seed_len) {
				RAND_pseudo_bytes(seed, qsize);
				seed_is_random = 1;
			} else {
				seed_is_random = 0;
				/* use random seed if 'seed_in' turns out
				   to be bad */
				seed_len = 0;
			}
			memcpy(buf, seed, qsize);
			memcpy(buf2, seed, qsize);
			/* precompute "SEED + 1" for step 7: */
			for (i = qsize - 1; i >= 0; i--) {
				buf[i]++;
				if (buf[i] != 0)
					break;
			}

			/* step 2 */
			if (!EVP_Digest(seed, qsize, md,   NULL, evpmd, NULL))
				goto err;
			if (!EVP_Digest(buf,  qsize, buf2, NULL, evpmd, NULL))
				goto err;
			for (i = 0; i < qsize; i++)
				md[i] ^= buf2[i];

			/* step 3 */
			md[0] |= 0x80;
			md[qsize - 1] |= 0x01;
			if (!BN_bin2bn(md, qsize, q))
				goto err;

			/* step 4 */
			r = BN_is_prime_fasttest_ex(q, DSS_prime_checks, ctx,
			    seed_is_random, cb);
			if (r > 0)
				break;
			if (r != 0)
				goto err;

			/* do a callback call */
			/* step 5 */
		}

		if (!BN_GENCB_call(cb, 2, 0))
			goto err;
		if (!BN_GENCB_call(cb, 3, 0))
			goto err;

		/* step 6 */
		counter = 0;
		/* "offset = 2" */

		n = (bits - 1) / 160;

		for (;;) {
			if (counter != 0 && !BN_GENCB_call(cb, 0, counter))
				goto err;

			/* step 7 */
			BN_zero(W);
			/* now 'buf' contains "SEED + offset - 1" */
			for (k = 0; k <= n; k++) {
				/* obtain "SEED + offset + k" by incrementing: */
				for (i = qsize - 1; i >= 0; i--) {
					buf[i]++;
					if (buf[i] != 0)
						break;
				}

				if (!EVP_Digest(buf, qsize, md ,NULL, evpmd,
				    NULL))
					goto err;

				/* step 8 */
				if (!BN_bin2bn(md, qsize, r0))
					goto err;
				if (!BN_lshift(r0, r0, (qsize << 3) * k))
					goto err;
				if (!BN_add(W, W, r0))
					goto err;
			}

			/* more of step 8 */
			if (!BN_mask_bits(W, bits - 1))
				goto err;
			if (!BN_copy(X, W))
				goto err;
			if (!BN_add(X, X, test))
				goto err;

			/* step 9 */
			if (!BN_lshift1(r0, q))
				goto err;
			if (!BN_mod(c, X, r0, ctx))
				goto err;
			if (!BN_sub(r0, c, BN_value_one()))
				goto err;
			if (!BN_sub(p, X, r0))
				goto err;

			/* step 10 */
			if (BN_cmp(p, test) >= 0) {
				/* step 11 */
				r = BN_is_prime_fasttest_ex(p, DSS_prime_checks,
				    ctx, 1, cb);
				if (r > 0)
					goto end; /* found it */
				if (r != 0)
					goto err;
			}

			/* step 13 */
			counter++;
			/* "offset = offset + n + 1" */

			/* step 14 */
			if (counter >= 4096)
				break;
		}
	}
end:
	if (!BN_GENCB_call(cb, 2, 1))
		goto err;

	/* We now need to generate g */
	/* Set r0=(p-1)/q */
	if (!BN_sub(test, p, BN_value_one()))
		goto err;
	if (!BN_div(r0, NULL, test, q, ctx))
		goto err;

	if (!BN_set_word(test, h))
		goto err;
	if (!BN_MONT_CTX_set(mont, p, ctx))
		goto err;

	for (;;) {
		/* g=test^r0%p */
		if (!BN_mod_exp_mont(g, test, r0, p, ctx, mont))
			goto err;
		if (!BN_is_one(g))
			break;
		if (!BN_add(test, test, BN_value_one()))
			goto err;
		h++;
	}

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

	ok = 1;
err:
	if (ok) {
		if (ret->p)
			BN_free(ret->p);
		if (ret->q)
			BN_free(ret->q);
		if (ret->g)
			BN_free(ret->g);
		ret->p = BN_dup(p);
		ret->q = BN_dup(q);
		ret->g = BN_dup(g);
		if (ret->p == NULL || ret->q == NULL || ret->g == NULL) {
			ok = 0;
			goto err;
		}
		if (counter_ret != NULL)
			*counter_ret = counter;
		if (h_ret != NULL)
			*h_ret = h;
		if (seed_out)
			memcpy(seed_out, seed, qsize);
	}
	if (ctx) {
		BN_CTX_end(ctx);
		BN_CTX_free(ctx);
	}
	if (mont != NULL)
		BN_MONT_CTX_free(mont);
	return ok;
}
예제 #30
0
/*
 * Generate key
 */
static int westcos_pkcs15init_generate_key(sc_profile_t *profile,
						sc_pkcs15_card_t *p15card,
						sc_pkcs15_object_t *obj,
						sc_pkcs15_pubkey_t *pubkey)
{
#ifndef ENABLE_OPENSSL
	return SC_ERROR_NOT_SUPPORTED;
#else
	int r = SC_ERROR_UNKNOWN;
	long lg;
	u8 *p;
	sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) obj->data;
	RSA *rsa = NULL;
	BIGNUM *bn = NULL;
	BIO *mem = NULL;

	sc_file_t *prkf = NULL;

	if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) {
		return SC_ERROR_NOT_SUPPORTED;
	}

#if OPENSSL_VERSION_NUMBER>=0x00908000L
	rsa = RSA_new();
	bn = BN_new();
	mem = BIO_new(BIO_s_mem());

	if(rsa == NULL || bn == NULL || mem == NULL)
	{
		r = SC_ERROR_OUT_OF_MEMORY;
		goto out;
	}

	if(!BN_set_word(bn, RSA_F4) ||
		!RSA_generate_key_ex(rsa, key_info->modulus_length, bn, NULL))
#else
	mem = BIO_new(BIO_s_mem());

	if(mem == NULL)
	{
		r = SC_ERROR_OUT_OF_MEMORY;
		goto out;
	}

	rsa = RSA_generate_key(key_info->modulus_length, RSA_F4, NULL, NULL);
	if (!rsa)
#endif
	{
		r = SC_ERROR_UNKNOWN;
		goto out;
	}

	rsa->meth = RSA_PKCS1_SSLeay();

	if(pubkey != NULL)
	{
		if(!i2d_RSAPublicKey_bio(mem, rsa))
		{
			r = SC_ERROR_UNKNOWN;
			goto out;
		}

		lg = BIO_get_mem_data(mem, &p);

		pubkey->algorithm = SC_ALGORITHM_RSA;

		r = sc_pkcs15_decode_pubkey(p15card->card->ctx, pubkey, p, lg);
	}

	(void) BIO_reset(mem);

	if(!i2d_RSAPrivateKey_bio(mem, rsa))
	{
		r = SC_ERROR_UNKNOWN;
		goto out;
	}

	lg = BIO_get_mem_data(mem, &p);

	/* Get the private key file */
	r = sc_profile_get_file_by_path(profile, &key_info->path, &prkf);
	if (r < 0)
	{
		char pbuf[SC_MAX_PATH_STRING_SIZE];

		r = sc_path_print(pbuf, sizeof(pbuf), &key_info->path);
		if (r != SC_SUCCESS)
			pbuf[0] = '\0';

		goto out;
	}

	prkf->size = lg;

	r = sc_pkcs15init_create_file(profile, p15card, prkf);
	if(r) goto out;

	r = sc_pkcs15init_update_file(profile, p15card, prkf, p, lg);
	if(r) goto out;

out:
	if(mem)
		BIO_free(mem);
	if(bn)
		BN_free(bn);
	if(rsa)
		RSA_free(rsa);
	if(prkf)
		sc_file_free(prkf);

	return r;
#endif
}