diff options
Diffstat (limited to 'security/nss/lib/freebl/det_rng.c')
-rw-r--r-- | security/nss/lib/freebl/det_rng.c | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/security/nss/lib/freebl/det_rng.c b/security/nss/lib/freebl/det_rng.c new file mode 100644 index 0000000000..f50a3c4446 --- /dev/null +++ b/security/nss/lib/freebl/det_rng.c @@ -0,0 +1,163 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "blapi.h" +#include "blapit.h" +#include "Hacl_Chacha20.h" +#include "nssilock.h" +#include "seccomon.h" +#include "secerr.h" +#include "prinit.h" + +#define GLOBAL_BYTES_SIZE 100 +static PRUint8 globalBytes[GLOBAL_BYTES_SIZE]; +static unsigned long globalNumCalls = 0; +static PZLock *rng_lock = NULL; +static PRCallOnceType coRNGInit; +static const PRCallOnceType pristineCallOnce; + +static PRStatus +rng_init(void) +{ + rng_lock = PZ_NewLock(nssILockOther); + if (!rng_lock) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return PR_FAILURE; + } + /* --- LOCKED --- */ + PZ_Lock(rng_lock); + memset(globalBytes, 0, GLOBAL_BYTES_SIZE); + PZ_Unlock(rng_lock); + /* --- UNLOCKED --- */ + + return PR_SUCCESS; +} + +SECStatus +RNG_RNGInit(void) +{ + /* Allow only one call to initialize the context */ + if (PR_CallOnce(&coRNGInit, rng_init) != PR_SUCCESS) { + return SECFailure; + } + + return SECSuccess; +} + +/* Take min(size, GLOBAL_BYTES_SIZE) bytes from data and use as seed and reset + * the rng state. */ +SECStatus +RNG_RandomUpdate(const void *data, size_t bytes) +{ + /* Check for a valid RNG lock. */ + PORT_Assert(rng_lock != NULL); + if (rng_lock == NULL) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + /* --- LOCKED --- */ + PZ_Lock(rng_lock); + memset(globalBytes, 0, GLOBAL_BYTES_SIZE); + globalNumCalls = 0; + if (data) { + memcpy(globalBytes, (PRUint8 *)data, PR_MIN(bytes, GLOBAL_BYTES_SIZE)); + } + PZ_Unlock(rng_lock); + /* --- UNLOCKED --- */ + + return SECSuccess; +} + +SECStatus +RNG_GenerateGlobalRandomBytes(void *dest, size_t len) +{ + static const uint8_t key[32] = { 0 }; + uint8_t nonce[12] = { 0 }; + + /* Check for a valid RNG lock. */ + PORT_Assert(rng_lock != NULL); + if (rng_lock == NULL) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + /* --- LOCKED --- */ + PZ_Lock(rng_lock); + + memcpy(nonce, &globalNumCalls, sizeof(globalNumCalls)); + globalNumCalls++; + + ChaCha20Poly1305Context *cx = + ChaCha20Poly1305_CreateContext(key, sizeof(key), 16); + if (!cx) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + PZ_Unlock(rng_lock); + return SECFailure; + } + + memset(dest, 0, len); + memcpy(dest, globalBytes, PR_MIN(len, GLOBAL_BYTES_SIZE)); + Hacl_Chacha20_chacha20_encrypt(len, (uint8_t *)dest, (uint8_t *)dest, + (uint8_t *)key, nonce, 0); + ChaCha20Poly1305_DestroyContext(cx, PR_TRUE); + + PZ_Unlock(rng_lock); + /* --- UNLOCKED --- */ + + return SECSuccess; +} + +void +RNG_RNGShutdown(void) +{ + if (rng_lock) { + PZ_DestroyLock(rng_lock); + rng_lock = NULL; + } + coRNGInit = pristineCallOnce; +} + +/* Test functions are not implemented! */ +SECStatus +PRNGTEST_Instantiate(const PRUint8 *entropy, unsigned int entropy_len, + const PRUint8 *nonce, unsigned int nonce_len, + const PRUint8 *personal_string, unsigned int ps_len) +{ + return SECFailure; +} + +SECStatus +PRNGTEST_Reseed(const PRUint8 *entropy, unsigned int entropy_len, + const PRUint8 *additional, unsigned int additional_len) +{ + return SECFailure; +} + +SECStatus +PRNGTEST_Generate(PRUint8 *bytes, unsigned int bytes_len, + const PRUint8 *additional, unsigned int additional_len) +{ + return SECFailure; +} + +SECStatus +PRNGTEST_Uninstantiate() +{ + return SECFailure; +} + +SECStatus +PRNGTEST_RunHealthTests() +{ + return SECFailure; +} + +SECStatus +PRNGTEST_Instantiate_Kat(const PRUint8 *entropy, unsigned int entropy_len, + const PRUint8 *nonce, unsigned int nonce_len, + const PRUint8 *personal_string, unsigned int ps_len) +{ + return SECFailure; +} |