Beispiel #1
0
static EC_KEY *extract_ec_pub_key(CPK_PUBLIC_PARAMS *param, const char *id)
{
	int e = 1;
	EC_KEY *ec_key = NULL;
	const EC_GROUP *ec_group;
	EC_POINT *pub_key = NULL;
	EC_POINT *pt = NULL;
	BIGNUM *order = BN_new();
	BIGNUM *bn = BN_new();
	BN_CTX *ctx = BN_CTX_new();
	int *index = NULL;
	int i, bn_size, pt_size, num_indexes, num_factors;
	
	if (!(ec_key = X509_ALGOR_get1_EC_KEY(param->pkey_algor))) {
		goto err;		
	}
	ec_group = EC_KEY_get0_group(ec_key);
	
	if (!(pub_key = EC_POINT_new(ec_group))) {
		goto err;
	}
	if (!(pt = EC_POINT_new(ec_group))) {
		goto err;
	}
	if (!EC_GROUP_get_order(ec_group, order, ctx)) {
		goto err;
	}
	bn_size = BN_num_bytes(order);
	pt_size = bn_size + 1;
	if ((num_factors = CPK_MAP_num_factors(param->map_algor)) <= 0) {
		goto err;
	}
	if (M_ASN1_STRING_length(param->public_factors) != pt_size * num_factors) {
		goto err;
	}

	if ((num_indexes = CPK_MAP_num_indexes(param->map_algor)) <= 0) {
		goto err;
	}
	if (!(index = OPENSSL_malloc(sizeof(int) * num_indexes))) {
		goto err;
	}		
	if (!CPK_MAP_str2index(param->map_algor, id, index)) {
		goto err;
	}

	if (!EC_POINT_set_to_infinity(ec_group, pub_key)) {
		goto err;
	}
	for (i = 0; i < num_indexes; i++) {
		const unsigned char *p = 
			M_ASN1_STRING_data(param->public_factors) + 
			pt_size * index[i];		

		if (!EC_POINT_oct2point(ec_group, pt, p, pt_size, ctx)) {
			goto err;
		}
		if (!EC_POINT_add(ec_group, pub_key, pub_key, pt, ctx)) {
			goto err;
		}
	}

	if (!EC_KEY_set_public_key(ec_key, pub_key)) {
		goto err;
	}
	e = 0;
err:
	if (e && ec_key) {
		EC_KEY_free(ec_key);
		ec_key = NULL;
	}
	if (pub_key) EC_POINT_free(pub_key);
	if (order) BN_free(order);
	if (bn) BN_free(bn);
	if (ctx) BN_CTX_free(ctx);
	if (index) OPENSSL_free(index);
	return ec_key;
}
Beispiel #2
0
/*
 * Computes gost_ec signature as DSA_SIG structure
 *
 */
DSA_SIG *gost_ec_sign(const unsigned char *dgst, int dlen, EC_KEY *eckey)
{
    DSA_SIG *newsig = NULL, *ret = NULL;
    BIGNUM *md = NULL;
    BIGNUM *order = NULL;
    const EC_GROUP *group;
    const BIGNUM *priv_key;
    BIGNUM *r = NULL, *s = NULL, *X = NULL, *tmp = NULL, *tmp2 = NULL,
        *k = NULL, *e = NULL;
    EC_POINT *C = NULL;
    BN_CTX *ctx;

    OPENSSL_assert(dgst != NULL && eckey != NULL);

    if (!(ctx = BN_CTX_new())) {
        GOSTerr(GOST_F_GOST_EC_SIGN, ERR_R_MALLOC_FAILURE);
        return NULL;
    }

    BN_CTX_start(ctx);
    OPENSSL_assert(dlen == 32 || dlen == 64);
    md = hashsum2bn(dgst, dlen);
    newsig = DSA_SIG_new();
    if (!newsig || !md) {
        GOSTerr(GOST_F_GOST_EC_SIGN, ERR_R_MALLOC_FAILURE);
        goto err;
    }
    group = EC_KEY_get0_group(eckey);
    if (!group) {
        GOSTerr(GOST_F_GOST_EC_SIGN, ERR_R_INTERNAL_ERROR);
        goto err;
    }
    order = BN_CTX_get(ctx);
    if (!order || !EC_GROUP_get_order(group, order, ctx)) {
        GOSTerr(GOST_F_GOST_EC_SIGN, ERR_R_INTERNAL_ERROR);
        goto err;
    }
    priv_key = EC_KEY_get0_private_key(eckey);
    if (!priv_key) {
        GOSTerr(GOST_F_GOST_EC_SIGN, ERR_R_INTERNAL_ERROR);
        goto err;
    }
    e = BN_CTX_get(ctx);
    if (!e || !BN_mod(e, md, order, ctx)) {
        GOSTerr(GOST_F_GOST_EC_SIGN, ERR_R_INTERNAL_ERROR);
        goto err;
    }
#ifdef DEBUG_SIGN
    fprintf(stderr, "digest as bignum=");
    BN_print_fp(stderr, md);
    fprintf(stderr, "\ndigest mod q=");
    BN_print_fp(stderr, e);
    fprintf(stderr, "\n");
#endif
    if (BN_is_zero(e)) {
        BN_one(e);
    }
    k = BN_CTX_get(ctx);
    C = EC_POINT_new(group);
    if (!k || !C) {
        GOSTerr(GOST_F_GOST_EC_SIGN, ERR_R_MALLOC_FAILURE);
        goto err;
    }

    do {
        do {
            if (!BN_rand_range(k, order)) {
                GOSTerr(GOST_F_GOST_EC_SIGN, GOST_R_RNG_ERROR);
                goto err;
            }
            /*
             * To avoid timing information leaking the length of k,
             * compute C*k using an equivalent scalar of fixed bit-length */
            if (!BN_add(k, k, order)
                || (BN_num_bits(k) <= BN_num_bits(order)
                    && !BN_add(k, k, order))) {
                goto err;
            }
            if (!EC_POINT_mul(group, C, k, NULL, NULL, ctx)) {
                GOSTerr(GOST_F_GOST_EC_SIGN, ERR_R_EC_LIB);
                goto err;
            }
            if (!X)
                X = BN_CTX_get(ctx);
            if (!r)
                r = BN_CTX_get(ctx);
            if (!X || !r) {
                GOSTerr(GOST_F_GOST_EC_SIGN, ERR_R_MALLOC_FAILURE);
                goto err;
            }
            if (!EC_POINT_get_affine_coordinates_GFp(group, C, X, NULL, ctx)) {
                GOSTerr(GOST_F_GOST_EC_SIGN, ERR_R_EC_LIB);
                goto err;
            }

            if (!BN_nnmod(r, X, order, ctx)) {
                GOSTerr(GOST_F_GOST_EC_SIGN, ERR_R_INTERNAL_ERROR);
                goto err;
            }
        }
        while (BN_is_zero(r));
        /* s =  (r*priv_key+k*e) mod order */
        if (!tmp)
            tmp = BN_CTX_get(ctx);
        if (!tmp2)
            tmp2 = BN_CTX_get(ctx);
        if (!s)
            s = BN_CTX_get(ctx);
        if (!tmp || !tmp2 || !s) {
            GOSTerr(GOST_F_GOST_EC_SIGN, ERR_R_MALLOC_FAILURE);
            goto err;
        }

        if (!BN_mod_mul(tmp, priv_key, r, order, ctx)
            || !BN_mod_mul(tmp2, k, e, order, ctx)
            || !BN_mod_add(s, tmp, tmp2, order, ctx)) {
            GOSTerr(GOST_F_GOST_EC_SIGN, ERR_R_INTERNAL_ERROR);
            goto err;
        }
    }
    while (BN_is_zero(s));

    newsig->s = BN_dup(s);
    newsig->r = BN_dup(r);
    if (!newsig->s || !newsig->r) {
        GOSTerr(GOST_F_GOST_EC_SIGN, ERR_R_MALLOC_FAILURE);
        goto err;
    }

    ret = newsig;
 err:
    BN_CTX_end(ctx);
    BN_CTX_free(ctx);
    if (C)
        EC_POINT_free(C);
    if (md)
        BN_free(md);
    if (!ret && newsig) {
        DSA_SIG_free(newsig);
    }
    return ret;
}
Beispiel #3
0
int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)
	{
	int    r = 0;
	BIGNUM *a1, *a2, *a3, *b1, *b2, *b3;
	BN_CTX *ctx_new = NULL;

	/* compare the field types*/
	if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) !=
	    EC_METHOD_get_field_type(EC_GROUP_method_of(b)))
		return 1;
	/* compare the curve name (if present) */
	if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) &&
	    EC_GROUP_get_curve_name(a) == EC_GROUP_get_curve_name(b))
		return 0;

	if (!ctx)
		ctx_new = ctx = BN_CTX_new();
	if (!ctx)
		return -1;
	
	BN_CTX_start(ctx);
	a1 = BN_CTX_get(ctx);
	a2 = BN_CTX_get(ctx);
	a3 = BN_CTX_get(ctx);
	b1 = BN_CTX_get(ctx);
	b2 = BN_CTX_get(ctx);
	b3 = BN_CTX_get(ctx);
	if (!b3)
		{
		BN_CTX_end(ctx);
		if (ctx_new)
			BN_CTX_free(ctx);
		return -1;
		}

	/* XXX This approach assumes that the external representation
	 * of curves over the same field type is the same.
	 */
	if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) ||
	    !b->meth->group_get_curve(b, b1, b2, b3, ctx))
		r = 1;

	if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3))
		r = 1;

	/* XXX EC_POINT_cmp() assumes that the methods are equal */
	if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a),
	    EC_GROUP_get0_generator(b), ctx))
		r = 1;

	if (!r)
		{
		/* compare the order and cofactor */
		if (!EC_GROUP_get_order(a, a1, ctx) ||
		    !EC_GROUP_get_order(b, b1, ctx) ||
		    !EC_GROUP_get_cofactor(a, a2, ctx) ||
		    !EC_GROUP_get_cofactor(b, b2, ctx))
			{
			BN_CTX_end(ctx);
			if (ctx_new)
				BN_CTX_free(ctx);
			return -1;
			}
		if (BN_cmp(a1, b1) || BN_cmp(a2, b2))
			r = 1;
		}

	BN_CTX_end(ctx);
	if (ctx_new)
		BN_CTX_free(ctx);

	return r;
	}
Beispiel #4
0
static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype)
{
    unsigned char *buffer = NULL;
    const char *ecstr;
    size_t buf_len = 0, i;
    int ret = 0, reason = ERR_R_BIO_LIB;
    BIGNUM *pub_key = NULL, *order = NULL;
    BN_CTX *ctx = NULL;
    const EC_GROUP *group;
    const EC_POINT *public_key;
    const BIGNUM *priv_key;

    if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) {
        reason = ERR_R_PASSED_NULL_PARAMETER;
        goto err;
    }

    ctx = BN_CTX_new();
    if (ctx == NULL) {
        reason = ERR_R_MALLOC_FAILURE;
        goto err;
    }

    if (ktype > 0) {
        public_key = EC_KEY_get0_public_key(x);
        if (public_key != NULL) {
            if ((pub_key = EC_POINT_point2bn(group, public_key,
                                             EC_KEY_get_conv_form(x), NULL,
                                             ctx)) == NULL) {
                reason = ERR_R_EC_LIB;
                goto err;
            }
            buf_len = (size_t)BN_num_bytes(pub_key);
        }
    }

    if (ktype == 2) {
        priv_key = EC_KEY_get0_private_key(x);
        if (priv_key && (i = (size_t)BN_num_bytes(priv_key)) > buf_len)
            buf_len = i;
    } else
        priv_key = NULL;

    if (ktype > 0) {
        buf_len += 10;
        if ((buffer = OPENSSL_malloc(buf_len)) == NULL) {
            reason = ERR_R_MALLOC_FAILURE;
            goto err;
        }
    }
    if (ktype == 2)
        ecstr = "Private-Key";
    else if (ktype == 1)
        ecstr = "Public-Key";
    else
        ecstr = "ECDSA-Parameters";

    if (!BIO_indent(bp, off, 128))
        goto err;
    if ((order = BN_new()) == NULL)
        goto err;
    if (!EC_GROUP_get_order(group, order, NULL))
        goto err;
    if (BIO_printf(bp, "%s: (%d bit)\n", ecstr, BN_num_bits(order)) <= 0)
        goto err;

    if ((priv_key != NULL) && !ASN1_bn_print(bp, "priv:", priv_key,
                                             buffer, off))
        goto err;
    if ((pub_key != NULL) && !ASN1_bn_print(bp, "pub: ", pub_key,
                                            buffer, off))
        goto err;
    if (!ECPKParameters_print(bp, group, off))
        goto err;
    ret = 1;
 err:
    if (!ret)
        ECerr(EC_F_DO_EC_KEY_PRINT, reason);
    if (pub_key)
        BN_free(pub_key);
    if (order)
        BN_free(order);
    if (ctx)
        BN_CTX_free(ctx);
    if (buffer != NULL)
        OPENSSL_free(buffer);
    return (ret);
}
/*
 * Verifies gost 2001 signature
 *
 */ 
int gost2001_do_verify(const unsigned char *dgst,int dgst_len,
	DSA_SIG *sig, EC_KEY *ec)
	{
	BN_CTX *ctx=BN_CTX_new();
	const EC_GROUP *group = EC_KEY_get0_group(ec);
	BIGNUM *order;
	BIGNUM *md = NULL,*e=NULL,*R=NULL,*v=NULL,*z1=NULL,*z2=NULL;
	BIGNUM *X=NULL,*tmp=NULL;
	EC_POINT *C = NULL;
	const EC_POINT *pub_key=NULL;
	int ok=0;

	BN_CTX_start(ctx);
	order = BN_CTX_get(ctx);
	e = BN_CTX_get(ctx);
	z1 = BN_CTX_get(ctx);
	z2 = BN_CTX_get(ctx);
	tmp = BN_CTX_get(ctx);
	X= BN_CTX_get(ctx);	
	R=BN_CTX_get(ctx);
	v=BN_CTX_get(ctx);
	
	EC_GROUP_get_order(group,order,ctx);
	pub_key = EC_KEY_get0_public_key(ec);
	if (BN_is_zero(sig->s) || BN_is_zero(sig->r) ||
		(BN_cmp(sig->s,order)>=1) || (BN_cmp(sig->r,order)>=1)) 
		{
		GOSTerr(GOST_F_GOST2001_DO_VERIFY,GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q);
		goto err;

		}
	md = hashsum2bn(dgst);

	BN_mod(e,md,order,ctx);
#ifdef DEBUG_SIGN
	fprintf(stderr,"digest as bignum: ");
	BN_print_fp(stderr,md);
	fprintf(stderr,"\ndigest mod q: ");
	BN_print_fp(stderr,e);
#endif	
	if (BN_is_zero(e)) BN_one(e);
	v=BN_mod_inverse(v,e,order,ctx);
	BN_mod_mul(z1,sig->s,v,order,ctx);
	BN_sub(tmp,order,sig->r);
	BN_mod_mul(z2,tmp,v,order,ctx);
#ifdef DEBUG_SIGN
	fprintf(stderr,"\nInverted digest value: ");
	BN_print_fp(stderr,v);
	fprintf(stderr,"\nz1: ");
	BN_print_fp(stderr,z1);
	fprintf(stderr,"\nz2: ");
	BN_print_fp(stderr,z2);
#endif	
	C = EC_POINT_new(group);
	if (!EC_POINT_mul(group,C,z1,pub_key,z2,ctx)) 
		{	
		GOSTerr(GOST_F_GOST2001_DO_VERIFY,ERR_R_EC_LIB);
		goto err;
		}	
	if (!EC_POINT_get_affine_coordinates_GFp(group,C,X,NULL,ctx)) 
		{
		GOSTerr(GOST_F_GOST2001_DO_VERIFY,ERR_R_EC_LIB);
		goto err;
		}
	BN_mod(R,X,order,ctx);
#ifdef DEBUG_SIGN
	fprintf(stderr,"\nX=");
	BN_print_fp(stderr,X);
	fprintf(stderr,"\nX mod q=");
	BN_print_fp(stderr,R);
	fprintf(stderr,"\n");
#endif	
	if (BN_cmp(R,sig->r)!=0)
		{
		GOSTerr(GOST_F_GOST2001_DO_VERIFY,GOST_R_SIGNATURE_MISMATCH);
		}
	else
		{
		ok = 1;
		}
	err:
	EC_POINT_free(C);
	BN_CTX_end(ctx);
	BN_CTX_free(ctx);
	BN_free(md);
	return ok;
	}
