Пример #1
0
static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
                            BIGNUM **kinvp, BIGNUM **rp,
                            const unsigned char *dgst, int dlen)
{
    BN_CTX *ctx = NULL;
    BIGNUM *k = NULL, *r = NULL, *X = NULL;
    const BIGNUM *order;
    EC_POINT *tmp_point = NULL;
    const EC_GROUP *group;
    int ret = 0;
    int order_bits;

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

    if (!EC_KEY_can_sign(eckey)) {
        ECerr(EC_F_ECDSA_SIGN_SETUP, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING);
        return 0;
    }

    if (ctx_in == NULL) {
        if ((ctx = BN_CTX_new()) == NULL) {
            ECerr(EC_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 */
    X = BN_new();
    if (k == NULL || r == NULL || X == NULL) {
        ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE);
        goto err;
    }
    if ((tmp_point = EC_POINT_new(group)) == NULL) {
        ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB);
        goto err;
    }
    order = EC_GROUP_get0_order(group);
    if (order == NULL) {
        ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB);
        goto err;
    }

    /* Preallocate space */
    order_bits = BN_num_bits(order);
    if (!BN_set_bit(k, order_bits)
        || !BN_set_bit(r, order_bits)
        || !BN_set_bit(X, order_bits))
        goto err;

    do {
        /* get random k */
        do
            if (dgst != NULL) {
                if (!BN_generate_dsa_nonce
                    (k, order, EC_KEY_get0_private_key(eckey), dgst, dlen,
                     ctx)) {
                    ECerr(EC_F_ECDSA_SIGN_SETUP,
                             EC_R_RANDOM_NUMBER_GENERATION_FAILED);
                    goto err;
                }
            } else {
                if (!BN_priv_rand_range(k, order)) {
                    ECerr(EC_F_ECDSA_SIGN_SETUP,
                             EC_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)) {
            ECerr(EC_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)) {
                ECerr(EC_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)) {
                ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB);
                goto err;
            }
        }
#endif
        if (!BN_nnmod(r, X, order, ctx)) {
            ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB);
            goto err;
        }
    }
    while (BN_is_zero(r));

    /* Check if optimized inverse is implemented */
    if (EC_GROUP_do_inverse_ord(group, k, k, ctx) == 0) {
        /* compute the inverse of k */
        if (group->mont_data != 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)) {
                ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB);
                goto err;
            }
            if (!BN_mod_sub(X, order, X, order, ctx)) {
                ECerr(EC_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,
                                           group->mont_data)) {
                ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB);
                goto err;
            }
        } else {
            if (!BN_mod_inverse(k, k, order, ctx)) {
                ECerr(EC_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 != ctx_in)
        BN_CTX_free(ctx);
    EC_POINT_free(tmp_point);
    BN_clear_free(X);
    return ret;
}
Пример #2
0
EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src)
	{
	EC_EXTRA_DATA *d;

	if (dest == NULL || src == NULL)
		{
		ECerr(EC_F_EC_KEY_COPY, ERR_R_PASSED_NULL_PARAMETER);
		return NULL;
		}
	/* copy the parameters */
	if (src->group)
		{
		const EC_METHOD *meth = EC_GROUP_method_of(src->group);
		/* clear the old group */
		if (dest->group)
			EC_GROUP_free(dest->group);
		dest->group = EC_GROUP_new(meth);
		if (dest->group == NULL)
			return NULL;
		if (!EC_GROUP_copy(dest->group, src->group))
			return NULL;
		}
	/*  copy the public key */
	if (src->pub_key && src->group)
		{
		if (dest->pub_key)
			EC_POINT_free(dest->pub_key);
		dest->pub_key = EC_POINT_new(src->group);
		if (dest->pub_key == NULL)
			return NULL;
		if (!EC_POINT_copy(dest->pub_key, src->pub_key))
			return NULL;
		}
	/* copy the private key */
	if (src->priv_key)
		{
		if (dest->priv_key == NULL)
			{
			dest->priv_key = BN_new();
			if (dest->priv_key == NULL)
				return NULL;
			}
		if (!BN_copy(dest->priv_key, src->priv_key))
			return NULL;
		}
	/* copy method/extra data */
	EC_EX_DATA_free_all_data(&dest->method_data);

	for (d = src->method_data; d != NULL; d = d->next)
		{
		void *t = d->dup_func(d->data);
		
		if (t == NULL)
			return 0;
		if (!EC_EX_DATA_set_data(&dest->method_data, t, d->dup_func, d->free_func, d->clear_free_func))
			return 0;
		}

	/* copy the rest */
	dest->enc_flag  = src->enc_flag;
	dest->conv_form = src->conv_form;
	dest->version   = src->version;
	dest->flags = src->flags;

	return dest;
	}
Пример #3
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) <= 0)
		{
		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);
	if (point != NULL)
		EC_POINT_free(point);
	return(ok);
	}
Пример #4
0
/*
 * Converts an EC_POINT to an octet string. If buf is NULL, the encoded
 * length will be returned. If the length len of buf is smaller than required
 * an error will be returned.
 */
size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point,
                                point_conversion_form_t form,
                                unsigned char *buf, size_t len, BN_CTX *ctx)
{
    size_t ret;
    BN_CTX *new_ctx = NULL;
    int used_ctx = 0;
    BIGNUM *x, *y, *yxi;
    size_t field_len, i, skip;

    if ((form != POINT_CONVERSION_COMPRESSED)
        && (form != POINT_CONVERSION_UNCOMPRESSED)
        && (form != POINT_CONVERSION_HYBRID)) {
        ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
        goto err;
    }

    if (EC_POINT_is_at_infinity(group, point)) {
        /* encodes to a single 0 octet */
        if (buf != NULL) {
            if (len < 1) {
                ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
                return 0;
            }
            buf[0] = 0;
        }
        return 1;
    }

    /* ret := required output buffer length */
    field_len = (EC_GROUP_get_degree(group) + 7) / 8;
    ret =
        (form ==
         POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len;

    /* if 'buf' is NULL, just return required length */
    if (buf != NULL) {
        if (len < ret) {
            ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
            goto err;
        }

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

        BN_CTX_start(ctx);
        used_ctx = 1;
        x = BN_CTX_get(ctx);
        y = BN_CTX_get(ctx);
        yxi = BN_CTX_get(ctx);
        if (yxi == NULL)
            goto err;

        if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx))
            goto err;

        buf[0] = form;
        if ((form != POINT_CONVERSION_UNCOMPRESSED) && !BN_is_zero(x)) {
            if (!group->meth->field_div(group, yxi, y, x, ctx))
                goto err;
            if (BN_is_odd(yxi))
                buf[0]++;
        }

        i = 1;

        skip = field_len - BN_num_bytes(x);
        if (skip > field_len) {
            ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
            goto err;
        }
        while (skip > 0) {
            buf[i++] = 0;
            skip--;
        }
        skip = BN_bn2bin(x, buf + i);
        i += skip;
        if (i != 1 + field_len) {
            ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
            goto err;
        }

        if (form == POINT_CONVERSION_UNCOMPRESSED
            || form == POINT_CONVERSION_HYBRID) {
            skip = field_len - BN_num_bytes(y);
            if (skip > field_len) {
                ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
                goto err;
            }
            while (skip > 0) {
                buf[i++] = 0;
                skip--;
            }
            skip = BN_bn2bin(y, buf + i);
            i += skip;
        }

        if (i != ret) {
            ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
            goto err;
        }
    }

    if (used_ctx)
        BN_CTX_end(ctx);
    BN_CTX_free(new_ctx);
    return ret;

 err:
    if (used_ctx)
        BN_CTX_end(ctx);
    BN_CTX_free(new_ctx);
    return 0;
}
Пример #5
0
/*-
 * Calculates and sets the affine coordinates of an EC_POINT from the given
 * compressed coordinates.  Uses algorithm 2.3.4 of SEC 1.
 * Note that the simple implementation only uses affine coordinates.
 *
 * The method is from the following publication:
 *
 *     Harper, Menezes, Vanstone:
 *     "Public-Key Cryptosystems with Very Small Key Lengths",
 *     EUROCRYPT '92, Springer-Verlag LNCS 658,
 *     published February 1993
 *
 * US Patents 6,141,420 and 6,618,483 (Vanstone, Mullin, Agnew) describe
 * the same method, but claim no priority date earlier than July 29, 1994
 * (and additionally fail to cite the EUROCRYPT '92 publication as prior art).
 */
