Пример #1
0
int compute_password_element(REQUEST *request, pwd_session_t *session, uint16_t grp_num,
			     char const *password, int password_len,
			     char const *id_server, int id_server_len,
			     char const *id_peer, int id_peer_len,
			     uint32_t *token)
{
	BIGNUM		*x_candidate = NULL, *rnd = NULL, *cofactor = NULL;
	HMAC_CTX	*hmac_ctx = NULL;
	uint8_t		pwe_digest[SHA256_DIGEST_LENGTH], *prf_buf = NULL, ctr;
	int		nid, is_odd, prime_bit_len, prime_byte_len, ret = 0;

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

	case 20:
		nid = NID_secp384r1;
		break;

	case 21:
		nid = NID_secp521r1;
		break;

	case 25:
		nid = NID_X9_62_prime192v1;
		break;

	case 26:
		nid = NID_secp224r1;
		break;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	session->group_num = grp_num;

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

	return ret;
}
Пример #2
0
// unsigned char *pM      输出,明文
// unsigned char *pPDKey  私钥
// unsigned char *pC      密文
// unsigned long Clen     密文长度
unsigned char eccDecrypt(unsigned char *pM, unsigned char *pPDKey, unsigned char *pC, unsigned long Clen)
{
	EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_sm2p256v1);
	EC_GROUP *ec_group = EC_GROUP_new_by_curve_name(NID_sm2p256v1);

	KDF_FUNC kdf = KDF_get_x9_63(EVP_sm3());

	// 设置私钥
	BIGNUM *pri_key = BN_new();
	BN_bin2bn(pPDKey, 32, pri_key);
	EC_KEY_set_private_key(ec_key, pri_key);

	int ret = 1;
	EC_POINT *point = NULL;
	BIGNUM *n = NULL;
	BIGNUM *h = NULL;
	BN_CTX *bn_ctx = NULL;
	EVP_MD_CTX *md_ctx = NULL;
	unsigned char buf[(OPENSSL_ECC_MAX_FIELD_BITS + 7)/4 + 1];
	unsigned char mac[EVP_MAX_MD_SIZE];
	unsigned int maclen;
	int nbytes;
	size_t size;
	size_t i;

	if (!ec_group || !pri_key) {
		goto end;
	}
	if (!kdf) {
		goto end;
	}

	EC_POINT *ephem_point = EC_POINT_new(ec_group);
	EC_POINT_oct2point(ec_group, ephem_point, pC, 65, NULL);

	/* init vars */
	point = EC_POINT_new(ec_group);
	n = BN_new();
	h = BN_new();
	bn_ctx = BN_CTX_new();
	md_ctx = EVP_MD_CTX_create();
	if (!point || !n || !h || !bn_ctx || !md_ctx) {
		goto end;
	}

	/* init ec domain parameters */
	if (!EC_GROUP_get_order(ec_group, n, bn_ctx)) {
		goto end;
	}
	if (!EC_GROUP_get_cofactor(ec_group, h, bn_ctx)) {
		goto end;
	}
	nbytes = (EC_GROUP_get_degree(ec_group) + 7) / 8;

	/* B2: check [h]C1 != O */
	if (!EC_POINT_mul(ec_group, point, NULL, ephem_point, h, bn_ctx)) {
		goto end;
	}
	if (EC_POINT_is_at_infinity(ec_group, point)) {
		goto end;
	}

	/* B3: compute ECDH [d]C1 = (x2, y2) */	
	if (!EC_POINT_mul(ec_group, point, NULL, ephem_point, pri_key, bn_ctx)) {
		goto end;
	}
	if (!(size = EC_POINT_point2oct(ec_group, point,
		POINT_CONVERSION_UNCOMPRESSED, buf, sizeof(buf), bn_ctx))) {
			goto end;
	}
	OPENSSL_assert(size == 1 + nbytes * 2);

	/* B4: compute t = KDF(x2 || y2, clen) */

	size_t len = 0;
	size_t *outlen = &len;
	*outlen = Clen - 97; //FIXME: duplicated code
	unsigned char *out = (unsigned char *)OPENSSL_malloc(*outlen);
	kdf(buf + 1, size - 1, out, outlen);

	unsigned char *ciphertext = pC + 65;

	/* B5: compute M = C2 xor t */
	for (i = 0; i < len; i++) {
		out[i] ^= ciphertext[i];
	}
	*outlen = len;

	if (1) {

		/* B6: check Hash(x2 || M || y2) == C3 */
		if (!EVP_DigestInit_ex(md_ctx, EVP_sm3(), NULL)) {
			goto end;
		}
		if (!EVP_DigestUpdate(md_ctx, buf + 1, nbytes)) {
			goto end;
		}
		if (!EVP_DigestUpdate(md_ctx, out, *outlen)) {
			goto end;
		}
		if (!EVP_DigestUpdate(md_ctx, buf + 1 + nbytes, nbytes)) {
			goto end;
		}
		if (!EVP_DigestFinal_ex(md_ctx, mac, &maclen)) {
			goto end;
		}

		/* GmSSL specific */
		if (memcmp(mac, pC + 129, 32)) {
			goto end;
		}
	}

	for (i = 0; i < len; i++) {
		pM[i] = out[i] ;
	}

	ret = 0;
end:
	if (point) EC_POINT_free(point);
	if (n) BN_free(n);	
	if (h) BN_free(h);
	if (bn_ctx) BN_CTX_free(bn_ctx);
	if (md_ctx) EVP_MD_CTX_destroy(md_ctx);

	return ret;
}
Пример #3
0
int process_peer_commit(REQUEST *request, pwd_session_t *session, uint8_t *in, size_t in_len, BN_CTX *bn_ctx)
{
	uint8_t		*ptr;
	size_t		data_len;
	BIGNUM		*x = NULL, *y = NULL, *cofactor = NULL;
	EC_POINT	*K = NULL, *point = NULL;
	int		ret = 1;

	MEM(session->peer_scalar = BN_new());
	MEM(session->k = BN_new());
	MEM(session->peer_element = EC_POINT_new(session->group));
	MEM(point = EC_POINT_new(session->group));
	MEM(K = EC_POINT_new(session->group));

	MEM(cofactor = BN_new());
	MEM(x = BN_new());
	MEM(y = BN_new());

	if (!EC_GROUP_get_cofactor(session->group, cofactor, NULL)) {
		REDEBUG("Unable to get group co-factor");
		goto finish;
	}

	/* element, x then y, followed by scalar */
	ptr = (uint8_t *)in;
	data_len = BN_num_bytes(session->prime);

	/*
	 *	Did the peer send enough data?
	 */
	if (in_len < (2 * data_len + BN_num_bytes(session->order))) {
		REDEBUG("Invalid commit packet");
		goto finish;
	}

	BN_bin2bn(ptr, data_len, x);
	ptr += data_len;
	BN_bin2bn(ptr, data_len, y);
	ptr += data_len;

	data_len = BN_num_bytes(session->order);
	BN_bin2bn(ptr, data_len, session->peer_scalar);

	/* validate received scalar */
	if (BN_is_zero(session->peer_scalar) ||
	    BN_is_one(session->peer_scalar) ||
	    BN_cmp(session->peer_scalar, session->order) >= 0) {
		REDEBUG("Peer's scalar is not within the allowed range");
		goto finish;
	}

	if (!EC_POINT_set_affine_coordinates_GFp(session->group, session->peer_element, x, y, bn_ctx)) {
		REDEBUG("Unable to get coordinates of peer's element");
		goto finish;
	}

	/* validate received element */
	if (!EC_POINT_is_on_curve(session->group, session->peer_element, bn_ctx) ||
	    EC_POINT_is_at_infinity(session->group, session->peer_element)) {
		REDEBUG("Peer's element is not a point on the elliptic curve");
		goto finish;
	}

	/* check to ensure peer's element is not in a small sub-group */
	if (BN_cmp(cofactor, BN_value_one())) {
		if (!EC_POINT_mul(session->group, point, NULL, session->peer_element, cofactor, NULL)) {
			REDEBUG("Unable to multiply element by co-factor");
			goto finish;
		}

		if (EC_POINT_is_at_infinity(session->group, point)) {
			REDEBUG("Peer's element is in small sub-group");
			goto finish;
		}
	}

	/* detect reflection attacks */
	if (BN_cmp(session->peer_scalar, session->my_scalar) == 0 ||
	    EC_POINT_cmp(session->group, session->peer_element, session->my_element, bn_ctx) == 0) {
		REDEBUG("Reflection attack detected");
		goto finish;
	}

	/* compute the shared key, k */
	if ((!EC_POINT_mul(session->group, K, NULL, session->pwe, session->peer_scalar, bn_ctx)) ||
	    (!EC_POINT_add(session->group, K, K, session->peer_element, bn_ctx)) ||
	    (!EC_POINT_mul(session->group, K, NULL, K, session->private_value, bn_ctx))) {
		REDEBUG("Unable to compute shared key, k");
		goto finish;
	}

	/* ensure that the shared key isn't in a small sub-group */
	if (BN_cmp(cofactor, BN_value_one())) {
		if (!EC_POINT_mul(session->group, K, NULL, K, cofactor, NULL)) {
			REDEBUG("Unable to multiply k by co-factor");
			goto finish;
		}
	}

	/*
	 * This check is strictly speaking just for the case above where
	 * co-factor > 1 but it was suggested that even though this is probably
	 * never going to happen it is a simple and safe check "just to be
	 * sure" so let's be safe.
	 */
	if (EC_POINT_is_at_infinity(session->group, K)) {
		REDEBUG("K is point-at-infinity");
		goto finish;
	}

	if (!EC_POINT_get_affine_coordinates_GFp(session->group, K, session->k, NULL, bn_ctx)) {
		REDEBUG("Unable to get shared secret from K");
		goto finish;
	}
	ret = 0;

finish:
	EC_POINT_clear_free(K);
	EC_POINT_clear_free(point);
	BN_clear_free(cofactor);
	BN_clear_free(x);
	BN_clear_free(y);

	return ret;
}
Пример #4
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) > 0) {
		BN_zero(&r->Z);
		r->Z_is_one = 0;
		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);
	if ((n0 = BN_CTX_get(ctx)) == NULL)
		goto err;
	if ((n1 = BN_CTX_get(ctx)) == NULL)
		goto err;
	if ((n2 = BN_CTX_get(ctx)) == NULL)
		goto err;
	if ((n3 = BN_CTX_get(ctx)) == 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 (a->Z_is_one) {
		if (!field_sqr(group, n0, &a->X, ctx))
			goto err;
		if (!BN_mod_lshift1_quick(n1, n0, p))
			goto err;
		if (!BN_mod_add_quick(n0, n0, n1, p))
			goto err;
		if (!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))
			goto err;
		if (!BN_mod_add_quick(n0, &a->X, n1, p))
			goto err;
		if (!BN_mod_sub_quick(n2, &a->X, n1, p))
			goto err;
		if (!field_mul(group, n1, n0, n2, ctx))
			goto err;
		if (!BN_mod_lshift1_quick(n0, n1, p))
			goto err;
		if (!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))
			goto err;
		if (!BN_mod_lshift1_quick(n1, n0, p))
			goto err;
		if (!BN_mod_add_quick(n0, n0, n1, p))
			goto err;
		if (!field_sqr(group, n1, &a->Z, ctx))
			goto err;
		if (!field_sqr(group, n1, n1, ctx))
			goto err;
		if (!field_mul(group, n1, n1, &group->a, ctx))
			goto err;
		if (!BN_mod_add_quick(n1, n1, n0, p))
			goto err;
		/* n1 = 3 * X_a^2 + a_curve * Z_a^4 */
	}

	/* Z_r */
	if (a->Z_is_one) {
		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;
	r->Z_is_one = 0;
	/* Z_r = 2 * Y_a * Z_a */

	/* n2 */
	if (!field_sqr(group, n3, &a->Y, ctx))
		goto err;
	if (!field_mul(group, n2, &a->X, n3, ctx))
		goto err;
	if (!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))
		goto err;
	if (!field_sqr(group, &r->X, n1, ctx))
		goto err;
	if (!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))
		goto err;
	if (!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))
		goto err;
	if (!field_mul(group, n0, n1, n0, ctx))
		goto err;
	if (!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;
}
Пример #5
0
static struct wpabuf *
eap_pwd_perform_commit_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
				struct eap_method_ret *ret,
				const struct wpabuf *reqData,
				const u8 *payload, size_t payload_len)
{
	struct wpabuf *resp = NULL;
	EC_POINT *K = NULL, *point = NULL;
	BIGNUM *mask = NULL, *x = NULL, *y = NULL, *cofactor = NULL;
	u16 offset;
	u8 *ptr, *scalar = NULL, *element = NULL;

	if (((data->private_value = BN_new()) == NULL) ||
	    ((data->my_element = EC_POINT_new(data->grp->group)) == NULL) ||
	    ((cofactor = BN_new()) == NULL) ||
	    ((data->my_scalar = BN_new()) == NULL) ||
	    ((mask = BN_new()) == NULL)) {
		wpa_printf(MSG_INFO, "EAP-PWD (peer): scalar allocation fail");
		goto fin;
	}

	if (!EC_GROUP_get_cofactor(data->grp->group, cofactor, NULL)) {
		wpa_printf(MSG_INFO, "EAP-pwd (peer): unable to get cofactor "
			   "for curve");
		goto fin;
	}

	BN_rand_range(data->private_value, data->grp->order);
	BN_rand_range(mask, data->grp->order);
	BN_add(data->my_scalar, data->private_value, mask);
	BN_mod(data->my_scalar, data->my_scalar, data->grp->order,
	       data->bnctx);

	if (!EC_POINT_mul(data->grp->group, data->my_element, NULL,
			  data->grp->pwe, mask, data->bnctx)) {
		wpa_printf(MSG_INFO, "EAP-PWD (peer): element allocation "
			   "fail");
		eap_pwd_state(data, FAILURE);
		goto fin;
	}

	if (!EC_POINT_invert(data->grp->group, data->my_element, data->bnctx))
	{
		wpa_printf(MSG_INFO, "EAP-PWD (peer): element inversion fail");
		goto fin;
	}
	BN_free(mask);

	if (((x = BN_new()) == NULL) ||
	    ((y = BN_new()) == NULL)) {
		wpa_printf(MSG_INFO, "EAP-PWD (peer): point allocation fail");
		goto fin;
	}

	/* process the request */
	if (((data->server_scalar = BN_new()) == NULL) ||
	    ((data->k = BN_new()) == NULL) ||
	    ((K = EC_POINT_new(data->grp->group)) == NULL) ||
	    ((point = EC_POINT_new(data->grp->group)) == NULL) ||
	    ((data->server_element = EC_POINT_new(data->grp->group)) == NULL))
	{
		wpa_printf(MSG_INFO, "EAP-PWD (peer): peer data allocation "
			   "fail");
		goto fin;
	}

	/* element, x then y, followed by scalar */
	ptr = (u8 *) payload;
	BN_bin2bn(ptr, BN_num_bytes(data->grp->prime), x);
	ptr += BN_num_bytes(data->grp->prime);
	BN_bin2bn(ptr, BN_num_bytes(data->grp->prime), y);
	ptr += BN_num_bytes(data->grp->prime);
	BN_bin2bn(ptr, BN_num_bytes(data->grp->order), data->server_scalar);
	if (!EC_POINT_set_affine_coordinates_GFp(data->grp->group,
						 data->server_element, x, y,
						 data->bnctx)) {
		wpa_printf(MSG_INFO, "EAP-PWD (peer): setting peer element "
			   "fail");
		goto fin;
	}

	/* check to ensure server's element is not in a small sub-group */
	if (BN_cmp(cofactor, BN_value_one())) {
		if (!EC_POINT_mul(data->grp->group, point, NULL,
				  data->server_element, cofactor, NULL)) {
			wpa_printf(MSG_INFO, "EAP-PWD (peer): cannot multiply "
				   "server element by order!\n");
			goto fin;
		}
		if (EC_POINT_is_at_infinity(data->grp->group, point)) {
			wpa_printf(MSG_INFO, "EAP-PWD (peer): server element "
				   "is at infinity!\n");
			goto fin;
		}
	}

	/* compute the shared key, k */
	if ((!EC_POINT_mul(data->grp->group, K, NULL, data->grp->pwe,
			   data->server_scalar, data->bnctx)) ||
	    (!EC_POINT_add(data->grp->group, K, K, data->server_element,
			   data->bnctx)) ||
	    (!EC_POINT_mul(data->grp->group, K, NULL, K, data->private_value,
			   data->bnctx))) {
		wpa_printf(MSG_INFO, "EAP-PWD (peer): computing shared key "
			   "fail");
		goto fin;
	}

	/* ensure that the shared key isn't in a small sub-group */
	if (BN_cmp(cofactor, BN_value_one())) {
		if (!EC_POINT_mul(data->grp->group, K, NULL, K, cofactor,
				  NULL)) {
			wpa_printf(MSG_INFO, "EAP-PWD (peer): cannot multiply "
				   "shared key point by order");
			goto fin;
		}
	}

	/*
	 * This check is strictly speaking just for the case above where
	 * co-factor > 1 but it was suggested that even though this is probably
	 * never going to happen it is a simple and safe check "just to be
	 * sure" so let's be safe.
	 */
	if (EC_POINT_is_at_infinity(data->grp->group, K)) {
		wpa_printf(MSG_INFO, "EAP-PWD (peer): shared key point is at "
			   "infinity!\n");
		goto fin;
	}

	if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, K, data->k,
						 NULL, data->bnctx)) {
		wpa_printf(MSG_INFO, "EAP-PWD (peer): unable to extract "
			   "shared secret from point");
		goto fin;
	}

	/* now do the response */
	if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
						 data->my_element, x, y,
						 data->bnctx)) {
		wpa_printf(MSG_INFO, "EAP-PWD (peer): point assignment fail");
		goto fin;
	}

	if (((scalar = os_malloc(BN_num_bytes(data->grp->order))) == NULL) ||
	    ((element = os_malloc(BN_num_bytes(data->grp->prime) * 2)) ==
	     NULL)) {
		wpa_printf(MSG_INFO, "EAP-PWD (peer): data allocation fail");
		goto fin;
	}

	/*
	 * bignums occupy as little memory as possible so one that is
	 * sufficiently smaller than the prime or order might need pre-pending
	 * with zeros.
	 */
	os_memset(scalar, 0, BN_num_bytes(data->grp->order));
	os_memset(element, 0, BN_num_bytes(data->grp->prime) * 2);
	offset = BN_num_bytes(data->grp->order) -
		BN_num_bytes(data->my_scalar);
	BN_bn2bin(data->my_scalar, scalar + offset);

	offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
	BN_bn2bin(x, element + offset);
	offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
	BN_bn2bin(y, element + BN_num_bytes(data->grp->prime) + offset);

	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD,
			     sizeof(struct eap_pwd_hdr) +
			     BN_num_bytes(data->grp->order) +
			     (2 * BN_num_bytes(data->grp->prime)),
			     EAP_CODE_RESPONSE, eap_get_id(reqData));
	if (resp == NULL)
		goto fin;

	wpabuf_put_u8(resp, EAP_PWD_OPCODE_COMMIT_EXCH);

	/* we send the element as (x,y) follwed by the scalar */
	wpabuf_put_data(resp, element, (2 * BN_num_bytes(data->grp->prime)));
	wpabuf_put_data(resp, scalar, BN_num_bytes(data->grp->order));

