When ssh_crypto_init() cannot seed the CTR-DRBG, typically because no entropy source is available, it frees the DRBG context and reports failure. The automatic constructor initialisation has no way to hand that failure to the application, so the library remains loaded with a zeroed DRBG context, and the first ssh_get_random() call runs mbedtls_ctr_drbg_random() on that zeroed context and crashes inside mbedtls (SIGSEGV or SIGBUS, depending on the platform). The same holds for any RNG use after ssh_finalize().
Make ssh_mbedtls_initialized() available with mbedtls 3.x as well and check it in ssh_mbedtls_random() before touching the DRBG, returning failure exactly as the PSA (mbedtls 4.x) implementation already does. The callers of ssh_get_random() all handle a failure return. Signed-off-by: Daniel Golle <[email protected]> --- include/libssh/libmbedcrypto.h | 1 + src/getrandom_mbedcrypto.c | 3 +++ src/libmbedcrypto.c | 4 ++-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/include/libssh/libmbedcrypto.h b/include/libssh/libmbedcrypto.h index 2e021ef7..0ba3d6fe 100644 --- a/include/libssh/libmbedcrypto.h +++ b/include/libssh/libmbedcrypto.h @@ -162,6 +162,7 @@ mbedtls_ctr_drbg_context *ssh_get_mbedtls_ctr_drbg_context(void); #endif /* MBEDTLS_VERSION_MAJOR */ +int ssh_mbedtls_initialized(void); int ssh_mbedtls_random(void *where, int len, int strong); ssh_string make_ecpoint_string(const mbedtls_ecp_group *g, const diff --git a/src/getrandom_mbedcrypto.c b/src/getrandom_mbedcrypto.c index 850a17d9..d8337050 100644 --- a/src/getrandom_mbedcrypto.c +++ b/src/getrandom_mbedcrypto.c @@ -33,6 +33,9 @@ int ssh_mbedtls_random(void *where, int len, int strong) { int rc = 0; + if (!ssh_mbedtls_initialized()) { + return 0; + } if (strong) { mbedtls_ctr_drbg_set_prediction_resistance(&ssh_mbedtls_ctr_drbg, MBEDTLS_CTR_DRBG_PR_ON); diff --git a/src/libmbedcrypto.c b/src/libmbedcrypto.c index a6df81ad..8fd7cf18 100644 --- a/src/libmbedcrypto.c +++ b/src/libmbedcrypto.c @@ -64,12 +64,12 @@ int ssh_kdf(struct ssh_crypto_struct *crypto, key_type, output, requested_len); } -#if MBEDTLS_VERSION_MAJOR >= 4 int ssh_mbedtls_initialized(void) { return libmbedcrypto_initialized; } -#else /* MBEDTLS_VERSION_MAJOR < 4 */ + +#if MBEDTLS_VERSION_MAJOR < 4 void ssh_reseed(void) { -- 2.55.0