int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group,
                                              EC_POINT *point,
                                              const BIGNUM *x_, int y_bit,
                                              BN_CTX *ctx)
{
    BN_CTX *new_ctx = NULL;
    BIGNUM *tmp, *x, *y, *z;
    int ret = 0, z0;

    /* clear error queue */
    ERR_clear_error();

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

    y_bit = (y_bit != 0) ? 1 : 0;

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

    if (!BN_GF2m_mod_arr(x, x_, group->poly))
        goto err;
    if (BN_is_zero(x)) {
        if (!BN_GF2m_mod_sqrt_arr(y, group->b, group->poly, ctx))
            goto err;
    } else {
        if (!group->meth->field_sqr(group, tmp, x, ctx))
            goto err;
        if (!group->meth->field_div(group, tmp, group->b, tmp, ctx))
            goto err;
        if (!BN_GF2m_add(tmp, group->a, tmp))
            goto err;
        if (!BN_GF2m_add(tmp, x, tmp))
            goto err;
        if (!BN_GF2m_mod_solve_quad_arr(z, tmp, group->poly, ctx)) {
            unsigned long err = ERR_peek_last_error();

            if (ERR_GET_LIB(err) == ERR_LIB_BN
                && ERR_GET_REASON(err) == BN_R_NO_SOLUTION) {
                ERR_clear_error();
                ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES,
                      EC_R_INVALID_COMPRESSED_POINT);
            } else
                ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES,
                      ERR_R_BN_LIB);
            goto err;
        }
        z0 = (BN_is_odd(z)) ? 1 : 0;
        if (!group->meth->field_mul(group, y, x, z, ctx))
            goto err;
        if (z0 != y_bit) {
            if (!BN_GF2m_add(y, y, x))
                goto err;
        }
    }

    if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx))
        goto err;

    ret = 1;

 err:
    BN_CTX_end(ctx);
    BN_CTX_free(new_ctx);
    return ret;
}
Пример #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;
		}

	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;
			}

		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 */
			{
			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) && !print(bp, "Polynomial:", p, buffer,
				off))
				goto err;
			}
		else
			{
			if ((p != NULL) && !print(bp, "Prime:", p, buffer,off))
				goto err;
			}
		if ((a != NULL) && !print(bp, "A:   ", a, buffer, off)) 
			goto err;
		if ((b != NULL) && !print(bp, "B:   ", b, buffer, off))
			goto err;
		if (form == POINT_CONVERSION_COMPRESSED)
			{
			if ((gen != NULL) && !print(bp, gen_compressed, gen,
				buffer, off))
				goto err;
			}
		else if (form == POINT_CONVERSION_UNCOMPRESSED)
			{
			if ((gen != NULL) && !print(bp, gen_uncompressed, gen,
				buffer, off))
				goto err;
			}
		else /* form == POINT_CONVERSION_HYBRID */
			{
			if ((gen != NULL) && !print(bp, gen_hybrid, gen,
				buffer, off))
				goto err;
			}
		if ((order != NULL) && !print(bp, "Order: ", order, 
			buffer, off)) goto err;
		if ((cofactor != NULL) && !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);	
	}
Пример #7
0
int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
	{
	EC_EXTRA_DATA *d;

	if (dest->meth->group_copy == 0)
		{
		ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
		return 0;
		}
	if (dest->meth != src->meth)
		{
		ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS);
		return 0;
		}
	if (dest == src)
		return 1;
	
	EC_EX_DATA_free_all_data(&dest->extra_data);

	for (d = src->extra_data; d != NULL; d = d->next)
		{
		void *t = d->dup_func(d->data);
		
		if (t == NULL)
			return 0;
		if (!EC_EX_DATA_set_data(&dest->extra_data, t, d->dup_func, d->free_func, d->clear_free_func))
			return 0;
		}

	if (src->generator != NULL)
		{
		if (dest->generator == NULL)
			{
			dest->generator = EC_POINT_new(dest);
			if (dest->generator == NULL) return 0;
			}
		if (!EC_POINT_copy(dest->generator, src->generator)) return 0;
		}
	else
		{
		/* src->generator == NULL */
		if (dest->generator != NULL)
			{
			EC_POINT_clear_free(dest->generator);
			dest->generator = NULL;
			}
		}

	if (!BN_copy(&dest->order, &src->order)) return 0;
	if (!BN_copy(&dest->cofactor, &src->cofactor)) return 0;

	dest->curve_name = src->curve_name;
	dest->asn1_flag  = src->asn1_flag;
	dest->asn1_form  = src->asn1_form;

	if (src->seed)
		{
		if (dest->seed)
			OPENSSL_free(dest->seed);
		dest->seed = clBnAlloc( "EC_GROUP_copy",src->seed_len);		/* pcg */
		if (dest->seed == NULL)
			return 0;
		if (!memcpy(dest->seed, src->seed, src->seed_len))
			return 0;
		dest->seed_len = src->seed_len;
		}
	else
		{
		if (dest->seed)
			OPENSSL_free(dest->seed);
		dest->seed = NULL;
		dest->seed_len = 0;
		}
	

	return dest->meth->group_copy(dest, src);
	}
Пример #8
0
/* Determine the modified width-(w+1) Non-Adjacent Form (wNAF) of 'scalar'.
 * This is an array  r[]  of values that are either zero or odd with an
 * absolute value less than  2^w  satisfying
 *     scalar = \sum_j r[j]*2^j
 * where at most one of any  w+1  consecutive digits is non-zero
 * with the exception that the most significant digit may be only
 * w-1 zeros away from that next non-zero digit.
 */