fin:
	os_free(scalar);
	os_free(element);
	BN_free(x);
	BN_free(y);
	BN_free(cofactor);
	EC_POINT_free(K);
	EC_POINT_free(point);
	if (resp == NULL)
		eap_pwd_state(data, FAILURE);
	else
		eap_pwd_state(data, PWD_Confirm_Req);

	return resp;
}
Пример #6
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;
}
Пример #7
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) > 0) {
		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);
	if ((Z = BN_CTX_get(ctx)) == NULL)
		goto err;
	if ((Z_1 = BN_CTX_get(ctx)) == NULL)
		goto err;
	if ((Z_2 = BN_CTX_get(ctx)) == NULL)
		goto err;
	if ((Z_3 = BN_CTX_get(ctx)) == 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);
	BN_CTX_free(new_ctx);
	return ret;
}
Пример #8
0
int SM2_do_decrypt(const EVP_MD *kdf_md, const EVP_MD *mac_md,
	const SM2_CIPHERTEXT_VALUE *cv, unsigned char *out, size_t *outlen,
	EC_KEY *ec_key)
{
	int ret = 0;
	const EC_GROUP *ec_group = EC_KEY_get0_group(ec_key);
	const BIGNUM *pri_key = EC_KEY_get0_private_key(ec_key);
	KDF_FUNC kdf = KDF_get_x9_63(kdf_md);
	EC_POINT *point = NULL;
	BIGNUM *n = NULL;
	BIGNUM *h = NULL;
	BN_CTX *bn_ctx = NULL;
	EVP_MD_CTX *md_ctx = NULL;
	unsigned char buf[(OPENSSL_ECC_MAX_FIELD_BITS + 7)/4 + 1];
	unsigned char mac[EVP_MAX_MD_SIZE];
	unsigned int maclen;
	int nbytes;
	size_t size;
	int i;

	OPENSSL_assert(kdf_md && mac_md && cv && ec_key);
	OPENSSL_assert(cv->ephem_point && cv->ciphertext);

	if (!ec_group || !pri_key) {
		goto end;
	}
	if (!kdf) {
		goto end;
	}

	if (!out) {
		*outlen = cv->ciphertext_size;
		return 1;
	}
	if (*outlen < cv->ciphertext_size) {
		goto end;
	}

	/* init vars */
	point = EC_POINT_new(ec_group);
	n = BN_new();
	h = BN_new();
	bn_ctx = BN_CTX_new();
	md_ctx = EVP_MD_CTX_create();
	if (!point || !n || !h || !bn_ctx || !md_ctx) {
		goto end;
	}
	
	/* init ec domain parameters */
	if (!EC_GROUP_get_order(ec_group, n, bn_ctx)) {
		goto end;
	}
	if (!EC_GROUP_get_cofactor(ec_group, h, bn_ctx)) {
		goto end;
	}
	nbytes = (EC_GROUP_get_degree(ec_group) + 7) / 8;
	//OPENSSL_assert(nbytes == BN_num_bytes(n));

#if 0
	/* check sm2 curve and md is 256 bits */
	OPENSSL_assert(nbytes == 32);
	OPENSSL_assert(EVP_MD_size(kdf_md) == 32);
	OPENSSL_assert(EVP_MD_size(mac_md) == 32);
#endif

	/* B2: check [h]C1 != O */
	if (!EC_POINT_mul(ec_group, point, NULL, cv->ephem_point, h, bn_ctx)) {
		goto end;
	}
	if (EC_POINT_is_at_infinity(ec_group, point)) {
		goto end;
	}

	/* B3: compute ECDH [d]C1 = (x2, y2) */	
	if (!EC_POINT_mul(ec_group, point, NULL, cv->ephem_point, pri_key, bn_ctx)) {
		goto end;
	}
	if (!(size = EC_POINT_point2oct(ec_group, point,
		POINT_CONVERSION_UNCOMPRESSED, buf, sizeof(buf), bn_ctx))) {
		goto end;
	}
	OPENSSL_assert(size == 1 + nbytes * 2);

	/* B4: compute t = KDF(x2 || y2, clen) */

	*outlen = cv->ciphertext_size; //FIXME: duplicated code
	kdf(buf + 1, size - 1, out, outlen);


	/* B5: compute M = C2 xor t */
	for (i = 0; i < cv->ciphertext_size; i++) {
		out[i] ^= cv->ciphertext[i];
	}
	*outlen = cv->ciphertext_size;

	/* B6: check Hash(x2 || M || y2) == C3 */
	if (!EVP_DigestInit_ex(md_ctx, mac_md, NULL)) {
		goto end;
	}
	if (!EVP_DigestUpdate(md_ctx, buf + 1, nbytes)) {
		goto end;
	}
	if (!EVP_DigestUpdate(md_ctx, out, *outlen)) {
		goto end;
	}
	if (!EVP_DigestUpdate(md_ctx, buf + 1 + nbytes, nbytes)) {
		goto end;
	}
	if (!EVP_DigestFinal_ex(md_ctx, mac, &maclen)) {
		goto end;
	}
	if (cv->mactag_size != maclen ||
		memcmp(cv->mactag, mac, maclen)) {
		goto end;
	}

	ret = 1;
end:
	if (point) EC_POINT_free(point);
	if (n) BN_free(n);	
	if (h) BN_free(h);
	if (bn_ctx) BN_CTX_free(bn_ctx);
	if (md_ctx) EVP_MD_CTX_destroy(md_ctx);

	return ret;
}
Пример #9
0
void prime_field_tests()
	{	
	BN_CTX *ctx = NULL;
	BIGNUM *p, *a, *b;
	EC_GROUP *group;
	EC_GROUP *P_160 = NULL, *P_192 = NULL, *P_224 = NULL, *P_256 = NULL, *P_384 = NULL, *P_521 = NULL;
	EC_POINT *P, *Q, *R;
	BIGNUM *x, *y, *z;
	unsigned char buf[100];
	size_t i, len;
	int k;
	
#if 1 /* optional */
	ctx = BN_CTX_new();
	if (!ctx) ABORT;
#endif

	p = BN_new();
	a = BN_new();
	b = BN_new();
	if (!p || !a || !b) ABORT;

	if (!BN_hex2bn(&p, "17")) ABORT;
	if (!BN_hex2bn(&a, "1")) ABORT;
	if (!BN_hex2bn(&b, "1")) ABORT;
	
	group = EC_GROUP_new(EC_GFp_mont_method()); /* applications should use EC_GROUP_new_curve_GFp
	                                             * so that the library gets to choose the EC_METHOD */
	if (!group) ABORT;

	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;

	{
		EC_GROUP *tmp;
		tmp = EC_GROUP_new(EC_GROUP_method_of(group));
		if (!tmp) ABORT;
		if (!EC_GROUP_copy(tmp, group)) ABORT;
		EC_GROUP_free(group);
		group = tmp;
	}
	
	if (!EC_GROUP_get_curve_GFp(group, p, a, b, ctx)) ABORT;

	fprintf(stdout, "Curve defined by Weierstrass equation\n     y^2 = x^3 + a*x + b  (mod 0x");
	BN_print_fp(stdout, p);
	fprintf(stdout, ")\n     a = 0x");
	BN_print_fp(stdout, a);
	fprintf(stdout, "\n     b = 0x");
	BN_print_fp(stdout, b);
	fprintf(stdout, "\n");

	P = EC_POINT_new(group);
	Q = EC_POINT_new(group);
	R = EC_POINT_new(group);
	if (!P || !Q || !R) ABORT;
	
	if (!EC_POINT_set_to_infinity(group, P)) ABORT;
	if (!EC_POINT_is_at_infinity(group, P)) ABORT;

	buf[0] = 0;
	if (!EC_POINT_oct2point(group, Q, buf, 1, ctx)) ABORT;

	if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT;
	if (!EC_POINT_is_at_infinity(group, P)) ABORT;

	x = BN_new();
	y = BN_new();
	z = BN_new();
	if (!x || !y || !z) ABORT;

	if (!BN_hex2bn(&x, "D")) ABORT;
	if (!EC_POINT_set_compressed_coordinates_GFp(group, Q, x, 1, ctx)) ABORT;
	if (!EC_POINT_is_on_curve(group, Q, ctx))
		{
		if (!EC_POINT_get_affine_coordinates_GFp(group, Q, x, y, ctx)) ABORT;
		fprintf(stderr, "Point is not on curve: x = 0x");
		BN_print_fp(stderr, x);
		fprintf(stderr, ", y = 0x");
		BN_print_fp(stderr, y);
		fprintf(stderr, "\n");
		ABORT;
		}

	fprintf(stdout, "A cyclic subgroup:\n");
	k = 100;
	do
		{
		if (k-- == 0) ABORT;

		if (EC_POINT_is_at_infinity(group, P))
			fprintf(stdout, "     point at infinity\n");
		else
			{
			if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;

			fprintf(stdout, "     x = 0x");
			BN_print_fp(stdout, x);
			fprintf(stdout, ", y = 0x");
			BN_print_fp(stdout, y);
			fprintf(stdout, "\n");
			}
		
		if (!EC_POINT_copy(R, P)) ABORT;
		if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT;

#if 0 /* optional */
		{
			EC_POINT *points[3];
		
			points[0] = R;
			points[1] = Q;
			points[2] = P;
			if (!EC_POINTs_make_affine(group, 2, points, ctx)) ABORT;
		}
#endif

		}
	while (!EC_POINT_is_at_infinity(group, P));

	if (!EC_POINT_add(group, P, Q, R, ctx)) ABORT;
	if (!EC_POINT_is_at_infinity(group, P)) ABORT;

	len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_COMPRESSED, buf, sizeof buf, ctx);
	if (len == 0) ABORT;
	if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
	if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
	fprintf(stdout, "Generator as octect string, compressed form:\n     ");
	for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
	
	len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof buf, ctx);
	if (len == 0) ABORT;
	if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
	if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
	fprintf(stdout, "\nGenerator as octect string, uncompressed form:\n     ");
	for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
	
	len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof buf, ctx);
	if (len == 0) ABORT;
	if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
	if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
	fprintf(stdout, "\nGenerator as octect string, hybrid form:\n     ");
	for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
	
	if (!EC_POINT_get_Jprojective_coordinates_GFp(group, R, x, y, z, ctx)) ABORT;
	fprintf(stdout, "\nA representation of the inverse of that generator in\nJacobian projective coordinates:\n     X = 0x");
	BN_print_fp(stdout, x);
	fprintf(stdout, ", Y = 0x");
	BN_print_fp(stdout, y);
	fprintf(stdout, ", Z = 0x");
	BN_print_fp(stdout, z);
	fprintf(stdout, "\n");

	if (!EC_POINT_invert(group, P, ctx)) ABORT;
	if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT;


	/* Curve secp160r1 (Certicom Research SEC 2 Version 1.0, section 2.4.2, 2000)
	 * -- not a NIST curve, but commonly used */
	
	if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF")) ABORT;
	if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
	if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC")) ABORT;
	if (!BN_hex2bn(&b, "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45")) ABORT;
	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;

	if (!BN_hex2bn(&x, "4A96B5688EF573284664698968C38BB913CBFC82")) ABORT;
	if (!BN_hex2bn(&y, "23a628553168947d59dcc912042351377ac5fb32")) ABORT;
	if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
	if (!BN_hex2bn(&z, "0100000000000000000001F4C8F927AED3CA752257")) ABORT;
	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;

	if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
	fprintf(stdout, "\nSEC2 curve secp160r1 -- Generator:\n     x = 0x");
	BN_print_fp(stdout, x);
	fprintf(stdout, "\n     y = 0x");
	BN_print_fp(stdout, y);
	fprintf(stdout, "\n");
	/* G_y value taken from the standard: */
	if (!BN_hex2bn(&z, "23a628553168947d59dcc912042351377ac5fb32")) ABORT;
	if (0 != BN_cmp(y, z)) ABORT;

	fprintf(stdout, "verify degree ...");
	if (EC_GROUP_get_degree(group) != 160) ABORT;
	fprintf(stdout, " ok\n");
	
	fprintf(stdout, "verify group order ...");
	fflush(stdout);
	if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
	fprintf(stdout, ".");
	fflush(stdout);
	if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
	fprintf(stdout, " ok\n");

	if (!(P_160 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
	if (!EC_GROUP_copy(P_160, group)) ABORT;


	/* Curve P-192 (FIPS PUB 186-2, App. 6) */
	
	if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF")) ABORT;
	if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
	if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC")) ABORT;
	if (!BN_hex2bn(&b, "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1")) ABORT;
	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;

	if (!BN_hex2bn(&x, "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012")) ABORT;
	if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) ABORT;
	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
	if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831")) ABORT;
	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;

	if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
	fprintf(stdout, "\nNIST curve P-192 -- Generator:\n     x = 0x");
	BN_print_fp(stdout, x);
	fprintf(stdout, "\n     y = 0x");
	BN_print_fp(stdout, y);
	fprintf(stdout, "\n");
	/* G_y value taken from the standard: */
	if (!BN_hex2bn(&z, "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811")) ABORT;
	if (0 != BN_cmp(y, z)) ABORT;

	fprintf(stdout, "verify degree ...");
	if (EC_GROUP_get_degree(group) != 192) ABORT;
	fprintf(stdout, " ok\n");
	
	fprintf(stdout, "verify group order ...");
	fflush(stdout);
	if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
	fprintf(stdout, ".");
	fflush(stdout);
#if 0
	if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
#endif
	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
	fprintf(stdout, " ok\n");

	if (!(P_192 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
	if (!EC_GROUP_copy(P_192, group)) ABORT;


	/* Curve P-224 (FIPS PUB 186-2, App. 6) */
	
	if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001")) ABORT;
	if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
	if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE")) ABORT;
	if (!BN_hex2bn(&b, "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4")) ABORT;
	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;

	if (!BN_hex2bn(&x, "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21")) ABORT;
	if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 0, ctx)) ABORT;
	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
	if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D")) ABORT;
	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;

	if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
	fprintf(stdout, "\nNIST curve P-224 -- Generator:\n     x = 0x");
	BN_print_fp(stdout, x);
	fprintf(stdout, "\n     y = 0x");
	BN_print_fp(stdout, y);
	fprintf(stdout, "\n");
	/* G_y value taken from the standard: */
	if (!BN_hex2bn(&z, "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34")) ABORT;
	if (0 != BN_cmp(y, z)) ABORT;
	
	fprintf(stdout, "verify degree ...");
	if (EC_GROUP_get_degree(group) != 224) ABORT;
	fprintf(stdout, " ok\n");
	
	fprintf(stdout, "verify group order ...");
	fflush(stdout);
	if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
	fprintf(stdout, ".");
	fflush(stdout);
#if 0
	if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
#endif
	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
	fprintf(stdout, " ok\n");

	if (!(P_224 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
	if (!EC_GROUP_copy(P_224, group)) ABORT;


	/* Curve P-256 (FIPS PUB 186-2, App. 6) */
	
	if (!BN_hex2bn(&p, "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF")) ABORT;
	if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
	if (!BN_hex2bn(&a, "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC")) ABORT;
	if (!BN_hex2bn(&b, "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B")) ABORT;
	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;

	if (!BN_hex2bn(&x, "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296")) ABORT;
	if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) ABORT;
	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
	if (!BN_hex2bn(&z, "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E"
		"84F3B9CAC2FC632551")) ABORT;
	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;

	if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
	fprintf(stdout, "\nNIST curve P-256 -- Generator:\n     x = 0x");
	BN_print_fp(stdout, x);
	fprintf(stdout, "\n     y = 0x");
	BN_print_fp(stdout, y);
	fprintf(stdout, "\n");
	/* G_y value taken from the standard: */
	if (!BN_hex2bn(&z, "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5")) ABORT;
	if (0 != BN_cmp(y, z)) ABORT;
	
	fprintf(stdout, "verify degree ...");
	if (EC_GROUP_get_degree(group) != 256) ABORT;
	fprintf(stdout, " ok\n");
	
	fprintf(stdout, "verify group order ...");
	fflush(stdout);
	if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
	fprintf(stdout, ".");
	fflush(stdout);
#if 0
	if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
#endif
	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
	fprintf(stdout, " ok\n");

	if (!(P_256 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
	if (!EC_GROUP_copy(P_256, group)) ABORT;


	/* Curve P-384 (FIPS PUB 186-2, App. 6) */
	
	if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
		"FFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF")) ABORT;
	if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
	if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
		"FFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC")) ABORT;
	if (!BN_hex2bn(&b, "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141"
		"120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF")) ABORT;
	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;

	if (!BN_hex2bn(&x, "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B"
		"9859F741E082542A385502F25DBF55296C3A545E3872760AB7")) ABORT;
	if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) ABORT;
	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
	if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
		"FFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973")) ABORT;
	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;

	if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
	fprintf(stdout, "\nNIST curve P-384 -- Generator:\n     x = 0x");
	BN_print_fp(stdout, x);
	fprintf(stdout, "\n     y = 0x");
	BN_print_fp(stdout, y);
	fprintf(stdout, "\n");
	/* G_y value taken from the standard: */
	if (!BN_hex2bn(&z, "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A14"
		"7CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F")) ABORT;
	if (0 != BN_cmp(y, z)) ABORT;
	
	fprintf(stdout, "verify degree ...");
	if (EC_GROUP_get_degree(group) != 384) ABORT;
	fprintf(stdout, " ok\n");
	
	fprintf(stdout, "verify group order ...");
	fflush(stdout);
	if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
	fprintf(stdout, ".");
	fflush(stdout);
