Compare commits
5 Commits
a9e6a5eb2f
...
main
Author | SHA1 | Date | |
---|---|---|---|
40520c3a9e | |||
f2aafd5070 | |||
3296fda329 | |||
95f8360c8a | |||
a6d132af39 |
83
chacha20.h
83
chacha20.h
@@ -20,7 +20,7 @@
|
|||||||
* - SLOWCRYPT_CHACHA20_IMPL
|
* - SLOWCRYPT_CHACHA20_IMPL
|
||||||
* - SLOWCRYPT_CHACHA20_FUNC
|
* - SLOWCRYPT_CHACHA20_FUNC
|
||||||
* will be used in front of every function definition / declaration
|
* will be used in front of every function definition / declaration
|
||||||
* - SLOWCRYPT_CHACHA20_UINT32
|
* - uint32_t
|
||||||
* if this is not set, will include <stdint.h>, and use `uint32_t`
|
* if this is not set, will include <stdint.h>, and use `uint32_t`
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
@@ -90,10 +90,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef SLOWCRYPT_CHACHA20_UINT32
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#define SLOWCRYPT_CHACHA20_UINT32 uint32_t
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef SLOWCRYPT_CHACHA20_FUNC
|
#ifndef SLOWCRYPT_CHACHA20_FUNC
|
||||||
#define SLOWCRYPT_CHACHA20_FUNC /**/
|
#define SLOWCRYPT_CHACHA20_FUNC /**/
|
||||||
@@ -101,7 +98,7 @@ extern "C" {
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
SLOWCRYPT_CHACHA20_UINT32 state[16];
|
uint32_t state[16];
|
||||||
} slowcrypt_chacha20;
|
} slowcrypt_chacha20;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -111,46 +108,36 @@ typedef struct
|
|||||||
*/
|
*/
|
||||||
SLOWCRYPT_CHACHA20_FUNC void slowcrypt_chacha20_block(
|
SLOWCRYPT_CHACHA20_FUNC void slowcrypt_chacha20_block(
|
||||||
slowcrypt_chacha20 state[2],
|
slowcrypt_chacha20 state[2],
|
||||||
char const key[32],
|
uint8_t const key[32],
|
||||||
SLOWCRYPT_CHACHA20_UINT32 block_ctr,
|
uint32_t block_ctr,
|
||||||
char const nonce[12],
|
uint8_t const nonce[12],
|
||||||
char data[64]);
|
uint8_t data[64]);
|
||||||
|
|
||||||
/* call this to zero out memory */
|
/* call this to zero out memory */
|
||||||
SLOWCRYPT_CHACHA20_FUNC void slowcrypt_chacha20_deinit(
|
SLOWCRYPT_CHACHA20_FUNC void slowcrypt_chacha20_deinit(
|
||||||
slowcrypt_chacha20* state);
|
slowcrypt_chacha20* state);
|
||||||
|
|
||||||
SLOWCRYPT_CHACHA20_FUNC void slowcrypt_chacha20_init(
|
SLOWCRYPT_CHACHA20_FUNC void slowcrypt_chacha20_init(slowcrypt_chacha20* state,
|
||||||
slowcrypt_chacha20* state,
|
uint8_t const key[32],
|
||||||
char const key[32],
|
uint32_t block_ctr,
|
||||||
SLOWCRYPT_CHACHA20_UINT32 block_ctr,
|
uint8_t const nonce[12]);
|
||||||
char const nonce[12]);
|
|
||||||
|
|
||||||
SLOWCRYPT_CHACHA20_FUNC void slowcrypt_chacha20_serialize(
|
SLOWCRYPT_CHACHA20_FUNC void slowcrypt_chacha20_serialize(
|
||||||
char buf[64],
|
uint8_t buf[64],
|
||||||
slowcrypt_chacha20 const* state);
|
slowcrypt_chacha20 const* state);
|
||||||
|
|
||||||
SLOWCRYPT_CHACHA20_FUNC void slowcrypt_chacha20_serialize_xor(
|
SLOWCRYPT_CHACHA20_FUNC void slowcrypt_chacha20_serialize_xor(
|
||||||
char buf[64],
|
uint8_t buf[64],
|
||||||
slowcrypt_chacha20 const* state);
|
slowcrypt_chacha20 const* state);
|
||||||
|
|
||||||
SLOWCRYPT_CHACHA20_FUNC void slowcrypt_chacha20_run(slowcrypt_chacha20* state,
|
SLOWCRYPT_CHACHA20_FUNC void slowcrypt_chacha20_run(slowcrypt_chacha20* state,
|
||||||
slowcrypt_chacha20* swap,
|
slowcrypt_chacha20* swap,
|
||||||
int num_rounds);
|
int num_rounds);
|
||||||
|
|
||||||
SLOWCRYPT_CHACHA20_FUNC SLOWCRYPT_CHACHA20_UINT32
|
#define SLOWCRYPT_CHACHA20_LAST32(n, bits) (((uint32_t)(n)) >> (32 - (bits)))
|
||||||
slowcrypt_chacha20_read_ul32(char const* buf);
|
|
||||||
|
|
||||||
SLOWCRYPT_CHACHA20_FUNC void slowcrypt_chacha20_write_ul32(
|
|
||||||
char* buf,
|
|
||||||
SLOWCRYPT_CHACHA20_UINT32 val);
|
|
||||||
|
|
||||||
#define SLOWCRYPT_CHACHA20_LAST32(n, bits) \
|
|
||||||
(((SLOWCRYPT_CHACHA20_UINT32)(n)) >> (32 - (bits)))
|
|
||||||
|
|
||||||
#define SLOWCRYPT_CHACHA20_ROL32(n, by) \
|
#define SLOWCRYPT_CHACHA20_ROL32(n, by) \
|
||||||
((((SLOWCRYPT_CHACHA20_UINT32)(n)) << (by)) | \
|
((((uint32_t)(n)) << (by)) | SLOWCRYPT_CHACHA20_LAST32((n), (by)))
|
||||||
SLOWCRYPT_CHACHA20_LAST32((n), (by)))
|
|
||||||
|
|
||||||
#define SLOWCRYPT_CHACHA20_QROUND(state, a, b, c, d) \
|
#define SLOWCRYPT_CHACHA20_QROUND(state, a, b, c, d) \
|
||||||
do { \
|
do { \
|
||||||
@@ -181,20 +168,16 @@ SLOWCRYPT_CHACHA20_FUNC void slowcrypt_chacha20_deinit(
|
|||||||
*(volatile int*)&state->state[i] = 0;
|
*(volatile int*)&state->state[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SLOWCRYPT_CHACHA20_FUNC SLOWCRYPT_CHACHA20_UINT32
|
static uint32_t slowcrypt_chacha20_read_ul32(uint8_t const* buf)
|
||||||
slowcrypt_chacha20_read_ul32(char const* buf)
|
|
||||||
{
|
{
|
||||||
SLOWCRYPT_CHACHA20_UINT32 o =
|
uint32_t o = (uint32_t)((uint8_t const*)buf)[0];
|
||||||
(SLOWCRYPT_CHACHA20_UINT32)((uint8_t const*)buf)[0];
|
o |= (uint32_t)((uint8_t const*)buf)[1] << 8;
|
||||||
o |= (SLOWCRYPT_CHACHA20_UINT32)((uint8_t const*)buf)[1] << 8;
|
o |= (uint32_t)((uint8_t const*)buf)[2] << 16;
|
||||||
o |= (SLOWCRYPT_CHACHA20_UINT32)((uint8_t const*)buf)[2] << 16;
|
o |= (uint32_t)((uint8_t const*)buf)[3] << 24;
|
||||||
o |= (SLOWCRYPT_CHACHA20_UINT32)((uint8_t const*)buf)[3] << 24;
|
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
SLOWCRYPT_CHACHA20_FUNC void slowcrypt_chacha20_write_ul32(
|
static void slowcrypt_chacha20_write_ul32(uint8_t* buf, uint32_t val)
|
||||||
char* buf,
|
|
||||||
SLOWCRYPT_CHACHA20_UINT32 val)
|
|
||||||
{
|
{
|
||||||
((uint8_t*)buf)[0] = (uint8_t)(val & 0xFF);
|
((uint8_t*)buf)[0] = (uint8_t)(val & 0xFF);
|
||||||
((uint8_t*)buf)[1] = (uint8_t)((val >> 8) & 0xFF);
|
((uint8_t*)buf)[1] = (uint8_t)((val >> 8) & 0xFF);
|
||||||
@@ -202,11 +185,10 @@ SLOWCRYPT_CHACHA20_FUNC void slowcrypt_chacha20_write_ul32(
|
|||||||
((uint8_t*)buf)[3] = (uint8_t)((val >> 24) & 0xFF);
|
((uint8_t*)buf)[3] = (uint8_t)((val >> 24) & 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
SLOWCRYPT_CHACHA20_FUNC void slowcrypt_chacha20_init(
|
SLOWCRYPT_CHACHA20_FUNC void slowcrypt_chacha20_init(slowcrypt_chacha20* state,
|
||||||
slowcrypt_chacha20* state,
|
uint8_t const key[32],
|
||||||
char const key[32],
|
uint32_t block_ctr,
|
||||||
SLOWCRYPT_CHACHA20_UINT32 block_ctr,
|
uint8_t const nonce[12])
|
||||||
char const nonce[12])
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@@ -225,7 +207,7 @@ SLOWCRYPT_CHACHA20_FUNC void slowcrypt_chacha20_init(
|
|||||||
}
|
}
|
||||||
|
|
||||||
SLOWCRYPT_CHACHA20_FUNC void slowcrypt_chacha20_serialize(
|
SLOWCRYPT_CHACHA20_FUNC void slowcrypt_chacha20_serialize(
|
||||||
char buf[64],
|
uint8_t buf[64],
|
||||||
slowcrypt_chacha20 const* state)
|
slowcrypt_chacha20 const* state)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -234,10 +216,10 @@ SLOWCRYPT_CHACHA20_FUNC void slowcrypt_chacha20_serialize(
|
|||||||
}
|
}
|
||||||
|
|
||||||
SLOWCRYPT_CHACHA20_FUNC void slowcrypt_chacha20_serialize_xor(
|
SLOWCRYPT_CHACHA20_FUNC void slowcrypt_chacha20_serialize_xor(
|
||||||
char buf[64],
|
uint8_t buf[64],
|
||||||
slowcrypt_chacha20 const* state)
|
slowcrypt_chacha20 const* state)
|
||||||
{
|
{
|
||||||
char swp[4];
|
uint8_t swp[4];
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
for (i = 0; i < 16; i++) {
|
for (i = 0; i < 16; i++) {
|
||||||
@@ -245,6 +227,9 @@ SLOWCRYPT_CHACHA20_FUNC void slowcrypt_chacha20_serialize_xor(
|
|||||||
for (j = 0; j < 4; j++)
|
for (j = 0; j < 4; j++)
|
||||||
buf[i * 4 + j] ^= swp[j];
|
buf[i * 4 + j] ^= swp[j];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
swp[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SLOWCRYPT_CHACHA20_FUNC void slowcrypt_chacha20_run(slowcrypt_chacha20* state,
|
SLOWCRYPT_CHACHA20_FUNC void slowcrypt_chacha20_run(slowcrypt_chacha20* state,
|
||||||
@@ -278,10 +263,10 @@ SLOWCRYPT_CHACHA20_FUNC void slowcrypt_chacha20_run(slowcrypt_chacha20* state,
|
|||||||
|
|
||||||
SLOWCRYPT_CHACHA20_FUNC void slowcrypt_chacha20_block(
|
SLOWCRYPT_CHACHA20_FUNC void slowcrypt_chacha20_block(
|
||||||
slowcrypt_chacha20 state[2],
|
slowcrypt_chacha20 state[2],
|
||||||
char const key[32],
|
uint8_t const key[32],
|
||||||
SLOWCRYPT_CHACHA20_UINT32 block_ctr,
|
uint32_t block_ctr,
|
||||||
char const nonce[12],
|
uint8_t const nonce[12],
|
||||||
char data[64])
|
uint8_t data[64])
|
||||||
{
|
{
|
||||||
slowcrypt_chacha20_init(state, key, block_ctr, nonce);
|
slowcrypt_chacha20_init(state, key, block_ctr, nonce);
|
||||||
slowcrypt_chacha20_run(state, &state[1], 20);
|
slowcrypt_chacha20_run(state, &state[1], 20);
|
||||||
|
179
poly1305.h
Normal file
179
poly1305.h
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
#ifndef SLOWCRYPT_POLY1305_H
|
||||||
|
#define SLOWCRYPT_POLY1305_H
|
||||||
|
|
||||||
|
#ifndef SLOWCRYPT_POLY1305_FUNC
|
||||||
|
#define SLOWCRYPT_POLY1305_FUNC /**/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SLOWCRYPT_POLY1305_DONT_USE_BITINT
|
||||||
|
#include <limits.h>
|
||||||
|
#ifdef BITINT_MAXWIDTH
|
||||||
|
#if BITINT_MAXWIDTH >= 264
|
||||||
|
#define SLOWCRYPT_POLY1305_USE_BITINT
|
||||||
|
#endif
|
||||||
|
#elif defined(__BITINT_MAXWIDTH__)
|
||||||
|
#if __BITINT_MAXWIDTH__ >= 264
|
||||||
|
#define SLOWCRYPT_POLY1305_USE_BITINT
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SLOWCRYPT_POLY1305_USE_BITINT
|
||||||
|
#else
|
||||||
|
ERROR NOT YET IMPLEMENTED;
|
||||||
|
#ifdef SLOWCRYPT_POLY1305_IMPL
|
||||||
|
#define BIGINT_IMPLEMENTATION
|
||||||
|
#endif
|
||||||
|
#define BIGINT_FUNC SLOWCRYPT_POLY1305_FUNC
|
||||||
|
#define BIGINT_NAMESPACE(x) slowcrypt_poly1305_bigint_##x
|
||||||
|
#define BIGINT_UNDEF
|
||||||
|
#define BIGINT_NO_MALLOC
|
||||||
|
#define BIGINT_DEFAULT_LIMIT 33
|
||||||
|
#define BIGINT_WORD_WIDTH 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
#ifdef SLOWCRYPT_POLY1305_USE_BITINT
|
||||||
|
unsigned _BitInt(128) r, s;
|
||||||
|
unsigned _BitInt(136) acc;
|
||||||
|
unsigned _BitInt(264) prod;
|
||||||
|
#else
|
||||||
|
slowcrypt_poly1305_bigint_bigint r, s, acc, p, temp1, temp2;
|
||||||
|
#endif
|
||||||
|
} slowcrypt_poly1305;
|
||||||
|
|
||||||
|
/* the key buffer will be destroyed: used as scratch buffer */
|
||||||
|
SLOWCRYPT_POLY1305_FUNC void slowcrypt_poly1305_init(slowcrypt_poly1305* p,
|
||||||
|
uint8_t key[32]);
|
||||||
|
|
||||||
|
/* only the last block is allowed to be shorter than 16 bytes!
|
||||||
|
*
|
||||||
|
* length has to be maximum 16
|
||||||
|
*/
|
||||||
|
SLOWCRYPT_POLY1305_FUNC void slowcrypt_poly1305_next_block(
|
||||||
|
slowcrypt_poly1305* p,
|
||||||
|
uint8_t const* data,
|
||||||
|
unsigned int length);
|
||||||
|
|
||||||
|
/* also zeroizes memory */
|
||||||
|
SLOWCRYPT_POLY1305_FUNC void slowcrypt_poly1305_finish(slowcrypt_poly1305* p,
|
||||||
|
uint8_t out[16]);
|
||||||
|
|
||||||
|
#ifdef SLOWCRYPT_POLY1305_IMPL
|
||||||
|
|
||||||
|
#ifdef SLOWCRYPT_POLY1305_USE_BITINT
|
||||||
|
|
||||||
|
static unsigned _BitInt(136) slowcrypt_poly1305_from_le(uint8_t const* buf,
|
||||||
|
unsigned int buf_len,
|
||||||
|
uint8_t top)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
unsigned _BitInt(136) out = (unsigned _BitInt(136))top << (buf_len * 8);
|
||||||
|
for (i = 0; i < buf_len; i++)
|
||||||
|
out |= (unsigned _BitInt(136))buf[i] << (i * 8);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
SLOWCRYPT_POLY1305_FUNC void slowcrypt_poly1305_init(slowcrypt_poly1305* p,
|
||||||
|
uint8_t key[32])
|
||||||
|
{
|
||||||
|
key[3] &= 15;
|
||||||
|
key[7] &= 15;
|
||||||
|
key[11] &= 15;
|
||||||
|
key[15] &= 15;
|
||||||
|
key[4] &= 252;
|
||||||
|
key[8] &= 252;
|
||||||
|
key[12] &= 252;
|
||||||
|
p->r = (unsigned _BitInt(128))slowcrypt_poly1305_from_le(key, 16, 0);
|
||||||
|
p->s = (unsigned _BitInt(128))slowcrypt_poly1305_from_le(&key[16], 16, 0);
|
||||||
|
p->acc = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SLOWCRYPT_POLY1305_FUNC void slowcrypt_poly1305_next_block(
|
||||||
|
slowcrypt_poly1305* p,
|
||||||
|
uint8_t const* data,
|
||||||
|
unsigned int length)
|
||||||
|
{
|
||||||
|
if (length == 0)
|
||||||
|
return;
|
||||||
|
p->prod = p->acc + slowcrypt_poly1305_from_le(data, length, 0x01);
|
||||||
|
p->prod *= p->r;
|
||||||
|
p->prod %= ((unsigned _BitInt(136))1 << 130) - (unsigned _BitInt(136))5;
|
||||||
|
p->acc = p->prod;
|
||||||
|
}
|
||||||
|
|
||||||
|
SLOWCRYPT_POLY1305_FUNC void slowcrypt_poly1305_finish(slowcrypt_poly1305* p,
|
||||||
|
uint8_t out[16])
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
p->acc += p->s;
|
||||||
|
for (i = 0; i < 16; i++)
|
||||||
|
out[i] = (uint8_t)((p->acc >> (i * 8)));
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(slowcrypt_poly1305); i++)
|
||||||
|
((char*)p)[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
static void slowcrypt_poly1305_from_le(slowcrypt_poly1305_bigint_bigint* out,
|
||||||
|
slowcrypt_poly1305_bigint_bigint* temp,
|
||||||
|
uint8_t const* buf,
|
||||||
|
unsigned int buf_len,
|
||||||
|
uint8_t top)
|
||||||
|
{
|
||||||
|
slowcrypt_poly1305_bigint_from_u8(temp, top);
|
||||||
|
for (; buf_len-- > 0; buf++) {
|
||||||
|
slowcrypt_poly1305_bigint_from_u8(temp, *buf);
|
||||||
|
slowcrypt_poly1305_bigint_lshift_overwrite(out, 8);
|
||||||
|
slowcrypt_poly1305_bigint_inc(out, temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SLOWCRYPT_POLY1305_FUNC void slowcrypt_poly1305_init(slowcrypt_poly1305* p,
|
||||||
|
uint8_t key[32])
|
||||||
|
{
|
||||||
|
(void)slowcrypt_poly1305_bigint_from_cstring(
|
||||||
|
&p->p, "3fffffffffffffffffffffffffffffffb", 16);
|
||||||
|
key[3] &= 15;
|
||||||
|
key[7] &= 15;
|
||||||
|
key[11] &= 15;
|
||||||
|
key[15] &= 15;
|
||||||
|
key[4] &= 252;
|
||||||
|
key[8] &= 252;
|
||||||
|
key[12] &= 252;
|
||||||
|
slowcrypt_poly1305_from_le(&p->r, &p->temp1, key, 16, 0);
|
||||||
|
slowcrypt_poly1305_from_le(&p->s, &p->temp1, &key[16], 16, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* only the last block is allowed to be shorter than 16 bytes! */
|
||||||
|
SLOWCRYPT_POLY1305_FUNC void slowcrypt_poly1305_next_block(
|
||||||
|
slowcrypt_poly1305* p,
|
||||||
|
uint8_t const* data,
|
||||||
|
unsigned int length)
|
||||||
|
{
|
||||||
|
if (length == 0)
|
||||||
|
return;
|
||||||
|
slowcrypt_poly1305_from_le(&p->temp1, &p->temp2, data, length, 0x01);
|
||||||
|
slowcrypt_poly1305_bigint_inc(&p->acc, &p->temp1);
|
||||||
|
slowcrypt_poly1305_bigint_mul(&p->acc, &p->acc, &p->r);
|
||||||
|
slowcrypt_poly1305_bigint_div_mod(&p->temp1, &p->acc, &p->acc, &p->p);
|
||||||
|
}
|
||||||
|
|
||||||
|
SLOWCRYPT_POLY1305_FUNC void slowcrypt_poly1305_finish(slowcrypt_poly1305* p,
|
||||||
|
uint8_t out[16])
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
slowcrypt_poly1305_bigint_inc(&p->acc, &p->s);
|
||||||
|
for (i = 0; i < 16; i++)
|
||||||
|
out[i] = p->acc.words[i];
|
||||||
|
for (i = 0; i < sizeof(slowcrypt_poly1305); i++)
|
||||||
|
((char*)p)[i] = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
448
slowcrypt/slowcrypt.c
Normal file
448
slowcrypt/slowcrypt.c
Normal file
@@ -0,0 +1,448 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define SLOWCRYPT_CHACHA20_IMPL
|
||||||
|
#include "../chacha20.h"
|
||||||
|
|
||||||
|
#define SLOWCRYPT_POLY1305_IMPL
|
||||||
|
#include "../poly1305.h"
|
||||||
|
|
||||||
|
#define SLOWCRYPT_SYSTEMRAND_IMPL
|
||||||
|
#include "../systemrand.h"
|
||||||
|
|
||||||
|
struct algo
|
||||||
|
{
|
||||||
|
char const* name;
|
||||||
|
void (*run)(char**);
|
||||||
|
};
|
||||||
|
|
||||||
|
static FILE* file_open(char const* path)
|
||||||
|
{
|
||||||
|
FILE* fp;
|
||||||
|
|
||||||
|
if (!strcmp(path, "-"))
|
||||||
|
return stdin;
|
||||||
|
|
||||||
|
fp = fopen(path, "rb");
|
||||||
|
if (!fp) {
|
||||||
|
fprintf(stderr, "Could not open %s\n", path);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return fp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void file_close(FILE* p)
|
||||||
|
{
|
||||||
|
if (!p)
|
||||||
|
return;
|
||||||
|
if (p == stdout || p == stdin || p == stderr)
|
||||||
|
return;
|
||||||
|
fclose(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int anyeq__impl(char const* str, char const** opts)
|
||||||
|
{
|
||||||
|
for (; *opts; opts++)
|
||||||
|
if (!strcmp(str, *opts))
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#define anyeq(str, ...) anyeq__impl(str, (char const*[]){__VA_ARGS__, 0})
|
||||||
|
|
||||||
|
static char const* parse_hex_prefix(char const* msg)
|
||||||
|
{
|
||||||
|
if (*msg == 'h')
|
||||||
|
msg++;
|
||||||
|
else if (msg[0] == '0' && msg[1] == 'x')
|
||||||
|
msg++;
|
||||||
|
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t parse_hex_nibble(char c)
|
||||||
|
{
|
||||||
|
if (c >= '0' && c <= '9')
|
||||||
|
return c - '0';
|
||||||
|
if (c >= 'a' && c <= 'f')
|
||||||
|
return c - 'a' + 0xA;
|
||||||
|
if (c >= 'A' && c <= 'F')
|
||||||
|
return c - 'A' + 0xA;
|
||||||
|
fprintf(stderr, "Not a hexadecimal number!\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t parse_hex(char const** msg)
|
||||||
|
{
|
||||||
|
uint8_t res = parse_hex_nibble(*(*msg)++);
|
||||||
|
if (**msg) {
|
||||||
|
res <<= 4;
|
||||||
|
res |= parse_hex_nibble(*(*msg)++);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void parse_hex2buf(uint8_t* buf,
|
||||||
|
unsigned int buflen,
|
||||||
|
char const* label,
|
||||||
|
char const* hex)
|
||||||
|
{
|
||||||
|
unsigned int num = 0;
|
||||||
|
hex = parse_hex_prefix(hex);
|
||||||
|
for (; num < buflen && *hex; num++)
|
||||||
|
buf[num] = parse_hex(&hex);
|
||||||
|
if (num != buflen || *hex) {
|
||||||
|
fprintf(stderr, "Expected %s to be %u (hexadecimal) bytes!\n", label,
|
||||||
|
buflen);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned long file_read_chunk(FILE* file,
|
||||||
|
uint8_t* buf,
|
||||||
|
unsigned long buflen)
|
||||||
|
{
|
||||||
|
unsigned long n;
|
||||||
|
if (feof(file))
|
||||||
|
return 0;
|
||||||
|
n = fread(buf, 1, buflen, file);
|
||||||
|
if (ferror(file)) {
|
||||||
|
fprintf(stderr, "File read error!");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void run_chacha20_core(char** args)
|
||||||
|
{
|
||||||
|
static char const help[] =
|
||||||
|
"chacha20-core <key> <counter> <nonce>\n"
|
||||||
|
"\n"
|
||||||
|
"Run the ChaCha20 block function\n";
|
||||||
|
char const *key, *nonce;
|
||||||
|
unsigned int npos = 0;
|
||||||
|
unsigned int nb;
|
||||||
|
unsigned long lu;
|
||||||
|
uint32_t counter;
|
||||||
|
slowcrypt_chacha20 state[2];
|
||||||
|
uint8_t buf[64];
|
||||||
|
uint8_t keyb[32];
|
||||||
|
uint8_t nonceb[12];
|
||||||
|
|
||||||
|
if (!*args) {
|
||||||
|
printf("%s", help);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; *args; args++) {
|
||||||
|
if (anyeq(*args, "-h", "-help", "--help")) {
|
||||||
|
printf("%s", help);
|
||||||
|
exit(0);
|
||||||
|
} else if (npos == 2 && ++npos) {
|
||||||
|
nonce = *args;
|
||||||
|
} else if (npos == 1 && ++npos) {
|
||||||
|
sscanf(*args, "%lu", &lu);
|
||||||
|
counter = lu;
|
||||||
|
} else if (npos == 0 && ++npos) {
|
||||||
|
key = *args;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Unexpected argument: %s\n", *args);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (npos != 3) {
|
||||||
|
fprintf(stderr, "Missing arguments!\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_hex2buf(keyb, 32, "key", key);
|
||||||
|
parse_hex2buf(nonceb, 12, "nonce", nonce);
|
||||||
|
|
||||||
|
slowcrypt_chacha20_init(state, keyb, counter, nonceb);
|
||||||
|
slowcrypt_chacha20_run(state, &state[1], 20);
|
||||||
|
slowcrypt_chacha20_serialize(buf, state);
|
||||||
|
|
||||||
|
for (nb = 0; nb < 64; nb++)
|
||||||
|
printf("%02x", buf[nb]);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void run_chacha20_crypt(char** args)
|
||||||
|
{
|
||||||
|
static char const help[] =
|
||||||
|
"chacha20 [--pad <padding>] [--init-counter <n>] [--full-chunks] <key> "
|
||||||
|
"<nonce> <file>\n"
|
||||||
|
"\n"
|
||||||
|
"Run the ChaCha20 en-/de- cryption algorithm on the given file, or "
|
||||||
|
"stdin, and output the result to stdout\n"
|
||||||
|
"\n"
|
||||||
|
"Defaults to padding with zeros, but can be overwritten with --pad <n>\n"
|
||||||
|
""
|
||||||
|
"Outputs only the number of input bytes from the last block. This "
|
||||||
|
"behaviour can be changed by passing --full-chunks\n";
|
||||||
|
char const *key, *nonce, *fpath = "-";
|
||||||
|
unsigned int npos = 0;
|
||||||
|
unsigned int nb, i;
|
||||||
|
unsigned long ul;
|
||||||
|
uint8_t pad = 0;
|
||||||
|
int full_chunks = 0;
|
||||||
|
uint32_t counter = 1;
|
||||||
|
slowcrypt_chacha20 state[2];
|
||||||
|
uint8_t buf[64];
|
||||||
|
uint8_t keyb[32];
|
||||||
|
uint8_t nonceb[12];
|
||||||
|
FILE* fp;
|
||||||
|
|
||||||
|
if (!*args) {
|
||||||
|
printf("%s", help);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; *args; args++) {
|
||||||
|
if (anyeq(*args, "-full-chunk", "--full-chunk", "-full-chunks",
|
||||||
|
"--full-chunks")) {
|
||||||
|
full_chunks = 1;
|
||||||
|
} else if (anyeq(*args, "-pad", "--pad", "--padding") && args[1]) {
|
||||||
|
args++;
|
||||||
|
pad = (uint8_t)atoi(*args);
|
||||||
|
} else if (anyeq(*args, "-init-counter", "-initial-counter",
|
||||||
|
"--initial-counter", "--init-counter") &&
|
||||||
|
args[1]) {
|
||||||
|
args++;
|
||||||
|
sscanf(*args, "%lu", &ul);
|
||||||
|
counter = ul;
|
||||||
|
} else if (anyeq(*args, "-h", "-help", "--help")) {
|
||||||
|
printf("%s", help);
|
||||||
|
exit(0);
|
||||||
|
} else if (npos == 2 && ++npos) {
|
||||||
|
fpath = *args;
|
||||||
|
} else if (npos == 1 && ++npos) {
|
||||||
|
nonce = *args;
|
||||||
|
} else if (npos == 0 && ++npos) {
|
||||||
|
key = *args;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Unexpected argument: %s\n", *args);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (npos < 2) {
|
||||||
|
fprintf(stderr, "Missing arguments!\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_hex2buf(keyb, 32, "key", key);
|
||||||
|
parse_hex2buf(nonceb, 12, "nonce", nonce);
|
||||||
|
|
||||||
|
fp = file_open(fpath);
|
||||||
|
|
||||||
|
for (; (nb = file_read_chunk(fp, buf, 64)); counter++) {
|
||||||
|
for (i = nb; i < 64; i++)
|
||||||
|
buf[i] = pad;
|
||||||
|
slowcrypt_chacha20_block(state, keyb, counter, nonceb, buf);
|
||||||
|
if (full_chunks)
|
||||||
|
nb = 64;
|
||||||
|
fwrite(buf, 1, nb, stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
file_close(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void run_chacha20_csprng(char** args)
|
||||||
|
{
|
||||||
|
static char const help[] =
|
||||||
|
"chacha20-csprng [--limit <num bytes>] [--init-counter <n>] [--key "
|
||||||
|
"<key>] "
|
||||||
|
"[--nonce <nonce>] \n"
|
||||||
|
"\n"
|
||||||
|
"Run the ChaCha20 function repeatedly, with incrementing counter, "
|
||||||
|
"(starting at the given initial counter, defaulting to 1),"
|
||||||
|
"writing the output to stdout.\n"
|
||||||
|
"\n"
|
||||||
|
"If no limit (in number of bytes) is given, will repeat forever.\n"
|
||||||
|
"\n"
|
||||||
|
"Both key and nonce will be generated randomly (using the highest "
|
||||||
|
"entropy random source available), unless overwritten\n";
|
||||||
|
char const* key = 0;
|
||||||
|
char const* nonce = 0;
|
||||||
|
unsigned long ul;
|
||||||
|
unsigned long limit = 0;
|
||||||
|
unsigned long nb, nwrb;
|
||||||
|
uint32_t counter = 1;
|
||||||
|
slowcrypt_chacha20 state[2];
|
||||||
|
uint8_t buf[64];
|
||||||
|
uint8_t keyb[32];
|
||||||
|
uint8_t nonceb[12];
|
||||||
|
|
||||||
|
for (; *args; args++) {
|
||||||
|
if (anyeq(*args, "-limit", "--limit") && args[1]) {
|
||||||
|
args++;
|
||||||
|
sscanf(*args, "%lu", &ul);
|
||||||
|
limit = ul;
|
||||||
|
} else if (anyeq(*args, "-init-counter", "-initial-counter",
|
||||||
|
"--initial-counter", "--init-counter") &&
|
||||||
|
args[1]) {
|
||||||
|
args++;
|
||||||
|
sscanf(*args, "%lu", &ul);
|
||||||
|
counter = ul;
|
||||||
|
} else if (anyeq(*args, "-h", "-help", "--help")) {
|
||||||
|
printf("%s", help);
|
||||||
|
exit(0);
|
||||||
|
} else if (anyeq(*args, "-key", "--key")) {
|
||||||
|
args++;
|
||||||
|
key = *args;
|
||||||
|
} else if (anyeq(*args, "-nonce", "--nonce")) {
|
||||||
|
args++;
|
||||||
|
nonce = *args;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Unexpected argument: %s\n", *args);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key) {
|
||||||
|
parse_hex2buf(keyb, 32, "key", key);
|
||||||
|
} else {
|
||||||
|
slowcrypt_systemrand(keyb, 32, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nonce) {
|
||||||
|
parse_hex2buf(nonceb, 12, "nonce", nonce);
|
||||||
|
} else {
|
||||||
|
slowcrypt_systemrand(keyb, 12, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!limit) {
|
||||||
|
for (;; counter++) {
|
||||||
|
slowcrypt_chacha20_init(state, keyb, counter, nonceb);
|
||||||
|
slowcrypt_chacha20_run(state, &state[1], 20);
|
||||||
|
slowcrypt_chacha20_serialize(buf, state);
|
||||||
|
fwrite(buf, 1, 64, stdout);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (nb = 0; nb < limit; (nb += 64, counter++)) {
|
||||||
|
nwrb = limit - nb;
|
||||||
|
if (nwrb > 64)
|
||||||
|
nwrb = 64;
|
||||||
|
slowcrypt_chacha20_init(state, keyb, counter, nonceb);
|
||||||
|
slowcrypt_chacha20_run(state, &state[1], 20);
|
||||||
|
slowcrypt_chacha20_serialize(buf, state);
|
||||||
|
fwrite(buf, 1, nwrb, stdout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void run_poly1305(char** args)
|
||||||
|
{
|
||||||
|
static char const help[] =
|
||||||
|
"poly1305 [--key] <hex-key> [file]\n"
|
||||||
|
"\n"
|
||||||
|
"Run the Poly1305 one-time authenticator on the data from the given file "
|
||||||
|
"or stdin\n";
|
||||||
|
char const* key = 0;
|
||||||
|
char const* fpath = "-";
|
||||||
|
FILE* fp;
|
||||||
|
unsigned int npos = 0;
|
||||||
|
uint8_t keybuf[32];
|
||||||
|
uint8_t chunk[16];
|
||||||
|
slowcrypt_poly1305 poly1305;
|
||||||
|
unsigned int nb;
|
||||||
|
|
||||||
|
if (!*args) {
|
||||||
|
printf("%s", help);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; *args; args++) {
|
||||||
|
if (!key && anyeq(*args, "-k", "-key", "--key") && args[1]) {
|
||||||
|
args++;
|
||||||
|
key = *args;
|
||||||
|
} else if (anyeq(*args, "-h", "-help", "--help")) {
|
||||||
|
printf("%s", help);
|
||||||
|
exit(0);
|
||||||
|
} else if (npos == 1 && ++npos) {
|
||||||
|
fpath = *args;
|
||||||
|
} else if (npos == 0 && ++npos && !key) {
|
||||||
|
key = *args;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Unexpected argument: %s\n", *args);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!key) {
|
||||||
|
fprintf(stderr, "Missing argument: [--key] <hex-key>");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fp = file_open(fpath);
|
||||||
|
|
||||||
|
parse_hex2buf(keybuf, 32, "key", key);
|
||||||
|
slowcrypt_poly1305_init(&poly1305, keybuf);
|
||||||
|
|
||||||
|
while ((nb = file_read_chunk(fp, chunk, 16))) {
|
||||||
|
slowcrypt_poly1305_next_block(&poly1305, chunk, nb);
|
||||||
|
}
|
||||||
|
slowcrypt_poly1305_finish(&poly1305, chunk);
|
||||||
|
|
||||||
|
for (nb = 0; nb < 16; nb++)
|
||||||
|
printf("%02x", chunk[nb]);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
file_close(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct algo bytes2scalar[] = {{"poly1305", run_poly1305},
|
||||||
|
{"chacha20-core", run_chacha20_core},
|
||||||
|
{0, 0}};
|
||||||
|
|
||||||
|
static struct algo bytes2bytes[] = {{"chacha20", run_chacha20_crypt}, {0, 0}};
|
||||||
|
|
||||||
|
static struct algo scalar2bytes[] = {{"chacha20-csprng", run_chacha20_csprng},
|
||||||
|
{0, 0}};
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
struct algo* a;
|
||||||
|
(void)argc;
|
||||||
|
argv++;
|
||||||
|
|
||||||
|
if (!*argv || anyeq(*argv, "-h", "-help", "--help")) {
|
||||||
|
printf("bytes -> scalar\n");
|
||||||
|
for (a = bytes2scalar; a->name; a++)
|
||||||
|
printf(" %s\n", a->name);
|
||||||
|
printf("\nbytes -> bytes\n");
|
||||||
|
for (a = bytes2bytes; a->name; a++)
|
||||||
|
printf(" %s\n", a->name);
|
||||||
|
printf("\nscalar -> bytes\n");
|
||||||
|
for (a = scalar2bytes; a->name; a++)
|
||||||
|
printf(" %s\n", a->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (a = bytes2scalar; a->name; a++) {
|
||||||
|
if (!strcmp(a->name, *argv)) {
|
||||||
|
a->run(argv + 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (a = bytes2bytes; a->name; a++) {
|
||||||
|
if (!strcmp(a->name, *argv)) {
|
||||||
|
a->run(argv + 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (a = scalar2bytes; a->name; a++) {
|
||||||
|
if (!strcmp(a->name, *argv)) {
|
||||||
|
a->run(argv + 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Unknown algorithm %s\n", *argv);
|
||||||
|
return 1;
|
||||||
|
}
|
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