* MPSAFE */
| 186 | * MPSAFE |
| 187 | */ |
| 188 | void |
| 189 | arc4rand(void *ptr, u_int len, int reseed) |
| 190 | { |
| 191 | struct chacha20_s *chacha20; |
| 192 | struct timeval tv; |
| 193 | u_int length; |
| 194 | u_int8_t *p; |
| 195 | |
| 196 | #ifdef RANDOM_FENESTRASX |
| 197 | if (__predict_false(reseed)) |
| 198 | #else |
| 199 | if (__predict_false(reseed || |
| 200 | (arc4rand_iniseed_state == ARC4_ENTR_HAVE && |
| 201 | atomic_cmpset_int(&arc4rand_iniseed_state, ARC4_ENTR_HAVE, ARC4_ENTR_SEED)))) |
| 202 | #endif |
| 203 | CHACHA20_FOREACH(chacha20) |
| 204 | chacha20_randomstir(chacha20); |
| 205 | |
| 206 | getmicrouptime(&tv); |
| 207 | chacha20 = &chacha20inst[curcpu]; |
| 208 | /* We may get unlucky and be migrated off this CPU, but that is expected to be infrequent */ |
| 209 | if ((chacha20->numbytes > CHACHA20_RESEED_BYTES) || (tv.tv_sec > chacha20->t_reseed)) |
| 210 | chacha20_randomstir(chacha20); |
| 211 | |
| 212 | mtx_lock(&chacha20->mtx); |
| 213 | #ifdef RANDOM_FENESTRASX |
| 214 | if (__predict_false( |
| 215 | atomic_load_acq_64(&fxrng_root_generation) != chacha20->seed_version |
| 216 | )) { |
| 217 | mtx_unlock(&chacha20->mtx); |
| 218 | chacha20_randomstir(chacha20); |
| 219 | mtx_lock(&chacha20->mtx); |
| 220 | } |
| 221 | #endif |
| 222 | |
| 223 | p = ptr; |
| 224 | while (len) { |
| 225 | length = MIN(CHACHA20_BUFFER_SIZE, len); |
| 226 | chacha_encrypt_bytes(&chacha20->ctx, chacha20->m_buffer, p, length); |
| 227 | p += length; |
| 228 | len -= length; |
| 229 | chacha20->numbytes += length; |
| 230 | if (chacha20->numbytes > CHACHA20_RESEED_BYTES) { |
| 231 | mtx_unlock(&chacha20->mtx); |
| 232 | chacha20_randomstir(chacha20); |
| 233 | mtx_lock(&chacha20->mtx); |
| 234 | } |
| 235 | } |
| 236 | mtx_unlock(&chacha20->mtx); |
| 237 | } |
| 238 | |
| 239 | uint32_t |
| 240 | arc4random(void) |
no test coverage detected