#if 0
	if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
#endif
	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
	fprintf(stdout, " ok\n");

	if (!(P_384 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
	if (!EC_GROUP_copy(P_384, group)) ABORT;


	/* Curve P-521 (FIPS PUB 186-2, App. 6) */
	
	if (!BN_hex2bn(&p, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
		"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
		"FFFFFFFFFFFFFFFFFFFFFFFFFFFF")) ABORT;
	if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
	if (!BN_hex2bn(&a, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
		"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
		"FFFFFFFFFFFFFFFFFFFFFFFFFFFC")) ABORT;
	if (!BN_hex2bn(&b, "051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B"
		"315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573"
		"DF883D2C34F1EF451FD46B503F00")) ABORT;
	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;

	if (!BN_hex2bn(&x, "C6858E06B70404E9CD9E3ECB662395B4429C648139053F"
		"B521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B"
		"3C1856A429BF97E7E31C2E5BD66")) ABORT;
	if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 0, ctx)) ABORT;
	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
	if (!BN_hex2bn(&z, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
		"FFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5"
		"C9B8899C47AEBB6FB71E91386409")) ABORT;
	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;

	if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
	fprintf(stdout, "\nNIST curve P-521 -- Generator:\n     x = 0x");
	BN_print_fp(stdout, x);
	fprintf(stdout, "\n     y = 0x");
	BN_print_fp(stdout, y);
	fprintf(stdout, "\n");
	/* G_y value taken from the standard: */
	if (!BN_hex2bn(&z, "11839296A789A3BC0045C8A5FB42C7D1BD998F54449579"
		"B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C"
		"7086A272C24088BE94769FD16650")) ABORT;
	if (0 != BN_cmp(y, z)) ABORT;
	
	fprintf(stdout, "verify degree ...");
	if (EC_GROUP_get_degree(group) != 521) ABORT;
	fprintf(stdout, " ok\n");
	
	fprintf(stdout, "verify group order ...");
	fflush(stdout);
	if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
	fprintf(stdout, ".");
	fflush(stdout);
