summaryrefslogtreecommitdiffstats
path: root/crypto/ec/ec_ameth.c
diff options
context:
space:
mode:
authorNicola Tuveri <nic.tuv@gmail.com>2020-01-21 16:48:49 +0200
committerNicola Tuveri <nic.tuv@gmail.com>2020-02-18 19:11:10 +0200
commita377871db10afcdfb080c79f3245baf441fe07fc (patch)
tree36775b1bd4257f438dc4377dd405f2c9e330a663 /crypto/ec/ec_ameth.c
parent4fe54d674f14e7964f982285d1aeb86698a33c3c (diff)
[PROV][KEYMGMT][EC] Import/export of priv_key as padded const time BN
For EC keys it is particularly important to avoid leaking the bit length of the secret scalar. Key import/export should never leak the bit length of the secret scalar in the key. For this reason, on export we use padded BIGNUMs with fixed length, using the new `ossl_param_bld_push_BN_pad()`. When importing we also should make sure that, even if short lived, the newly created BIGNUM is marked with the BN_FLG_CONSTTIME flag as soon as possible, so that any processing of this BIGNUM might opt for constant time implementations in the backend. Setting the BN_FLG_CONSTTIME flag alone is never enough, we also have to preallocate the BIGNUM internal buffer to a fixed size big enough that operations performed during the processing never trigger a realloc which would leak the size of the scalar through memory accesses. Fixed length ------------ The order of the large prime subgroup of the curve is our choice for a fixed public size, as that is generally the upper bound for generating a private key in EC cryptosystems and should fit all valid secret scalars. For padding on export we just use the bit length of the order converted to bytes (rounding up). For preallocating the BIGNUM storage we look at the number of "words" required for the internal representation of the order, and we preallocate 2 extra "words" in case any of the subsequent processing might temporarily overflow the order length. Future work ----------- To ensure the flag and fixed size preallocation persists upon `EC_KEY_set_private_key()`, we need to further harden `EC_KEY_set_private_key()` and `BN_copy()`. This is done in separate commits. Reviewed-by: Matt Caswell <matt@openssl.org> Reviewed-by: Richard Levitte <levitte@openssl.org> Reviewed-by: Shane Lontis <shane.lontis@oracle.com> (Merged from https://github.com/openssl/openssl/pull/10631)
Diffstat (limited to 'crypto/ec/ec_ameth.c')
-rw-r--r--crypto/ec/ec_ameth.c55
1 files changed, 48 insertions, 7 deletions
diff --git a/crypto/ec/ec_ameth.c b/crypto/ec/ec_ameth.c
index c4e8177c28..d6807661ff 100644
--- a/crypto/ec/ec_ameth.c
+++ b/crypto/ec/ec_ameth.c
@@ -663,20 +663,61 @@ int ec_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
goto err;
if (priv_key != NULL) {
+ size_t sz;
+ int ecbits;
+ int ecdh_cofactor_mode;
+
+ /*
+ * Key import/export should never leak the bit length of the secret
+ * scalar in the key.
+ *
+ * For this reason, on export we use padded BIGNUMs with fixed length.
+ *
+ * When importing we also should make sure that, even if short lived,
+ * the newly created BIGNUM is marked with the BN_FLG_CONSTTIME flag as
+ * soon as possible, so that any processing of this BIGNUM might opt for
+ * constant time implementations in the backend.
+ *
+ * Setting the BN_FLG_CONSTTIME flag alone is never enough, we also have
+ * to preallocate the BIGNUM internal buffer to a fixed public size big
+ * enough that operations performed during the processing never trigger
+ * a realloc which would leak the size of the scalar through memory
+ * accesses.
+ *
+ * Fixed Length
+ * ------------
+ *
+ * The order of the large prime subgroup of the curve is our choice for
+ * a fixed public size, as that is generally the upper bound for
+ * generating a private key in EC cryptosystems and should fit all valid
+ * secret scalars.
+ *
+ * For padding on export we just use the bit length of the order
+ * converted to bytes (rounding up).
+ *
+ * For preallocating the BIGNUM storage we look at the number of "words"
+ * required for the internal representation of the order, and we
+ * preallocate 2 extra "words" in case any of the subsequent processing
+ * might temporarily overflow the order length.
+ */
+ ecbits = EC_GROUP_order_bits(ecg);
+ if (ecbits <= 0)
+ goto err;
+
+ sz = (ecbits + 7 ) / 8;
+ if (!ossl_param_bld_push_BN_pad(&tmpl,
+ OSSL_PKEY_PARAM_PRIV_KEY,
+ priv_key, sz))
+ goto err;
+
/*
* The ECDH Cofactor Mode is defined only if the EC_KEY actually
* contains a private key, so we check for the flag and export it only
* in this case.
*/
- int ecdh_cofactor_mode =
+ ecdh_cofactor_mode =
(EC_KEY_get_flags(eckey) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0;
- /* Export the actual private key */
- if (!ossl_param_bld_push_BN(&tmpl,
- OSSL_PKEY_PARAM_PRIV_KEY,
- priv_key))
- goto err;
-
/* Export the ECDH_COFACTOR_MODE parameter */
if (!ossl_param_bld_push_int(&tmpl,
OSSL_PKEY_PARAM_USE_COFACTOR_ECDH,