Kaynağa Gözat

Safe (EC)DSA nonces.

This change causes (EC)DSA nonces be to calculated by hashing the
message and private key along with entropy.
kris/onging/CECPQ3_patch15
Adam Langley 10 yıl önce
ebeveyn
işleme
d4b4f085d9
9 değiştirilmiş dosya ile 129 ekleme ve 20 silme
  1. +12
    -0
      crypto/bn/bn.h
  2. +2
    -0
      crypto/bn/bn_error.c
  3. +66
    -0
      crypto/bn/random.c
  4. +2
    -2
      crypto/dsa/dsa.c
  5. +2
    -1
      crypto/dsa/dsa.h
  6. +13
    -2
      crypto/dsa/dsa_impl.c
  7. +30
    -15
      crypto/ecdsa/ecdsa.c
  8. +1
    -0
      crypto/ecdsa/ecdsa.h
  9. +1
    -0
      crypto/ecdsa/ecdsa_error.c

+ 12
- 0
crypto/bn/bn.h Dosyayı Görüntüle

@@ -520,6 +520,16 @@ int BN_rand_range(BIGNUM *rnd, const BIGNUM *range);
/* BN_pseudo_rand_range is an alias for BN_rand_range. */
int BN_pseudo_rand_range(BIGNUM *rnd, const BIGNUM *range);

/* BN_generate_dsa_nonce generates a random number 0 <= out < range. Unlike
* BN_rand_range, it also includes the contents of |priv| and |message| in the
* generation so that an RNG failure isn't fatal as long as |priv| remains
* secret. This is intended for use in DSA and ECDSA where an RNG weakness
* leads directly to private key exposure unless this function is used.
* It returns one on success and zero on error. */
int BN_generate_dsa_nonce(BIGNUM *out, const BIGNUM *range, const BIGNUM *priv,
const uint8_t *message, size_t message_len,
BN_CTX *ctx);

/* BN_GENCB holds a callback function that is used by generation functions that
* can take a very long time to complete. Use |BN_GENCB_set| to initialise a
* |BN_GENCB| structure.
@@ -769,6 +779,7 @@ unsigned BN_num_bits_word(BN_ULONG l);
#define BN_F_BN_mod_lshift_quick 119
#define BN_F_BN_CTX_new 120
#define BN_F_BN_mod_inverse_no_branch 121
#define BN_F_BN_generate_dsa_nonce 122
#define BN_R_NOT_A_SQUARE 100
#define BN_R_TOO_MANY_ITERATIONS 101
#define BN_R_INPUT_NOT_REDUCED 102
@@ -783,5 +794,6 @@ unsigned BN_num_bits_word(BN_ULONG l);
#define BN_R_INVALID_RANGE 111
#define BN_R_ARG2_LT_ARG3 112
#define BN_R_BIGNUM_TOO_LONG 113
#define BN_R_PRIVATE_KEY_TOO_LARGE 114

#endif /* OPENSSL_HEADER_BN_H */

+ 2
- 0
crypto/bn/bn_error.c Dosyayı Görüntüle