#if 0
	if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
#endif
	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
	fprintf(stdout, " ok\n");

	if (!(P_521 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
	if (!EC_GROUP_copy(P_521, group)) ABORT;


	/* more tests using the last curve */

	if (!EC_POINT_copy(Q, P)) ABORT;
	if (EC_POINT_is_at_infinity(group, Q)) ABORT;
	if (!EC_POINT_dbl(group, P, P, ctx)) ABORT;
	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
	if (!EC_POINT_invert(group, Q, ctx)) ABORT; /* P = -2Q */

	if (!EC_POINT_add(group, R, P, Q, ctx)) ABORT;
	if (!EC_POINT_add(group, R, R, Q, ctx)) ABORT;
	if (!EC_POINT_is_at_infinity(group, R)) ABORT; /* R = P + 2Q */

	{
		const EC_POINT *points[3];
		const BIGNUM *scalars[3];
	
		if (EC_POINT_is_at_infinity(group, Q)) ABORT;
		points[0] = Q;
		points[1] = Q;
		points[2] = Q;

		if (!BN_add(y, z, BN_value_one())) ABORT;
		if (BN_is_odd(y)) ABORT;
		if (!BN_rshift1(y, y)) ABORT;
		scalars[0] = y; /* (group order + 1)/2,  so  y*Q + y*Q = Q */
		scalars[1] = y;

		fprintf(stdout, "combined multiplication ...");
		fflush(stdout);

		/* z is still the group order */
		if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT;
		if (!EC_POINTs_mul(group, R, z, 2, points, scalars, ctx)) ABORT;
		if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT;
		if (0 != EC_POINT_cmp(group, R, Q, ctx)) ABORT;

		fprintf(stdout, ".");
		fflush(stdout);

		if (!BN_pseudo_rand(y, BN_num_bits(y), 0, 0)) ABORT;
		if (!BN_add(z, z, y)) ABORT;
		BN_set_negative(z, 1);
		scalars[0] = y;
		scalars[1] = z; /* z = -(order + y) */

		if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT;
		if (!EC_POINT_is_at_infinity(group, P)) ABORT;

		fprintf(stdout, ".");
		fflush(stdout);

		if (!BN_pseudo_rand(x, BN_num_bits(y) - 1, 0, 0)) ABORT;
		if (!BN_add(z, x, y)) ABORT;
		BN_set_negative(z, 1);
		scalars[0] = x;
		scalars[1] = y;
		scalars[2] = z; /* z = -(x+y) */

		if (!EC_POINTs_mul(group, P, NULL, 3, points, scalars, ctx)) ABORT;
		if (!EC_POINT_is_at_infinity(group, P)) ABORT;

		fprintf(stdout, " ok\n\n");
	}


#if 0
	timings(P_160, TIMING_BASE_PT, ctx);
	timings(P_160, TIMING_RAND_PT, ctx);
	timings(P_160, TIMING_SIMUL, ctx);
	timings(P_192, TIMING_BASE_PT, ctx);
	timings(P_192, TIMING_RAND_PT, ctx);
	timings(P_192, TIMING_SIMUL, ctx);
	timings(P_224, TIMING_BASE_PT, ctx);
	timings(P_224, TIMING_RAND_PT, ctx);
	timings(P_224, TIMING_SIMUL, ctx);
	timings(P_256, TIMING_BASE_PT, ctx);
	timings(P_256, TIMING_RAND_PT, ctx);
	timings(P_256, TIMING_SIMUL, ctx);
	timings(P_384, TIMING_BASE_PT, ctx);
	timings(P_384, TIMING_RAND_PT, ctx);
	timings(P_384, TIMING_SIMUL, ctx);
	timings(P_521, TIMING_BASE_PT, ctx);
	timings(P_521, TIMING_RAND_PT, ctx);
	timings(P_521, TIMING_SIMUL, ctx);
#endif


	if (ctx)
		BN_CTX_free(ctx);
	BN_free(p); BN_free(a);	BN_free(b);
	EC_GROUP_free(group);
	EC_POINT_free(P);
	EC_POINT_free(Q);
	EC_POINT_free(R);
	BN_free(x); BN_free(y); BN_free(z);

	if (P_160) EC_GROUP_free(P_160);
	if (P_192) EC_GROUP_free(P_192);
	if (P_224) EC_GROUP_free(P_224);
	if (P_256) EC_GROUP_free(P_256);
	if (P_384) EC_GROUP_free(P_384);
	if (P_521) EC_GROUP_free(P_521);

	}
Пример #10
0
static int ec_GFp_mont_point_get_affine_coordinates(const EC_GROUP *group,
                                                    const EC_POINT *point,
                                                    BIGNUM *x, BIGNUM *y,
                                                    BN_CTX *ctx) {
  if (EC_POINT_is_at_infinity(group, point)) {
    OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY);
    return 0;
  }

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

  int ret = 0;

  BN_CTX_start(ctx);

  if (BN_cmp(&point->Z, &group->one) == 0) {
    /* |point| is already affine. */
    if (x != NULL && !BN_from_montgomery(x, &point->X, &group->mont, ctx)) {
      goto err;
    }
    if (y != NULL && !BN_from_montgomery(y, &point->Y, &group->mont, ctx)) {
      goto err;
    }
  } else {
    /* transform  (X, Y, Z)  into  (x, y) := (X/Z^2, Y/Z^3) */

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

    /* The straightforward way to calculate the inverse of a Montgomery-encoded
     * value where the result is Montgomery-encoded is:
     *
     *    |BN_from_montgomery| + |BN_mod_inverse| + |BN_to_montgomery|.
     *
     * This is equivalent, but more efficient, because |BN_from_montgomery|
     * is more efficient (at least in theory) than |BN_to_montgomery|, since it
     * doesn't have to do the multiplication before the reduction. */
    if (!BN_from_montgomery(Z_1, &point->Z, &group->mont, ctx) ||
        !BN_from_montgomery(Z_1, Z_1, &group->mont, ctx) ||
        !BN_mod_inverse(Z_1, Z_1, &group->field, ctx)) {
      goto err;
    }

    if (!BN_mod_mul_montgomery(Z_2, Z_1, Z_1, &group->mont, ctx)) {
      goto err;
    }

    /* Instead of using |BN_from_montgomery| to convert the |x| coordinate
     * and then calling |BN_from_montgomery| again to convert the |y|
     * coordinate below, convert the common factor |Z_2| once now, saving one
     * reduction. */
    if (!BN_from_montgomery(Z_2, Z_2, &group->mont, ctx)) {
      goto err;
    }

    if (x != NULL) {
      if (!BN_mod_mul_montgomery(x, &point->X, Z_2, &group->mont, ctx)) {
        goto err;
      }
    }

    if (y != NULL) {
      if (!BN_mod_mul_montgomery(Z_3, Z_2, Z_1, &group->mont, ctx) ||
          !BN_mod_mul_montgomery(y, &point->Y, Z_3, &group->mont, ctx)) {
        goto err;
      }
    }
  }

  ret = 1;

err:
  BN_CTX_end(ctx);
  BN_CTX_free(new_ctx);
  return ret;
}
Пример #11
0
SM2_CIPHERTEXT_VALUE *SM2_do_encrypt(const EVP_MD *kdf_md, const EVP_MD *mac_md,
	const unsigned char *in, size_t inlen, EC_KEY *ec_key)
{
	int ok = 0;
	SM2_CIPHERTEXT_VALUE *cv = NULL;
	const EC_GROUP *ec_group = EC_KEY_get0_group(ec_key);
	const EC_POINT *pub_key = EC_KEY_get0_public_key(ec_key);
	KDF_FUNC kdf = KDF_get_x9_63(kdf_md);
	EC_POINT *point = NULL;
	BIGNUM *n = NULL;
	BIGNUM *h = NULL;
	BIGNUM *k = NULL;
	BN_CTX *bn_ctx = NULL;
	EVP_MD_CTX *md_ctx = NULL;
	unsigned char buf[(OPENSSL_ECC_MAX_FIELD_BITS + 7)/4 + 1];
	int nbytes;
	size_t len;
	int i;

	if (!ec_group || !pub_key) {
		goto end;
	}
	if (!kdf) {
		goto end;
	}

	/* init ciphertext_value */
	if (!(cv = OPENSSL_malloc(sizeof(SM2_CIPHERTEXT_VALUE)))) {
		goto end;
	}
	bzero(cv, sizeof(SM2_CIPHERTEXT_VALUE));
	cv->ephem_point = EC_POINT_new(ec_group);
	cv->ciphertext = OPENSSL_malloc(inlen);
	cv->ciphertext_size = inlen;
	if (!cv->ephem_point || !cv->ciphertext) {
		goto end;
	}

	point = EC_POINT_new(ec_group);
	n = BN_new();
	h = BN_new();
	k = BN_new();
	bn_ctx = BN_CTX_new();
	md_ctx = EVP_MD_CTX_create();
	if (!point || !n || !h || !k || !bn_ctx || !md_ctx) {
		goto end;
	}

	/* init ec domain parameters */
	if (!EC_GROUP_get_order(ec_group, n, bn_ctx)) {
		goto end;
	}
	if (!EC_GROUP_get_cofactor(ec_group, h, bn_ctx)) {
		goto end;
	}
	nbytes = (EC_GROUP_get_degree(ec_group) + 7) / 8;


	//OPENSSL_assert(nbytes == BN_num_bytes(n));

#if 0
	/* check sm2 curve and md is 256 bits */
	OPENSSL_assert(nbytes == 32);
	OPENSSL_assert(EVP_MD_size(kdf_md) == 32);
	OPENSSL_assert(EVP_MD_size(mac_md) == 32);
#endif

	do
	{
		/* A1: rand k in [1, n-1] */
		do {
			BN_rand_range(k, n);
		} while (BN_is_zero(k));

	
		/* A2: C1 = [k]G = (x1, y1) */
		if (!EC_POINT_mul(ec_group, cv->ephem_point, k, NULL, NULL, bn_ctx)) {
			goto end;
		}
		
		/* A3: check [h]P_B != O */
		if (!EC_POINT_mul(ec_group, point, NULL, pub_key, h, bn_ctx)) {
			goto end;
		}
		if (EC_POINT_is_at_infinity(ec_group, point)) {
			goto end;
		}

		/* A4: compute ECDH [k]P_B = (x2, y2) */
		if (!EC_POINT_mul(ec_group, point, NULL, pub_key, k, bn_ctx)) {
			goto end;
		}
		if (!(len = EC_POINT_point2oct(ec_group, point,
			POINT_CONVERSION_UNCOMPRESSED, buf, sizeof(buf), bn_ctx))) {
			goto end;
		}
		OPENSSL_assert(len == nbytes * 2 + 1);
		
		/* A5: t = KDF(x2 || y2, klen) */
		kdf(buf + 1, len - 1, cv->ciphertext, &cv->ciphertext_size);

		for (i = 0; i < cv->ciphertext_size; i++) {
			if (cv->ciphertext[i]) {
				break;
			}
		}
		if (i == cv->ciphertext_size) {
			continue;
		}

		break;

	} while (1);


	/* A6: C2 = M xor t */
	for (i = 0; i < inlen; i++) {
		cv->ciphertext[i] ^= in[i];
	}
	
	/* A7: C3 = Hash(x2 || M || y2) */
	if (!EVP_DigestInit_ex(md_ctx, mac_md, NULL)) {
		goto end;
	}
	if (!EVP_DigestUpdate(md_ctx, buf + 1, nbytes)) {
		goto end;
	}
	if (!EVP_DigestUpdate(md_ctx, in, inlen)) {
		goto end;
	}
	if (!EVP_DigestUpdate(md_ctx, buf + 1 + nbytes, nbytes)) {
		goto end;
	}
	if (!EVP_DigestFinal_ex(md_ctx, cv->mactag, &cv->mactag_size)) {
		goto end;
	}


	ok = 1;

end:
	if (!ok && cv) {
		SM2_CIPHERTEXT_VALUE_free(cv);
		cv = NULL;
	}

	if (point) EC_POINT_free(point);
	if (n) BN_free(n);
	if (h) BN_free(h);
	if (k) BN_free(k);
	if (bn_ctx) BN_CTX_free(bn_ctx);
	if (md_ctx) EVP_MD_CTX_destroy(md_ctx);

	return cv;
}
Пример #12
0
int
process_peer_commit (pwd_session_t *sess, uint8_t *commit, BN_CTX *bnctx)
{
    uint8_t *ptr;
    BIGNUM *x = NULL, *y = NULL, *cofactor = NULL;
    EC_POINT *K = NULL, *point = NULL;
    int res = 1;

    if (((sess->peer_scalar = BN_new()) == NULL) ||
	((sess->k = BN_new()) == NULL) ||
	((cofactor = BN_new()) == NULL) ||
	((x = BN_new()) == NULL) ||
	((y = BN_new()) == NULL) ||
	((point = EC_POINT_new(sess->group)) == NULL) ||
	((K = EC_POINT_new(sess->group)) == NULL) ||
	((sess->peer_element = EC_POINT_new(sess->group)) == NULL)) {
	DEBUG2("pwd: failed to allocate room to process peer's commit");
	goto fin;
    }

    if (!EC_GROUP_get_cofactor(sess->group, cofactor, NULL)) {
	DEBUG2("pwd: unable to get group co-factor");
	goto fin;
    }

    /* element, x then y, followed by scalar */
    ptr = (uint8_t *)commit;
    BN_bin2bn(ptr, BN_num_bytes(sess->prime), x);
    ptr += BN_num_bytes(sess->prime);
    BN_bin2bn(ptr, BN_num_bytes(sess->prime), y);
    ptr += BN_num_bytes(sess->prime);
    BN_bin2bn(ptr, BN_num_bytes(sess->order), sess->peer_scalar);
    if (!EC_POINT_set_affine_coordinates_GFp(sess->group,
					     sess->peer_element, x, y,
					     bnctx)) {
	DEBUG2("pwd: unable to get coordinates of peer's element");
	goto fin;
    }

    /* check to ensure peer's element is not in a small sub-group */
    if (BN_cmp(cofactor, BN_value_one())) {
	if (!EC_POINT_mul(sess->group, point, NULL,
			  sess->peer_element, cofactor, NULL)) {
	    DEBUG2("pwd: unable to multiply element by co-factor");
	    goto fin;
	}
	if (EC_POINT_is_at_infinity(sess->group, point)) {
	    DEBUG2("pwd: peer's element is in small sub-group");
	    goto fin;
	}
    }

    /* compute the shared key, k */
    if ((!EC_POINT_mul(sess->group, K, NULL, sess->pwe,
		       sess->peer_scalar, bnctx)) ||
	(!EC_POINT_add(sess->group, K, K, sess->peer_element,
		       bnctx)) ||
	(!EC_POINT_mul(sess->group, K, NULL, K, sess->private_value,
		       bnctx))) {
	DEBUG2("pwd: unable to compute shared key, k");
	goto fin;
    }

    /* ensure that the shared key isn't in a small sub-group */
    if (BN_cmp(cofactor, BN_value_one())) {
	if (!EC_POINT_mul(sess->group, K, NULL, K, cofactor,
			  NULL)) {
	    DEBUG2("pwd: unable to multiply k by co-factor");
	    goto fin;
	}
    }

    /*
     * This check is strictly speaking just for the case above where
     * co-factor > 1 but it was suggested that even though this is probably
     * never going to happen it is a simple and safe check "just to be
     * sure" so let's be safe.
     */
    if (EC_POINT_is_at_infinity(sess->group, K)) {
	DEBUG2("pwd: k is point-at-infinity!");
	goto fin;
    }
    if (!EC_POINT_get_affine_coordinates_GFp(sess->group, K, sess->k,
					     NULL, bnctx)) {
	DEBUG2("pwd: unable to get shared secret from K");
	goto fin;
    }
    res = 0;

  fin:
    EC_POINT_free(K);
    EC_POINT_free(point);
    BN_free(cofactor);
    BN_free(x);
    BN_free(y);

    return res;
}
Пример #13
0
SM2CiphertextValue *SM2_do_encrypt(const EVP_MD *md,
	const unsigned char *in, size_t inlen, EC_KEY *ec_key)
{
	SM2CiphertextValue *ret = NULL;
	SM2CiphertextValue *cv = NULL;
	const EC_GROUP *group;
	const EC_POINT *pub_key;
	KDF_FUNC kdf;
	EC_POINT *ephem_point = NULL;
	EC_POINT *share_point = NULL;
	BIGNUM *n = NULL;
	BIGNUM *h = NULL;
	BIGNUM *k = NULL;
	BN_CTX *bn_ctx = NULL;
	EVP_MD_CTX *md_ctx = NULL;

	unsigned char buf[(OPENSSL_ECC_MAX_FIELD_BITS + 7)/4 + 1];
	int nbytes;
	size_t len;
	size_t i;
	unsigned int hashlen;

	/* check arguments */
	if (!md || !in || !ec_key) {
		SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_PASSED_NULL_PARAMETER);
		return 0;
	}

	if (inlen < SM2_MIN_PLAINTEXT_LENGTH || inlen > SM2_MAX_PLAINTEXT_LENGTH) {
		SM2err(SM2_F_SM2_DO_ENCRYPT, SM2_R_INVALID_PLAINTEXT_LENGTH);
		return 0;
	}

	if (!(kdf = KDF_get_x9_63(md))) {
		SM2err(SM2_F_SM2_DO_ENCRYPT, SM2_R_INVALID_DIGEST_ALGOR);
		return 0;
	}

	if (!(group = EC_KEY_get0_group(ec_key))
		|| !(pub_key = EC_KEY_get0_public_key(ec_key))) {
		SM2err(SM2_F_SM2_DO_ENCRYPT, SM2_R_INVALID_EC_KEY);
		return 0;
	}

	/* malloc */
	if (!(cv = SM2CiphertextValue_new())
		|| !(ephem_point = EC_POINT_new(group))
		|| !(share_point = EC_POINT_new(group))
		|| !(n = BN_new())
		|| !(h = BN_new())
		|| !(k = BN_new())
		|| !(bn_ctx = BN_CTX_new())
		|| !(md_ctx = EVP_MD_CTX_new())) {
		SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_MALLOC_FAILURE);
		goto end;
	}

	if (!ASN1_OCTET_STRING_set(cv->ciphertext, NULL, (int)inlen)
		|| !ASN1_OCTET_STRING_set(cv->hash, NULL, EVP_MD_size(md))) {
		SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_ASN1_LIB);
		goto end;
	}

	/* init ec domain parameters */
	if (!EC_GROUP_get_order(group, n, bn_ctx)) {
		ECerr(EC_F_SM2_DO_ENCRYPT, EC_R_ERROR);
		goto end;
	}

	if (!EC_GROUP_get_cofactor(group, h, bn_ctx)) {
		ECerr(EC_F_SM2_DO_ENCRYPT, EC_R_ERROR);
		goto end;
	}

	nbytes = (EC_GROUP_get_degree(group) + 7) / 8;

	/* check [h]P_B != O */
	if (!EC_POINT_mul(group, share_point, NULL, pub_key, h, bn_ctx)) {
		SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_EC_LIB);
		goto end;
	}

	if (EC_POINT_is_at_infinity(group, share_point)) {
		SM2err(SM2_F_SM2_DO_ENCRYPT, SM2_R_INVALID_PUBLIC_KEY);
		goto end;
	}

	do
	{
		size_t size;

		/* rand k in [1, n-1] */
		do {
			BN_rand_range(k, n);
		} while (BN_is_zero(k));

		/* compute ephem_point [k]G = (x1, y1) */
		if (!EC_POINT_mul(group, ephem_point, k, NULL, NULL, bn_ctx)) {
			SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_EC_LIB);
			goto end;
		}

		/* compute ECDH share_point [k]P_B = (x2, y2) */
		if (!EC_POINT_mul(group, share_point, NULL, pub_key, k, bn_ctx)) {
			SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_EC_LIB);
			goto end;
		}

		/* compute t = KDF(x2 || y2, klen) */
		if (!(len = EC_POINT_point2oct(group, share_point,
			POINT_CONVERSION_UNCOMPRESSED, buf, sizeof(buf), bn_ctx))) {
			SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_EC_LIB);
			goto end;
		}

		size = cv->ciphertext->length;
		kdf(buf + 1, len - 1, cv->ciphertext->data, &size);
		if (size != inlen) {
			SM2err(SM2_F_SM2_DO_ENCRYPT, SM2_R_KDF_FAILURE);
			goto end;
		}

		/* ASN1_OCTET_STRING_is_zero in asn1.h and a_octet.c */
	} while (ASN1_OCTET_STRING_is_zero(cv->ciphertext));

	/* set x/yCoordinates as (x1, y1) */
	if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) {
		if (!EC_POINT_get_affine_coordinates_GFp(group, ephem_point,
			cv->xCoordinate, cv->yCoordinate, bn_ctx)) {
			SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_EC_LIB);
			goto end;
		}
	} else {
		if (!EC_POINT_get_affine_coordinates_GF2m(group, ephem_point,
			cv->xCoordinate, cv->yCoordinate, bn_ctx)) {
			SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_EC_LIB);
			goto end;
		}
	}

	/* ciphertext = t xor in */
	for (i = 0; i < inlen; i++) {
		cv->ciphertext->data[i] ^= in[i];
	}

	/* generate hash = Hash(x2 || M || y2) */
	hashlen = cv->hash->length;
	if (!EVP_DigestInit_ex(md_ctx, md, NULL)
		|| !EVP_DigestUpdate(md_ctx, buf + 1, nbytes)
		|| !EVP_DigestUpdate(md_ctx, in, inlen)
		|| !EVP_DigestUpdate(md_ctx, buf + 1 + nbytes, nbytes)
		|| !EVP_DigestFinal_ex(md_ctx, cv->hash->data, &hashlen)) {
		SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_EVP_LIB);
		goto end;
	}

	ret = cv;
	cv = NULL;

