xmss-KAT-generator/prg.c

79 lines
2.2 KiB
C
Raw Normal View History

/*
2016-02-10 14:57:16 +00:00
prg.c version 20151120
Andreas Hülsing
Public domain.
*/
2015-08-11 11:08:27 +01:00
#include "chacha.h"
#include "prg.h"
2015-08-12 16:59:29 +01:00
#include <stdio.h>
2015-10-28 14:49:46 +00:00
#include <openssl/sha.h>
#include <openssl/hmac.h>
#include <openssl/evp.h>
2015-08-11 11:08:27 +01:00
const unsigned char zero_nonce[12] = {0};
/**
* Generates rlen output bytes using ChaCha20 with a zero nonce and counter = 0
*/
void prg(unsigned char *r, unsigned long long rlen, const unsigned char *key, unsigned int key_len)
{
if (key_len == 32) {
2015-10-28 14:49:46 +00:00
CRYPTO_chacha_20_keystream(r, rlen, key, zero_nonce, 0);
}
else {
if (key_len == 64) {
2015-10-28 14:49:46 +00:00
unsigned long long left = rlen;
u_int32_t counter = 0;
unsigned char *c = (unsigned char*)&counter;
unsigned int length;
unsigned int i = 0;
2015-10-28 14:49:46 +00:00
unsigned char tmp[64];
while (left > 0) {
HMAC(EVP_sha512(), key, key_len, c , 4, tmp, &length);
if (length != 64) {
fprintf(stderr, "HMAC outputs %d bytes... That should not happen...", length);
}
for (i = 0; ((i < length) && (i < left)); i++) {
r[rlen-left+i] = tmp[i];
}
left -= length;
counter++;
2015-10-28 14:49:46 +00:00
}
}
else {
fprintf(stderr,"prg.c:: Code only supports 32 byte and 64 byte seeds");
}
}
2015-08-11 11:08:27 +01:00
}
/**
2015-10-28 14:49:46 +00:00
* Generates n output bytes using ChaCha20 (n=32) or HMAC-SHA2-512 (n=64).
*
2015-10-28 14:49:46 +00:00
* For ChaCha, nonce and counter are set depending on the address addr. For HMAC, addr is used as message.
2015-08-11 11:08:27 +01:00
*/
2015-10-28 14:49:46 +00:00
void prg_with_counter(unsigned char *r, const unsigned char *key, unsigned int n, const unsigned char addr[16])
2015-08-11 11:08:27 +01:00
{
int i;
unsigned char nonce[12];
if (n == 32) {
for (i = 0; i < 12; i++) {
2015-08-12 16:59:29 +01:00
nonce[i] = addr[i];
}
uint32_t counter;
counter = (((uint32_t)addr[12]) << 24) | (((uint32_t)addr[13]) << 16) | (((uint32_t)addr[14]) << 8) | addr[15];
2015-08-12 16:59:29 +01:00
// TODO: Check address handling. Endianess?
2015-10-28 14:49:46 +00:00
CRYPTO_chacha_20_keystream(r, n, key, nonce, counter);
}
else {
if (n == 64) {
2015-10-28 14:49:46 +00:00
unsigned int length;
HMAC(EVP_sha512(), key, n, addr, 16, r, &length);
if (length != 64) {
fprintf(stderr, "HMAC outputs %d bytes... That should not happen...", length);
2015-08-12 16:59:29 +01:00
}
}
else {
2015-08-12 16:59:29 +01:00
fprintf(stderr,"prg.c:: Code only supports 32 byte and 64 byte seeds");
}
2015-08-11 11:08:27 +01:00
}
}