Beispiel #6
0
int EC_KEY_generate_key(EC_KEY *eckey)
	{	
	int	ok = 0;
	BN_CTX	*ctx = NULL;
	BIGNUM	*priv_key = NULL, *order = NULL;
	EC_POINT *pub_key = NULL;

#ifdef OPENSSL_FIPS
	if (FIPS_mode())
		return FIPS_ec_key_generate_key(eckey);
#endif

	if (!eckey || !eckey->group)
		{
		ECerr(EC_F_EC_KEY_GENERATE_KEY, ERR_R_PASSED_NULL_PARAMETER);
		return 0;
		}

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

	if (eckey->priv_key == NULL)
		{
		priv_key = BN_new();
		if (priv_key == NULL)
			goto err;
		}
	else
		priv_key = eckey->priv_key;

	if (!EC_GROUP_get_order(eckey->group, order, ctx))
		goto err;

	do
		if (!BN_rand_range(priv_key, order))
			goto err;
	while (BN_is_zero(priv_key));

	if (eckey->pub_key == NULL)
		{
		pub_key = EC_POINT_new(eckey->group);
		if (pub_key == NULL)
			goto err;
		}
	else
		pub_key = eckey->pub_key;

	if (!EC_POINT_mul(eckey->group, pub_key, priv_key, NULL, NULL, ctx))
		goto err;

	eckey->priv_key = priv_key;
	eckey->pub_key  = pub_key;

	ok=1;

err:	
	if (order)
		BN_free(order);
	if (pub_key  != NULL && eckey->pub_key  == NULL)
		EC_POINT_free(pub_key);
	if (priv_key != NULL && eckey->priv_key == NULL)
		BN_free(priv_key);
	if (ctx != NULL)
		BN_CTX_free(ctx);
	return(ok);
	}
Beispiel #7
0
int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx)
	{
	int ret = 0;
	BIGNUM *order;
	BN_CTX *new_ctx = NULL;
	EC_POINT *point = NULL;

	if (ctx == NULL)
		{
		ctx = new_ctx = BN_CTX_new();
		if (ctx == NULL)
			{
		//	ECerr(EC_F_EC_GROUP_CHECK, ERR_R_MALLOC_FAILURE);
			goto err;
			}
		}
	BN_CTX_start(ctx);
	if ((order = BN_CTX_get(ctx)) == NULL) goto err;

	/* check the discriminant */
	if (!EC_GROUP_check_discriminant(group, ctx))
		{
	//	ECerr(EC_F_EC_GROUP_CHECK, EC_R_DISCRIMINANT_IS_ZERO);
		goto err;
		}

	/* check the generator */
	if (group->generator == NULL)
		{
	//	ECerr(EC_F_EC_GROUP_CHECK, EC_R_UNDEFINED_GENERATOR);
		goto err;
		}
	if (!EC_POINT_is_on_curve(group, group->generator, ctx))
		{
	//	ECerr(EC_F_EC_GROUP_CHECK, EC_R_POINT_IS_NOT_ON_CURVE);
		goto err;
		}

	/* check the order of the generator */
	if ((point = EC_POINT_new(group)) == NULL) goto err;
	if (!EC_GROUP_get_order(group, order, ctx)) goto err; 
	if (BN_is_zero(order))
		{
	//	ECerr(EC_F_EC_GROUP_CHECK, EC_R_UNDEFINED_ORDER);
		goto err;
		}
	
	if (!EC_POINT_mul(group, point, order, NULL, NULL, ctx)) goto err;
	if (!EC_POINT_is_at_infinity(group, point))
		{
	//	ECerr(EC_F_EC_GROUP_CHECK, EC_R_INVALID_GROUP_ORDER);
		goto err;
		}

	ret = 1;

err:
	if (ctx != NULL)
		BN_CTX_end(ctx);
	if (new_ctx != NULL)
		BN_CTX_free(new_ctx);
	if (point)
		EC_POINT_free(point);
	return ret;
	}
Beispiel #8
0
int compute_password_element(REQUEST *request, pwd_session_t *session, uint16_t grp_num,
			     char const *password, int password_len,
			     char const *id_server, int id_server_len,
			     char const *id_peer, int id_peer_len,
			     uint32_t *token)
{
	BIGNUM		*x_candidate = NULL, *rnd = NULL, *cofactor = NULL;
	HMAC_CTX	*hmac_ctx = NULL;
	uint8_t		pwe_digest[SHA256_DIGEST_LENGTH], *prf_buf = NULL, ctr;
	int		nid, is_odd, prime_bit_len, prime_byte_len, ret = 0;

	switch (grp_num) { /* from IANA registry for IKE D-H groups */
	case 19:
		nid = NID_X9_62_prime256v1;
		break;

	case 20:
		nid = NID_secp384r1;
		break;

	case 21:
		nid = NID_secp521r1;
		break;

	case 25:
		nid = NID_X9_62_prime192v1;
		break;

	case 26:
		nid = NID_secp224r1;
		break;

	default:
		REDEBUG("Unknown group %d", grp_num);
	error:
		ret = -1;
		goto finish;
	}

	session->pwe = NULL;
	session->order = NULL;
	session->prime = NULL;
	session->group = EC_GROUP_new_by_curve_name(nid);
	if (!session->group) {
		REDEBUG("Unable to create EC_GROUP");
		goto error;
	}

	MEM(session->pwe = EC_POINT_new(session->group));
	MEM(session->order = BN_new());
	MEM(session->prime = BN_new());

	MEM(rnd = BN_new());
	MEM(cofactor = BN_new());
	MEM(x_candidate = BN_new());

	if (!EC_GROUP_get_curve_GFp(session->group, session->prime, NULL, NULL, NULL)) {
		REDEBUG("Unable to get prime for GFp curve");
		goto error;
	}

	if (!EC_GROUP_get_order(session->group, session->order, NULL)) {
		REDEBUG("Unable to get order for curve");
		goto error;
	}

	if (!EC_GROUP_get_cofactor(session->group, cofactor, NULL)) {
		REDEBUG("unable to get cofactor for curve");
		goto error;
	}

	prime_bit_len = BN_num_bits(session->prime);
	prime_byte_len = BN_num_bytes(session->prime);
	MEM(prf_buf = talloc_zero_array(session, uint8_t, prime_byte_len));
	MEM(hmac_ctx = HMAC_CTX_new());
	ctr = 0;
	for (;;) {
		if (ctr > 10) {
			REDEBUG("Unable to find random point on curve for group %d, something's fishy", grp_num);
			goto error;
		}
		ctr++;

		/*
		 * compute counter-mode password value and stretch to prime
		 *    pwd-seed = H(token | peer-id | server-id | password |
		 *		   counter)
		 */
		HMAC_Init_ex(hmac_ctx, allzero, SHA256_DIGEST_LENGTH, EVP_sha256(), NULL);
		HMAC_Update(hmac_ctx, (uint8_t *)token, sizeof(*token));
		HMAC_Update(hmac_ctx, (uint8_t const *)id_peer, id_peer_len);
		HMAC_Update(hmac_ctx, (uint8_t const *)id_server, id_server_len);
		HMAC_Update(hmac_ctx, (uint8_t const *)password, password_len);
		HMAC_Update(hmac_ctx, (uint8_t *)&ctr, sizeof(ctr));
		pwd_hmac_final(hmac_ctx, pwe_digest);

		BN_bin2bn(pwe_digest, SHA256_DIGEST_LENGTH, rnd);
		eap_pwd_kdf(pwe_digest, SHA256_DIGEST_LENGTH, "EAP-pwd Hunting And Pecking",
			    strlen("EAP-pwd Hunting And Pecking"), prf_buf, prime_bit_len);

		BN_bin2bn(prf_buf, prime_byte_len, x_candidate);
		/*
		 * eap_pwd_kdf() returns a string of bits 0..prime_bit_len but
		 * BN_bin2bn will treat that string of bits as a big endian
		 * number. If the prime_bit_len is not an even multiple of 8
		 * then excessive bits-- those _after_ prime_bit_len-- so now
		 * we have to shift right the amount we masked off.
		 */
		if (prime_bit_len % 8) BN_rshift(x_candidate, x_candidate, (8 - (prime_bit_len % 8)));
		if (BN_ucmp(x_candidate, session->prime) >= 0) continue;

		/*
		 * need to unambiguously identify the solution, if there is
		 * one...
		 */
		is_odd = BN_is_odd(rnd) ? 1 : 0;

		/*
		 * solve the quadratic equation, if it's not solvable then we
		 * don't have a point
		 */
		if (!EC_POINT_set_compressed_coordinates_GFp(session->group, session->pwe, x_candidate, is_odd, NULL)) {
			continue;
		}

		/*
		 * If there's a solution to the equation then the point must be
		 * on the curve so why check again explicitly? OpenSSL code
		 * says this is required by X9.62. We're not X9.62 but it can't
		 * hurt just to be sure.
		 */
		if (!EC_POINT_is_on_curve(session->group, session->pwe, NULL)) {
			REDEBUG("Point is not on curve");
			continue;
		}

		if (BN_cmp(cofactor, BN_value_one())) {
			/* make sure the point is not in a small sub-group */
			if (!EC_POINT_mul(session->group, session->pwe, NULL, session->pwe,
				cofactor, NULL)) {
				RDEBUG("Cannot multiply generator by order");
				continue;
			}

			if (EC_POINT_is_at_infinity(session->group, session->pwe)) {
				REDEBUG("Point is at infinity");
				continue;
			}
		}
		/* if we got here then we have a new generator. */
		break;
	}

	session->group_num = grp_num;

finish:
	/* cleanliness and order.... */
	HMAC_CTX_free(hmac_ctx);
	BN_clear_free(cofactor);
	BN_clear_free(x_candidate);
	BN_clear_free(rnd);
	talloc_free(prf_buf);

	return ret;
}
/*
 * compute a "random" secret point on an elliptic curve based
 * on the password and identities.
 */
