mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2026-07-30 16:26:33 +08:00
Protect the PSA RNG from duplication on fork
If a process forks with the PSA subsystem active, the PSA RNG state is duplicated. This led to the parent process and the child process generating the same sequence of random numbers. Fix this by forcing a reseed if the value of `getpid()` changes. This is the same technique used in OpenSSL ≥1.1.1d. Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
This commit is contained in:
parent
ce8a71c071
commit
0b93865aed
@ -6,6 +6,10 @@ Features
|
||||
prediction resistance in the PSA random generator.
|
||||
|
||||
Security
|
||||
* If an application called psa_crypto_init() then fork() and continued to
|
||||
use cryptography APIs (possibly indirectly, e.g. for TLS), the random
|
||||
generator states were duplicated. Fix this by forcing a RNG reseed in
|
||||
the child process. CVE-2026-25835
|
||||
* Applications running in environments where the application state is
|
||||
cloned (for example due to resuming a frozen system state multiple
|
||||
times, or due to cloning a virtual machine image) should arrange to
|
||||
|
||||
@ -13,11 +13,17 @@
|
||||
#include "psa_crypto_core.h"
|
||||
#include "psa_crypto_random.h"
|
||||
#include "psa_crypto_random_impl.h"
|
||||
#include "threading_internal.h"
|
||||
|
||||
#if defined(MBEDTLS_PSA_INJECT_ENTROPY)
|
||||
#include "entropy_poll.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_PLATFORM_IS_UNIXLIKE)
|
||||
/* For getpid(), for fork protection */
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
void psa_random_internal_init(mbedtls_psa_random_context_t *rng)
|
||||
{
|
||||
/* Set default configuration if
|
||||
@ -53,6 +59,9 @@ psa_status_t psa_random_internal_seed(mbedtls_psa_random_context_t *rng)
|
||||
const unsigned char drbg_seed[] = "PSA";
|
||||
int ret = mbedtls_psa_drbg_seed(&rng->drbg, &rng->entropy,
|
||||
drbg_seed, sizeof(drbg_seed) - 1);
|
||||
#if defined(MBEDTLS_PLATFORM_IS_UNIXLIKE)
|
||||
rng->pid = getpid();
|
||||
#endif
|
||||
return mbedtls_to_psa_error(ret);
|
||||
}
|
||||
|
||||
@ -60,6 +69,27 @@ psa_status_t psa_random_internal_generate(
|
||||
mbedtls_psa_random_context_t *rng,
|
||||
uint8_t *output, size_t output_size)
|
||||
{
|
||||
#if defined(MBEDTLS_PLATFORM_IS_UNIXLIKE)
|
||||
intmax_t pid = getpid();
|
||||
if (pid != rng->pid) {
|
||||
/* This is a (grand...)child of the original process, but
|
||||
* we inherited the RNG state from our parent. We must reseed! */
|
||||
#if defined(MBEDTLS_THREADING_C)
|
||||
mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex);
|
||||
#endif /* defined(MBEDTLS_THREADING_C) */
|
||||
int ret = mbedtls_psa_drbg_reseed(&rng->drbg, NULL, 0);
|
||||
if (ret == 0) {
|
||||
rng->pid = pid;
|
||||
}
|
||||
#if defined(MBEDTLS_THREADING_C)
|
||||
mbedtls_mutex_unlock(&mbedtls_threading_psa_rngdata_mutex);
|
||||
#endif /* defined(MBEDTLS_THREADING_C) */
|
||||
if (ret != 0) {
|
||||
return mbedtls_to_psa_error(ret);
|
||||
}
|
||||
}
|
||||
#endif /* MBEDTLS_PLATFORM_IS_UNIXLIKE */
|
||||
|
||||
while (output_size > 0) {
|
||||
size_t request_size =
|
||||
(output_size > MBEDTLS_PSA_RANDOM_MAX_REQUEST ?
|
||||
|
||||
@ -70,6 +70,23 @@ typedef struct {
|
||||
void (* entropy_free)(mbedtls_entropy_context *ctx);
|
||||
mbedtls_entropy_context entropy;
|
||||
mbedtls_psa_drbg_context_t drbg;
|
||||
#if defined(MBEDTLS_PLATFORM_IS_UNIXLIKE)
|
||||
/* Fork protection: normally pid = getpid(). If the value changes,
|
||||
* we are in a (grand)*child of the original process, so reseed
|
||||
* the RNG to ensure that the child and the original process have
|
||||
* distinct RNG states. See psa_random_internal_generate().
|
||||
*
|
||||
* The type is intmax_t, not pid_t, for portability reasons:
|
||||
* pid_t is defined in `unistd.h`, but on some platforms, it may
|
||||
* only be defined if a certain compatibility level is requested
|
||||
* by defining a macro such as _POSIX_C_SOURCE or _XOPEN_SOURCE.
|
||||
* The macro needs to be defined before any system header, which
|
||||
* may be hard to do in some C files that include this header
|
||||
* (e.g. test suites). So we sidestep this complication, at the
|
||||
* cost of possibly a few more instructions to compare pid values.
|
||||
*/
|
||||
intmax_t pid;
|
||||
#endif
|
||||
} mbedtls_psa_random_context_t;
|
||||
|
||||
/** Initialize the PSA DRBG.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user