2002-08-02 22:28:37 +08:00
|
|
|
/*
|
2021-03-11 21:27:36 +08:00
|
|
|
* Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
|
2017-06-15 22:16:46 +08:00
|
|
|
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
|
2001-03-06 04:14:00 +08:00
|
|
|
*
|
2018-12-06 20:38:06 +08:00
|
|
|
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
2016-05-18 02:51:04 +08:00
|
|
|
* 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
|
2001-03-06 04:14:00 +08:00
|
|
|
*/
|
2016-05-18 02:51:04 +08:00
|
|
|
|
2020-01-28 13:14:18 +08:00
|
|
|
/*
|
2022-08-24 02:33:58 +08:00
|
|
|
* ECDSA low-level APIs are deprecated for public use, but still ok for
|
2020-01-28 13:14:18 +08:00
|
|
|
* internal use.
|
|
|
|
*/
|
|
|
|
#include "internal/deprecated.h"
|
|
|
|
|
2001-03-09 04:55:16 +08:00
|
|
|
#include <openssl/err.h>
|
|
|
|
|
2019-09-28 06:45:40 +08:00
|
|
|
#include "ec_local.h"
|
2001-03-07 09:17:05 +08:00
|
|
|
|
|
|
|
const EC_METHOD *EC_GFp_mont_method(void)
|
|
|
|
{
|
2001-03-07 17:29:45 +08:00
|
|
|
static const EC_METHOD ret = {
|
2011-02-15 00:52:12 +08:00
|
|
|
EC_FLAGS_DEFAULT_OCT,
|
2002-06-10 20:18:21 +08:00
|
|
|
NID_X9_62_prime_field,
|
2021-02-18 18:27:26 +08:00
|
|
|
ossl_ec_GFp_mont_group_init,
|
|
|
|
ossl_ec_GFp_mont_group_finish,
|
|
|
|
ossl_ec_GFp_mont_group_clear_finish,
|
|
|
|
ossl_ec_GFp_mont_group_copy,
|
|
|
|
ossl_ec_GFp_mont_group_set_curve,
|
|
|
|
ossl_ec_GFp_simple_group_get_curve,
|
|
|
|
ossl_ec_GFp_simple_group_get_degree,
|
|
|
|
ossl_ec_group_simple_order_bits,
|
|
|
|
ossl_ec_GFp_simple_group_check_discriminant,
|
|
|
|
ossl_ec_GFp_simple_point_init,
|
|
|
|
ossl_ec_GFp_simple_point_finish,
|
|
|
|
ossl_ec_GFp_simple_point_clear_finish,
|
|
|
|
ossl_ec_GFp_simple_point_copy,
|
|
|
|
ossl_ec_GFp_simple_point_set_to_infinity,
|
|
|
|
ossl_ec_GFp_simple_point_set_affine_coordinates,
|
|
|
|
ossl_ec_GFp_simple_point_get_affine_coordinates,
|
2011-02-15 00:52:12 +08:00
|
|
|
0, 0, 0,
|
2021-02-18 18:27:26 +08:00
|
|
|
ossl_ec_GFp_simple_add,
|
|
|
|
ossl_ec_GFp_simple_dbl,
|
|
|
|
ossl_ec_GFp_simple_invert,
|
|
|
|
ossl_ec_GFp_simple_is_at_infinity,
|
|
|
|
ossl_ec_GFp_simple_is_on_curve,
|
|
|
|
ossl_ec_GFp_simple_cmp,
|
|
|
|
ossl_ec_GFp_simple_make_affine,
|
|
|
|
ossl_ec_GFp_simple_points_make_affine,
|
2003-02-07 03:25:12 +08:00
|
|
|
0 /* mul */ ,
|
|
|
|
0 /* precompute_mult */ ,
|
|
|
|
0 /* have_precompute_mult */ ,
|
2021-02-18 18:27:26 +08:00
|
|
|
ossl_ec_GFp_mont_field_mul,
|
|
|
|
ossl_ec_GFp_mont_field_sqr,
|
2002-08-02 21:42:24 +08:00
|
|
|
0 /* field_div */ ,
|
2021-02-18 18:27:26 +08:00
|
|
|
ossl_ec_GFp_mont_field_inv,
|
|
|
|
ossl_ec_GFp_mont_field_encode,
|
|
|
|
ossl_ec_GFp_mont_field_decode,
|
|
|
|
ossl_ec_GFp_mont_field_set_to_one,
|
|
|
|
ossl_ec_key_simple_priv2oct,
|
|
|
|
ossl_ec_key_simple_oct2priv,
|
2016-02-29 01:48:48 +08:00
|
|
|
0, /* set private */
|
2021-02-18 18:27:26 +08:00
|
|
|
ossl_ec_key_simple_generate_key,
|
|
|
|
ossl_ec_key_simple_check_key,
|
|
|
|
ossl_ec_key_simple_generate_public_key,
|
2016-02-29 01:48:48 +08:00
|
|
|
0, /* keycopy */
|
|
|
|
0, /* keyfinish */
|
2021-02-18 18:27:26 +08:00
|
|
|
ossl_ecdh_simple_compute_key,
|
|
|
|
ossl_ecdsa_simple_sign_setup,
|
|
|
|
ossl_ecdsa_simple_sign_sig,
|
|
|
|
ossl_ecdsa_simple_verify_sig,
|
Implement coordinate blinding for EC_POINT
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)
2018-06-16 22:07:40 +08:00
|
|
|
0, /* field_inverse_mod_ord */
|
2021-02-18 18:27:26 +08:00
|
|
|
ossl_ec_GFp_simple_blind_coordinates,
|
|
|
|
ossl_ec_GFp_simple_ladder_pre,
|
|
|
|
ossl_ec_GFp_simple_ladder_step,
|
|
|
|
ossl_ec_GFp_simple_ladder_post
|
2001-03-11 07:18:35 +08:00
|
|
|
};
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2001-03-07 09:17:05 +08:00
|
|
|
return &ret;
|
|
|
|
}
|
2001-03-08 03:54:35 +08:00
|
|
|
|
2021-02-18 18:27:26 +08:00
|
|
|
int ossl_ec_GFp_mont_group_init(EC_GROUP *group)
|
2001-03-08 03:54:35 +08:00
|
|
|
{
|
|
|
|
int ok;
|
|
|
|
|
2021-02-18 18:27:26 +08:00
|
|
|
ok = ossl_ec_GFp_simple_group_init(group);
|
2001-03-11 07:18:35 +08:00
|
|
|
group->field_data1 = NULL;
|
|
|
|
group->field_data2 = NULL;
|
2001-03-08 03:54:35 +08:00
|
|
|
return ok;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2001-03-08 03:54:35 +08:00
|
|
|
|
2021-02-18 18:27:26 +08:00
|
|
|
void ossl_ec_GFp_mont_group_finish(EC_GROUP *group)
|
2001-03-09 04:55:16 +08:00
|
|
|
{
|
2015-05-01 09:37:06 +08:00
|
|
|
BN_MONT_CTX_free(group->field_data1);
|
|
|
|
group->field_data1 = NULL;
|
|
|
|
BN_free(group->field_data2);
|
|
|
|
group->field_data2 = NULL;
|
2021-02-18 18:27:26 +08:00
|
|
|
ossl_ec_GFp_simple_group_finish(group);
|
2001-03-09 04:55:16 +08:00
|
|
|
}
|
2001-03-08 03:54:35 +08:00
|
|
|
|
2021-02-18 18:27:26 +08:00
|
|
|
void ossl_ec_GFp_mont_group_clear_finish(EC_GROUP *group)
|
2001-03-09 04:55:16 +08:00
|
|
|
{
|
2015-05-01 09:37:06 +08:00
|
|
|
BN_MONT_CTX_free(group->field_data1);
|
|
|
|
group->field_data1 = NULL;
|
|
|
|
BN_clear_free(group->field_data2);
|
|
|
|
group->field_data2 = NULL;
|
2021-02-18 18:27:26 +08:00
|
|
|
ossl_ec_GFp_simple_group_clear_finish(group);
|
2001-03-09 04:55:16 +08:00
|
|
|
}
|
2001-03-08 03:54:35 +08:00
|
|
|
|
2021-02-18 18:27:26 +08:00
|
|
|
int ossl_ec_GFp_mont_group_copy(EC_GROUP *dest, const EC_GROUP *src)
|
2001-03-09 04:55:16 +08:00
|
|
|
{
|
2015-05-01 09:37:06 +08:00
|
|
|
BN_MONT_CTX_free(dest->field_data1);
|
|
|
|
dest->field_data1 = NULL;
|
|
|
|
BN_clear_free(dest->field_data2);
|
|
|
|
dest->field_data2 = NULL;
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2021-02-18 18:27:26 +08:00
|
|
|
if (!ossl_ec_GFp_simple_group_copy(dest, src))
|
2001-03-09 04:55:16 +08:00
|
|
|
return 0;
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2001-03-11 07:18:35 +08:00
|
|
|
if (src->field_data1 != NULL) {
|
|
|
|
dest->field_data1 = BN_MONT_CTX_new();
|
|
|
|
if (dest->field_data1 == NULL)
|
|
|
|
return 0;
|
|
|
|
if (!BN_MONT_CTX_copy(dest->field_data1, src->field_data1))
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
if (src->field_data2 != NULL) {
|
|
|
|
dest->field_data2 = BN_dup(src->field_data2);
|
|
|
|
if (dest->field_data2 == NULL)
|
|
|
|
goto err;
|
2001-03-09 04:55:16 +08:00
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2001-03-09 04:55:16 +08:00
|
|
|
return 1;
|
2001-03-11 07:18:35 +08:00
|
|
|
|
|
|
|
err:
|
2015-05-01 09:37:06 +08:00
|
|
|
BN_MONT_CTX_free(dest->field_data1);
|
|
|
|
dest->field_data1 = NULL;
|
2001-03-11 07:18:35 +08:00
|
|
|
return 0;
|
2001-03-09 04:55:16 +08:00
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2021-02-18 18:27:26 +08:00
|
|
|
int ossl_ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p,
|
|
|
|
const BIGNUM *a, const BIGNUM *b,
|
|
|
|
BN_CTX *ctx)
|
2002-11-18 22:33:39 +08:00
|
|
|
{
|
|
|
|
BN_CTX *new_ctx = NULL;
|
|
|
|
BN_MONT_CTX *mont = NULL;
|
|
|
|
BIGNUM *one = NULL;
|
|
|
|
int ret = 0;
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2015-05-01 09:37:06 +08:00
|
|
|
BN_MONT_CTX_free(group->field_data1);
|
|
|
|
group->field_data1 = NULL;
|
|
|
|
BN_free(group->field_data2);
|
|
|
|
group->field_data2 = NULL;
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2002-11-18 22:33:39 +08:00
|
|
|
if (ctx == NULL) {
|
2019-07-04 00:30:03 +08:00
|
|
|
ctx = new_ctx = BN_CTX_new_ex(group->libctx);
|
2002-11-18 22:33:39 +08:00
|
|
|
if (ctx == NULL)
|
|
|
|
return 0;
|
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2002-11-18 22:33:39 +08:00
|
|
|
mont = BN_MONT_CTX_new();
|
|
|
|
if (mont == NULL)
|
|
|
|
goto err;
|
|
|
|
if (!BN_MONT_CTX_set(mont, p, ctx)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
|
2002-11-18 22:33:39 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
one = BN_new();
|
|
|
|
if (one == NULL)
|
|
|
|
goto err;
|
|
|
|
if (!BN_to_montgomery(one, BN_value_one(), mont, ctx))
|
|
|
|
goto err;
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2002-11-18 22:33:39 +08:00
|
|
|
group->field_data1 = mont;
|
|
|
|
mont = NULL;
|
|
|
|
group->field_data2 = one;
|
|
|
|
one = NULL;
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2021-02-18 18:27:26 +08:00
|
|
|
ret = ossl_ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2002-11-18 22:33:39 +08:00
|
|
|
if (!ret) {
|
|
|
|
BN_MONT_CTX_free(group->field_data1);
|
|
|
|
group->field_data1 = NULL;
|
|
|
|
BN_free(group->field_data2);
|
|
|
|
group->field_data2 = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
err:
|
2016-07-14 23:14:08 +08:00
|
|
|
BN_free(one);
|
2015-05-01 09:37:06 +08:00
|
|
|
BN_CTX_free(new_ctx);
|
|
|
|
BN_MONT_CTX_free(mont);
|
2002-11-18 22:33:39 +08:00
|
|
|
return ret;
|
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2021-02-18 18:27:26 +08:00
|
|
|
int ossl_ec_GFp_mont_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
|
|
|
|
const BIGNUM *b, BN_CTX *ctx)
|
2001-03-09 04:55:16 +08:00
|
|
|
{
|
2001-03-11 07:18:35 +08:00
|
|
|
if (group->field_data1 == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_NOT_INITIALIZED);
|
2001-03-09 04:55:16 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2001-03-11 07:18:35 +08:00
|
|
|
return BN_mod_mul_montgomery(r, a, b, group->field_data1, ctx);
|
2001-03-09 04:55:16 +08:00
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2021-02-18 18:27:26 +08:00
|
|
|
int ossl_ec_GFp_mont_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
|
|
|
|
BN_CTX *ctx)
|
2001-03-09 04:55:16 +08:00
|
|
|
{
|
2001-03-11 07:18:35 +08:00
|
|
|
if (group->field_data1 == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_NOT_INITIALIZED);
|
2001-03-09 04:55:16 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2001-03-11 07:18:35 +08:00
|
|
|
return BN_mod_mul_montgomery(r, a, a, group->field_data1, ctx);
|
2001-03-09 04:55:16 +08:00
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
|
SCA hardening for mod. field inversion in EC_GROUP
This commit adds a dedicated function in `EC_METHOD` to access a modular
field inversion implementation suitable for the specifics of the
implemented curve, featuring SCA countermeasures.
The new pointer is defined as:
`int (*field_inv)(const EC_GROUP*, BIGNUM *r, const BIGNUM *a, BN_CTX*)`
and computes the multiplicative inverse of `a` in the underlying field,
storing the result in `r`.
Three implementations are included, each including specific SCA
countermeasures:
- `ec_GFp_simple_field_inv()`, featuring SCA hardening through
blinding.
- `ec_GFp_mont_field_inv()`, featuring SCA hardening through Fermat's
Little Theorem (FLT) inversion.
- `ec_GF2m_simple_field_inv()`, that uses `BN_GF2m_mod_inv()` which
already features SCA hardening through blinding.
From a security point of view, this also helps addressing a leakage
previously affecting conversions from projective to affine coordinates.
This commit also adds a new error reason code (i.e.,
`EC_R_CANNOT_INVERT`) to improve consistency between the three
implementations as all of them could fail for the same reason but
through different code paths resulting in inconsistent error stack
states.
Co-authored-by: Nicola Tuveri <nic.tuv@gmail.com>
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Nicola Tuveri <nic.tuv@gmail.com>
(Merged from https://github.com/openssl/openssl/pull/8254)
2019-02-02 16:53:29 +08:00
|
|
|
/*-
|
|
|
|
* Computes the multiplicative inverse of a in GF(p), storing the result in r.
|
2022-08-24 02:33:58 +08:00
|
|
|
* If a is zero (or equivalent), you'll get an EC_R_CANNOT_INVERT error.
|
SCA hardening for mod. field inversion in EC_GROUP
This commit adds a dedicated function in `EC_METHOD` to access a modular
field inversion implementation suitable for the specifics of the
implemented curve, featuring SCA countermeasures.
The new pointer is defined as:
`int (*field_inv)(const EC_GROUP*, BIGNUM *r, const BIGNUM *a, BN_CTX*)`
and computes the multiplicative inverse of `a` in the underlying field,
storing the result in `r`.
Three implementations are included, each including specific SCA
countermeasures:
- `ec_GFp_simple_field_inv()`, featuring SCA hardening through
blinding.
- `ec_GFp_mont_field_inv()`, featuring SCA hardening through Fermat's
Little Theorem (FLT) inversion.
- `ec_GF2m_simple_field_inv()`, that uses `BN_GF2m_mod_inv()` which
already features SCA hardening through blinding.
From a security point of view, this also helps addressing a leakage
previously affecting conversions from projective to affine coordinates.
This commit also adds a new error reason code (i.e.,
`EC_R_CANNOT_INVERT`) to improve consistency between the three
implementations as all of them could fail for the same reason but
through different code paths resulting in inconsistent error stack
states.
Co-authored-by: Nicola Tuveri <nic.tuv@gmail.com>
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Nicola Tuveri <nic.tuv@gmail.com>
(Merged from https://github.com/openssl/openssl/pull/8254)
2019-02-02 16:53:29 +08:00
|
|
|
* We have a Mont structure, so SCA hardening is FLT inversion.
|
|
|
|
*/
|
2021-02-18 18:27:26 +08:00
|
|
|
int ossl_ec_GFp_mont_field_inv(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
|
|
|
|
BN_CTX *ctx)
|
SCA hardening for mod. field inversion in EC_GROUP
This commit adds a dedicated function in `EC_METHOD` to access a modular
field inversion implementation suitable for the specifics of the
implemented curve, featuring SCA countermeasures.
The new pointer is defined as:
`int (*field_inv)(const EC_GROUP*, BIGNUM *r, const BIGNUM *a, BN_CTX*)`
and computes the multiplicative inverse of `a` in the underlying field,
storing the result in `r`.
Three implementations are included, each including specific SCA
countermeasures:
- `ec_GFp_simple_field_inv()`, featuring SCA hardening through
blinding.
- `ec_GFp_mont_field_inv()`, featuring SCA hardening through Fermat's
Little Theorem (FLT) inversion.
- `ec_GF2m_simple_field_inv()`, that uses `BN_GF2m_mod_inv()` which
already features SCA hardening through blinding.
From a security point of view, this also helps addressing a leakage
previously affecting conversions from projective to affine coordinates.
This commit also adds a new error reason code (i.e.,
`EC_R_CANNOT_INVERT`) to improve consistency between the three
implementations as all of them could fail for the same reason but
through different code paths resulting in inconsistent error stack
states.
Co-authored-by: Nicola Tuveri <nic.tuv@gmail.com>
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Nicola Tuveri <nic.tuv@gmail.com>
(Merged from https://github.com/openssl/openssl/pull/8254)
2019-02-02 16:53:29 +08:00
|
|
|
{
|
|
|
|
BIGNUM *e = NULL;
|
|
|
|
BN_CTX *new_ctx = NULL;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
if (group->field_data1 == NULL)
|
|
|
|
return 0;
|
|
|
|
|
2019-07-04 00:30:03 +08:00
|
|
|
if (ctx == NULL
|
|
|
|
&& (ctx = new_ctx = BN_CTX_secure_new_ex(group->libctx)) == NULL)
|
SCA hardening for mod. field inversion in EC_GROUP
This commit adds a dedicated function in `EC_METHOD` to access a modular
field inversion implementation suitable for the specifics of the
implemented curve, featuring SCA countermeasures.
The new pointer is defined as:
`int (*field_inv)(const EC_GROUP*, BIGNUM *r, const BIGNUM *a, BN_CTX*)`
and computes the multiplicative inverse of `a` in the underlying field,
storing the result in `r`.
Three implementations are included, each including specific SCA
countermeasures:
- `ec_GFp_simple_field_inv()`, featuring SCA hardening through
blinding.
- `ec_GFp_mont_field_inv()`, featuring SCA hardening through Fermat's
Little Theorem (FLT) inversion.
- `ec_GF2m_simple_field_inv()`, that uses `BN_GF2m_mod_inv()` which
already features SCA hardening through blinding.
From a security point of view, this also helps addressing a leakage
previously affecting conversions from projective to affine coordinates.
This commit also adds a new error reason code (i.e.,
`EC_R_CANNOT_INVERT`) to improve consistency between the three
implementations as all of them could fail for the same reason but
through different code paths resulting in inconsistent error stack
states.
Co-authored-by: Nicola Tuveri <nic.tuv@gmail.com>
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Nicola Tuveri <nic.tuv@gmail.com>
(Merged from https://github.com/openssl/openssl/pull/8254)
2019-02-02 16:53:29 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
BN_CTX_start(ctx);
|
|
|
|
if ((e = BN_CTX_get(ctx)) == NULL)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
/* Inverse in constant time with Fermats Little Theorem */
|
|
|
|
if (!BN_set_word(e, 2))
|
|
|
|
goto err;
|
|
|
|
if (!BN_sub(e, group->field, e))
|
|
|
|
goto err;
|
|
|
|
/*-
|
|
|
|
* Exponent e is public.
|
|
|
|
* No need for scatter-gather or BN_FLG_CONSTTIME.
|
|
|
|
*/
|
|
|
|
if (!BN_mod_exp_mont(r, a, e, group->field, ctx, group->field_data1))
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
/* throw an error on zero */
|
|
|
|
if (BN_is_zero(r)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_CANNOT_INVERT);
|
SCA hardening for mod. field inversion in EC_GROUP
This commit adds a dedicated function in `EC_METHOD` to access a modular
field inversion implementation suitable for the specifics of the
implemented curve, featuring SCA countermeasures.
The new pointer is defined as:
`int (*field_inv)(const EC_GROUP*, BIGNUM *r, const BIGNUM *a, BN_CTX*)`
and computes the multiplicative inverse of `a` in the underlying field,
storing the result in `r`.
Three implementations are included, each including specific SCA
countermeasures:
- `ec_GFp_simple_field_inv()`, featuring SCA hardening through
blinding.
- `ec_GFp_mont_field_inv()`, featuring SCA hardening through Fermat's
Little Theorem (FLT) inversion.
- `ec_GF2m_simple_field_inv()`, that uses `BN_GF2m_mod_inv()` which
already features SCA hardening through blinding.
From a security point of view, this also helps addressing a leakage
previously affecting conversions from projective to affine coordinates.
This commit also adds a new error reason code (i.e.,
`EC_R_CANNOT_INVERT`) to improve consistency between the three
implementations as all of them could fail for the same reason but
through different code paths resulting in inconsistent error stack
states.
Co-authored-by: Nicola Tuveri <nic.tuv@gmail.com>
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Nicola Tuveri <nic.tuv@gmail.com>
(Merged from https://github.com/openssl/openssl/pull/8254)
2019-02-02 16:53:29 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 1;
|
|
|
|
|
|
|
|
err:
|
|
|
|
BN_CTX_end(ctx);
|
|
|
|
BN_CTX_free(new_ctx);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2021-02-18 18:27:26 +08:00
|
|
|
int ossl_ec_GFp_mont_field_encode(const EC_GROUP *group, BIGNUM *r,
|
|
|
|
const BIGNUM *a, BN_CTX *ctx)
|
2001-03-09 04:55:16 +08:00
|
|
|
{
|
2001-03-11 07:18:35 +08:00
|
|
|
if (group->field_data1 == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_NOT_INITIALIZED);
|
2001-03-09 04:55:16 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2001-03-11 07:18:35 +08:00
|
|
|
return BN_to_montgomery(r, a, (BN_MONT_CTX *)group->field_data1, ctx);
|
2001-03-09 04:55:16 +08:00
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2021-02-18 18:27:26 +08:00
|
|
|
int ossl_ec_GFp_mont_field_decode(const EC_GROUP *group, BIGNUM *r,
|
|
|
|
const BIGNUM *a, BN_CTX *ctx)
|
2001-03-09 04:55:16 +08:00
|
|
|
{
|
2001-03-11 07:18:35 +08:00
|
|
|
if (group->field_data1 == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_NOT_INITIALIZED);
|
2001-03-09 04:55:16 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2001-03-11 07:18:35 +08:00
|
|
|
return BN_from_montgomery(r, a, group->field_data1, ctx);
|
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2021-02-18 18:27:26 +08:00
|
|
|
int ossl_ec_GFp_mont_field_set_to_one(const EC_GROUP *group, BIGNUM *r,
|
|
|
|
BN_CTX *ctx)
|
2001-03-11 07:18:35 +08:00
|
|
|
{
|
|
|
|
if (group->field_data2 == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_NOT_INITIALIZED);
|
2001-03-11 07:18:35 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2001-03-11 07:18:35 +08:00
|
|
|
if (!BN_copy(r, group->field_data2))
|
|
|
|
return 0;
|
|
|
|
return 1;
|
2001-03-09 04:55:16 +08:00
|
|
|
}
|