Ejemplo n.º 1
0
static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp)
	{
	BN_CTX *ctx;
	BIGNUM k,kq,*K,*kinv=NULL,*r=NULL;
	int ret=0;

	if (!dsa->p || !dsa->q || !dsa->g)
		{
		DSAerr(DSA_F_DSA_SIGN_SETUP,DSA_R_MISSING_PARAMETERS);
		return 0;
		}

	BN_init(&k);
	BN_init(&kq);

	if (ctx_in == NULL)
		{
		if ((ctx=BN_CTX_new()) == NULL) goto err;
		}
	else
		ctx=ctx_in;

	if ((r=BN_new()) == NULL) goto err;

	/* Get random k */
	do
		if (!BN_rand_range(&k, dsa->q)) goto err;
	while (BN_is_zero(&k));
	if ((dsa->flags & DSA_FLAG_NO_EXP_CONSTTIME) == 0)
		{
		BN_set_flags(&k, BN_FLG_CONSTTIME);
		}

	if (dsa->flags & DSA_FLAG_CACHE_MONT_P)
		{
		if (!BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p,
						CRYPTO_LOCK_DSA,
						dsa->p, ctx))
			goto err;
		}

	/* Compute r = (g^k mod p) mod q */

	if ((dsa->flags & DSA_FLAG_NO_EXP_CONSTTIME) == 0)
		{
		if (!BN_copy(&kq, &k)) goto err;

		/* We do not want timing information to leak the length of k,
		 * so we compute g^k using an equivalent exponent of fixed length.
		 *
		 * (This is a kludge that we need because the BN_mod_exp_mont()
		 * does not let us specify the desired timing behaviour.) */

		if (!BN_add(&kq, &kq, dsa->q)) goto err;
		if (BN_num_bits(&kq) <= BN_num_bits(dsa->q))
			{
			if (!BN_add(&kq, &kq, dsa->q)) goto err;
			}

		K = &kq;
		}
	else
		{
		K = &k;
		}
	if (!dsa->meth->bn_mod_exp(dsa, r,dsa->g,K,dsa->p,ctx,
		(BN_MONT_CTX *)dsa->method_mont_p)) goto err;
	if (!BN_mod(r,r,dsa->q,ctx)) goto err;

	/* Compute  part of 's = inv(k) (m + xr) mod q' */
	if ((kinv=BN_mod_inverse(NULL,&k,dsa->q,ctx)) == NULL) goto err;

	if (*kinvp != NULL) BN_clear_free(*kinvp);
	*kinvp=kinv;
	kinv=NULL;
	if (*rp != NULL) BN_clear_free(*rp);
	*rp=r;
	ret=1;
err:
	if (!ret)
		{
		DSAerr(DSA_F_DSA_SIGN_SETUP,ERR_R_BN_LIB);
		if (kinv != NULL) BN_clear_free(kinv);
		if (r != NULL) BN_clear_free(r);
		}
	if (ctx_in == NULL) BN_CTX_free(ctx);
	if (kinv != NULL) BN_clear_free(kinv);
	BN_clear_free(&k);
	BN_clear_free(&kq);
	return(ret);
	}
Ejemplo n.º 2
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);
	EC_POINT_free(point);
	return ret;
}
Ejemplo n.º 3
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 nonzero, 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;
}
Ejemplo n.º 4
0
int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe,
	const BIGNUM *add, const BIGNUM *rem, BN_GENCB *cb)
	{
	BIGNUM *t;
	int found=0;
	int i,j,c1=0;
	BN_CTX *ctx;
	int checks = BN_prime_checks_for_size(bits);

	ctx=BN_CTX_new();
	if (ctx == NULL) goto err;
	BN_CTX_start(ctx);
	t = BN_CTX_get(ctx);
	if(!t) goto err;
loop: 
	/* make a random number and set the top and bottom bits */
	if (add == NULL)
		{
		if (!probable_prime(ret,bits)) goto err;
		}
	else
		{
		if (safe)
			{
			if (!probable_prime_dh_safe(ret,bits,add,rem,ctx))
				 goto err;
			}
		else
			{
			if (!probable_prime_dh(ret,bits,add,rem,ctx))
				goto err;
			}
		}
	/* if (BN_mod_word(ret,(BN_ULONG)3) == 1) goto loop; */
	if(!BN_GENCB_call(cb, 0, c1++))
		/* aborted */
		goto err;

	if (!safe)
		{
		i=BN_is_prime_fasttest_ex(ret,checks,ctx,0,cb);
		if (i == -1) goto err;
		if (i == 0) goto loop;
		}
	else
		{
		/* for "safe prime" generation,
		 * check that (p-1)/2 is prime.
		 * Since a prime is odd, We just
		 * need to divide by 2 */
		if (!BN_rshift1(t,ret)) goto err;

		for (i=0; i<checks; i++)
			{
			j=BN_is_prime_fasttest_ex(ret,1,ctx,0,cb);
			if (j == -1) goto err;
			if (j == 0) goto loop;

			j=BN_is_prime_fasttest_ex(t,1,ctx,0,cb);
			if (j == -1) goto err;
			if (j == 0) goto loop;

			if(!BN_GENCB_call(cb, 2, c1-1))
				goto err;
			/* We have a safe prime test pass */
			}
		}
	/* we have a prime :-) */
	found = 1;
err:
	if (ctx != NULL)
		{
		BN_CTX_end(ctx);
		BN_CTX_free(ctx);
		}
	bn_check_top(ret);
	return found;
	}
Ejemplo n.º 5
0
/* Computes a + b and stores the result in r.  r could be a or b, a could be b.
 * Uses algorithm A.10.2 of IEEE P1363.
 */
int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
	{
	BN_CTX *new_ctx = NULL;
	BIGNUM *x0, *y0, *x1, *y1, *x2, *y2, *s, *t;
	int ret = 0;
	
	if (EC_POINT_is_at_infinity(group, a))
		{
		if (!EC_POINT_copy(r, b)) return 0;
		return 1;
		}

	if (EC_POINT_is_at_infinity(group, b))
		{
		if (!EC_POINT_copy(r, a)) return 0;
		return 1;
		}

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

	BN_CTX_start(ctx);
	x0 = BN_CTX_get(ctx);
	y0 = BN_CTX_get(ctx);
	x1 = BN_CTX_get(ctx);
	y1 = BN_CTX_get(ctx);
	x2 = BN_CTX_get(ctx);
	y2 = BN_CTX_get(ctx);
	s = BN_CTX_get(ctx);
	t = BN_CTX_get(ctx);
	if (t == NULL) goto err;

	if (a->Z_is_one) 
		{
		if (!BN_copy(x0, &a->X)) goto err;
		if (!BN_copy(y0, &a->Y)) goto err;
		}
	else
		{
		if (!EC_POINT_get_affine_coordinates_GF2m(group, a, x0, y0, ctx)) goto err;
		}
	if (b->Z_is_one) 
		{
		if (!BN_copy(x1, &b->X)) goto err;
		if (!BN_copy(y1, &b->Y)) goto err;
		}
	else
		{
		if (!EC_POINT_get_affine_coordinates_GF2m(group, b, x1, y1, ctx)) goto err;
		}


	if (BN_GF2m_cmp(x0, x1))
		{
		if (!BN_GF2m_add(t, x0, x1)) goto err;
		if (!BN_GF2m_add(s, y0, y1)) goto err;
		if (!group->meth->field_div(group, s, s, t, ctx)) goto err;
		if (!group->meth->field_sqr(group, x2, s, ctx)) goto err;
		if (!BN_GF2m_add(x2, x2, &group->a)) goto err;
		if (!BN_GF2m_add(x2, x2, s)) goto err;
		if (!BN_GF2m_add(x2, x2, t)) goto err;
		}
	else
		{
		if (BN_GF2m_cmp(y0, y1) || BN_is_zero(x1))
			{
			if (!EC_POINT_set_to_infinity(group, r)) goto err;
			ret = 1;
			goto err;
			}
		if (!group->meth->field_div(group, s, y1, x1, ctx)) goto err;
		if (!BN_GF2m_add(s, s, x1)) goto err;
		
		if (!group->meth->field_sqr(group, x2, s, ctx)) goto err;
		if (!BN_GF2m_add(x2, x2, s)) goto err;
		if (!BN_GF2m_add(x2, x2, &group->a)) goto err;
		}

	if (!BN_GF2m_add(y2, x1, x2)) goto err;
	if (!group->meth->field_mul(group, y2, y2, s, ctx)) goto err;
	if (!BN_GF2m_add(y2, y2, x2)) goto err;
	if (!BN_GF2m_add(y2, y2, y1)) goto err;

	if (!EC_POINT_set_affine_coordinates_GF2m(group, r, x2, y2, ctx)) goto err;

	ret = 1;

 err:
	BN_CTX_end(ctx);
	if (new_ctx != NULL)
		BN_CTX_free(new_ctx);
	return ret;
	}