int compute_password_element(EAP_PWD_group *grp, u16 num,
			     u8 *password, int password_len,
			     u8 *id_server, int id_server_len,
			     u8 *id_peer, int id_peer_len, u8 *token)
{
	BIGNUM *x_candidate = NULL, *rnd = NULL, *cofactor = NULL;
	struct crypto_hash *hash;
	unsigned char pwe_digest[SHA256_MAC_LEN], *prfbuf = NULL, ctr;
	int nid, is_odd, ret = 0;
	size_t primebytelen, primebitlen;

	switch (num) { /* from IANA registry for IKE D-H groups */
        case 19:
		nid = NID_X9_62_prime256v1;
		break;
        case 20:
		nid = NID_secp384r1;
		break;
        case 21:
		nid = NID_secp521r1;
		break;
        case 25:
		nid = NID_X9_62_prime192v1;
		break;
        case 26:
		nid = NID_secp224r1;
		break;
        default:
		wpa_printf(MSG_INFO, "EAP-pwd: unsupported group %d", num);
		return -1;
	}

	grp->pwe = NULL;
	grp->order = NULL;
	grp->prime = NULL;

	if ((grp->group = EC_GROUP_new_by_curve_name(nid)) == NULL) {
		wpa_printf(MSG_INFO, "EAP-pwd: unable to create EC_GROUP");
		goto fail;
	}

	if (((rnd = BN_new()) == NULL) ||
	    ((cofactor = BN_new()) == NULL) ||
	    ((grp->pwe = EC_POINT_new(grp->group)) == NULL) ||
	    ((grp->order = BN_new()) == NULL) ||
	    ((grp->prime = BN_new()) == NULL) ||
	    ((x_candidate = BN_new()) == NULL)) {
		wpa_printf(MSG_INFO, "EAP-pwd: unable to create bignums");
		goto fail;
	}

	if (!EC_GROUP_get_curve_GFp(grp->group, grp->prime, NULL, NULL, NULL))
	{
		wpa_printf(MSG_INFO, "EAP-pwd: unable to get prime for GFp "
			   "curve");
		goto fail;
	}
	if (!EC_GROUP_get_order(grp->group, grp->order, NULL)) {
		wpa_printf(MSG_INFO, "EAP-pwd: unable to get order for curve");
		goto fail;
	}
	if (!EC_GROUP_get_cofactor(grp->group, cofactor, NULL)) {
		wpa_printf(MSG_INFO, "EAP-pwd: unable to get cofactor for "
			   "curve");
		goto fail;
	}
	primebitlen = BN_num_bits(grp->prime);
	primebytelen = BN_num_bytes(grp->prime);
	if ((prfbuf = os_malloc(primebytelen)) == NULL) {
		wpa_printf(MSG_INFO, "EAP-pwd: unable to malloc space for prf "
			   "buffer");
		goto fail;
	}
	os_memset(prfbuf, 0, primebytelen);
	ctr = 0;
	while (1) {
		if (ctr > 30) {
			wpa_printf(MSG_INFO, "EAP-pwd: unable to find random "
				   "point on curve for group %d, something's "
				   "fishy", num);
			goto fail;
		}
		ctr++;

		/*
		 * compute counter-mode password value and stretch to prime
		 *    pwd-seed = H(token | peer-id | server-id | password |
		 *		   counter)
		 */
		hash = eap_pwd_h_init();
		if (hash == NULL)
			goto fail;
		eap_pwd_h_update(hash, token, sizeof(u32));
		eap_pwd_h_update(hash, id_peer, id_peer_len);
		eap_pwd_h_update(hash, id_server, id_server_len);
		eap_pwd_h_update(hash, password, password_len);
		eap_pwd_h_update(hash, &ctr, sizeof(ctr));
		eap_pwd_h_final(hash, pwe_digest);

		BN_bin2bn(pwe_digest, SHA256_MAC_LEN, rnd);

		if (eap_pwd_kdf(pwe_digest, SHA256_MAC_LEN,
				(u8 *) "EAP-pwd Hunting And Pecking",
				os_strlen("EAP-pwd Hunting And Pecking"),
				prfbuf, primebitlen) < 0)
			goto fail;

		BN_bin2bn(prfbuf, primebytelen, x_candidate);

		/*
		 * eap_pwd_kdf() returns a string of bits 0..primebitlen but
		 * BN_bin2bn will treat that string of bits as a big endian
		 * number. If the primebitlen is not an even multiple of 8
		 * then excessive bits-- those _after_ primebitlen-- so now
		 * we have to shift right the amount we masked off.
		 */
		if (primebitlen % 8)
			BN_rshift(x_candidate, x_candidate,
				  (8 - (primebitlen % 8)));

		if (BN_ucmp(x_candidate, grp->prime) >= 0)
			continue;

		wpa_hexdump(MSG_DEBUG, "EAP-pwd: x_candidate",
			    prfbuf, primebytelen);

		/*
		 * need to unambiguously identify the solution, if there is
		 * one...
		 */
		if (BN_is_odd(rnd))
			is_odd = 1;
		else
			is_odd = 0;

		/*
		 * solve the quadratic equation, if it's not solvable then we
		 * don't have a point
		 */
		if (!EC_POINT_set_compressed_coordinates_GFp(grp->group,
							     grp->pwe,
							     x_candidate,
							     is_odd, NULL))
			continue;
		/*
		 * If there's a solution to the equation then the point must be
		 * on the curve so why check again explicitly? OpenSSL code
		 * says this is required by X9.62. We're not X9.62 but it can't
		 * hurt just to be sure.
		 */
		if (!EC_POINT_is_on_curve(grp->group, grp->pwe, NULL)) {
			wpa_printf(MSG_INFO, "EAP-pwd: point is not on curve");
			continue;
		}

		if (BN_cmp(cofactor, BN_value_one())) {
			/* make sure the point is not in a small sub-group */
			if (!EC_POINT_mul(grp->group, grp->pwe, NULL, grp->pwe,
					  cofactor, NULL)) {
				wpa_printf(MSG_INFO, "EAP-pwd: cannot "
					   "multiply generator by order");
				continue;
			}
			if (EC_POINT_is_at_infinity(grp->group, grp->pwe)) {
				wpa_printf(MSG_INFO, "EAP-pwd: point is at "
					   "infinity");
				continue;
			}
		}
		/* if we got here then we have a new generator. */
		break;
	}
	wpa_printf(MSG_DEBUG, "EAP-pwd: found a PWE in %d tries", ctr);
	grp->group_num = num;
	if (0) {
 fail:
		EC_GROUP_free(grp->group);
		grp->group = NULL;
		EC_POINT_free(grp->pwe);
		grp->pwe = NULL;
		BN_free(grp->order);
		grp->order = NULL;
		BN_free(grp->prime);
		grp->prime = NULL;
		ret = 1;
	}
	/* cleanliness and order.... */
	BN_free(cofactor);
	BN_free(x_candidate);
	BN_free(rnd);
	os_free(prfbuf);

	return ret;
}
Beispiel #10
0
static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
                            BIGNUM **rp, const uint8_t *digest,
                            size_t digest_len) {
  BN_CTX *ctx = NULL;
  BIGNUM *k = NULL, *r = NULL, *order = NULL, *X = NULL;
  EC_POINT *tmp_point = NULL;
  const EC_GROUP *group;
  int ret = 0;

  if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_PASSED_NULL_PARAMETER);
    return 0;
  }

  if (ctx_in == NULL) {
    if ((ctx = BN_CTX_new()) == NULL) {
      OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE);
      return 0;
    }
  } else {
    ctx = ctx_in;
  }

  k = BN_new(); /* this value is later returned in *kinvp */
  r = BN_new(); /* this value is later returned in *rp    */
  order = BN_new();
  X = BN_new();
  if (!k || !r || !order || !X) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE);
    goto err;
  }
  tmp_point = EC_POINT_new(group);
  if (tmp_point == NULL) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB);
    goto err;
  }
  if (!EC_GROUP_get_order(group, order, ctx)) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB);
    goto err;
  }

  do {
    /* If possible, we'll include the private key and message digest in the k
     * generation. The |digest| argument is only empty if |ECDSA_sign_setup| is
     * being used. */
    do {
      int ok;

      if (digest_len > 0) {
        ok = BN_generate_dsa_nonce(k, order, EC_KEY_get0_private_key(eckey),
                                   digest, digest_len, ctx);
      } else {
        ok = BN_rand_range(k, order);
      }
      if (!ok) {
        OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED);
        goto err;
      }
    } while (BN_is_zero(k));

    /* We do not want timing information to leak the length of k,
     * so we compute G*k using an equivalent scalar of fixed
     * bit-length. */

    if (!BN_add(k, k, order)) {
      goto err;
    }
    if (BN_num_bits(k) <= BN_num_bits(order)) {
      if (!BN_add(k, k, order)) {
        goto err;
      }
    }

    /* compute r the x-coordinate of generator * k */
    if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx)) {
      OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB);
      goto err;
    }
    if (!EC_POINT_get_affine_coordinates_GFp(group, tmp_point, X, NULL, ctx)) {
      OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB);
      goto err;
    }

    if (!BN_nnmod(r, X, order, ctx)) {
      OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
      goto err;
    }
  } while (BN_is_zero(r));

  /* compute the inverse of k */
  if (!BN_mod_inverse(k, k, order, ctx)) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
    goto err;
  }
  /* clear old values if necessary */
  BN_clear_free(*rp);
  BN_clear_free(*kinvp);

  /* save the pre-computed values  */
  *rp = r;
  *kinvp = k;
  ret = 1;

err:
  if (!ret) {
    BN_clear_free(k);
    BN_clear_free(r);
  }
  if (ctx_in == NULL) {
    BN_CTX_free(ctx);
  }
  BN_free(order);
  EC_POINT_free(tmp_point);
  BN_clear_free(X);
  return ret;
}
Beispiel #11
0
ECDSA_SIG *ECDSA_do_sign_ex(const uint8_t *digest, size_t digest_len,
                            const BIGNUM *in_kinv, const BIGNUM *in_r,
                            EC_KEY *eckey) {
  int ok = 0;
  BIGNUM *kinv = NULL, *s, *m = NULL, *tmp = NULL, *order = NULL;
  const BIGNUM *ckinv;
  BN_CTX *ctx = NULL;
  const EC_GROUP *group;
  ECDSA_SIG *ret;
  const BIGNUM *priv_key;

  group = EC_KEY_get0_group(eckey);
  priv_key = EC_KEY_get0_private_key(eckey);

  if (group == NULL || priv_key == NULL) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_PASSED_NULL_PARAMETER);
    return NULL;
  }

  ret = ECDSA_SIG_new();
  if (!ret) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE);
    return NULL;
  }
  s = ret->s;

  if ((ctx = BN_CTX_new()) == NULL || (order = BN_new()) == NULL ||
      (tmp = BN_new()) == NULL || (m = BN_new()) == NULL) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE);
    goto err;
  }

  if (!EC_GROUP_get_order(group, order, ctx)) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB);
    goto err;
  }
  if (!digest_to_bn(m, digest, digest_len, order)) {
    goto err;
  }
  for (;;) {
    if (in_kinv == NULL || in_r == NULL) {
      if (!ecdsa_sign_setup(eckey, ctx, &kinv, &ret->r, digest, digest_len)) {
        OPENSSL_PUT_ERROR(ECDSA, ERR_R_ECDSA_LIB);
        goto err;
      }
      ckinv = kinv;
    } else {
      ckinv = in_kinv;
      if (BN_copy(ret->r, in_r) == NULL) {
        OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE);
        goto err;
      }
    }

    if (!BN_mod_mul(tmp, priv_key, ret->r, order, ctx)) {
      OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
      goto err;
    }
    if (!BN_mod_add_quick(s, tmp, m, order)) {
      OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
      goto err;
    }
    if (!BN_mod_mul(s, s, ckinv, order, ctx)) {
      OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
      goto err;
    }
    if (BN_is_zero(s)) {
      /* if kinv and r have been supplied by the caller
       * don't to generate new kinv and r values */
      if (in_kinv != NULL && in_r != NULL) {
        OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_NEED_NEW_SETUP_VALUES);
        goto err;
      }
    } else {
      /* s != 0 => we have a valid signature */
      break;
    }
  }

  ok = 1;

err:
  if (!ok) {
    ECDSA_SIG_free(ret);
    ret = NULL;
  }
  BN_CTX_free(ctx);
  BN_clear_free(m);
  BN_clear_free(tmp);
  BN_free(order);
  BN_clear_free(kinv);
  return ret;
}
Beispiel #12
0
int ECDSA_do_verify_point(const uint8_t *digest, size_t digest_len,
                          const ECDSA_SIG *sig, const EC_GROUP *group,
                          const EC_POINT *pub_key) {
  int ret = 0;
  BN_CTX *ctx;
  BIGNUM *order, *u1, *u2, *m, *X;
  EC_POINT *point = NULL;

  /* check input values */
  ctx = BN_CTX_new();
  if (!ctx) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE);
    return 0;
  }
  BN_CTX_start(ctx);
  order = BN_CTX_get(ctx);
  u1 = BN_CTX_get(ctx);
  u2 = BN_CTX_get(ctx);
  m = BN_CTX_get(ctx);
  X = BN_CTX_get(ctx);
  if (order == NULL || u1 == NULL || u2 == NULL || m == NULL || X == NULL) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
    goto err;
  }

  if (!EC_GROUP_get_order(group, order, ctx)) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB);
    goto err;
  }

  if (BN_is_zero(sig->r) || BN_is_negative(sig->r) ||
      BN_ucmp(sig->r, order) >= 0 || BN_is_zero(sig->s) ||
      BN_is_negative(sig->s) || BN_ucmp(sig->s, order) >= 0) {
    OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_BAD_SIGNATURE);
    ret = 0; /* signature is invalid */
    goto err;
  }
  /* calculate tmp1 = inv(S) mod order */
  if (!BN_mod_inverse(u2, sig->s, order, ctx)) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
    goto err;
  }
  if (!digest_to_bn(m, digest, digest_len, order)) {
    goto err;
  }
  /* u1 = m * tmp mod order */
  if (!BN_mod_mul(u1, m, u2, order, ctx)) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
    goto err;
  }
  /* u2 = r * w mod q */
  if (!BN_mod_mul(u2, sig->r, u2, order, ctx)) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
    goto err;
  }

  point = EC_POINT_new(group);
  if (point == NULL) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE);
    goto err;
  }
  if (!EC_POINT_mul(group, point, u1, pub_key, u2, ctx)) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB);
    goto err;
  }
  if (!EC_POINT_get_affine_coordinates_GFp(group, point, X, NULL, ctx)) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB);
    goto err;
  }
  if (!BN_nnmod(u1, X, order, ctx)) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
    goto err;
  }
  /* if the signature is correct u1 is equal to sig->r */
  ret = (BN_ucmp(u1, sig->r) == 0);

err:
  BN_CTX_end(ctx);
  BN_CTX_free(ctx);
  EC_POINT_free(point);
  return ret;
}
Beispiel #13
0
/* creates a bitcoin address+private key from the SHA256
 *  hash of string. converts to base58 if base58 is 'true'
 *  returns 1 if successful, 0 if not*/
