/src/nss-nspr/nss/lib/freebl/det_rng.c
Line | Count | Source (jump to first uncovered line) |
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 | 2 | #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 | 2 | { |
23 | 2 | rng_lock = PZ_NewLock(nssILockOther); |
24 | 2 | if (!rng_lock) { |
25 | 0 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
26 | 0 | return PR_FAILURE; |
27 | 0 | } |
28 | | /* --- LOCKED --- */ |
29 | 2 | PZ_Lock(rng_lock); |
30 | 2 | memset(globalBytes, 0, GLOBAL_BYTES_SIZE); |
31 | 2 | PZ_Unlock(rng_lock); |
32 | | /* --- UNLOCKED --- */ |
33 | | |
34 | 2 | return PR_SUCCESS; |
35 | 2 | } |
36 | | |
37 | | SECStatus |
38 | | RNG_RNGInit(void) |
39 | 6 | { |
40 | | /* Allow only one call to initialize the context */ |
41 | 6 | if (PR_CallOnce(&coRNGInit, rng_init) != PR_SUCCESS) { |
42 | 0 | return SECFailure; |
43 | 0 | } |
44 | | |
45 | 6 | return SECSuccess; |
46 | 6 | } |
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 | 0 | { |
53 | | /* Check for a valid RNG lock. */ |
54 | 0 | PORT_Assert(rng_lock != NULL); |
55 | 0 | if (rng_lock == NULL) { |
56 | 0 | PORT_SetError(SEC_ERROR_INVALID_ARGS); |
57 | 0 | return SECFailure; |
58 | 0 | } |
59 | | |
60 | | /* --- LOCKED --- */ |
61 | 0 | PZ_Lock(rng_lock); |
62 | 0 | memset(globalBytes, 0, GLOBAL_BYTES_SIZE); |
63 | 0 | globalNumCalls = 0; |
64 | 0 | if (data) { |
65 | 0 | memcpy(globalBytes, (PRUint8 *)data, PR_MIN(bytes, GLOBAL_BYTES_SIZE)); |
66 | 0 | } |
67 | 0 | PZ_Unlock(rng_lock); |
68 | | /* --- UNLOCKED --- */ |
69 | |
|
70 | 0 | return SECSuccess; |
71 | 0 | } |
72 | | |
73 | | SECStatus |
74 | | RNG_GenerateGlobalRandomBytes(void *dest, size_t len) |
75 | 156 | { |
76 | 156 | static const uint8_t key[32] = { 0 }; |
77 | 156 | uint8_t nonce[12] = { 0 }; |
78 | | |
79 | | /* Check for a valid RNG lock. */ |
80 | 156 | PORT_Assert(rng_lock != NULL); |
81 | 156 | if (rng_lock == NULL) { |
82 | 0 | PORT_SetError(SEC_ERROR_INVALID_ARGS); |
83 | 0 | return SECFailure; |
84 | 0 | } |
85 | | |
86 | | /* --- LOCKED --- */ |
87 | 156 | PZ_Lock(rng_lock); |
88 | | |
89 | 156 | memcpy(nonce, &globalNumCalls, sizeof(globalNumCalls)); |
90 | 156 | globalNumCalls++; |
91 | | |
92 | 156 | ChaCha20Poly1305Context *cx = |
93 | 156 | ChaCha20Poly1305_CreateContext(key, sizeof(key), 16); |
94 | 156 | if (!cx) { |
95 | 0 | PORT_SetError(SEC_ERROR_NO_MEMORY); |
96 | 0 | PZ_Unlock(rng_lock); |
97 | 0 | return SECFailure; |
98 | 0 | } |
99 | | |
100 | 156 | memset(dest, 0, len); |
101 | 156 | memcpy(dest, globalBytes, PR_MIN(len, GLOBAL_BYTES_SIZE)); |
102 | 156 | Hacl_Chacha20_chacha20_encrypt(len, (uint8_t *)dest, (uint8_t *)dest, |
103 | 156 | (uint8_t *)key, nonce, 0); |
104 | 156 | ChaCha20Poly1305_DestroyContext(cx, PR_TRUE); |
105 | | |
106 | 156 | PZ_Unlock(rng_lock); |
107 | | /* --- UNLOCKED --- */ |
108 | | |
109 | 156 | return SECSuccess; |
110 | 156 | } |
111 | | |
112 | | void |
113 | | RNG_RNGShutdown(void) |
114 | 0 | { |
115 | 0 | if (rng_lock) { |
116 | 0 | PZ_DestroyLock(rng_lock); |
117 | 0 | rng_lock = NULL; |
118 | 0 | } |
119 | 0 | coRNGInit = pristineCallOnce; |
120 | 0 | } |
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 | 0 | { |
128 | 0 | return SECFailure; |
129 | 0 | } |
130 | | |
131 | | SECStatus |
132 | | PRNGTEST_Reseed(const PRUint8 *entropy, unsigned int entropy_len, |
133 | | const PRUint8 *additional, unsigned int additional_len) |
134 | 0 | { |
135 | 0 | return SECFailure; |
136 | 0 | } |
137 | | |
138 | | SECStatus |
139 | | PRNGTEST_Generate(PRUint8 *bytes, unsigned int bytes_len, |
140 | | const PRUint8 *additional, unsigned int additional_len) |
141 | 0 | { |
142 | 0 | return SECFailure; |
143 | 0 | } |
144 | | |
145 | | SECStatus |
146 | | PRNGTEST_Uninstantiate() |
147 | 0 | { |
148 | 0 | return SECFailure; |
149 | 0 | } |
150 | | |
151 | | SECStatus |
152 | | PRNGTEST_RunHealthTests() |
153 | 2 | { |
154 | 2 | return SECFailure; |
155 | 2 | } |
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 | 0 | { |
162 | 0 | return SECFailure; |
163 | 0 | } |