Ejemplo n.º 6
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 = OPENSSL_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);
    if (buffer != NULL)
        OPENSSL_free(buffer);
    return (ret);
}
Ejemplo n.º 7
0
int RSA_check_key_ex(const RSA *key, BN_GENCB *cb)
{
    BIGNUM *i, *j, *k, *l, *m;
    BN_CTX *ctx;
    int ret = 1, ex_primes = 0, idx;
    RSA_PRIME_INFO *pinfo;

    if (key->p == NULL || key->q == NULL || key->n == NULL
            || key->e == NULL || key->d == NULL) {
        RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_VALUE_MISSING);
        return 0;
    }

    /* multi-prime? */
    if (key->version == RSA_ASN1_VERSION_MULTI) {
        ex_primes = sk_RSA_PRIME_INFO_num(key->prime_infos);
        if (ex_primes <= 0
                || (ex_primes + 2) > rsa_multip_cap(BN_num_bits(key->n))) {
            RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_INVALID_MULTI_PRIME_KEY);
            return 0;
        }
    }

    i = BN_new();
    j = BN_new();
    k = BN_new();
    l = BN_new();
    m = BN_new();
    ctx = BN_CTX_new();
    if (i == NULL || j == NULL || k == NULL || l == NULL
            || m == NULL || ctx == NULL) {
        ret = -1;
        RSAerr(RSA_F_RSA_CHECK_KEY_EX, ERR_R_MALLOC_FAILURE);
        goto err;
    }

    if (BN_is_one(key->e)) {
        ret = 0;
        RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_BAD_E_VALUE);
    }
    if (!BN_is_odd(key->e)) {
        ret = 0;
        RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_BAD_E_VALUE);
    }

    /* p prime? */
    if (BN_is_prime_ex(key->p, BN_prime_checks, NULL, cb) != 1) {
        ret = 0;
        RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_P_NOT_PRIME);
    }

    /* q prime? */
    if (BN_is_prime_ex(key->q, BN_prime_checks, NULL, cb) != 1) {
        ret = 0;
        RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_Q_NOT_PRIME);
    }

    /* r_i prime? */
    for (idx = 0; idx < ex_primes; idx++) {
        pinfo = sk_RSA_PRIME_INFO_value(key->prime_infos, idx);
        if (BN_is_prime_ex(pinfo->r, BN_prime_checks, NULL, cb) != 1) {
            ret = 0;
            RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_MP_R_NOT_PRIME);
        }
    }

    /* n = p*q * r_3...r_i? */
    if (!BN_mul(i, key->p, key->q, ctx)) {
        ret = -1;
        goto err;
    }
    for (idx = 0; idx < ex_primes; idx++) {
        pinfo = sk_RSA_PRIME_INFO_value(key->prime_infos, idx);
        if (!BN_mul(i, i, pinfo->r, ctx)) {
            ret = -1;
            goto err;
        }
    }
    if (BN_cmp(i, key->n) != 0) {
        ret = 0;
        if (ex_primes)
            RSAerr(RSA_F_RSA_CHECK_KEY_EX,
                   RSA_R_N_DOES_NOT_EQUAL_PRODUCT_OF_PRIMES);
        else
            RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_N_DOES_NOT_EQUAL_P_Q);
    }

    /* d*e = 1  mod \lambda(n)? */
    if (!BN_sub(i, key->p, BN_value_one())) {
        ret = -1;
        goto err;
    }
    if (!BN_sub(j, key->q, BN_value_one())) {
        ret = -1;
        goto err;
    }

    /* now compute k = \lambda(n) = LCM(i, j, r_3 - 1...) */
    if (!BN_mul(l, i, j, ctx)) {
        ret = -1;
        goto err;
    }
    if (!BN_gcd(m, i, j, ctx)) {
        ret = -1;
        goto err;
    }
    for (idx = 0; idx < ex_primes; idx++) {
        pinfo = sk_RSA_PRIME_INFO_value(key->prime_infos, idx);
        if (!BN_sub(k, pinfo->r, BN_value_one())) {
            ret = -1;
            goto err;
        }
        if (!BN_mul(l, l, k, ctx)) {
            ret = -1;
            goto err;
        }
        if (!BN_gcd(m, m, k, ctx)) {
            ret = -1;
            goto err;
        }
    }
    if (!BN_div(k, NULL, l, m, ctx)) { /* remainder is 0 */
        ret = -1;
        goto err;
    }
    if (!BN_mod_mul(i, key->d, key->e, k, ctx)) {
        ret = -1;
        goto err;
    }

    if (!BN_is_one(i)) {
        ret = 0;
        RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_D_E_NOT_CONGRUENT_TO_1);
    }

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

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

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

    for (idx = 0; idx < ex_primes; idx++) {
        pinfo = sk_RSA_PRIME_INFO_value(key->prime_infos, idx);
        /* d_i = d mod (r_i - 1)? */
        if (!BN_sub(i, pinfo->r, BN_value_one())) {
            ret = -1;
            goto err;
        }
        if (!BN_mod(j, key->d, i, ctx)) {
            ret = -1;
            goto err;
        }
        if (BN_cmp(j, pinfo->d) != 0) {
            ret = 0;
            RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_MP_EXPONENT_NOT_CONGRUENT_TO_D);
        }
        /* t_i = R_i ^ -1 mod r_i ? */
        if (!BN_mod_inverse(i, pinfo->pp, pinfo->r, ctx)) {
            ret = -1;
            goto err;
        }
        if (BN_cmp(i, pinfo->t) != 0) {
            ret = 0;
            RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_MP_COEFFICIENT_NOT_INVERSE_OF_R);
        }
    }

 err:
    BN_free(i);
    BN_free(j);
    BN_free(k);
    BN_free(l);
    BN_free(m);
    BN_CTX_free(ctx);
    return ret;
}
Ejemplo n.º 8
0
int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
                      const EC_POINT *b, BN_CTX *ctx) {
  int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *,
                   BN_CTX *);
  int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
  const BIGNUM *p;
  BN_CTX *new_ctx = NULL;
  BIGNUM *n0, *n1, *n2, *n3, *n4, *n5, *n6;
  int ret = 0;

  if (a == b) {
    return EC_POINT_dbl(group, r, a, ctx);
  }
  if (EC_POINT_is_at_infinity(group, a)) {
    return EC_POINT_copy(r, b);
  }
  if (EC_POINT_is_at_infinity(group, b)) {
    return EC_POINT_copy(r, a);
  }

  field_mul = group->meth->field_mul;
  field_sqr = group->meth->field_sqr;
  p = &group->field;

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

  BN_CTX_start(ctx);
  n0 = BN_CTX_get(ctx);
  n1 = BN_CTX_get(ctx);
  n2 = BN_CTX_get(ctx);
  n3 = BN_CTX_get(ctx);
  n4 = BN_CTX_get(ctx);
  n5 = BN_CTX_get(ctx);
  n6 = BN_CTX_get(ctx);
  if (n6 == NULL) {
    goto end;
  }

  /* Note that in this function we must not read components of 'a' or 'b'
   * once we have written the corresponding components of 'r'.
   * ('r' might be one of 'a' or 'b'.)
   */

  /* n1, n2 */
  int b_Z_is_one = BN_cmp(&b->Z, &group->one) == 0;

  if (b_Z_is_one) {
    if (!BN_copy(n1, &a->X) || !BN_copy(n2, &a->Y)) {
      goto end;
    }
    /* n1 = X_a */
    /* n2 = Y_a */
  } else {
    if (!field_sqr(group, n0, &b->Z, ctx) ||
        !field_mul(group, n1, &a->X, n0, ctx)) {
      goto end;
    }
    /* n1 = X_a * Z_b^2 */

    if (!field_mul(group, n0, n0, &b->Z, ctx) ||
        !field_mul(group, n2, &a->Y, n0, ctx)) {
      goto end;
    }
    /* n2 = Y_a * Z_b^3 */
  }

  /* n3, n4 */
  int a_Z_is_one = BN_cmp(&a->Z, &group->one) == 0;
  if (a_Z_is_one) {
    if (!BN_copy(n3, &b->X) || !BN_copy(n4, &b->Y)) {
      goto end;
    }
    /* n3 = X_b */
    /* n4 = Y_b */
  } else {
    if (!field_sqr(group, n0, &a->Z, ctx) ||
        !field_mul(group, n3, &b->X, n0, ctx)) {
      goto end;
    }
    /* n3 = X_b * Z_a^2 */

    if (!field_mul(group, n0, n0, &a->Z, ctx) ||
        !field_mul(group, n4, &b->Y, n0, ctx)) {
      goto end;
    }
    /* n4 = Y_b * Z_a^3 */
  }

  /* n5, n6 */
  if (!BN_mod_sub_quick(n5, n1, n3, p) ||
      !BN_mod_sub_quick(n6, n2, n4, p)) {
    goto end;
  }
  /* n5 = n1 - n3 */
  /* n6 = n2 - n4 */

  if (BN_is_zero(n5)) {
    if (BN_is_zero(n6)) {
      /* a is the same point as b */
      BN_CTX_end(ctx);
      ret = EC_POINT_dbl(group, r, a, ctx);
      ctx = NULL;
      goto end;
    } else {
      /* a is the inverse of b */
      BN_zero(&r->Z);
      ret = 1;
      goto end;
    }
  }

  /* 'n7', 'n8' */
  if (!BN_mod_add_quick(n1, n1, n3, p) ||
      !BN_mod_add_quick(n2, n2, n4, p)) {
    goto end;
  }
  /* 'n7' = n1 + n3 */
  /* 'n8' = n2 + n4 */

  /* Z_r */
  if (a_Z_is_one && b_Z_is_one) {
    if (!BN_copy(&r->Z, n5)) {
      goto end;
    }
  } else {
    if (a_Z_is_one) {
      if (!BN_copy(n0, &b->Z)) {
        goto end;
      }
    } else if (b_Z_is_one) {
      if (!BN_copy(n0, &a->Z)) {
        goto end;
      }
    } else if (!field_mul(group, n0, &a->Z, &b->Z, ctx)) {
      goto end;
    }
    if (!field_mul(group, &r->Z, n0, n5, ctx)) {
      goto end;
    }
  }

  /* Z_r = Z_a * Z_b * n5 */

  /* X_r */
  if (!field_sqr(group, n0, n6, ctx) ||
      !field_sqr(group, n4, n5, ctx) ||
      !field_mul(group, n3, n1, n4, ctx) ||
      !BN_mod_sub_quick(&r->X, n0, n3, p)) {
    goto end;
  }
  /* X_r = n6^2 - n5^2 * 'n7' */

  /* 'n9' */
  if (!BN_mod_lshift1_quick(n0, &r->X, p) ||
      !BN_mod_sub_quick(n0, n3, n0, p)) {
    goto end;
  }
  /* n9 = n5^2 * 'n7' - 2 * X_r */

  /* Y_r */
  if (!field_mul(group, n0, n0, n6, ctx) ||
      !field_mul(group, n5, n4, n5, ctx)) {
    goto end; /* now n5 is n5^3 */
  }
  if (!field_mul(group, n1, n2, n5, ctx) ||
      !BN_mod_sub_quick(n0, n0, n1, p)) {
    goto end;
  }
  if (BN_is_odd(n0) && !BN_add(n0, n0, p)) {
    goto end;
  }
  /* now  0 <= n0 < 2*p,  and n0 is even */
  if (!BN_rshift1(&r->Y, n0)) {
    goto end;
  }
  /* Y_r = (n6 * 'n9' - 'n8' * 'n5^3') / 2 */

  ret = 1;