static signed char *
compute_wNAF(const BIGNUM * scalar, int w, size_t * ret_len)
{
	int window_val;
	int ok = 0;
	signed char *r = NULL;
	int sign = 1;
	int bit, next_bit, mask;
	size_t len = 0, j;

	if (BN_is_zero(scalar)) {
		r = malloc(1);
		if (!r) {
			ECerr(EC_F_COMPUTE_WNAF, ERR_R_MALLOC_FAILURE);
			goto err;
		}
		r[0] = 0;
		*ret_len = 1;
		return r;
	}
	if (w <= 0 || w > 7) {
		/* 'signed char' can represent integers with
		 * absolute values less than 2^7 */
		ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR);
		goto err;
	}
	bit = 1 << w;		/* at most 128 */
	next_bit = bit << 1;	/* at most 256 */
	mask = next_bit - 1;	/* at most 255 */

	if (BN_is_negative(scalar)) {
		sign = -1;
	}
	if (scalar->d == NULL || scalar->top == 0) {
		ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR);
		goto err;
	}
	len = BN_num_bits(scalar);
	r = malloc(len + 1);	/* modified wNAF may be one digit longer than
				 * binary representation (*ret_len will be
				 * set to the actual length, i.e. at most
				 * BN_num_bits(scalar) + 1) */
	if (r == NULL) {
		ECerr(EC_F_COMPUTE_WNAF, ERR_R_MALLOC_FAILURE);
		goto err;
	}
	window_val = scalar->d[0] & mask;
	j = 0;
	while ((window_val != 0) || (j + w + 1 < len)) {
		/* if j+w+1 >= len, window_val will not increase */
		int digit = 0;

		/* 0 <= window_val <= 2^(w+1) */
		if (window_val & 1) {
			/* 0 < window_val < 2^(w+1) */
			if (window_val & bit) {
				digit = window_val - next_bit;	/* -2^w < digit < 0 */

#if 1				/* modified wNAF */
				if (j + w + 1 >= len) {
					/*
					 * special case for generating
					 * modified wNAFs: no new bits will
					 * be added into window_val, so using
					 * a positive digit here will
					 * decrease the total length of the
					 * representation
					 */

					digit = window_val & (mask >> 1);	/* 0 < digit < 2^w */
				}
#endif
			} else {
Пример #9
0
static EC_GROUP *ec_group_new_from_data(const ec_list_element curve)
{
    EC_GROUP *group = NULL;
    EC_POINT *P = NULL;
    BN_CTX *ctx = NULL;
    BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL, *order =
        NULL;
    int ok = 0;
    int seed_len, param_len;
    const EC_METHOD *meth;
    const EC_CURVE_DATA *data;
    const unsigned char *params;

    /* If no curve data curve method must handle everything */
    if (curve.data == NULL)
        return EC_GROUP_new(curve.meth != NULL ? curve.meth() : NULL);

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

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

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

    if (curve.meth != 0) {
        meth = curve.meth();
        if (((group = EC_GROUP_new(meth)) == NULL) ||
            (!(group->meth->group_set_curve(group, p, a, b, ctx)))) {
            ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
            goto err;
        }
    } else if (data->field_type == NID_X9_62_prime_field) {
        if ((group = EC_GROUP_new_curve_GFp(p, a, b, ctx)) == NULL) {
            ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
            goto err;
        }
    }
#ifndef OPENSSL_NO_EC2M
    else {                      /* field_type ==
                                 * NID_X9_62_characteristic_two_field */

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

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

    if ((x = BN_bin2bn(params + 3 * param_len, param_len, NULL)) == NULL
        || (y = BN_bin2bn(params + 4 * param_len, param_len, NULL)) == NULL) {
        ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB);
        goto err;
    }
    if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) {
        ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
        goto err;
    }
    if ((order = BN_bin2bn(params + 5 * param_len, param_len, NULL)) == NULL
        || !BN_set_word(x, (BN_ULONG)data->cofactor)) {
        ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB);
        goto err;
    }
    if (!EC_GROUP_set_generator(group, P, order, x)) {
        ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
        goto err;
    }
    if (seed_len) {
        if (!EC_GROUP_set_seed(group, params - seed_len, seed_len)) {
            ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
            goto err;
        }
    }
    ok = 1;
 err:
    if (!ok) {
        EC_GROUP_free(group);
        group = NULL;
    }
    EC_POINT_free(P);
    BN_CTX_free(ctx);
    BN_free(p);
    BN_free(a);
    BN_free(b);
    BN_free(order);
    BN_free(x);
    BN_free(y);
    return group;
}
Пример #10
0
static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
{
    EC_PKEY_CTX *dctx = ctx->data;
    EC_GROUP *group;
    switch (type) {
    case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID:
        group = EC_GROUP_new_by_curve_name(p1);
        if (group == NULL) {
            ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_CURVE);
            return 0;
        }
        EC_GROUP_free(dctx->gen_group);
        dctx->gen_group = group;
        return 1;

    case EVP_PKEY_CTRL_EC_PARAM_ENC:
        if (!dctx->gen_group) {
            ECerr(EC_F_PKEY_EC_CTRL, EC_R_NO_PARAMETERS_SET);
            return 0;
        }
        EC_GROUP_set_asn1_flag(dctx->gen_group, p1);
        return 1;

#ifndef OPENSSL_NO_EC
    case EVP_PKEY_CTRL_EC_ECDH_COFACTOR:
        if (p1 == -2) {
            if (dctx->cofactor_mode != -1)
                return dctx->cofactor_mode;
            else {
                EC_KEY *ec_key = ctx->pkey->pkey.ec;
                return EC_KEY_get_flags(ec_key) & EC_FLAG_COFACTOR_ECDH ? 1 :
                    0;
            }
        } else if (p1 < -1 || p1 > 1)
            return -2;
        dctx->cofactor_mode = p1;
        if (p1 != -1) {
            EC_KEY *ec_key = ctx->pkey->pkey.ec;
            if (!ec_key->group)
                return -2;
            /* If cofactor is 1 cofactor mode does nothing */
            if (BN_is_one(ec_key->group->cofactor))
                return 1;
            if (!dctx->co_key) {
                dctx->co_key = EC_KEY_dup(ec_key);
                if (!dctx->co_key)
                    return 0;
            }
            if (p1)
                EC_KEY_set_flags(dctx->co_key, EC_FLAG_COFACTOR_ECDH);
            else
                EC_KEY_clear_flags(dctx->co_key, EC_FLAG_COFACTOR_ECDH);
        } else {
            EC_KEY_free(dctx->co_key);
            dctx->co_key = NULL;
        }
        return 1;
#endif

    case EVP_PKEY_CTRL_EC_KDF_TYPE:
        if (p1 == -2)
            return dctx->kdf_type;
        if (p1 != EVP_PKEY_ECDH_KDF_NONE && p1 != EVP_PKEY_ECDH_KDF_X9_62)
            return -2;
        dctx->kdf_type = p1;
        return 1;

#ifndef OPENSSL_NO_SM2
    case EVP_PKEY_CTRL_EC_SCHEME:
        if (p1 == -2) {
            return dctx->ec_scheme;
        }
        if (p1 != NID_secg_scheme && p1 != NID_sm_scheme) {
            ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_EC_SCHEME);
            return 0;
        }
        dctx->ec_scheme = p1;
        return 1;

    case EVP_PKEY_CTRL_SIGNER_ID:
        if (!p2 || !strlen((char *)p2) || strlen((char *)p2) > SM2_MAX_ID_LENGTH) {
            ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_SIGNER_ID);
            return 0;
        } else {
            char *id = NULL;
            if (!(id = OPENSSL_strdup((char *)p2))) {
                ECerr(EC_F_PKEY_EC_CTRL, ERR_R_MALLOC_FAILURE);
                return 0;
            }
            if (dctx->signer_id)
                OPENSSL_free(dctx->signer_id);
            dctx->signer_id = id;
            if (dctx->ec_scheme == NID_sm_scheme) {
                EC_KEY *ec_key = ctx->pkey->pkey.ec;
                unsigned char zid[SM3_DIGEST_LENGTH];
                size_t zidlen = SM3_DIGEST_LENGTH;
                if (!SM2_compute_id_digest(EVP_sm3(), dctx->signer_id,
                    strlen(dctx->signer_id), zid, &zidlen, ec_key)) {
                    ECerr(EC_F_PKEY_EC_CTRL, ERR_R_SM2_LIB);
                    return 0;
                }
                if (!dctx->signer_zid) {
                    if (!(dctx->signer_zid = OPENSSL_malloc(zidlen))) {
                        ECerr(EC_F_PKEY_EC_CTRL, ERR_R_MALLOC_FAILURE);
                        return 0;
                    }
                }
                memcpy(dctx->signer_zid, zid, zidlen);
            }
        }
        return 1;

    case EVP_PKEY_CTRL_GET_SIGNER_ID:
        *(const char **)p2 = dctx->signer_id;
        return 1;

    case EVP_PKEY_CTRL_GET_SIGNER_ZID:
        if (dctx->ec_scheme != NID_sm_scheme) {
            *(const unsigned char **)p2 = NULL;
            return -2;
        }
        if (!dctx->signer_zid) {
            EC_KEY *ec_key = ctx->pkey->pkey.ec;
            unsigned char *zid;
            size_t zidlen = SM3_DIGEST_LENGTH;
            if (!(zid = OPENSSL_malloc(zidlen))) {
                ECerr(EC_F_PKEY_EC_CTRL, ERR_R_MALLOC_FAILURE);
                return 0;
            }
            if (!SM2_compute_id_digest(EVP_sm3(), SM2_DEFAULT_ID,
                SM2_DEFAULT_ID_LENGTH, zid, &zidlen, ec_key)) {
                ECerr(EC_F_PKEY_EC_CTRL, ERR_R_SM2_LIB);
                OPENSSL_free(zid);
                return 0;
            }
            dctx->signer_zid = zid;
        }
        *(const unsigned char **)p2 = dctx->signer_zid;
        return 1;

    case EVP_PKEY_CTRL_EC_ENCRYPT_PARAM:
        if (p1 == -2) {
            return dctx->ec_encrypt_param;
        }
        dctx->ec_encrypt_param = p1;
        return 1;
#endif

    case EVP_PKEY_CTRL_EC_KDF_MD:
        dctx->kdf_md = p2;
        return 1;

    case EVP_PKEY_CTRL_GET_EC_KDF_MD:
        *(const EVP_MD **)p2 = dctx->kdf_md;
        return 1;

    case EVP_PKEY_CTRL_EC_KDF_OUTLEN:
        if (p1 <= 0)
            return -2;
        dctx->kdf_outlen = (size_t)p1;
        return 1;

    case EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN:
        *(int *)p2 = dctx->kdf_outlen;
        return 1;

    case EVP_PKEY_CTRL_EC_KDF_UKM:
        OPENSSL_free(dctx->kdf_ukm);
        dctx->kdf_ukm = p2;
        if (p2)
            dctx->kdf_ukmlen = p1;
        else
            dctx->kdf_ukmlen = 0;
        return 1;

    case EVP_PKEY_CTRL_GET_EC_KDF_UKM:
        *(unsigned char **)p2 = dctx->kdf_ukm;
        return dctx->kdf_ukmlen;

    case EVP_PKEY_CTRL_MD:
        if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 &&
