openssl-1_1/openssl-1_1-serialize-jitterentropy-calls.patch

81 lines
2.4 KiB
Diff

---
crypto/fips/fips_entropy.c | 40 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 38 insertions(+), 2 deletions(-)
--- a/crypto/fips/fips_entropy.c
+++ b/crypto/fips/fips_entropy.c
@@ -4,35 +4,71 @@
#include "jitterentropy.h"
static struct rand_data* ec = NULL;
+static CRYPTO_RWLOCK *jent_lock = NULL;
+static int stop = 0;
struct rand_data* FIPS_entropy_init(void)
{
- if (ec != NULL)
+ if (ec != NULL) {
/* Entropy source has been initiated and collector allocated */
return ec;
+ }
+ if (stop != 0) {
+ /* FIPS_entropy_cleanup() already called, don't initialize it again */
+ return NULL;
+ }
+ if (jent_lock == NULL) {
+ /* Allocates a new lock to serialize access to jent library */
+ jent_lock = CRYPTO_THREAD_lock_new();
+ if (jent_lock == NULL) {
+ return NULL;
+ }
+ }
+ if (CRYPTO_THREAD_write_lock(jent_lock) == 0) {
+ return NULL;
+ }
/* If the initialization is successful, the call returns with 0 */
if (jent_entropy_init_ex(1, JENT_FORCE_FIPS) == 0)
/* Allocate entropy collector */
ec = jent_entropy_collector_alloc(1, JENT_FORCE_FIPS);
+ CRYPTO_THREAD_unlock(jent_lock);
return ec;
}
void FIPS_entropy_cleanup(void)
{
+ if (jent_lock != NULL && stop == 0) {
+ CRYPTO_THREAD_write_lock(jent_lock);
+ }
+ /* Disable re-initialization in FIPS_entropy_init() */
+ stop = 1;
/* Free entropy collector */
if (ec != NULL) {
jent_entropy_collector_free(ec);
ec = NULL;
}
+ CRYPTO_THREAD_lock_free(jent_lock);
+ jent_lock = NULL;
}
ssize_t FIPS_jitter_entropy(unsigned char *buf, size_t buflen)
{
ssize_t ent_bytes = -1;
- if (buf != NULL && buflen != 0 && FIPS_entropy_init()) {
+ /*
+ * Order is important. We need to call FIPS_entropy_init() before we
+ * acquire jent_lock, otherwise it can lead to deadlock. Once we have
+ * jent_lock, we need to ensure that FIPS_entropy_cleanup() was not called
+ * in the meantime. Then it's safe to read entropy.
+ */
+ if (buf != NULL
+ && buflen != 0
+ && FIPS_entropy_init()
+ && CRYPTO_THREAD_write_lock(jent_lock) != 0
+ && stop == 0) {
/* Get entropy */
ent_bytes = jent_read_entropy_safe(&ec, (char *)buf, buflen);
+ CRYPTO_THREAD_unlock(jent_lock);
}
return ent_bytes;
}