int create_address_from_string(const unsigned char *string,
		unsigned char *address,
		unsigned char *priv_key,
		EC_GROUP *precompgroup,
		bool base58,
		bool debug) {

    u_int8_t * hash = malloc(SHA256_DIGEST_LENGTH);
    BIGNUM * n = BN_new();

    //first we hash the string
    SHA256 (string, strlen(string), hash);
	//then we convert the hash to the BIGNUM n
    n = BN_bin2bn(hash, SHA256_DIGEST_LENGTH, n);

    BIGNUM * order = BN_new();
    BIGNUM * nmodorder = BN_new();
	BN_CTX *bnctx;
	bnctx = BN_CTX_new();

    //then we create a new EC group with the curve secp256k1
	EC_GROUP * pgroup;
	pgroup = EC_GROUP_new_by_curve_name(NID_secp256k1);

    if (!pgroup) {
    	printf("ERROR: Couldn't get new group\n");
    	return 0;
    }

    //now we need to get the order of the group, and make sure that
    //the number we use for the private key is less than or equal to
    //the group order by using "nmodorder = n % order"
    EC_GROUP_get_order(pgroup, order, NULL);
    BN_mod(nmodorder, n, order, bnctx);

    if (BN_is_zero(nmodorder)) {
    	printf("ERROR: SHA256(string) % order == 0. Pick another string.\n");
    	return 0;
    }

    if (debug)
    	printf ("Secret number: %s\n", BN_bn2dec(nmodorder));

    //now we create a new EC point, ecpoint, and place in it the secp256k1
    //generator point multiplied by nmodorder. this newly created
    //point is the public key

    EC_POINT * ecpoint = EC_POINT_new(pgroup);

	if (!EC_POINT_mul(pgroup, ecpoint, nmodorder, NULL, NULL, NULL))
	{
    	printf("ERROR: Couldn't multiply the generator point with n\n");
    	return 0;
    }


    if (debug) {
        BIGNUM *x=NULL, *y=NULL;
        x=BN_new();
        y=BN_new();

        if (!EC_POINT_get_affine_coordinates_GFp(pgroup, ecpoint, x, y, NULL)) {
        	printf("ERROR: Failed getting coordinates.");
        	//don't fail on debug fail
        	//return 0;
        }

    	printf ("Public key coordinates. x: %s, y: %s\n", BN_bn2dec(x), BN_bn2dec(y));

        BN_free(x);
        BN_free(y);
    }

    //then we need to convert the public key point to data
    //first we get the required size of the buffer in which the data is placed
    //by passing NULL as the buffer argument to EC_POINT_point2oct
    unsigned int bufsize = EC_POINT_point2oct (pgroup, ecpoint, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL);
    u_int8_t * buffer = malloc(bufsize);
    //then we place the data in the buffer
    int len = EC_POINT_point2oct (pgroup, ecpoint, POINT_CONVERSION_UNCOMPRESSED, buffer, bufsize, NULL);
    if (len == 0) {
    	printf("ERROR: Couldn't convert point to octet string.");
    	return 0;
    }

    if (debug) {
    	printf("DER encoded public key: ");
    	print_hex(buffer, len);
    }

    //next we need to hash the public key data. first with SHA256, then with RIPEMD160
    SHA256(buffer, len, hash);
    if (debug) {
    	printf("SHA256 hash of public key: ");
    	print_hex(hash, SHA256_DIGEST_LENGTH);
    }

    u_int8_t * ripemd = malloc(RIPEMD160_DIGEST_LENGTH+1+4);
    RIPEMD160(hash, SHA256_DIGEST_LENGTH, ripemd);

    if (debug) {
    	printf("RIPEMD160 hash of SHA256 hash: ");
    	print_hex(ripemd, RIPEMD160_DIGEST_LENGTH);
    }

    if (base58 == true) {
		//here we add the version byte to the beginning of the public key and four checksum
		//bytes at the end
		prepare_for_address(ripemd, RIPEMD160_DIGEST_LENGTH, 0);

		if (debug) {
			printf("Address in hex with version byte and checksum: ");
			print_hex(ripemd, RIPEMD160_DIGEST_LENGTH+1+4);
		}

		//and we convert the resulting data to base58
		base58_encode(ripemd, RIPEMD160_DIGEST_LENGTH+1+4, address);
    } else {
    	memcpy(address, ripemd, RIPEMD160_DIGEST_LENGTH);
    }

    //now we need to convert the big number nmodorder (private key) to data
    int buflen = BN_num_bytes(nmodorder);
    u_int8_t * buf = malloc(buflen+1+4);
    int datalen;

    //nmodorder is converted to binary representation
    datalen = BN_bn2bin(nmodorder, buf);

    if (debug) {
    	printf("Private key: ");
    	print_hex(buf, datalen);
    }

    if (base58 == true) {
		//and we add version byte and four byte checksum to the data
		prepare_for_address(buf, datalen, 0x80);

        //and convert this to base58
        base58_encode(buf, datalen+5, priv_key);
    } else {
    	memcpy(priv_key, buf, datalen+5);
    }

    free(hash);
    free(buffer);
    free(ripemd);
    free(buf);
    BN_free(n);
    BN_free(order);
    BN_free(nmodorder);
    if (precompgroup == NULL)
    	EC_GROUP_free(pgroup);
    EC_POINT_free(ecpoint);
    BN_CTX_free(bnctx);

    return 1;
}
Beispiel #14
0
int GOST_KEY_check_key(const GOST_KEY *key)
{
    int ok = 0;
    BN_CTX *ctx = NULL;
    BIGNUM *order = NULL;
    EC_POINT *point = NULL;

    if (!key || !key->group || !key->pub_key) {
        GOSTerr(GOST_F_GOST_KEY_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER);
        return 0;
    }
    if (EC_POINT_is_at_infinity(key->group, key->pub_key)) {
        GOSTerr(GOST_F_GOST_KEY_CHECK_KEY, EC_R_POINT_AT_INFINITY);
        goto err;
    }
    if ((ctx = BN_CTX_new()) == NULL)
        goto err;
    if ((point = EC_POINT_new(key->group)) == NULL)
        goto err;

    /* testing whether the pub_key is on the elliptic curve */
    if (EC_POINT_is_on_curve(key->group, key->pub_key, ctx) <= 0) {
        GOSTerr(GOST_F_GOST_KEY_CHECK_KEY, EC_R_POINT_IS_NOT_ON_CURVE);
        goto err;
    }
    /* testing whether pub_key * order is the point at infinity */
    if ((order = BN_new()) == NULL)
        goto err;
    if (!EC_GROUP_get_order(key->group, order, ctx)) {
        GOSTerr(GOST_F_GOST_KEY_CHECK_KEY, EC_R_INVALID_GROUP_ORDER);
        goto err;
    }
    if (!EC_POINT_mul(key->group, point, NULL, key->pub_key, order, ctx)) {
        GOSTerr(GOST_F_GOST_KEY_CHECK_KEY, ERR_R_EC_LIB);
        goto err;
    }
    if (!EC_POINT_is_at_infinity(key->group, point)) {
        GOSTerr(GOST_F_GOST_KEY_CHECK_KEY, EC_R_WRONG_ORDER);
        goto err;
    }
    /*
     * in case the priv_key is present : check if generator * priv_key ==
     * pub_key
     */
    if (key->priv_key) {
        if (BN_cmp(key->priv_key, order) >= 0) {
            GOSTerr(GOST_F_GOST_KEY_CHECK_KEY, EC_R_WRONG_ORDER);
            goto err;
        }
        if (!EC_POINT_mul(key->group, point, key->priv_key, NULL, NULL, ctx)) {
            GOSTerr(GOST_F_GOST_KEY_CHECK_KEY, ERR_R_EC_LIB);
            goto err;
        }
        if (EC_POINT_cmp(key->group, point, key->pub_key, ctx) != 0) {
            GOSTerr(GOST_F_GOST_KEY_CHECK_KEY, EC_R_INVALID_PRIVATE_KEY);
            goto err;
        }
    }
    ok = 1;
err:
    BN_free(order);
    BN_CTX_free(ctx);
    EC_POINT_free(point);
    return (ok);
}
Beispiel #15
0
int StealthSecretSpend(ec_secret& scanSecret, ec_point& ephemPubkey, ec_secret& spendSecret, ec_secret& secretOut)
{
    /*
    
    c  = H(dP)
    R' = R + cG     [without decrypting wallet]
       = (f + c)G   [after decryption of wallet]
         Remember: mod curve.order, pad with 0x00s where necessary?
    */
    
    int rv = 0;
    std::vector<uint8_t> vchOutP;
    
    BN_CTX* bnCtx           = NULL;
    BIGNUM* bnScanSecret    = NULL;
    BIGNUM* bnP             = NULL;
    EC_POINT* P             = NULL;
    BIGNUM* bnOutP          = NULL;
    BIGNUM* bnc             = NULL;
    BIGNUM* bnOrder         = NULL;
    BIGNUM* bnSpend         = NULL;
    
    EC_GROUP* ecgrp = EC_GROUP_new_by_curve_name(NID_secp256k1);
    
    if (!ecgrp)
    {
        LogPrintf("StealthSecretSpend(): EC_GROUP_new_by_curve_name failed.\n");
        return 1;
    };
    
    if (!(bnCtx = BN_CTX_new()))
    {
        LogPrintf("StealthSecretSpend(): BN_CTX_new failed.\n");
        rv = 1;
        goto End;
    };
    
    if (!(bnScanSecret = BN_bin2bn(&scanSecret.e[0], ec_secret_size, BN_new())))
    {
        LogPrintf("StealthSecretSpend(): bnScanSecret BN_bin2bn failed.\n");
        rv = 1;
        goto End;
    };
    
    if (!(bnP = BN_bin2bn(&ephemPubkey[0], ephemPubkey.size(), BN_new())))
    {
        LogPrintf("StealthSecretSpend(): bnP BN_bin2bn failed\n");
        rv = 1;
        goto End;
    };
    
    if (!(P = EC_POINT_bn2point(ecgrp, bnP, NULL, bnCtx)))
    {
        LogPrintf("StealthSecretSpend(): P EC_POINT_bn2point failed\n");
        rv = 1;
        goto End;
    };
    
    // -- dP
    if (!EC_POINT_mul(ecgrp, P, NULL, P, bnScanSecret, bnCtx))
    {
        LogPrintf("StealthSecretSpend(): dP EC_POINT_mul failed\n");
        rv = 1;
        goto End;
    };
    
    if (!(bnOutP = EC_POINT_point2bn(ecgrp, P, POINT_CONVERSION_COMPRESSED, BN_new(), bnCtx)))
    {
        LogPrintf("StealthSecretSpend(): P EC_POINT_bn2point failed\n");
        rv = 1;
        goto End;
    };
    
    
    vchOutP.resize(ec_compressed_size);
    if (BN_num_bytes(bnOutP) != (int) ec_compressed_size
        || BN_bn2bin(bnOutP, &vchOutP[0]) != (int) ec_compressed_size)
    {
        LogPrintf("StealthSecretSpend(): bnOutP incorrect length.\n");
        rv = 1;
        goto End;
    };
    
    uint8_t hash1[32];
    SHA256(&vchOutP[0], vchOutP.size(), (uint8_t*)hash1);
    
    
    if (!(bnc = BN_bin2bn(&hash1[0], 32, BN_new())))
    {
        LogPrintf("StealthSecretSpend(): BN_bin2bn failed\n");
        rv = 1;
        goto End;
    };
    
    if (!(bnOrder = BN_new())
        || !EC_GROUP_get_order(ecgrp, bnOrder, bnCtx))
    {
        LogPrintf("StealthSecretSpend(): EC_GROUP_get_order failed\n");
        rv = 1;
        goto End;
    };
    
    if (!(bnSpend = BN_bin2bn(&spendSecret.e[0], ec_secret_size, BN_new())))
    {
        LogPrintf("StealthSecretSpend(): bnSpend BN_bin2bn failed.\n");
        rv = 1;
        goto End;
    };
    
    //if (!BN_add(r, a, b)) return 0;
    //return BN_nnmod(r, r, m, ctx);
    if (!BN_mod_add(bnSpend, bnSpend, bnc, bnOrder, bnCtx))
    {
        LogPrintf("StealthSecretSpend(): bnSpend BN_mod_add failed.\n");
        rv = 1;
        goto End;
    };
    
    if (BN_is_zero(bnSpend)) // possible?
    {
        LogPrintf("StealthSecretSpend(): bnSpend is zero.\n");
        rv = 1;
        goto End;
    };
    
    int nBytes;
    memset(&secretOut.e[0], 0, ec_secret_size);
    if ((nBytes = BN_num_bytes(bnSpend)) > (int)ec_secret_size
        || BN_bn2bin(bnSpend, &secretOut.e[ec_secret_size-nBytes]) != nBytes)
    {
        LogPrintf("StealthSecretSpend(): bnSpend incorrect length.\n");
        rv = 1;
        goto End;
    };
    
    End:
    if (bnSpend)        BN_free(bnSpend);
    if (bnOrder)        BN_free(bnOrder);
    if (bnc)            BN_free(bnc);
    if (bnOutP)         BN_free(bnOutP);
    if (P)              EC_POINT_free(P);
    if (bnP)            BN_free(bnP);
    if (bnScanSecret)   BN_free(bnScanSecret);
    if (bnCtx)          BN_CTX_free(bnCtx);
    EC_GROUP_free(ecgrp);
    
    return rv;
};
Beispiel #16
0
int ecparam_main(int argc, char **argv)
{
    BIGNUM *ec_gen = NULL, *ec_order = NULL, *ec_cofactor = NULL;
    BIGNUM *ec_p = NULL, *ec_a = NULL, *ec_b = NULL;
    BIO *in = NULL, *out = NULL;
    EC_GROUP *group = NULL;
    point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED;
    char *curve_name = NULL, *inrand = NULL;
    char *infile = NULL, *outfile = NULL, *prog;
    unsigned char *buffer = NULL;
    OPTION_CHOICE o;
    int asn1_flag = OPENSSL_EC_NAMED_CURVE, new_asn1_flag = 0;
    int informat = FORMAT_PEM, outformat = FORMAT_PEM, noout = 0, C = 0, ret =
        1;
    int list_curves = 0, no_seed = 0, check = 0, new_form = 0;
    int text = 0, i, need_rand = 0, genkey = 0;

    prog = opt_init(argc, argv, ecparam_options);
    while ((o = opt_next()) != OPT_EOF) {
        switch (o) {
        case OPT_EOF:
        case OPT_ERR:
 opthelp:
            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
            goto end;
        case OPT_HELP:
            opt_help(ecparam_options);
            ret = 0;
            goto end;
        case OPT_INFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
                goto opthelp;
            break;
        case OPT_IN:
            infile = opt_arg();
            break;
        case OPT_OUTFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat))
                goto opthelp;
            break;
        case OPT_OUT:
            outfile = opt_arg();
            break;
        case OPT_TEXT:
            text = 1;
            break;
        case OPT_C:
            C = 1;
            break;
        case OPT_CHECK:
            check = 1;
            break;
        case OPT_LIST_CURVES:
            list_curves = 1;
            break;
        case OPT_NO_SEED:
            no_seed = 1;
            break;
        case OPT_NOOUT:
            noout = 1;
            break;
        case OPT_NAME:
            curve_name = opt_arg();
            break;
        case OPT_CONV_FORM:
            if (!opt_pair(opt_arg(), forms, &new_form))
                goto opthelp;
            form = new_form;
            new_form = 1;
            break;
        case OPT_PARAM_ENC:
            if (!opt_pair(opt_arg(), encodings, &asn1_flag))
                goto opthelp;
            new_asn1_flag = 1;
            break;
        case OPT_GENKEY:
            genkey = need_rand = 1;
            break;
        case OPT_RAND:
            inrand = opt_arg();
            need_rand = 1;
            break;
        case OPT_ENGINE:
            (void)setup_engine(opt_arg(), 0);
            break;
        }
    }
    argc = opt_num_rest();
    argv = opt_rest();

    in = bio_open_default(infile, RB(informat));
    if (in == NULL)
        goto end;
    out = bio_open_default(outfile, WB(outformat));
    if (out == NULL)
        goto end;

    if (list_curves) {
        EC_builtin_curve *curves = NULL;
        size_t crv_len = EC_get_builtin_curves(NULL, 0);
        size_t n;

        curves = app_malloc((int)sizeof(*curves) * crv_len, "list curves");
        if (!EC_get_builtin_curves(curves, crv_len)) {
            OPENSSL_free(curves);
            goto end;
        }

        for (n = 0; n < crv_len; n++) {
            const char *comment;
            const char *sname;
            comment = curves[n].comment;
            sname = OBJ_nid2sn(curves[n].nid);
            if (comment == NULL)
                comment = "CURVE DESCRIPTION NOT AVAILABLE";
            if (sname == NULL)
                sname = "";

            BIO_printf(out, "  %-10s: ", sname);
            BIO_printf(out, "%s\n", comment);
        }

        OPENSSL_free(curves);
        ret = 0;
        goto end;
    }

    if (curve_name != NULL) {
        int nid;

        /*
         * workaround for the SECG curve names secp192r1 and secp256r1 (which
         * are the same as the curves prime192v1 and prime256v1 defined in
         * X9.62)
         */
        if (strcmp(curve_name, "secp192r1") == 0) {
            BIO_printf(bio_err, "using curve name prime192v1 "
                       "instead of secp192r1\n");
            nid = NID_X9_62_prime192v1;
        } else if (strcmp(curve_name, "secp256r1") == 0) {
            BIO_printf(bio_err, "using curve name prime256v1 "
                       "instead of secp256r1\n");
            nid = NID_X9_62_prime256v1;
        } else
            nid = OBJ_sn2nid(curve_name);

        if (nid == 0)
            nid = EC_curve_nist2nid(curve_name);

        if (nid == 0) {
            BIO_printf(bio_err, "unknown curve name (%s)\n", curve_name);
            goto end;
        }

        group = EC_GROUP_new_by_curve_name(nid);
        if (group == NULL) {
            BIO_printf(bio_err, "unable to create curve (%s)\n", curve_name);
            goto end;
        }
        EC_GROUP_set_asn1_flag(group, asn1_flag);
        EC_GROUP_set_point_conversion_form(group, form);
    } else if (informat == FORMAT_ASN1)
        group = d2i_ECPKParameters_bio(in, NULL);
    else
        group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL);
    if (group == NULL) {
        BIO_printf(bio_err, "unable to load elliptic curve parameters\n");
        ERR_print_errors(bio_err);
        goto end;
    }

    if (new_form)
        EC_GROUP_set_point_conversion_form(group, form);

    if (new_asn1_flag)
        EC_GROUP_set_asn1_flag(group, asn1_flag);

    if (no_seed) {
        EC_GROUP_set_seed(group, NULL, 0);
    }

    if (text) {
        if (!ECPKParameters_print(out, group, 0))
            goto end;
    }

    if (check) {
        if (group == NULL)
            BIO_printf(bio_err, "no elliptic curve parameters\n");
        BIO_printf(bio_err, "checking elliptic curve parameters: ");
        if (!EC_GROUP_check(group, NULL)) {
            BIO_printf(bio_err, "failed\n");
            ERR_print_errors(bio_err);
        } else
            BIO_printf(bio_err, "ok\n");

    }

    if (C) {
        size_t buf_len = 0, tmp_len = 0;
        const EC_POINT *point;
        int is_prime, len = 0;
        const EC_METHOD *meth = EC_GROUP_method_of(group);

        if ((ec_p = BN_new()) == NULL
                || (ec_a = BN_new()) == NULL
                || (ec_b = BN_new()) == NULL
                || (ec_gen = BN_new()) == NULL
                || (ec_order = BN_new()) == NULL
                || (ec_cofactor = BN_new()) == NULL) {
            perror("Can't allocate BN");
            goto end;
        }

        is_prime = (EC_METHOD_get_field_type(meth) == NID_X9_62_prime_field);
        if (!is_prime) {
            BIO_printf(bio_err, "Can only handle X9.62 prime fields\n");
            goto end;
        }

        if (!EC_GROUP_get_curve_GFp(group, ec_p, ec_a, ec_b, NULL))
            goto end;

        if ((point = EC_GROUP_get0_generator(group)) == NULL)
            goto end;
        if (!EC_POINT_point2bn(group, point,
                               EC_GROUP_get_point_conversion_form(group),
                               ec_gen, NULL))
            goto end;
        if (!EC_GROUP_get_order(group, ec_order, NULL))
            goto end;
        if (!EC_GROUP_get_cofactor(group, ec_cofactor, NULL))
            goto end;

        if (!ec_p || !ec_a || !ec_b || !ec_gen || !ec_order || !ec_cofactor)
            goto end;

        len = BN_num_bits(ec_order);

        if ((tmp_len = (size_t)BN_num_bytes(ec_p)) > buf_len)
            buf_len = tmp_len;
        if ((tmp_len = (size_t)BN_num_bytes(ec_a)) > buf_len)
            buf_len = tmp_len;
        if ((tmp_len = (size_t)BN_num_bytes(ec_b)) > buf_len)
            buf_len = tmp_len;
        if ((tmp_len = (size_t)BN_num_bytes(ec_gen)) > buf_len)
            buf_len = tmp_len;
        if ((tmp_len = (size_t)BN_num_bytes(ec_order)) > buf_len)
            buf_len = tmp_len;
        if ((tmp_len = (size_t)BN_num_bytes(ec_cofactor)) > buf_len)
            buf_len = tmp_len;

        buffer = app_malloc(buf_len, "BN buffer");

        BIO_printf(out, "EC_GROUP *get_ec_group_%d(void)\n{\n", len);
        print_bignum_var(out, ec_p, "ec_p", len, buffer);
        print_bignum_var(out, ec_a, "ec_a", len, buffer);
        print_bignum_var(out, ec_b, "ec_b", len, buffer);
        print_bignum_var(out, ec_gen, "ec_gen", len, buffer);
        print_bignum_var(out, ec_order, "ec_order", len, buffer);
        print_bignum_var(out, ec_cofactor, "ec_cofactor", len, buffer);
        BIO_printf(out, "    int ok = 0;\n"
                        "    EC_GROUP *group = NULL;\n"
                        "    EC_POINT *point = NULL;\n"
                        "    BIGNUM *tmp_1 = NULL;\n"
                        "    BIGNUM *tmp_2 = NULL;\n"
                        "    BIGNUM *tmp_3 = NULL;\n"
                        "\n");

        BIO_printf(out, "    if ((tmp_1 = BN_bin2bn(ec_p_%d, sizeof (ec_p_%d), NULL)) == NULL)\n"
                        "        goto err;\n", len, len);
        BIO_printf(out, "    if ((tmp_2 = BN_bin2bn(ec_a_%d, sizeof (ec_a_%d), NULL)) == NULL)\n"
                        "        goto err;\n", len, len);
        BIO_printf(out, "    if ((tmp_3 = BN_bin2bn(ec_b_%d, sizeof (ec_b_%d), NULL)) == NULL)\n"
                        "        goto err;\n", len, len);
        BIO_printf(out, "    if ((group = EC_GROUP_new_curve_GFp(tmp_1, tmp_2, tmp_3, NULL)) == NULL)\n"
                        "        goto err;\n"
                        "\n");
        BIO_printf(out, "    /* build generator */\n");
        BIO_printf(out, "    if ((tmp_1 = BN_bin2bn(ec_gen_%d, sizeof (ec_gen_%d), tmp_1)) == NULL)\n"
                        "        goto err;\n", len, len);
        BIO_printf(out, "    point = EC_POINT_bn2point(group, tmp_1, NULL, NULL);\n");
        BIO_printf(out, "    if (point == NULL)\n"
                        "        goto err;\n");
        BIO_printf(out, "    if ((tmp_2 = BN_bin2bn(ec_order_%d, sizeof (ec_order_%d), tmp_2)) == NULL)\n"
                        "        goto err;\n", len, len);
        BIO_printf(out, "    if ((tmp_3 = BN_bin2bn(ec_cofactor_%d, sizeof (ec_cofactor_%d), tmp_3)) == NULL)\n"
                        "        goto err;\n", len, len);
        BIO_printf(out, "    if (!EC_GROUP_set_generator(group, point, tmp_2, tmp_3))\n"
                        "        goto err;\n"
                        "ok = 1;"
                        "\n");
        BIO_printf(out, "err:\n"
                        "    BN_free(tmp_1);\n"
                        "    BN_free(tmp_2);\n"
                        "    BN_free(tmp_3);\n"
                        "    EC_POINT_free(point);\n"
                        "    if (!ok) {\n"
                        "        EC_GROUP_free(group);\n"
                        "        return NULL;\n"
                        "    }\n"
                        "    return (group);\n"
                        "}\n");
    }

    if (!noout) {
        if (outformat == FORMAT_ASN1)
            i = i2d_ECPKParameters_bio(out, group);
        else
            i = PEM_write_bio_ECPKParameters(out, group);
        if (!i) {
            BIO_printf(bio_err, "unable to write elliptic "
                       "curve parameters\n");
            ERR_print_errors(bio_err);
            goto end;
        }
    }

    if (need_rand) {
        app_RAND_load_file(NULL, (inrand != NULL));
        if (inrand != NULL)
            BIO_printf(bio_err, "%ld semi-random bytes loaded\n",
                       app_RAND_load_files(inrand));
    }

    if (genkey) {
        EC_KEY *eckey = EC_KEY_new();

        if (eckey == NULL)
            goto end;

        assert(need_rand);

        if (EC_KEY_set_group(eckey, group) == 0)
            goto end;

        if (!EC_KEY_generate_key(eckey)) {
            EC_KEY_free(eckey);
            goto end;
        }
        if (outformat == FORMAT_ASN1)
            i = i2d_ECPrivateKey_bio(out, eckey);
        else
            i = PEM_write_bio_ECPrivateKey(out, eckey, NULL,
                                           NULL, 0, NULL, NULL);
        EC_KEY_free(eckey);
    }

    if (need_rand)
        app_RAND_write_file(NULL);

    ret = 0;
 end:
    BN_free(ec_p);
    BN_free(ec_a);
    BN_free(ec_b);
    BN_free(ec_gen);
    BN_free(ec_order);
    BN_free(ec_cofactor);
    OPENSSL_free(buffer);
    BIO_free(in);
    BIO_free_all(out);
    EC_GROUP_free(group);
    return (ret);
}
Beispiel #17
0
int StealthSharedToSecretSpend(ec_secret& sharedS, ec_secret& spendSecret, ec_secret& secretOut)
{
    int rv = 0;
    std::vector<uint8_t> vchOutP;
    
    BN_CTX* bnCtx           = NULL;
    BIGNUM* bnc             = NULL;
    BIGNUM* bnOrder         = NULL;
    BIGNUM* bnSpend         = NULL;
    
    EC_GROUP* ecgrp = EC_GROUP_new_by_curve_name(NID_secp256k1);
    
    if (!ecgrp)
    {
        LogPrintf("StealthSecretSpend(): EC_GROUP_new_by_curve_name failed.\n");
        return 1;
    };
    
    if (!(bnCtx = BN_CTX_new()))
    {
        LogPrintf("StealthSecretSpend(): BN_CTX_new failed.\n");
        rv = 1;
        goto End;
    };
    
    if (!(bnc = BN_bin2bn(&sharedS.e[0], ec_secret_size, BN_new())))
    {
        LogPrintf("StealthSecretSpend(): BN_bin2bn failed\n");
        rv = 1;
        goto End;
    };
    
    if (!(bnOrder = BN_new())
        || !EC_GROUP_get_order(ecgrp, bnOrder, bnCtx))
    {
        LogPrintf("StealthSecretSpend(): EC_GROUP_get_order failed\n");
        rv = 1;
        goto End;
    };
    
    if (!(bnSpend = BN_bin2bn(&spendSecret.e[0], ec_secret_size, BN_new())))
    {
        LogPrintf("StealthSecretSpend(): bnSpend BN_bin2bn failed.\n");
        rv = 1;
        goto End;
    };
    
    //if (!BN_add(r, a, b)) return 0;
    //return BN_nnmod(r, r, m, ctx);
    if (!BN_mod_add(bnSpend, bnSpend, bnc, bnOrder, bnCtx))
    {
        LogPrintf("StealthSecretSpend(): bnSpend BN_mod_add failed.\n");
        rv = 1;
        goto End;
    };
    
    if (BN_is_zero(bnSpend)) // possible?
    {
        LogPrintf("StealthSecretSpend(): bnSpend is zero.\n");
        rv = 1;
        goto End;
    };
    
    int nBytes;
    memset(&secretOut.e[0], 0, ec_secret_size);
    if ((nBytes = BN_num_bytes(bnSpend)) > (int)ec_secret_size
        || BN_bn2bin(bnSpend, &secretOut.e[ec_secret_size-nBytes]) != nBytes)
    {
        LogPrintf("StealthSecretSpend(): bnSpend incorrect length.\n");
        rv = 1;
        goto End;
    };
    
    End:
    if (bnSpend)        BN_free(bnSpend);
    if (bnOrder)        BN_free(bnOrder);
    if (bnc)            BN_free(bnc);
    if (bnCtx)          BN_CTX_free(bnCtx);
    EC_GROUP_free(ecgrp);
    
    return rv;
};
Beispiel #18
0
int EC_KEY_check_key(const EC_KEY *eckey)
  {
  int  ok   = 0;
  BN_CTX  *ctx = NULL;
  BIGNUM  *order  = NULL;
  EC_POINT *point = NULL;

  if (!eckey || !eckey->group || !eckey->pub_key)
    {
    ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER);
    return 0;
    }
  
  if ((ctx = BN_CTX_new()) == NULL)
    goto err;
  if ((order = BN_new()) == NULL)
    goto err;
  if ((point = EC_POINT_new(eckey->group)) == NULL)
    goto err;

  /* testing whether the pub_key is on the elliptic curve */
  if (!EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx))
    {
    ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_POINT_IS_NOT_ON_CURVE);
    goto err;
    }
  /* testing whether pub_key * order is the point at infinity */
  if (!EC_GROUP_get_order(eckey->group, order, ctx))
    {
    ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_INVALID_GROUP_ORDER);
    goto err;
    }
  if (!EC_POINT_copy(point, eckey->pub_key))
    {
    ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_EC_LIB);
    goto err;
    }
  if (!EC_POINT_mul(eckey->group, point, order, NULL, NULL, ctx))
    {
    ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_EC_LIB);
    goto err;
    }
  if (!EC_POINT_is_at_infinity(eckey->group, point))
    {
    ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_WRONG_ORDER);
    goto err;
    }
  /* in case the priv_key is present : 
   * check if generator * priv_key == pub_key 
   */
  if (eckey->priv_key)
    {
    if (BN_cmp(eckey->priv_key, order) >= 0)
      {
      ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_WRONG_ORDER);
      goto err;
      }
    if (!EC_POINT_mul(eckey->group, point, eckey->priv_key,
      NULL, NULL, ctx))
      {
      ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_EC_LIB);
      goto err;
      }
    if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, 
      ctx) != 0)
      {
      ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_INVALID_PRIVATE_KEY);
      goto err;
      }
    }
  ok = 1;