#ifndef OPENSSL_NO_SM3
            EVP_MD_type((const EVP_MD *)p2) != NID_sm3 &&
#endif
            EVP_MD_type((const EVP_MD *)p2) != NID_ecdsa_with_SHA1 &&
            EVP_MD_type((const EVP_MD *)p2) != NID_sha224 &&
            EVP_MD_type((const EVP_MD *)p2) != NID_sha256 &&
            EVP_MD_type((const EVP_MD *)p2) != NID_sha384 &&
            EVP_MD_type((const EVP_MD *)p2) != NID_sha512) {
            ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_DIGEST_TYPE);
            return 0;
        }
        dctx->md = p2;
        return 1;

    case EVP_PKEY_CTRL_GET_MD:
        *(const EVP_MD **)p2 = dctx->md;
        return 1;

    case EVP_PKEY_CTRL_PEER_KEY:
        /* Default behaviour is OK */
    case EVP_PKEY_CTRL_DIGESTINIT:
    case EVP_PKEY_CTRL_PKCS7_SIGN:
    case EVP_PKEY_CTRL_CMS_SIGN:
        return 1;

    default:
        return -2;

    }
}
Пример #11
0
/* Setup EVP_PKEY using public, private or generation */
static int ecx_key_op(EVP_PKEY *pkey, int id, const X509_ALGOR *palg,
                      const unsigned char *p, int plen, ecx_key_op_t op)
{
    ECX_KEY *key = NULL;
    unsigned char *privkey, *pubkey;

    if (op != KEY_OP_KEYGEN) {
        if (palg != NULL) {
            int ptype;

            /* Algorithm parameters must be absent */
            X509_ALGOR_get0(NULL, &ptype, NULL, palg);
            if (ptype != V_ASN1_UNDEF) {
                ECerr(EC_F_ECX_KEY_OP, EC_R_INVALID_ENCODING);
                return 0;
            }
        }

        if (p == NULL || plen != KEYLENID(id)) {
            ECerr(EC_F_ECX_KEY_OP, EC_R_INVALID_ENCODING);
            return 0;
        }
    }

    key = OPENSSL_zalloc(sizeof(*key));
    if (key == NULL) {
        ECerr(EC_F_ECX_KEY_OP, ERR_R_MALLOC_FAILURE);
        return 0;
    }
    pubkey = key->pubkey;

    if (op == KEY_OP_PUBLIC) {
        memcpy(pubkey, p, plen);
    } else {
        privkey = key->privkey = OPENSSL_secure_malloc(KEYLENID(id));
        if (privkey == NULL) {
            ECerr(EC_F_ECX_KEY_OP, ERR_R_MALLOC_FAILURE);
            goto err;
        }
        if (op == KEY_OP_KEYGEN) {
            if (RAND_priv_bytes(privkey, KEYLENID(id)) <= 0) {
                OPENSSL_secure_free(privkey);
                key->privkey = NULL;
                goto err;
            }
            if (id == EVP_PKEY_X25519) {
                privkey[0] &= 248;
                privkey[X25519_KEYLEN - 1] &= 127;
                privkey[X25519_KEYLEN - 1] |= 64;
            } else if (id == EVP_PKEY_X448) {
                privkey[0] &= 252;
                privkey[X448_KEYLEN - 1] |= 128;
            }
        } else {
            memcpy(privkey, p, KEYLENID(id));
        }
        switch (id) {
        case EVP_PKEY_X25519:
            X25519_public_from_private(pubkey, privkey);
            break;
        case EVP_PKEY_ED25519:
            ED25519_public_from_private(pubkey, privkey);
            break;
        case EVP_PKEY_X448:
            X448_public_from_private(pubkey, privkey);
            break;
        case EVP_PKEY_ED448:
            ED448_public_from_private(pubkey, privkey);
            break;
        }
    }

    EVP_PKEY_assign(pkey, id, key);
    return 1;
 err:
    OPENSSL_free(key);
    return 0;
}
Пример #12
0
static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, ec_print_t ktype)
{
    const char *ecstr;
    unsigned char *priv = NULL, *pub = NULL;
    size_t privlen = 0, publen = 0;
    int ret = 0;
    const EC_GROUP *group;

    if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) {
        ECerr(EC_F_DO_EC_KEY_PRINT, ERR_R_PASSED_NULL_PARAMETER);
        return 0;
    }

    if (ktype != EC_KEY_PRINT_PARAM && EC_KEY_get0_public_key(x) != NULL) {
        publen = EC_KEY_key2buf(x, EC_KEY_get_conv_form(x), &pub, NULL);
        if (publen == 0)
            goto err;
    }

    if (ktype == EC_KEY_PRINT_PRIVATE && EC_KEY_get0_private_key(x) != NULL) {
        privlen = EC_KEY_priv2buf(x, &priv);
        if (privlen == 0)
            goto err;
    }

    if (ktype == EC_KEY_PRINT_PRIVATE)
        ecstr = "Private-Key";
    else if (ktype == EC_KEY_PRINT_PUBLIC)
        ecstr = "Public-Key";
    else
        ecstr = "ECDSA-Parameters";

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

    if (privlen != 0) {
        if (BIO_printf(bp, "%*spriv:\n", off, "") <= 0)
            goto err;
        if (ASN1_buf_print(bp, priv, privlen, off + 4) == 0)
            goto err;
    }

    if (publen != 0) {
        if (BIO_printf(bp, "%*spub:\n", off, "") <= 0)
            goto err;
        if (ASN1_buf_print(bp, pub, publen, off + 4) == 0)
            goto err;
    }

    if (!ECPKParameters_print(bp, group, off))
        goto err;
    ret = 1;
 err:
    if (!ret)
        ECerr(EC_F_DO_EC_KEY_PRINT, ERR_R_EC_LIB);
    OPENSSL_clear_free(priv, privlen);
    OPENSSL_free(pub);
    return ret;
}
Пример #13
0
/*-
 * This implementation is based on the following primitives in the IEEE 1363 standard:
 *  - ECKAS-DH1
 *  - ECSVDP-DH
 * Finally an optional KDF is applied.
 */
int ossl_ecdh_compute_key(void *out, size_t outlen, const EC_POINT *pub_key,
                          const EC_KEY *ecdh,
                          void *(*KDF) (const void *in, size_t inlen,
                                        void *out, size_t *outlen))
{
    BN_CTX *ctx;
    EC_POINT *tmp = NULL;
    BIGNUM *x = NULL, *y = NULL;
    const BIGNUM *priv_key;
    const EC_GROUP *group;
    int ret = -1;
    size_t buflen, len;
    unsigned char *buf = NULL;

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

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

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

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

    group = EC_KEY_get0_group(ecdh);

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

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

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

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

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

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

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

 err:
    EC_POINT_free(tmp);
    if (ctx)
        BN_CTX_end(ctx);
    BN_CTX_free(ctx);
    OPENSSL_free(buf);
    return (ret);
}
Пример #14
0
int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len,
                          const ECDSA_SIG *sig, EC_KEY *eckey)
{
    int ret = -1, i;
    BN_CTX *ctx;
    const BIGNUM *order;
    BIGNUM *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) {
        ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, EC_R_MISSING_PARAMETERS);
        return -1;
    }

    if (!EC_KEY_can_sign(eckey)) {
        ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING);
        return -1;
    }

    ctx = BN_CTX_new();
    if (ctx == NULL) {
        ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_MALLOC_FAILURE);
        return -1;
    }
    BN_CTX_start(ctx);
    u1 = BN_CTX_get(ctx);
    u2 = BN_CTX_get(ctx);
    m = BN_CTX_get(ctx);
    X = BN_CTX_get(ctx);
    if (X == NULL) {
        ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB);
        goto err;
    }

    order = EC_GROUP_get0_order(group);
    if (order == NULL) {
        ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, 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) {
        ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, EC_R_BAD_SIGNATURE);
        ret = 0;                /* signature is invalid */
        goto err;
    }
    /* calculate tmp1 = inv(S) mod order */
    /* Check if optimized inverse is implemented */
    if (EC_GROUP_do_inverse_ord(group, u2, sig->s, ctx) == 0) {
        if (!BN_mod_inverse(u2, sig->s, order, ctx)) {
            ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, 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)) {
        ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, 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))) {
        ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB);
        goto err;
    }
    /* u1 = m * tmp mod order */
    if (!BN_mod_mul(u1, m, u2, order, ctx)) {
        ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB);
        goto err;
    }
    /* u2 = r * w mod q */
    if (!BN_mod_mul(u2, sig->r, u2, order, ctx)) {
        ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB);
        goto err;
    }

    if ((point = EC_POINT_new(group)) == NULL) {
        ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_MALLOC_FAILURE);
        goto err;
    }
    if (!EC_POINT_mul(group, point, u1, pub_key, u2, ctx)) {
        ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, 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)) {
            ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, 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)) {
            ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_EC_LIB);
            goto err;
        }
    }