end:
  if (ctx) {
    /* otherwise we already called BN_CTX_end */
    BN_CTX_end(ctx);
  }
  BN_CTX_free(new_ctx);
  return ret;
}
Ejemplo n.º 9
0
int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
                      BN_CTX *ctx) {
  int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *,
                   BN_CTX *);
  int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
  const BIGNUM *p;
  BN_CTX *new_ctx = NULL;
  BIGNUM *n0, *n1, *n2, *n3;
  int ret = 0;

  if (EC_POINT_is_at_infinity(group, a)) {
    BN_zero(&r->Z);
    return 1;
  }

  field_mul = group->meth->field_mul;
  field_sqr = group->meth->field_sqr;
  p = &group->field;

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

  BN_CTX_start(ctx);
  n0 = BN_CTX_get(ctx);
  n1 = BN_CTX_get(ctx);
  n2 = BN_CTX_get(ctx);
  n3 = BN_CTX_get(ctx);
  if (n3 == NULL) {
    goto err;
  }

  /* Note that in this function we must not read components of 'a'
   * once we have written the corresponding components of 'r'.
   * ('r' might the same as 'a'.)
   */

  /* n1 */
  if (BN_cmp(&a->Z, &group->one) == 0) {
    if (!field_sqr(group, n0, &a->X, ctx) ||
        !BN_mod_lshift1_quick(n1, n0, p) ||
        !BN_mod_add_quick(n0, n0, n1, p) ||
        !BN_mod_add_quick(n1, n0, &group->a, p)) {
      goto err;
    }
    /* n1 = 3 * X_a^2 + a_curve */
  } else if (group->a_is_minus3) {
    if (!field_sqr(group, n1, &a->Z, ctx) ||
        !BN_mod_add_quick(n0, &a->X, n1, p) ||
        !BN_mod_sub_quick(n2, &a->X, n1, p) ||
        !field_mul(group, n1, n0, n2, ctx) ||
        !BN_mod_lshift1_quick(n0, n1, p) ||
        !BN_mod_add_quick(n1, n0, n1, p)) {
      goto err;
    }
    /* n1 = 3 * (X_a + Z_a^2) * (X_a - Z_a^2)
     *    = 3 * X_a^2 - 3 * Z_a^4 */
  } else {
    if (!field_sqr(group, n0, &a->X, ctx) ||
        !BN_mod_lshift1_quick(n1, n0, p) ||
        !BN_mod_add_quick(n0, n0, n1, p) ||
        !field_sqr(group, n1, &a->Z, ctx) ||
        !field_sqr(group, n1, n1, ctx) ||
        !field_mul(group, n1, n1, &group->a, ctx) ||
        !BN_mod_add_quick(n1, n1, n0, p)) {
      goto err;
    }
    /* n1 = 3 * X_a^2 + a_curve * Z_a^4 */
  }

  /* Z_r */
  if (BN_cmp(&a->Z, &group->one) == 0) {
    if (!BN_copy(n0, &a->Y)) {
      goto err;
    }
  } else if (!field_mul(group, n0, &a->Y, &a->Z, ctx)) {
    goto err;
  }
  if (!BN_mod_lshift1_quick(&r->Z, n0, p)) {
    goto err;
  }
  /* Z_r = 2 * Y_a * Z_a */

  /* n2 */
  if (!field_sqr(group, n3, &a->Y, ctx) ||
      !field_mul(group, n2, &a->X, n3, ctx) ||
      !BN_mod_lshift_quick(n2, n2, 2, p)) {
    goto err;
  }
  /* n2 = 4 * X_a * Y_a^2 */

  /* X_r */
  if (!BN_mod_lshift1_quick(n0, n2, p) ||
      !field_sqr(group, &r->X, n1, ctx) ||
      !BN_mod_sub_quick(&r->X, &r->X, n0, p)) {
    goto err;
  }
  /* X_r = n1^2 - 2 * n2 */

  /* n3 */
  if (!field_sqr(group, n0, n3, ctx) ||
      !BN_mod_lshift_quick(n3, n0, 3, p)) {
    goto err;
  }
  /* n3 = 8 * Y_a^4 */

  /* Y_r */
  if (!BN_mod_sub_quick(n0, n2, &r->X, p) ||
      !field_mul(group, n0, n1, n0, ctx) ||
      !BN_mod_sub_quick(&r->Y, n0, n3, p)) {
    goto err;
  }
  /* Y_r = n1 * (n2 - X_r) - n3 */

  ret = 1;

err:
  BN_CTX_end(ctx);
  BN_CTX_free(new_ctx);
  return ret;
}
Ejemplo n.º 10
0
int ec_GFp_simple_group_set_curve(EC_GROUP *group, const BIGNUM *p,
                                  const BIGNUM *a, const BIGNUM *b,
                                  BN_CTX *ctx) {
  int ret = 0;
  BN_CTX *new_ctx = NULL;
  BIGNUM *tmp_a;

  /* p must be a prime > 3 */
  if (BN_num_bits(p) <= 2 || !BN_is_odd(p)) {
    OPENSSL_PUT_ERROR(EC, EC_R_INVALID_FIELD);
    return 0;
  }

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

  BN_CTX_start(ctx);
  tmp_a = BN_CTX_get(ctx);
  if (tmp_a == NULL) {
    goto err;
  }

  /* group->field */
  if (!BN_copy(&group->field, p)) {
    goto err;
  }
  BN_set_negative(&group->field, 0);

  /* group->a */
  if (!BN_nnmod(tmp_a, a, p, ctx)) {
    goto err;
  }
  if (group->meth->field_encode) {
    if (!group->meth->field_encode(group, &group->a, tmp_a, ctx)) {
      goto err;
    }
  } else if (!BN_copy(&group->a, tmp_a)) {
    goto err;
  }

  /* group->b */
  if (!BN_nnmod(&group->b, b, p, ctx)) {
    goto err;
  }
  if (group->meth->field_encode &&
      !group->meth->field_encode(group, &group->b, &group->b, ctx)) {
    goto err;
  }

  /* group->a_is_minus3 */
  if (!BN_add_word(tmp_a, 3)) {
    goto err;
  }
  group->a_is_minus3 = (0 == BN_cmp(tmp_a, &group->field));

  if (group->meth->field_encode != NULL) {
    if (!group->meth->field_encode(group, &group->one, BN_value_one(), ctx)) {
      goto err;
    }
  } else if (!BN_copy(&group->one, BN_value_one())) {
    goto err;
  }

  ret = 1;

err:
  BN_CTX_end(ctx);
  BN_CTX_free(new_ctx);
  return ret;
}
Ejemplo n.º 11
0
int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group,
                                               const EC_POINT *point, BIGNUM *x,
                                               BIGNUM *y, BN_CTX *ctx) {
  BN_CTX *new_ctx = NULL;
  BIGNUM *Z, *Z_1, *Z_2, *Z_3;
  const BIGNUM *Z_;
  int ret = 0;

  if (EC_POINT_is_at_infinity(group, point)) {
    OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY);
    return 0;
  }

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

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

  /* transform  (X, Y, Z)  into  (x, y) := (X/Z^2, Y/Z^3) */

  if (group->meth->field_decode) {
    if (!group->meth->field_decode(group, Z, &point->Z, ctx)) {
      goto err;
    }
    Z_ = Z;
  } else {
    Z_ = &point->Z;
  }

  if (BN_is_one(Z_)) {
    if (group->meth->field_decode) {
      if (x != NULL && !group->meth->field_decode(group, x, &point->X, ctx)) {
        goto err;
      }
      if (y != NULL && !group->meth->field_decode(group, y, &point->Y, ctx)) {
        goto err;
      }
    } else {
      if (x != NULL && !BN_copy(x, &point->X)) {
        goto err;
      }
      if (y != NULL && !BN_copy(y, &point->Y)) {
        goto err;
      }
    }
  } else {
    if (!BN_mod_inverse(Z_1, Z_, &group->field, ctx)) {
      OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
      goto err;
    }

    if (group->meth->field_encode == 0) {
      /* field_sqr works on standard representation */
      if (!group->meth->field_sqr(group, Z_2, Z_1, ctx)) {
        goto err;
      }
    } else if (!BN_mod_sqr(Z_2, Z_1, &group->field, ctx)) {
      goto err;
    }

    /* in the Montgomery case, field_mul will cancel out Montgomery factor in
     * X: */
    if (x != NULL && !group->meth->field_mul(group, x, &point->X, Z_2, ctx)) {
      goto err;
    }

    if (y != NULL) {
      if (group->meth->field_encode == 0) {
        /* field_mul works on standard representation */
        if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx)) {
          goto err;
        }
      } else if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx)) {
        goto err;
      }

      /* in the Montgomery case, field_mul will cancel out Montgomery factor in
       * Y: */
      if (!group->meth->field_mul(group, y, &point->Y, Z_3, ctx)) {
        goto err;
      }
    }
  }

  ret = 1;

err:
  BN_CTX_end(ctx);
  BN_CTX_free(new_ctx);
  return ret;
}
Ejemplo n.º 12
0
int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num,
                                     EC_POINT *points[], BN_CTX *ctx) {
  BN_CTX *new_ctx = NULL;
  BIGNUM *tmp, *tmp_Z;
  BIGNUM **prod_Z = NULL;
  size_t i;
  int ret = 0;

  if (num == 0) {
    return 1;
  }

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

  BN_CTX_start(ctx);
  tmp = BN_CTX_get(ctx);
  tmp_Z = BN_CTX_get(ctx);
  if (tmp == NULL || tmp_Z == NULL) {
    goto err;
  }

  prod_Z = OPENSSL_malloc(num * sizeof(prod_Z[0]));
  if (prod_Z == NULL) {
    goto err;
  }
  memset(prod_Z, 0, num * sizeof(prod_Z[0]));
  for (i = 0; i < num; i++) {
    prod_Z[i] = BN_new();
    if (prod_Z[i] == NULL) {
      goto err;
    }
  }

  /* Set each prod_Z[i] to the product of points[0]->Z .. points[i]->Z,
   * skipping any zero-valued inputs (pretend that they're 1). */

  if (!BN_is_zero(&points[0]->Z)) {
    if (!BN_copy(prod_Z[0], &points[0]->Z)) {
      goto err;
    }
  } else {
    if (BN_copy(prod_Z[0], &group->one) == NULL) {
      goto err;
    }
  }

  for (i = 1; i < num; i++) {
    if (!BN_is_zero(&points[i]->Z)) {
      if (!group->meth->field_mul(group, prod_Z[i], prod_Z[i - 1],
                                  &points[i]->Z, ctx)) {
        goto err;
      }
    } else {
      if (!BN_copy(prod_Z[i], prod_Z[i - 1])) {
        goto err;
      }
    }
  }

  /* Now use a single explicit inversion to replace every
   * non-zero points[i]->Z by its inverse. */

  if (!BN_mod_inverse(tmp, prod_Z[num - 1], &group->field, ctx)) {
    OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
    goto err;
  }

  if (group->meth->field_encode != NULL) {
    /* In the Montgomery case, we just turned R*H (representing H)
     * into 1/(R*H), but we need R*(1/H) (representing 1/H);
     * i.e. we need to multiply by the Montgomery factor twice. */
    if (!group->meth->field_encode(group, tmp, tmp, ctx) ||
        !group->meth->field_encode(group, tmp, tmp, ctx)) {
      goto err;
    }
  }

  for (i = num - 1; i > 0; --i) {
    /* Loop invariant: tmp is the product of the inverses of
     * points[0]->Z .. points[i]->Z (zero-valued inputs skipped). */
    if (BN_is_zero(&points[i]->Z)) {
      continue;
    }

    /* Set tmp_Z to the inverse of points[i]->Z (as product
     * of Z inverses 0 .. i, Z values 0 .. i - 1). */
    if (!group->meth->field_mul(group, tmp_Z, prod_Z[i - 1], tmp, ctx) ||
        /* Update tmp to satisfy the loop invariant for i - 1. */
        !group->meth->field_mul(group, tmp, tmp, &points[i]->Z, ctx) ||
        /* Replace points[i]->Z by its inverse. */
        !BN_copy(&points[i]->Z, tmp_Z)) {
      goto err;
    }
  }

  /* Replace points[0]->Z by its inverse. */
  if (!BN_is_zero(&points[0]->Z) && !BN_copy(&points[0]->Z, tmp)) {
    goto err;
  }

  /* Finally, fix up the X and Y coordinates for all points. */
  for (i = 0; i < num; i++) {
    EC_POINT *p = points[i];

    if (!BN_is_zero(&p->Z)) {
      /* turn (X, Y, 1/Z) into (X/Z^2, Y/Z^3, 1). */
      if (!group->meth->field_sqr(group, tmp, &p->Z, ctx) ||
          !group->meth->field_mul(group, &p->X, &p->X, tmp, ctx) ||
          !group->meth->field_mul(group, tmp, tmp, &p->Z, ctx) ||
          !group->meth->field_mul(group, &p->Y, &p->Y, tmp, ctx)) {
        goto err;
      }

      if (BN_copy(&p->Z, &group->one) == NULL) {
        goto err;
      }
    }
  }

  ret = 1;

err:
  BN_CTX_end(ctx);
  BN_CTX_free(new_ctx);
  if (prod_Z != NULL) {
    for (i = 0; i < num; i++) {
      if (prod_Z[i] == NULL) {
        break;
      }
      BN_clear_free(prod_Z[i]);
    }
    OPENSSL_free(prod_Z);
  }

  return ret;
}
Ejemplo n.º 13
0
static int dsa_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8)
	{
	const unsigned char *p, *pm;
	int pklen, pmlen;
	int ptype;
	void *pval;
	ASN1_STRING *pstr;
	X509_ALGOR *palg;
	ASN1_INTEGER *privkey = NULL;
	BN_CTX *ctx = NULL;

	STACK_OF(ASN1_TYPE) *ndsa = NULL;
	DSA *dsa = NULL;

	if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8))
		return 0;
	X509_ALGOR_get0(NULL, &ptype, &pval, palg);

	/* Check for broken DSA PKCS#8, UGH! */
	if (*p == (V_ASN1_SEQUENCE|V_ASN1_CONSTRUCTED))
		{
		ASN1_TYPE *t1, *t2;
	    	if(!(ndsa = d2i_ASN1_SEQUENCE_ANY(NULL, &p, pklen)))
			goto decerr;
		if (sk_ASN1_TYPE_num(ndsa) != 2)
			goto decerr;
		/* Handle Two broken types:
	    	 * SEQUENCE {parameters, priv_key}
		 * SEQUENCE {pub_key, priv_key}
		 */

		t1 = sk_ASN1_TYPE_value(ndsa, 0);
		t2 = sk_ASN1_TYPE_value(ndsa, 1);
		if (t1->type == V_ASN1_SEQUENCE)
			{
			p8->broken = PKCS8_EMBEDDED_PARAM;
			pval = t1->value.ptr;
			}
		else if (ptype == V_ASN1_SEQUENCE)
			p8->broken = PKCS8_NS_DB;
		else
			goto decerr;

		if (t2->type != V_ASN1_INTEGER)
			goto decerr;

		privkey = t2->value.integer;
		}
	else
		{
		const unsigned char *q = p;
		if (!(privkey=d2i_ASN1_INTEGER(NULL, &p, pklen)))
			goto decerr;
		if (privkey->type == V_ASN1_NEG_INTEGER)
			{
			p8->broken = PKCS8_NEG_PRIVKEY;
			ASN1_INTEGER_free(privkey);
			if (!(privkey=d2i_ASN1_UINTEGER(NULL, &q, pklen)))
				goto decerr;
			}
		if (ptype != V_ASN1_SEQUENCE)
			goto decerr;
		}

	pstr = pval;	
	pm = pstr->data;
	pmlen = pstr->length;
	if (!(dsa = d2i_DSAparams(NULL, &pm, pmlen)))
		goto decerr;
	/* We have parameters now set private key */
	if (!(dsa->priv_key = ASN1_INTEGER_to_BN(privkey, NULL)))
		{
		DSAerr(DSA_F_DSA_PRIV_DECODE,DSA_R_BN_ERROR);
		goto dsaerr;
		}
	/* Calculate public key */
	if (!(dsa->pub_key = BN_new()))
		{
		DSAerr(DSA_F_DSA_PRIV_DECODE, ERR_R_MALLOC_FAILURE);
		goto dsaerr;
		}
	if (!(ctx = BN_CTX_new()))
		{
		DSAerr(DSA_F_DSA_PRIV_DECODE, ERR_R_MALLOC_FAILURE);
		goto dsaerr;
		}
			
	if (!BN_mod_exp(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx))
		{
		DSAerr(DSA_F_DSA_PRIV_DECODE,DSA_R_BN_ERROR);
		goto dsaerr;
		}

	EVP_PKEY_assign_DSA(pkey, dsa);
	BN_CTX_free (ctx);
	if(ndsa)
		sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free);
	else
		ASN1_INTEGER_free(privkey);

	return 1;

	decerr:
	DSAerr(DSA_F_DSA_PRIV_DECODE, EVP_R_DECODE_ERROR);
	dsaerr:
	BN_CTX_free (ctx);
	if (privkey)
		ASN1_INTEGER_free(privkey);
	sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free);
	DSA_free(dsa);
	return 0;
	}
