tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

det_rng.c (3992B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #include "blapi.h"
      6 #include "blapit.h"
      7 #include "Hacl_Chacha20.h"
      8 #include "nssilock.h"
      9 #include "seccomon.h"
     10 #include "secerr.h"
     11 #include "prinit.h"
     12 
     13 #define GLOBAL_BYTES_SIZE 100
     14 static PRUint8 globalBytes[GLOBAL_BYTES_SIZE];
     15 static unsigned long globalNumCalls = 0;
     16 static PZLock *rng_lock = NULL;
     17 static PRCallOnceType coRNGInit;
     18 static const PRCallOnceType pristineCallOnce;
     19 
     20 static PRStatus
     21 rng_init(void)
     22 {
     23    rng_lock = PZ_NewLock(nssILockOther);
     24    if (!rng_lock) {
     25        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
     26        return PR_FAILURE;
     27    }
     28    /* --- LOCKED --- */
     29    PZ_Lock(rng_lock);
     30    memset(globalBytes, 0, GLOBAL_BYTES_SIZE);
     31    PZ_Unlock(rng_lock);
     32    /* --- UNLOCKED --- */
     33 
     34    return PR_SUCCESS;
     35 }
     36 
     37 SECStatus
     38 RNG_RNGInit(void)
     39 {
     40    /* Allow only one call to initialize the context */
     41    if (PR_CallOnce(&coRNGInit, rng_init) != PR_SUCCESS) {
     42        return SECFailure;
     43    }
     44 
     45    return SECSuccess;
     46 }
     47 
     48 /* Take min(size, GLOBAL_BYTES_SIZE) bytes from data and use as seed and reset
     49 * the rng state. */
     50 SECStatus
     51 RNG_RandomUpdate(const void *data, size_t bytes)
     52 {
     53    /* Check for a valid RNG lock. */
     54    PORT_Assert(rng_lock != NULL);
     55    if (rng_lock == NULL) {
     56        PORT_SetError(SEC_ERROR_INVALID_ARGS);
     57        return SECFailure;
     58    }
     59 
     60    /* --- LOCKED --- */
     61    PZ_Lock(rng_lock);
     62    memset(globalBytes, 0, GLOBAL_BYTES_SIZE);
     63    globalNumCalls = 0;
     64    if (data) {
     65        memcpy(globalBytes, (PRUint8 *)data, PR_MIN(bytes, GLOBAL_BYTES_SIZE));
     66    }
     67    PZ_Unlock(rng_lock);
     68    /* --- UNLOCKED --- */
     69 
     70    return SECSuccess;
     71 }
     72 
     73 SECStatus
     74 RNG_GenerateGlobalRandomBytes(void *dest, size_t len)
     75 {
     76    static const uint8_t key[32] = { 0 };
     77    uint8_t nonce[12] = { 0 };
     78 
     79    /* Check for a valid RNG lock. */
     80    PORT_Assert(rng_lock != NULL);
     81    if (rng_lock == NULL) {
     82        PORT_SetError(SEC_ERROR_INVALID_ARGS);
     83        return SECFailure;
     84    }
     85 
     86    /* --- LOCKED --- */
     87    PZ_Lock(rng_lock);
     88 
     89    memcpy(nonce, &globalNumCalls, sizeof(globalNumCalls));
     90    globalNumCalls++;
     91 
     92    ChaCha20Poly1305Context *cx =
     93        ChaCha20Poly1305_CreateContext(key, sizeof(key), 16);
     94    if (!cx) {
     95        PORT_SetError(SEC_ERROR_NO_MEMORY);
     96        PZ_Unlock(rng_lock);
     97        return SECFailure;
     98    }
     99 
    100    memset(dest, 0, len);
    101    memcpy(dest, globalBytes, PR_MIN(len, GLOBAL_BYTES_SIZE));
    102    Hacl_Chacha20_chacha20_encrypt(len, (uint8_t *)dest, (uint8_t *)dest,
    103                                   (uint8_t *)key, nonce, 0);
    104    ChaCha20Poly1305_DestroyContext(cx, PR_TRUE);
    105 
    106    PZ_Unlock(rng_lock);
    107    /* --- UNLOCKED --- */
    108 
    109    return SECSuccess;
    110 }
    111 
    112 void
    113 RNG_RNGShutdown(void)
    114 {
    115    if (rng_lock) {
    116        PZ_DestroyLock(rng_lock);
    117        rng_lock = NULL;
    118    }
    119    coRNGInit = pristineCallOnce;
    120 }
    121 
    122 /* Test functions are not implemented! */
    123 SECStatus
    124 PRNGTEST_Instantiate(const PRUint8 *entropy, unsigned int entropy_len,
    125                     const PRUint8 *nonce, unsigned int nonce_len,
    126                     const PRUint8 *personal_string, unsigned int ps_len)
    127 {
    128    return SECFailure;
    129 }
    130 
    131 SECStatus
    132 PRNGTEST_Reseed(const PRUint8 *entropy, unsigned int entropy_len,
    133                const PRUint8 *additional, unsigned int additional_len)
    134 {
    135    return SECFailure;
    136 }
    137 
    138 SECStatus
    139 PRNGTEST_Generate(PRUint8 *bytes, unsigned int bytes_len,
    140                  const PRUint8 *additional, unsigned int additional_len)
    141 {
    142    return SECFailure;
    143 }
    144 
    145 SECStatus
    146 PRNGTEST_Uninstantiate()
    147 {
    148    return SECFailure;
    149 }
    150 
    151 SECStatus
    152 PRNGTEST_RunHealthTests()
    153 {
    154    return SECFailure;
    155 }
    156 
    157 SECStatus
    158 PRNGTEST_Instantiate_Kat(const PRUint8 *entropy, unsigned int entropy_len,
    159                         const PRUint8 *nonce, unsigned int nonce_len,
    160                         const PRUint8 *personal_string, unsigned int ps_len)
    161 {
    162    return SECFailure;
    163 }