end:
	SM2CiphertextValue_free(cv);
	EC_POINT_free(share_point);
	EC_POINT_free(ephem_point);
	BN_free(n);
	BN_free(h);
	BN_clear_free(k);
	BN_CTX_free(bn_ctx);
	EVP_MD_CTX_free(md_ctx);
	return ret;
}
Пример #14
0
int SM2_do_decrypt(const EVP_MD *md, const SM2CiphertextValue *cv,
	unsigned char *out, size_t *outlen, EC_KEY *ec_key)
{
	int ret = 0;
	const EC_GROUP *group;
	const BIGNUM *pri_key;
	KDF_FUNC kdf;
	EC_POINT *point = NULL;
	EC_POINT *tmp_point = NULL;
	BIGNUM *n = NULL;
	BIGNUM *h = NULL;
	BN_CTX *bn_ctx = NULL;
	EVP_MD_CTX *md_ctx = NULL;
	unsigned char buf[(OPENSSL_ECC_MAX_FIELD_BITS + 7)/4 + 1];
	unsigned char mac[EVP_MAX_MD_SIZE];
	unsigned int maclen = sizeof(mac);
	int nbytes, len, i;

	/* check arguments */
	if (!md || !cv || !outlen || !ec_key) {
		SM2err(SM2_F_SM2_DO_DECRYPT, ERR_R_PASSED_NULL_PARAMETER);
		return 0;
	}

	if (!(kdf = KDF_get_x9_63(md))) {
		SM2err(SM2_F_SM2_DO_DECRYPT, SM2_R_INVALID_DIGEST_ALGOR);
		return 0;
	}

	if (!cv->xCoordinate || !cv->yCoordinate || !cv->hash || !cv->ciphertext) {
		SM2err(SM2_F_SM2_DO_DECRYPT, SM2_R_INVALID_CIPHERTEXT);
		return 0;
	}

	if (cv->hash->length != EVP_MD_size(md)) {
		SM2err(SM2_F_SM2_DO_DECRYPT, SM2_R_INVALID_CIPHERTEXT);
		return 0;
	}

	if (cv->ciphertext->length < SM2_MIN_PLAINTEXT_LENGTH
		|| cv->ciphertext->length > SM2_MAX_PLAINTEXT_LENGTH) {
		SM2err(SM2_F_SM2_DO_DECRYPT, SM2_R_INVALID_CIPHERTEXT);
		return 0;
	}

	if (!(group = EC_KEY_get0_group(ec_key))
		|| !(pri_key = EC_KEY_get0_private_key(ec_key))) {
		SM2err(SM2_F_SM2_DO_DECRYPT, SM2_R_INVALID_EC_KEY);
		return 0;
	}

	if (!out) {
		*outlen = cv->ciphertext->length;
		return 1;
	}
	if (*outlen < cv->ciphertext->length) {
		SM2err(SM2_F_SM2_DO_DECRYPT, SM2_R_BUFFER_TOO_SMALL);
		return 0;
	}

	/* malloc */
	point = EC_POINT_new(group);
	tmp_point = EC_POINT_new(group);
	n = BN_new();
	h = BN_new();
	bn_ctx = BN_CTX_new();
	md_ctx = EVP_MD_CTX_new();
	if (!point || !n || !h || !bn_ctx || !md_ctx) {
		SM2err(SM2_F_SM2_DO_DECRYPT, ERR_R_MALLOC_FAILURE);
		goto end;
	}

	/* init ec domain parameters */
	if (!EC_GROUP_get_order(group, n, bn_ctx)) {
		SM2err(SM2_F_SM2_DO_DECRYPT, ERR_R_EC_LIB);
		goto end;
	}

	if (!EC_GROUP_get_cofactor(group, h, bn_ctx)) {
		SM2err(SM2_F_SM2_DO_DECRYPT, ERR_R_EC_LIB);
		goto end;
	}

	nbytes = (EC_GROUP_get_degree(group) + 7) / 8;

	/* get x/yCoordinates as C1 = (x1, y1) */
	if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) {
		if (!EC_POINT_set_affine_coordinates_GFp(group, point,
			cv->xCoordinate, cv->yCoordinate, bn_ctx)) {
			SM2err(SM2_F_SM2_DO_DECRYPT, SM2_R_INVALID_CIPHERTEXT);
			goto end;
		}
	} else {
		if (!EC_POINT_set_affine_coordinates_GF2m(group, point,
			cv->xCoordinate, cv->yCoordinate, bn_ctx)) {
			SM2err(SM2_F_SM2_DO_DECRYPT, SM2_R_INVALID_CIPHERTEXT);
			goto end;
		}
	}

	/* check [h]C1 != O */
	if (!EC_POINT_mul(group, tmp_point, NULL, point, h, bn_ctx)) {
		SM2err(SM2_F_SM2_DO_DECRYPT, ERR_R_EC_LIB);
		goto end;
	}

	if (EC_POINT_is_at_infinity(group, tmp_point)) {
		SM2err(SM2_F_SM2_DO_DECRYPT, SM2_R_INVALID_CIPHERTEXT);
		goto end;
	}

	/* compute ECDH [d]C1 = (x2, y2) */
	if (!EC_POINT_mul(group, point, NULL, point, pri_key, bn_ctx)) {
		SM2err(SM2_F_SM2_DO_DECRYPT, ERR_R_EC_LIB);
		goto end;
	}

	if (!(len = EC_POINT_point2oct(group, point,
		POINT_CONVERSION_UNCOMPRESSED, buf, sizeof(buf), bn_ctx))) {
		SM2err(SM2_F_SM2_DO_DECRYPT, ERR_R_EC_LIB);
		goto end;
	}

	/* compute t = KDF(x2 || y2, clen) */
	*outlen = cv->ciphertext->length;
	kdf(buf + 1, len - 1, out, outlen);


	/* compute M = C2 xor t */
	for (i = 0; i < cv->ciphertext->length; i++) {
		out[i] ^= cv->ciphertext->data[i];
	}

	/* check hash == Hash(x2 || M || y2) */
	if (!EVP_DigestInit_ex(md_ctx, md, NULL)
		|| !EVP_DigestUpdate(md_ctx, buf + 1, nbytes)
		|| !EVP_DigestUpdate(md_ctx, out, *outlen)
		|| !EVP_DigestUpdate(md_ctx, buf + 1 + nbytes, nbytes)
		|| !EVP_DigestFinal_ex(md_ctx, mac, &maclen)) {
		SM2err(SM2_F_SM2_DO_DECRYPT, ERR_R_EVP_LIB);
		goto end;
	}

	if (OPENSSL_memcmp(cv->hash->data, mac, maclen) != 0) {
		SM2err(SM2_F_SM2_DO_DECRYPT, SM2_R_INVALID_CIPHERTEXT);
		goto end;
	}

	ret = 1;