err:
  if (ctx   != NULL)
    BN_CTX_free(ctx);
  if (order != NULL)
    BN_free(order);
  if (point != NULL)
    EC_POINT_free(point);
  return(ok);
  }
Beispiel #19
0
int 
ECPKParameters_print(BIO * bp, const EC_GROUP * x, int off)
{
	unsigned char *buffer = NULL;
	size_t buf_len = 0, i;
	int ret = 0, reason = ERR_R_BIO_LIB;
	BN_CTX *ctx = NULL;
	const EC_POINT *point = NULL;
	BIGNUM *p = NULL, *a = NULL, *b = NULL, *gen = NULL, *order = NULL,
	*cofactor = NULL;
	const unsigned char *seed;
	size_t seed_len = 0;

	static const char *gen_compressed = "Generator (compressed):";
	static const char *gen_uncompressed = "Generator (uncompressed):";
	static const char *gen_hybrid = "Generator (hybrid):";

	if (!x) {
		reason = ERR_R_PASSED_NULL_PARAMETER;
		goto err;
	}
	ctx = BN_CTX_new();
	if (ctx == NULL) {
		reason = ERR_R_MALLOC_FAILURE;
		goto err;
	}
	if (EC_GROUP_get_asn1_flag(x)) {
		/* the curve parameter are given by an asn1 OID */
		int nid;

		if (!BIO_indent(bp, off, 128))
			goto err;

		nid = EC_GROUP_get_curve_name(x);
		if (nid == 0)
			goto err;

		if (BIO_printf(bp, "ASN1 OID: %s", OBJ_nid2sn(nid)) <= 0)
			goto err;
		if (BIO_printf(bp, "\n") <= 0)
			goto err;
	} else {
		/* explicit parameters */
		int is_char_two = 0;
		point_conversion_form_t form;
		int tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(x));

		if (tmp_nid == NID_X9_62_characteristic_two_field)
			is_char_two = 1;

		if ((p = BN_new()) == NULL || (a = BN_new()) == NULL ||
		    (b = BN_new()) == NULL || (order = BN_new()) == NULL ||
		    (cofactor = BN_new()) == NULL) {
			reason = ERR_R_MALLOC_FAILURE;
			goto err;
		}
#ifndef OPENSSL_NO_EC2M
		if (is_char_two) {
			if (!EC_GROUP_get_curve_GF2m(x, p, a, b, ctx)) {
				reason = ERR_R_EC_LIB;
				goto err;
			}
		} else		/* prime field */
#endif
		{
			if (!EC_GROUP_get_curve_GFp(x, p, a, b, ctx)) {
				reason = ERR_R_EC_LIB;
				goto err;
			}
		}

		if ((point = EC_GROUP_get0_generator(x)) == NULL) {
			reason = ERR_R_EC_LIB;
			goto err;
		}
		if (!EC_GROUP_get_order(x, order, NULL) ||
		    !EC_GROUP_get_cofactor(x, cofactor, NULL)) {
			reason = ERR_R_EC_LIB;
			goto err;
		}
		form = EC_GROUP_get_point_conversion_form(x);

		if ((gen = EC_POINT_point2bn(x, point,
			    form, NULL, ctx)) == NULL) {
			reason = ERR_R_EC_LIB;
			goto err;
		}
		buf_len = (size_t) BN_num_bytes(p);
		if (buf_len < (i = (size_t) BN_num_bytes(a)))
			buf_len = i;
		if (buf_len < (i = (size_t) BN_num_bytes(b)))
			buf_len = i;
		if (buf_len < (i = (size_t) BN_num_bytes(gen)))
			buf_len = i;
		if (buf_len < (i = (size_t) BN_num_bytes(order)))
			buf_len = i;
		if (buf_len < (i = (size_t) BN_num_bytes(cofactor)))
			buf_len = i;

		if ((seed = EC_GROUP_get0_seed(x)) != NULL)
			seed_len = EC_GROUP_get_seed_len(x);

		buf_len += 10;
		if ((buffer = malloc(buf_len)) == NULL) {
			reason = ERR_R_MALLOC_FAILURE;
			goto err;
		}
		if (!BIO_indent(bp, off, 128))
			goto err;

		/* print the 'short name' of the field type */
		if (BIO_printf(bp, "Field Type: %s\n", OBJ_nid2sn(tmp_nid))
		    <= 0)
			goto err;

		if (is_char_two) {
			/* print the 'short name' of the base type OID */
			int basis_type = EC_GROUP_get_basis_type(x);
			if (basis_type == 0)
				goto err;

			if (!BIO_indent(bp, off, 128))
				goto err;

			if (BIO_printf(bp, "Basis Type: %s\n",
				OBJ_nid2sn(basis_type)) <= 0)
				goto err;

			/* print the polynomial */
			if ((p != NULL) && !ASN1_bn_print(bp, "Polynomial:", p, buffer,
				off))
				goto err;
		} else {
			if ((p != NULL) && !ASN1_bn_print(bp, "Prime:", p, buffer, off))
				goto err;
		}
		if ((a != NULL) && !ASN1_bn_print(bp, "A:   ", a, buffer, off))
			goto err;
		if ((b != NULL) && !ASN1_bn_print(bp, "B:   ", b, buffer, off))
			goto err;
		if (form == POINT_CONVERSION_COMPRESSED) {
			if ((gen != NULL) && !ASN1_bn_print(bp, gen_compressed, gen,
				buffer, off))
				goto err;
		} else if (form == POINT_CONVERSION_UNCOMPRESSED) {
			if ((gen != NULL) && !ASN1_bn_print(bp, gen_uncompressed, gen,
				buffer, off))
				goto err;
		} else {	/* form == POINT_CONVERSION_HYBRID */
			if ((gen != NULL) && !ASN1_bn_print(bp, gen_hybrid, gen,
				buffer, off))
				goto err;
		}
		if ((order != NULL) && !ASN1_bn_print(bp, "Order: ", order,
			buffer, off))
			goto err;
		if ((cofactor != NULL) && !ASN1_bn_print(bp, "Cofactor: ", cofactor,
			buffer, off))
			goto err;
		if (seed && !print_bin(bp, "Seed:", seed, seed_len, off))
			goto err;
	}
	ret = 1;
