mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-30 16:28:30 +00:00
Add SSL to redbean
Your redbean can now interoperate with clients that require TLS crypto. This is accomplished using a protocol polyglot that lets us distinguish between HTTP and HTTPS regardless of the port number. Certificates will be generated automatically, if none are supplied by the user. Footprint increases by only a few hundred kb so redbean in MODY=tiny is now 1.0mb - Add lseek() polyfills for ZIP executable - Automatically polyfill /tmp/FOO paths on NT - Fix readdir() / ftw() / nftw() bugs on Windows - Introduce -B flag for slower SSL that's stronger - Remove mbedtls features Cosmopolitan doesn't need - Have base64 decoder support the uri-safe alternative - Remove Truncated HMAC because it's forbidden by the IETF - Add all the mbedtls test suites and make them go 3x faster - Support opendir() / readdir() / closedir() on ZIP executable - Use Everest for ECDHE-ECDSA because it's so good it's so good - Add tinier implementation of sha1 since it's not worth the rom - Add chi-square monte-carlo mean correlation tests for getrandom() - Source entropy on Windows from the proper interface everyone uses We're continuing to outperform NGINX and other servers on raw message throughput. Using SSL means that instead of 1,000,000 qps you can get around 300,000 qps. However redbean isn't as fast as NGINX yet at SSL handshakes, since redbean can do 2,627 per second and NGINX does 4.3k Right now, the SSL UX story works best if you give your redbean a key signing key since that can be easily generated by openssl using a one liner then redbean will do all the things that are impossibly hard to do like signing ecdsa and rsa certificates that'll work in chrome. We should integrate the let's encrypt acme protocol in the future. Live Demo: https://redbean.justine.lol/ Root Cert: https://redbean.justine.lol/redbean1.crt
This commit is contained in:
parent
1beeb7a829
commit
cc1920749e
1032 changed files with 152673 additions and 69310 deletions
|
@ -1,53 +0,0 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or 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 "libc/bits/bits.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/consts/nr.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
||||
/**
|
||||
* Reads random bytes from system pseudo random number api.
|
||||
* @return 0 on success or -1 w/ errno
|
||||
*/
|
||||
int devrand(void *buf, size_t size) {
|
||||
int fd;
|
||||
size_t got;
|
||||
ssize_t rc;
|
||||
unsigned char *p, *pe;
|
||||
fd = -1;
|
||||
if (IsWindows()) return enosys();
|
||||
if ((fd = sys_openat(AT_FDCWD, "/dev/urandom", O_RDONLY, 0)) == -1) {
|
||||
return -1;
|
||||
}
|
||||
p = buf;
|
||||
pe = p + size;
|
||||
while (p < pe) {
|
||||
if ((rc = sys_read(fd, p, pe - p)) == -1) break;
|
||||
if (!(got = (size_t)rc)) break;
|
||||
p += got;
|
||||
}
|
||||
sys_close(fd);
|
||||
return p == pe ? 0 : -1;
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or 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 "libc/bits/bits.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/rand/xorshift.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
|
||||
hidden uint32_t g_rando32;
|
||||
|
||||
textstartup static void g_rando32_init() {
|
||||
intptr_t *auxvp;
|
||||
if (!IsXnu() && !IsWindows()) {
|
||||
asm("mov\t%%r15,%0" : "=r"(auxvp)); /* libc/crt/crt.S */
|
||||
for (; *auxvp; auxvp += 2) {
|
||||
if (*auxvp == AT_RANDOM) {
|
||||
uint8_t(*sysrandseed)[16] = (uint8_t(*)[16])auxvp[1];
|
||||
if (sysrandseed) g_rando32 ^= READ32LE(&(*sysrandseed)[8]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
g_rando32 ^= kMarsagliaXorshift32Seed;
|
||||
if (IsWindows()) {
|
||||
g_rando32 ^= winrandish();
|
||||
} else {
|
||||
devrand(&g_rando32, sizeof(g_rando32));
|
||||
}
|
||||
}
|
||||
|
||||
const void *const g_rando32_ctor[] initarray = {g_rando32_init};
|
|
@ -1,47 +0,0 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or 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 "libc/bits/bits.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/rand/xorshift.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
|
||||
hidden uint64_t g_rando64;
|
||||
|
||||
textstartup static void g_rando64_init() {
|
||||
intptr_t *auxvp;
|
||||
if (!IsXnu() && !IsWindows()) {
|
||||
asm("mov\t%%r15,%0" : "=r"(auxvp)); /* libc/crt/crt.S */
|
||||
for (; auxvp[0]; auxvp += 2) {
|
||||
if (auxvp[0] == AT_RANDOM) {
|
||||
uint8_t(*sysrandseed)[16] = (uint8_t(*)[16])auxvp[1];
|
||||
if (sysrandseed) g_rando64 ^= READ64LE(&(*sysrandseed)[0]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
g_rando64 ^= kMarsagliaXorshift64Seed;
|
||||
if (IsWindows()) {
|
||||
g_rando64 ^= winrandish();
|
||||
} else {
|
||||
devrand(&g_rando64, sizeof(g_rando64));
|
||||
}
|
||||
}
|
||||
|
||||
const void *const g_rando64_ctor[] initarray = {g_rando64_init};
|
|
@ -16,35 +16,196 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.internal.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/nexgen32e/kcpuids.h"
|
||||
#include "libc/nexgen32e/rdtsc.h"
|
||||
#include "libc/nexgen32e/vendor.internal.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/nexgen32e/x86info.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/rand/xorshift.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
#include "libc/sysv/consts/grnd.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static bool have_getrandom;
|
||||
|
||||
/**
|
||||
* Returns random bytes appropriate for random seeding.
|
||||
* Returns cryptographic random data.
|
||||
*
|
||||
* @param size should be the smallest value that meets your requirements
|
||||
* @param flags may be GRND_{RANDOM,NONBLOCK}
|
||||
* @return number of bytes copied on success; or -1 w/ errno, which
|
||||
* indicates only that the request couldn't be serviced by the host
|
||||
* kernel; this wrapper will still fill the buffer with random bytes
|
||||
* from fallback sources no matter what
|
||||
* This random number seed generator blends information from:
|
||||
*
|
||||
* - getrandom() on Linux
|
||||
* - getentropy() on XNU and OpenBSD
|
||||
* - sysctl(KERN_ARND) on FreeBSD and NetBSD
|
||||
* - RDSEED on Broadwell+ and Xen+ unless GRND_NORDRND
|
||||
* - RDRAND on Ivybridge+ and Xen+ unless GRND_NORDRND|GRND_RANDOM
|
||||
*
|
||||
* The following flags may be specified:
|
||||
*
|
||||
* - GRND_NORDRND: Don't source rando from hardware.
|
||||
* - GRND_NOSYSTEM: Don't source rando from operating system.
|
||||
* - GRND_RANDOM: Halt the entire system while I tap an entropy pool
|
||||
* so small that it's hard to use statistics to test if it's random
|
||||
* - GRND_NONBLOCK: Do not wait for i/o events or me to jiggle my
|
||||
* mouse, and instead return immediately the moment data isn't
|
||||
* available, even if the result needs to be -1 w/ EAGAIN
|
||||
*
|
||||
* This function is safe to use with fork() and vfork(). It will also
|
||||
* close any file descriptor it ends up needing before it returns.
|
||||
*
|
||||
* @asyncsignalsafe
|
||||
* @vforksafe
|
||||
*/
|
||||
ssize_t getrandom(void *buf, size_t size, unsigned flags) {
|
||||
ssize_t rc = sys_getrandom(buf, size, flags);
|
||||
size_t i = rc == -1 ? 0 : (size_t)rc;
|
||||
if (i > size) abort();
|
||||
if (i < size) {
|
||||
unsigned char *p = buf;
|
||||
int olderr = errno;
|
||||
do {
|
||||
uint64_t i64 = rand64();
|
||||
memcpy(&p[i], &i64, min(sizeof(i64), size - i));
|
||||
} while ((i += sizeof(uint64_t)) < size);
|
||||
errno = olderr;
|
||||
ssize_t getrandom(void *p, size_t n, unsigned f) {
|
||||
char cf;
|
||||
ssize_t rc;
|
||||
uint64_t x;
|
||||
size_t i, j, m;
|
||||
int fd, cmd[2];
|
||||
sigset_t neu, old;
|
||||
if (n > 256) n = 256;
|
||||
if (!IsTiny() &&
|
||||
(f & ~(GRND_RANDOM | GRND_NONBLOCK | GRND_NORDRND | GRND_NOSYSTEM))) {
|
||||
return einval();
|
||||
}
|
||||
if (!(f & GRND_NOSYSTEM)) {
|
||||
if (IsWindows()) {
|
||||
if (RtlGenRandom(p, n)) {
|
||||
rc = n;
|
||||
} else {
|
||||
return __winerr();
|
||||
}
|
||||
} else if (IsFreebsd() || IsNetbsd()) {
|
||||
if (IsFreebsd()) {
|
||||
cmd[0] = 1; /* CTL_KERN */
|
||||
cmd[1] = 37; /* KERN_ARND */
|
||||
} else {
|
||||
cmd[0] = 1; /* CTL_KERN */
|
||||
cmd[1] = 81; /* KERN_ARND */
|
||||
}
|
||||
m = n;
|
||||
if ((rc = sysctl(cmd, 2, p, &m, 0, 0)) != -1) {
|
||||
rc = m;
|
||||
}
|
||||
} else if (have_getrandom) {
|
||||
if ((rc = sys_getrandom(p, n, f & (GRND_RANDOM | GRND_NONBLOCK))) != -1) {
|
||||
if (!rc && (IsXnu() || IsOpenbsd())) {
|
||||
rc = n;
|
||||
}
|
||||
}
|
||||
} else if ((fd = __sys_openat(
|
||||
AT_FDCWD,
|
||||
(f & GRND_RANDOM) ? "/dev/random" : "/dev/urandom",
|
||||
O_RDONLY | ((f & GRND_NONBLOCK) ? O_NONBLOCK : 0), 0)) !=
|
||||
-1) {
|
||||
rc = sys_read(fd, p, n);
|
||||
sys_close(fd);
|
||||
} else {
|
||||
return enosys();
|
||||
}
|
||||
} else {
|
||||
memset(p, 0, n);
|
||||
rc = n;
|
||||
}
|
||||
if (rc != -1) {
|
||||
if (!IsTiny()) {
|
||||
if (rc < 0 || rc > n) {
|
||||
abort();
|
||||
}
|
||||
if (f & (GRND_RANDOM | GRND_NONBLOCK)) {
|
||||
if (n && !rc) {
|
||||
abort();
|
||||
}
|
||||
} else {
|
||||
if (rc != n) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!(f & GRND_NORDRND)) {
|
||||
if (X86_HAVE(RDSEED)) {
|
||||
for (i = j = 0; i < rc; ++j) {
|
||||
/* CF=1: Destination register valid. Quoth Intel DRNG-SIG 4.1.3 */
|
||||
asm volatile(CFLAG_ASM("rdseed\t%1")
|
||||
: CFLAG_CONSTRAINT(cf), "=r"(x)
|
||||
: /* no inputs */
|
||||
: "cc");
|
||||
if (cf) {
|
||||
j = 0;
|
||||
if (i + 8 <= rc) {
|
||||
x ^= READ64LE((char *)p + i);
|
||||
WRITE64LE((char *)p + i, x);
|
||||
i += 8;
|
||||
} else {
|
||||
for (; i < rc; x >>= 8) {
|
||||
((char *)p)[i++] ^= x;
|
||||
}
|
||||
}
|
||||
} else if (j == 10) {
|
||||
asm volatile("pause");
|
||||
}
|
||||
}
|
||||
rc = i;
|
||||
} else if (X86_HAVE(RDRND)) {
|
||||
for (i = j = 0; i < rc; ++j) {
|
||||
/* CF=1: Destination register valid. Quoth Intel DRNG-SIG 4.1.3 */
|
||||
asm volatile(CFLAG_ASM("rdrand\t%1")
|
||||
: CFLAG_CONSTRAINT(cf), "=r"(x)
|
||||
: /* no inputs */
|
||||
: "cc");
|
||||
if (cf) {
|
||||
j = 0;
|
||||
if (i + 8 <= rc) {
|
||||
x ^= READ64LE((char *)p + i);
|
||||
WRITE64LE((char *)p + i, x);
|
||||
i += 8;
|
||||
} else {
|
||||
for (; i < rc; x >>= 8) {
|
||||
((char *)p)[i++] ^= x;
|
||||
}
|
||||
}
|
||||
} else if (j == 10) {
|
||||
asm volatile("pause");
|
||||
}
|
||||
}
|
||||
rc = i;
|
||||
} else if (f & GRND_NOSYSTEM) {
|
||||
return enosys();
|
||||
}
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static textstartup void getrandom_init(int argc, char **argv, char **envp,
|
||||
intptr_t *auxv) {
|
||||
extern unsigned kMutableCpuids[KCPUIDS_LEN][4] asm("kCpuids");
|
||||
/*
|
||||
* Clear RDRAND on AMD models before Zen and then some
|
||||
* since it's not only slow but can freeze after sleep
|
||||
* https://bugzilla.redhat.com/show_bug.cgi?id=1150286
|
||||
*/
|
||||
if ((X86_HAVE(RDRND) || X86_HAVE(RDSEED)) &&
|
||||
(IsAuthenticAMD() &&
|
||||
(kX86CpuFamily < 0x17 ||
|
||||
(kX86CpuFamily == 0x17 &&
|
||||
(0x70 <= kX86CpuModel && kX86CpuModel <= 0x7F))))) {
|
||||
kMutableCpuids[KCPUIDS_1H][KCPUIDS_ECX] &= ~(1u << 30);
|
||||
kMutableCpuids[KCPUIDS_7H][KCPUIDS_EBX] &= ~(1u << 18);
|
||||
}
|
||||
if (sys_getrandom(0, 0, 0) == 0) {
|
||||
have_getrandom = true;
|
||||
}
|
||||
}
|
||||
|
||||
const void *const g_getrandom_init[] initarray = {getrandom_init};
|
||||
|
|
|
@ -6,12 +6,11 @@ COSMOPOLITAN_C_START_
|
|||
│ cosmopolitan § random ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
#define RAND_MAX __INT_MAX__ /* only applies to rand() */
|
||||
void srand(uint64_t) nothrow nocallback; /* seeds rand() only */
|
||||
int rand(void) nothrow nocallback; /* ≥0 unseeded lcg prng */
|
||||
uint32_t rand32(void) nothrow nocallback; /* random as possible rng */
|
||||
uint64_t rand64(void) nothrow nocallback; /* random as possible rng */
|
||||
double poz(double); /* verify our claims */
|
||||
#define RAND_MAX __INT_MAX__
|
||||
void srand(uint64_t) nothrow nocallback;
|
||||
int rand(void) nothrow nocallback;
|
||||
uint64_t rand64(void) nothrow nocallback;
|
||||
double poz(double);
|
||||
double pochisq(double, int);
|
||||
void rt_init(int);
|
||||
void rt_add(void *, int);
|
||||
|
@ -20,8 +19,6 @@ void *rngset(void *, size_t, uint64_t (*)(void), size_t) paramsnonnull();
|
|||
char *strfry(char *);
|
||||
int getentropy(void *, size_t);
|
||||
ssize_t getrandom(void *, size_t, unsigned);
|
||||
int devrand(void *, size_t);
|
||||
int64_t winrandish(void);
|
||||
uint64_t rdrand(void);
|
||||
uint64_t rdseed(void);
|
||||
float randf(void);
|
||||
|
|
|
@ -27,7 +27,7 @@ LIBC_RAND_A_DIRECTDEPS = \
|
|||
LIBC_CALLS \
|
||||
LIBC_INTRIN \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_NT_KERNEL32 \
|
||||
LIBC_NT_ADVAPI32 \
|
||||
LIBC_STR \
|
||||
LIBC_STUBS \
|
||||
LIBC_SYSV \
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or 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 "libc/dce.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/rand/xorshift.h"
|
||||
|
||||
hidden extern uint32_t g_rando32;
|
||||
|
||||
/**
|
||||
* This function is an independent 32-bit clone of rand64().
|
||||
*/
|
||||
nodebuginfo uint32_t(rand32)(void) {
|
||||
uint32_t res;
|
||||
if (X86_HAVE(RDRND)) {
|
||||
res = rdrand();
|
||||
} else {
|
||||
if (IsWindows()) {
|
||||
res = kMarsagliaXorshift32Seed ^ winrandish();
|
||||
} else {
|
||||
devrand(&res, sizeof(res));
|
||||
}
|
||||
res ^= MarsagliaXorshift32(&g_rando32);
|
||||
}
|
||||
return res;
|
||||
}
|
|
@ -16,34 +16,58 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/nexgen32e/rdtsc.h"
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/rand/xorshift.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
|
||||
hidden extern uint64_t g_rando64;
|
||||
static uint64_t thepool;
|
||||
|
||||
/**
|
||||
* Returns nondeterministic random number.
|
||||
* Returns nondeterministic random data.
|
||||
*
|
||||
* This function uses a good random source if it's available, which
|
||||
* takes ~400 cycles (~99ns). Otherwise it's seeded at program start
|
||||
* with the system provided random value and may perform a few
|
||||
* microseconds worth of system calls to get a good value.
|
||||
* This random number seed generator blends information from:
|
||||
*
|
||||
* @see rngset()
|
||||
* - rdtsc() hardware clock
|
||||
* - getpid() process identifier
|
||||
* - getauxval(AT_RANDOM) on Linux
|
||||
*
|
||||
* It's 100% guaranteed to not hard block the system.
|
||||
*
|
||||
* @see rngset(), getrandom()
|
||||
* @asyncsignalsafe
|
||||
* @vforksafe
|
||||
*/
|
||||
nodebuginfo uint64_t rand64(void) {
|
||||
uint64_t res;
|
||||
if (X86_HAVE(RDRND)) {
|
||||
res = rdrand();
|
||||
} else {
|
||||
if (IsWindows()) {
|
||||
res = winrandish();
|
||||
} else {
|
||||
devrand(&res, sizeof(res));
|
||||
}
|
||||
res ^= MarsagliaXorshift64(&g_rando64);
|
||||
}
|
||||
return res;
|
||||
uint64_t rand64(void) {
|
||||
register uint64_t t;
|
||||
t = thepool;
|
||||
t ^= getpid() * 11400714819643198487ull + 123456789123456789;
|
||||
t ^= t << 13;
|
||||
t ^= t >> 7;
|
||||
t ^= t << 17;
|
||||
t ^= rdtsc() * 11400714819643198487ull + 123456789123456789;
|
||||
t ^= t << 13;
|
||||
t ^= t >> 7;
|
||||
t ^= t << 17;
|
||||
thepool ^= t;
|
||||
return t;
|
||||
}
|
||||
|
||||
static textstartup void rand64_init(int argc, char **argv, char **envp,
|
||||
intptr_t *auxv) {
|
||||
uint64_t t;
|
||||
t = kStartTsc * 88172645463325252 + 123456789123456789;
|
||||
if (AT_RANDOM) {
|
||||
for (; auxv[0]; auxv += 2) {
|
||||
if (auxv[0] == AT_RANDOM) {
|
||||
t ^= READ64LE((const char *)auxv[1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
thepool = t;
|
||||
}
|
||||
|
||||
const void *const g_rand64_init[] initarray = {rand64_init};
|
||||
|
|
|
@ -16,31 +16,8 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/rand/rand.h"
|
||||
|
||||
/**
|
||||
* Intel Secure Key Digital Random Number Generator
|
||||
* Introduced w/ Ivy Bridge c. 2013 and Excavator c. 2015
|
||||
* @see rdseed(), rand32(), rand64(), and randcpy()
|
||||
*/
|
||||
uint64_t rdrand(void) {
|
||||
char cf;
|
||||
size_t i;
|
||||
uint64_t res;
|
||||
assert(X86_HAVE(RDRND));
|
||||
for (;;) {
|
||||
for (i = 0; i < 10; ++i) {
|
||||
/* CF=1: Destination register valid. Quoth Intel DRNG-SIG 4.1.3 */
|
||||
asm volatile(CFLAG_ASM("rdrand\t%1")
|
||||
: CFLAG_CONSTRAINT(cf), "=r"(res)
|
||||
: /* no inputs */
|
||||
: "cc");
|
||||
if (cf) return res;
|
||||
}
|
||||
asm volatile("rep nop"); /* unlikely 140 cycle spin */
|
||||
}
|
||||
return rand64();
|
||||
}
|
||||
|
|
|
@ -16,31 +16,17 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/sysv/consts/grnd.h"
|
||||
|
||||
/**
|
||||
* Intel Securer Key Digital Random Number Generator
|
||||
* Introduced w/ Ivy Bridge c. 2013 and Excavator c. 2015
|
||||
* @see rdrand(), rand32(), rand64(), and randcpy()
|
||||
*/
|
||||
uint64_t rdseed(void) {
|
||||
char cf;
|
||||
size_t i;
|
||||
uint64_t res;
|
||||
assert(X86_HAVE(RDSEED));
|
||||
for (;;) {
|
||||
for (i = 0; i < 10; ++i) {
|
||||
/* CF=1: Destination register valid. Quoth Intel DRNG-SIG 4.1.3 */
|
||||
asm volatile(CFLAG_ASM("rdseed\t%1")
|
||||
: CFLAG_CONSTRAINT(cf), "=r"(res)
|
||||
: /* no inputs */
|
||||
: "cc");
|
||||
if (cf) return res;
|
||||
}
|
||||
asm volatile("rep nop"); /* unlikely 140 cycle spin */
|
||||
register uint64_t x;
|
||||
volatile uint64_t b;
|
||||
if (getrandom(&b, 8, GRND_NONBLOCK | GRND_RANDOM) == 8) {
|
||||
x = b;
|
||||
b = 0;
|
||||
} else {
|
||||
x = (uint64_t)rand() << 62 | (uint64_t)rand() << 31 | rand();
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or 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 "libc/calls/calls.h"
|
||||
#include "libc/nexgen32e/rdtsc.h"
|
||||
#include "libc/nt/dll.h"
|
||||
#include "libc/nt/events.h"
|
||||
#include "libc/nt/struct/point.h"
|
||||
#include "libc/rand/rand.h"
|
||||
|
||||
/**
|
||||
* Returns somewhat randomish number on Windows.
|
||||
*/
|
||||
textwindows int64_t winrandish(void) {
|
||||
int64_t res;
|
||||
struct NtPoint point;
|
||||
res = ((int64_t)getpid() << 17) ^ gettid() ^ rdtsc();
|
||||
/*
|
||||
* This function is intended for older CPUs built before 2012, so
|
||||
* let's avoid having our CUI apps yoink USER32.DLL until we're
|
||||
* certain we need it, thus avoiding a hundred lines of noise in
|
||||
* NtTrace.exe output.
|
||||
*/
|
||||
typeof(GetCursorPos) *GetCursorPos_ =
|
||||
GetProcAddress(GetModuleHandle("user32.dll"), "GetCursorPos");
|
||||
if (GetCursorPos_ && GetCursorPos_(&point)) res ^= point.x * point.y;
|
||||
return res;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue