diff options
author | Jens Wiklander <jens.wiklander@linaro.org> | 2018-06-14 11:12:00 +0200 |
---|---|---|
committer | Jérôme Forissier <jerome.forissier@linaro.org> | 2018-06-18 10:01:13 +0200 |
commit | 6e954a6e42bd37911605d3b4cd22e4d1d23c2372 (patch) | |
tree | 1c305f414f6c5eccc142cbf6d76bf8784836d569 /core/lib | |
parent | b8d0b26e700584b85819b33306d93811deb48800 (diff) |
core: add new RNG implementation
Adds a new cryptographically secure pseudo random number generator known
as Fortuna. The implementation is based on the description in [0]. This
implementation replaces the implementation in LTC which was used until
now.
Gathering of entropy has been refined with crypto_rng_add_event() to
better match how entropy is added to Fortuna. A enum crypto_rng_src
identifies the source of the event. The source also controls how the
event is added. There are two options available, queue it in a circular
buffer for later processing or adding it directly to a pool. The former
option is suitable when being called from an interrupt handler or some
other place where RPC to normal world is forbidden.
plat_prng_add_jitter_entropy_norpc() is removed and
plat_prng_add_jitter_entropy() is updated to use this new entropy source
scheme.
The configuration of LTC is simplified by this, now PRNG is always drawn
via prng_mpa_desc.
plat_rng_init() takes care of initializing the PRNG in order to allow
platforms to override or enhance the Fortuna integration.
[0] Link:https://www.schneier.com/academic/paperfiles/fortuna.pdf
Reviewed-by: Jerome Forissier <jerome.forissier@linaro.org>
Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
Diffstat (limited to 'core/lib')
-rw-r--r-- | core/lib/libtomcrypt/src/sub.mk | 1 | ||||
-rw-r--r-- | core/lib/libtomcrypt/src/tee_ltc_provider.c | 204 |
2 files changed, 13 insertions, 192 deletions
diff --git a/core/lib/libtomcrypt/src/sub.mk b/core/lib/libtomcrypt/src/sub.mk index 89e74bd9..ca88fb1f 100644 --- a/core/lib/libtomcrypt/src/sub.mk +++ b/core/lib/libtomcrypt/src/sub.mk @@ -16,4 +16,3 @@ subdirs-$(_CFG_CRYPTO_WITH_ACIPHER) += math subdirs-y += misc subdirs-y += modes subdirs-$(_CFG_CRYPTO_WITH_ACIPHER) += pk -subdirs-$(CFG_WITH_SOFTWARE_PRNG) += prngs diff --git a/core/lib/libtomcrypt/src/tee_ltc_provider.c b/core/lib/libtomcrypt/src/tee_ltc_provider.c index 4cec762a..86000421 100644 --- a/core/lib/libtomcrypt/src/tee_ltc_provider.c +++ b/core/lib/libtomcrypt/src/tee_ltc_provider.c @@ -25,8 +25,6 @@ #include <kernel/thread.h> #endif -#if !defined(CFG_WITH_SOFTWARE_PRNG) - /* Random generator */ static int prng_mpa_start(union Prng_state *prng __unused) { @@ -49,10 +47,10 @@ static int prng_mpa_ready(union Prng_state *prng __unused) static unsigned long prng_mpa_read(unsigned char *out, unsigned long outlen, union Prng_state *prng __unused) { - if (TEE_SUCCESS == get_rng_array(out, outlen)) - return outlen; - else + if (crypto_rng_read(out, outlen)) return 0; + + return outlen; } static int prng_mpa_done(union Prng_state *prng __unused) @@ -92,69 +90,6 @@ static const struct ltc_prng_descriptor prng_mpa_desc = { .test = &prng_mpa_test, }; -#endif /* !CFG_WITH_SOFTWARE_PRNG */ - -struct tee_ltc_prng { - int index; - const char *name; - prng_state state; - bool inited; -}; - -static struct tee_ltc_prng _tee_ltc_prng = -#if defined(CFG_WITH_SOFTWARE_PRNG) - { -#if defined(_CFG_CRYPTO_WITH_FORTUNA_PRNG) - .name = "fortuna", -#else - /* - * we need AES and SHA256 for fortuna PRNG, - * if the system configuration can't provide those, - * fallback to RC4 - */ - .name = "rc4", -#endif - }; -#else - { - .name = "prng_mpa", - }; -#endif - -static struct tee_ltc_prng *tee_ltc_get_prng(void) -{ - return &_tee_ltc_prng; -} - -static TEE_Result tee_ltc_prng_init(struct tee_ltc_prng *prng) -{ - int res; - int prng_index; - - assert(prng); - - prng_index = find_prng(prng->name); - if (prng_index == -1) - return TEE_ERROR_BAD_PARAMETERS; - - if (!prng->inited) { - res = prng_descriptor[prng_index]->start(&prng->state); - if (res != CRYPT_OK) - return TEE_ERROR_BAD_STATE; - - plat_prng_add_jitter_entropy_norpc(); - - res = prng_descriptor[prng_index]->ready(&prng->state); - if (res != CRYPT_OK) - return TEE_ERROR_BAD_STATE; - - prng->index = prng_index; - prng->inited = true; - } - - return TEE_SUCCESS; -} - /* * tee_ltc_reg_algs(): Registers * - algorithms @@ -189,16 +124,7 @@ static void tee_ltc_reg_algs(void) #if defined(CFG_CRYPTO_SHA512) register_hash(&sha512_desc); #endif - -#if defined(CFG_WITH_SOFTWARE_PRNG) -#if defined(_CFG_CRYPTO_WITH_FORTUNA_PRNG) - register_prng(&fortuna_desc); -#else - register_prng(&rc4_desc); -#endif -#else register_prng(&prng_mpa_desc); -#endif } @@ -692,13 +618,12 @@ TEE_Result crypto_acipher_gen_rsa_key(struct rsa_keypair *key, size_t key_size) rsa_key ltc_tmp_key; int ltc_res; long e; - struct tee_ltc_prng *prng = tee_ltc_get_prng(); /* get the public exponent */ e = mp_get_int(key->e); /* Generate a temporary RSA key */ - ltc_res = rsa_make_key(&prng->state, prng->index, key_size/8, e, + ltc_res = rsa_make_key(NULL, find_prng("prng_mpa"), key_size / 8, e, <c_tmp_key); if (ltc_res != CRYPT_OK) { res = TEE_ERROR_BAD_PARAMETERS; @@ -934,7 +859,6 @@ TEE_Result crypto_acipher_rsaes_encrypt(uint32_t algo, .e = key->e, .N = key->n }; - struct tee_ltc_prng *prng = tee_ltc_get_prng(); mod_size = ltc_mp.unsigned_size((void *)(ltc_key.N)); if (*dst_len < mod_size) { @@ -956,7 +880,7 @@ TEE_Result crypto_acipher_rsaes_encrypt(uint32_t algo, ltc_res = rsa_encrypt_key_ex(src, src_len, dst, (unsigned long *)(dst_len), label, - label_len, &prng->state, prng->index, + label_len, NULL, find_prng("prng_mpa"), ltc_hashindex, ltc_rsa_algo, <c_key); switch (ltc_res) { case CRYPT_PK_INVALID_PADDING: @@ -988,7 +912,6 @@ TEE_Result crypto_acipher_rsassa_sign(uint32_t algo, struct rsa_keypair *key, int ltc_res, ltc_rsa_algo, ltc_hashindex; unsigned long ltc_sig_len; rsa_key ltc_key = { 0, }; - struct tee_ltc_prng *prng = tee_ltc_get_prng(); ltc_key.type = PK_PRIVATE; ltc_key.e = key->e; @@ -1050,7 +973,7 @@ TEE_Result crypto_acipher_rsassa_sign(uint32_t algo, struct rsa_keypair *key, ltc_sig_len = mod_size; ltc_res = rsa_sign_hash_ex(msg, msg_len, sig, <c_sig_len, - ltc_rsa_algo, &prng->state, prng->index, + ltc_rsa_algo, NULL, find_prng("prng_mpa"), ltc_hashindex, salt_len, <c_key); *sig_len = ltc_sig_len; @@ -1187,7 +1110,6 @@ TEE_Result crypto_acipher_gen_dsa_key(struct dsa_keypair *key, size_t key_size) dsa_key ltc_tmp_key; size_t group_size, modulus_size = key_size/8; int ltc_res; - struct tee_ltc_prng *prng = tee_ltc_get_prng(); if (modulus_size <= 128) group_size = 20; @@ -1199,7 +1121,7 @@ TEE_Result crypto_acipher_gen_dsa_key(struct dsa_keypair *key, size_t key_size) group_size = 40; /* Generate the DSA key */ - ltc_res = dsa_make_key(&prng->state, prng->index, group_size, + ltc_res = dsa_make_key(NULL, find_prng("prng_mpa"), group_size, modulus_size, <c_tmp_key); if (ltc_res != CRYPT_OK) { res = TEE_ERROR_BAD_PARAMETERS; @@ -1238,7 +1160,6 @@ TEE_Result crypto_acipher_dsa_sign(uint32_t algo, struct dsa_keypair *key, .y = key->y, .x = key->x, }; - struct tee_ltc_prng *prng = tee_ltc_get_prng(); if (algo != TEE_ALG_DSA_SHA1 && algo != TEE_ALG_DSA_SHA224 && @@ -1270,8 +1191,8 @@ TEE_Result crypto_acipher_dsa_sign(uint32_t algo, struct dsa_keypair *key, goto err; } - ltc_res = dsa_sign_hash_raw(msg, msg_len, r, s, &prng->state, - prng->index, <c_key); + ltc_res = dsa_sign_hash_raw(msg, msg_len, r, s, NULL, + find_prng("prng_mpa"), <c_key); if (ltc_res == CRYPT_OK) { *sig_len = 2 * mp_unsigned_bin_size(ltc_key.q); @@ -1363,12 +1284,11 @@ TEE_Result crypto_acipher_gen_dh_key(struct dh_keypair *key, struct bignum *q, TEE_Result res; dh_key ltc_tmp_key; int ltc_res; - struct tee_ltc_prng *prng = tee_ltc_get_prng(); /* Generate the DH key */ ltc_tmp_key.g = key->g; ltc_tmp_key.p = key->p; - ltc_res = dh_make_key(&prng->state, prng->index, q, xbits, + ltc_res = dh_make_key(NULL, find_prng("prng_mpa"), q, xbits, <c_tmp_key); if (ltc_res != CRYPT_OK) { res = TEE_ERROR_BAD_PARAMETERS; @@ -1521,7 +1441,6 @@ TEE_Result crypto_acipher_gen_ecc_key(struct ecc_keypair *key) TEE_Result res; ecc_key ltc_tmp_key; int ltc_res; - struct tee_ltc_prng *prng = tee_ltc_get_prng(); size_t key_size_bytes = 0; size_t key_size_bits = 0; @@ -1531,7 +1450,7 @@ TEE_Result crypto_acipher_gen_ecc_key(struct ecc_keypair *key) } /* Generate the ECC key */ - ltc_res = ecc_make_key(&prng->state, prng->index, + ltc_res = ecc_make_key(NULL, find_prng("prng_mpa"), key_size_bytes, <c_tmp_key); if (ltc_res != CRYPT_OK) { return TEE_ERROR_BAD_PARAMETERS; @@ -1647,7 +1566,6 @@ TEE_Result crypto_acipher_ecc_sign(uint32_t algo, struct ecc_keypair *key, void *r, *s; size_t key_size_bytes; ecc_key ltc_key; - struct tee_ltc_prng *prng = tee_ltc_get_prng(); if (algo == 0) { res = TEE_ERROR_BAD_PARAMETERS; @@ -1672,7 +1590,7 @@ TEE_Result crypto_acipher_ecc_sign(uint32_t algo, struct ecc_keypair *key, } ltc_res = ecc_sign_hash_raw(msg, msg_len, r, s, - &prng->state, prng->index, <c_key); + NULL, find_prng("prng_mpa"), <c_key); if (ltc_res == CRYPT_OK) { *sig_len = 2 * key_size_bytes; @@ -2867,69 +2785,6 @@ void crypto_aes_gcm_final(void *ctx) } #endif /*CFG_CRYPTO_AES_GCM_FROM_CRYPTOLIB*/ -/****************************************************************************** - * Pseudo Random Number Generator - ******************************************************************************/ -TEE_Result crypto_rng_read(void *buf, size_t blen) -{ - int err; - struct tee_ltc_prng *prng = tee_ltc_get_prng(); - - err = prng_is_valid(prng->index); - - if (err != CRYPT_OK) - return TEE_ERROR_BAD_STATE; - - if (prng_descriptor[prng->index]->read(buf, blen, &prng->state) != - (unsigned long)blen) - return TEE_ERROR_BAD_STATE; - - return TEE_SUCCESS; -} - -/* Called as a result of rng_generate() below */ -static TEE_Result _tee_ltc_prng_add_entropy( - const uint8_t *inbuf __maybe_unused, size_t len __maybe_unused) -{ -#if defined(CFG_WITH_SOFTWARE_PRNG) - int err; -#ifdef _CFG_CRYPTO_WITH_FORTUNA_PRNG - int (*add_entropy)(const unsigned char *, unsigned long, - prng_state *) = fortuna_add_entropy; -#else - int (*add_entropy)(const unsigned char *, unsigned long, - prng_state *) = rc4_add_entropy; -#endif - - err = add_entropy(inbuf, len, &_tee_ltc_prng.state); - if (err != CRYPT_OK) - return TEE_ERROR_BAD_STATE; - - return TEE_SUCCESS; -#else - return TEE_ERROR_BAD_STATE; -#endif -} - -TEE_Result crypto_rng_add_entropy(const uint8_t *inbuf, size_t len) -{ - int err; - struct tee_ltc_prng *prng = tee_ltc_get_prng(); - - err = prng_is_valid(prng->index); - - if (err != CRYPT_OK) - return _tee_ltc_prng_add_entropy(inbuf, len); - - err = prng_descriptor[prng->index]->add_entropy( - inbuf, len, &prng->state); - - if (err != CRYPT_OK) - return TEE_ERROR_BAD_STATE; - - return TEE_SUCCESS; -} - TEE_Result crypto_init(void) { #if defined(_CFG_CRYPTO_WITH_ACIPHER) @@ -2937,7 +2792,7 @@ TEE_Result crypto_init(void) #endif tee_ltc_reg_algs(); - return tee_ltc_prng_init(tee_ltc_get_prng()); + return TEE_SUCCESS; } #if defined(CFG_WITH_VFP) @@ -2971,39 +2826,6 @@ TEE_Result hash_sha256_check(const uint8_t *hash, const uint8_t *data, } #endif -TEE_Result rng_generate(void *buffer, size_t len) -{ -#if defined(CFG_WITH_SOFTWARE_PRNG) -#ifdef _CFG_CRYPTO_WITH_FORTUNA_PRNG - int (*start)(prng_state *) = fortuna_start; - int (*ready)(prng_state *) = fortuna_ready; - unsigned long (*read)(unsigned char *, unsigned long, prng_state *) = - fortuna_read; -#else - int (*start)(prng_state *) = rc4_start; - int (*ready)(prng_state *) = rc4_ready; - unsigned long (*read)(unsigned char *, unsigned long, prng_state *) = - rc4_read; -#endif - - if (!_tee_ltc_prng.inited) { - if (start(&_tee_ltc_prng.state) != CRYPT_OK) - return TEE_ERROR_BAD_STATE; - plat_prng_add_jitter_entropy_norpc(); - if (ready(&_tee_ltc_prng.state) != CRYPT_OK) - return TEE_ERROR_BAD_STATE; - _tee_ltc_prng.inited = true; - } - if (read(buffer, len, &_tee_ltc_prng.state) != len) - return TEE_ERROR_BAD_STATE; - return TEE_SUCCESS; - - -#else - return get_rng_array(buffer, len); -#endif -} - TEE_Result crypto_aes_expand_enc_key(const void *key, size_t key_len, void *enc_key, unsigned int *rounds) { |