Ejemplo n.º 14
0
static int dsa_do_verify(const unsigned char *dgst, FIPS_DSA_SIZE_T dgst_len, DSA_SIG *sig,
		  DSA *dsa)
	{
	BN_CTX *ctx;
	BIGNUM u1,u2,t1;
	BN_MONT_CTX *mont=NULL;
	int ret = -1;

	if (!dsa->p || !dsa->q || !dsa->g)
		{
		DSAerr(DSA_F_DSA_DO_VERIFY,DSA_R_MISSING_PARAMETERS);
		return -1;
		}

	if(FIPS_selftest_failed())
	    {
	    FIPSerr(FIPS_F_DSA_DO_VERIFY,FIPS_R_FIPS_SELFTEST_FAILED);
	    return -1;
	    }

	if (BN_num_bits(dsa->q) != 160)
		{
		DSAerr(DSA_F_DSA_DO_VERIFY,DSA_R_BAD_Q_VALUE);
		return -1;
		}

	if (BN_num_bits(dsa->p) > OPENSSL_DSA_MAX_MODULUS_BITS)
		{
		DSAerr(DSA_F_DSA_DO_VERIFY,DSA_R_MODULUS_TOO_LARGE);
		return -1;
		}

	if (FIPS_mode() && (BN_num_bits(dsa->p) < OPENSSL_DSA_FIPS_MIN_MODULUS_BITS))
		{
		DSAerr(DSA_F_DSA_DO_VERIFY, DSA_R_KEY_SIZE_TOO_SMALL);
		return -1;
		}

	BN_init(&u1);
	BN_init(&u2);
	BN_init(&t1);

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

	if (BN_is_zero(sig->r) || sig->r->neg || BN_ucmp(sig->r, dsa->q) >= 0)
		{
		ret = 0;
		goto err;
		}
	if (BN_is_zero(sig->s) || sig->s->neg || BN_ucmp(sig->s, dsa->q) >= 0)
		{
		ret = 0;
		goto err;
		}

	/* Calculate W = inv(S) mod Q
	 * save W in u2 */
	if ((BN_mod_inverse(&u2,sig->s,dsa->q,ctx)) == NULL) goto err;

	/* save M in u1 */
	if (BN_bin2bn(dgst,dgst_len,&u1) == NULL) goto err;

	/* u1 = M * w mod q */
	if (!BN_mod_mul(&u1,&u1,&u2,dsa->q,ctx)) goto err;

	/* u2 = r * w mod q */
	if (!BN_mod_mul(&u2,sig->r,&u2,dsa->q,ctx)) goto err;


	if (dsa->flags & DSA_FLAG_CACHE_MONT_P)
		{
		mont = BN_MONT_CTX_set_locked(
					(BN_MONT_CTX **)&dsa->method_mont_p,
					CRYPTO_LOCK_DSA, dsa->p, ctx);
		if (!mont)
			goto err;
		}

#if 0
	{
	BIGNUM t2;

	BN_init(&t2);
	/* v = ( g^u1 * y^u2 mod p ) mod q */
	/* let t1 = g ^ u1 mod p */
	if (!BN_mod_exp_mont(&t1,dsa->g,&u1,dsa->p,ctx,mont)) goto err;
	/* let t2 = y ^ u2 mod p */
	if (!BN_mod_exp_mont(&t2,dsa->pub_key,&u2,dsa->p,ctx,mont)) goto err;
	/* let u1 = t1 * t2 mod p */
	if (!BN_mod_mul(&u1,&t1,&t2,dsa->p,ctx)) goto err_bn;
	BN_free(&t2);
	}
	/* let u1 = u1 mod q */
	if (!BN_mod(&u1,&u1,dsa->q,ctx)) goto err;
#else
	{
	if (!dsa->meth->dsa_mod_exp(dsa, &t1,dsa->g,&u1,dsa->pub_key,&u2,
						dsa->p,ctx,mont)) goto err;
	/* BN_copy(&u1,&t1); */
	/* let u1 = u1 mod q */
	if (!BN_mod(&u1,&t1,dsa->q,ctx)) goto err;
	}
#endif
	/* V is now in u1.  If the signature is correct, it will be
	 * equal to R. */
	ret=(BN_ucmp(&u1, sig->r) == 0);

	err:
	if (ret != 1) DSAerr(DSA_F_DSA_DO_VERIFY,ERR_R_BN_LIB);
	if (ctx != NULL) BN_CTX_free(ctx);
	BN_free(&u1);
	BN_free(&u2);
	BN_free(&t1);
	return(ret);
	}
Ejemplo n.º 15
0
int EC_KEY_print(BIO *bp, const EC_KEY *x, int off)
	{
	unsigned char *buffer=NULL;
	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;
		}

	public_key = EC_KEY_get0_public_key(x);
	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);
	priv_key = EC_KEY_get0_private_key(x);
	if (priv_key != NULL)
		{
		if ((i = (size_t)BN_num_bytes(priv_key)) > buf_len)
			buf_len = i;
		}

	buf_len += 10;
	if ((buffer = OPENSSL_malloc(buf_len)) == NULL)
		{
		reason = ERR_R_MALLOC_FAILURE;
		goto err;
		}

	if (priv_key != NULL)
		{
		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, "Private-Key: (%d bit)\n", 
			BN_num_bits(order)) <= 0) goto err;
		}
  
	if ((priv_key != NULL) && !print(bp, "priv:", priv_key, 
		buffer, off))
		goto err;
	if ((pub_key != NULL) && !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_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);
	}
Ejemplo n.º 16
0
int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
                              BN_CTX *ctx) {
  int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *,
                   BN_CTX *);
  int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
  const BIGNUM *p;
  BN_CTX *new_ctx = NULL;
  BIGNUM *rh, *tmp, *Z4, *Z6;
  int ret = 0;

  if (EC_POINT_is_at_infinity(group, point)) {
    return 1;
  }

  field_mul = group->meth->field_mul;
  field_sqr = group->meth->field_sqr;
  p = &group->field;

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

  BN_CTX_start(ctx);
  rh = BN_CTX_get(ctx);
  tmp = BN_CTX_get(ctx);
  Z4 = BN_CTX_get(ctx);
  Z6 = BN_CTX_get(ctx);
  if (Z6 == NULL) {
    goto err;
  }

  /* We have a curve defined by a Weierstrass equation
   *      y^2 = x^3 + a*x + b.
   * The point to consider is given in Jacobian projective coordinates
   * where  (X, Y, Z)  represents  (x, y) = (X/Z^2, Y/Z^3).
   * Substituting this and multiplying by  Z^6  transforms the above equation
   * into
   *      Y^2 = X^3 + a*X*Z^4 + b*Z^6.
   * To test this, we add up the right-hand side in 'rh'.
   */

  /* rh := X^2 */
  if (!field_sqr(group, rh, &point->X, ctx)) {
    goto err;
  }

  if (BN_cmp(&point->Z, &group->one) != 0) {
    if (!field_sqr(group, tmp, &point->Z, ctx) ||
        !field_sqr(group, Z4, tmp, ctx) ||
        !field_mul(group, Z6, Z4, tmp, ctx)) {
      goto err;
    }

    /* rh := (rh + a*Z^4)*X */
    if (group->a_is_minus3) {
      if (!BN_mod_lshift1_quick(tmp, Z4, p) ||
          !BN_mod_add_quick(tmp, tmp, Z4, p) ||
          !BN_mod_sub_quick(rh, rh, tmp, p) ||
          !field_mul(group, rh, rh, &point->X, ctx)) {
        goto err;
      }
    } else {
      if (!field_mul(group, tmp, Z4, &group->a, ctx) ||
          !BN_mod_add_quick(rh, rh, tmp, p) ||
          !field_mul(group, rh, rh, &point->X, ctx)) {
        goto err;
      }
    }

    /* rh := rh + b*Z^6 */
    if (!field_mul(group, tmp, &group->b, Z6, ctx) ||
        !BN_mod_add_quick(rh, rh, tmp, p)) {
      goto err;
    }
  } else {
    /* rh := (rh + a)*X */
    if (!BN_mod_add_quick(rh, rh, &group->a, p) ||
        !field_mul(group, rh, rh, &point->X, ctx)) {
      goto err;
    }
    /* rh := rh + b */
    if (!BN_mod_add_quick(rh, rh, &group->b, p)) {
      goto err;
    }
  }

  /* 'lh' := Y^2 */
  if (!field_sqr(group, tmp, &point->Y, ctx)) {
    goto err;
  }

  ret = (0 == BN_ucmp(tmp, rh));

err:
  BN_CTX_end(ctx);
  BN_CTX_free(new_ctx);
  return ret;
}
Ejemplo n.º 17
0
/*-
 * Computes the sum
 *     scalar*group->generator + scalars[0]*points[0] + ... + scalars[num-1]*points[num-1]
 * gracefully ignoring NULL scalar values.
 */
int ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r,
                       const BIGNUM *scalar, size_t num,
                       const EC_POINT *points[], const BIGNUM *scalars[],
                       BN_CTX *ctx)
{
    BN_CTX *new_ctx = NULL;
    int ret = 0;
    size_t i;
    EC_POINT *p = NULL;
    EC_POINT *acc = NULL;

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

    /*
     * This implementation is more efficient than the wNAF implementation for
     * 2 or fewer points.  Use the ec_wNAF_mul implementation for 3 or more
     * points, or if we can perform a fast multiplication based on
     * precomputation.
     */
    if ((scalar && (num > 1)) || (num > 2)
        || (num == 0 && EC_GROUP_have_precompute_mult(group))) {
        ret = ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
        goto err;
    }

    if ((p = EC_POINT_new(group)) == NULL)
        goto err;
    if ((acc = EC_POINT_new(group)) == NULL)
        goto err;

    if (!EC_POINT_set_to_infinity(group, acc))
        goto err;

    if (scalar) {
        if (!ec_GF2m_montgomery_point_multiply
            (group, p, scalar, group->generator, ctx))
            goto err;
        if (BN_is_negative(scalar))
            if (!group->meth->invert(group, p, ctx))
                goto err;
        if (!group->meth->add(group, acc, acc, p, ctx))
            goto err;
    }

    for (i = 0; i < num; i++) {
        if (!ec_GF2m_montgomery_point_multiply
            (group, p, scalars[i], points[i], ctx))
            goto err;
        if (BN_is_negative(scalars[i]))
            if (!group->meth->invert(group, p, ctx))
                goto err;
        if (!group->meth->add(group, acc, acc, p, ctx))
            goto err;
    }

    if (!EC_POINT_copy(r, acc))
        goto err;

    ret = 1;

 err:
    if (p)
        EC_POINT_free(p);
    if (acc)
        EC_POINT_free(acc);
    if (new_ctx != NULL)
        BN_CTX_free(new_ctx);
    return ret;
}
Ejemplo n.º 18
0
int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
                      const EC_POINT *b, BN_CTX *ctx) {
  /* return values:
   *  -1   error
   *   0   equal (in affine coordinates)
   *   1   not equal
   */

  int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *,
                   BN_CTX *);
  int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
  BN_CTX *new_ctx = NULL;
  BIGNUM *tmp1, *tmp2, *Za23, *Zb23;
  const BIGNUM *tmp1_, *tmp2_;
  int ret = -1;

  if (EC_POINT_is_at_infinity(group, a)) {
    return EC_POINT_is_at_infinity(group, b) ? 0 : 1;
  }

  if (EC_POINT_is_at_infinity(group, b)) {
    return 1;
  }

  int a_Z_is_one = BN_cmp(&a->Z, &group->one) == 0;
  int b_Z_is_one = BN_cmp(&b->Z, &group->one) == 0;

  if (a_Z_is_one && b_Z_is_one) {
    return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1;
  }

  field_mul = group->meth->field_mul;
  field_sqr = group->meth->field_sqr;

  if (ctx == NULL) {
    ctx = new_ctx = BN_CTX_new();
    if (ctx == NULL) {
      return -1;
    }
  }

  BN_CTX_start(ctx);
  tmp1 = BN_CTX_get(ctx);
  tmp2 = BN_CTX_get(ctx);
  Za23 = BN_CTX_get(ctx);
  Zb23 = BN_CTX_get(ctx);
  if (Zb23 == NULL) {
    goto end;
  }

  /* We have to decide whether
   *     (X_a/Z_a^2, Y_a/Z_a^3) = (X_b/Z_b^2, Y_b/Z_b^3),
   * or equivalently, whether
   *     (X_a*Z_b^2, Y_a*Z_b^3) = (X_b*Z_a^2, Y_b*Z_a^3).
   */

  if (!b_Z_is_one) {
    if (!field_sqr(group, Zb23, &b->Z, ctx) ||
        !field_mul(group, tmp1, &a->X, Zb23, ctx)) {
      goto end;
    }
    tmp1_ = tmp1;
  } else {
    tmp1_ = &a->X;
  }
  if (!a_Z_is_one) {
    if (!field_sqr(group, Za23, &a->Z, ctx) ||
        !field_mul(group, tmp2, &b->X, Za23, ctx)) {
      goto end;
    }
    tmp2_ = tmp2;
  } else {
    tmp2_ = &b->X;
  }

  /* compare  X_a*Z_b^2  with  X_b*Z_a^2 */
  if (BN_cmp(tmp1_, tmp2_) != 0) {
    ret = 1; /* points differ */
    goto end;
  }


  if (!b_Z_is_one) {
    if (!field_mul(group, Zb23, Zb23, &b->Z, ctx) ||
        !field_mul(group, tmp1, &a->Y, Zb23, ctx)) {
      goto end;
    }
    /* tmp1_ = tmp1 */
  } else {
    tmp1_ = &a->Y;
  }
  if (!a_Z_is_one) {
    if (!field_mul(group, Za23, Za23, &a->Z, ctx) ||
        !field_mul(group, tmp2, &b->Y, Za23, ctx)) {
      goto end;
    }
    /* tmp2_ = tmp2 */
  } else {
    tmp2_ = &b->Y;
  }

  /* compare  Y_a*Z_b^3  with  Y_b*Z_a^3 */
  if (BN_cmp(tmp1_, tmp2_) != 0) {
    ret = 1; /* points differ */
    goto end;
  }

  /* points are equal */
  ret = 0;

