sync code with last fixes and improvements from OpenBSD

This commit is contained in:
purplerain 2023-07-27 09:35:44 +00:00
parent 58df21ce75
commit f960599e67
Signed by: purplerain
GPG key ID: F42C07F07E2E35B7
399 changed files with 7016 additions and 6902 deletions

View file

@ -1,4 +1,4 @@
/* $OpenBSD: ec_lib.c,v 1.64 2023/07/07 19:37:53 beck Exp $ */
/* $OpenBSD: ec_lib.c,v 1.65 2023/07/25 06:57:26 tb Exp $ */
/*
* Originally written by Bodo Moeller for the OpenSSL project.
*/
@ -1062,7 +1062,7 @@ EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
BN_CTX *ctx_in)
{
BN_CTX *ctx;
int ret = 0;
int ret = -1;
if ((ctx = ctx_in) == NULL)
ctx = BN_CTX_new();

View file

@ -1,4 +1,4 @@
/* $OpenBSD: ecp_smpl.c,v 1.46 2023/07/07 13:54:45 beck Exp $ */
/* $OpenBSD: ecp_smpl.c,v 1.55 2023/07/26 17:15:25 tb Exp $ */
/* Includes code written by Lenka Fibikova <fibikova@exp-math.uni-essen.de>
* for the OpenSSL project.
* Includes code written by Bodo Moeller for the OpenSSL project.
@ -114,11 +114,52 @@ ec_GFp_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
return 1;
}
static int
ec_decode_scalar(const EC_GROUP *group, BIGNUM *bn, const BIGNUM *x, BN_CTX *ctx)
{
if (bn == NULL)
return 1;
if (group->meth->field_decode != NULL)
return group->meth->field_decode(group, bn, x, ctx);
return bn_copy(bn, x);
}
static int
ec_encode_scalar(const EC_GROUP *group, BIGNUM *bn, const BIGNUM *x, BN_CTX *ctx)
{
if (!BN_nnmod(bn, x, &group->field, ctx))
return 0;
if (group->meth->field_encode != NULL)
return group->meth->field_encode(group, bn, bn, ctx);
return 1;
}
static int
ec_encode_z_coordinate(const EC_GROUP *group, BIGNUM *bn, int *is_one,
const BIGNUM *z, BN_CTX *ctx)
{
if (!BN_nnmod(bn, z, &group->field, ctx))
return 0;
*is_one = BN_is_one(bn);
if (*is_one && group->meth->field_set_to_one != NULL)
return group->meth->field_set_to_one(group, bn, ctx);
if (group->meth->field_encode != NULL)
return group->meth->field_encode(group, bn, bn, ctx);
return 1;
}
int
ec_GFp_simple_group_set_curve(EC_GROUP *group,
const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
{
BIGNUM *tmp_a;
BIGNUM *a_plus_3;
int ret = 0;
/* p must be a prime > 3 */
@ -129,34 +170,24 @@ ec_GFp_simple_group_set_curve(EC_GROUP *group,
BN_CTX_start(ctx);
if ((tmp_a = BN_CTX_get(ctx)) == NULL)
if ((a_plus_3 = BN_CTX_get(ctx)) == NULL)
goto err;
/* group->field */
if (!bn_copy(&group->field, p))
goto err;
BN_set_negative(&group->field, 0);
/* group->a */
if (!BN_nnmod(tmp_a, a, p, ctx))
if (!ec_encode_scalar(group, &group->a, a, ctx))
goto err;
if (group->meth->field_encode) {
if (!group->meth->field_encode(group, &group->a, tmp_a, ctx))
goto err;
} else if (!bn_copy(&group->a, tmp_a))
if (!ec_encode_scalar(group, &group->b, b, ctx))
goto err;
/* group->b */
if (!BN_nnmod(&group->b, b, p, ctx))
if (!BN_set_word(a_plus_3, 3))
goto err;
if (!BN_mod_add(a_plus_3, a_plus_3, a, &group->field, ctx))
goto err;
if (group->meth->field_encode)
if (!group->meth->field_encode(group, &group->b, &group->b, ctx))
goto err;
/* group->a_is_minus3 */
if (!BN_add_word(tmp_a, 3))
goto err;
group->a_is_minus3 = (0 == BN_cmp(tmp_a, &group->field));
group->a_is_minus3 = BN_is_zero(a_plus_3);
ret = 1;
@ -167,31 +198,17 @@ ec_GFp_simple_group_set_curve(EC_GROUP *group,
}
int
ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
BIGNUM *b, BN_CTX *ctx)
{
if (p != NULL) {
if (!bn_copy(p, &group->field))
return 0;
}
if (group->meth->field_decode != NULL) {
if (a != NULL) {
if (!group->meth->field_decode(group, a, &group->a, ctx))
return 0;
}
if (b != NULL) {
if (!group->meth->field_decode(group, b, &group->b, ctx))
return 0;
}
} else {
if (a != NULL) {
if (!bn_copy(a, &group->a))
return 0;
}
if (b != NULL) {
if (!bn_copy(b, &group->b))
return 0;
}
}
if (!ec_decode_scalar(group, a, &group->a, ctx))
return 0;
if (!ec_decode_scalar(group, b, &group->b, ctx))
return 0;
return 1;
}
@ -205,62 +222,52 @@ ec_GFp_simple_group_get_degree(const EC_GROUP *group)
int
ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
{
BIGNUM *a, *b, *order, *tmp_1, *tmp_2;
const BIGNUM *p = &group->field;
BIGNUM *p, *a, *b, *discriminant;
int ret = 0;
BN_CTX_start(ctx);
if ((p = BN_CTX_get(ctx)) == NULL)
goto err;
if ((a = BN_CTX_get(ctx)) == NULL)
goto err;
if ((b = BN_CTX_get(ctx)) == NULL)
goto err;
if ((tmp_1 = BN_CTX_get(ctx)) == NULL)
goto err;
if ((tmp_2 = BN_CTX_get(ctx)) == NULL)
goto err;
if ((order = BN_CTX_get(ctx)) == NULL)
if ((discriminant = BN_CTX_get(ctx)) == NULL)
goto err;
if (group->meth->field_decode) {
if (!group->meth->field_decode(group, a, &group->a, ctx))
goto err;
if (!group->meth->field_decode(group, b, &group->b, ctx))
goto err;
} else {
if (!bn_copy(a, &group->a))
goto err;
if (!bn_copy(b, &group->b))
goto err;
}
if (!EC_GROUP_get_curve(group, p, a, b, ctx))
goto err;
/*
* check the discriminant: y^2 = x^3 + a*x + b is an elliptic curve
* <=> 4*a^3 + 27*b^2 != 0 (mod p) 0 =< a, b < p
* Check that the discriminant 4a^3 + 27b^2 is non-zero modulo p.
*/
if (BN_is_zero(a)) {
if (BN_is_zero(b))
goto err;
} else if (!BN_is_zero(b)) {
if (!BN_mod_sqr(tmp_1, a, p, ctx))
goto err;
if (!BN_mod_mul(tmp_2, tmp_1, a, p, ctx))
goto err;
if (!BN_lshift(tmp_1, tmp_2, 2))
goto err;
/* tmp_1 = 4*a^3 */
if (!BN_mod_sqr(tmp_2, b, p, ctx))
goto err;
if (!BN_mul_word(tmp_2, 27))
goto err;
/* tmp_2 = 27*b^2 */
if (BN_is_zero(a) && BN_is_zero(b))
goto err;
if (BN_is_zero(a) || BN_is_zero(b))
goto done;
if (!BN_mod_add(a, tmp_1, tmp_2, p, ctx))
goto err;
if (BN_is_zero(a))
goto err;
}
/* Compute the discriminant: first 4a^3, then 27b^2, then their sum. */
if (!BN_mod_sqr(discriminant, a, p, ctx))
goto err;
if (!BN_mod_mul(discriminant, discriminant, a, p, ctx))
goto err;
if (!BN_lshift(discriminant, discriminant, 2))
goto err;
if (!BN_mod_sqr(b, b, p, ctx))
goto err;
if (!BN_mul_word(b, 27))
goto err;
if (!BN_mod_add(discriminant, discriminant, b, p, ctx))
goto err;
if (BN_is_zero(discriminant))
goto err;
done:
ret = 1;
err:
@ -318,39 +325,25 @@ ec_GFp_simple_set_Jprojective_coordinates(const EC_GROUP *group,
{
int ret = 0;
/*
* Setting individual coordinates allows the creation of bad points.
* EC_POINT_set_Jprojective_coordinates() checks at the API boundary.
*/
if (x != NULL) {
if (!BN_nnmod(&point->X, x, &group->field, ctx))
if (!ec_encode_scalar(group, &point->X, x, ctx))
goto err;
if (group->meth->field_encode != NULL) {
if (!group->meth->field_encode(group, &point->X, &point->X, ctx))
goto err;
}
}
if (y != NULL) {
if (!BN_nnmod(&point->Y, y, &group->field, ctx))
if (!ec_encode_scalar(group, &point->Y, y, ctx))
goto err;
if (group->meth->field_encode != NULL) {
if (!group->meth->field_encode(group, &point->Y, &point->Y, ctx))
goto err;
}
}
if (z != NULL) {
int Z_is_one;
if (!BN_nnmod(&point->Z, z, &group->field, ctx))
if (!ec_encode_z_coordinate(group, &point->Z, &point->Z_is_one,
z, ctx))
goto err;
Z_is_one = BN_is_one(&point->Z);
if (group->meth->field_encode != NULL) {
if (Z_is_one && (group->meth->field_set_to_one != 0)) {
if (!group->meth->field_set_to_one(group, &point->Z, ctx))
goto err;
} else {
if (!group->meth->field_encode(group, &point->Z, &point->Z, ctx))
goto err;
}
}
point->Z_is_one = Z_is_one;
}
ret = 1;
err:
@ -363,33 +356,12 @@ ec_GFp_simple_get_Jprojective_coordinates(const EC_GROUP *group,
{
int ret = 0;
if (group->meth->field_decode != NULL) {
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;
}
if (z != NULL) {
if (!group->meth->field_decode(group, z, &point->Z, 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;
}
if (z != NULL) {
if (!bn_copy(z, &point->Z))
goto err;
}
}
if (!ec_decode_scalar(group, x, &point->X, ctx))
goto err;
if (!ec_decode_scalar(group, y, &point->Y, ctx))
goto err;
if (!ec_decode_scalar(group, z, &point->Z, ctx))
goto err;
ret = 1;
@ -411,11 +383,10 @@ ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *group, EC_POINT *poin
}
int
ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point,
BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group,
const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
{
BIGNUM *Z, *Z_1, *Z_2, *Z_3;
const BIGNUM *Z_;
BIGNUM *z, *Z, *Z_1, *Z_2, *Z_3;
int ret = 0;
if (EC_POINT_is_at_infinity(group, point) > 0) {
@ -425,6 +396,8 @@ ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT
BN_CTX_start(ctx);
if ((z = BN_CTX_get(ctx)) == NULL)
goto err;
if ((Z = BN_CTX_get(ctx)) == NULL)
goto err;
if ((Z_1 = BN_CTX_get(ctx)) == NULL)
@ -434,77 +407,59 @@ ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT
if ((Z_3 = BN_CTX_get(ctx)) == NULL)
goto err;
/* transform (X, Y, Z) into (x, y) := (X/Z^2, Y/Z^3) */
/* Convert from projective coordinates (X, Y, Z) into (X/Z^2, Y/Z^3). */
if (group->meth->field_decode) {
if (!group->meth->field_decode(group, Z, &point->Z, ctx))
if (!ec_decode_scalar(group, z, &point->Z, ctx))
goto err;
if (BN_is_one(z)) {
if (!ec_decode_scalar(group, x, &point->X, ctx))
goto err;
Z_ = Z;
} else {
Z_ = &point->Z;
if (!ec_decode_scalar(group, y, &point->Y, ctx))
goto err;
goto done;
}
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_ct(Z_1, Z_, &group->field, ctx) == NULL) {
ECerror(ERR_R_BN_LIB);
if (BN_mod_inverse_ct(Z_1, z, &group->field, ctx) == NULL) {
ECerror(ERR_R_BN_LIB);
goto err;
}
if (group->meth->field_encode == NULL) {
/* 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 (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;
}
}
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 == NULL) {
/* 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;
}
done:
ret = 1;
err:
@ -704,11 +659,9 @@ ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX
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;
}
if (EC_POINT_is_at_infinity(group, a) > 0)
return EC_POINT_set_to_infinity(group, r);
field_mul = group->meth->field_mul;
field_sqr = group->meth->field_sqr;
p = &group->field;
@ -1162,7 +1115,7 @@ ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT *po
goto err;
}
}
if (group->meth->field_encode != 0) {
if (group->meth->field_encode != NULL) {
/*
* in the Montgomery case, we just turned R*H (representing
* H) into 1/(R*H), but we need R*(1/H) (representing
@ -1212,7 +1165,7 @@ ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT *po
if (!group->meth->field_mul(group, &p->Y, &p->Y, tmp1, ctx))
goto err;
if (group->meth->field_set_to_one != 0) {
if (group->meth->field_set_to_one != NULL) {
if (!group->meth->field_set_to_one(group, &p->Z, ctx))
goto err;
} else {
@ -1273,7 +1226,7 @@ ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx)
if ((tmp = BN_CTX_get(ctx)) == NULL)
goto err;
/* Generate lambda in [1, group->field - 1] */
/* Generate lambda in [1, group->field). */
if (!bn_rand_interval(lambda, BN_value_one(), &group->field))
goto err;

View file

@ -1,4 +1,4 @@
/* $OpenBSD: ecx_methods.c,v 1.7 2023/07/05 20:56:29 bcook Exp $ */
/* $OpenBSD: ecx_methods.c,v 1.9 2023/07/22 19:33:25 tb Exp $ */
/*
* Copyright (c) 2022 Joel Sing <jsing@openbsd.org>
*
@ -292,6 +292,42 @@ ecx_pub_cmp(const EVP_PKEY *pkey1, const EVP_PKEY *pkey2)
pkey1->pkey.ecx->pub_key_len) == 0;
}
/* Reimplementation of ASN1_buf_print() that adds a secondary indent of 4. */
static int
ecx_buf_print(BIO *bio, const uint8_t *buf, size_t buf_len, int indent)
{
uint8_t u8;
size_t octets = 0;
const char *sep = ":", *nl = "";
CBS cbs;
if (indent > 60)
indent = 60;
indent += 4;
if (indent < 0)
indent = 0;
CBS_init(&cbs, buf, buf_len);
while (CBS_len(&cbs) > 0) {
if (!CBS_get_u8(&cbs, &u8))
return 0;
if (octets++ % 15 == 0) {
if (BIO_printf(bio, "%s%*s", nl, indent, "") < 0)
return 0;
nl = "\n";
}
if (CBS_len(&cbs) == 0)
sep = "";
if (BIO_printf(bio, "%02x%s", u8, sep) <= 0)
return 0;
}
if (BIO_printf(bio, "\n") <= 0)
return 0;
return 1;
}
static int
ecx_pub_print(BIO *bio, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx)
{
@ -309,8 +345,7 @@ ecx_pub_print(BIO *bio, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx)
return 0;
if (BIO_printf(bio, "%*spub:\n", indent, "") <= 0)
return 0;
if (ASN1_buf_print(bio, ecx_key->pub_key, ecx_key->pub_key_len,
indent + 4) == 0)
if (!ecx_buf_print(bio, ecx_key->pub_key, ecx_key->pub_key_len, indent))
return 0;
return 1;
@ -422,13 +457,11 @@ ecx_priv_print(BIO *bio, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx)
return 0;
if (BIO_printf(bio, "%*spriv:\n", indent, "") <= 0)
return 0;
if (ASN1_buf_print(bio, ecx_key->priv_key, ecx_key->priv_key_len,
indent + 4) == 0)
if (!ecx_buf_print(bio, ecx_key->priv_key, ecx_key->priv_key_len, indent))
return 0;
if (BIO_printf(bio, "%*spub:\n", indent, "") <= 0)
return 0;
if (ASN1_buf_print(bio, ecx_key->pub_key, ecx_key->pub_key_len,
indent + 4) == 0)
if (!ecx_buf_print(bio, ecx_key->pub_key, ecx_key->pub_key_len, indent))
return 0;
return 1;