@@ -7,6 +7,7 @@ Public domain. | |||||
#include "hash_address.h" | #include "hash_address.h" | ||||
#include "xmss_commons.h" | #include "xmss_commons.h" | ||||
#include "hash.h" | |||||
#include <stddef.h> | #include <stddef.h> | ||||
#include <stdint.h> | #include <stdint.h> | ||||
@@ -16,6 +17,17 @@ Public domain. | |||||
#include <openssl/hmac.h> | #include <openssl/hmac.h> | ||||
#include <openssl/evp.h> | #include <openssl/evp.h> | ||||
unsigned char* addr_to_byte(unsigned char *bytes, const uint32_t addr[8]){ | |||||
#if IS_LITTLE_ENDIAN==1 | |||||
int i = 0; | |||||
for(i=0;i<8;i++) | |||||
to_byte(bytes+i*4, addr[i],4); | |||||
return bytes; | |||||
#else | |||||
memcpy(bytes, addr, 32); | |||||
return bytes; | |||||
#endif | |||||
} | |||||
int core_hash_SHA2(unsigned char *out, const unsigned int type, const unsigned char *key, unsigned int keylen, const unsigned char *in, unsigned long long inlen, unsigned int n){ | int core_hash_SHA2(unsigned char *out, const unsigned int type, const unsigned char *key, unsigned int keylen, const unsigned char *in, unsigned long long inlen, unsigned int n){ | ||||
unsigned long long i = 0; | unsigned long long i = 0; | ||||
@@ -51,9 +63,8 @@ int core_hash_SHA2(unsigned char *out, const unsigned int type, const unsigned c | |||||
* Implements PRF | * Implements PRF | ||||
*/ | */ | ||||
int prf(unsigned char *out, const unsigned char *in, const unsigned char *key, unsigned int keylen) | int prf(unsigned char *out, const unsigned char *in, const unsigned char *key, unsigned int keylen) | ||||
{ | |||||
size_t inlen = 32; | |||||
return core_hash_SHA2(out, 3, key, keylen, in, inlen, keylen); | |||||
{ | |||||
return core_hash_SHA2(out, 3, key, keylen, in, 32, keylen); | |||||
} | } | ||||
/* | /* | ||||
@@ -77,15 +88,19 @@ int hash_h(unsigned char *out, const unsigned char *in, const unsigned char *pub | |||||
unsigned char buf[2*n]; | unsigned char buf[2*n]; | ||||
unsigned char key[n]; | unsigned char key[n]; | ||||
unsigned char bitmask[2*n]; | unsigned char bitmask[2*n]; | ||||
unsigned char byte_addr[32]; | |||||
unsigned int i; | unsigned int i; | ||||
setKeyAndMask(addr, 0); | setKeyAndMask(addr, 0); | ||||
prf(key, (unsigned char *)addr, pub_seed, n); | |||||
addr_to_byte(byte_addr, addr); | |||||
prf(key, byte_addr, pub_seed, n); | |||||
// Use MSB order | // Use MSB order | ||||
setKeyAndMask(addr, 1); | setKeyAndMask(addr, 1); | ||||
prf(bitmask, (unsigned char *)addr, pub_seed, n); | |||||
addr_to_byte(byte_addr, addr); | |||||
prf(bitmask, byte_addr, pub_seed, n); | |||||
setKeyAndMask(addr, 2); | setKeyAndMask(addr, 2); | ||||
prf(bitmask+n, (unsigned char *)addr, pub_seed, n); | |||||
addr_to_byte(byte_addr, addr); | |||||
prf(bitmask+n, byte_addr, pub_seed, n); | |||||
for (i = 0; i < 2*n; i++) { | for (i = 0; i < 2*n; i++) { | ||||
buf[i] = in[i] ^ bitmask[i]; | buf[i] = in[i] ^ bitmask[i]; | ||||
} | } | ||||
@@ -97,13 +112,23 @@ int hash_f(unsigned char *out, const unsigned char *in, const unsigned char *pub | |||||
unsigned char buf[n]; | unsigned char buf[n]; | ||||
unsigned char key[n]; | unsigned char key[n]; | ||||
unsigned char bitmask[n]; | unsigned char bitmask[n]; | ||||
unsigned char byte_addr[32]; | |||||
unsigned int i; | unsigned int i; | ||||
setKeyAndMask(addr, 0); | setKeyAndMask(addr, 0); | ||||
prf(key, (unsigned char *)addr, pub_seed, n); | |||||
printf("\naddr before: "); | |||||
for(i = 0; i< 8; i++){ | |||||
printf("%08x",addr[i]); | |||||
} | |||||
addr_to_byte(byte_addr, addr); | |||||
printf("\naddr after: "); | |||||
hexdump(byte_addr,32); | |||||
printf("\n"); | |||||
prf(key, byte_addr, pub_seed, n); | |||||
// Use MSB order | // Use MSB order | ||||
setKeyAndMask(addr, 1); | setKeyAndMask(addr, 1); | ||||
prf(bitmask, (unsigned char *)addr, pub_seed, n); | |||||
addr_to_byte(byte_addr, addr); | |||||
prf(bitmask, byte_addr, pub_seed, n); | |||||
for (i = 0; i < n; i++) { | for (i = 0; i < n; i++) { | ||||
buf[i] = in[i] ^ bitmask[i]; | buf[i] = in[i] ^ bitmask[i]; | ||||
@@ -8,8 +8,11 @@ Public domain. | |||||
#ifndef HASH_H | #ifndef HASH_H | ||||
#define HASH_H | #define HASH_H | ||||
int prf(unsigned char *out, const unsigned char *in, const unsigned char *key, int keylen); | |||||
int h_msg(unsigned char *out,const unsigned char *in,unsigned long long inlen, const unsigned char *key, const int keylen, const int n); | |||||
#define IS_LITTLE_ENDIAN 1 | |||||
unsigned char* addr_to_byte(unsigned char *bytes, const uint32_t addr[8]); | |||||
int prf(unsigned char *out, const unsigned char *in, const unsigned char *key, unsigned int keylen); | |||||
int h_msg(unsigned char *out,const unsigned char *in,unsigned long long inlen, const unsigned char *key, const unsigned int keylen, const unsigned int n); | |||||
int hash_h(unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, uint32_t addr[8], const unsigned int n); | int hash_h(unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, uint32_t addr[8], const unsigned int n); | ||||
int hash_f(unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, uint32_t addr[8], const unsigned int n); | int hash_f(unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, uint32_t addr[8], const unsigned int n); | ||||
@@ -1,80 +0,0 @@ | |||||
/* | |||||
prg.c version 20160217 | |||||
Andreas Hülsing | |||||
Joost Rijneveld | |||||
Public domain. | |||||
*/ | |||||
#include "chacha.h" | |||||
#include "prg.h" | |||||
#include <stdio.h> | |||||
#include <openssl/sha.h> | |||||
#include <openssl/hmac.h> | |||||
#include <openssl/evp.h> | |||||
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) { | |||||
CRYPTO_chacha_20_keystream(r, rlen, key, zero_nonce, 0); | |||||
} | |||||
else { | |||||
if (key_len == 64) { | |||||
unsigned long long left = rlen; | |||||
u_int32_t counter = 0; | |||||
unsigned char *c = (unsigned char*)&counter; | |||||
unsigned int length; | |||||
unsigned int i = 0; | |||||
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++; | |||||
} | |||||
} | |||||
else { | |||||
fprintf(stderr,"prg.c:: Code only supports 32 byte and 64 byte seeds"); | |||||
} | |||||
} | |||||
} | |||||
/** | |||||
* Generates n output bytes using ChaCha20 (n=32) or HMAC-SHA2-512 (n=64). | |||||
* | |||||
* For ChaCha, nonce and counter are set depending on the address addr. For HMAC, addr is used as message. | |||||
*/ | |||||
void prg_with_counter(unsigned char *r, const unsigned char *key, unsigned int n, const unsigned char addr[16]) | |||||
{ | |||||
int i; | |||||
unsigned char nonce[12]; | |||||
if (n == 32) { | |||||
for (i = 0; i < 12; i++) { | |||||
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]; | |||||
// TODO: Check address handling. Endianess? | |||||
CRYPTO_chacha_20_keystream(r, n, key, nonce, counter); | |||||
} | |||||
else { | |||||
if (n == 64) { | |||||
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); | |||||
} | |||||
} | |||||
else { | |||||
fprintf(stderr,"prg.c:: Code only supports 32 byte and 64 byte seeds"); | |||||
} | |||||
} | |||||
} |
@@ -1,23 +0,0 @@ | |||||
/* | |||||
prg.h version 20160217 | |||||
Andreas Hülsing | |||||
Joost Rijneveld | |||||
Public domain. | |||||
*/ | |||||
#ifndef PRG_H | |||||
#define PRG_H | |||||
#include <stdlib.h> | |||||
/** | |||||
* Generates rlen output bytes using key_len-byte key and places them in r. | |||||
* | |||||
*/ | |||||
void prg(unsigned char *r, unsigned long long rlen, const unsigned char *key, unsigned int key_len); | |||||
/** | |||||
* Generates n output bytes using n-byte key and hash address addr and places them in r. | |||||
* | |||||
*/ | |||||
void prg_with_counter(unsigned char *r, const unsigned char *key, unsigned int n, const unsigned char addr[16]); | |||||
#endif |
@@ -30,12 +30,14 @@ Public domain. | |||||
*/ | */ | ||||
static void get_seed(unsigned char *seed, const unsigned char *sk_seed, int n, uint32_t addr[8]) | static void get_seed(unsigned char *seed, const unsigned char *sk_seed, int n, uint32_t addr[8]) | ||||
{ | { | ||||
unsigned char bytes[32]; | |||||
// Make sure that chain addr, hash addr, and key bit are 0! | // Make sure that chain addr, hash addr, and key bit are 0! | ||||
setChainADRS(addr,0); | setChainADRS(addr,0); | ||||
setHashADRS(addr,0); | setHashADRS(addr,0); | ||||
setKeyAndMask(addr,0); | setKeyAndMask(addr,0); | ||||
// Generate pseudorandom value | // Generate pseudorandom value | ||||
prf(seed, (unsigned char*) addr, sk_seed, n); | |||||
addr_to_byte(bytes, addr); | |||||
prf(seed, bytes, sk_seed, n); | |||||
} | } | ||||
/** | /** | ||||
@@ -360,7 +362,7 @@ int xmss_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *sig | |||||
to_byte(hash_key+2*n, idx, n); | to_byte(hash_key+2*n, idx, n); | ||||
// Then use it for message digest | // Then use it for message digest | ||||
h_msg(msg_h, msg, msglen, hash_key, 3*n, n); | h_msg(msg_h, msg, msglen, hash_key, 3*n, n); | ||||
// Start collecting signature | // Start collecting signature | ||||
*sig_msg_len = 0; | *sig_msg_len = 0; | ||||
@@ -454,7 +456,7 @@ int xmss_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigne | |||||
unsigned long long tmp_sig_len = params->wots_par.keysize+params->h*n; | unsigned long long tmp_sig_len = params->wots_par.keysize+params->h*n; | ||||
m_len = sig_msg_len - tmp_sig_len; | m_len = sig_msg_len - tmp_sig_len; | ||||
h_msg(msg_h, sig_msg + tmp_sig_len, m_len, hash_key, 3*n, n); | h_msg(msg_h, sig_msg + tmp_sig_len, m_len, hash_key, 3*n, n); | ||||
//----------------------- | //----------------------- | ||||
// Verify signature | // Verify signature | ||||
//----------------------- | //----------------------- | ||||
@@ -30,12 +30,14 @@ Public domain. | |||||
*/ | */ | ||||
static void get_seed(unsigned char *seed, const unsigned char *sk_seed, int n, uint32_t addr[8]) | static void get_seed(unsigned char *seed, const unsigned char *sk_seed, int n, uint32_t addr[8]) | ||||
{ | { | ||||
unsigned char bytes[32]; | |||||
// Make sure that chain addr, hash addr, and key bit are 0! | // Make sure that chain addr, hash addr, and key bit are 0! | ||||
setChainADRS(addr,0); | setChainADRS(addr,0); | ||||
setHashADRS(addr,0); | setHashADRS(addr,0); | ||||
setKeyAndMask(addr,0); | setKeyAndMask(addr,0); | ||||
// Generate pseudorandom value | // Generate pseudorandom value | ||||
prf(seed, (unsigned char*) addr, sk_seed, n); | |||||
addr_to_byte(bytes, addr); | |||||
prf(seed, bytes, sk_seed, n); | |||||
} | } | ||||
/** | /** | ||||