#endif
    if (!BN_nnmod(u1, X, order, ctx)) {
        ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, 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;
}
Пример #15
0
static int 
eckey_priv_decode(EVP_PKEY * pkey, PKCS8_PRIV_KEY_INFO * p8)
{
	const unsigned char *p = NULL;
	void *pval;
	int ptype, pklen;
	EC_KEY *eckey = NULL;
	X509_ALGOR *palg;

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

	eckey = eckey_type2param(ptype, pval);

	if (!eckey)
		goto ecliberr;

	/* We have parameters now set private key */
	if (!d2i_ECPrivateKey(&eckey, &p, pklen)) {
		ECerr(EC_F_ECKEY_PRIV_DECODE, EC_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) {
			ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
			goto ecliberr;
		}
		if (!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group))) {
			EC_POINT_free(pub_key);
			ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
			goto ecliberr;
		}
		priv_key = EC_KEY_get0_private_key(eckey);
		if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, NULL)) {
			EC_POINT_free(pub_key);
			ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
			goto ecliberr;
		}
		if (EC_KEY_set_public_key(eckey, pub_key) == 0) {
			EC_POINT_free(pub_key);
			ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
			goto ecliberr;
		}
		EC_POINT_free(pub_key);
	}
	EVP_PKEY_assign_EC_KEY(pkey, eckey);
	return 1;

ecliberr:
	ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
ecerr:
	if (eckey)
		EC_KEY_free(eckey);
	return 0;
}
Пример #16
0
EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src)
{
    if (dest == NULL || src == NULL) {
        ECerr(EC_F_EC_KEY_COPY, ERR_R_PASSED_NULL_PARAMETER);
        return NULL;
    }
    if (src->meth != dest->meth) {
        if (dest->meth->finish != NULL)
            dest->meth->finish(dest);
        if (dest->group && dest->group->meth->keyfinish)
            dest->group->meth->keyfinish(dest);
#ifndef OPENSSL_NO_ENGINE
        if (ENGINE_finish(dest->engine) == 0)
            return 0;
        dest->engine = NULL;
#endif
    }
    /* copy the parameters */
    if (src->group != NULL) {
        const EC_METHOD *meth = EC_GROUP_method_of(src->group);
        /* clear the old group */
        EC_GROUP_free(dest->group);
        dest->group = EC_GROUP_new(meth);
        if (dest->group == NULL)
            return NULL;
        if (!EC_GROUP_copy(dest->group, src->group))
            return NULL;

        /*  copy the public key */
        if (src->pub_key != NULL) {
            EC_POINT_free(dest->pub_key);
            dest->pub_key = EC_POINT_new(src->group);
            if (dest->pub_key == NULL)
                return NULL;
            if (!EC_POINT_copy(dest->pub_key, src->pub_key))
                return NULL;
        }
        /* copy the private key */
        if (src->priv_key != NULL) {
            if (dest->priv_key == NULL) {
                dest->priv_key = BN_new();
                if (dest->priv_key == NULL)
                    return NULL;
            }
            if (!BN_copy(dest->priv_key, src->priv_key))
                return NULL;
            if (src->group->meth->keycopy
                && src->group->meth->keycopy(dest, src) == 0)
                return NULL;
        }
    }


    /* copy the rest */
    dest->enc_flag = src->enc_flag;
    dest->conv_form = src->conv_form;
    dest->version = src->version;
    dest->flags = src->flags;
    if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_EC_KEY,
                            &dest->ex_data, &src->ex_data))
        return NULL;

    if (src->meth != dest->meth) {
#ifndef OPENSSL_NO_ENGINE
        if (src->engine != NULL && ENGINE_init(src->engine) == 0)
            return NULL;
        dest->engine = src->engine;
#endif
        dest->meth = src->meth;
    }

    if (src->meth->copy != NULL && src->meth->copy(dest, src) == 0)
        return NULL;

    return dest;
}
Пример #17
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 ((pub_key = EC_POINT_point2bn(group, public_key,
			    EC_KEY_get_conv_form(x), NULL, ctx)) == NULL) {
			reason = ERR_R_EC_LIB;
			goto err;
		}
		if (pub_key)
			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 = 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);
	BN_free(pub_key);
	BN_free(order);
	BN_CTX_free(ctx);
	free(buffer);
	return (ret);
}
Пример #18
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 *tmp0, *tmp1;
	size_t pow2 = 0;
	BIGNUM **heap = 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);
	tmp0 = BN_CTX_get(ctx);
	tmp1 = BN_CTX_get(ctx);
	if (tmp0  == NULL || tmp1 == NULL) goto err;

	/* Before converting the individual points, compute inverses of all Z values.
	 * Modular inversion is rather slow, but luckily we can do with a single
	 * explicit inversion, plus about 3 multiplications per input value.
	 */

	pow2 = 1;
	while (num > pow2)
		pow2 <<= 1;
	/* Now pow2 is the smallest power of 2 satifsying pow2 >= num.
	 * We need twice that. */
	pow2 <<= 1;

	heap = OPENSSL_malloc(pow2 * sizeof heap[0]);
	if (heap == NULL) goto err;
	
	/* The array is used as a binary tree, exactly as in heapsort:
	 *
	 *                               heap[1]
	 *                 heap[2]                     heap[3]
	 *          heap[4]       heap[5]       heap[6]       heap[7]
	 *   heap[8]heap[9] heap[10]heap[11] heap[12]heap[13] heap[14] heap[15]
	 *
	 * We put the Z's in the last line;
	 * then we set each other node to the product of its two child-nodes (where
	 * empty or 0 entries are treated as ones);
	 * then we invert heap[1];
	 * then we invert each other node by replacing it by the product of its
	 * parent (after inversion) and its sibling (before inversion).
	 */
	heap[0] = NULL;
	for (i = pow2/2 - 1; i > 0; i--)
		heap[i] = NULL;
	for (i = 0; i < num; i++)
		heap[pow2/2 + i] = &points[i]->Z;
	for (i = pow2/2 + num; i < pow2; i++)
		heap[i] = NULL;
	
	/* set each node to the product of its children */
	for (i = pow2/2 - 1; i > 0; i--)
		{
		heap[i] = BN_new();
		if (heap[i] == NULL) goto err;
		
		if (heap[2*i] != NULL)
			{
			if ((heap[2*i + 1] == NULL) || BN_is_zero(heap[2*i + 1]))
				{
				if (!BN_copy(heap[i], heap[2*i])) goto err;
				}
			else
				{
				if (BN_is_zero(heap[2*i]))
					{
					if (!BN_copy(heap[i], heap[2*i + 1])) goto err;
					}
				else
					{
					if (!group->meth->field_mul(group, heap[i],
						heap[2*i], heap[2*i + 1], ctx)) goto err;
					}
				}
			}
		}

	/* invert heap[1] */
	if (!BN_is_zero(heap[1]))
		{
		if (!BN_mod_inverse(heap[1], heap[1], &group->field, ctx))
			{
			ECerr(EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE, ERR_R_BN_LIB);
			goto err;
			}
		}
	if (group->meth->field_encode != 0)
		{
		/* 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 have need to multiply by the Montgomery factor twice */
		if (!group->meth->field_encode(group, heap[1], heap[1], ctx)) goto err;
		if (!group->meth->field_encode(group, heap[1], heap[1], ctx)) goto err;
		}

	/* set other heap[i]'s to their inverses */
	for (i = 2; i < pow2/2 + num; i += 2)
		{
		/* i is even */
		if ((heap[i + 1] != NULL) && !BN_is_zero(heap[i + 1]))
			{
			if (!group->meth->field_mul(group, tmp0, heap[i/2], heap[i + 1], ctx)) goto err;
			if (!group->meth->field_mul(group, tmp1, heap[i/2], heap[i], ctx)) goto err;
			if (!BN_copy(heap[i], tmp0)) goto err;
			if (!BN_copy(heap[i + 1], tmp1)) goto err;
			}
		else
			{
			if (!BN_copy(heap[i], heap[i/2])) goto err;
			}
		}

	/* we have replaced all non-zero Z's by their inverses, now fix up all the 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, tmp1, &p->Z, ctx)) goto err;
			if (!group->meth->field_mul(group, &p->X, &p->X, tmp1, ctx)) goto err;

			if (!group->meth->field_mul(group, tmp1, tmp1, &p->Z, ctx)) goto err;
			if (!group->meth->field_mul(group, &p->Y, &p->Y, tmp1, ctx)) goto err;
		
			if (group->meth->field_set_to_one != 0)
				{
				if (!group->meth->field_set_to_one(group, &p->Z, ctx)) goto err;
				}
			else
				{
				if (!BN_one(&p->Z)) goto err;
				}
			p->Z_is_one = 1;
			}
		}

	ret = 1;
		
 err:
	BN_CTX_end(ctx);
	if (new_ctx != NULL)
		BN_CTX_free(new_ctx);
	if (heap != NULL)
		{
		/* heap[pow2/2] .. heap[pow2-1] have not been allocated locally! */
		for (i = pow2/2 - 1; i > 0; i--)
			{
			if (heap[i] != NULL)
				BN_clear_free(heap[i]);
			}
		OPENSSL_free(heap);
		}
	return ret;
	}
