WIP systemrand.h
This commit is contained in:
175
systemrand.h
Normal file
175
systemrand.h
Normal file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Alexander Nutz
|
||||
* MIT licensed, see below documentation
|
||||
*
|
||||
* Latest version can be found at:
|
||||
* https://gitea.vxcc.dev/alexander.nutz/slow-libs
|
||||
*
|
||||
* ======== High-entropy system RNG =========
|
||||
*
|
||||
* Configuration options:
|
||||
* - SLOWCRYPT_SYSTEMRAND_IMPL
|
||||
* - SLOWCRYPT_SYSTEMRAND_FUNC
|
||||
* will be used in front of every function definition / declaration
|
||||
*
|
||||
* Tries these sources (depending on platform support), in order:
|
||||
* - getentropy()
|
||||
* - getrandom()
|
||||
* - unless _WIN32 is defined, read from /dev/random or /dev/urandom
|
||||
* - on _WIN32, try BCryptGenRandom
|
||||
* - on _WIN32, CryptGenRandom
|
||||
* - on _WIN32, RtlGenRandom
|
||||
* - random(), unless bail on insecure
|
||||
* - rand(), unless bail on insecure
|
||||
*
|
||||
* As with all slow-libs, a wide range of supported platforms is a priority,
|
||||
* so please report any incompatibility issues.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2025 Alexander Nutz
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef SLOWCRYPT_SYSTEMRAND_H
|
||||
#define SLOWCRYPT_SYSTEMRAND_H
|
||||
|
||||
#ifndef SLOWCRYPT_SYSTEMRAND_FUNC
|
||||
#define SLOWCRYPT_SYSTEMRAND_FUNC /**/
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SLOWCRYPT_SYSTEMRAND__BAIL_IF_INSECURE = 1 << 0,
|
||||
SLOWCRYPT_SYSTEMRAND__INSECURE_NON_BLOCKING = 1 << 1
|
||||
} slowcrypt_systemrand_flags;
|
||||
|
||||
/*
|
||||
* Return codes:
|
||||
* - 0: success
|
||||
* - 1: unexpected error
|
||||
* - 2: random number is not secure enough. Only returned with BAIL_IF_INSECURE
|
||||
*/
|
||||
SLOWCRYPT_SYSTEMRAND_FUNC int slowcrypt_systemrand(
|
||||
void* buffer,
|
||||
unsigned long length,
|
||||
slowcrypt_systemrand_flags flags);
|
||||
|
||||
#ifdef SLOWCRYPT_SYSTEMRAND_IMPL
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define SLOWCRYPT_SYSTEMRAND_UNDEF_GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef unix
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef SLOWCRYPT_SYSTEMRAND_UNDEF_GNU_SOURCE
|
||||
#undef SLOWCRYPT_SYSTEMRAND_UNDEF_GNU_SOURCE
|
||||
#undef _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
static int slowcrypt_systemrand__chunk256(void* buffer,
|
||||
unsigned long length,
|
||||
slowcrypt_systemrand_flags flags)
|
||||
{
|
||||
unsigned long i, j;
|
||||
unsigned char u8;
|
||||
char const* fpath;
|
||||
FILE* fp;
|
||||
|
||||
#if defined(unix) && defined(__GLIBC__) && \
|
||||
(__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25))
|
||||
|
||||
if (getentropy(buffer, length)) {
|
||||
if (errno != ENOSYS) {
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* TODO: getrandom (on glibc, freebsd, and probably others) */
|
||||
|
||||
#ifndef _WIN32
|
||||
fpath = (flags & SLOWCRYPT_SYSTEMRAND__INSECURE_NON_BLOCKING) ? "/dev/urandom"
|
||||
: "/dev/random";
|
||||
|
||||
fp = fopen(fpath, "rb");
|
||||
if (fp) {
|
||||
i = fread(buffer, 1, length, fp);
|
||||
fclose(fp);
|
||||
if (i == length)
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* TODO: windows stuff */
|
||||
|
||||
if (flags & SLOWCRYPT_SYSTEMRAND__BAIL_IF_INSECURE)
|
||||
return 2;
|
||||
|
||||
/* TODO: random() */
|
||||
|
||||
if (RAND_MAX >= 255) {
|
||||
for (i = 0; i < length; i++) {
|
||||
((unsigned char*)buffer)[i] =
|
||||
(unsigned char)((unsigned int)rand() / (unsigned int)(RAND_MAX));
|
||||
}
|
||||
} else {
|
||||
/* why would this ever happen... */
|
||||
for (i = 0; i < length; i++) {
|
||||
u8 = 0;
|
||||
for (j = 0; j < 8; j++) {
|
||||
u8 <<= 1;
|
||||
u8 ^= (unsigned char)rand();
|
||||
}
|
||||
((unsigned char*)buffer)[i] = u8;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
SLOWCRYPT_SYSTEMRAND_FUNC int slowcrypt_systemrand(
|
||||
void* buffer,
|
||||
unsigned long length,
|
||||
slowcrypt_systemrand_flags flags)
|
||||
{
|
||||
unsigned int i, j;
|
||||
int rc;
|
||||
|
||||
/* many random sources have a limit of 256 bytes */
|
||||
for (i = 0; i < length; i += 256) {
|
||||
j = length - i;
|
||||
if (j > 256)
|
||||
j = 256;
|
||||
if ((rc = slowcrypt_systemrand__chunk256(buffer, length, flags))) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user