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:
Justine Tunney 2021-06-24 12:31:26 -07:00
parent 1beeb7a829
commit cc1920749e
1032 changed files with 152673 additions and 69310 deletions

View file

@ -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;
}

View file

@ -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};

View file

@ -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};

View file

@ -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};

View file

@ -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);

View file

@ -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 \

View file

@ -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;
}

View file

@ -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};

View file

@ -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();
}

View file

@ -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;
}

View file

@ -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;
}