Пример #19
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);
	}
Пример #20
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;
    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 (group->meth->field_set_to_one != 0) {
            if (!group->meth->field_set_to_one(group, prod_Z[0], ctx))
                goto err;
        } else {
            if (!BN_one(prod_Z[0]))
                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)) {
        ECerr(EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE, ERR_R_BN_LIB);
        goto err;
    }
    if (group->meth->field_encode != 0) {
        /*
         * 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))
            goto err;
        if (!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)) {
            /*
             * 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))
                goto err;
            /*
             * Update tmp to satisfy the loop invariant for i - 1.
             */
            if (!group->meth->field_mul(group, tmp, tmp, &points[i]->Z, ctx))
                goto err;
            /* Replace points[i]->Z by its inverse. */
            if (!BN_copy(&points[i]->Z, tmp_Z))
                goto err;
        }
    }

    if (!BN_is_zero(&points[0]->Z)) {
        /* Replace points[0]->Z by its inverse. */
        if (!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))
                goto err;
            if (!group->meth->field_mul(group, &p->X, &p->X, tmp, ctx))
                goto err;

            if (!group->meth->field_mul(group, tmp, tmp, &p->Z, ctx))
                goto err;
            if (!group->meth->field_mul(group, &p->Y, &p->Y, tmp, ctx))
                goto err;

            if (group->meth->field_set_to_one != 0) {
                if (!group->meth->field_set_to_one(group, &p->Z, ctx))
                    goto err;
            } else {
                if (!BN_one(&p->Z))
                    goto err;
            }
            p->Z_is_one = 1;
        }
    }

    ret = 1;

err:
    BN_CTX_end(ctx);
    if (new_ctx != NULL)
        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;
}
Пример #21
0
/* Computes scalar*point and stores the result in r.
 * point can not equal r.
 * Uses a modified algorithm 2P of
 *     Lopez, J. and Dahab, R.  "Fast multiplication on elliptic curves over
 *     GF(2^m) without precomputation" (CHES '99, LNCS 1717).
 *
 * To protect against side-channel attack the function uses constant time swap,
 * avoiding conditional branches.
 */
static int ec_GF2m_montgomery_point_multiply(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
        const EC_POINT *point, BN_CTX *ctx)
{
    BIGNUM *x1, *x2, *z1, *z2;
    int ret = 0, i;
    BN_ULONG mask,word;

    if (r == point)
    {
        ECerr(EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY, EC_R_INVALID_ARGUMENT);
        return 0;
    }

    /* if result should be point at infinity */
    if ((scalar == NULL) || BN_is_zero(scalar) || (point == NULL) ||
            EC_POINT_is_at_infinity(group, point))
    {
        return EC_POINT_set_to_infinity(group, r);
    }

    /* only support affine coordinates */
    if (!point->Z_is_one) return 0;

    /* Since point_multiply is static we can guarantee that ctx != NULL. */
    BN_CTX_start(ctx);
    x1 = BN_CTX_get(ctx);
    z1 = BN_CTX_get(ctx);
    if (z1 == NULL) goto err;

    x2 = &r->X;
    z2 = &r->Y;

    bn_wexpand(x1, group->field.top);
    bn_wexpand(z1, group->field.top);
    bn_wexpand(x2, group->field.top);
    bn_wexpand(z2, group->field.top);

    if (!BN_GF2m_mod_arr(x1, &point->X, group->poly)) goto err; /* x1 = x */
    if (!BN_one(z1)) goto err; /* z1 = 1 */
    if (!group->meth->field_sqr(group, z2, x1, ctx)) goto err; /* z2 = x1^2 = x^2 */
    if (!group->meth->field_sqr(group, x2, z2, ctx)) goto err;
    if (!BN_GF2m_add(x2, x2, &group->b)) goto err; /* x2 = x^4 + b */

    /* find top most bit and go one past it */
    i = scalar->top - 1;
    mask = BN_TBIT;
    word = scalar->d[i];
    while (!(word & mask)) mask >>= 1;
    mask >>= 1;
    /* if top most bit was at word break, go to next word */
    if (!mask)
    {
        i--;
        mask = BN_TBIT;
    }

    for (; i >= 0; i--)
    {
        word = scalar->d[i];
        while (mask)
        {
            BN_consttime_swap(word & mask, x1, x2, group->field.top);
            BN_consttime_swap(word & mask, z1, z2, group->field.top);
            if (!gf2m_Madd(group, &point->X, x2, z2, x1, z1, ctx)) goto err;
            if (!gf2m_Mdouble(group, x1, z1, ctx)) goto err;
            BN_consttime_swap(word & mask, x1, x2, group->field.top);
            BN_consttime_swap(word & mask, z1, z2, group->field.top);
            mask >>= 1;
        }
        mask = BN_TBIT;
    }

    /* convert out of "projective" coordinates */
    i = gf2m_Mxy(group, &point->X, &point->Y, x1, z1, x2, z2, ctx);
    if (i == 0) goto err;
    else if (i == 1)
    {
        if (!EC_POINT_set_to_infinity(group, r)) goto err;
    }
    else
    {
        if (!BN_one(&r->Z)) goto err;
        r->Z_is_one = 1;
    }

    /* GF(2^m) field elements should always have BIGNUM::neg = 0 */
    BN_set_negative(&r->X, 0);
    BN_set_negative(&r->Y, 0);

    ret = 1;

err:
    BN_CTX_end(ctx);
    return ret;
}
Пример #22
0
int ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
{
    int ret = 0;
    BIGNUM *a, *b, *order, *tmp_1, *tmp_2;
    const BIGNUM *p = &group->field;
    BN_CTX *new_ctx = NULL;

    if (ctx == NULL) {
        ctx = new_ctx = BN_CTX_new();
        if (ctx == NULL) {
            ECerr(EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT,
                  ERR_R_MALLOC_FAILURE);
            goto err;
        }
    }
    BN_CTX_start(ctx);
    a = BN_CTX_get(ctx);
    b = BN_CTX_get(ctx);
    tmp_1 = BN_CTX_get(ctx);
    tmp_2 = BN_CTX_get(ctx);
    order = BN_CTX_get(ctx);
    if (order == NULL)
        goto err;

    if (group->meth->field_decode) {
        if (!group->meth->field_decode(group, a, &group->a, ctx))
            goto err;
        if (!group->meth->field_decode(group, b, &group->b, ctx))
            goto err;
    } else {
        if (!BN_copy(a, &group->a))
            goto err;
        if (!BN_copy(b, &group->b))
            goto err;
    }

    /*-
     * check the discriminant:
     * y^2 = x^3 + a*x + b is an elliptic curve <=> 4*a^3 + 27*b^2 != 0 (mod p)
     * 0 =< a, b < p
     */
    if (BN_is_zero(a)) {
        if (BN_is_zero(b))
            goto err;
    } else if (!BN_is_zero(b)) {
        if (!BN_mod_sqr(tmp_1, a, p, ctx))
            goto err;
        if (!BN_mod_mul(tmp_2, tmp_1, a, p, ctx))
            goto err;
        if (!BN_lshift(tmp_1, tmp_2, 2))
            goto err;
        /* tmp_1 = 4*a^3 */

        if (!BN_mod_sqr(tmp_2, b, p, ctx))
            goto err;
        if (!BN_mul_word(tmp_2, 27))
            goto err;
        /* tmp_2 = 27*b^2 */

        if (!BN_mod_add(a, tmp_1, tmp_2, p, ctx))
            goto err;
        if (BN_is_zero(a))
            goto err;
    }
    ret = 1;

err:
    if (ctx != NULL)
        BN_CTX_end(ctx);
    if (new_ctx != NULL)
        BN_CTX_free(new_ctx);
    return ret;
}
Пример #23
0
/*
 * Converts an octet string representation to an EC_POINT. Note that the
 * simple implementation only uses affine coordinates.
 */
