81 lines
2.4 KiB
Diff
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;
|
||
|
}
|