Latest update.
This commit is contained in:
+182
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
@@ -20,6 +20,11 @@
|
||||
#include "internal/refcount.h"
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/engine.h>
|
||||
#include <openssl/self_test.h>
|
||||
#include "crypto/bn.h"
|
||||
|
||||
static int ecdsa_keygen_pairwise_test(EC_KEY *eckey, OSSL_CALLBACK *cb,
|
||||
void *cbarg);
|
||||
|
||||
#ifndef FIPS_MODE
|
||||
EC_KEY *EC_KEY_new(void)
|
||||
@@ -169,6 +174,8 @@ EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src)
|
||||
if (src->meth->copy != NULL && src->meth->copy(dest, src) == 0)
|
||||
return NULL;
|
||||
|
||||
dest->dirty_cnt++;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
@@ -209,15 +216,28 @@ int EC_KEY_generate_key(EC_KEY *eckey)
|
||||
ECerr(EC_F_EC_KEY_GENERATE_KEY, ERR_R_PASSED_NULL_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
if (eckey->meth->keygen != NULL)
|
||||
return eckey->meth->keygen(eckey);
|
||||
if (eckey->meth->keygen != NULL) {
|
||||
int ret;
|
||||
|
||||
ret = eckey->meth->keygen(eckey);
|
||||
if (ret == 1)
|
||||
eckey->dirty_cnt++;
|
||||
|
||||
return ret;
|
||||
}
|
||||
ECerr(EC_F_EC_KEY_GENERATE_KEY, EC_R_OPERATION_NOT_SUPPORTED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ossl_ec_key_gen(EC_KEY *eckey)
|
||||
{
|
||||
return eckey->group->meth->keygen(eckey);
|
||||
int ret;
|
||||
|
||||
ret = eckey->group->meth->keygen(eckey);
|
||||
|
||||
if (ret == 1)
|
||||
eckey->dirty_cnt++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -225,11 +245,14 @@ int ossl_ec_key_gen(EC_KEY *eckey)
|
||||
* See SP800-56AR3 5.6.1.2.2 "Key Pair Generation by Testing Candidates"
|
||||
*
|
||||
* Params:
|
||||
* libctx A context containing an optional self test callback.
|
||||
* eckey An EC key object that contains domain params. The generated keypair
|
||||
* is stored in this object.
|
||||
* pairwise_test Set to non zero to perform a pairwise test. If the test
|
||||
* fails then the keypair is not generated,
|
||||
* Returns 1 if the keypair was generated or 0 otherwise.
|
||||
*/
|
||||
int ec_key_simple_generate_key(EC_KEY *eckey)
|
||||
int ec_generate_key(OPENSSL_CTX *libctx, EC_KEY *eckey, int pairwise_test)
|
||||
{
|
||||
int ok = 0;
|
||||
BIGNUM *priv_key = NULL;
|
||||
@@ -287,8 +310,20 @@ int ec_key_simple_generate_key(EC_KEY *eckey)
|
||||
priv_key = NULL;
|
||||
pub_key = NULL;
|
||||
|
||||
ok = 1;
|
||||
eckey->dirty_cnt++;
|
||||
|
||||
#ifdef FIPS_MODE
|
||||
pairwise_test = 1;
|
||||
#endif /* FIPS_MODE */
|
||||
|
||||
ok = 1;
|
||||
if (pairwise_test) {
|
||||
OSSL_CALLBACK *cb = NULL;
|
||||
void *cbarg = NULL;
|
||||
|
||||
OSSL_SELF_TEST_get_callback(libctx, &cb, &cbarg);
|
||||
ok = ecdsa_keygen_pairwise_test(eckey, cb, cbarg);
|
||||
}
|
||||
err:
|
||||
/* Step (9): If there is an error return an invalid keypair. */
|
||||
if (!ok) {
|
||||
@@ -303,14 +338,26 @@ err:
|
||||
return ok;
|
||||
}
|
||||
|
||||
int ec_key_simple_generate_key(EC_KEY *eckey)
|
||||
{
|
||||
return ec_generate_key(NULL, eckey, 0);
|
||||
}
|
||||
|
||||
int ec_key_simple_generate_public_key(EC_KEY *eckey)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* See SP800-56AR3 5.6.1.2.2: Step (8)
|
||||
* pub_key = priv_key * G (where G is a point on the curve)
|
||||
*/
|
||||
return EC_POINT_mul(eckey->group, eckey->pub_key, eckey->priv_key, NULL,
|
||||
NULL, NULL);
|
||||
ret = EC_POINT_mul(eckey->group, eckey->pub_key, eckey->priv_key, NULL,
|
||||
NULL, NULL);
|
||||
|
||||
if (ret == 1)
|
||||
eckey->dirty_cnt++;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int EC_KEY_check_key(const EC_KEY *eckey)
|
||||
@@ -505,6 +552,7 @@ int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x,
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* EC_KEY_set_public_key updates dirty_cnt */
|
||||
if (!EC_KEY_set_public_key(key, point))
|
||||
goto err;
|
||||
|
||||
@@ -532,6 +580,7 @@ int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group)
|
||||
return 0;
|
||||
EC_GROUP_free(key->group);
|
||||
key->group = EC_GROUP_dup(group);
|
||||
key->dirty_cnt++;
|
||||
return (key->group == NULL) ? 0 : 1;
|
||||
}
|
||||
|
||||
@@ -542,17 +591,87 @@ const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key)
|
||||
|
||||
int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key)
|
||||
{
|
||||
int fixed_top;
|
||||
const BIGNUM *order = NULL;
|
||||
BIGNUM *tmp_key = NULL;
|
||||
|
||||
if (key->group == NULL || key->group->meth == NULL)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Not only should key->group be set, but it should also be in a valid
|
||||
* fully initialized state.
|
||||
*
|
||||
* Specifically, to operate in constant time, we need that the group order
|
||||
* is set, as we use its length as the fixed public size of any scalar used
|
||||
* as an EC private key.
|
||||
*/
|
||||
order = EC_GROUP_get0_order(key->group);
|
||||
if (order == NULL || BN_is_zero(order))
|
||||
return 0; /* This should never happen */
|
||||
|
||||
if (key->group->meth->set_private != NULL
|
||||
&& key->group->meth->set_private(key, priv_key) == 0)
|
||||
return 0;
|
||||
if (key->meth->set_private != NULL
|
||||
&& key->meth->set_private(key, priv_key) == 0)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* We should never leak the bit length of the secret scalar in the key,
|
||||
* so we always set the `BN_FLG_CONSTTIME` flag on the internal `BIGNUM`
|
||||
* holding the secret scalar.
|
||||
*
|
||||
* This is important also because `BN_dup()` (and `BN_copy()`) do not
|
||||
* propagate the `BN_FLG_CONSTTIME` flag from the source `BIGNUM`, and
|
||||
* this brings an extra risk of inadvertently losing the flag, even when
|
||||
* the called specifically set it.
|
||||
*
|
||||
* The propagation has been turned on and off a few times in the past
|
||||
* years because in some conditions has shown unintended consequences in
|
||||
* some code paths, so at the moment we can't fix this in the BN layer.
|
||||
*
|
||||
* In `EC_KEY_set_private_key()` we can work around the propagation by
|
||||
* manually setting the flag after `BN_dup()` as we know for sure that
|
||||
* inside the EC module the `BN_FLG_CONSTTIME` is always treated
|
||||
* correctly and should not generate unintended consequences.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
tmp_key = BN_dup(priv_key);
|
||||
if (tmp_key == NULL)
|
||||
return 0;
|
||||
|
||||
BN_set_flags(tmp_key, BN_FLG_CONSTTIME);
|
||||
|
||||
fixed_top = bn_get_top(order) + 2;
|
||||
if (bn_wexpand(tmp_key, fixed_top) == NULL) {
|
||||
BN_clear_free(tmp_key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
BN_clear_free(key->priv_key);
|
||||
key->priv_key = BN_dup(priv_key);
|
||||
return (key->priv_key == NULL) ? 0 : 1;
|
||||
key->priv_key = tmp_key;
|
||||
key->dirty_cnt++;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key)
|
||||
@@ -567,6 +686,7 @@ int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key)
|
||||
return 0;
|
||||
EC_POINT_free(key->pub_key);
|
||||
key->pub_key = EC_POINT_dup(pub_key, key->group);
|
||||
key->dirty_cnt++;
|
||||
return (key->pub_key == NULL) ? 0 : 1;
|
||||
}
|
||||
|
||||
@@ -613,11 +733,13 @@ int EC_KEY_get_flags(const EC_KEY *key)
|
||||
void EC_KEY_set_flags(EC_KEY *key, int flags)
|
||||
{
|
||||
key->flags |= flags;
|
||||
key->dirty_cnt++;
|
||||
}
|
||||
|
||||
void EC_KEY_clear_flags(EC_KEY *key, int flags)
|
||||
{
|
||||
key->flags &= ~flags;
|
||||
key->dirty_cnt++;
|
||||
}
|
||||
|
||||
size_t EC_KEY_key2buf(const EC_KEY *key, point_conversion_form_t form,
|
||||
@@ -639,6 +761,7 @@ int EC_KEY_oct2key(EC_KEY *key, const unsigned char *buf, size_t len,
|
||||
return 0;
|
||||
if (EC_POINT_oct2point(key->group, key->pub_key, buf, len, ctx) == 0)
|
||||
return 0;
|
||||
key->dirty_cnt++;
|
||||
/*
|
||||
* Save the point conversion form.
|
||||
* For non-custom curves the first octet of the buffer (excluding
|
||||
@@ -689,13 +812,18 @@ size_t ec_key_simple_priv2oct(const EC_KEY *eckey,
|
||||
|
||||
int EC_KEY_oct2priv(EC_KEY *eckey, const unsigned char *buf, size_t len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (eckey->group == NULL || eckey->group->meth == NULL)
|
||||
return 0;
|
||||
if (eckey->group->meth->oct2priv == NULL) {
|
||||
ECerr(EC_F_EC_KEY_OCT2PRIV, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
||||
return 0;
|
||||
}
|
||||
return eckey->group->meth->oct2priv(eckey, buf, len);
|
||||
ret = eckey->group->meth->oct2priv(eckey, buf, len);
|
||||
if (ret == 1)
|
||||
eckey->dirty_cnt++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ec_key_simple_oct2priv(EC_KEY *eckey, const unsigned char *buf, size_t len)
|
||||
@@ -711,6 +839,7 @@ int ec_key_simple_oct2priv(EC_KEY *eckey, const unsigned char *buf, size_t len)
|
||||
ECerr(EC_F_EC_KEY_SIMPLE_OCT2PRIV, ERR_R_BN_LIB);
|
||||
return 0;
|
||||
}
|
||||
eckey->dirty_cnt++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -742,3 +871,45 @@ int EC_KEY_can_sign(const EC_KEY *eckey)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIPS 140-2 IG 9.9 AS09.33
|
||||
* Perform a sign/verify operation.
|
||||
*
|
||||
* NOTE: When generating keys for key-agreement schemes - FIPS 140-2 IG 9.9
|
||||
* states that no additional pairwise tests are required (apart from the tests
|
||||
* specified in SP800-56A) when generating keys. Hence pairwise ECDH tests are
|
||||
* omitted here.
|
||||
*/
|
||||
static int ecdsa_keygen_pairwise_test(EC_KEY *eckey, OSSL_CALLBACK *cb,
|
||||
void *cbarg)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned char dgst[16] = {0};
|
||||
int dgst_len = (int)sizeof(dgst);
|
||||
ECDSA_SIG *sig = NULL;
|
||||
OSSL_SELF_TEST *st = NULL;
|
||||
|
||||
st = OSSL_SELF_TEST_new(cb, cbarg);
|
||||
if (st == NULL)
|
||||
return 0;
|
||||
|
||||
OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_PCT,
|
||||
OSSL_SELF_TEST_DESC_PCT_ECDSA);
|
||||
|
||||
sig = ECDSA_do_sign(dgst, dgst_len, eckey);
|
||||
if (sig == NULL)
|
||||
goto err;
|
||||
|
||||
OSSL_SELF_TEST_oncorrupt_byte(st, dgst);
|
||||
|
||||
if (ECDSA_do_verify(dgst, dgst_len, sig, eckey) != 1)
|
||||
goto err;
|
||||
|
||||
ret = 1;
|
||||
err:
|
||||
OSSL_SELF_TEST_onend(st, ret);
|
||||
OSSL_SELF_TEST_free(st);
|
||||
ECDSA_SIG_free(sig);
|
||||
return ret;
|
||||
}
|
||||
Reference in New Issue
Block a user