summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/freebl/det_rng.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/freebl/det_rng.c')
-rw-r--r--security/nss/lib/freebl/det_rng.c163
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;
+}