From d992e8729ee38b082482dc010e090bb20d1c7bd5 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Fri, 6 Dec 2024 16:22:42 +0100 Subject: [PATCH] Add function to mix in an additional input into a RAND_POOL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It will be just xor-ed over the existing entropy in the pool. Reviewed-by: Paul Dale Reviewed-by: Saša Nedvědický (Merged from https://github.com/openssl/openssl/pull/26128) --- crypto/err/openssl.txt | 1 + crypto/rand/rand_err.c | 74 ++++++++++--------- crypto/rand/rand_pool.c | 39 ++++++++++ include/crypto/rand_pool.h | 2 + include/crypto/randerr.h | 2 +- include/openssl/randerr.h | 3 +- providers/implementations/rands/seed_src.c | 17 ++--- .../implementations/rands/seed_src_jitter.c | 19 ++--- 8 files changed, 96 insertions(+), 61 deletions(-) diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 404be7517a..938e2ce05d 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -1203,6 +1203,7 @@ RAND_R_PERSONALISATION_STRING_TOO_LONG:116:personalisation string too long RAND_R_PREDICTION_RESISTANCE_NOT_SUPPORTED:133:\ prediction resistance not supported RAND_R_PRNG_NOT_SEEDED:100:PRNG not seeded +RAND_R_RANDOM_POOL_IS_EMPTY:142:random pool is empty RAND_R_RANDOM_POOL_OVERFLOW:125:random pool overflow RAND_R_RANDOM_POOL_UNDERFLOW:134:random pool underflow RAND_R_REQUEST_TOO_LARGE_FOR_DRBG:117:request too large for drbg diff --git a/crypto/rand/rand_err.c b/crypto/rand/rand_err.c index 41a4c9cdea..6f078935c0 100644 --- a/crypto/rand/rand_err.c +++ b/crypto/rand/rand_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -16,84 +16,86 @@ static const ERR_STRING_DATA RAND_str_reasons[] = { {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ADDITIONAL_INPUT_TOO_LONG), - "additional input too long"}, + "additional input too long"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ALREADY_INSTANTIATED), - "already instantiated"}, + "already instantiated"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ARGUMENT_OUT_OF_RANGE), - "argument out of range"}, + "argument out of range"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_CANNOT_OPEN_FILE), "Cannot open file"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_DRBG_ALREADY_INITIALIZED), - "drbg already initialized"}, + "drbg already initialized"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_DRBG_NOT_INITIALISED), - "drbg not initialised"}, + "drbg not initialised"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ENTROPY_INPUT_TOO_LONG), - "entropy input too long"}, + "entropy input too long"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ENTROPY_OUT_OF_RANGE), - "entropy out of range"}, + "entropy out of range"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ERROR_ENTROPY_POOL_WAS_IGNORED), - "error entropy pool was ignored"}, + "error entropy pool was ignored"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ERROR_INITIALISING_DRBG), - "error initialising drbg"}, + "error initialising drbg"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ERROR_INSTANTIATING_DRBG), - "error instantiating drbg"}, + "error instantiating drbg"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ERROR_RETRIEVING_ADDITIONAL_INPUT), - "error retrieving additional input"}, + "error retrieving additional input"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ERROR_RETRIEVING_ENTROPY), - "error retrieving entropy"}, + "error retrieving entropy"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ERROR_RETRIEVING_NONCE), - "error retrieving nonce"}, + "error retrieving nonce"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_FAILED_TO_CREATE_LOCK), - "failed to create lock"}, + "failed to create lock"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_FUNC_NOT_IMPLEMENTED), - "Function not implemented"}, + "Function not implemented"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_FWRITE_ERROR), "Error writing file"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_GENERATE_ERROR), "generate error"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_INSUFFICIENT_DRBG_STRENGTH), - "insufficient drbg strength"}, + "insufficient drbg strength"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_INTERNAL_ERROR), "internal error"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_INVALID_PROPERTY_QUERY), - "invalid property query"}, + "invalid property query"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_IN_ERROR_STATE), "in error state"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_NOT_A_REGULAR_FILE), - "Not a regular file"}, + "Not a regular file"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_NOT_INSTANTIATED), "not instantiated"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_NO_DRBG_IMPLEMENTATION_SELECTED), - "no drbg implementation selected"}, + "no drbg implementation selected"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_PARENT_LOCKING_NOT_ENABLED), - "parent locking not enabled"}, + "parent locking not enabled"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_PARENT_STRENGTH_TOO_WEAK), - "parent strength too weak"}, + "parent strength too weak"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_PERSONALISATION_STRING_TOO_LONG), - "personalisation string too long"}, + "personalisation string too long"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_PREDICTION_RESISTANCE_NOT_SUPPORTED), - "prediction resistance not supported"}, + "prediction resistance not supported"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_PRNG_NOT_SEEDED), "PRNG not seeded"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_RANDOM_POOL_IS_EMPTY), + "random pool is empty"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_RANDOM_POOL_OVERFLOW), - "random pool overflow"}, + "random pool overflow"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_RANDOM_POOL_UNDERFLOW), - "random pool underflow"}, + "random pool underflow"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_REQUEST_TOO_LARGE_FOR_DRBG), - "request too large for drbg"}, + "request too large for drbg"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_RESEED_ERROR), "reseed error"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_SELFTEST_FAILURE), "selftest failure"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_TOO_LITTLE_NONCE_REQUESTED), - "too little nonce requested"}, + "too little nonce requested"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_TOO_MUCH_NONCE_REQUESTED), - "too much nonce requested"}, + "too much nonce requested"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_UNABLE_TO_CREATE_DRBG), - "unable to create drbg"}, + "unable to create drbg"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_UNABLE_TO_FETCH_DRBG), - "unable to fetch drbg"}, + "unable to fetch drbg"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_UNABLE_TO_GET_PARENT_RESEED_PROP_COUNTER), - "unable to get parent reseed prop counter"}, + "unable to get parent reseed prop counter"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_UNABLE_TO_GET_PARENT_STRENGTH), - "unable to get parent strength"}, + "unable to get parent strength"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_UNABLE_TO_LOCK_PARENT), - "unable to lock parent"}, + "unable to lock parent"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_UNSUPPORTED_DRBG_FLAGS), - "unsupported drbg flags"}, + "unsupported drbg flags"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_UNSUPPORTED_DRBG_TYPE), - "unsupported drbg type"}, + "unsupported drbg type"}, {0, NULL} }; diff --git a/crypto/rand/rand_pool.c b/crypto/rand/rand_pool.c index 8d77b77fd2..4f258b87ee 100644 --- a/crypto/rand/rand_pool.c +++ b/crypto/rand/rand_pool.c @@ -406,3 +406,42 @@ int ossl_rand_pool_add_end(RAND_POOL *pool, size_t len, size_t entropy) return 1; } + +/** + * @brief Mix in the additional input into an existing entropy in the pool + * + * @param pool A RAND_POOL to mix the additional input in + * @param adin A buffer with the additional input + * @param adin_len A length of the additional input + * + * @return 1 if there is any existing entropy in the pool so the additional input + * can be mixed in, 0 otherwise. + */ + +int ossl_rand_pool_adin_mix_in(RAND_POOL *pool, const unsigned char *adin, + size_t adin_len) +{ + if (adin == NULL || adin_len == 0) + /* Nothing to mix in -> success */ + return 1; + + if (pool->buffer == NULL) { + ERR_raise(ERR_LIB_RAND, ERR_R_INTERNAL_ERROR); + return 0; + } + + if (pool->len == 0) { + ERR_raise(ERR_LIB_RAND, RAND_R_RANDOM_POOL_IS_EMPTY); + return 0; + } + + if (adin != NULL && adin_len > 0) { + size_t i; + + /* xor the additional data into the pool */ + for (i = 0; i < adin_len; ++i) + pool->buffer[i % pool->len] ^= adin[i]; + } + + return 1; +} diff --git a/include/crypto/rand_pool.h b/include/crypto/rand_pool.h index f4d1d954bc..d76040924d 100644 --- a/include/crypto/rand_pool.h +++ b/include/crypto/rand_pool.h @@ -105,5 +105,7 @@ int ossl_rand_pool_add(RAND_POOL *pool, const unsigned char *buffer, size_t len, size_t entropy); unsigned char *ossl_rand_pool_add_begin(RAND_POOL *pool, size_t len); int ossl_rand_pool_add_end(RAND_POOL *pool, size_t len, size_t entropy); +int ossl_rand_pool_adin_mix_in(RAND_POOL *pool, const unsigned char *adin, + size_t adin_len); #endif /* OSSL_PROVIDER_RAND_POOL_H */ diff --git a/include/crypto/randerr.h b/include/crypto/randerr.h index 6e2eb0716f..3a73326734 100644 --- a/include/crypto/randerr.h +++ b/include/crypto/randerr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/include/openssl/randerr.h b/include/openssl/randerr.h index 04880374a3..5e1e6d7996 100644 --- a/include/openssl/randerr.h +++ b/include/openssl/randerr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -51,6 +51,7 @@ # define RAND_R_PERSONALISATION_STRING_TOO_LONG 116 # define RAND_R_PREDICTION_RESISTANCE_NOT_SUPPORTED 133 # define RAND_R_PRNG_NOT_SEEDED 100 +# define RAND_R_RANDOM_POOL_IS_EMPTY 142 # define RAND_R_RANDOM_POOL_OVERFLOW 125 # define RAND_R_RANDOM_POOL_UNDERFLOW 134 # define RAND_R_REQUEST_TOO_LARGE_FOR_DRBG 117 diff --git a/providers/implementations/rands/seed_src.c b/providers/implementations/rands/seed_src.c index e8f7ec9efc..b335a63862 100644 --- a/providers/implementations/rands/seed_src.c +++ b/providers/implementations/rands/seed_src.c @@ -88,8 +88,8 @@ static int seed_src_uninstantiate(void *vseed) static int seed_src_generate(void *vseed, unsigned char *out, size_t outlen, unsigned int strength, ossl_unused int prediction_resistance, - ossl_unused const unsigned char *adin, - ossl_unused size_t adin_len) + const unsigned char *adin, + size_t adin_len) { PROV_SEED_SRC *s = (PROV_SEED_SRC *)vseed; size_t entropy_available; @@ -111,8 +111,11 @@ static int seed_src_generate(void *vseed, unsigned char *out, size_t outlen, /* Get entropy by polling system entropy sources. */ entropy_available = ossl_pool_acquire_entropy(pool); - if (entropy_available > 0) + if (entropy_available > 0) { + if (!ossl_rand_pool_adin_mix_in(pool, adin, adin_len)) + return 0; memcpy(out, ossl_rand_pool_buffer(pool), ossl_rand_pool_length(pool)); + } ossl_rand_pool_free(pool); return entropy_available > 0; @@ -179,7 +182,6 @@ static size_t seed_get_seed(void *vseed, unsigned char **pout, { size_t ret = 0; size_t entropy_available = 0; - size_t i; RAND_POOL *pool; pool = ossl_rand_pool_new(entropy, 1, min_len, max_len); @@ -191,13 +193,10 @@ static size_t seed_get_seed(void *vseed, unsigned char **pout, /* Get entropy by polling system entropy sources. */ entropy_available = ossl_pool_acquire_entropy(pool); - if (entropy_available > 0) { + if (entropy_available > 0 + && ossl_rand_pool_adin_mix_in(pool, adin, adin_len)) { ret = ossl_rand_pool_length(pool); *pout = ossl_rand_pool_detach(pool); - - /* xor the additional data into the output */ - for (i = 0 ; i < adin_len ; ++i) - (*pout)[i % ret] ^= adin[i]; } else { ERR_raise(ERR_LIB_PROV, PROV_R_ENTROPY_SOURCE_STRENGTH_TOO_WEAK); } diff --git a/providers/implementations/rands/seed_src_jitter.c b/providers/implementations/rands/seed_src_jitter.c index 23d8384a40..5d1ff37402 100644 --- a/providers/implementations/rands/seed_src_jitter.c +++ b/providers/implementations/rands/seed_src_jitter.c @@ -197,15 +197,10 @@ static int jitter_generate(void *vseed, unsigned char *out, size_t outlen, /* Get entropy from jitter entropy library. */ entropy_available = ossl_prov_acquire_entropy_from_jitter(s, pool); - if (entropy_available > 0) + if (entropy_available > 0) { + if (!ossl_rand_pool_adin_mix_in(pool, adin, adin_len)) + return 0; memcpy(out, ossl_rand_pool_buffer(pool), ossl_rand_pool_length(pool)); - - if (adin != NULL && adin_len > 0) { - size_t i; - - /* xor the additional data into the output */ - for (i = 0; i < adin_len; ++i) - out[i % outlen] ^= adin[i]; } ossl_rand_pool_free(pool); @@ -275,7 +270,6 @@ static size_t jitter_get_seed(void *vseed, unsigned char **pout, { size_t ret = 0; size_t entropy_available = 0; - size_t i; RAND_POOL *pool; PROV_JITTER *s = (PROV_JITTER *)vseed; @@ -288,13 +282,10 @@ static size_t jitter_get_seed(void *vseed, unsigned char **pout, /* Get entropy from jitter entropy library. */ entropy_available = ossl_prov_acquire_entropy_from_jitter(s, pool); - if (entropy_available > 0) { + if (entropy_available > 0 + && ossl_rand_pool_adin_mix_in(pool, adin, adin_len)) { ret = ossl_rand_pool_length(pool); *pout = ossl_rand_pool_detach(pool); - - /* xor the additional data into the output */ - for (i = 0; i < adin_len; ++i) - (*pout)[i % ret] ^= adin[i]; } else { ERR_raise(ERR_LIB_PROV, PROV_R_ENTROPY_SOURCE_STRENGTH_TOO_WEAK); }