int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
                             const unsigned char *buf, size_t len,
                             BN_CTX *ctx)
{
    point_conversion_form_t form;
    int y_bit;
    BN_CTX *new_ctx = NULL;
    BIGNUM *x, *y, *yxi;
    size_t field_len, enc_len;
    int ret = 0;

    if (len == 0) {
        ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
        return 0;
    }
    form = buf[0];
    y_bit = form & 1;
    form = form & ~1U;
    if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED)
        && (form != POINT_CONVERSION_UNCOMPRESSED)
        && (form != POINT_CONVERSION_HYBRID)) {
        ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
        return 0;
    }
    if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit) {
        ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
        return 0;
    }

    if (form == 0) {
        if (len != 1) {
            ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
            return 0;
        }

        return EC_POINT_set_to_infinity(group, point);
    }

    field_len = (EC_GROUP_get_degree(group) + 7) / 8;
    enc_len =
        (form ==
         POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len;

    if (len != enc_len) {
        ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
        return 0;
    }

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

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

    if (!BN_bin2bn(buf + 1, field_len, x))
        goto err;
    if (BN_ucmp(x, group->field) >= 0) {
        ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
        goto err;
    }

    if (form == POINT_CONVERSION_COMPRESSED) {
        if (!EC_POINT_set_compressed_coordinates_GF2m
            (group, point, x, y_bit, ctx))
            goto err;
    } else {
        if (!BN_bin2bn(buf + 1 + field_len, field_len, y))
            goto err;
        if (BN_ucmp(y, group->field) >= 0) {
            ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
            goto err;
        }
        if (form == POINT_CONVERSION_HYBRID) {
            if (!group->meth->field_div(group, yxi, y, x, ctx))
                goto err;
            if (y_bit != BN_is_odd(yxi)) {
                ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
                goto err;
            }
        }

        if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx))
            goto err;
    }

    /* test required by X9.62 */
    if (EC_POINT_is_on_curve(group, point, ctx) <= 0) {
        ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE);
        goto err;
    }

    ret = 1;

 err:
    BN_CTX_end(ctx);
    BN_CTX_free(new_ctx);
    return ret;
}
Пример #24
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)) {
        ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES,
              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_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) {
                if (!group->meth->field_decode(group, x, &point->X, ctx))
                    goto err;
            }
            if (y != NULL) {
                if (!group->meth->field_decode(group, y, &point->Y, ctx))
                    goto err;
            }
        } else {
            if (x != NULL) {
                if (!BN_copy(x, &point->X))
                    goto err;
            }
            if (y != NULL) {
                if (!BN_copy(y, &point->Y))
                    goto err;
            }
        }
    } else {
        if (!BN_mod_inverse(Z_1, Z_, &group->field, ctx)) {
            ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES,
                  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;
        }

        if (x != NULL) {
            /*
             * in the Montgomery case, field_mul will cancel out Montgomery
             * factor in X:
             */
            if (!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);
    if (new_ctx != NULL)
        BN_CTX_free(new_ctx);
    return ret;
}
Пример #25
0
int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
{
    if (dest->meth->group_copy == 0) {
        ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
        return 0;
    }
    if (dest->meth != src->meth) {
        ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS);
        return 0;
    }
    if (dest == src)
        return 1;

    dest->curve_name = src->curve_name;

    /* Copy precomputed */
    dest->pre_comp_type = src->pre_comp_type;
    switch (src->pre_comp_type) {
    case PCT_none:
        dest->pre_comp.ec = NULL;
        break;
    case PCT_nistz256:
#ifdef ECP_NISTZ256_ASM
        dest->pre_comp.nistz256 = EC_nistz256_pre_comp_dup(src->pre_comp.nistz256);
#endif
        break;
#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
    case PCT_nistp224:
        dest->pre_comp.nistp224 = EC_nistp224_pre_comp_dup(src->pre_comp.nistp224);
        break;
    case PCT_nistp256:
        dest->pre_comp.nistp256 = EC_nistp256_pre_comp_dup(src->pre_comp.nistp256);
        break;
    case PCT_nistp521:
        dest->pre_comp.nistp521 = EC_nistp521_pre_comp_dup(src->pre_comp.nistp521);
        break;
#else
    case PCT_nistp224:
    case PCT_nistp256:
    case PCT_nistp521:
        break;
#endif
    case PCT_ec:
        dest->pre_comp.ec = EC_ec_pre_comp_dup(src->pre_comp.ec);
        break;
    }

    if (src->mont_data != NULL) {
        if (dest->mont_data == NULL) {
            dest->mont_data = BN_MONT_CTX_new();
            if (dest->mont_data == NULL)
                return 0;
        }
        if (!BN_MONT_CTX_copy(dest->mont_data, src->mont_data))
            return 0;
    } else {
        /* src->generator == NULL */
        BN_MONT_CTX_free(dest->mont_data);
        dest->mont_data = NULL;
    }

    if (src->generator != NULL) {
        if (dest->generator == NULL) {
            dest->generator = EC_POINT_new(dest);
            if (dest->generator == NULL)
                return 0;
        }
        if (!EC_POINT_copy(dest->generator, src->generator))
            return 0;
    } else {
        /* src->generator == NULL */
        EC_POINT_clear_free(dest->generator);
        dest->generator = NULL;
    }

    if ((src->meth->flags & EC_FLAGS_CUSTOM_CURVE) == 0) {
        if (!BN_copy(dest->order, src->order))
            return 0;
        if (!BN_copy(dest->cofactor, src->cofactor))
            return 0;
    }

    dest->asn1_flag = src->asn1_flag;
    dest->asn1_form = src->asn1_form;

    if (src->seed) {
        OPENSSL_free(dest->seed);
        if ((dest->seed = OPENSSL_malloc(src->seed_len)) == NULL) {
            ECerr(EC_F_EC_GROUP_COPY, ERR_R_MALLOC_FAILURE);
            return 0;
        }
        if (!memcpy(dest->seed, src->seed, src->seed_len))
            return 0;
        dest->seed_len = src->seed_len;
    } else {
        OPENSSL_free(dest->seed);
        dest->seed = NULL;
        dest->seed_len = 0;
    }

    return dest->meth->group_copy(dest, src);
}
Пример #26
0
int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group,
        EC_POINT *point,
        const BIGNUM *x_, int y_bit,
        BN_CTX *ctx)
{
    BN_CTX *new_ctx = NULL;
    BIGNUM *tmp1, *tmp2, *x, *y;
    int ret = 0;

    /* clear error queue */
    ERR_clear_error();

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

    y_bit = (y_bit != 0);

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

    /*-
     * Recover y.  We have a Weierstrass equation
     *     y^2 = x^3 + a*x + b,
     * so  y  is one of the square roots of  x^3 + a*x + b.
     */

    /* tmp1 := x^3 */
    if (!BN_nnmod(x, x_, &group->field, ctx))
        goto err;
    if (group->meth->field_decode == 0) {
        /* field_{sqr,mul} work on standard representation */
        if (!group->meth->field_sqr(group, tmp2, x_, ctx))
            goto err;
        if (!group->meth->field_mul(group, tmp1, tmp2, x_, ctx))
            goto err;
    } else {
        if (!BN_mod_sqr(tmp2, x_, &group->field, ctx))
            goto err;
        if (!BN_mod_mul(tmp1, tmp2, x_, &group->field, ctx))
            goto err;
    }

    /* tmp1 := tmp1 + a*x */
    if (group->a_is_minus3) {
        if (!BN_mod_lshift1_quick(tmp2, x, &group->field))
            goto err;
        if (!BN_mod_add_quick(tmp2, tmp2, x, &group->field))
            goto err;
        if (!BN_mod_sub_quick(tmp1, tmp1, tmp2, &group->field))
            goto err;
    } else {
        if (group->meth->field_decode) {
            if (!group->meth->field_decode(group, tmp2, &group->a, ctx))
                goto err;
            if (!BN_mod_mul(tmp2, tmp2, x, &group->field, ctx))
                goto err;
        } else {
            /* field_mul works on standard representation */
            if (!group->meth->field_mul(group, tmp2, &group->a, x, ctx))
                goto err;
        }

        if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field))
            goto err;
    }

    /* tmp1 := tmp1 + b */
    if (group->meth->field_decode) {
        if (!group->meth->field_decode(group, tmp2, &group->b, ctx))
            goto err;
        if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field))
            goto err;
    } else {
        if (!BN_mod_add_quick(tmp1, tmp1, &group->b, &group->field))
            goto err;
    }

    if (!BN_mod_sqrt(y, tmp1, &group->field, ctx)) {
        unsigned long err = ERR_peek_last_error();

        if (ERR_GET_LIB(err) == ERR_LIB_BN
                && ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE) {
            ERR_clear_error();
            ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES,
                  EC_R_INVALID_COMPRESSED_POINT);
        } else
            ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES,
                  ERR_R_BN_LIB);
        goto err;
    }

    if (y_bit != BN_is_odd(y)) {
        if (BN_is_zero(y)) {
            int kron;

            kron = BN_kronecker(x, &group->field, ctx);
            if (kron == -2)
                goto err;

            if (kron == 1)
                ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES,
                      EC_R_INVALID_COMPRESSION_BIT);
            else
                /*
                 * BN_mod_sqrt() should have cought this error (not a square)
                 */
                ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES,
                      EC_R_INVALID_COMPRESSED_POINT);
            goto err;
        }
        if (!BN_usub(y, &group->field, y))
            goto err;
    }
    if (y_bit != BN_is_odd(y)) {
        ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES,
              ERR_R_INTERNAL_ERROR);
        goto err;
    }

    if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx))
        goto err;

    ret = 1;

