2019-06-22 17:17:07 +01:00
|
|
|
/// @file utils_prng.c
|
|
|
|
/// @brief The implementation of PRNG related functions.
|
|
|
|
///
|
|
|
|
|
2019-07-24 09:15:48 +01:00
|
|
|
#include "utils_prng.h"
|
2019-06-22 17:17:07 +01:00
|
|
|
#include "aes.h"
|
|
|
|
#include "randombytes.h"
|
|
|
|
#include "utils_hash.h"
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
static void prng_update(const unsigned char *provided_data,
|
|
|
|
unsigned char *Key,
|
|
|
|
unsigned char *V) {
|
2019-07-24 09:15:48 +01:00
|
|
|
unsigned char temp[48];
|
2019-06-22 17:17:07 +01:00
|
|
|
aes256ctx ctx;
|
|
|
|
aes256_keyexp(&ctx, Key);
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
|
|
//increment V
|
|
|
|
for (int j = 15; j >= 0; j--) {
|
2019-07-24 09:15:48 +01:00
|
|
|
if (V[j] == 0xff) {
|
2019-06-22 17:17:07 +01:00
|
|
|
V[j] = 0x00;
|
|
|
|
} else {
|
|
|
|
V[j]++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
aes256_ecb(temp + 16 * i, V, 1, &ctx);
|
|
|
|
}
|
2019-07-24 09:15:48 +01:00
|
|
|
if (provided_data != NULL) {
|
2019-06-22 17:17:07 +01:00
|
|
|
for (int i = 0; i < 48; i++) {
|
|
|
|
temp[i] ^= provided_data[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
memcpy(Key, temp, 32);
|
|
|
|
memcpy(V, temp + 32, 16);
|
|
|
|
}
|
|
|
|
static void randombytes_init_with_state(prng_t *state,
|
2019-07-24 09:15:48 +01:00
|
|
|
unsigned char *entropy_input_48bytes) {
|
2019-06-22 17:17:07 +01:00
|
|
|
memset(state->Key, 0x00, 32);
|
|
|
|
memset(state->V, 0x00, 16);
|
|
|
|
prng_update(entropy_input_48bytes, state->Key, state->V);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int randombytes_with_state(prng_t *state,
|
|
|
|
unsigned char *x,
|
|
|
|
size_t xlen) {
|
|
|
|
|
2019-07-24 09:15:48 +01:00
|
|
|
unsigned char block[16];
|
|
|
|
int i = 0;
|
2019-06-22 17:17:07 +01:00
|
|
|
|
|
|
|
aes256ctx ctx;
|
|
|
|
aes256_keyexp(&ctx, state->Key);
|
|
|
|
|
2019-07-24 09:15:48 +01:00
|
|
|
while (xlen > 0) {
|
2019-06-22 17:17:07 +01:00
|
|
|
//increment V
|
|
|
|
for (int j = 15; j >= 0; j--) {
|
2019-07-24 09:15:48 +01:00
|
|
|
if (state->V[j] == 0xff) {
|
2019-06-22 17:17:07 +01:00
|
|
|
state->V[j] = 0x00;
|
|
|
|
} else {
|
|
|
|
state->V[j]++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
aes256_ecb(block, state->V, 1, &ctx);
|
2019-07-24 09:15:48 +01:00
|
|
|
if (xlen > 15) {
|
2019-06-22 17:17:07 +01:00
|
|
|
memcpy(x + i, block, 16);
|
|
|
|
i += 16;
|
|
|
|
xlen -= 16;
|
|
|
|
} else {
|
|
|
|
memcpy(x + i, block, xlen);
|
|
|
|
xlen = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
prng_update(NULL, state->Key, state->V);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_prng_set(prng_t *ctx, const void *prng_seed, unsigned long prng_seedlen) {
|
|
|
|
unsigned char seed[48];
|
2019-07-24 09:15:48 +01:00
|
|
|
if (prng_seedlen >= 48) {
|
|
|
|
memcpy(seed, prng_seed, 48);
|
2019-06-22 17:17:07 +01:00
|
|
|
} else {
|
2019-07-24 09:15:48 +01:00
|
|
|
memcpy(seed, prng_seed, prng_seedlen);
|
|
|
|
PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_hash_msg(seed + prng_seedlen, 48 - (unsigned)prng_seedlen, (const unsigned char *)prng_seed, prng_seedlen);
|
2019-06-22 17:17:07 +01:00
|
|
|
}
|
|
|
|
|
2019-07-24 09:15:48 +01:00
|
|
|
randombytes_init_with_state(ctx, seed);
|
2019-06-22 17:17:07 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_prng_gen(prng_t *ctx, unsigned char *out, unsigned long outlen) {
|
2019-07-24 09:15:48 +01:00
|
|
|
return randombytes_with_state(ctx, out, outlen);
|
2019-06-22 17:17:07 +01:00
|
|
|
}
|