1*9d12795fSRobert Mustacchi /* 2*9d12795fSRobert Mustacchi * Copyright (c) 1996, David Mazieres <dm@uun.org> 3*9d12795fSRobert Mustacchi * Copyright (c) 2008, Damien Miller <djm@openbsd.org> 4*9d12795fSRobert Mustacchi * Copyright (c) 2013, Markus Friedl <markus@openbsd.org> 5*9d12795fSRobert Mustacchi * Copyright (c) 2015 Joyent, Inc. 6*9d12795fSRobert Mustacchi * 7*9d12795fSRobert Mustacchi * Permission to use, copy, modify, and distribute this software for any 8*9d12795fSRobert Mustacchi * purpose with or without fee is hereby granted, provided that the above 9*9d12795fSRobert Mustacchi * copyright notice and this permission notice appear in all copies. 10*9d12795fSRobert Mustacchi * 11*9d12795fSRobert Mustacchi * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12*9d12795fSRobert Mustacchi * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13*9d12795fSRobert Mustacchi * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14*9d12795fSRobert Mustacchi * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15*9d12795fSRobert Mustacchi * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16*9d12795fSRobert Mustacchi * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17*9d12795fSRobert Mustacchi * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18*9d12795fSRobert Mustacchi */ 19*9d12795fSRobert Mustacchi 20*9d12795fSRobert Mustacchi /* 21*9d12795fSRobert Mustacchi * arc4random(3C), derived from the OpenBSD version. 22*9d12795fSRobert Mustacchi * 23*9d12795fSRobert Mustacchi * To ensure that a parent process and any potential children see a different 24*9d12795fSRobert Mustacchi * state, we mmap the entire arc4_state_t structure and mark that page as 25*9d12795fSRobert Mustacchi * MC_INHERIT_ZERO. That ensures that the data is zeroed, and really the bit we 26*9d12795fSRobert Mustacchi * care about, arc4_init is set to B_FALSE, which will cause the child to 27*9d12795fSRobert Mustacchi * reinitialize it when they first use the interface. 28*9d12795fSRobert Mustacchi */ 29*9d12795fSRobert Mustacchi 30*9d12795fSRobert Mustacchi #include <synch.h> 31*9d12795fSRobert Mustacchi #include <stdlib.h> 32*9d12795fSRobert Mustacchi #include <string.h> 33*9d12795fSRobert Mustacchi #include <unistd.h> 34*9d12795fSRobert Mustacchi #include <sys/sysmacros.h> 35*9d12795fSRobert Mustacchi #include <chacha.h> 36*9d12795fSRobert Mustacchi 37*9d12795fSRobert Mustacchi #include "thr_uberdata.h" 38*9d12795fSRobert Mustacchi 39*9d12795fSRobert Mustacchi #define ARC4_KEYSZ 32 40*9d12795fSRobert Mustacchi #define ARC4_IVSZ 8 41*9d12795fSRobert Mustacchi #define ARC4_BLOCKSZ 64 42*9d12795fSRobert Mustacchi #define ARC4_KSBUFSZ (16*ARC4_BLOCKSZ) /* key stream byte size */ 43*9d12795fSRobert Mustacchi #define ARC4_COUNT 1600000 /* bytes for rekeying */ 44*9d12795fSRobert Mustacchi 45*9d12795fSRobert Mustacchi typedef struct arc4_state { 46*9d12795fSRobert Mustacchi boolean_t arc4_init; /* Initialized? */ 47*9d12795fSRobert Mustacchi size_t arc4_have; /* Valid bytes in arc4_buf */ 48*9d12795fSRobert Mustacchi size_t arc4_count; /* bytes until reseed */ 49*9d12795fSRobert Mustacchi chacha_ctx_t arc4_chacha; /* chacha context */ 50*9d12795fSRobert Mustacchi uint8_t arc4_buf[ARC4_KSBUFSZ]; /* keystream blocks */ 51*9d12795fSRobert Mustacchi } arc4_state_t; 52*9d12795fSRobert Mustacchi 53*9d12795fSRobert Mustacchi static arc4_state_t *arc4; 54*9d12795fSRobert Mustacchi static mutex_t arc4_lock = DEFAULTMUTEX; 55*9d12795fSRobert Mustacchi 56*9d12795fSRobert Mustacchi static void 57*9d12795fSRobert Mustacchi arc4_init(uint8_t *buf, size_t n) 58*9d12795fSRobert Mustacchi { 59*9d12795fSRobert Mustacchi if (n < ARC4_KEYSZ + ARC4_IVSZ) 60*9d12795fSRobert Mustacchi abort(); 61*9d12795fSRobert Mustacchi 62*9d12795fSRobert Mustacchi chacha_keysetup(&arc4->arc4_chacha, buf, ARC4_KEYSZ * 8, 0); 63*9d12795fSRobert Mustacchi chacha_ivsetup(&arc4->arc4_chacha, buf + ARC4_KEYSZ); 64*9d12795fSRobert Mustacchi } 65*9d12795fSRobert Mustacchi 66*9d12795fSRobert Mustacchi static void 67*9d12795fSRobert Mustacchi arc4_rekey(uint8_t *data, size_t datalen) 68*9d12795fSRobert Mustacchi { 69*9d12795fSRobert Mustacchi /* Fill in the keystream buffer */ 70*9d12795fSRobert Mustacchi chacha_encrypt_bytes(&arc4->arc4_chacha, arc4->arc4_buf, arc4->arc4_buf, 71*9d12795fSRobert Mustacchi sizeof (arc4->arc4_buf)); 72*9d12795fSRobert Mustacchi 73*9d12795fSRobert Mustacchi /* mix in optional user provided data */ 74*9d12795fSRobert Mustacchi if (data != NULL) { 75*9d12795fSRobert Mustacchi size_t i, m; 76*9d12795fSRobert Mustacchi 77*9d12795fSRobert Mustacchi m = MIN(datalen, ARC4_KEYSZ + ARC4_IVSZ); 78*9d12795fSRobert Mustacchi for (i = 0; i < m; i++) 79*9d12795fSRobert Mustacchi arc4->arc4_buf[i] ^= data[i]; 80*9d12795fSRobert Mustacchi } 81*9d12795fSRobert Mustacchi 82*9d12795fSRobert Mustacchi /* immediately reinit for backtracking resistence */ 83*9d12795fSRobert Mustacchi arc4_init(arc4->arc4_buf, ARC4_KEYSZ + ARC4_IVSZ); 84*9d12795fSRobert Mustacchi explicit_bzero(arc4->arc4_buf, ARC4_KEYSZ + ARC4_IVSZ); 85*9d12795fSRobert Mustacchi arc4->arc4_have = sizeof (arc4->arc4_buf) - ARC4_KEYSZ - ARC4_IVSZ; 86*9d12795fSRobert Mustacchi } 87*9d12795fSRobert Mustacchi 88*9d12795fSRobert Mustacchi static void 89*9d12795fSRobert Mustacchi arc4_stir(size_t len) 90*9d12795fSRobert Mustacchi { 91*9d12795fSRobert Mustacchi uint8_t rnd[ARC4_KEYSZ + ARC4_IVSZ]; 92*9d12795fSRobert Mustacchi 93*9d12795fSRobert Mustacchi if (arc4->arc4_count <= len) { 94*9d12795fSRobert Mustacchi if (getentropy(rnd, sizeof (rnd)) == -1) 95*9d12795fSRobert Mustacchi abort(); 96*9d12795fSRobert Mustacchi 97*9d12795fSRobert Mustacchi if (arc4->arc4_init == B_FALSE) { 98*9d12795fSRobert Mustacchi arc4_init(rnd, sizeof (rnd)); 99*9d12795fSRobert Mustacchi arc4->arc4_init = B_TRUE; 100*9d12795fSRobert Mustacchi } else { 101*9d12795fSRobert Mustacchi arc4_rekey(rnd, sizeof (rnd)); 102*9d12795fSRobert Mustacchi } 103*9d12795fSRobert Mustacchi explicit_bzero(rnd, sizeof (rnd)); 104*9d12795fSRobert Mustacchi 105*9d12795fSRobert Mustacchi /* Invalidate the data buffer */ 106*9d12795fSRobert Mustacchi arc4->arc4_have = 0; 107*9d12795fSRobert Mustacchi memset(arc4->arc4_buf, 0, sizeof (arc4->arc4_buf)); 108*9d12795fSRobert Mustacchi arc4->arc4_count = ARC4_COUNT; 109*9d12795fSRobert Mustacchi } 110*9d12795fSRobert Mustacchi 111*9d12795fSRobert Mustacchi if (arc4->arc4_count <= len) { 112*9d12795fSRobert Mustacchi arc4->arc4_count = 0; 113*9d12795fSRobert Mustacchi } else { 114*9d12795fSRobert Mustacchi arc4->arc4_count -= len; 115*9d12795fSRobert Mustacchi } 116*9d12795fSRobert Mustacchi } 117*9d12795fSRobert Mustacchi 118*9d12795fSRobert Mustacchi static void 119*9d12795fSRobert Mustacchi arc4_fill(uint8_t *buf, size_t n) 120*9d12795fSRobert Mustacchi { 121*9d12795fSRobert Mustacchi if (arc4 == NULL) { 122*9d12795fSRobert Mustacchi size_t pgsz, mapsz; 123*9d12795fSRobert Mustacchi void *a; 124*9d12795fSRobert Mustacchi 125*9d12795fSRobert Mustacchi pgsz = sysconf(_SC_PAGESIZE); 126*9d12795fSRobert Mustacchi if (pgsz == -1) 127*9d12795fSRobert Mustacchi abort(); 128*9d12795fSRobert Mustacchi mapsz = P2ROUNDUP(sizeof (arc4_state_t), pgsz); 129*9d12795fSRobert Mustacchi a = mmap(NULL, mapsz, PROT_READ | PROT_WRITE, 130*9d12795fSRobert Mustacchi MAP_PRIVATE | MAP_ANON, -1, 0); 131*9d12795fSRobert Mustacchi if (a == MAP_FAILED) 132*9d12795fSRobert Mustacchi abort(); 133*9d12795fSRobert Mustacchi if (memcntl(a, mapsz, MC_INHERIT_ZERO, 0, 0, 0) != 0) 134*9d12795fSRobert Mustacchi abort(); 135*9d12795fSRobert Mustacchi arc4 = a; 136*9d12795fSRobert Mustacchi } 137*9d12795fSRobert Mustacchi 138*9d12795fSRobert Mustacchi arc4_stir(n); 139*9d12795fSRobert Mustacchi while (n > 0) { 140*9d12795fSRobert Mustacchi if (arc4->arc4_have > 0) { 141*9d12795fSRobert Mustacchi uint8_t *keystream; 142*9d12795fSRobert Mustacchi size_t m = MIN(n, arc4->arc4_have); 143*9d12795fSRobert Mustacchi 144*9d12795fSRobert Mustacchi keystream = arc4->arc4_buf + sizeof (arc4->arc4_buf) - 145*9d12795fSRobert Mustacchi arc4->arc4_have; 146*9d12795fSRobert Mustacchi memcpy(buf, keystream, m); 147*9d12795fSRobert Mustacchi explicit_bzero(keystream, m); 148*9d12795fSRobert Mustacchi buf += m; 149*9d12795fSRobert Mustacchi n -= m; 150*9d12795fSRobert Mustacchi arc4->arc4_have -= m; 151*9d12795fSRobert Mustacchi } 152*9d12795fSRobert Mustacchi if (arc4->arc4_have == 0) 153*9d12795fSRobert Mustacchi arc4_rekey(NULL, 0); 154*9d12795fSRobert Mustacchi } 155*9d12795fSRobert Mustacchi } 156*9d12795fSRobert Mustacchi 157*9d12795fSRobert Mustacchi uint32_t 158*9d12795fSRobert Mustacchi arc4random(void) 159*9d12795fSRobert Mustacchi { 160*9d12795fSRobert Mustacchi uint32_t out; 161*9d12795fSRobert Mustacchi 162*9d12795fSRobert Mustacchi lmutex_lock(&arc4_lock); 163*9d12795fSRobert Mustacchi arc4_fill((uint8_t *)&out, sizeof (uint32_t)); 164*9d12795fSRobert Mustacchi lmutex_unlock(&arc4_lock); 165*9d12795fSRobert Mustacchi return (out); 166*9d12795fSRobert Mustacchi } 167*9d12795fSRobert Mustacchi 168*9d12795fSRobert Mustacchi void 169*9d12795fSRobert Mustacchi arc4random_buf(void *buf, size_t n) 170*9d12795fSRobert Mustacchi { 171*9d12795fSRobert Mustacchi lmutex_lock(&arc4_lock); 172*9d12795fSRobert Mustacchi arc4_fill(buf, n); 173*9d12795fSRobert Mustacchi lmutex_unlock(&arc4_lock); 174*9d12795fSRobert Mustacchi } 175