err:
    BN_CTX_end(ctx);
    if (new_ctx != NULL)
        BN_CTX_free(new_ctx);
    return ret;
}
Пример #27
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);
	}
Пример #28
0
static int ecdh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
	{
	int rv = 0;

	X509_ALGOR *alg, *kekalg = NULL;
	ASN1_OCTET_STRING *ukm;
	const unsigned char *p;
	unsigned char *der = NULL;
	int plen, keylen;
	const EVP_CIPHER *kekcipher;
	EVP_CIPHER_CTX *kekctx;

	if (!CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm))
		return 0;

	if (!ecdh_cms_set_kdf_param(pctx, OBJ_obj2nid(alg->algorithm)))
		{
		ECerr(EC_F_ECDH_CMS_SET_SHARED_INFO, EC_R_KDF_PARAMETER_ERROR);
		return 0;
		}

	if (alg->parameter->type != V_ASN1_SEQUENCE)
		return 0;

	p = alg->parameter->value.sequence->data;
	plen = alg->parameter->value.sequence->length;
	kekalg = d2i_X509_ALGOR(NULL, &p, plen);
	if (!kekalg)
		goto err;
	kekctx = CMS_RecipientInfo_kari_get0_ctx(ri);
	if (!kekctx)
		goto err;
	kekcipher = EVP_get_cipherbyobj(kekalg->algorithm);
	if (!kekcipher || EVP_CIPHER_mode(kekcipher) != EVP_CIPH_WRAP_MODE)
		goto err;
	if (!EVP_EncryptInit_ex(kekctx, kekcipher, NULL, NULL, NULL))
		goto err;
	if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0)
		goto err;

	keylen = EVP_CIPHER_CTX_key_length(kekctx);
	if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0)
		goto err;

	plen = CMS_SharedInfo_encode(&der, kekalg, ukm, keylen);

	if (!plen)
		goto err;

	if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, der, plen) <= 0)
		goto err;
	der = NULL;

	rv = 1;
	err:
	if (kekalg)
		X509_ALGOR_free(kekalg);
	if (der)
		OPENSSL_free(der);
	return rv;
	}
Пример #29
0
int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, BIGNUM *y)
	{
	BN_CTX *ctx = NULL;
	BIGNUM *tx, *ty;
	EC_POINT *point = NULL;
	int ok = 0, tmp_nid, is_char_two = 0;

	if (!key || !key->group || !x || !y)
		{
		ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES,
						ERR_R_PASSED_NULL_PARAMETER);
		return 0;
		}
	ctx = BN_CTX_new();
	if (!ctx)
		goto err;

	point = EC_POINT_new(key->group);

	if (!point)
		goto err;

	tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(key->group));

        if (tmp_nid == NID_X9_62_characteristic_two_field)
		is_char_two = 1;

	tx = BN_CTX_get(ctx);
	ty = BN_CTX_get(ctx);
#ifndef OPENSSL_NO_EC2M
	if (is_char_two)
		{
		if (!EC_POINT_set_affine_coordinates_GF2m(key->group, point,
								x, y, ctx))
			goto err;
		if (!EC_POINT_get_affine_coordinates_GF2m(key->group, point,
								tx, ty, ctx))
			goto err;
		}
	else
#endif
		{
		if (!EC_POINT_set_affine_coordinates_GFp(key->group, point,
								x, y, ctx))
			goto err;
		if (!EC_POINT_get_affine_coordinates_GFp(key->group, point,
								tx, ty, ctx))
			goto err;
		}
	/* Check if retrieved coordinates match originals: if not values
	 * are out of range.
	 */
	if (BN_cmp(x, tx) || BN_cmp(y, ty))
		{
		ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES,
			EC_R_COORDINATES_OUT_OF_RANGE);
		goto err;
		}

	if (!EC_KEY_set_public_key(key, point))
		goto err;

	if (EC_KEY_check_key(key) == 0)
		goto err;

	ok = 1;

	err:
	if (ctx)
		BN_CTX_free(ctx);
	if (point)
		EC_POINT_free(point);
	return ok;

	}
Пример #30
0
ECDSA_SIG *ossl_ecdsa_sign_sig(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;
    const BIGNUM *order, *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) {
        ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_PASSED_NULL_PARAMETER);
        return NULL;
    }

    if (!EC_KEY_can_sign(eckey)) {
        ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING);
        return NULL;
    }

    ret = ECDSA_SIG_new();
    if (ret == NULL) {
        ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE);
        return NULL;
    }
    ret->r = BN_new();
    ret->s = BN_new();
    if (ret->r == NULL || ret->s == NULL) {
        ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE);
        goto err;
    }
    s = ret->s;

    if ((ctx = BN_CTX_new()) == NULL ||
        (tmp = BN_new()) == NULL || (m = BN_new()) == NULL) {
        ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE);
        goto err;
    }

    order = EC_GROUP_get0_order(group);
    if (order == NULL) {
        ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, 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)) {
        ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, 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))) {
        ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
        goto err;
    }
    do {
        if (in_kinv == NULL || in_r == NULL) {
            if (!ecdsa_sign_setup(eckey, ctx, &kinv, &ret->r, dgst, dgst_len)) {
                ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_ECDSA_LIB);
                goto err;
            }
            ckinv = kinv;
        } else {
            ckinv = in_kinv;
            if (BN_copy(ret->r, in_r) == NULL) {
                ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE);
                goto err;
            }
        }

        if (!BN_mod_mul(tmp, priv_key, ret->r, order, ctx)) {
            ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
            goto err;
        }
        if (!BN_mod_add_quick(s, tmp, m, order)) {
            ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
            goto err;
        }
        if (!BN_mod_mul(s, s, ckinv, order, ctx)) {
            ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
            goto err;
        }
        if (BN_is_zero(s)) {
            /*
             * if kinv and r have been supplied by the caller, don't
             * generate new kinv and r values
             */
            if (in_kinv != NULL && in_r != NULL) {
                ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, EC_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_clear_free(kinv);
    return ret;
}