err:
	if (!ret)
		ECerr(EC_F_ECPKPARAMETERS_PRINT, reason);
	if (p)
		BN_free(p);
	if (a)
		BN_free(a);
	if (b)
		BN_free(b);
	if (gen)
		BN_free(gen);
	if (order)
		BN_free(order);
	if (cofactor)
		BN_free(cofactor);
	if (ctx)
		BN_CTX_free(ctx);
	free(buffer);
	return (ret);
}
Beispiel #20
0
static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
		BIGNUM **rp)
{
	BN_CTX   *ctx = NULL;
	BIGNUM	 *k = NULL, *r = NULL, *order = NULL, *X = NULL;
	EC_POINT *tmp_point=NULL;
	const EC_GROUP *group;
	int 	 ret = 0;

	if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL)
	{
		ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_PASSED_NULL_PARAMETER);
		return 0;
	}

	if (ctx_in == NULL) 
	{
		if ((ctx = BN_CTX_new()) == NULL)
		{
			ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,ERR_R_MALLOC_FAILURE);
			return 0;
		}
	}
	else
		ctx = ctx_in;

	k     = BN_new();	/* this value is later returned in *kinvp */
	r     = BN_new();	/* this value is later returned in *rp    */
	order = BN_new();
	X     = BN_new();
	if (!k || !r || !order || !X)
	{
		ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE);
		goto err;
	}
	if ((tmp_point = EC_POINT_new(group)) == NULL)
	{
		ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB);
		goto err;
	}
	if (!EC_GROUP_get_order(group, order, ctx))
	{
		ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB);
		goto err;
	}
	
	do
	{
		/* get random k */	
		do
			if (!BN_rand_range(k, order))
			{
				ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,
				 ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED);	
				goto err;
			}
		while (BN_is_zero(k));

		/* compute r the x-coordinate of generator * k */
		if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx))
		{
			ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB);
			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_point, X, NULL, ctx))
			{
				ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,ERR_R_EC_LIB);
				goto err;
			}
		}
		else /* NID_X9_62_characteristic_two_field */
		{
			if (!EC_POINT_get_affine_coordinates_GF2m(group,
				tmp_point, X, NULL, ctx))
			{
				ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,ERR_R_EC_LIB);
				goto err;
			}
		}
		if (!BN_nnmod(r, X, order, ctx))
		{
			ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB);
			goto err;
		}
	}
	while (BN_is_zero(r));

	/* compute the inverse of k */
	if (!BN_mod_inverse(k, k, order, ctx))
	{
		ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB);
		goto err;	
	}
	/* clear old values if necessary */
	if (*rp != NULL)
		BN_clear_free(*rp);
	if (*kinvp != NULL) 
		BN_clear_free(*kinvp);
	/* save the pre-computed values  */
	*rp    = r;
	*kinvp = k;
	ret = 1;
err:
	if (!ret)
	{
		if (k != NULL) BN_clear_free(k);
		if (r != NULL) BN_clear_free(r);
	}
	if (ctx_in == NULL) 
		BN_CTX_free(ctx);
	if (order != NULL)
		BN_free(order);
	if (tmp_point != NULL) 
		EC_POINT_free(tmp_point);
	if (X)
		BN_clear_free(X);
	return(ret);
}
Beispiel #21
0
static void CheckPublicKey(X509 *x509, struct tm tm_after)
{
	EVP_PKEY *pkey = X509_get_pubkey(x509);
	if (pkey == NULL)
	{
		SetError(ERR_UNKNOWN_PUBLIC_KEY_TYPE);
	}
	else if (EVP_PKEY_base_id(pkey) == EVP_PKEY_RSA)
	{
		RSA *rsa = EVP_PKEY_get1_RSA(pkey);

		if (rsa == NULL)
		{
			SetError(ERR_INVALID);
			RSA_free(rsa);
			return;
		}

		const BIGNUM *n, *e;
		RSA_get0_key(rsa, &n, &e, NULL);
		if (n == NULL || e == NULL)
		{
			SetError(ERR_INVALID);
			RSA_free(rsa);
			return;
		}
		if (!GetBit(errors, ERR_INVALID_TIME_FORMAT))
		{
			if (tm_after.tm_year >= 114 && BN_num_bits(n) < 2048)
			{
				SetError(ERR_RSA_SIZE_2048);
			}
		}
		if (BN_is_odd(e) == 0)
		{
			SetError(ERR_RSA_EXP_NOT_ODD);
		}
		BIGNUM *i = BN_new();
		BN_set_word(i, 3);
		if (BN_cmp(e, i) < 0)
		{
			SetError(ERR_RSA_EXP_3);
		}
		else
		{
			BN_set_word(i, 0x10001);
			if (BN_cmp(e, i) < 0)
			{
				SetWarning(WARN_RSA_EXP_RANGE);
			}
			BN_hex2bn(&i, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
			if (BN_cmp(e, i) > 0)
			{
				SetWarning(WARN_RSA_EXP_RANGE);
			}
		}
		BN_CTX *ctx = BN_CTX_new();
		if (BN_gcd(i, n, bn_factors, ctx) == 0 || !BN_is_one(i))
		{
			SetError(ERR_RSA_SMALL_FACTOR);
		}
		BN_free(i);
		BN_CTX_free(ctx);
		RSA_free(rsa);
	}
	else if (EVP_PKEY_base_id(pkey) == EVP_PKEY_EC)
	{
		EC_KEY *ec_key = EVP_PKEY_get1_EC_KEY(pkey);
		const EC_GROUP *group = EC_KEY_get0_group(ec_key);
		const EC_POINT *point = EC_KEY_get0_public_key(ec_key);
		BN_CTX *ctx = BN_CTX_new();
		BIGNUM *order = BN_new();
		EC_GROUP_get_order(group, order, ctx);
		if (EC_POINT_is_at_infinity(group, point))
		{
			SetError(ERR_EC_AT_INFINITY);
		}
		if (EC_POINT_is_on_curve(group, point, ctx) != 1)
		{
			SetError(ERR_EC_POINT_NOT_ON_CURVE);
		}
		EC_POINT *result = EC_POINT_new(group);
		if (BN_is_zero(order))
		{
			SetError(ERR_EC_INVALID_GROUP_ORDER);
		}
		EC_POINT_mul(group, result, NULL, point, order, ctx);
		if (!EC_POINT_is_at_infinity(group, result))
		{
			SetError(ERR_EC_INCORRECT_ORDER);
		}
		int nid = EC_GROUP_get_curve_name(group);
		if (nid != NID_X9_62_prime256v1 && nid != NID_secp384r1 && nid != NID_secp521r1)
		{
			SetError(ERR_EC_NON_ALLOWED_CURVE);
		}
		EC_POINT_free(result);
		BN_free(order);
		BN_CTX_free(ctx);
		EC_KEY_free(ec_key);
	}
	else
	{
		SetError(ERR_UNKNOWN_PUBLIC_KEY_TYPE);
	}

	if (pkey != NULL)
	{
		EVP_PKEY_free(pkey);
	}
}
Beispiel #22
0
static ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dgst_len,
                                const BIGNUM *in_kinv, const BIGNUM *in_r,
                                EC_KEY *eckey)
{
    int ok = 0, i;
    BIGNUM *kinv = NULL, *s, *m = NULL, *tmp = NULL, *order = NULL;
    const BIGNUM *ckinv;
    BN_CTX *ctx = NULL;
    const EC_GROUP *group;
    ECDSA_SIG *ret;
    ECDSA_DATA *ecdsa;
    const BIGNUM *priv_key;

    ecdsa = ecdsa_check(eckey);
    group = EC_KEY_get0_group(eckey);
    priv_key = EC_KEY_get0_private_key(eckey);

    if (group == NULL || priv_key == NULL || ecdsa == NULL) {
        ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_PASSED_NULL_PARAMETER);
        return NULL;
    }

    ret = ECDSA_SIG_new();
    if (!ret) {
        ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
        return NULL;
    }
    s = ret->s;

    if ((ctx = BN_CTX_new()) == NULL || (order = BN_new()) == NULL ||
        (tmp = BN_new()) == NULL || (m = BN_new()) == NULL) {
        ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
        goto err;
    }

    if (!EC_GROUP_get_order(group, order, ctx)) {
        ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_EC_LIB);
        goto err;
    }
    i = BN_num_bits(order);
    /*
     * Need to truncate digest if it is too long: first truncate whole bytes.
     */
    if (8 * dgst_len > i)
        dgst_len = (i + 7) / 8;
    if (!BN_bin2bn(dgst, dgst_len, m)) {
        ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
        goto err;
    }
    /* If still too long truncate remaining bits with a shift */
    if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) {
        ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
        goto err;
    }
    do {
        if (in_kinv == NULL || in_r == NULL) {
            if (!ECDSA_sign_setup(eckey, ctx, &kinv, &ret->r)) {
                ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_ECDSA_LIB);
                goto err;
            }
            ckinv = kinv;
        } else {
            ckinv = in_kinv;
            if (BN_copy(ret->r, in_r) == NULL) {
                ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
                goto err;
            }
        }

        if (!BN_mod_mul(tmp, priv_key, ret->r, order, ctx)) {
            ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
            goto err;
        }
        if (!BN_mod_add_quick(s, tmp, m, order)) {
            ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
            goto err;
        }
        if (!BN_mod_mul(s, s, ckinv, order, ctx)) {
            ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
            goto err;
        }
        if (BN_is_zero(s)) {
            /*
             * if kinv and r have been supplied by the caller don't to
             * generate new kinv and r values
             */
            if (in_kinv != NULL && in_r != NULL) {
                ECDSAerr(ECDSA_F_ECDSA_DO_SIGN,
                         ECDSA_R_NEED_NEW_SETUP_VALUES);
                goto err;
            }
        } else
            /* s != 0 => we have a valid signature */
            break;
    }
    while (1);

    ok = 1;
 err:
    if (!ok) {
        ECDSA_SIG_free(ret);
        ret = NULL;
    }
    if (ctx)
        BN_CTX_free(ctx);
    if (m)
        BN_clear_free(m);
    if (tmp)
        BN_clear_free(tmp);
    if (order)
        BN_free(order);
    if (kinv)
        BN_clear_free(kinv);
    return ret;
}
Beispiel #23
0
// Perform ECDSA key recovery (see SEC1 4.1.6) for curves over (mod p)-fields
// recid selects which key is recovered
// if check is non-zero, additional checks are performed
int ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned char *msg, int msglen, int recid, int check)
{
    if (!eckey) return 0;

    int ret = 0;
    BN_CTX *ctx = NULL;

    BIGNUM *x = NULL;
    BIGNUM *e = NULL;
    BIGNUM *order = NULL;
    BIGNUM *sor = NULL;
    BIGNUM *eor = NULL;
    BIGNUM *field = NULL;
    EC_POINT *R = NULL;
    EC_POINT *O = NULL;
    EC_POINT *Q = NULL;
    BIGNUM *rr = NULL;
    BIGNUM *zero = NULL;
    int n = 0;
    int i = recid / 2;

    const EC_GROUP *group = EC_KEY_get0_group(eckey);
    if ((ctx = BN_CTX_new()) == NULL) { ret = -1; goto err; }
    BN_CTX_start(ctx);
    order = BN_CTX_get(ctx);
    if (!EC_GROUP_get_order(group, order, ctx)) { ret = -2; goto err; }
    x = BN_CTX_get(ctx);
    if (!BN_copy(x, order)) { ret=-1; goto err; }
    if (!BN_mul_word(x, i)) { ret=-1; goto err; }
    if (!BN_add(x, x, ecsig->r)) { ret=-1; goto err; }
    field = BN_CTX_get(ctx);
    if (!EC_GROUP_get_curve_GFp(group, field, NULL, NULL, ctx)) { ret=-2; goto err; }
    if (BN_cmp(x, field) >= 0) { ret=0; goto err; }
    if ((R = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
    if (!EC_POINT_set_compressed_coordinates_GFp(group, R, x, recid % 2, ctx)) { ret=0; goto err; }
    if (check)
    {
        if ((O = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
        if (!EC_POINT_mul(group, O, NULL, R, order, ctx)) { ret=-2; goto err; }
        if (!EC_POINT_is_at_infinity(group, O)) { ret = 0; goto err; }
    }
    if ((Q = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
    n = EC_GROUP_get_degree(group);
    e = BN_CTX_get(ctx);
    if (!BN_bin2bn(msg, msglen, e)) { ret=-1; goto err; }
    if (8*msglen > n) BN_rshift(e, e, 8-(n & 7));
    zero = BN_CTX_get(ctx);
    if (!BN_zero(zero)) { ret=-1; goto err; }
    if (!BN_mod_sub(e, zero, e, order, ctx)) { ret=-1; goto err; }
    rr = BN_CTX_get(ctx);
    if (!BN_mod_inverse(rr, ecsig->r, order, ctx)) { ret=-1; goto err; }
    sor = BN_CTX_get(ctx);
    if (!BN_mod_mul(sor, ecsig->s, rr, order, ctx)) { ret=-1; goto err; }
    eor = BN_CTX_get(ctx);
    if (!BN_mod_mul(eor, e, rr, order, ctx)) { ret=-1; goto err; }
    if (!EC_POINT_mul(group, Q, eor, R, sor, ctx)) { ret=-2; goto err; }
    if (!EC_KEY_set_public_key(eckey, Q)) { ret=-2; goto err; }

    ret = 1;

err:
    if (ctx) {
        BN_CTX_end(ctx);
        BN_CTX_free(ctx);
    }
    if (R != NULL) EC_POINT_free(R);
    if (O != NULL) EC_POINT_free(O);
    if (Q != NULL) EC_POINT_free(Q);
    return ret;
}
Beispiel #24
0
static int ecdsa_do_verify(const unsigned char *dgst, int dgst_len,
                           const ECDSA_SIG *sig, EC_KEY *eckey)
{
    int ret = -1, i;
    BN_CTX *ctx;
    BIGNUM *order, *u1, *u2, *m, *X;
    EC_POINT *point = NULL;
    const EC_GROUP *group;
    const EC_POINT *pub_key;

    /* check input values */
    if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL ||
        (pub_key = EC_KEY_get0_public_key(eckey)) == NULL || sig == NULL) {
        ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_MISSING_PARAMETERS);
        return -1;
    }

    ctx = BN_CTX_new();
    if (!ctx) {
        ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE);
        return -1;
    }
    BN_CTX_start(ctx);
    order = BN_CTX_get(ctx);
    u1 = BN_CTX_get(ctx);
    u2 = BN_CTX_get(ctx);
    m = BN_CTX_get(ctx);
    X = BN_CTX_get(ctx);
    if (!X) {
        ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
        goto err;
    }

    if (!EC_GROUP_get_order(group, order, ctx)) {
        ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
        goto err;
    }

    if (BN_is_zero(sig->r) || BN_is_negative(sig->r) ||
        BN_ucmp(sig->r, order) >= 0 || BN_is_zero(sig->s) ||
        BN_is_negative(sig->s) || BN_ucmp(sig->s, order) >= 0) {
        ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_BAD_SIGNATURE);
        ret = 0;                /* signature is invalid */
        goto err;
    }
    /* calculate tmp1 = inv(S) mod order */
    if (!BN_mod_inverse(u2, sig->s, order, ctx)) {
        ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
        goto err;
    }
    /* digest -> m */
    i = BN_num_bits(order);
    /*
     * Need to truncate digest if it is too long: first truncate whole bytes.
     */
    if (8 * dgst_len > i)
        dgst_len = (i + 7) / 8;
    if (!BN_bin2bn(dgst, dgst_len, m)) {
        ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
        goto err;
    }
    /* If still too long truncate remaining bits with a shift */
    if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) {
        ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
        goto err;
    }
    /* u1 = m * tmp mod order */
    if (!BN_mod_mul(u1, m, u2, order, ctx)) {
        ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
        goto err;
    }
    /* u2 = r * w mod q */
    if (!BN_mod_mul(u2, sig->r, u2, order, ctx)) {
        ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
        goto err;
    }

    if ((point = EC_POINT_new(group)) == NULL) {
        ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE);
        goto err;
    }
    if (!EC_POINT_mul(group, point, u1, pub_key, u2, ctx)) {
        ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
        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, point, X, NULL, ctx)) {
            ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
            goto err;
        }
    }
