33232a0343
* Sebastian's HQC merge request * Clean up changes to common infrastructure * Fix Bitmask macro It assumed that ``unsigned long`` was 64 bit * Remove maxlen from nistseedexpander It's a complicated thing to handle because the value is larger than size_t supports on 32-bit platforms * Initialize buffers to help linter * Add Nistseedexpander test * Resolve UB in gf2x.c Some of the shifts could be larger than WORD_SIZE_BITS, ie. larger than the width of uint64_t. This apparently on Intel gets interpreted as the shift mod 64, but on ARM something else happened. * Fix Windows complaints * rename log, exp which appear to be existing functions on MS * Solve endianness problems * remove all spaces before ';' * Fix duplicate consistency * Fix duplicate consistency * Fix complaints by MSVC about narrowing int * Add nistseedexpander.obj to COMMON_OBJECTS_NOPATH * astyle format util.[ch] * add util.h to makefile * Sort includes in util.h * Fix more Windows MSVC complaints Co-authored-by: Sebastian Verschoor <sebastian@zeroknowledge.me> Co-authored-by: Thom Wiggers <thom@thomwiggers.nl>
105 lines
2.8 KiB
C
105 lines
2.8 KiB
C
//
|
|
// rng.c
|
|
//
|
|
// Created by Bassham, Lawrence E (Fed) on 8/29/17.
|
|
// Copyright © 2017 Bassham, Lawrence E (Fed). All rights reserved.
|
|
// Modified for liboqs by Douglas Stebila
|
|
//
|
|
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
|
|
#include "aes.h"
|
|
#include "randombytes.h"
|
|
|
|
typedef struct {
|
|
uint8_t Key[32];
|
|
uint8_t V[16];
|
|
int reseed_counter;
|
|
} AES256_CTR_DRBG_struct;
|
|
|
|
static AES256_CTR_DRBG_struct DRBG_ctx;
|
|
static void AES256_CTR_DRBG_Update(const uint8_t *provided_data, uint8_t *Key, uint8_t *V);
|
|
|
|
// Use whatever AES implementation you have. This uses AES from openSSL library
|
|
// key - 256-bit AES key
|
|
// ctr - a 128-bit plaintext value
|
|
// buffer - a 128-bit ciphertext value
|
|
static void AES256_ECB(uint8_t *key, uint8_t *ctr, uint8_t *buffer) {
|
|
aes256ctx ctx;
|
|
aes256_keyexp(&ctx, key);
|
|
aes256_ecb(buffer, ctr, 1, &ctx);
|
|
aes256_ctx_release(&ctx);
|
|
}
|
|
|
|
void nist_kat_init(uint8_t *entropy_input, const uint8_t *personalization_string, int security_strength);
|
|
void nist_kat_init(uint8_t *entropy_input, const uint8_t *personalization_string, int security_strength) {
|
|
uint8_t seed_material[48];
|
|
|
|
assert(security_strength == 256);
|
|
memcpy(seed_material, entropy_input, 48);
|
|
if (personalization_string) {
|
|
for (int i = 0; i < 48; i++) {
|
|
seed_material[i] ^= personalization_string[i];
|
|
}
|
|
}
|
|
memset(DRBG_ctx.Key, 0x00, 32);
|
|
memset(DRBG_ctx.V, 0x00, 16);
|
|
AES256_CTR_DRBG_Update(seed_material, DRBG_ctx.Key, DRBG_ctx.V);
|
|
DRBG_ctx.reseed_counter = 1;
|
|
}
|
|
|
|
int randombytes(uint8_t *buf, size_t n) {
|
|
uint8_t block[16];
|
|
int i = 0;
|
|
|
|
while (n > 0) {
|
|
//increment V
|
|
for (int j = 15; j >= 0; j--) {
|
|
if (DRBG_ctx.V[j] == 0xff) {
|
|
DRBG_ctx.V[j] = 0x00;
|
|
} else {
|
|
DRBG_ctx.V[j]++;
|
|
break;
|
|
}
|
|
}
|
|
AES256_ECB(DRBG_ctx.Key, DRBG_ctx.V, block);
|
|
if (n > 15) {
|
|
memcpy(buf + i, block, 16);
|
|
i += 16;
|
|
n -= 16;
|
|
} else {
|
|
memcpy(buf + i, block, n);
|
|
n = 0;
|
|
}
|
|
}
|
|
AES256_CTR_DRBG_Update(NULL, DRBG_ctx.Key, DRBG_ctx.V);
|
|
DRBG_ctx.reseed_counter++;
|
|
return 0;
|
|
}
|
|
|
|
static void AES256_CTR_DRBG_Update(const uint8_t *provided_data, uint8_t *Key, uint8_t *V) {
|
|
uint8_t temp[48];
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
//increment V
|
|
for (int j = 15; j >= 0; j--) {
|
|
if (V[j] == 0xff) {
|
|
V[j] = 0x00;
|
|
} else {
|
|
V[j]++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
AES256_ECB(Key, V, temp + 16 * i);
|
|
}
|
|
if (provided_data != NULL) {
|
|
for (int i = 0; i < 48; i++) {
|
|
temp[i] ^= provided_data[i];
|
|
}
|
|
}
|
|
memcpy(Key, temp, 32);
|
|
memcpy(V, temp + 32, 16);
|
|
}
|