end:
  BN_CTX_end(ctx);
  BN_CTX_free(new_ctx);
  return ret;
}
Ejemplo n.º 19
0
static int dsa_builtin_paramgen(DSA *ret, int bits,
		unsigned char *seed_in, int seed_len,
		int *counter_ret, unsigned long *h_ret, BN_GENCB *cb)
	{
	int ok=0;
	unsigned char seed[SHA_DIGEST_LENGTH];
	unsigned char md[SHA_DIGEST_LENGTH];
	unsigned char buf[SHA_DIGEST_LENGTH],buf2[SHA_DIGEST_LENGTH];
	BIGNUM *r0,*W,*X,*c,*test;
	BIGNUM *g=NULL,*q=NULL,*p=NULL;
	BN_MONT_CTX *mont=NULL;
	int k,n=0,i,b,m=0;
	int counter=0;
	int r=0;
	BN_CTX *ctx=NULL;
	unsigned int h=2;

	if (bits < 512) bits=512;
	bits=(bits+63)/64*64;

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

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

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

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

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

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

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

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

			/* step 2 */
			EVP_Digest(seed,SHA_DIGEST_LENGTH,md,NULL,HASH, NULL);
			EVP_Digest(buf,SHA_DIGEST_LENGTH,buf2,NULL,HASH, NULL);
			for (i=0; i<SHA_DIGEST_LENGTH; i++)
				md[i]^=buf2[i];

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

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

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

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

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

		n=(bits-1)/160;
		b=(bits-1)-n*160;

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

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

				EVP_Digest(buf,SHA_DIGEST_LENGTH,md,NULL,HASH, NULL);

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

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

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

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

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

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

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

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

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

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

	ok=1;
err:
	if (ok)
		{
		if(ret->p) BN_free(ret->p);
		if(ret->q) BN_free(ret->q);
		if(ret->g) BN_free(ret->g);
		ret->p=BN_dup(p);
		ret->q=BN_dup(q);
		ret->g=BN_dup(g);
		if (ret->p == NULL || ret->q == NULL || ret->g == NULL)
			{
			ok=0;
			goto err;
			}
		if (seed_in != NULL) memcpy(seed_in,seed,20);
		if (counter_ret != NULL) *counter_ret=counter;
		if (h_ret != NULL) *h_ret=h;
		}
	if(ctx)
		{
		BN_CTX_end(ctx);
		BN_CTX_free(ctx);
		}
	if (mont != NULL) BN_MONT_CTX_free(mont);
	return ok;
	}
Ejemplo n.º 20
0
EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8)
{
	EVP_PKEY *pkey = NULL;
#ifndef OPENSSL_NO_RSA
	RSA *rsa = NULL;
#endif
#ifndef OPENSSL_NO_DSA
	DSA *dsa = NULL;
	ASN1_TYPE *t1, *t2;
	ASN1_INTEGER *privkey;
	STACK_OF(ASN1_TYPE) *ndsa = NULL;
#endif
#ifndef OPENSSL_NO_EC
	EC_KEY *eckey = NULL;
	const unsigned char *p_tmp;
#endif
#if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_EC)
	ASN1_TYPE    *param = NULL;	
	BN_CTX *ctx = NULL;
	int plen;
#endif
	X509_ALGOR *a;
	const unsigned char *p;
	const unsigned char *cp;
	int pkeylen;
	int  nid;
	char obj_tmp[80];

	if(p8->pkey->type == V_ASN1_OCTET_STRING) {
		p8->broken = PKCS8_OK;
		p = p8->pkey->value.octet_string->data;
		pkeylen = p8->pkey->value.octet_string->length;
	} else {
		p8->broken = PKCS8_NO_OCTET;
		p = p8->pkey->value.sequence->data;
		pkeylen = p8->pkey->value.sequence->length;
	}
	if (!(pkey = EVP_PKEY_new())) {
		EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE);
		return NULL;
	}
	a = p8->pkeyalg;
	nid = OBJ_obj2nid(a->algorithm);
	switch(nid)
	{
#ifndef OPENSSL_NO_RSA
		case NID_rsaEncryption:
		cp = p;
		if (!(rsa = d2i_RSAPrivateKey (NULL,&cp, pkeylen))) {
			EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR);
			return NULL;
		}
		EVP_PKEY_assign_RSA (pkey, rsa);
		break;
#endif
#ifndef OPENSSL_NO_DSA
		case NID_dsa:
		/* PKCS#8 DSA is weird: you just get a private key integer
	         * and parameters in the AlgorithmIdentifier the pubkey must
		 * be recalculated.
		 */
	
		/* Check for broken DSA PKCS#8, UGH! */
		if(*p == (V_ASN1_SEQUENCE|V_ASN1_CONSTRUCTED)) {
		    if(!(ndsa = ASN1_seq_unpack_ASN1_TYPE(p, pkeylen, 
							  d2i_ASN1_TYPE,
							  ASN1_TYPE_free))) {
			EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR);
			goto dsaerr;
		    }
		    if(sk_ASN1_TYPE_num(ndsa) != 2 ) {
			EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR);
			goto dsaerr;
		    }
		    /* Handle Two broken types:
		     * SEQUENCE {parameters, priv_key}
		     * SEQUENCE {pub_key, priv_key}
		     */

		    t1 = sk_ASN1_TYPE_value(ndsa, 0);
		    t2 = sk_ASN1_TYPE_value(ndsa, 1);
		    if(t1->type == V_ASN1_SEQUENCE) {
			p8->broken = PKCS8_EMBEDDED_PARAM;
			param = t1;
		    } else if(a->parameter->type == V_ASN1_SEQUENCE) {
			p8->broken = PKCS8_NS_DB;
			param = a->parameter;
		    } else {
			EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR);
			goto dsaerr;
		    }

		    if(t2->type != V_ASN1_INTEGER) {
			EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR);
			goto dsaerr;
		    }
		    privkey = t2->value.integer;
		} else {
			if (!(privkey=d2i_ASN1_INTEGER (NULL, &p, pkeylen))) {
				EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR);
				goto dsaerr;
			}
			param = p8->pkeyalg->parameter;
		}
		if (!param || (param->type != V_ASN1_SEQUENCE)) {
			EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR);
			goto dsaerr;
		}
		cp = p = param->value.sequence->data;
		plen = param->value.sequence->length;
		if (!(dsa = d2i_DSAparams (NULL, &cp, plen))) {
			EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR);
			goto dsaerr;
		}
		/* We have parameters now set private key */
		if (!(dsa->priv_key = ASN1_INTEGER_to_BN(privkey, NULL))) {
			EVPerr(EVP_F_EVP_PKCS82PKEY,EVP_R_BN_DECODE_ERROR);
			goto dsaerr;
		}
		/* Calculate public key (ouch!) */
		if (!(dsa->pub_key = BN_new())) {
			EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE);
			goto dsaerr;
		}
		if (!(ctx = BN_CTX_new())) {
			EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE);
			goto dsaerr;
		}
			
		if (!BN_mod_exp(dsa->pub_key, dsa->g,
						 dsa->priv_key, dsa->p, ctx)) {
			
			EVPerr(EVP_F_EVP_PKCS82PKEY,EVP_R_BN_PUBKEY_ERROR);
			goto dsaerr;
		}

		EVP_PKEY_assign_DSA(pkey, dsa);
		BN_CTX_free (ctx);
		if(ndsa) sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free);
		else ASN1_INTEGER_free(privkey);
		break;
		dsaerr:
		BN_CTX_free (ctx);
		sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free);
		DSA_free(dsa);
		EVP_PKEY_free(pkey);
		return NULL;
		break;
