unrealircd

- supernets unrealircd source & configuration
git clone git://git.acid.vegas/unrealircd.git
Log | Files | Refs | Archive | README | LICENSE

random.c (12826B)

      1 /************************************************************************
      2  *   IRC - Internet Relay Chat, random.c
      3  *   (C) 2004-2019 Bram Matthys (Syzop) and the UnrealIRCd Team
      4  *
      5  *   See file AUTHORS in IRC package for additional names of
      6  *   the programmers. 
      7  *
      8  *   This program is free software; you can redistribute it and/or modify
      9  *   it under the terms of the GNU General Public License as published by
     10  *   the Free Software Foundation; either version 1, or (at your option)
     11  *   any later version.
     12  *
     13  *   This program is distributed in the hope that it will be useful,
     14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16  *   GNU General Public License for more details.
     17  *
     18  *   You should have received a copy of the GNU General Public License
     19  *   along with this program; if not, write to the Free Software
     20  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     21  *
     22  */
     23 
     24 #include "unrealircd.h"
     25 
     26 #ifndef HAVE_ARC4RANDOM
     27 
     28 #define KEYSTREAM_ONLY
     29 
     30 /* chacha_private.h from openssh/openssh-portable
     31  * "chacha-merged.c version 20080118
     32  *  D. J. Bernstein
     33  *  Public domain."
     34  */
     35 
     36 /* $OpenBSD: chacha_private.h,v 1.2 2013/10/04 07:02:27 djm Exp $ */
     37 
     38 typedef unsigned char u8;
     39 typedef unsigned int u32;
     40 
     41 typedef struct
     42 {
     43   u32 input[16]; /* could be compressed */
     44 } chacha_ctx;
     45 
     46 #define U8C(v) (v##U)
     47 #define U32C(v) (v##U)
     48 
     49 #define U8V(v) ((u8)(v) & U8C(0xFF))
     50 #define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF))
     51 
     52 #define ROTL32(v, n) \
     53   (U32V((v) << (n)) | ((v) >> (32 - (n))))
     54 
     55 #define U8TO32_LITTLE(p) \
     56   (((u32)((p)[0])      ) | \
     57    ((u32)((p)[1]) <<  8) | \
     58    ((u32)((p)[2]) << 16) | \
     59    ((u32)((p)[3]) << 24))
     60 
     61 #define U32TO8_LITTLE(p, v) \
     62   do { \
     63     (p)[0] = U8V((v)      ); \
     64     (p)[1] = U8V((v) >>  8); \
     65     (p)[2] = U8V((v) >> 16); \
     66     (p)[3] = U8V((v) >> 24); \
     67   } while (0)
     68 
     69 #define ROTATE(v,c) (ROTL32(v,c))
     70 #define XOR(v,w) ((v) ^ (w))
     71 #define PLUS(v,w) (U32V((v) + (w)))
     72 #define PLUSONE(v) (PLUS((v),1))
     73 
     74 #define QUARTERROUND(a,b,c,d) \
     75   a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \
     76   c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \
     77   a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
     78   c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
     79 
     80 static const char sigma[16] = "expand 32-byte k";
     81 static const char tau[16] = "expand 16-byte k";
     82 
     83 static void
     84 chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits,u32 ivbits)
     85 {
     86   const char *constants;
     87 
     88   x->input[4] = U8TO32_LITTLE(k + 0);
     89   x->input[5] = U8TO32_LITTLE(k + 4);
     90   x->input[6] = U8TO32_LITTLE(k + 8);
     91   x->input[7] = U8TO32_LITTLE(k + 12);
     92   if (kbits == 256) { /* recommended */
     93     k += 16;
     94     constants = sigma;
     95   } else { /* kbits == 128 */
     96     constants = tau;
     97   }
     98   x->input[8] = U8TO32_LITTLE(k + 0);
     99   x->input[9] = U8TO32_LITTLE(k + 4);
    100   x->input[10] = U8TO32_LITTLE(k + 8);
    101   x->input[11] = U8TO32_LITTLE(k + 12);
    102   x->input[0] = U8TO32_LITTLE(constants + 0);
    103   x->input[1] = U8TO32_LITTLE(constants + 4);
    104   x->input[2] = U8TO32_LITTLE(constants + 8);
    105   x->input[3] = U8TO32_LITTLE(constants + 12);
    106 }
    107 
    108 static void
    109 chacha_ivsetup(chacha_ctx *x,const u8 *iv)
    110 {
    111   x->input[12] = 0;
    112   x->input[13] = 0;
    113   x->input[14] = U8TO32_LITTLE(iv + 0);
    114   x->input[15] = U8TO32_LITTLE(iv + 4);
    115 }
    116 
    117 static void
    118 chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes)
    119 {
    120   u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
    121   u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
    122   u8 *ctarget = NULL;
    123   u8 tmp[64];
    124   u_int i;
    125 
    126   if (!bytes) return;
    127 
    128   j0 = x->input[0];
    129   j1 = x->input[1];
    130   j2 = x->input[2];
    131   j3 = x->input[3];
    132   j4 = x->input[4];
    133   j5 = x->input[5];
    134   j6 = x->input[6];
    135   j7 = x->input[7];
    136   j8 = x->input[8];
    137   j9 = x->input[9];
    138   j10 = x->input[10];
    139   j11 = x->input[11];
    140   j12 = x->input[12];
    141   j13 = x->input[13];
    142   j14 = x->input[14];
    143   j15 = x->input[15];
    144 
    145   for (;;) {
    146     if (bytes < 64) {
    147       for (i = 0;i < bytes;++i) tmp[i] = m[i];
    148       m = tmp;
    149       ctarget = c;
    150       c = tmp;
    151     }
    152     x0 = j0;
    153     x1 = j1;
    154     x2 = j2;
    155     x3 = j3;
    156     x4 = j4;
    157     x5 = j5;
    158     x6 = j6;
    159     x7 = j7;
    160     x8 = j8;
    161     x9 = j9;
    162     x10 = j10;
    163     x11 = j11;
    164     x12 = j12;
    165     x13 = j13;
    166     x14 = j14;
    167     x15 = j15;
    168     for (i = 20;i > 0;i -= 2) {
    169       QUARTERROUND( x0, x4, x8,x12)
    170       QUARTERROUND( x1, x5, x9,x13)
    171       QUARTERROUND( x2, x6,x10,x14)
    172       QUARTERROUND( x3, x7,x11,x15)
    173       QUARTERROUND( x0, x5,x10,x15)
    174       QUARTERROUND( x1, x6,x11,x12)
    175       QUARTERROUND( x2, x7, x8,x13)
    176       QUARTERROUND( x3, x4, x9,x14)
    177     }
    178     x0 = PLUS(x0,j0);
    179     x1 = PLUS(x1,j1);
    180     x2 = PLUS(x2,j2);
    181     x3 = PLUS(x3,j3);
    182     x4 = PLUS(x4,j4);
    183     x5 = PLUS(x5,j5);
    184     x6 = PLUS(x6,j6);
    185     x7 = PLUS(x7,j7);
    186     x8 = PLUS(x8,j8);
    187     x9 = PLUS(x9,j9);
    188     x10 = PLUS(x10,j10);
    189     x11 = PLUS(x11,j11);
    190     x12 = PLUS(x12,j12);
    191     x13 = PLUS(x13,j13);
    192     x14 = PLUS(x14,j14);
    193     x15 = PLUS(x15,j15);
    194 
    195 #ifndef KEYSTREAM_ONLY
    196     x0 = XOR(x0,U8TO32_LITTLE(m + 0));
    197     x1 = XOR(x1,U8TO32_LITTLE(m + 4));
    198     x2 = XOR(x2,U8TO32_LITTLE(m + 8));
    199     x3 = XOR(x3,U8TO32_LITTLE(m + 12));
    200     x4 = XOR(x4,U8TO32_LITTLE(m + 16));
    201     x5 = XOR(x5,U8TO32_LITTLE(m + 20));
    202     x6 = XOR(x6,U8TO32_LITTLE(m + 24));
    203     x7 = XOR(x7,U8TO32_LITTLE(m + 28));
    204     x8 = XOR(x8,U8TO32_LITTLE(m + 32));
    205     x9 = XOR(x9,U8TO32_LITTLE(m + 36));
    206     x10 = XOR(x10,U8TO32_LITTLE(m + 40));
    207     x11 = XOR(x11,U8TO32_LITTLE(m + 44));
    208     x12 = XOR(x12,U8TO32_LITTLE(m + 48));
    209     x13 = XOR(x13,U8TO32_LITTLE(m + 52));
    210     x14 = XOR(x14,U8TO32_LITTLE(m + 56));
    211     x15 = XOR(x15,U8TO32_LITTLE(m + 60));
    212 #endif
    213 
    214     j12 = PLUSONE(j12);
    215     if (!j12) {
    216       j13 = PLUSONE(j13);
    217       /* stopping at 2^70 bytes per nonce is user's responsibility */
    218     }
    219 
    220     U32TO8_LITTLE(c + 0,x0);
    221     U32TO8_LITTLE(c + 4,x1);
    222     U32TO8_LITTLE(c + 8,x2);
    223     U32TO8_LITTLE(c + 12,x3);
    224     U32TO8_LITTLE(c + 16,x4);
    225     U32TO8_LITTLE(c + 20,x5);
    226     U32TO8_LITTLE(c + 24,x6);
    227     U32TO8_LITTLE(c + 28,x7);
    228     U32TO8_LITTLE(c + 32,x8);
    229     U32TO8_LITTLE(c + 36,x9);
    230     U32TO8_LITTLE(c + 40,x10);
    231     U32TO8_LITTLE(c + 44,x11);
    232     U32TO8_LITTLE(c + 48,x12);
    233     U32TO8_LITTLE(c + 52,x13);
    234     U32TO8_LITTLE(c + 56,x14);
    235     U32TO8_LITTLE(c + 60,x15);
    236 
    237     if (bytes <= 64) {
    238       if (bytes < 64) {
    239         for (i = 0;i < bytes;++i) ctarget[i] = c[i];
    240       }
    241       x->input[12] = j12;
    242       x->input[13] = j13;
    243       return;
    244     }
    245     bytes -= 64;
    246     c += 64;
    247 #ifndef KEYSTREAM_ONLY
    248     m += 64;
    249 #endif
    250   }
    251 }
    252 
    253 /* The following is taken from arc4random.c
    254  * from openssh/openssh-portable/, which has an ISC license,
    255  * which is GPL compatible.
    256  */
    257 
    258 /* OPENBSD ORIGINAL: lib/libc/crypto/arc4random.c */
    259 /* $OpenBSD: arc4random.c,v 1.25 2013/10/01 18:34:57 markus Exp $	*/
    260 /*
    261  * Copyright (c) 1996, David Mazieres <dm@uun.org>
    262  * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
    263  * Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
    264  *
    265  * Permission to use, copy, modify, and distribute this software for any
    266  * purpose with or without fee is hereby granted, provided that the above
    267  * copyright notice and this permission notice appear in all copies.
    268  *
    269  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
    270  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
    271  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
    272  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    273  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
    274  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    275  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    276  */
    277 
    278 /* Modified for UnrealIRCd by Bram Matthys ("Syzop") in 2019.
    279  * Things like taking out #if (n)def's for openssl (which we always
    280  * compile with), re-indenting, removing various stuff, etc.
    281  */
    282 
    283 
    284 
    285 #define KEYSZ	32
    286 #define IVSZ	8
    287 #define BLOCKSZ	64
    288 #define RSBUFSZ	(16*BLOCKSZ)
    289 static int rs_initialized;
    290 static chacha_ctx rs;		/* chacha context for random keystream */
    291 static u_char rs_buf[RSBUFSZ];	/* keystream blocks */
    292 static size_t rs_have;		/* valid bytes at end of rs_buf */
    293 static size_t rs_count;		/* bytes till reseed */
    294 
    295 static inline void _rs_rekey(u_char *dat, size_t datlen);
    296 
    297 static inline void _rs_init(u_char *buf, size_t n)
    298 {
    299 	if (n < KEYSZ + IVSZ)
    300 		return;
    301 	chacha_keysetup(&rs, buf, KEYSZ * 8, 0);
    302 	chacha_ivsetup(&rs, buf + KEYSZ);
    303 }
    304 
    305 static void _rs_stir(void)
    306 {
    307 	u_char rnd[KEYSZ + IVSZ];
    308 
    309 	if (RAND_bytes(rnd, sizeof(rnd)) <= 0)
    310 	{
    311 		unreal_log(ULOG_FATAL, "random", "RANDOM_OUT_OF_BYTES", NULL,
    312 		           "Could not obtain random bytes, error $tls_error_code",
    313 		           log_data_integer("tls_error_code", ERR_get_error()));
    314 		abort();
    315 	}
    316 
    317 	if (!rs_initialized) {
    318 		rs_initialized = 1;
    319 		_rs_init(rnd, sizeof(rnd));
    320 	} else
    321 		_rs_rekey(rnd, sizeof(rnd));
    322 #ifdef HAVE_EXPLICIT_BZERO
    323 	explicit_bzero(rnd, sizeof(rnd));
    324 #else
    325 	/* Not terribly important in this case */
    326 	memset(rnd, 0, sizeof(rnd));
    327 #endif
    328 	/* invalidate rs_buf */
    329 	rs_have = 0;
    330 	memset(rs_buf, 0, RSBUFSZ);
    331 
    332 	rs_count = 1600000;
    333 }
    334 
    335 static inline void _rs_stir_if_needed(size_t len)
    336 {
    337 	if (rs_count <= len || !rs_initialized) {
    338 		_rs_stir();
    339 	} else
    340 		rs_count -= len;
    341 }
    342 
    343 static inline void _rs_rekey(u_char *dat, size_t datlen)
    344 {
    345 #ifndef KEYSTREAM_ONLY
    346 	memset(rs_buf, 0,RSBUFSZ);
    347 #endif
    348 	/* fill rs_buf with the keystream */
    349 	chacha_encrypt_bytes(&rs, rs_buf, rs_buf, RSBUFSZ);
    350 	/* mix in optional user provided data */
    351 	if (dat) {
    352 		size_t i, m;
    353 
    354 		m = MIN(datlen, KEYSZ + IVSZ);
    355 		for (i = 0; i < m; i++)
    356 			rs_buf[i] ^= dat[i];
    357 	}
    358 	/* immediately reinit for backtracking resistance */
    359 	_rs_init(rs_buf, KEYSZ + IVSZ);
    360 	memset(rs_buf, 0, KEYSZ + IVSZ);
    361 	rs_have = RSBUFSZ - KEYSZ - IVSZ;
    362 }
    363 
    364 static inline void _rs_random_buf(void *_buf, size_t n)
    365 {
    366 	u_char *buf = (u_char *)_buf;
    367 	size_t m;
    368 
    369 	_rs_stir_if_needed(n);
    370 	while (n > 0) {
    371 		if (rs_have > 0) {
    372 			m = MIN(n, rs_have);
    373 			memcpy(buf, rs_buf + RSBUFSZ - rs_have, m);
    374 			memset(rs_buf + RSBUFSZ - rs_have, 0, m);
    375 			buf += m;
    376 			n -= m;
    377 			rs_have -= m;
    378 		}
    379 		if (rs_have == 0)
    380 			_rs_rekey(NULL, 0);
    381 	}
    382 }
    383 
    384 static inline void _rs_random_u32(uint32_t *val)
    385 {
    386 	_rs_stir_if_needed(sizeof(*val));
    387 	if (rs_have < sizeof(*val))
    388 		_rs_rekey(NULL, 0);
    389 	memcpy(val, rs_buf + RSBUFSZ - rs_have, sizeof(*val));
    390 	memset(rs_buf + RSBUFSZ - rs_have, 0, sizeof(*val));
    391 	rs_have -= sizeof(*val);
    392 	return;
    393 }
    394 
    395 void arc4random_stir(void)
    396 {
    397 	_rs_stir();
    398 }
    399 
    400 void arc4random_doaddrandom(u_char *dat, int datlen)
    401 {
    402 	int m;
    403 
    404 	if (!rs_initialized)
    405 		_rs_stir();
    406 	while (datlen > 0) {
    407 		m = MIN(datlen, KEYSZ + IVSZ);
    408 		_rs_rekey(dat, m);
    409 		dat += m;
    410 		datlen -= m;
    411 	}
    412 }
    413 
    414 #endif /* !HAVE_ARC4RANDOM */
    415 
    416 /* UnrealIRCd-specific functions follow */
    417 
    418 static void arc4_addrandom(void *dat, int datlen)
    419 {
    420 	arc4random_doaddrandom((unsigned char *)dat, datlen);
    421 	return;
    422 }
    423 
    424 void add_entropy_configfile(struct stat *st, char *buf)
    425 {
    426 	char sha256buf[SHA256_DIGEST_LENGTH];
    427 
    428 	arc4_addrandom(&st->st_size, sizeof(st->st_size));
    429 	arc4_addrandom(&st->st_mtime, sizeof(st->st_mtime));
    430 	sha256hash_binary(sha256buf, buf, strlen(buf));
    431 	arc4_addrandom(sha256buf, sizeof(sha256buf));
    432 }
    433 
    434 /*
    435  * init_random, written by Syzop.
    436  * This function tries to initialize the arc4 random number generator securely.
    437  */
    438 void init_random()
    439 {
    440 	struct {
    441 #ifndef _WIN32
    442 		struct timeval nowt;		/* time */
    443 		char rnd[32];			/* /dev/urandom */
    444 #else
    445 		struct _timeb nowt;		/* time */
    446 		MEMORYSTATUS mstat;		/* memory status */
    447 #endif
    448 	} rdat;
    449 
    450 #ifndef _WIN32
    451 	int fd;
    452 #endif
    453 
    454 	_rs_stir();
    455 
    456 	/* Grab OS specific "random" data */
    457 #ifndef _WIN32
    458 	gettimeofday(&rdat.nowt, NULL);
    459 	fd = open("/dev/urandom", O_RDONLY);
    460 	if (fd >= 0)
    461 	{
    462 		int n = read(fd, &rdat.rnd, sizeof(rdat.rnd));
    463 		close(fd);
    464 	}
    465 #else
    466 	_ftime(&rdat.nowt);
    467 	GlobalMemoryStatus (&rdat.mstat);
    468 #endif	
    469 
    470 	arc4_addrandom(&rdat, sizeof(rdat));
    471 
    472 	/* NOTE: addtional entropy is added by add_entropy_* function(s) */
    473 }
    474 
    475 uint32_t arc4random(void)
    476 {
    477 	uint32_t val;
    478 
    479 	_rs_random_u32(&val);
    480 	return val;
    481 }
    482 
    483 /** Get 8 bits (1 byte) of randomness */
    484 u_char getrandom8()
    485 {
    486 	return arc4random() & 0xff;
    487 }
    488 
    489 /** Get 16 bits (2 bytes) of randomness */
    490 uint16_t getrandom16()
    491 {
    492 	return arc4random() & 0xffff;
    493 }
    494 
    495 /** Get 32 bits (4 bytes) of randomness */
    496 uint32_t getrandom32()
    497 {
    498 	return arc4random();
    499 }
    500 
    501 /** Generate an alphanumeric string (eg: XzHe5G).
    502  * @param buf      The buffer
    503  * @param numbytes The number of random bytes.
    504  * @note  Note that numbytes+1 bytes are written to buf.
    505  *        In other words, numbytes does NOT include the NUL byte.
    506  */
    507 void gen_random_alnum(char *buf, int numbytes)
    508 {
    509 	for (; numbytes > 0; numbytes--)
    510 	{
    511 		unsigned char v = getrandom8() % (26+26+10);
    512 		if (v < 26)
    513 			*buf++ = 'a'+v;
    514 		else if (v < 52)
    515 			*buf++ = 'A'+(v-26);
    516 		else
    517 			*buf++ = '0'+(v-52);
    518 	}
    519 	*buf = '\0';
    520 }