#ifndef OPENSSL_NO_EC2M
    else {                      /* NID_X9_62_characteristic_two_field */

        if (!EC_POINT_get_affine_coordinates_GF2m(group, point, X, NULL, ctx)) {
            ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
            goto err;
        }
    }
#endif
    if (!BN_nnmod(u1, X, order, ctx)) {
        ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
        goto err;
    }
    /*  if the signature is correct u1 is equal to sig->r */
    ret = (BN_ucmp(u1, sig->r) == 0);
 err:
    BN_CTX_end(ctx);
    BN_CTX_free(ctx);
    if (point)
        EC_POINT_free(point);
    return ret;
}
/*
 * Computes gost2001 signature as DSA_SIG structure 
 *
 *
 */ 
DSA_SIG *gost2001_do_sign(const unsigned char *dgst,int dlen, EC_KEY *eckey)
	{
	DSA_SIG *newsig = NULL;
	BIGNUM *md = hashsum2bn(dgst);
	BIGNUM *order = NULL;
	const EC_GROUP *group;
	const BIGNUM *priv_key;
	BIGNUM *r=NULL,*s=NULL,*X=NULL,*tmp=NULL,*tmp2=NULL, *k=NULL,*e=NULL;
	EC_POINT *C=NULL;
	BN_CTX *ctx = BN_CTX_new();	
	BN_CTX_start(ctx);
	OPENSSL_assert(dlen==32);
	newsig=DSA_SIG_new();
	if (!newsig) 
		{
		GOSTerr(GOST_F_GOST2001_DO_SIGN,GOST_R_NO_MEMORY);
		goto err;
		}	
	group = EC_KEY_get0_group(eckey);
	order=BN_CTX_get(ctx);
	EC_GROUP_get_order(group,order,ctx);
	priv_key = EC_KEY_get0_private_key(eckey);
	e = BN_CTX_get(ctx);
	BN_mod(e,md,order,ctx);
#ifdef DEBUG_SIGN
	fprintf(stderr,"digest as bignum=");
	BN_print_fp(stderr,md);
	fprintf(stderr,"\ndigest mod q=");
	BN_print_fp(stderr,e);
	fprintf(stderr,"\n");
#endif		
	if (BN_is_zero(e))
		{
		BN_one(e);
		}   
	k =BN_CTX_get(ctx);
	C=EC_POINT_new(group);
	do 
		{
		do 
			{
			if (!BN_rand_range(k,order)) 
				{
				GOSTerr(GOST_F_GOST2001_DO_SIGN,GOST_R_RANDOM_NUMBER_GENERATOR_FAILED);
				DSA_SIG_free(newsig);
				goto err;
				}	
			if (!EC_POINT_mul(group,C,k,NULL,NULL,ctx))
				{
				GOSTerr(GOST_F_GOST2001_DO_SIGN,ERR_R_EC_LIB);
				DSA_SIG_free(newsig);
				goto err;
				}	
			if (!X) X=BN_CTX_get(ctx);
			if (!EC_POINT_get_affine_coordinates_GFp(group,C,X,NULL,ctx))
				{
				GOSTerr(GOST_F_GOST2001_DO_SIGN,ERR_R_EC_LIB);
				DSA_SIG_free(newsig);
				goto err;
				}	
			if (!r) r=BN_CTX_get(ctx);
			BN_nnmod(r,X,order,ctx);
			}
		while (BN_is_zero(r));
		/* s =  (r*priv_key+k*e) mod order */
		if (!tmp) tmp = BN_CTX_get(ctx);
		BN_mod_mul(tmp,priv_key,r,order,ctx);
		if (!tmp2) tmp2 = BN_CTX_get(ctx);
		BN_mod_mul(tmp2,k,e,order,ctx);
		if (!s) s=BN_CTX_get(ctx);
		BN_mod_add(s,tmp,tmp2,order,ctx);
		}
	while (BN_is_zero(s));	

	newsig->s=BN_dup(s);
	newsig->r=BN_dup(r);
	err:			
	BN_CTX_end(ctx);
	BN_CTX_free(ctx);
	EC_POINT_free(C);
	BN_free(md);
	return newsig;
	}
Beispiel #26
0
static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
                            BIGNUM **rp)
{
    BN_CTX *ctx = NULL;
    BIGNUM *k = NULL, *r = NULL, *order = NULL, *X = NULL;
    EC_POINT *tmp_point = NULL;
    const EC_GROUP *group;
    int ret = 0;

    if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL) {
        ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_PASSED_NULL_PARAMETER);
        return 0;
    }

    if (ctx_in == NULL) {
        if ((ctx = BN_CTX_new()) == NULL) {
            ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE);
            return 0;
        }
    } else
        ctx = ctx_in;

    k = BN_new();               /* this value is later returned in *kinvp */
    r = BN_new();               /* this value is later returned in *rp */
    order = BN_new();
    X = BN_new();
    if (!k || !r || !order || !X) {
        ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE);
        goto err;
    }
    if ((tmp_point = EC_POINT_new(group)) == NULL) {
        ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB);
        goto err;
    }
    if (!EC_GROUP_get_order(group, order, ctx)) {
        ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB);
        goto err;
    }

    do {
        /* get random k */
        do
            if (!BN_rand_range(k, order)) {
                ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,
                         ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED);
                goto err;
            }
        while (BN_is_zero(k)) ;

        /*
         * We do not want timing information to leak the length of k, so we
         * compute G*k using an equivalent scalar of fixed bit-length.
         */

        if (!BN_add(k, k, order))
            goto err;
        if (BN_num_bits(k) <= BN_num_bits(order))
            if (!BN_add(k, k, order))
                goto err;

        /* compute r the x-coordinate of generator * k */
        if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx)) {
            ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB);
            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_point, X, NULL, ctx)) {
                ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB);
                goto err;
            }
        }
#ifndef OPENSSL_NO_EC2M
        else {                  /* NID_X9_62_characteristic_two_field */

            if (!EC_POINT_get_affine_coordinates_GF2m(group,
                                                      tmp_point, X, NULL,
                                                      ctx)) {
                ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB);
                goto err;
            }
        }
#endif
        if (!BN_nnmod(r, X, order, ctx)) {
            ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB);
            goto err;
        }
    }
    while (BN_is_zero(r));

    /* compute the inverse of k */
    if (EC_GROUP_get_mont_data(group) != NULL) {
        /*
         * We want inverse in constant time, therefore we utilize the fact
         * order must be prime and use Fermats Little Theorem instead.
         */
        if (!BN_set_word(X, 2)) {
            ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB);
            goto err;
        }
        if (!BN_mod_sub(X, order, X, order, ctx)) {
            ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB);
            goto err;
        }
        BN_set_flags(X, BN_FLG_CONSTTIME);
        if (!BN_mod_exp_mont_consttime
            (k, k, X, order, ctx, EC_GROUP_get_mont_data(group))) {
            ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB);
            goto err;
        }
    } else {
        if (!BN_mod_inverse(k, k, order, ctx)) {
            ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB);
            goto err;
        }
    }

    /* clear old values if necessary */
    if (*rp != NULL)
        BN_clear_free(*rp);
    if (*kinvp != NULL)
        BN_clear_free(*kinvp);
    /* save the pre-computed values  */
    *rp = r;
    *kinvp = k;
    ret = 1;
 err:
    if (!ret) {
        if (k != NULL)
            BN_clear_free(k);
        if (r != NULL)
            BN_clear_free(r);
    }
    if (ctx_in == NULL)
        BN_CTX_free(ctx);
    if (order != NULL)
        BN_free(order);
    if (tmp_point != NULL)
        EC_POINT_free(tmp_point);
    if (X)
        BN_clear_free(X);
    return (ret);
}
Beispiel #27
0
/*
 * Verifies gost ec signature
 *
 */