end:
	EC_POINT_free(point);
	EC_POINT_free(tmp_point);
	BN_free(n);
	BN_free(h);
	BN_CTX_free(bn_ctx);
	EVP_MD_CTX_free(md_ctx);
	return ret;
}
Пример #15
0
/*
 * compute a "random" secret point on an elliptic curve based
 * on the password and identities.
 */
int compute_password_element(EAP_PWD_group *grp, u16 num,
			     u8 *password, int password_len,
			     u8 *id_server, int id_server_len,
			     u8 *id_peer, int id_peer_len, u8 *token)
{
	BIGNUM *x_candidate = NULL, *rnd = NULL, *cofactor = NULL;
	struct crypto_hash *hash;
	unsigned char pwe_digest[SHA256_MAC_LEN], *prfbuf = NULL, ctr;
	int nid, is_odd, ret = 0;
	size_t primebytelen, primebitlen;

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

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

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

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

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

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

		BN_bin2bn(pwe_digest, SHA256_MAC_LEN, rnd);

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

		BN_bin2bn(prfbuf, primebytelen, x_candidate);

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

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

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

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

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

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

	return ret;
}
Пример #16
0
void char2_field_tests()
	{	
	BN_CTX *ctx = NULL;
	BIGNUM *p, *a, *b;
	EC_GROUP *group;
	EC_GROUP *C2_K163 = NULL, *C2_K233 = NULL, *C2_K283 = NULL, *C2_K409 = NULL, *C2_K571 = NULL;
	EC_GROUP *C2_B163 = NULL, *C2_B233 = NULL, *C2_B283 = NULL, *C2_B409 = NULL, *C2_B571 = NULL;
	EC_POINT *P, *Q, *R;
	BIGNUM *x, *y, *z, *cof;
	unsigned char buf[100];
	size_t i, len;
	int k;
	
#if 1 /* optional */
	ctx = BN_CTX_new();
	if (!ctx) ABORT;
#endif

	p = BN_new();
	a = BN_new();
	b = BN_new();
	if (!p || !a || !b) ABORT;

	if (!BN_hex2bn(&p, "13")) ABORT;
	if (!BN_hex2bn(&a, "3")) ABORT;
	if (!BN_hex2bn(&b, "1")) ABORT;
	
	group = EC_GROUP_new(EC_GF2m_simple_method()); /* applications should use EC_GROUP_new_curve_GF2m
	                                                * so that the library gets to choose the EC_METHOD */
	if (!group) ABORT;
	if (!EC_GROUP_set_curve_GF2m(group, p, a, b, ctx)) ABORT;

	{
		EC_GROUP *tmp;
		tmp = EC_GROUP_new(EC_GROUP_method_of(group));
		if (!tmp) ABORT;
		if (!EC_GROUP_copy(tmp, group)) ABORT;
		EC_GROUP_free(group);
		group = tmp;
	}
	
	if (!EC_GROUP_get_curve_GF2m(group, p, a, b, ctx)) ABORT;

	fprintf(stdout, "Curve defined by Weierstrass equation\n     y^2 + x*y = x^3 + a*x^2 + b  (mod 0x");
	BN_print_fp(stdout, p);
	fprintf(stdout, ")\n     a = 0x");
	BN_print_fp(stdout, a);
	fprintf(stdout, "\n     b = 0x");
	BN_print_fp(stdout, b);
	fprintf(stdout, "\n(0x... means binary polynomial)\n");

	P = EC_POINT_new(group);
	Q = EC_POINT_new(group);
	R = EC_POINT_new(group);
	if (!P || !Q || !R) ABORT;
	
	if (!EC_POINT_set_to_infinity(group, P)) ABORT;
	if (!EC_POINT_is_at_infinity(group, P)) ABORT;

	buf[0] = 0;
	if (!EC_POINT_oct2point(group, Q, buf, 1, ctx)) ABORT;

	if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT;
	if (!EC_POINT_is_at_infinity(group, P)) ABORT;

	x = BN_new();
	y = BN_new();
	z = BN_new();
	cof = BN_new();
	if (!x || !y || !z || !cof) ABORT;

	if (!BN_hex2bn(&x, "6")) ABORT;
/* Change test based on whether binary point compression is enabled or not. */
#ifdef OPENSSL_EC_BIN_PT_COMP
	if (!EC_POINT_set_compressed_coordinates_GF2m(group, Q, x, 1, ctx)) ABORT;
#else
	if (!BN_hex2bn(&y, "8")) ABORT;
	if (!EC_POINT_set_affine_coordinates_GF2m(group, Q, x, y, ctx)) ABORT;
#endif
	if (!EC_POINT_is_on_curve(group, Q, ctx))
		{
/* Change test based on whether binary point compression is enabled or not. */
#ifdef OPENSSL_EC_BIN_PT_COMP
		if (!EC_POINT_get_affine_coordinates_GF2m(group, Q, x, y, ctx)) ABORT;
#endif
		fprintf(stderr, "Point is not on curve: x = 0x");
		BN_print_fp(stderr, x);
		fprintf(stderr, ", y = 0x");
		BN_print_fp(stderr, y);
		fprintf(stderr, "\n");
		ABORT;
		}

	fprintf(stdout, "A cyclic subgroup:\n");
	k = 100;
	do
		{
		if (k-- == 0) ABORT;

		if (EC_POINT_is_at_infinity(group, P))
			fprintf(stdout, "     point at infinity\n");
		else
			{
			if (!EC_POINT_get_affine_coordinates_GF2m(group, P, x, y, ctx)) ABORT;

			fprintf(stdout, "     x = 0x");
			BN_print_fp(stdout, x);
			fprintf(stdout, ", y = 0x");
			BN_print_fp(stdout, y);
			fprintf(stdout, "\n");
			}
		
		if (!EC_POINT_copy(R, P)) ABORT;
		if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT;
		}
	while (!EC_POINT_is_at_infinity(group, P));

	if (!EC_POINT_add(group, P, Q, R, ctx)) ABORT;
	if (!EC_POINT_is_at_infinity(group, P)) ABORT;

/* Change test based on whether binary point compression is enabled or not. */
#ifdef OPENSSL_EC_BIN_PT_COMP
	len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_COMPRESSED, buf, sizeof buf, ctx);
	if (len == 0) ABORT;
	if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
	if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
	fprintf(stdout, "Generator as octet string, compressed form:\n     ");
	for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
#endif
	
	len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof buf, ctx);
	if (len == 0) ABORT;
	if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
	if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
	fprintf(stdout, "\nGenerator as octet string, uncompressed form:\n     ");
	for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
	
/* Change test based on whether binary point compression is enabled or not. */
#ifdef OPENSSL_EC_BIN_PT_COMP
	len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof buf, ctx);
	if (len == 0) ABORT;
	if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
	if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
	fprintf(stdout, "\nGenerator as octet string, hybrid form:\n     ");
	for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