@@ -25,6 +25,7 @@ const ERR_STRING_DATA BN_error_string_data[] = {
{ERR_PACK(ERR_LIB_BN, BN_F_BN_div, 0), "BN_div"},
{ERR_PACK(ERR_LIB_BN, BN_F_BN_div_recp, 0), "BN_div_recp"},
{ERR_PACK(ERR_LIB_BN, BN_F_BN_exp, 0), "BN_exp"},
{ERR_PACK(ERR_LIB_BN, BN_F_BN_generate_dsa_nonce, 0), "BN_generate_dsa_nonce"},
{ERR_PACK(ERR_LIB_BN, BN_F_BN_mod_exp2_mont, 0), "BN_mod_exp2_mont"},
{ERR_PACK(ERR_LIB_BN, BN_F_BN_mod_exp_mont, 0), "BN_mod_exp_mont"},
{ERR_PACK(ERR_LIB_BN, BN_F_BN_mod_exp_mont_consttime, 0), "BN_mod_exp_mont_consttime"},
@@ -50,6 +51,7 @@ const ERR_STRING_DATA BN_error_string_data[] = {
{ERR_PACK(ERR_LIB_BN, 0, BN_R_NOT_A_SQUARE), "NOT_A_SQUARE"},
{ERR_PACK(ERR_LIB_BN, 0, BN_R_NOT_INITIALIZED), "NOT_INITIALIZED"},
{ERR_PACK(ERR_LIB_BN, 0, BN_R_NO_INVERSE), "NO_INVERSE"},
{ERR_PACK(ERR_LIB_BN, 0, BN_R_PRIVATE_KEY_TOO_LARGE), "PRIVATE_KEY_TOO_LARGE"},
{ERR_PACK(ERR_LIB_BN, 0, BN_R_P_IS_NOT_PRIME), "P_IS_NOT_PRIME"},
{ERR_PACK(ERR_LIB_BN, 0, BN_R_TOO_MANY_ITERATIONS), "TOO_MANY_ITERATIONS"},
{ERR_PACK(ERR_LIB_BN, 0, BN_R_TOO_MANY_TEMPORARY_VARIABLES), "TOO_MANY_TEMPORARY_VARIABLES"},


+ 66
- 0
crypto/bn/random.c Dosyayı Görüntüle

@@ -111,6 +111,7 @@
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/rand.h>
#include <openssl/sha.h>

int BN_rand(BIGNUM *rnd, int bits, int top, int bottom) {
uint8_t *buf = NULL;
@@ -235,3 +236,68 @@ int BN_rand_range(BIGNUM *r, const BIGNUM *range) {
int BN_pseudo_rand_range(BIGNUM *r, const BIGNUM *range) {
return BN_rand_range(r, range);
}

int BN_generate_dsa_nonce(BIGNUM *out, const BIGNUM *range, const BIGNUM *priv,
const uint8_t *message, size_t message_len,
BN_CTX *ctx) {
SHA512_CTX sha;
/* We use 512 bits of random data per iteration to
* ensure that we have at least |range| bits of randomness. */
uint8_t random_bytes[64];
uint8_t digest[SHA512_DIGEST_LENGTH];
size_t done, todo;
/* We generate |range|+8 bytes of random output. */
const unsigned num_k_bytes = BN_num_bytes(range) + 8;
uint8_t private_bytes[96];
uint8_t *k_bytes;
int ret = 0;

k_bytes = OPENSSL_malloc(num_k_bytes);
if (!k_bytes) {
goto err;
}

/* We copy |priv| into a local buffer to avoid furthur exposing its
* length. */
todo = sizeof(priv->d[0]) * priv->top;
if (todo > sizeof(private_bytes)) {
/* No reasonable DSA or ECDSA key should have a private key
* this large and we don't handle this case in order to avoid
* leaking the length of the private key. */
OPENSSL_PUT_ERROR(BN, BN_generate_dsa_nonce, BN_R_PRIVATE_KEY_TOO_LARGE);
goto err;
}
memcpy(private_bytes, priv->d, todo);
memset(private_bytes + todo, 0, sizeof(private_bytes) - todo);

for (done = 0; done < num_k_bytes;) {
if (RAND_pseudo_bytes(random_bytes, sizeof(random_bytes)) != 1) {
goto err;
}
SHA512_Init(&sha);
SHA512_Update(&sha, &done, sizeof(done));
SHA512_Update(&sha, private_bytes, sizeof(private_bytes));
SHA512_Update(&sha, message, message_len);
SHA512_Update(&sha, random_bytes, sizeof(random_bytes));
SHA512_Final(digest, &sha);

todo = num_k_bytes - done;
if (todo > SHA512_DIGEST_LENGTH) {
todo = SHA512_DIGEST_LENGTH;
}
memcpy(k_bytes + done, digest, todo);
done += todo;
}

if (!BN_bin2bn(k_bytes, num_k_bytes, out) ||
BN_mod(out, out, range, ctx) != 1) {
goto err;
}
ret = 1;

err:
if (k_bytes) {
OPENSSL_free(k_bytes);
}
return ret;
}

+ 2
- 2
crypto/dsa/dsa.c Dosyayı Görüntüle

@@ -313,10 +313,10 @@ int DSA_size(const DSA *dsa) {
int DSA_sign_setup(const DSA *dsa, BN_CTX *ctx, BIGNUM **out_kinv,
BIGNUM **out_r) {
if (dsa->meth->sign_setup) {
return dsa->meth->sign_setup(dsa, ctx, out_kinv, out_r);
return dsa->meth->sign_setup(dsa, ctx, out_kinv, out_r, NULL, 0);
}

return DSA_default_method.sign_setup(dsa, ctx, out_kinv, out_r);
return DSA_default_method.sign_setup(dsa, ctx, out_kinv, out_r, NULL, 0);
}

int DSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,


+ 2
- 1
crypto/dsa/dsa.h Dosyayı Görüntüle

@@ -304,7 +304,8 @@ struct dsa_method {

DSA_SIG *(*sign)(const uint8_t *digest, size_t digest_len, DSA *dsa);

int (*sign_setup)(const DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp);
int (*sign_setup)(const DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp,
const uint8_t *digest, size_t digest_len);

int (*verify)(int *out_valid, const uint8_t *digest, size_t digest_len,
DSA_SIG *sig, const DSA *dsa);


+ 13
- 2
crypto/dsa/dsa_impl.c Dosyayı Görüntüle

@@ -74,7 +74,7 @@
#define DSS_prime_checks 50

static int sign_setup(const DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
BIGNUM **rp) {
BIGNUM **rp, const uint8_t *digest, size_t digest_len) {
BN_CTX *ctx;
BIGNUM k, kq, *K, *kinv = NULL, *r = NULL;
int ret = 0;
@@ -102,7 +102,18 @@ static int sign_setup(const DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,

/* Get random k */
do {
if (!BN_rand_range(&k, dsa->q)) {
/* If possible, we'll include the private key and message digest in the k
* generation. The |digest| argument is only empty if |DSA_sign_setup| is
* being used. */
int ok;

if (digest_len > 0) {
ok = BN_generate_dsa_nonce(&k, dsa->q, dsa->priv_key, digest, digest_len,
ctx);
} else {
ok = BN_rand_range(&k, dsa->q);
}
if (!ok) {
goto err;
}
} while (BN_is_zero(&k));


+ 30
- 15
crypto/ecdsa/ecdsa.c Dosyayı Görüntüle

@@ -222,8 +222,9 @@ err:
return ret;
}

int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
BIGNUM **rp) {
static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
BIGNUM **rp, const uint8_t *digest,
size_t digest_len) {
BN_CTX *ctx = NULL;
BIGNUM *k = NULL, *r = NULL, *order = NULL, *X = NULL;
EC_POINT *tmp_point = NULL;
@@ -231,13 +232,13 @@ int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
int ret = 0;

if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL) {
OPENSSL_PUT_ERROR(ECDSA, ECDSA_sign_setup, ERR_R_PASSED_NULL_PARAMETER);
OPENSSL_PUT_ERROR(ECDSA, ecdsa_sign_setup, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}

if (ctx_in == NULL) {
if ((ctx = BN_CTX_new()) == NULL) {
OPENSSL_PUT_ERROR(ECDSA, ECDSA_sign_setup, ERR_R_MALLOC_FAILURE);
OPENSSL_PUT_ERROR(ECDSA, ecdsa_sign_setup, ERR_R_MALLOC_FAILURE);
return 0;
}
} else {
@@ -249,24 +250,34 @@ int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
order = BN_new();
X = BN_new();
if (!k || !r || !order || !X) {
OPENSSL_PUT_ERROR(ECDSA, ECDSA_sign_setup, ERR_R_MALLOC_FAILURE);
OPENSSL_PUT_ERROR(ECDSA, ecdsa_sign_setup, ERR_R_MALLOC_FAILURE);
goto err;
}
tmp_point = EC_POINT_new(group);
if (tmp_point == NULL) {
OPENSSL_PUT_ERROR(ECDSA, ECDSA_sign_setup, ERR_R_EC_LIB);
OPENSSL_PUT_ERROR(ECDSA, ecdsa_sign_setup, ERR_R_EC_LIB);
goto err;
}
if (!EC_GROUP_get_order(group, order, ctx)) {
OPENSSL_PUT_ERROR(ECDSA, ECDSA_sign_setup, ERR_R_EC_LIB);
OPENSSL_PUT_ERROR(ECDSA, ecdsa_sign_setup, ERR_R_EC_LIB);
goto err;
}

do {
/* get random k */
/* If possible, we'll include the private key and message digest in the k
* generation. The |digest| argument is only empty if |ECDSA_sign_setup| is
* being used. */
do {
if (!BN_rand_range(k, order)) {
OPENSSL_PUT_ERROR(ECDSA, ECDSA_sign_setup,
int ok;

if (digest_len > 0) {
ok = BN_generate_dsa_nonce(k, order, EC_KEY_get0_private_key(eckey),
digest, digest_len, ctx);
} else {
ok = BN_rand_range(k, order);
}
if (!ok) {
OPENSSL_PUT_ERROR(ECDSA, ecdsa_sign_setup,
ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED);
goto err;
}
@@ -287,23 +298,23 @@ int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,

/* compute r the x-coordinate of generator * k */
if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx)) {
OPENSSL_PUT_ERROR(ECDSA, ECDSA_sign_setup, ERR_R_EC_LIB);
OPENSSL_PUT_ERROR(ECDSA, ecdsa_sign_setup, ERR_R_EC_LIB);
goto err;
}
if (!EC_POINT_get_affine_coordinates_GFp(group, tmp_point, X, NULL, ctx)) {
OPENSSL_PUT_ERROR(ECDSA, ECDSA_sign_setup, ERR_R_EC_LIB);
OPENSSL_PUT_ERROR(ECDSA, ecdsa_sign_setup, ERR_R_EC_LIB);
goto err;
}

if (!BN_nnmod(r, X, order, ctx)) {
OPENSSL_PUT_ERROR(ECDSA, ECDSA_sign_setup, ERR_R_BN_LIB);
OPENSSL_PUT_ERROR(ECDSA, ecdsa_sign_setup, ERR_R_BN_LIB);
goto err;
}
} while (BN_is_zero(r));

/* compute the inverse of k */
if (!BN_mod_inverse(k, k, order, ctx)) {
OPENSSL_PUT_ERROR(ECDSA, ECDSA_sign_setup, ERR_R_BN_LIB);
OPENSSL_PUT_ERROR(ECDSA, ecdsa_sign_setup, ERR_R_BN_LIB);
goto err;
}
/* clear old values if necessary */
@@ -339,6 +350,10 @@ err:
return ret;
}

int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, BIGNUM **rp) {
return ecdsa_sign_setup(eckey, ctx, kinv, rp, NULL, 0);
}

ECDSA_SIG *ECDSA_do_sign_ex(const uint8_t *digest, size_t digest_len,
const BIGNUM *in_kinv, const BIGNUM *in_r,
EC_KEY *eckey) {
@@ -385,7 +400,7 @@ ECDSA_SIG *ECDSA_do_sign_ex(const uint8_t *digest, size_t digest_len,
}
for (;;) {
if (in_kinv == NULL || in_r == NULL) {
if (!ECDSA_sign_setup(eckey, ctx, &kinv, &ret->r)) {
if (!ecdsa_sign_setup(eckey, ctx, &kinv, &ret->r, digest, digest_len)) {
OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_sign_ex, ERR_R_ECDSA_LIB);
goto err;
}


+ 1
- 0
crypto/ecdsa/ecdsa.h Dosyayı Görüntüle

@@ -178,6 +178,7 @@ int i2d_ECDSA_SIG(const ECDSA_SIG *sig, uint8_t **outp);
#define ECDSA_F_ECDSA_sign_setup 102
#define ECDSA_F_ECDSA_do_sign_ex 103
#define ECDSA_F_ECDSA_sign_ex 104
#define ECDSA_F_ecdsa_sign_setup 105
#define ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED 100
#define ECDSA_R_NEED_NEW_SETUP_VALUES 101
#define ECDSA_R_MISSING_PARAMETERS 102


+ 1
- 0
crypto/ecdsa/ecdsa_error.c Dosyayı Görüntüle

@@ -22,6 +22,7 @@ const ERR_STRING_DATA ECDSA_error_string_data[] = {
{ERR_PACK(ERR_LIB_ECDSA, ECDSA_F_ECDSA_sign_ex, 0), "ECDSA_sign_ex"},
{ERR_PACK(ERR_LIB_ECDSA, ECDSA_F_ECDSA_sign_setup, 0), "ECDSA_sign_setup"},
{ERR_PACK(ERR_LIB_ECDSA, ECDSA_F_digest_to_bn, 0), "digest_to_bn"},
{ERR_PACK(ERR_LIB_ECDSA, ECDSA_F_ecdsa_sign_setup, 0), "ecdsa_sign_setup"},
{ERR_PACK(ERR_LIB_ECDSA, 0, ECDSA_R_BAD_SIGNATURE), "BAD_SIGNATURE"},
{ERR_PACK(ERR_LIB_ECDSA, 0, ECDSA_R_MISSING_PARAMETERS), "MISSING_PARAMETERS"},
{ERR_PACK(ERR_LIB_ECDSA, 0, ECDSA_R_NEED_NEW_SETUP_VALUES), "NEED_NEW_SETUP_VALUES"},


Yükleniyor…
İptal
Kaydet