1*f7167e0eSDag-Erling Smørgrav /* OPENBSD ORIGINAL: lib/libc/crypto/arc4random.c */ 2*f7167e0eSDag-Erling Smørgrav 3*f7167e0eSDag-Erling Smørgrav /* $OpenBSD: arc4random.c,v 1.25 2013/10/01 18:34:57 markus Exp $ */ 4*f7167e0eSDag-Erling Smørgrav 5*f7167e0eSDag-Erling Smørgrav /* 6*f7167e0eSDag-Erling Smørgrav * Copyright (c) 1996, David Mazieres <dm@uun.org> 7*f7167e0eSDag-Erling Smørgrav * Copyright (c) 2008, Damien Miller <djm@openbsd.org> 8*f7167e0eSDag-Erling Smørgrav * Copyright (c) 2013, Markus Friedl <markus@openbsd.org> 9*f7167e0eSDag-Erling Smørgrav * 10*f7167e0eSDag-Erling Smørgrav * Permission to use, copy, modify, and distribute this software for any 11*f7167e0eSDag-Erling Smørgrav * purpose with or without fee is hereby granted, provided that the above 12*f7167e0eSDag-Erling Smørgrav * copyright notice and this permission notice appear in all copies. 13*f7167e0eSDag-Erling Smørgrav * 14*f7167e0eSDag-Erling Smørgrav * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 15*f7167e0eSDag-Erling Smørgrav * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 16*f7167e0eSDag-Erling Smørgrav * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 17*f7167e0eSDag-Erling Smørgrav * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 18*f7167e0eSDag-Erling Smørgrav * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 19*f7167e0eSDag-Erling Smørgrav * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 20*f7167e0eSDag-Erling Smørgrav * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 21*f7167e0eSDag-Erling Smørgrav */ 22*f7167e0eSDag-Erling Smørgrav 23*f7167e0eSDag-Erling Smørgrav /* 24*f7167e0eSDag-Erling Smørgrav * ChaCha based random number generator for OpenBSD. 25*f7167e0eSDag-Erling Smørgrav */ 26*f7167e0eSDag-Erling Smørgrav 27*f7167e0eSDag-Erling Smørgrav #include "includes.h" 28*f7167e0eSDag-Erling Smørgrav 29*f7167e0eSDag-Erling Smørgrav #include <stdlib.h> 30*f7167e0eSDag-Erling Smørgrav #include <string.h> 31*f7167e0eSDag-Erling Smørgrav #include <unistd.h> 32*f7167e0eSDag-Erling Smørgrav #include <sys/types.h> 33*f7167e0eSDag-Erling Smørgrav 34*f7167e0eSDag-Erling Smørgrav #ifndef HAVE_ARC4RANDOM 35*f7167e0eSDag-Erling Smørgrav 36*f7167e0eSDag-Erling Smørgrav #include <openssl/rand.h> 37*f7167e0eSDag-Erling Smørgrav #include <openssl/err.h> 38*f7167e0eSDag-Erling Smørgrav 39*f7167e0eSDag-Erling Smørgrav #include "log.h" 40*f7167e0eSDag-Erling Smørgrav 41*f7167e0eSDag-Erling Smørgrav #define KEYSTREAM_ONLY 42*f7167e0eSDag-Erling Smørgrav #include "chacha_private.h" 43*f7167e0eSDag-Erling Smørgrav 44*f7167e0eSDag-Erling Smørgrav #ifdef __GNUC__ 45*f7167e0eSDag-Erling Smørgrav #define inline __inline 46*f7167e0eSDag-Erling Smørgrav #else /* !__GNUC__ */ 47*f7167e0eSDag-Erling Smørgrav #define inline 48*f7167e0eSDag-Erling Smørgrav #endif /* !__GNUC__ */ 49*f7167e0eSDag-Erling Smørgrav 50*f7167e0eSDag-Erling Smørgrav /* OpenSSH isn't multithreaded */ 51*f7167e0eSDag-Erling Smørgrav #define _ARC4_LOCK() 52*f7167e0eSDag-Erling Smørgrav #define _ARC4_UNLOCK() 53*f7167e0eSDag-Erling Smørgrav 54*f7167e0eSDag-Erling Smørgrav #define KEYSZ 32 55*f7167e0eSDag-Erling Smørgrav #define IVSZ 8 56*f7167e0eSDag-Erling Smørgrav #define BLOCKSZ 64 57*f7167e0eSDag-Erling Smørgrav #define RSBUFSZ (16*BLOCKSZ) 58*f7167e0eSDag-Erling Smørgrav static int rs_initialized; 59*f7167e0eSDag-Erling Smørgrav static pid_t rs_stir_pid; 60*f7167e0eSDag-Erling Smørgrav static chacha_ctx rs; /* chacha context for random keystream */ 61*f7167e0eSDag-Erling Smørgrav static u_char rs_buf[RSBUFSZ]; /* keystream blocks */ 62*f7167e0eSDag-Erling Smørgrav static size_t rs_have; /* valid bytes at end of rs_buf */ 63*f7167e0eSDag-Erling Smørgrav static size_t rs_count; /* bytes till reseed */ 64*f7167e0eSDag-Erling Smørgrav 65*f7167e0eSDag-Erling Smørgrav static inline void _rs_rekey(u_char *dat, size_t datlen); 66*f7167e0eSDag-Erling Smørgrav 67*f7167e0eSDag-Erling Smørgrav static inline void 68*f7167e0eSDag-Erling Smørgrav _rs_init(u_char *buf, size_t n) 69*f7167e0eSDag-Erling Smørgrav { 70*f7167e0eSDag-Erling Smørgrav if (n < KEYSZ + IVSZ) 71*f7167e0eSDag-Erling Smørgrav return; 72*f7167e0eSDag-Erling Smørgrav chacha_keysetup(&rs, buf, KEYSZ * 8, 0); 73*f7167e0eSDag-Erling Smørgrav chacha_ivsetup(&rs, buf + KEYSZ); 74*f7167e0eSDag-Erling Smørgrav } 75*f7167e0eSDag-Erling Smørgrav 76*f7167e0eSDag-Erling Smørgrav static void 77*f7167e0eSDag-Erling Smørgrav _rs_stir(void) 78*f7167e0eSDag-Erling Smørgrav { 79*f7167e0eSDag-Erling Smørgrav u_char rnd[KEYSZ + IVSZ]; 80*f7167e0eSDag-Erling Smørgrav 81*f7167e0eSDag-Erling Smørgrav if (RAND_bytes(rnd, sizeof(rnd)) <= 0) 82*f7167e0eSDag-Erling Smørgrav fatal("Couldn't obtain random bytes (error %ld)", 83*f7167e0eSDag-Erling Smørgrav ERR_get_error()); 84*f7167e0eSDag-Erling Smørgrav 85*f7167e0eSDag-Erling Smørgrav if (!rs_initialized) { 86*f7167e0eSDag-Erling Smørgrav rs_initialized = 1; 87*f7167e0eSDag-Erling Smørgrav _rs_init(rnd, sizeof(rnd)); 88*f7167e0eSDag-Erling Smørgrav } else 89*f7167e0eSDag-Erling Smørgrav _rs_rekey(rnd, sizeof(rnd)); 90*f7167e0eSDag-Erling Smørgrav memset(rnd, 0, sizeof(rnd)); 91*f7167e0eSDag-Erling Smørgrav 92*f7167e0eSDag-Erling Smørgrav /* invalidate rs_buf */ 93*f7167e0eSDag-Erling Smørgrav rs_have = 0; 94*f7167e0eSDag-Erling Smørgrav memset(rs_buf, 0, RSBUFSZ); 95*f7167e0eSDag-Erling Smørgrav 96*f7167e0eSDag-Erling Smørgrav rs_count = 1600000; 97*f7167e0eSDag-Erling Smørgrav } 98*f7167e0eSDag-Erling Smørgrav 99*f7167e0eSDag-Erling Smørgrav static inline void 100*f7167e0eSDag-Erling Smørgrav _rs_stir_if_needed(size_t len) 101*f7167e0eSDag-Erling Smørgrav { 102*f7167e0eSDag-Erling Smørgrav pid_t pid = getpid(); 103*f7167e0eSDag-Erling Smørgrav 104*f7167e0eSDag-Erling Smørgrav if (rs_count <= len || !rs_initialized || rs_stir_pid != pid) { 105*f7167e0eSDag-Erling Smørgrav rs_stir_pid = pid; 106*f7167e0eSDag-Erling Smørgrav _rs_stir(); 107*f7167e0eSDag-Erling Smørgrav } else 108*f7167e0eSDag-Erling Smørgrav rs_count -= len; 109*f7167e0eSDag-Erling Smørgrav } 110*f7167e0eSDag-Erling Smørgrav 111*f7167e0eSDag-Erling Smørgrav static inline void 112*f7167e0eSDag-Erling Smørgrav _rs_rekey(u_char *dat, size_t datlen) 113*f7167e0eSDag-Erling Smørgrav { 114*f7167e0eSDag-Erling Smørgrav #ifndef KEYSTREAM_ONLY 115*f7167e0eSDag-Erling Smørgrav memset(rs_buf, 0,RSBUFSZ); 116*f7167e0eSDag-Erling Smørgrav #endif 117*f7167e0eSDag-Erling Smørgrav /* fill rs_buf with the keystream */ 118*f7167e0eSDag-Erling Smørgrav chacha_encrypt_bytes(&rs, rs_buf, rs_buf, RSBUFSZ); 119*f7167e0eSDag-Erling Smørgrav /* mix in optional user provided data */ 120*f7167e0eSDag-Erling Smørgrav if (dat) { 121*f7167e0eSDag-Erling Smørgrav size_t i, m; 122*f7167e0eSDag-Erling Smørgrav 123*f7167e0eSDag-Erling Smørgrav m = MIN(datlen, KEYSZ + IVSZ); 124*f7167e0eSDag-Erling Smørgrav for (i = 0; i < m; i++) 125*f7167e0eSDag-Erling Smørgrav rs_buf[i] ^= dat[i]; 126*f7167e0eSDag-Erling Smørgrav } 127*f7167e0eSDag-Erling Smørgrav /* immediately reinit for backtracking resistance */ 128*f7167e0eSDag-Erling Smørgrav _rs_init(rs_buf, KEYSZ + IVSZ); 129*f7167e0eSDag-Erling Smørgrav memset(rs_buf, 0, KEYSZ + IVSZ); 130*f7167e0eSDag-Erling Smørgrav rs_have = RSBUFSZ - KEYSZ - IVSZ; 131*f7167e0eSDag-Erling Smørgrav } 132*f7167e0eSDag-Erling Smørgrav 133*f7167e0eSDag-Erling Smørgrav static inline void 134*f7167e0eSDag-Erling Smørgrav _rs_random_buf(void *_buf, size_t n) 135*f7167e0eSDag-Erling Smørgrav { 136*f7167e0eSDag-Erling Smørgrav u_char *buf = (u_char *)_buf; 137*f7167e0eSDag-Erling Smørgrav size_t m; 138*f7167e0eSDag-Erling Smørgrav 139*f7167e0eSDag-Erling Smørgrav _rs_stir_if_needed(n); 140*f7167e0eSDag-Erling Smørgrav while (n > 0) { 141*f7167e0eSDag-Erling Smørgrav if (rs_have > 0) { 142*f7167e0eSDag-Erling Smørgrav m = MIN(n, rs_have); 143*f7167e0eSDag-Erling Smørgrav memcpy(buf, rs_buf + RSBUFSZ - rs_have, m); 144*f7167e0eSDag-Erling Smørgrav memset(rs_buf + RSBUFSZ - rs_have, 0, m); 145*f7167e0eSDag-Erling Smørgrav buf += m; 146*f7167e0eSDag-Erling Smørgrav n -= m; 147*f7167e0eSDag-Erling Smørgrav rs_have -= m; 148*f7167e0eSDag-Erling Smørgrav } 149*f7167e0eSDag-Erling Smørgrav if (rs_have == 0) 150*f7167e0eSDag-Erling Smørgrav _rs_rekey(NULL, 0); 151*f7167e0eSDag-Erling Smørgrav } 152*f7167e0eSDag-Erling Smørgrav } 153*f7167e0eSDag-Erling Smørgrav 154*f7167e0eSDag-Erling Smørgrav static inline void 155*f7167e0eSDag-Erling Smørgrav _rs_random_u32(u_int32_t *val) 156*f7167e0eSDag-Erling Smørgrav { 157*f7167e0eSDag-Erling Smørgrav _rs_stir_if_needed(sizeof(*val)); 158*f7167e0eSDag-Erling Smørgrav if (rs_have < sizeof(*val)) 159*f7167e0eSDag-Erling Smørgrav _rs_rekey(NULL, 0); 160*f7167e0eSDag-Erling Smørgrav memcpy(val, rs_buf + RSBUFSZ - rs_have, sizeof(*val)); 161*f7167e0eSDag-Erling Smørgrav memset(rs_buf + RSBUFSZ - rs_have, 0, sizeof(*val)); 162*f7167e0eSDag-Erling Smørgrav rs_have -= sizeof(*val); 163*f7167e0eSDag-Erling Smørgrav return; 164*f7167e0eSDag-Erling Smørgrav } 165*f7167e0eSDag-Erling Smørgrav 166*f7167e0eSDag-Erling Smørgrav void 167*f7167e0eSDag-Erling Smørgrav arc4random_stir(void) 168*f7167e0eSDag-Erling Smørgrav { 169*f7167e0eSDag-Erling Smørgrav _ARC4_LOCK(); 170*f7167e0eSDag-Erling Smørgrav _rs_stir(); 171*f7167e0eSDag-Erling Smørgrav _ARC4_UNLOCK(); 172*f7167e0eSDag-Erling Smørgrav } 173*f7167e0eSDag-Erling Smørgrav 174*f7167e0eSDag-Erling Smørgrav void 175*f7167e0eSDag-Erling Smørgrav arc4random_addrandom(u_char *dat, int datlen) 176*f7167e0eSDag-Erling Smørgrav { 177*f7167e0eSDag-Erling Smørgrav int m; 178*f7167e0eSDag-Erling Smørgrav 179*f7167e0eSDag-Erling Smørgrav _ARC4_LOCK(); 180*f7167e0eSDag-Erling Smørgrav if (!rs_initialized) 181*f7167e0eSDag-Erling Smørgrav _rs_stir(); 182*f7167e0eSDag-Erling Smørgrav while (datlen > 0) { 183*f7167e0eSDag-Erling Smørgrav m = MIN(datlen, KEYSZ + IVSZ); 184*f7167e0eSDag-Erling Smørgrav _rs_rekey(dat, m); 185*f7167e0eSDag-Erling Smørgrav dat += m; 186*f7167e0eSDag-Erling Smørgrav datlen -= m; 187*f7167e0eSDag-Erling Smørgrav } 188*f7167e0eSDag-Erling Smørgrav _ARC4_UNLOCK(); 189*f7167e0eSDag-Erling Smørgrav } 190*f7167e0eSDag-Erling Smørgrav 191*f7167e0eSDag-Erling Smørgrav u_int32_t 192*f7167e0eSDag-Erling Smørgrav arc4random(void) 193*f7167e0eSDag-Erling Smørgrav { 194*f7167e0eSDag-Erling Smørgrav u_int32_t val; 195*f7167e0eSDag-Erling Smørgrav 196*f7167e0eSDag-Erling Smørgrav _ARC4_LOCK(); 197*f7167e0eSDag-Erling Smørgrav _rs_random_u32(&val); 198*f7167e0eSDag-Erling Smørgrav _ARC4_UNLOCK(); 199*f7167e0eSDag-Erling Smørgrav return val; 200*f7167e0eSDag-Erling Smørgrav } 201*f7167e0eSDag-Erling Smørgrav 202*f7167e0eSDag-Erling Smørgrav /* 203*f7167e0eSDag-Erling Smørgrav * If we are providing arc4random, then we can provide a more efficient 204*f7167e0eSDag-Erling Smørgrav * arc4random_buf(). 205*f7167e0eSDag-Erling Smørgrav */ 206*f7167e0eSDag-Erling Smørgrav # ifndef HAVE_ARC4RANDOM_BUF 207*f7167e0eSDag-Erling Smørgrav void 208*f7167e0eSDag-Erling Smørgrav arc4random_buf(void *buf, size_t n) 209*f7167e0eSDag-Erling Smørgrav { 210*f7167e0eSDag-Erling Smørgrav _ARC4_LOCK(); 211*f7167e0eSDag-Erling Smørgrav _rs_random_buf(buf, n); 212*f7167e0eSDag-Erling Smørgrav _ARC4_UNLOCK(); 213*f7167e0eSDag-Erling Smørgrav } 214*f7167e0eSDag-Erling Smørgrav # endif /* !HAVE_ARC4RANDOM_BUF */ 215*f7167e0eSDag-Erling Smørgrav #endif /* !HAVE_ARC4RANDOM */ 216*f7167e0eSDag-Erling Smørgrav 217*f7167e0eSDag-Erling Smørgrav /* arc4random_buf() that uses platform arc4random() */ 218*f7167e0eSDag-Erling Smørgrav #if !defined(HAVE_ARC4RANDOM_BUF) && defined(HAVE_ARC4RANDOM) 219*f7167e0eSDag-Erling Smørgrav void 220*f7167e0eSDag-Erling Smørgrav arc4random_buf(void *_buf, size_t n) 221*f7167e0eSDag-Erling Smørgrav { 222*f7167e0eSDag-Erling Smørgrav size_t i; 223*f7167e0eSDag-Erling Smørgrav u_int32_t r = 0; 224*f7167e0eSDag-Erling Smørgrav char *buf = (char *)_buf; 225*f7167e0eSDag-Erling Smørgrav 226*f7167e0eSDag-Erling Smørgrav for (i = 0; i < n; i++) { 227*f7167e0eSDag-Erling Smørgrav if (i % 4 == 0) 228*f7167e0eSDag-Erling Smørgrav r = arc4random(); 229*f7167e0eSDag-Erling Smørgrav buf[i] = r & 0xff; 230*f7167e0eSDag-Erling Smørgrav r >>= 8; 231*f7167e0eSDag-Erling Smørgrav } 232*f7167e0eSDag-Erling Smørgrav i = r = 0; 233*f7167e0eSDag-Erling Smørgrav } 234*f7167e0eSDag-Erling Smørgrav #endif /* !defined(HAVE_ARC4RANDOM_BUF) && defined(HAVE_ARC4RANDOM) */ 235*f7167e0eSDag-Erling Smørgrav 236*f7167e0eSDag-Erling Smørgrav #ifndef HAVE_ARC4RANDOM_UNIFORM 237*f7167e0eSDag-Erling Smørgrav /* 238*f7167e0eSDag-Erling Smørgrav * Calculate a uniformly distributed random number less than upper_bound 239*f7167e0eSDag-Erling Smørgrav * avoiding "modulo bias". 240*f7167e0eSDag-Erling Smørgrav * 241*f7167e0eSDag-Erling Smørgrav * Uniformity is achieved by generating new random numbers until the one 242*f7167e0eSDag-Erling Smørgrav * returned is outside the range [0, 2**32 % upper_bound). This 243*f7167e0eSDag-Erling Smørgrav * guarantees the selected random number will be inside 244*f7167e0eSDag-Erling Smørgrav * [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound) 245*f7167e0eSDag-Erling Smørgrav * after reduction modulo upper_bound. 246*f7167e0eSDag-Erling Smørgrav */ 247*f7167e0eSDag-Erling Smørgrav u_int32_t 248*f7167e0eSDag-Erling Smørgrav arc4random_uniform(u_int32_t upper_bound) 249*f7167e0eSDag-Erling Smørgrav { 250*f7167e0eSDag-Erling Smørgrav u_int32_t r, min; 251*f7167e0eSDag-Erling Smørgrav 252*f7167e0eSDag-Erling Smørgrav if (upper_bound < 2) 253*f7167e0eSDag-Erling Smørgrav return 0; 254*f7167e0eSDag-Erling Smørgrav 255*f7167e0eSDag-Erling Smørgrav /* 2**32 % x == (2**32 - x) % x */ 256*f7167e0eSDag-Erling Smørgrav min = -upper_bound % upper_bound; 257*f7167e0eSDag-Erling Smørgrav 258*f7167e0eSDag-Erling Smørgrav /* 259*f7167e0eSDag-Erling Smørgrav * This could theoretically loop forever but each retry has 260*f7167e0eSDag-Erling Smørgrav * p > 0.5 (worst case, usually far better) of selecting a 261*f7167e0eSDag-Erling Smørgrav * number inside the range we need, so it should rarely need 262*f7167e0eSDag-Erling Smørgrav * to re-roll. 263*f7167e0eSDag-Erling Smørgrav */ 264*f7167e0eSDag-Erling Smørgrav for (;;) { 265*f7167e0eSDag-Erling Smørgrav r = arc4random(); 266*f7167e0eSDag-Erling Smørgrav if (r >= min) 267*f7167e0eSDag-Erling Smørgrav break; 268*f7167e0eSDag-Erling Smørgrav } 269*f7167e0eSDag-Erling Smørgrav 270*f7167e0eSDag-Erling Smørgrav return r % upper_bound; 271*f7167e0eSDag-Erling Smørgrav } 272*f7167e0eSDag-Erling Smørgrav #endif /* !HAVE_ARC4RANDOM_UNIFORM */ 273*f7167e0eSDag-Erling Smørgrav 274*f7167e0eSDag-Erling Smørgrav #if 0 275*f7167e0eSDag-Erling Smørgrav /*-------- Test code for i386 --------*/ 276*f7167e0eSDag-Erling Smørgrav #include <stdio.h> 277*f7167e0eSDag-Erling Smørgrav #include <machine/pctr.h> 278*f7167e0eSDag-Erling Smørgrav int 279*f7167e0eSDag-Erling Smørgrav main(int argc, char **argv) 280*f7167e0eSDag-Erling Smørgrav { 281*f7167e0eSDag-Erling Smørgrav const int iter = 1000000; 282*f7167e0eSDag-Erling Smørgrav int i; 283*f7167e0eSDag-Erling Smørgrav pctrval v; 284*f7167e0eSDag-Erling Smørgrav 285*f7167e0eSDag-Erling Smørgrav v = rdtsc(); 286*f7167e0eSDag-Erling Smørgrav for (i = 0; i < iter; i++) 287*f7167e0eSDag-Erling Smørgrav arc4random(); 288*f7167e0eSDag-Erling Smørgrav v = rdtsc() - v; 289*f7167e0eSDag-Erling Smørgrav v /= iter; 290*f7167e0eSDag-Erling Smørgrav 291*f7167e0eSDag-Erling Smørgrav printf("%qd cycles\n", v); 292*f7167e0eSDag-Erling Smørgrav exit(0); 293*f7167e0eSDag-Erling Smørgrav } 294*f7167e0eSDag-Erling Smørgrav #endif 295