#endif

	fprintf(stdout, "\n");
	
	if (!EC_POINT_invert(group, P, ctx)) ABORT;
	if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT;


	/* Curve K-163 (FIPS PUB 186-2, App. 6) */
	CHAR2_CURVE_TEST
		(
		"NIST curve K-163",
		"0800000000000000000000000000000000000000C9",
		"1",
		"1",
		"02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8",
		"0289070FB05D38FF58321F2E800536D538CCDAA3D9",
		1,
		"04000000000000000000020108A2E0CC0D99F8A5EF",
		"2",
		163,
		C2_K163
		);

	/* Curve B-163 (FIPS PUB 186-2, App. 6) */
	CHAR2_CURVE_TEST
		(
		"NIST curve B-163",
		"0800000000000000000000000000000000000000C9",
		"1",
		"020A601907B8C953CA1481EB10512F78744A3205FD",
		"03F0EBA16286A2D57EA0991168D4994637E8343E36",
		"00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1",
		1,
		"040000000000000000000292FE77E70C12A4234C33",
		"2",
		163,
		C2_B163
		);

	/* Curve K-233 (FIPS PUB 186-2, App. 6) */
	CHAR2_CURVE_TEST
		(
		"NIST curve K-233",
		"020000000000000000000000000000000000000004000000000000000001",
		"0",
		"1",
		"017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126",
		"01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3",
		0,
		"008000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF",
		"4",
		233,
		C2_K233
		);

	/* Curve B-233 (FIPS PUB 186-2, App. 6) */
	CHAR2_CURVE_TEST
		(
		"NIST curve B-233",
		"020000000000000000000000000000000000000004000000000000000001",
		"000000000000000000000000000000000000000000000000000000000001",
		"0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD",
		"00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B",
		"01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052",
		1,
		"01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7",
		"2",
		233,
		C2_B233
		);

	/* Curve K-283 (FIPS PUB 186-2, App. 6) */
	CHAR2_CURVE_TEST
		(
		"NIST curve K-283",
		"0800000000000000000000000000000000000000000000000000000000000000000010A1",
		"0",
		"1",
		"0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836",
		"01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259",
		0,
		"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61",
		"4",
		283,
		C2_K283
		);

	/* Curve B-283 (FIPS PUB 186-2, App. 6) */
	CHAR2_CURVE_TEST
		(
		"NIST curve B-283",
		"0800000000000000000000000000000000000000000000000000000000000000000010A1",
		"000000000000000000000000000000000000000000000000000000000000000000000001",
		"027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5",
		"05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053",
		"03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4",
		1,
		"03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307",
		"2",
		283,
		C2_B283
		);

	/* Curve K-409 (FIPS PUB 186-2, App. 6) */
	CHAR2_CURVE_TEST
		(
		"NIST curve K-409",
		"02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001",
		"0",
		"1",
		"0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746",
		"01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B",
		1,
		"007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF",
		"4",
		409,
		C2_K409
		);

	/* Curve B-409 (FIPS PUB 186-2, App. 6) */
	CHAR2_CURVE_TEST
		(
		"NIST curve B-409",
		"02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001",
		"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
		"0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F",
		"015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7",
		"0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706",
		1,
		"010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173",
		"2",
		409,
		C2_B409
		);

	/* Curve K-571 (FIPS PUB 186-2, App. 6) */
	CHAR2_CURVE_TEST
		(
		"NIST curve K-571",
		"80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425",
		"0",
		"1",
		"026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972",
		"0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3",
		0,
		"020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001",
		"4",
		571,
		C2_K571
		);

	/* Curve B-571 (FIPS PUB 186-2, App. 6) */
	CHAR2_CURVE_TEST
		(
		"NIST curve B-571",
		"80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425",
		"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
		"02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A",
		"0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19",
		"037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B",
		1,
		"03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47",
		"2",
		571,
		C2_B571
		);

	/* more tests using the last curve */

	if (!EC_POINT_copy(Q, P)) ABORT;
	if (EC_POINT_is_at_infinity(group, Q)) ABORT;
	if (!EC_POINT_dbl(group, P, P, ctx)) ABORT;
	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
	if (!EC_POINT_invert(group, Q, ctx)) ABORT; /* P = -2Q */

	if (!EC_POINT_add(group, R, P, Q, ctx)) ABORT;
	if (!EC_POINT_add(group, R, R, Q, ctx)) ABORT;
	if (!EC_POINT_is_at_infinity(group, R)) ABORT; /* R = P + 2Q */

	{
		const EC_POINT *points[3];
		const BIGNUM *scalars[3];
	
		if (EC_POINT_is_at_infinity(group, Q)) ABORT;
		points[0] = Q;
		points[1] = Q;
		points[2] = Q;

		if (!BN_add(y, z, BN_value_one())) ABORT;
		if (BN_is_odd(y)) ABORT;
		if (!BN_rshift1(y, y)) ABORT;
		scalars[0] = y; /* (group order + 1)/2,  so  y*Q + y*Q = Q */
		scalars[1] = y;

		fprintf(stdout, "combined multiplication ...");
		fflush(stdout);

		/* z is still the group order */
		if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT;
		if (!EC_POINTs_mul(group, R, z, 2, points, scalars, ctx)) ABORT;
		if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT;
		if (0 != EC_POINT_cmp(group, R, Q, ctx)) ABORT;

		fprintf(stdout, ".");
		fflush(stdout);

		if (!BN_pseudo_rand(y, BN_num_bits(y), 0, 0)) ABORT;
		if (!BN_add(z, z, y)) ABORT;
		BN_set_negative(z, 1);
		scalars[0] = y;
		scalars[1] = z; /* z = -(order + y) */

		if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT;
		if (!EC_POINT_is_at_infinity(group, P)) ABORT;

		fprintf(stdout, ".");
		fflush(stdout);

		if (!BN_pseudo_rand(x, BN_num_bits(y) - 1, 0, 0)) ABORT;
		if (!BN_add(z, x, y)) ABORT;
		BN_set_negative(z, 1);
		scalars[0] = x;
		scalars[1] = y;
		scalars[2] = z; /* z = -(x+y) */

		if (!EC_POINTs_mul(group, P, NULL, 3, points, scalars, ctx)) ABORT;
		if (!EC_POINT_is_at_infinity(group, P)) ABORT;

		fprintf(stdout, " ok\n\n");
	}


#if 0
	timings(C2_K163, TIMING_BASE_PT, ctx);
	timings(C2_K163, TIMING_RAND_PT, ctx);
	timings(C2_K163, TIMING_SIMUL, ctx);
	timings(C2_B163, TIMING_BASE_PT, ctx);
	timings(C2_B163, TIMING_RAND_PT, ctx);
	timings(C2_B163, TIMING_SIMUL, ctx);
	timings(C2_K233, TIMING_BASE_PT, ctx);
	timings(C2_K233, TIMING_RAND_PT, ctx);
	timings(C2_K233, TIMING_SIMUL, ctx);
	timings(C2_B233, TIMING_BASE_PT, ctx);
	timings(C2_B233, TIMING_RAND_PT, ctx);
	timings(C2_B233, TIMING_SIMUL, ctx);
	timings(C2_K283, TIMING_BASE_PT, ctx);
	timings(C2_K283, TIMING_RAND_PT, ctx);
	timings(C2_K283, TIMING_SIMUL, ctx);
	timings(C2_B283, TIMING_BASE_PT, ctx);
	timings(C2_B283, TIMING_RAND_PT, ctx);
	timings(C2_B283, TIMING_SIMUL, ctx);
	timings(C2_K409, TIMING_BASE_PT, ctx);
	timings(C2_K409, TIMING_RAND_PT, ctx);
	timings(C2_K409, TIMING_SIMUL, ctx);
	timings(C2_B409, TIMING_BASE_PT, ctx);
	timings(C2_B409, TIMING_RAND_PT, ctx);
	timings(C2_B409, TIMING_SIMUL, ctx);
	timings(C2_K571, TIMING_BASE_PT, ctx);
	timings(C2_K571, TIMING_RAND_PT, ctx);
	timings(C2_K571, TIMING_SIMUL, ctx);
	timings(C2_B571, TIMING_BASE_PT, ctx);
	timings(C2_B571, TIMING_RAND_PT, ctx);
	timings(C2_B571, TIMING_SIMUL, ctx);
#endif


	if (ctx)
		BN_CTX_free(ctx);
	BN_free(p); BN_free(a);	BN_free(b);
	EC_GROUP_free(group);
	EC_POINT_free(P);
	EC_POINT_free(Q);
	EC_POINT_free(R);
	BN_free(x); BN_free(y); BN_free(z); BN_free(cof);

	if (C2_K163) EC_GROUP_free(C2_K163);
	if (C2_B163) EC_GROUP_free(C2_B163);
	if (C2_K233) EC_GROUP_free(C2_K233);
	if (C2_B233) EC_GROUP_free(C2_B233);
	if (C2_K283) EC_GROUP_free(C2_K283);
	if (C2_B283) EC_GROUP_free(C2_B283);
	if (C2_K409) EC_GROUP_free(C2_K409);
	if (C2_B409) EC_GROUP_free(C2_B409);
	if (C2_K571) EC_GROUP_free(C2_K571);
	if (C2_B571) EC_GROUP_free(C2_B571);

	}
Пример #17
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;
	}