#endif
#ifndef OPENSSL_NO_EC
		case NID_X9_62_id_ecPublicKey:
		p_tmp = p;
		/* extract the ec parameters */
		param = p8->pkeyalg->parameter;

		if (!param || ((param->type != V_ASN1_SEQUENCE) &&
		    (param->type != V_ASN1_OBJECT)))
		{
			EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR);
			goto ecerr;
		}

		if (param->type == V_ASN1_SEQUENCE)
		{
			cp = p = param->value.sequence->data;
			plen = param->value.sequence->length;

			if (!(eckey = d2i_ECParameters(NULL, &cp, plen)))
			{
				EVPerr(EVP_F_EVP_PKCS82PKEY,
					EVP_R_DECODE_ERROR);
				goto ecerr;
			}
		}
		else
		{
			EC_GROUP *group;
			cp = p = param->value.object->data;
			plen = param->value.object->length;

			/* type == V_ASN1_OBJECT => the parameters are given
			 * by an asn1 OID
			 */
			if ((eckey = EC_KEY_new()) == NULL)
			{
				EVPerr(EVP_F_EVP_PKCS82PKEY,
					ERR_R_MALLOC_FAILURE);
				goto ecerr;
			}
			group = EC_GROUP_new_by_curve_name(OBJ_obj2nid(a->parameter->value.object));
			if (group == NULL)
				goto ecerr;
			EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
			if (EC_KEY_set_group(eckey, group) == 0)
				goto ecerr;
			EC_GROUP_free(group);
		}

		/* We have parameters now set private key */
		if (!d2i_ECPrivateKey(&eckey, &p_tmp, pkeylen))
		{
			EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR);
			goto ecerr;
		}

		/* calculate public key (if necessary) */
		if (EC_KEY_get0_public_key(eckey) == NULL)
		{
			const BIGNUM *priv_key;
			const EC_GROUP *group;
			EC_POINT *pub_key;
			/* the public key was not included in the SEC1 private
			 * key => calculate the public key */
			group   = EC_KEY_get0_group(eckey);
			pub_key = EC_POINT_new(group);
			if (pub_key == NULL)
			{
				EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_EC_LIB);
				goto ecerr;
			}
			if (!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group)))
			{
				EC_POINT_free(pub_key);
				EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_EC_LIB);
				goto ecerr;
			}
			priv_key = EC_KEY_get0_private_key(eckey);
			if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
			{
				EC_POINT_free(pub_key);
				EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_EC_LIB);
				goto ecerr;
			}
			if (EC_KEY_set_public_key(eckey, pub_key) == 0)
			{
				EC_POINT_free(pub_key);
				EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_EC_LIB);
				goto ecerr;
			}
			EC_POINT_free(pub_key);
		}

		EVP_PKEY_assign_EC_KEY(pkey, eckey);
		if (ctx)
			BN_CTX_free(ctx);
		break;
ecerr:
		if (ctx)
			BN_CTX_free(ctx);
		if (eckey)
			EC_KEY_free(eckey);
		if (pkey)
			EVP_PKEY_free(pkey);
		return NULL;
#endif
		default:
		EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM);
		if (!a->algorithm) BUF_strlcpy (obj_tmp, "NULL", sizeof obj_tmp);
		else i2t_ASN1_OBJECT(obj_tmp, 80, a->algorithm);
		ERR_add_error_data(2, "TYPE=", obj_tmp);
		EVP_PKEY_free (pkey);
		return NULL;
	}
	return pkey;
}
Ejemplo n.º 21
0
BN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *in_ctx)
{
	BIGNUM local_n;
	BIGNUM *e,*n;
	BN_CTX *ctx;
	BN_BLINDING *ret = NULL;

	if (in_ctx == NULL)
		{
		if ((ctx = BN_CTX_new()) == NULL) return 0;
		}
	else
		ctx = in_ctx;

	BN_CTX_start(ctx);
	e  = BN_CTX_get(ctx);
	if (e == NULL)
		{
		RSAerr(RSA_F_RSA_SETUP_BLINDING, ERR_R_MALLOC_FAILURE);
		goto err;
		}

	if (rsa->e == NULL)
		{
		e = rsa_get_public_exp(rsa->d, rsa->p, rsa->q, ctx);
		if (e == NULL)
			{
			RSAerr(RSA_F_RSA_SETUP_BLINDING, RSA_R_NO_PUBLIC_EXPONENT);
			goto err;
			}
		}
	else
		e = rsa->e;

	
	if ((RAND_status() == 0) && rsa->d != NULL && rsa->d->d != NULL)
		{
		/* if PRNG is not properly seeded, resort to secret
		 * exponent as unpredictable seed */
		RAND_add(rsa->d->d, rsa->d->dmax * sizeof rsa->d->d[0], 0.0);
		}

	if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
		{
		/* Set BN_FLG_CONSTTIME flag */
		n = &local_n;
		BN_with_flags(n, rsa->n, BN_FLG_CONSTTIME);
		}
	else
		n = rsa->n;

	ret = BN_BLINDING_create_param(NULL, e, n, ctx,
			rsa->meth->bn_mod_exp, rsa->_method_mod_n);
	if (ret == NULL)
		{
		RSAerr(RSA_F_RSA_SETUP_BLINDING, ERR_R_BN_LIB);
		goto err;
		}
	CRYPTO_THREADID_current(BN_BLINDING_thread_id(ret));
err:
	BN_CTX_end(ctx);
	if (in_ctx == NULL)
		BN_CTX_free(ctx);
	if(rsa->e == NULL)
		BN_free(e);

	return ret;
}
Ejemplo n.º 22
0
/*
 * 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;
}
Ejemplo n.º 23
0
int BN_is_prime_fasttest_ex(const BIGNUM *a, int checks, BN_CTX *ctx_passed,
		int do_trial_division, BN_GENCB *cb)
	{
	int i, j, ret = -1;
	int k;
	BN_CTX *ctx = NULL;
	BIGNUM *A1, *A1_odd, *check; /* taken from ctx */
	BN_MONT_CTX *mont = NULL;
	const BIGNUM *A = NULL;

	if (BN_cmp(a, BN_value_one()) <= 0)
		return 0;
	
	if (checks == BN_prime_checks)
		checks = BN_prime_checks_for_size(BN_num_bits(a));

	/* first look for small factors */
	if (!BN_is_odd(a))
		/* a is even => a is prime if and only if a == 2 */
		return BN_is_word(a, 2);
	if (do_trial_division)
		{
		for (i = 1; i < NUMPRIMES; i++)
			if (BN_mod_word(a, primes[i]) == 0) 
				return 0;
		if(!BN_GENCB_call(cb, 1, -1))
			goto err;
		}

	if (ctx_passed != NULL)
		ctx = ctx_passed;
	else
		if ((ctx=BN_CTX_new()) == NULL)
			goto err;
	BN_CTX_start(ctx);

	/* A := abs(a) */
	if (a->neg)
		{
		BIGNUM *t;
		if ((t = BN_CTX_get(ctx)) == NULL) goto err;
		BN_copy(t, a);
		t->neg = 0;
		A = t;
		}
	else
		A = a;
	A1 = BN_CTX_get(ctx);
	A1_odd = BN_CTX_get(ctx);
	check = BN_CTX_get(ctx);
	if (check == NULL) goto err;

	/* compute A1 := A - 1 */
	if (!BN_copy(A1, A))
		goto err;
	if (!BN_sub_word(A1, 1))
		goto err;
	if (BN_is_zero(A1))
		{
		ret = 0;
		goto err;
		}

	/* write  A1  as  A1_odd * 2^k */
	k = 1;
	while (!BN_is_bit_set(A1, k))
		k++;
	if (!BN_rshift(A1_odd, A1, k))
		goto err;

	/* Montgomery setup for computations mod A */
	mont = BN_MONT_CTX_new();
	if (mont == NULL)
		goto err;
	if (!BN_MONT_CTX_set(mont, A, ctx))
		goto err;
	
	for (i = 0; i < checks; i++)
		{
		if (!BN_pseudo_rand_range(check, A1))
			goto err;
		if (!BN_add_word(check, 1))
			goto err;
		/* now 1 <= check < A */

		j = witness(check, A, A1, A1_odd, k, ctx, mont);
		if (j == -1) goto err;
		if (j)
			{
			ret=0;
			goto err;
			}
		if(!BN_GENCB_call(cb, 1, i))
			goto err;
		}
	ret=1;
err:
	if (ctx != NULL)
		{
		BN_CTX_end(ctx);
		if (ctx_passed == NULL)
			BN_CTX_free(ctx);
		}
	if (mont != NULL)
		BN_MONT_CTX_free(mont);

	return(ret);
	}
