diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..342d53a --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +*~ +*.o +/Makefile +/condhashconsts.h +/generate +/nodehashconsts.h +/varhashconsts.h +/omake diff --git a/arc4random-local.h b/arc4random-local.h new file mode 100644 index 0000000..40229ad --- /dev/null +++ b/arc4random-local.h @@ -0,0 +1,14 @@ +/* public domain */ + +#ifndef _ARC4RANDOM_LOCAL_H +#define _ARC4RANDOM_LOCAL_H + +#ifdef __linux__ +void arc4random_stir(void); +void arc4random_addrandom(unsigned char *dat, int datlen); +uint32_t arc4random(void); +void arc4random_buf(void *buf, size_t n); +uint32_t arc4random_uniform(uint32_t upper_bound); +#endif + +#endif diff --git a/arc4random.c b/arc4random.c new file mode 100644 index 0000000..1a7b72f --- /dev/null +++ b/arc4random.c @@ -0,0 +1,212 @@ +/* $OpenBSD: arc4random.c,v 1.53 2015/09/10 18:53:50 bcook Exp $ */ + +/* + * Copyright (c) 1996, David Mazieres + * Copyright (c) 2008, Damien Miller + * Copyright (c) 2013, Markus Friedl + * Copyright (c) 2014, Theo de Raadt + * Copyright (c) 2015, Guillem Jover + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * ChaCha based random number generator for OpenBSD. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define KEYSTREAM_ONLY +#include "chacha_private.h" + +#define minimum(a, b) ((a) < (b) ? (a) : (b)) + +#if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER) +#define inline __inline +#else /* __GNUC__ || __clang__ || _MSC_VER */ +#define inline +#endif /* !__GNUC__ && !__clang__ && !_MSC_VER */ + +#define KEYSZ 32 +#define IVSZ 8 +#define BLOCKSZ 64 +#define RSBUFSZ (16*BLOCKSZ) + +/* Marked MAP_INHERIT_ZERO, so zero'd out in fork children. */ +static struct _rs { + size_t rs_have; /* valid bytes at end of rs_buf */ + size_t rs_count; /* bytes till reseed */ +} *rs; + +/* Maybe be preserved in fork children, if _rs_allocate() decides. */ +static struct _rsx { + chacha_ctx rs_chacha; /* chacha context for random keystream */ + unsigned char rs_buf[RSBUFSZ]; /* keystream blocks */ +} *rsx; + +static inline int _rs_allocate(struct _rs **, struct _rsx **); +static inline void _rs_forkdetect(void); +#include "arc4random.h" + +static inline void +_rs_init(unsigned char *buf, size_t n) +{ + if (n < KEYSZ + IVSZ) + return; + + if (rs == NULL) { + if (_rs_allocate(&rs, &rsx) == -1) + abort(); + } + + chacha_keysetup(&rsx->rs_chacha, buf, KEYSZ * 8, 0); + chacha_ivsetup(&rsx->rs_chacha, buf + KEYSZ); +} + +static inline void +_rs_rekey(unsigned char *dat, size_t datlen) +{ +#ifndef KEYSTREAM_ONLY + memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf)); +#endif + /* fill rs_buf with the keystream */ + chacha_encrypt_bytes(&rsx->rs_chacha, rsx->rs_buf, + rsx->rs_buf, sizeof(rsx->rs_buf)); + /* mix in optional user provided data */ + if (dat) { + size_t i, m; + + m = minimum(datlen, KEYSZ + IVSZ); + for (i = 0; i < m; i++) + rsx->rs_buf[i] ^= dat[i]; + } + /* immediately reinit for backtracking resistance */ + _rs_init(rsx->rs_buf, KEYSZ + IVSZ); + memset(rsx->rs_buf, 0, KEYSZ + IVSZ); + rs->rs_have = sizeof(rsx->rs_buf) - KEYSZ - IVSZ; +} + +static void +_rs_stir(void) +{ + unsigned char rnd[KEYSZ + IVSZ]; + + if (getentropy(rnd, sizeof rnd) == -1) + _getentropy_fail(); + + if (!rs) + _rs_init(rnd, sizeof(rnd)); + else + _rs_rekey(rnd, sizeof(rnd)); + explicit_bzero(rnd, sizeof(rnd)); /* discard source seed */ + + /* invalidate rs_buf */ + rs->rs_have = 0; + memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf)); + + rs->rs_count = 1600000; +} + +static inline void +_rs_stir_if_needed(size_t len) +{ + _rs_forkdetect(); + if (!rs || rs->rs_count <= len) + _rs_stir(); + if (rs->rs_count <= len) + rs->rs_count = 0; + else + rs->rs_count -= len; +} + +static inline void +_rs_random_buf(void *_buf, size_t n) +{ + unsigned char *buf = (unsigned char *)_buf; + unsigned char *keystream; + size_t m; + + _rs_stir_if_needed(n); + while (n > 0) { + if (rs->rs_have > 0) { + m = minimum(n, rs->rs_have); + keystream = rsx->rs_buf + sizeof(rsx->rs_buf) + - rs->rs_have; + memcpy(buf, keystream, m); + memset(keystream, 0, m); + buf += m; + n -= m; + rs->rs_have -= m; + } + if (rs->rs_have == 0) + _rs_rekey(NULL, 0); + } +} + +static inline void +_rs_random_u32(uint32_t *val) +{ + unsigned char *keystream; + + _rs_stir_if_needed(sizeof(*val)); + if (rs->rs_have < sizeof(*val)) + _rs_rekey(NULL, 0); + keystream = rsx->rs_buf + sizeof(rsx->rs_buf) - rs->rs_have; + memcpy(val, keystream, sizeof(*val)); + memset(keystream, 0, sizeof(*val)); + rs->rs_have -= sizeof(*val); +} + +void +arc4random_stir(void) +{ + _ARC4_LOCK(); + _rs_stir(); + _ARC4_UNLOCK(); +} + +void +arc4random_addrandom(unsigned char *dat, int datlen) +{ + _ARC4_LOCK(); + _rs_stir_if_needed(datlen); + _rs_rekey(dat, datlen); + _ARC4_UNLOCK(); +} + +uint32_t +arc4random(void) +{ + uint32_t val; + + _ARC4_LOCK(); + _rs_random_u32(&val); + _ARC4_UNLOCK(); + return val; +} + +void +arc4random_buf(void *buf, size_t n) +{ + _ARC4_LOCK(); + _rs_random_buf(buf, n); + _ARC4_UNLOCK(); +} diff --git a/arc4random.h b/arc4random.h new file mode 100644 index 0000000..812188b --- /dev/null +++ b/arc4random.h @@ -0,0 +1,45 @@ +/* + * Copyright © 2015 Guillem Jover + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LIBBSD_ARC4RANDOM_H +#define LIBBSD_ARC4RANDOM_H + +#include + +int +getentropy(void *buf, size_t len); + +#if defined(__OpenBSD__) +#include "arc4random_openbsd.h" +#elif defined(__linux__) +#include "arc4random_linux.h" +#elif defined(_WIN32) +#include "arc4random_win.h" +#else +#include "arc4random_unix.h" +#endif + +#endif diff --git a/arc4random_linux.h b/arc4random_linux.h new file mode 100644 index 0000000..bc57cd1 --- /dev/null +++ b/arc4random_linux.h @@ -0,0 +1,88 @@ +/* $OpenBSD: arc4random_linux.h,v 1.11 2016/06/30 12:19:51 bcook Exp $ */ + +/* + * Copyright (c) 1996, David Mazieres + * Copyright (c) 2008, Damien Miller + * Copyright (c) 2013, Markus Friedl + * Copyright (c) 2014, Theo de Raadt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Stub functions for portability. + */ + +#include + +#include +#include + +static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER; +#define _ARC4_LOCK() pthread_mutex_lock(&arc4random_mtx) +#define _ARC4_UNLOCK() pthread_mutex_unlock(&arc4random_mtx) + +#ifdef HAVE___REGISTER_ATFORK +extern void *__dso_handle; +extern int __register_atfork(void (*)(void), void(*)(void), void (*)(void), void *); +#define _ARC4_ATFORK(f) __register_atfork(NULL, NULL, (f), __dso_handle) +#else +#define _ARC4_ATFORK(f) pthread_atfork(NULL, NULL, (f)) +#endif + +static inline void +_getentropy_fail(void) +{ + raise(SIGKILL); +} + +static volatile sig_atomic_t _rs_forked; + +static inline void +_rs_forkhandler(void) +{ + _rs_forked = 1; +} + +static inline void +_rs_forkdetect(void) +{ + static pid_t _rs_pid = 0; + pid_t pid = getpid(); + + /* XXX unusual calls to clone() can bypass checks */ + if (_rs_pid == 0 || _rs_pid == 1 || _rs_pid != pid || _rs_forked) { + _rs_pid = pid; + _rs_forked = 0; + if (rs) + memset(rs, 0, sizeof(*rs)); + } +} + +static inline int +_rs_allocate(struct _rs **rsp, struct _rsx **rsxp) +{ + if ((*rsp = mmap(NULL, sizeof(**rsp), PROT_READ|PROT_WRITE, + MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) + return (-1); + + if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE, + MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) { + munmap(*rsp, sizeof(**rsp)); + *rsp = NULL; + return (-1); + } + + _ARC4_ATFORK(_rs_forkhandler); + return (0); +} diff --git a/arc4random_openbsd.h b/arc4random_openbsd.h new file mode 100644 index 0000000..9cd8b68 --- /dev/null +++ b/arc4random_openbsd.h @@ -0,0 +1,61 @@ +/* $OpenBSD: arc4random.h,v 1.3 2014/07/20 20:51:13 bcook Exp $ */ + +/* + * Copyright (c) 1996, David Mazieres + * Copyright (c) 2008, Damien Miller + * Copyright (c) 2013, Markus Friedl + * Copyright (c) 2014, Theo de Raadt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Stub functions for portability. + */ +#include + +#include + +#include "thread_private.h" + +static inline void +_getentropy_fail(void) +{ + raise(SIGKILL); +} + +static inline int +_rs_allocate(struct _rs **rsp, struct _rsx **rsxp) +{ + struct { + struct _rs rs; + struct _rsx rsx; + } *p; + + if ((p = mmap(NULL, sizeof(*p), PROT_READ|PROT_WRITE, + MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) + return (-1); + if (minherit(p, sizeof(*p), MAP_INHERIT_ZERO) == -1) { + munmap(p, sizeof(*p)); + return (-1); + } + + *rsp = &p->rs; + *rsxp = &p->rsx; + return (0); +} + +static inline void +_rs_forkdetect(void) +{ +} diff --git a/arc4random_uniform.c b/arc4random_uniform.c new file mode 100644 index 0000000..4ac006a --- /dev/null +++ b/arc4random_uniform.c @@ -0,0 +1,61 @@ +/* $OpenBSD: arc4random_uniform.c,v 1.1 2014/07/12 13:24:54 deraadt Exp $ */ + +/* + * Copyright (c) 2008, Damien Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include /* for getpid in arc4random_linux.h */ + +#include "arc4random-local.h" + +/* + * Calculate a uniformly distributed random number less than upper_bound + * avoiding "modulo bias". + * + * Uniformity is achieved by generating new random numbers until the one + * returned is outside the range [0, 2**32 % upper_bound). This + * guarantees the selected random number will be inside + * [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound) + * after reduction modulo upper_bound. + */ +uint32_t +arc4random_uniform(uint32_t upper_bound) +{ + uint32_t r, min; + + if (upper_bound < 2) + return 0; + + /* 2**32 % x == (2**32 - x) % x */ + min = -upper_bound % upper_bound; + + /* + * This could theoretically loop forever but each retry has + * p > 0.5 (worst case, usually far better) of selecting a + * number inside the range we need, so it should rarely need + * to re-roll. + */ + for (;;) { + r = arc4random(); + if (r >= min) + break; + } + + return r % upper_bound; +} +//DEF_WEAK(arc4random_uniform); diff --git a/arc4random_unix.h b/arc4random_unix.h new file mode 100644 index 0000000..2e6c6ea --- /dev/null +++ b/arc4random_unix.h @@ -0,0 +1,93 @@ +/* $OpenBSD: arc4random_freebsd.h,v 1.4 2016/06/30 12:19:51 bcook Exp $ */ + +/* + * Copyright (c) 1996, David Mazieres + * Copyright (c) 2008, Damien Miller + * Copyright (c) 2013, Markus Friedl + * Copyright (c) 2014, Theo de Raadt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Stub functions for portability. + */ + +#include + +#include +#include + +static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER; +#define _ARC4_LOCK() pthread_mutex_lock(&arc4random_mtx) +#define _ARC4_UNLOCK() pthread_mutex_unlock(&arc4random_mtx) + +#ifdef HAVE___REGISTER_ATFORK +extern void *__dso_handle; +extern int __register_atfork(void (*)(void), void(*)(void), void (*)(void), void *); +#define _ARC4_ATFORK(f) __register_atfork(NULL, NULL, (f), __dso_handle) +#else +/* + * Unfortunately, pthread_atfork() is broken on FreeBSD (at least 9 and 10) if + * a program does not link to -lthr. Callbacks registered with pthread_atfork() + * appear to fail silently. So, it is not always possible to detect a PID + * wraparound. + */ +#define _ARC4_ATFORK(f) pthread_atfork(NULL, NULL, (f)) +#endif + +static inline void +_getentropy_fail(void) +{ + raise(SIGKILL); +} + +static volatile sig_atomic_t _rs_forked; + +static inline void +_rs_forkhandler(void) +{ + _rs_forked = 1; +} + +static inline void +_rs_forkdetect(void) +{ + static pid_t _rs_pid = 0; + pid_t pid = getpid(); + + if (_rs_pid == 0 || _rs_pid != pid || _rs_forked) { + _rs_pid = pid; + _rs_forked = 0; + if (rs) + memset(rs, 0, sizeof(*rs)); + } +} + +static inline int +_rs_allocate(struct _rs **rsp, struct _rsx **rsxp) +{ + if ((*rsp = mmap(NULL, sizeof(**rsp), PROT_READ|PROT_WRITE, + MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) + return (-1); + + if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE, + MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) { + munmap(*rsp, sizeof(**rsp)); + *rsp = NULL; + return (-1); + } + + _ARC4_ATFORK(_rs_forkhandler); + return (0); +} diff --git a/arch.h b/arch.h index 1c205e4..2166b2e 100644 --- a/arch.h +++ b/arch.h @@ -34,6 +34,10 @@ #include +#ifdef HAS_TIME_H +#include +#endif + /* Initialization and cleanup */ extern void Arch_Init(void); diff --git a/cdefs-local.h b/cdefs-local.h new file mode 100644 index 0000000..84caff8 --- /dev/null +++ b/cdefs-local.h @@ -0,0 +1,78 @@ +/* +MIT License + +Copyright (c) 2005-2018 Luc Van Oostenryck + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +**** + +taken from https://github.com/lucvoo/slibc/blob/master/include/sys/cdefs.h + +added additional ifdefs for all definitions, useful when using musl +libc + +*/ + +#ifndef _CDEFS_LOCAL_H +#define _CDEFS_LOCAL_H + +#ifndef __GNUC_VERSION +#define __GNUC_VERSION (__GNUC__*100 + __GNUC_MINOR__) +#endif + +#ifdef __cplusplus +#ifndef __THROW +#define __THROW throw () +#endif +#ifndef __BEGIN_DECLS +#define __BEGIN_DECLS extern "C" { +#endif +#ifndef __END_DECLS +#define __END_DECLS } +#endif +#else /* __cplusplus */ +#ifndef __THROW +#define __THROW +#endif +#ifndef __BEGIN_DECLS +#define __BEGIN_DECLS +#endif +#ifndef __END_DECLS +#define __END_DECLS +#endif +#endif /* __cplusplus */ + +#ifndef __CONST +#define __CONST __attribute__((__const__)) +#endif + +#ifndef __MALLOC +#define __MALLOC __attribute__((__malloc__)) +#endif + +#ifndef __NORETURN +#define __NORETURN __attribute__((__noreturn__)) +#endif + +#ifndef __PURE +#define __PURE __attribute__((__pure__)) +#endif + +#endif diff --git a/chacha_private.h b/chacha_private.h new file mode 100644 index 0000000..3b4ec93 --- /dev/null +++ b/chacha_private.h @@ -0,0 +1,222 @@ +/* +chacha-merged.c version 20080118 +D. J. Bernstein +Public domain. +*/ + +/* $OpenBSD: chacha_private.h,v 1.2 2013/10/04 07:02:27 djm Exp $ */ + +typedef unsigned char u8; +typedef unsigned int u32; + +typedef struct +{ + u32 input[16]; /* could be compressed */ +} chacha_ctx; + +#define U8C(v) (v##U) +#define U32C(v) (v##U) + +#define U8V(v) ((u8)(v) & U8C(0xFF)) +#define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF)) + +#define ROTL32(v, n) \ + (U32V((v) << (n)) | ((v) >> (32 - (n)))) + +#define U8TO32_LITTLE(p) \ + (((u32)((p)[0]) ) | \ + ((u32)((p)[1]) << 8) | \ + ((u32)((p)[2]) << 16) | \ + ((u32)((p)[3]) << 24)) + +#define U32TO8_LITTLE(p, v) \ + do { \ + (p)[0] = U8V((v) ); \ + (p)[1] = U8V((v) >> 8); \ + (p)[2] = U8V((v) >> 16); \ + (p)[3] = U8V((v) >> 24); \ + } while (0) + +#define ROTATE(v,c) (ROTL32(v,c)) +#define XOR(v,w) ((v) ^ (w)) +#define PLUS(v,w) (U32V((v) + (w))) +#define PLUSONE(v) (PLUS((v),1)) + +#define QUARTERROUND(a,b,c,d) \ + a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \ + c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \ + a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \ + c = PLUS(c,d); b = ROTATE(XOR(b,c), 7); + +static const char sigma[16] = "expand 32-byte k"; +static const char tau[16] = "expand 16-byte k"; + +static void +chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits,u32 ivbits) +{ + const char *constants; + + x->input[4] = U8TO32_LITTLE(k + 0); + x->input[5] = U8TO32_LITTLE(k + 4); + x->input[6] = U8TO32_LITTLE(k + 8); + x->input[7] = U8TO32_LITTLE(k + 12); + if (kbits == 256) { /* recommended */ + k += 16; + constants = sigma; + } else { /* kbits == 128 */ + constants = tau; + } + x->input[8] = U8TO32_LITTLE(k + 0); + x->input[9] = U8TO32_LITTLE(k + 4); + x->input[10] = U8TO32_LITTLE(k + 8); + x->input[11] = U8TO32_LITTLE(k + 12); + x->input[0] = U8TO32_LITTLE(constants + 0); + x->input[1] = U8TO32_LITTLE(constants + 4); + x->input[2] = U8TO32_LITTLE(constants + 8); + x->input[3] = U8TO32_LITTLE(constants + 12); +} + +static void +chacha_ivsetup(chacha_ctx *x,const u8 *iv) +{ + x->input[12] = 0; + x->input[13] = 0; + x->input[14] = U8TO32_LITTLE(iv + 0); + x->input[15] = U8TO32_LITTLE(iv + 4); +} + +static void +chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes) +{ + u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; + u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15; + u8 *ctarget = NULL; + u8 tmp[64]; + unsigned int i; + + if (!bytes) return; + + j0 = x->input[0]; + j1 = x->input[1]; + j2 = x->input[2]; + j3 = x->input[3]; + j4 = x->input[4]; + j5 = x->input[5]; + j6 = x->input[6]; + j7 = x->input[7]; + j8 = x->input[8]; + j9 = x->input[9]; + j10 = x->input[10]; + j11 = x->input[11]; + j12 = x->input[12]; + j13 = x->input[13]; + j14 = x->input[14]; + j15 = x->input[15]; + + for (;;) { + if (bytes < 64) { + for (i = 0;i < bytes;++i) tmp[i] = m[i]; + m = tmp; + ctarget = c; + c = tmp; + } + x0 = j0; + x1 = j1; + x2 = j2; + x3 = j3; + x4 = j4; + x5 = j5; + x6 = j6; + x7 = j7; + x8 = j8; + x9 = j9; + x10 = j10; + x11 = j11; + x12 = j12; + x13 = j13; + x14 = j14; + x15 = j15; + for (i = 20;i > 0;i -= 2) { + QUARTERROUND( x0, x4, x8,x12) + QUARTERROUND( x1, x5, x9,x13) + QUARTERROUND( x2, x6,x10,x14) + QUARTERROUND( x3, x7,x11,x15) + QUARTERROUND( x0, x5,x10,x15) + QUARTERROUND( x1, x6,x11,x12) + QUARTERROUND( x2, x7, x8,x13) + QUARTERROUND( x3, x4, x9,x14) + } + x0 = PLUS(x0,j0); + x1 = PLUS(x1,j1); + x2 = PLUS(x2,j2); + x3 = PLUS(x3,j3); + x4 = PLUS(x4,j4); + x5 = PLUS(x5,j5); + x6 = PLUS(x6,j6); + x7 = PLUS(x7,j7); + x8 = PLUS(x8,j8); + x9 = PLUS(x9,j9); + x10 = PLUS(x10,j10); + x11 = PLUS(x11,j11); + x12 = PLUS(x12,j12); + x13 = PLUS(x13,j13); + x14 = PLUS(x14,j14); + x15 = PLUS(x15,j15); + +#ifndef KEYSTREAM_ONLY + x0 = XOR(x0,U8TO32_LITTLE(m + 0)); + x1 = XOR(x1,U8TO32_LITTLE(m + 4)); + x2 = XOR(x2,U8TO32_LITTLE(m + 8)); + x3 = XOR(x3,U8TO32_LITTLE(m + 12)); + x4 = XOR(x4,U8TO32_LITTLE(m + 16)); + x5 = XOR(x5,U8TO32_LITTLE(m + 20)); + x6 = XOR(x6,U8TO32_LITTLE(m + 24)); + x7 = XOR(x7,U8TO32_LITTLE(m + 28)); + x8 = XOR(x8,U8TO32_LITTLE(m + 32)); + x9 = XOR(x9,U8TO32_LITTLE(m + 36)); + x10 = XOR(x10,U8TO32_LITTLE(m + 40)); + x11 = XOR(x11,U8TO32_LITTLE(m + 44)); + x12 = XOR(x12,U8TO32_LITTLE(m + 48)); + x13 = XOR(x13,U8TO32_LITTLE(m + 52)); + x14 = XOR(x14,U8TO32_LITTLE(m + 56)); + x15 = XOR(x15,U8TO32_LITTLE(m + 60)); +#endif + + j12 = PLUSONE(j12); + if (!j12) { + j13 = PLUSONE(j13); + /* stopping at 2^70 bytes per nonce is user's responsibility */ + } + + U32TO8_LITTLE(c + 0,x0); + U32TO8_LITTLE(c + 4,x1); + U32TO8_LITTLE(c + 8,x2); + U32TO8_LITTLE(c + 12,x3); + U32TO8_LITTLE(c + 16,x4); + U32TO8_LITTLE(c + 20,x5); + U32TO8_LITTLE(c + 24,x6); + U32TO8_LITTLE(c + 28,x7); + U32TO8_LITTLE(c + 32,x8); + U32TO8_LITTLE(c + 36,x9); + U32TO8_LITTLE(c + 40,x10); + U32TO8_LITTLE(c + 44,x11); + U32TO8_LITTLE(c + 48,x12); + U32TO8_LITTLE(c + 52,x13); + U32TO8_LITTLE(c + 56,x14); + U32TO8_LITTLE(c + 60,x15); + + if (bytes <= 64) { + if (bytes < 64) { + for (i = 0;i < bytes;++i) ctarget[i] = c[i]; + } + x->input[12] = j12; + x->input[13] = j13; + return; + } + bytes -= 64; + c += 64; +#ifndef KEYSTREAM_ONLY + m += 64; +#endif + } +} diff --git a/compat.c b/compat.c index 97f0524..6fc0f79 100644 --- a/compat.c +++ b/compat.c @@ -56,6 +56,10 @@ #include "timestamp.h" #include "lst.h" +#ifdef HAS_TIME_H +#include +#endif + static void CompatMake(void *, void *); /*- diff --git a/configure b/configure index 24e5fe1..dd26fed 100755 --- a/configure +++ b/configure @@ -5,13 +5,6 @@ # Program name prog="omake" -# Default prefix -prefix="/usr/local" -DSP="-D_PATH_DEFSYSPATH=\"\\\"$prefix/share/mk\\\"\"" - -# Default manual page directory -mandir="$prefix/man" - # What OS are we on? os=`uname -s` @@ -21,7 +14,6 @@ do case "$opt" in --prefix=*) prefix=${opt#*=} - DSP="-D_PATH_DEFSYSPATH=\"\\\"$prefix/share/mk\\\"\"" ;; --mandir=*) mandir=${opt#*=} @@ -52,6 +44,13 @@ do esac done +# Default prefix +[ x"$prefix" != x ] || prefix=/usr/local +DSP="-D_PATH_DEFSYSPATH=\"\\\"$prefix/share/mk\\\"\"" + +# Default manual page directory +[ x"$mandir" != x ] || mandir=$prefix/share/man + # Figure out C compiler. # We can probably assume gcc is available, so it's the failsafe. printf "checking for C compiler... " @@ -243,6 +242,61 @@ fi rm -f /tmp/checkprogname /tmp/checkprogname.c checkprogname.o +printf "checking for sys_signame... " +cat << EOF > /tmp/checksigname.c +/* This file generated by omake configure script. */ + +#include + +extern const char *const sys_signame[]; + +int +main(void) +{ + (void) fprintf(stderr, "%s\n", sys_signame[0]); + + return 0; +} +EOF + +$cc -o /tmp/checksigname /tmp/checksigname.c > /dev/null 2>&1 + +if [ $? -ne 0 ] ; then + DNSN="-DNEED_SYS_SIGNAME" + echo "no" +else + echo "yes" +fi + +rm -f /tmp/checksigname /tmp/checksigname.c checksigname.o + +printf "checking for time.h... " +cat << EOF > /tmp/checktime_h.c +/* This file generated by omake configure script. */ + +#include +#include + +int +main(void) +{ + (void) fprintf(stderr, "time.h found\n"); + + return 0; +} +EOF + +$cc -o /tmp/checktime_h /tmp/checktime_h.c > /dev/null 2>&1 + +if [ $? -ne 0 ] ; then + echo "no" +else + DHT="-DHAS_TIME_H" + echo "yes" +fi + +rm -f /tmp/checktime_h /tmp/checktime_h.c checktime_h.o + if [ "x$os" = "xOpenBSD" ] ; then cflags="-O2 -pipe -std=c99" elif [ "x$os" = "xFreeBSD" ] ; then @@ -270,7 +324,7 @@ elif [ "x$os" = "xAIX" ] ; then else os=`uname -s | cut -c 1-6` if [ "x$os" = "xCYGWIN" ] ; then - cflags="-O2 -pipe -std=c99 -D_GNU_SOURCE -DNEED_SYS_SIGNAME" + cflags="-O2 -pipe -std=c99 -D_GNU_SOURCE" else echo "Unknown operating system, please add the OS to this script" echo "and submit a pull request to https://github.com/ibara/make" @@ -279,7 +333,7 @@ else fi fi -cat << EOF > Makefile +cat << EOF > Makefile.tmp # This Makefile generated by configure. PREFIX= $prefix @@ -289,6 +343,7 @@ CC= $cc CFLAGS= $cflags $DSP CFLAGS+=-I. -DHAS_PATHS_H -DHAS_EXTENDED_GETCWD CFLAGS+=$DNA $DNF $DNP $DNR $DNS $DNSTN +CFLAGS+=$DNSN $DHT PROG= $prog OBJS= arch.o buf.o cmd_exec.o compat.o cond.o dir.o direxpand.o dump.o \\ @@ -298,7 +353,8 @@ OBJS= arch.o buf.o cmd_exec.o compat.o cond.o dir.o direxpand.o dump.o \\ varmodifiers.o varname.o \\ lstAddNew.o lstAppend.o lstConcat.o lstConcatDestroy.o lstDeQueue.o \\ lstDestroy.o lstDupl.o lstFindFrom.o lstForEachFrom.o lstInsert.o \\ - lstMember.o lstRemove.o lstReplace.o lstRequeue.o lstSucc.o + lstMember.o lstRemove.o lstReplace.o lstRequeue.o lstSucc.o \\ + arc4random.o arc4random_uniform.o GENOBJS=generate.o stats.o memory.o ohash.o portable.o @@ -359,3 +415,6 @@ clean: distclean: clean rm -f Makefile EOF + +mv -f Makefile.tmp Makefile +chmod a-w Makefile diff --git a/engine.c b/engine.c index d043822..46a1172 100644 --- a/engine.c +++ b/engine.c @@ -92,6 +92,7 @@ #include "buf.h" #include "job.h" #include "lowparse.h" +#include "arc4random-local.h" static void MakeTimeStamp(void *, void *); static int rewrite_time(const char *); diff --git a/job.c b/job.c index 3686a3a..313f516 100644 --- a/job.c +++ b/job.c @@ -108,6 +108,12 @@ #include "buf.h" #include "enginechoice.h" +#ifdef __linux__ +#ifndef WAIT_ANY +#define WAIT_ANY ((pid_t)-1) +#endif +#endif + static int aborting = 0; /* why is the make aborting? */ #define ABORT_ERROR 1 /* Because of an error */ #define ABORT_INTERRUPT 2 /* Because it was interrupted */ diff --git a/make.c b/make.c index 11e566c..cc1b7a1 100644 --- a/make.c +++ b/make.c @@ -82,6 +82,11 @@ #include "targequiv.h" #include "garray.h" #include "memory.h" +#include "arc4random-local.h" + +#ifdef HAS_TIME_H +#include +#endif /* what gets added each time. Kept as one static array so that it doesn't * get resized every time. diff --git a/ohash.h b/ohash.h index 66b07c9..cd2139d 100644 --- a/ohash.h +++ b/ohash.h @@ -23,6 +23,8 @@ #include #include +#include "cdefs-local.h" + /* Open hashing support. * Open hashing was chosen because it is much lighter than other hash * techniques, and more efficient in most cases. diff --git a/timestamp.c b/timestamp.c index ad1a282..ea531a3 100644 --- a/timestamp.c +++ b/timestamp.c @@ -31,6 +31,9 @@ #include "defines.h" #include "timestamp.h" +#ifdef HAS_TIME_H +#include +#endif struct timespec starttime;