int gost_ec_verify(const unsigned char *dgst, int dgst_len,
                   DSA_SIG *sig, EC_KEY *ec)
{
    BN_CTX *ctx;
    const EC_GROUP *group = (ec) ? EC_KEY_get0_group(ec) : NULL;
    BIGNUM *order;
    BIGNUM *md = NULL, *e = NULL, *R = NULL, *v = NULL,
        *z1 = NULL, *z2 = NULL;
    BIGNUM *X = NULL, *tmp = NULL;
    EC_POINT *C = NULL;
    const EC_POINT *pub_key = NULL;
    int ok = 0;

    OPENSSL_assert(dgst != NULL && sig != NULL && group != NULL);

    if (!(ctx = BN_CTX_new())) {
        GOSTerr(GOST_F_GOST_EC_VERIFY, ERR_R_MALLOC_FAILURE);
        return 0;
    }

    BN_CTX_start(ctx);
    order = BN_CTX_get(ctx);
    e = BN_CTX_get(ctx);
    z1 = BN_CTX_get(ctx);
    z2 = BN_CTX_get(ctx);
    tmp = BN_CTX_get(ctx);
    X = BN_CTX_get(ctx);
    R = BN_CTX_get(ctx);
    v = BN_CTX_get(ctx);
    if (!order || !e || !z1 || !z2 || !tmp || !X || !R || !v) {
        GOSTerr(GOST_F_GOST_EC_VERIFY, ERR_R_MALLOC_FAILURE);
        goto err;
    }

    pub_key = EC_KEY_get0_public_key(ec);
    if (!pub_key || !EC_GROUP_get_order(group, order, ctx)) {
        GOSTerr(GOST_F_GOST_EC_VERIFY, ERR_R_INTERNAL_ERROR);
        goto err;
    }

    if (BN_is_zero(sig->s) || BN_is_zero(sig->r) ||
        (BN_cmp(sig->s, order) >= 1) || (BN_cmp(sig->r, order) >= 1)) {
        GOSTerr(GOST_F_GOST_EC_VERIFY, GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q);
        goto err;

    }

    OPENSSL_assert(dgst_len == 32 || dgst_len == 64);
    md = hashsum2bn(dgst, dgst_len);
    if (!md || !BN_mod(e, md, order, ctx)) {
        GOSTerr(GOST_F_GOST_EC_VERIFY, ERR_R_INTERNAL_ERROR);
        goto err;
    }
#ifdef DEBUG_SIGN
    fprintf(stderr, "digest as bignum: ");
    BN_print_fp(stderr, md);
    fprintf(stderr, "\ndigest mod q: ");
    BN_print_fp(stderr, e);
#endif
    if (BN_is_zero(e) && !BN_one(e)) {
        GOSTerr(GOST_F_GOST_EC_VERIFY, ERR_R_INTERNAL_ERROR);
        goto err;
    }
    v = BN_mod_inverse(v, e, order, ctx);
    if (!v || !BN_mod_mul(z1, sig->s, v, order, ctx)
        || !BN_sub(tmp, order, sig->r)
        || !BN_mod_mul(z2, tmp, v, order, ctx)) {
        GOSTerr(GOST_F_GOST_EC_VERIFY, ERR_R_INTERNAL_ERROR);
        goto err;
    }
#ifdef DEBUG_SIGN
    fprintf(stderr, "\nInverted digest value: ");
    BN_print_fp(stderr, v);
    fprintf(stderr, "\nz1: ");
    BN_print_fp(stderr, z1);
    fprintf(stderr, "\nz2: ");
    BN_print_fp(stderr, z2);
#endif
    C = EC_POINT_new(group);
    if (!C) {
        GOSTerr(GOST_F_GOST_EC_VERIFY, ERR_R_MALLOC_FAILURE);
        goto err;
    }
    if (!EC_POINT_mul(group, C, z1, pub_key, z2, ctx)) {
        GOSTerr(GOST_F_GOST_EC_VERIFY, ERR_R_EC_LIB);
        goto err;
    }
    if (!EC_POINT_get_affine_coordinates_GFp(group, C, X, NULL, ctx)) {
        GOSTerr(GOST_F_GOST_EC_VERIFY, ERR_R_EC_LIB);
        goto err;
    }
    if (!BN_mod(R, X, order, ctx)) {
        GOSTerr(GOST_F_GOST_EC_VERIFY, ERR_R_INTERNAL_ERROR);
        goto err;
    }
#ifdef DEBUG_SIGN
    fprintf(stderr, "\nX=");
    BN_print_fp(stderr, X);
    fprintf(stderr, "\nX mod q=");
    BN_print_fp(stderr, R);
    fprintf(stderr, "\n");
#endif
    if (BN_cmp(R, sig->r) != 0) {
        GOSTerr(GOST_F_GOST_EC_VERIFY, GOST_R_SIGNATURE_MISMATCH);
    } else {
        ok = 1;
    }
 err:
    if (C)
        EC_POINT_free(C);
    BN_CTX_end(ctx);
    BN_CTX_free(ctx);
    if (md)
        BN_free(md);
    return ok;
}
Beispiel #28
0
void *
vg_thread_loop(void *arg)
{
	unsigned char hash_buf[128];
	unsigned char *eckey_buf;
	unsigned char hash1[32];

	int i, c, len, output_interval;
	int hash_len;

	const BN_ULONG rekey_max = 10000000;
	BN_ULONG npoints, rekey_at, nbatch;

	vg_context_t *vcp = (vg_context_t *) arg;
	EC_KEY *pkey = NULL;
	const EC_GROUP *pgroup;
	const EC_POINT *pgen;
	const int ptarraysize = 256;
	EC_POINT *ppnt[ptarraysize];
	EC_POINT *pbatchinc;

	vg_test_func_t test_func = vcp->vc_test;
	vg_exec_context_t ctx;
	vg_exec_context_t *vxcp;

	struct timeval tvstart;


	memset(&ctx, 0, sizeof(ctx));
	vxcp = &ctx;

	vg_exec_context_init(vcp, &ctx);

	pkey = vxcp->vxc_key;
	pgroup = EC_KEY_get0_group(pkey);
	pgen = EC_GROUP_get0_generator(pgroup);

	for (i = 0; i < ptarraysize; i++) {
		ppnt[i] = EC_POINT_new(pgroup);
		if (!ppnt[i]) {
			fprintf(stderr, "ERROR: out of memory?\n");
			exit(1);
		}
	}
	pbatchinc = EC_POINT_new(pgroup);
	if (!pbatchinc) {
		fprintf(stderr, "ERROR: out of memory?\n");
		exit(1);
	}

	BN_set_word(&vxcp->vxc_bntmp, ptarraysize);
	EC_POINT_mul(pgroup, pbatchinc, &vxcp->vxc_bntmp, NULL, NULL,
		     vxcp->vxc_bnctx);
	EC_POINT_make_affine(pgroup, pbatchinc, vxcp->vxc_bnctx);

	npoints = 0;
	rekey_at = 0;
	nbatch = 0;
	vxcp->vxc_key = pkey;
	vxcp->vxc_binres[0] = vcp->vc_addrtype;
	c = 0;
	output_interval = 1000;
	gettimeofday(&tvstart, NULL);

	if (vcp->vc_format == VCF_SCRIPT) {
		hash_buf[ 0] = 0x51;  // OP_1
		hash_buf[ 1] = 0x41;  // pubkey length
		// gap for pubkey
		hash_buf[67] = 0x51;  // OP_1
		hash_buf[68] = 0xae;  // OP_CHECKMULTISIG
		eckey_buf = hash_buf + 2;
		hash_len = 69;

	} else {
		eckey_buf = hash_buf;
		hash_len = (vcp->vc_compressed)?33:65;
	}

	while (!vcp->vc_halt) {
		if (++npoints >= rekey_at) {
			vg_exec_context_upgrade_lock(vxcp);
			/* Generate a new random private key */
			EC_KEY_generate_key(pkey);
			npoints = 0;

			/* Determine rekey interval */
			EC_GROUP_get_order(pgroup, &vxcp->vxc_bntmp,
					   vxcp->vxc_bnctx);
			BN_sub(&vxcp->vxc_bntmp2,
			       &vxcp->vxc_bntmp,
			       EC_KEY_get0_private_key(pkey));
			rekey_at = BN_get_word(&vxcp->vxc_bntmp2);
			if ((rekey_at == BN_MASK2) || (rekey_at > rekey_max))
				rekey_at = rekey_max;
			assert(rekey_at > 0);

			EC_POINT_copy(ppnt[0], EC_KEY_get0_public_key(pkey));
			vg_exec_context_downgrade_lock(vxcp);

			npoints++;
			vxcp->vxc_delta = 0;

			if (vcp->vc_pubkey_base)
				EC_POINT_add(pgroup,
					     ppnt[0],
					     ppnt[0],
					     vcp->vc_pubkey_base,
					     vxcp->vxc_bnctx);

			for (nbatch = 1;
			     (nbatch < ptarraysize) && (npoints < rekey_at);
			     nbatch++, npoints++) {
				EC_POINT_add(pgroup,
					     ppnt[nbatch],
					     ppnt[nbatch-1],
					     pgen, vxcp->vxc_bnctx);
			}

		} else {
			/*
			 * Common case
			 *
			 * EC_POINT_add() can skip a few multiplies if
			 * one or both inputs are affine (Z_is_one).
			 * This is the case for every point in ppnt, as
			 * well as pbatchinc.
			 */
			assert(nbatch == ptarraysize);
			for (nbatch = 0;
			     (nbatch < ptarraysize) && (npoints < rekey_at);
			     nbatch++, npoints++) {
				EC_POINT_add(pgroup,
					     ppnt[nbatch],
					     ppnt[nbatch],
					     pbatchinc,
					     vxcp->vxc_bnctx);
			}
		}

		/*
		 * The single most expensive operation performed in this
		 * loop is modular inversion of ppnt->Z.  There is an
		 * algorithm implemented in OpenSSL to do batched inversion
		 * that only does one actual BN_mod_inverse(), and saves
		 * a _lot_ of time.
		 *
		 * To take advantage of this, we batch up a few points,
		 * and feed them to EC_POINTs_make_affine() below.
		 */

		EC_POINTs_make_affine(pgroup, nbatch, ppnt, vxcp->vxc_bnctx);

		for (i = 0; i < nbatch; i++, vxcp->vxc_delta++) {
			/* Hash the public key */
			len = EC_POINT_point2oct(pgroup, ppnt[i],
						 (vcp->vc_compressed)?POINT_CONVERSION_COMPRESSED:POINT_CONVERSION_UNCOMPRESSED,
						 eckey_buf,
						 (vcp->vc_compressed)?33:65,
						 vxcp->vxc_bnctx);
			assert(len == (vcp->vc_compressed)?33:65);

			SHA256(hash_buf, hash_len, hash1);
			RIPEMD160(hash1, sizeof(hash1), &vxcp->vxc_binres[1]);

			switch (test_func(vxcp)) {
			case 1:
				npoints = 0;
				rekey_at = 0;
				i = nbatch;
				break;
			case 2:
				goto out;
			default:
				break;
			}
		}

		c += i;
		if (c >= output_interval) {
			output_interval = vg_output_timing(vcp, c, &tvstart);
			if (output_interval > 250000)
				output_interval = 250000;
			c = 0;
		}

		vg_exec_context_yield(vxcp);
	}

out:
	vg_exec_context_del(&ctx);
	vg_context_thread_exit(vcp);

	for (i = 0; i < ptarraysize; i++)
		if (ppnt[i])
			EC_POINT_free(ppnt[i]);
	if (pbatchinc)
		EC_POINT_free(pbatchinc);
	return NULL;
}
Beispiel #29
0
std::vector<unsigned char> decrypt_bip38_ec(const std::vector<unsigned char> key,  const std::string& passwd)
{
    int i;
    uint8_t passfactor[PASSFACTOR_SIZE];

    memset(passfactor,0,PASSFACTOR_SIZE);

    const unsigned char * s_key = reinterpret_cast<const unsigned char*>(key.data());

    crypto_scrypt((const uint8_t *)passwd.c_str(), passwd.length(),
                   &s_key[3 + ADDRESSHASH_SIZE], OWNERSALT_SIZE,
                   16384, 8, 8, passfactor, PASSFACTOR_SIZE );

    // compute EC point (passpoint) using passfactor
    struct bp_key ec_point;
    if(!bp_key_init(&ec_point)) {
        fprintf(stderr,"%s","cannot init EC point key");
        exit(3);
    }
    if(!bp_key_secret_set(&ec_point,passfactor,PASSFACTOR_SIZE)) {
        fprintf(stderr,"%s","cannot set EC point from passfactor");
        exit(3);
    }

    // get the passpoint as bytes
    unsigned char * passpoint;
    size_t passpoint_len;

    if(!bp_pubkey_get(&ec_point,(unsigned char **)&passpoint,&passpoint_len)) {
        fprintf(stderr,"%s","cannot get pubkey for EC point");
        exit(4);
    }

    // now we need to decrypt seedb
    uint8_t encryptedpart2[16];
    memset(encryptedpart2,0,16);
    memcpy(encryptedpart2, &s_key[3 + ADDRESSHASH_SIZE + OWNERSALT_SIZE + 8], 16);

    uint8_t encryptedpart1[16];
    memset(encryptedpart1,0,16);
    memcpy(encryptedpart1, &s_key[3 + ADDRESSHASH_SIZE + OWNERSALT_SIZE], 8);

    unsigned char derived[DERIVED_SIZE];
    // get the encryption key for seedb using scrypt
    // with passpoint as the key, salt is addresshash+ownersalt
    unsigned char derived_scrypt_salt[ADDRESSHASH_SIZE + OWNERSALT_SIZE];
    memcpy(derived_scrypt_salt, &s_key[3], ADDRESSHASH_SIZE); // copy the addresshash
    memcpy(derived_scrypt_salt+ADDRESSHASH_SIZE, &s_key[3+ADDRESSHASH_SIZE], OWNERSALT_SIZE); // copy the ownersalt
    crypto_scrypt( passpoint, passpoint_len,
                   derived_scrypt_salt, ADDRESSHASH_SIZE+OWNERSALT_SIZE,
                   1024, 1, 1, derived, DERIVED_SIZE );

    //get decryption key
    unsigned char derivedhalf2[DERIVED_SIZE/2];
    memcpy(derivedhalf2, derived+(DERIVED_SIZE/2), DERIVED_SIZE/2);

    unsigned char iv[32];
    memset(iv,0,32);

    EVP_CIPHER_CTX d;
    EVP_CIPHER_CTX_init(&d);
    EVP_DecryptInit_ex(&d, EVP_aes_256_ecb(), NULL, derivedhalf2, iv);

    unsigned char unencryptedpart2[32];
    int decrypt_len;

    EVP_DecryptUpdate(&d, unencryptedpart2, &decrypt_len, encryptedpart2, 16);
    EVP_DecryptUpdate(&d, unencryptedpart2, &decrypt_len, encryptedpart2, 16);
    for(i=0; i<16; i++) {
        unencryptedpart2[i] ^= derived[i + 16];
    }
    unsigned char unencryptedpart1[32];
    memcpy(encryptedpart1+8, unencryptedpart2, 8);
    EVP_DecryptUpdate(&d, unencryptedpart1, &decrypt_len, encryptedpart1, 16);
    EVP_DecryptUpdate(&d, unencryptedpart1, &decrypt_len, encryptedpart1, 16);
    for(i=0; i<16; i++) {
        unencryptedpart1[i] ^= derived[i];
    }

    // recoved seedb
    unsigned char seedb[24];
    memcpy(seedb, unencryptedpart1, 16);
    memcpy(&(seedb[16]), &(unencryptedpart2[8]), 8);

    // turn seedb into factorb (factorb = SHA256(SHA256(seedb)))
    unsigned char factorb[32];
    bu_Hash(factorb, seedb, 24);

    // multiply by passfactor (ec_point_pub)
    const EC_GROUP * ec_group = EC_KEY_get0_group(ec_point.k);
    const EC_POINT * ec_point_pub = EC_KEY_get0_public_key(ec_point.k);
    BIGNUM * bn_passfactor = BN_bin2bn(passfactor,32,BN_new());
    BIGNUM * bn_factorb = BN_bin2bn(factorb,32,BN_new());
    BIGNUM * bn_res = BN_new();
    BIGNUM * bn_final = BN_new();
    BIGNUM * bn_n = BN_new();
    BN_CTX * ctx = BN_CTX_new();
    EC_GROUP_get_order(ec_group, bn_n, ctx);
    BN_mul(bn_res, bn_passfactor, bn_factorb, ctx);
    BN_mod(bn_final, bn_res, bn_n, ctx);

    unsigned char finalKey[32];
    memset(finalKey, 0, 32);
    int n = BN_bn2bin(bn_final, finalKey);

    BN_clear_free(bn_passfactor);
    BN_clear_free(bn_factorb);
    BN_clear_free(bn_res);
    BN_clear_free(bn_n);
    BN_clear_free(bn_final);

    printf("\n");
    print_hex((char *)finalKey, 32);
    printf("\n");

    std::vector<unsigned char> out;
    out.assign(finalKey, finalKey + 32);

    return out;
}
Beispiel #30
0
static EC_KEY *extract_ec_priv_key(CPK_MASTER_SECRET *master, const char *id)
{
	int e = 1;
	EC_KEY *ec_key = NULL;
	const EC_GROUP *ec_group;
	EC_POINT *pub_key = NULL;
	BIGNUM *priv_key = BN_new();
	BIGNUM *order = BN_new();
	BIGNUM *bn = BN_new();
	BN_CTX *ctx = BN_CTX_new();
	int *index = NULL;
	int i, num_indexes, bn_size;

	
	if (!priv_key || !bn || !order || !ctx) {
		goto err;
	}
	
	if (!(ec_key = X509_ALGOR_get1_EC_KEY(master->pkey_algor))) {
		goto err;
	}
	ec_group = EC_KEY_get0_group(ec_key);
	if (!(pub_key = EC_POINT_new(ec_group))) {
		goto err;
	}

	if ((num_indexes = CPK_MAP_num_indexes(master->map_algor)) <= 0) {
		goto err;
	}
	if (!(index = OPENSSL_malloc(sizeof(int) * num_indexes))) {
		goto err;
	}		
	if (!CPK_MAP_str2index(master->map_algor, id, index)) {
		goto err;
	}
	
	BN_zero(priv_key);
	if (!(EC_GROUP_get_order(EC_KEY_get0_group(ec_key), order, ctx))) {
		goto err;
	}
	bn_size = BN_num_bytes(order);
	
	for (i = 0; i < num_indexes; i++) {
		const unsigned char *p = 
			M_ASN1_STRING_data(master->secret_factors) + 
			bn_size * index[i];
		
		if (!BN_bin2bn(p, bn_size, bn)) {
			goto err;
		}
		if (BN_is_zero(bn) || BN_cmp(bn, order) >= 0) {
			goto err;
		}		
		if (!BN_mod_add(priv_key, priv_key, bn, order, ctx)) {
			goto err;
		}
	}
	if (!EC_KEY_set_private_key(ec_key, priv_key)) {
		goto err;
	}

	if (!EC_POINT_mul(ec_group, pub_key, priv_key, NULL, NULL, ctx)) {
		goto err;
	}
	if (!EC_KEY_set_public_key(ec_key, pub_key)) {
		goto err;
	}
	e = 0;
	
err:
	if (e && ec_key) {
		EC_KEY_free(ec_key);
		ec_key = NULL;
	}
	if (priv_key) BN_free(priv_key);
	if (pub_key) EC_POINT_free(pub_key);
	if (order) BN_free(order);
	if (bn) BN_free(bn);
	if (ctx) BN_CTX_free(ctx);
	if (index) OPENSSL_free(index);
	return ec_key;
}