mirror of
https://github.com/openssl/openssl.git
synced 2024-12-09 05:51:54 +08:00
f667820c16
This commit implements coordinate blinding, i.e., it randomizes the representative of an elliptic curve point in its equivalence class, for prime curves implemented through EC_GFp_simple_method, EC_GFp_mont_method, and EC_GFp_nist_method. This commit is derived from the patch https://marc.info/?l=openssl-dev&m=131194808413635 by Billy Brumley. Coordinate blinding is a generally useful side-channel countermeasure and is (mostly) free. The function itself takes a few field multiplicationss, but is usually only necessary at the beginning of a scalar multiplication (as implemented in the patch). When used this way, it makes the values that variables take (i.e., field elements in an algorithm state) unpredictable. For instance, this mitigates chosen EC point side-channel attacks for settings such as ECDH and EC private key decryption, for the aforementioned curves. For EC_METHODs using different coordinate representations this commit does nothing, but the corresponding coordinate blinding function can be easily added in the future to extend these changes to such curves. Co-authored-by: Nicola Tuveri <nic.tuv@gmail.com> Co-authored-by: Billy Brumley <bbrumley@gmail.com> Reviewed-by: Andy Polyakov <appro@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/6501)
165 lines
4.7 KiB
C
165 lines
4.7 KiB
C
/*
|
|
* Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
|
|
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
|
|
*
|
|
* Licensed under the OpenSSL license (the "License"). You may not use
|
|
* this file except in compliance with the License. You can obtain a copy
|
|
* in the file LICENSE in the source distribution or at
|
|
* https://www.openssl.org/source/license.html
|
|
*/
|
|
|
|
#include <limits.h>
|
|
|
|
#include <openssl/err.h>
|
|
#include <openssl/obj_mac.h>
|
|
#include "ec_lcl.h"
|
|
|
|
const EC_METHOD *EC_GFp_nist_method(void)
|
|
{
|
|
static const EC_METHOD ret = {
|
|
EC_FLAGS_DEFAULT_OCT,
|
|
NID_X9_62_prime_field,
|
|
ec_GFp_simple_group_init,
|
|
ec_GFp_simple_group_finish,
|
|
ec_GFp_simple_group_clear_finish,
|
|
ec_GFp_nist_group_copy,
|
|
ec_GFp_nist_group_set_curve,
|
|
ec_GFp_simple_group_get_curve,
|
|
ec_GFp_simple_group_get_degree,
|
|
ec_group_simple_order_bits,
|
|
ec_GFp_simple_group_check_discriminant,
|
|
ec_GFp_simple_point_init,
|
|
ec_GFp_simple_point_finish,
|
|
ec_GFp_simple_point_clear_finish,
|
|
ec_GFp_simple_point_copy,
|
|
ec_GFp_simple_point_set_to_infinity,
|
|
ec_GFp_simple_set_Jprojective_coordinates_GFp,
|
|
ec_GFp_simple_get_Jprojective_coordinates_GFp,
|
|
ec_GFp_simple_point_set_affine_coordinates,
|
|
ec_GFp_simple_point_get_affine_coordinates,
|
|
0, 0, 0,
|
|
ec_GFp_simple_add,
|
|
ec_GFp_simple_dbl,
|
|
ec_GFp_simple_invert,
|
|
ec_GFp_simple_is_at_infinity,
|
|
ec_GFp_simple_is_on_curve,
|
|
ec_GFp_simple_cmp,
|
|
ec_GFp_simple_make_affine,
|
|
ec_GFp_simple_points_make_affine,
|
|
0 /* mul */ ,
|
|
0 /* precompute_mult */ ,
|
|
0 /* have_precompute_mult */ ,
|
|
ec_GFp_nist_field_mul,
|
|
ec_GFp_nist_field_sqr,
|
|
0 /* field_div */ ,
|
|
0 /* field_encode */ ,
|
|
0 /* field_decode */ ,
|
|
0, /* field_set_to_one */
|
|
ec_key_simple_priv2oct,
|
|
ec_key_simple_oct2priv,
|
|
0, /* set private */
|
|
ec_key_simple_generate_key,
|
|
ec_key_simple_check_key,
|
|
ec_key_simple_generate_public_key,
|
|
0, /* keycopy */
|
|
0, /* keyfinish */
|
|
ecdh_simple_compute_key,
|
|
0, /* field_inverse_mod_ord */
|
|
ec_GFp_simple_blind_coordinates
|
|
};
|
|
|
|
return &ret;
|
|
}
|
|
|
|
int ec_GFp_nist_group_copy(EC_GROUP *dest, const EC_GROUP *src)
|
|
{
|
|
dest->field_mod_func = src->field_mod_func;
|
|
|
|
return ec_GFp_simple_group_copy(dest, src);
|
|
}
|
|
|
|
int ec_GFp_nist_group_set_curve(EC_GROUP *group, const BIGNUM *p,
|
|
const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
|
|
{
|
|
int ret = 0;
|
|
BN_CTX *new_ctx = NULL;
|
|
|
|
if (ctx == NULL)
|
|
if ((ctx = new_ctx = BN_CTX_new()) == NULL)
|
|
return 0;
|
|
|
|
BN_CTX_start(ctx);
|
|
|
|
if (BN_ucmp(BN_get0_nist_prime_192(), p) == 0)
|
|
group->field_mod_func = BN_nist_mod_192;
|
|
else if (BN_ucmp(BN_get0_nist_prime_224(), p) == 0)
|
|
group->field_mod_func = BN_nist_mod_224;
|
|
else if (BN_ucmp(BN_get0_nist_prime_256(), p) == 0)
|
|
group->field_mod_func = BN_nist_mod_256;
|
|
else if (BN_ucmp(BN_get0_nist_prime_384(), p) == 0)
|
|
group->field_mod_func = BN_nist_mod_384;
|
|
else if (BN_ucmp(BN_get0_nist_prime_521(), p) == 0)
|
|
group->field_mod_func = BN_nist_mod_521;
|
|
else {
|
|
ECerr(EC_F_EC_GFP_NIST_GROUP_SET_CURVE, EC_R_NOT_A_NIST_PRIME);
|
|
goto err;
|
|
}
|
|
|
|
ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
|
|
|
|
err:
|
|
BN_CTX_end(ctx);
|
|
BN_CTX_free(new_ctx);
|
|
return ret;
|
|
}
|
|
|
|
int ec_GFp_nist_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
|
|
const BIGNUM *b, BN_CTX *ctx)
|
|
{
|
|
int ret = 0;
|
|
BN_CTX *ctx_new = NULL;
|
|
|
|
if (!group || !r || !a || !b) {
|
|
ECerr(EC_F_EC_GFP_NIST_FIELD_MUL, ERR_R_PASSED_NULL_PARAMETER);
|
|
goto err;
|
|
}
|
|
if (!ctx)
|
|
if ((ctx_new = ctx = BN_CTX_new()) == NULL)
|
|
goto err;
|
|
|
|
if (!BN_mul(r, a, b, ctx))
|
|
goto err;
|
|
if (!group->field_mod_func(r, r, group->field, ctx))
|
|
goto err;
|
|
|
|
ret = 1;
|
|
err:
|
|
BN_CTX_free(ctx_new);
|
|
return ret;
|
|
}
|
|
|
|
int ec_GFp_nist_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
|
|
BN_CTX *ctx)
|
|
{
|
|
int ret = 0;
|
|
BN_CTX *ctx_new = NULL;
|
|
|
|
if (!group || !r || !a) {
|
|
ECerr(EC_F_EC_GFP_NIST_FIELD_SQR, EC_R_PASSED_NULL_PARAMETER);
|
|
goto err;
|
|
}
|
|
if (!ctx)
|
|
if ((ctx_new = ctx = BN_CTX_new()) == NULL)
|
|
goto err;
|
|
|
|
if (!BN_sqr(r, a, ctx))
|
|
goto err;
|
|
if (!group->field_mod_func(r, r, group->field, ctx))
|
|
goto err;
|
|
|
|
ret = 1;
|
|
err:
|
|
BN_CTX_free(ctx_new);
|
|
return ret;
|
|
}
|