Пример #18
0
int GOST_KEY_check_key(const GOST_KEY *key)
{
    int ok = 0;
    BN_CTX *ctx = NULL;
    BIGNUM *order = NULL;
    EC_POINT *point = NULL;

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

    /* testing whether the pub_key is on the elliptic curve */
    if (EC_POINT_is_on_curve(key->group, key->pub_key, ctx) <= 0) {
        GOSTerr(GOST_F_GOST_KEY_CHECK_KEY, EC_R_POINT_IS_NOT_ON_CURVE);
        goto err;
    }
    /* testing whether pub_key * order is the point at infinity */
    if ((order = BN_new()) == NULL)
        goto err;
    if (!EC_GROUP_get_order(key->group, order, ctx)) {
        GOSTerr(GOST_F_GOST_KEY_CHECK_KEY, EC_R_INVALID_GROUP_ORDER);
        goto err;
    }
    if (!EC_POINT_mul(key->group, point, NULL, key->pub_key, order, ctx)) {
        GOSTerr(GOST_F_GOST_KEY_CHECK_KEY, ERR_R_EC_LIB);
        goto err;
    }
    if (!EC_POINT_is_at_infinity(key->group, point)) {
        GOSTerr(GOST_F_GOST_KEY_CHECK_KEY, EC_R_WRONG_ORDER);
        goto err;
    }
    /*
     * in case the priv_key is present : check if generator * priv_key ==
     * pub_key
     */
    if (key->priv_key) {
        if (BN_cmp(key->priv_key, order) >= 0) {
            GOSTerr(GOST_F_GOST_KEY_CHECK_KEY, EC_R_WRONG_ORDER);
            goto err;
        }
        if (!EC_POINT_mul(key->group, point, key->priv_key, NULL, NULL, ctx)) {
            GOSTerr(GOST_F_GOST_KEY_CHECK_KEY, ERR_R_EC_LIB);
            goto err;
        }
        if (EC_POINT_cmp(key->group, point, key->pub_key, ctx) != 0) {
            GOSTerr(GOST_F_GOST_KEY_CHECK_KEY, EC_R_INVALID_PRIVATE_KEY);
            goto err;
        }
    }
    ok = 1;
err:
    BN_free(order);
    BN_CTX_free(ctx);
    EC_POINT_free(point);
    return (ok);
}
Пример #19
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) > 0) {
		return EC_POINT_is_at_infinity(group, b) > 0 ? 0 : 1;
	}
	if (EC_POINT_is_at_infinity(group, b) > 0)
		return 1;

	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);
	if ((tmp1 = BN_CTX_get(ctx)) == NULL)
		goto end;
	if ((tmp2 = BN_CTX_get(ctx)) == NULL)
		goto end;
	if ((Za23 = BN_CTX_get(ctx)) == NULL)
		goto end;
	if ((Zb23 = BN_CTX_get(ctx)) == 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))
			goto end;
		if (!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))
			goto end;
		if (!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))
			goto end;
		if (!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))
			goto end;
		if (!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;
}
Пример #20
0
static size_t ec_GFp_simple_point2oct(const EC_GROUP *group,
                                      const EC_POINT *point,
                                      point_conversion_form_t form,
                                      uint8_t *buf, size_t len, BN_CTX *ctx) {
  size_t ret;
  BN_CTX *new_ctx = NULL;
  int used_ctx = 0;
  BIGNUM *x, *y;
  size_t field_len, i;

  if ((form != POINT_CONVERSION_COMPRESSED) &&
      (form != POINT_CONVERSION_UNCOMPRESSED)) {
    OPENSSL_PUT_ERROR(EC, EC_R_INVALID_FORM);
    goto err;
  }

  if (EC_POINT_is_at_infinity(group, point)) {
    OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY);
    goto err;
  }

  /* ret := required output buffer length */
  field_len = BN_num_bytes(&group->field);
  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) {
      OPENSSL_PUT_ERROR(EC, EC_R_BUFFER_TOO_SMALL);
      goto err;
    }

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

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

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

    if ((form == POINT_CONVERSION_COMPRESSED) &&
        BN_is_odd(y)) {
      buf[0] = form + 1;
    } else {
      buf[0] = form;
    }
    i = 1;

    if (!BN_bn2bin_padded(buf + i, field_len, x)) {
      OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
      goto err;
    }
    i += field_len;

    if (form == POINT_CONVERSION_UNCOMPRESSED) {
      if (!BN_bn2bin_padded(buf + i, field_len, y)) {
        OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
        goto err;
      }
      i += field_len;
    }

    if (i != ret) {
      OPENSSL_PUT_ERROR(EC, 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;
}
Пример #21
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) > 0)
		return EC_POINT_copy(r, b);
	if (EC_POINT_is_at_infinity(group, b) > 0)
		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);
	if ((n0 = BN_CTX_get(ctx)) == NULL)
		goto end;
	if ((n1 = BN_CTX_get(ctx)) == NULL)
		goto end;
	if ((n2 = BN_CTX_get(ctx)) == NULL)
		goto end;
	if ((n3 = BN_CTX_get(ctx)) == NULL)
		goto end;
	if ((n4 = BN_CTX_get(ctx)) == NULL)
		goto end;
	if ((n5 = BN_CTX_get(ctx)) == NULL)
		goto end;
	if ((n6 = BN_CTX_get(ctx)) == 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 */
	if (b->Z_is_one) {
		if (!BN_copy(n1, &a->X))
			goto end;
		if (!BN_copy(n2, &a->Y))
			goto end;
		/* n1 = X_a */
		/* n2 = Y_a */
	} else {
		if (!field_sqr(group, n0, &b->Z, ctx))
			goto end;
		if (!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))
			goto end;
		if (!field_mul(group, n2, &a->Y, n0, ctx))
			goto end;
		/* n2 = Y_a * Z_b^3 */
	}

	/* n3, n4 */
	if (a->Z_is_one) {
		if (!BN_copy(n3, &b->X))
			goto end;
		if (!BN_copy(n4, &b->Y))
			goto end;
		/* n3 = X_b */
		/* n4 = Y_b */
	} else {
		if (!field_sqr(group, n0, &a->Z, ctx))
			goto end;
		if (!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))
			goto end;
		if (!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))
		goto end;
	if (!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);
			r->Z_is_one = 0;
			ret = 1;
			goto end;
		}
	}
	/* 'n7', 'n8' */
	if (!BN_mod_add_quick(n1, n1, n3, p))
		goto end;
	if (!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;
	}
	r->Z_is_one = 0;
	/* Z_r = Z_a * Z_b * n5 */

	/* X_r */
	if (!field_sqr(group, n0, n6, ctx))
		goto end;
	if (!field_sqr(group, n4, n5, ctx))
		goto end;
	if (!field_mul(group, n3, n1, n4, ctx))
		goto end;
	if (!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))
		goto end;
	if (!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))
		goto end;
	if (!field_mul(group, n5, n4, n5, ctx))
		goto end;	/* now n5 is n5^3 */
	if (!field_mul(group, n1, n2, n5, ctx))
		goto end;
	if (!BN_mod_sub_quick(n0, n0, n1, p))
		goto end;
	if (BN_is_odd(n0))
		if (!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;
}
Пример #22
0
size_t ec_GFp_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;
	size_t field_len, i, skip;

	if ((form != POINT_CONVERSION_COMPRESSED)
		&& (form != POINT_CONVERSION_UNCOMPRESSED)
		&& (form != POINT_CONVERSION_HYBRID))
		{
		ECerr(EC_F_EC_GFP_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_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
				return 0;
				}
			buf[0] = 0;
			}
		return 1;
		}


	/* ret := required output buffer length */
	field_len = BN_num_bytes(&group->field);
	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_GFP_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);
		if (y == NULL) goto err;

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

		if ((form == POINT_CONVERSION_COMPRESSED || form == POINT_CONVERSION_HYBRID) && BN_is_odd(y))
			buf[0] = form + 1;
		else
			buf[0] = form;
	
		i = 1;
		
		skip = field_len - BN_num_bytes(x);
		if (skip > field_len)
			{
			ECerr(EC_F_EC_GFP_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_GFP_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_GFP_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_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
			goto err;
			}
		}
	
	if (used_ctx)
		BN_CTX_end(ctx);
	if (new_ctx != NULL)
		BN_CTX_free(new_ctx);
	return ret;

 err:
	if (used_ctx)
		BN_CTX_end(ctx);
	if (new_ctx != NULL)
		BN_CTX_free(new_ctx);
	return 0;
	}
Пример #23
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 = -1;

	if (EC_POINT_is_at_infinity(group, point) > 0)
		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 -1;
	}
	BN_CTX_start(ctx);
	if ((rh = BN_CTX_get(ctx)) == NULL)
		goto err;
	if ((tmp = BN_CTX_get(ctx)) == NULL)
		goto err;
	if ((Z4 = BN_CTX_get(ctx)) == NULL)
		goto err;
	if ((Z6 = BN_CTX_get(ctx)) == 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 (!point->Z_is_one) {
		if (!field_sqr(group, tmp, &point->Z, ctx))
			goto err;
		if (!field_sqr(group, Z4, tmp, ctx))
			goto err;
		if (!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))
				goto err;
			if (!BN_mod_add_quick(tmp, tmp, Z4, p))
				goto err;
			if (!BN_mod_sub_quick(rh, rh, tmp, p))
				goto err;
			if (!field_mul(group, rh, rh, &point->X, ctx))
				goto err;
		} else {
			if (!field_mul(group, tmp, Z4, &group->a, ctx))
				goto err;
			if (!BN_mod_add_quick(rh, rh, tmp, p))
				goto err;
			if (!field_mul(group, rh, rh, &point->X, ctx))
				goto err;
		}

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

		/* rh := (rh + a)*X */
		if (!BN_mod_add_quick(rh, rh, &group->a, p))
			goto err;
		if (!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;
}
Пример #24
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;
}
Пример #25
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 ((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);
	if (point != NULL)
		EC_POINT_free(point);
	return(ok);
	}
Пример #26
0
// unsigned char *pC      输出,密文
// unsigned char *pPxKey, unsigned char *pPyKey  公钥
// unsigned char *pM      明文
// unsigned long MLen     明文长度
unsigned char eccEncrypt(unsigned char *pC, 
						 unsigned char *pPxKey, unsigned char *pPyKey, 
						 unsigned char *pM, unsigned long MLen)
{
	// NID_sm2p256v1
	EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_sm2p256v1);
	//// 相当于
	//EC_KEY *ret = EC_KEY_new();
	EC_GROUP *ec_group = EC_GROUP_new_by_curve_name(NID_sm2p256v1);

	KDF_FUNC kdf = KDF_get_x9_63(EVP_sm3());;

	EC_POINT *point = NULL;
	//// 设置私钥
	//BIGNUM *d = NULL;
	//BN_hex2bn(&d, pPDKey);
	//EC_KEY_set_private_key(ec_key, d);
	int ret = 1;

	BIGNUM *x = BN_new();;
	BIGNUM *y = BN_new();;
	if (!BN_bin2bn(pPxKey, 32, x)) {
		goto end;
	}
	if (!BN_bin2bn(pPyKey, 32, y)) {
		goto end;
	}
	if (!EC_KEY_set_public_key_affine_coordinates(ec_key, x, y)) {
		goto end;
	}
	const EC_POINT *pub_key = EC_KEY_get0_public_key(ec_key);
	/* init ec domain parameters */
	BIGNUM *n = NULL;
	BIGNUM *h = NULL;
	BIGNUM *k = NULL;
	n = BN_new();
	h = BN_new();
	k = BN_new();
	BN_CTX *bn_ctx = NULL;
	bn_ctx = BN_CTX_new();
	if (!EC_GROUP_get_order(ec_group, n, bn_ctx)) {
		goto end;
	}
	if (!EC_GROUP_get_cofactor(ec_group, h, bn_ctx)) {
		goto end;
	}
	int nbytes = (EC_GROUP_get_degree(ec_group) + 7) / 8;

	EC_POINT *ec_point = EC_POINT_new(ec_group);
	point = EC_POINT_new(ec_group);
	unsigned char buf[(OPENSSL_ECC_MAX_FIELD_BITS + 7)/4 + 1];
	size_t len;
	char *ciphertext = (char *)OPENSSL_malloc(MLen);
	size_t ciphertext_size = MLen;
	do
	{
		/* A1: rand k in [1, n-1] */
		do {
			BN_rand_range(k, n);
		} while (BN_is_zero(k));

		/* A2: C1 = [k]G = (x1, y1) */
		if (!EC_POINT_mul(ec_group, ec_point, k, NULL, NULL, bn_ctx)) {
			goto end;
		}
#if 1
		if (!(len = EC_POINT_point2oct(ec_group, ec_point,
			POINT_CONVERSION_UNCOMPRESSED, buf, sizeof(buf), bn_ctx))) {
				goto end;
		}
		BN_bin2bn(buf, 65, n);
		printf(BN_bn2hex(n));
		printf("\n");
		printf(BN_bn2hex(k));
#endif
		/* A3: check [h]P_B != O */
		if (!EC_POINT_mul(ec_group, point, NULL, pub_key, h, bn_ctx)) {
			goto end;
		}
		if (EC_POINT_is_at_infinity(ec_group, point)) {
			goto end;
		}

		/* A4: compute ECDH [k]P_B = (x2, y2) */
		if (!EC_POINT_mul(ec_group, point, NULL, pub_key, k, bn_ctx)) {
			goto end;
		}
		if (!(len = EC_POINT_point2oct(ec_group, point,
			POINT_CONVERSION_UNCOMPRESSED, buf, sizeof(buf), bn_ctx))) {
				goto end;
		}
		OPENSSL_assert(len == nbytes * 2 + 1);

		/* A5: t = KDF(x2 || y2, klen) */
		kdf(buf + 1, len - 1, (unsigned char *)ciphertext, &ciphertext_size);

		// 防止全0
		size_t i = 0;
		for (i = 0; i < ciphertext_size; i++) {
			if (ciphertext[i]) {
				break;
			}
		}
		if (i == ciphertext_size) {
			continue;
		}
		break;
	} while (1);


	/* A6: C2 = M xor t */
	for (size_t i = 0; i < MLen; i++) {
		ciphertext[i] ^= pM[i];
	}

	unsigned char dgst[EVP_MAX_MD_SIZE];
	unsigned int dgstlen;
	EVP_MD_CTX *md_ctx = EVP_MD_CTX_create();
	if (1) {

		/* A7: C3 = Hash(x2 || M || y2) */
		if (!EVP_DigestInit_ex(md_ctx, EVP_sm3(), NULL)) {
			goto end;
		}
		if (!EVP_DigestUpdate(md_ctx, buf + 1, nbytes)) {
			goto end;
		}
		if (!EVP_DigestUpdate(md_ctx, pM, MLen)) {
			goto end;
		}
		if (!EVP_DigestUpdate(md_ctx, buf + 1 + nbytes, nbytes)) {
			goto end;
		}
		if (!EVP_DigestFinal_ex(md_ctx, dgst, &dgstlen)) {
			goto end;
		}
	}

	EC_POINT_point2oct(ec_group, point, POINT_CONVERSION_UNCOMPRESSED, pC, 65, NULL);
	memcpy(&pC[65], ciphertext, MLen);
	memcpy(&pC[65 + MLen], dgst, dgstlen);
ret = 0;
end:

	if (point) EC_POINT_free(point);
	if (n) BN_free(n);
	if (h) BN_free(h);
	if (k) BN_free(k);
	if (bn_ctx) BN_CTX_free(bn_ctx);
	if (md_ctx) EVP_MD_CTX_destroy(md_ctx);

	return ret;
}