Ejemplo n.º 24
0
/*
 * 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);
                newsig = NULL;
                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);
                newsig = NULL;
                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);
                newsig = NULL;
                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;
}
Ejemplo n.º 25
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;
	}
	BN_CTX_free(ctx);
	BN_clear_free(m);
	BN_clear_free(tmp);
	BN_free(order);
	BN_clear_free(kinv);
	return ret;
}
Ejemplo n.º 26
0
int main(int argc, char *argv[])
	{
	BN_CTX *ctx;
	BIO *out;
	char *outfile=NULL;

	results = 0;

	RAND_seed(rnd_seed, sizeof rnd_seed); /* or BN_generate_prime may fail */

	argc--;
	argv++;
	while (argc >= 1)
		{
		if (strcmp(*argv,"-results") == 0)
			results=1;
		else if (strcmp(*argv,"-out") == 0)
			{
			if (--argc < 1) break;
			outfile= *(++argv);
			}
		argc--;
		argv++;
		}


	ctx=BN_CTX_new();
	if (ctx == NULL) EXIT(1);

	out=BIO_new(BIO_s_file());
	if (out == NULL) EXIT(1);
	if (outfile == NULL)
		{
		BIO_set_fp(out,stdout,BIO_NOCLOSE);
		}
	else
		{
		if (!BIO_write_filename(out,outfile))
			{
			perror(outfile);
			EXIT(1);
			}
		}

	if (!results)
		BIO_puts(out,"obase=16\nibase=16\n");

	message(out,"BN_add");
	if (!test_add(out)) goto err;
	(void)BIO_flush(out);

	message(out,"BN_sub");
	if (!test_sub(out)) goto err;
	(void)BIO_flush(out);

	message(out,"BN_lshift1");
	if (!test_lshift1(out)) goto err;
	(void)BIO_flush(out);

	message(out,"BN_lshift (fixed)");
	if (!test_lshift(out,ctx,BN_bin2bn(lst,sizeof(lst)-1,NULL)))
	    goto err;
	(void)BIO_flush(out);

	message(out,"BN_lshift");
	if (!test_lshift(out,ctx,NULL)) goto err;
	(void)BIO_flush(out);

	message(out,"BN_rshift1");
	if (!test_rshift1(out)) goto err;
	(void)BIO_flush(out);

	message(out,"BN_rshift");
	if (!test_rshift(out,ctx)) goto err;
	(void)BIO_flush(out);

	message(out,"BN_sqr");
	if (!test_sqr(out,ctx)) goto err;
	(void)BIO_flush(out);

	message(out,"BN_mul");
	if (!test_mul(out)) goto err;
	(void)BIO_flush(out);

	message(out,"BN_div");
	if (!test_div(out,ctx)) goto err;
	(void)BIO_flush(out);

	message(out,"BN_div_word");
	if (!test_div_word(out)) goto err;
	(void)BIO_flush(out);

	message(out,"BN_div_recp");
	if (!test_div_recp(out,ctx)) goto err;
	(void)BIO_flush(out);

	message(out,"BN_mod");
	if (!test_mod(out,ctx)) goto err;
	(void)BIO_flush(out);

	message(out,"BN_mod_mul");
	if (!test_mod_mul(out,ctx)) goto err;
	(void)BIO_flush(out);

	message(out,"BN_mont");
	if (!test_mont(out,ctx)) goto err;
	(void)BIO_flush(out);

	message(out,"BN_mod_exp");
	if (!test_mod_exp(out,ctx)) goto err;
	(void)BIO_flush(out);

	message(out,"BN_mod_exp_mont_consttime");
	if (!test_mod_exp_mont_consttime(out,ctx)) goto err;
	if (!test_mod_exp_mont5(out,ctx)) goto err;
	(void)BIO_flush(out);

	message(out,"BN_exp");
	if (!test_exp(out,ctx)) goto err;
	(void)BIO_flush(out);

	message(out,"BN_kronecker");
	if (!test_kron(out,ctx)) goto err;
	(void)BIO_flush(out);

	message(out,"BN_mod_sqrt");
	if (!test_sqrt(out,ctx)) goto err;
	(void)BIO_flush(out);

	message(out,"Small prime generation");
	if (!test_small_prime(out,ctx)) goto err;
	(void)BIO_flush(out);

#ifndef OPENSSL_NO_EC2M
	message(out,"BN_GF2m_add");
	if (!test_gf2m_add(out)) goto err;
	(void)BIO_flush(out);

	message(out,"BN_GF2m_mod");
	if (!test_gf2m_mod(out)) goto err;
	(void)BIO_flush(out);

	message(out,"BN_GF2m_mod_mul");
	if (!test_gf2m_mod_mul(out,ctx)) goto err;
	(void)BIO_flush(out);

	message(out,"BN_GF2m_mod_sqr");
	if (!test_gf2m_mod_sqr(out,ctx)) goto err;
	(void)BIO_flush(out);

	message(out,"BN_GF2m_mod_inv");
	if (!test_gf2m_mod_inv(out,ctx)) goto err;
	(void)BIO_flush(out);

	message(out,"BN_GF2m_mod_div");
	if (!test_gf2m_mod_div(out,ctx)) goto err;
	(void)BIO_flush(out);

	message(out,"BN_GF2m_mod_exp");
	if (!test_gf2m_mod_exp(out,ctx)) goto err;
	(void)BIO_flush(out);

	message(out,"BN_GF2m_mod_sqrt");
	if (!test_gf2m_mod_sqrt(out,ctx)) goto err;
	(void)BIO_flush(out);

	message(out,"BN_GF2m_mod_solve_quad");
	if (!test_gf2m_mod_solve_quad(out,ctx)) goto err;
	(void)BIO_flush(out);
#endif
	BN_CTX_free(ctx);
	BIO_free(out);

/**/
	EXIT(0);
err:
	BIO_puts(out,"1\n"); /* make sure the Perl script fed by bc notices
	                      * the failure, see test_bn in test/Makefile.ssl*/
	(void)BIO_flush(out);
	ERR_load_crypto_strings();
	ERR_print_errors_fp(stderr);
	EXIT(1);
	return(1);
	}
Ejemplo n.º 27
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 (!BN_mod_inverse(k, k, order, ctx))
	{
		ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, 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);
}
Ejemplo n.º 28
0
/* Actually there is no reason to insist that 'generator' be a generator.
 * It's just as OK (and in some sense better) to use a generator of the
 * order-q subgroup.
 */
static int dh_builtin_genparams(DH *ret, int prime_len, int generator, BN_GENCB *cb)
{
    BIGNUM *t1, *t2;
    int g, ok = -1;
    BN_CTX *ctx = NULL;

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

    /* Make sure 'ret' has the necessary elements */
    if (!ret->p && ((ret->p = BN_new()) == NULL))
        goto err;
    if (!ret->g && ((ret->g = BN_new()) == NULL))
        goto err;

    if (generator <= 1) {
        DHerr(DH_F_DH_BUILTIN_GENPARAMS, DH_R_BAD_GENERATOR);
        goto err;
    }
    if (generator == DH_GENERATOR_2) {
        if (!BN_set_word(t1, 24))
            goto err;
        if (!BN_set_word(t2, 11))
            goto err;
        g = 2;
    } else if (generator == DH_GENERATOR_5) {
        if (!BN_set_word(t1, 10))
            goto err;
        if (!BN_set_word(t2, 3))
            goto err;
        /* BN_set_word(t3,7); just have to miss
         * out on these ones :-( */
        g = 5;
    } else {
        /* in the general case, don't worry if 'generator' is a
         * generator or not: since we are using safe primes,
         * it will generate either an order-q or an order-2q group,
         * which both is OK */
        if (!BN_set_word(t1, 2))
            goto err;
        if (!BN_set_word(t2, 1))
            goto err;
        g = generator;
    }

    if (!BN_generate_prime_ex(ret->p, prime_len, 1, t1, t2, cb))
        goto err;
    if (!BN_GENCB_call(cb, 3, 0))
        goto err;
    if (!BN_set_word(ret->g, g))
        goto err;
    ok = 1;
err:
    if (ok == -1) {
        DHerr(DH_F_DH_BUILTIN_GENPARAMS, ERR_R_BN_LIB);
        ok = 0;
    }

    if (ctx != NULL) {
        BN_CTX_end(ctx);
        BN_CTX_free(ctx);
    }
    return ok;
}
Ejemplo n.º 29
0
int EC_KEY_check_key(const EC_KEY *eckey)
{
    int ok = 0;
    BN_CTX *ctx = NULL;
    const 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 (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key)) {
        ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_POINT_AT_INFINITY);
        goto err;
    }

    if ((ctx = BN_CTX_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 */
    order = eckey->group->order;
    if (BN_is_zero(order)) {
        ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_INVALID_GROUP_ORDER);
        goto err;
    }
    if (!EC_POINT_mul(eckey->group, point, NULL, eckey->pub_key, order, 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);
    EC_POINT_free(point);
    return (ok);
}
Ejemplo n.º 30
0
static DSA_SIG *dsa_do_sign(const unsigned char *dgst, FIPS_DSA_SIZE_T dlen, DSA *dsa)
	{
	BIGNUM *kinv=NULL,*r=NULL,*s=NULL;
	BIGNUM m;
	BIGNUM xr;
	BN_CTX *ctx=NULL;
	int i,reason=ERR_R_BN_LIB;
	DSA_SIG *ret=NULL;

	if(FIPS_selftest_failed())
	    {
	    FIPSerr(FIPS_F_DSA_DO_SIGN,FIPS_R_FIPS_SELFTEST_FAILED);
	    return NULL;
	    }

	if (FIPS_mode() && (BN_num_bits(dsa->p) < OPENSSL_DSA_FIPS_MIN_MODULUS_BITS))
		{
		DSAerr(DSA_F_DSA_DO_SIGN, DSA_R_KEY_SIZE_TOO_SMALL);
		return NULL;
		}

	BN_init(&m);
	BN_init(&xr);

	if (!dsa->p || !dsa->q || !dsa->g)
		{
		reason=DSA_R_MISSING_PARAMETERS;
		goto err;
		}

	s=BN_new();
	if (s == NULL) goto err;

	i=BN_num_bytes(dsa->q); /* should be 20 */
	if ((dlen > i) || (dlen > 50))
		{
		reason=DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE;
		goto err;
		}

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

	if (!dsa->meth->dsa_sign_setup(dsa,ctx,&kinv,&r)) goto err;

	if (BN_bin2bn(dgst,dlen,&m) == NULL) goto err;

	/* Compute  s = inv(k) (m + xr) mod q */
	if (!BN_mod_mul(&xr,dsa->priv_key,r,dsa->q,ctx)) goto err;/* s = xr */
	if (!BN_add(s, &xr, &m)) goto err;		/* s = m + xr */
	if (BN_cmp(s,dsa->q) > 0)
		BN_sub(s,s,dsa->q);
	if (!BN_mod_mul(s,s,kinv,dsa->q,ctx)) goto err;

	ret= DSA_SIG_new();
	if (ret == NULL) goto err;
	ret->r = r;
	ret->s = s;
	
err:
	if (!ret)
		{
		DSAerr(DSA_F_DSA_DO_SIGN,reason);
		BN_free(r);
		BN_free(s);
		}
	if (ctx != NULL) BN_CTX_free(ctx);
	BN_clear_free(&m);
	BN_clear_free(&xr);
	if (kinv != NULL) /* dsa->kinv is NULL now if we used it */
	    BN_clear_free(kinv);
	return(ret);
	}