@@ -101,12 +101,12 @@ int hash_2n_n(unsigned char *out,const unsigned char *in, const unsigned char *p | |||
SET_KEY_BIT(addr,1); | |||
SET_BLOCK_BIT(addr,0); | |||
prg_with_counter(key, n, pub_seed, n, addr); | |||
prg_with_counter(key, pub_seed, n, addr); | |||
SET_KEY_BIT(addr,0); | |||
// Use MSB order | |||
prg_with_counter(bitmask, n, pub_seed, n, addr); | |||
prg_with_counter(bitmask, pub_seed, n, addr); | |||
SET_BLOCK_BIT(addr,1); | |||
prg_with_counter(bitmask+n, n, pub_seed, n, addr); | |||
prg_with_counter(bitmask+n, pub_seed, n, addr); | |||
for(i=0;i<n;i++) | |||
{ | |||
buf[i] = 0x00; | |||
@@ -136,9 +136,9 @@ int hash_n_n(unsigned char *out,const unsigned char *in, const unsigned char *pu | |||
int i; | |||
WOTS_SELECT_KEY(addr); | |||
prg_with_counter(key, n, pub_seed, n, addr); | |||
prg_with_counter(key, pub_seed, n, addr); | |||
WOTS_SELECT_BLOCK(addr); | |||
prg_with_counter(bitmask, n, pub_seed, n, addr); | |||
prg_with_counter(bitmask, pub_seed, n, addr); | |||
for(i=0;i<n;i++) | |||
{ | |||
buf[i] = 0x00; | |||
@@ -6,7 +6,9 @@ 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}; | |||
@@ -15,18 +17,50 @@ const unsigned char zero_nonce[12] = {0}; | |||
*/ | |||
void prg(unsigned char *r, unsigned long long rlen, const unsigned char *key, unsigned int key_len) | |||
{ | |||
CRYPTO_chacha_20_keystream(r, rlen, key, zero_nonce, 0); | |||
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 rlen output bytes using ChaCha20. | |||
* Nonce and counter are set depending on the address addr. | |||
* 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, unsigned long long rlen, const unsigned char *key, unsigned int key_len, const unsigned char addr[16]) | |||
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(key_len == 32){ | |||
if(n == 32){ | |||
for(i = 0; i < 12; i++) | |||
{ | |||
nonce[i] = addr[i]; | |||
@@ -34,20 +68,26 @@ void prg_with_counter(unsigned char *r, unsigned long long rlen, const unsigned | |||
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, rlen, key, nonce, counter); | |||
CRYPTO_chacha_20_keystream(r, n, key, nonce, counter); | |||
} | |||
else | |||
{ | |||
if(key_len == 64) | |||
if(n == 64) | |||
{ | |||
for(i = 0; i < 12; i++) | |||
// 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: WRONG! Uses only 32 byte of key. However, does not compile with HMAC-SHA512 | |||
// CRYPTO_chacha_20_keystream(r, rlen, key, nonce, counter); | |||
unsigned int length; | |||
HMAC(EVP_sha512(), key, n, addr, 16, r, &length); | |||
if(length != 64) | |||
{ | |||
nonce[i] = addr[i]; | |||
fprintf(stderr, "HMAC outputs %d bytes... That should not happen...",length); | |||
} | |||
uint32_t counter; | |||
counter = (((uint32_t)addr[12]) << 24)|(((uint32_t)addr[13]) << 16)|(((uint32_t)addr[14]) << 8)|addr[15]; | |||
// TODO: WRONG! Uses only 32 byte of key. However, does not compile with HMAC-SHA512 | |||
CRYPTO_chacha_20_keystream(r, rlen, key, nonce, counter); | |||
} else { | |||
fprintf(stderr,"prg.c:: Code only supports 32 byte and 64 byte seeds"); | |||
} | |||
@@ -15,8 +15,8 @@ Public domain. | |||
void prg(unsigned char *r, unsigned long long rlen, const unsigned char *key, unsigned int key_len); | |||
/** | |||
* Generates rlen output bytes using key_len-byte key and hash address addr and places them in r. | |||
* Generates n output bytes using n-byte key and hash address addr and places them in r. | |||
* | |||
*/ | |||
void prg_with_counter(unsigned char *r, unsigned long long rlen, const unsigned char *key, unsigned int key_len, const unsigned char addr[16]); | |||
void prg_with_counter(unsigned char *r, const unsigned char *key, unsigned int n, const unsigned char addr[16]); | |||
#endif |
@@ -11,23 +11,26 @@ static void hexdump(unsigned char *a, size_t len) | |||
int main() | |||
{ | |||
int n = 32; | |||
unsigned char seed[32] = {0}; | |||
unsigned char out[64]; | |||
// unsigned char seed[64] = {0,0}; | |||
unsigned char out[2*n]; | |||
unsigned char addr[16] = {2}; | |||
printf("Case 1: All 0\n"); | |||
prg(out, 64, seed, 32); | |||
prg(out, 2*n, seed, n); | |||
printf("\n"); | |||
hexdump(out, 64); | |||
hexdump(out, 2*n); | |||
printf("\n"); | |||
printf("Case 2: key = 1\n"); | |||
seed[31] = 1; | |||
prg_with_counter(out, 64, seed, 32, addr); | |||
prg_with_counter(out, seed, n, addr); | |||
printf("\n"); | |||
hexdump(out, 64); | |||
hexdump(out, n); | |||
printf("\n"); | |||
return 0; | |||
} |
@@ -11,24 +11,25 @@ static void hexdump(unsigned char *a, size_t len) | |||
int main() | |||
{ | |||
unsigned char seed[32]; | |||
unsigned char pub_seed[32]; | |||
wots_params params; | |||
wots_set_params(¶ms, 32, 32, 16); | |||
int n = 32; | |||
unsigned char seed[n]; | |||
unsigned char pub_seed[n]; | |||
wots_params params; | |||
wots_set_params(¶ms, n, n, 16); | |||
int sig_len = params.len*params.n; | |||
int sig_len = params.len*params.n; | |||
unsigned char pk1[sig_len]; | |||
unsigned char pk2[sig_len]; | |||
unsigned char sig[sig_len]; | |||
unsigned char addr[16] = {1,2,3,4}; | |||
unsigned char pk1[sig_len]; | |||
unsigned char pk2[sig_len]; | |||
unsigned char sig[sig_len]; | |||
unsigned char addr[16] = {1,2,3,4}; | |||
unsigned char msg[32]; | |||
unsigned char msg[n]; | |||
int i; | |||
randombytes(seed, 32); | |||
randombytes(pub_seed, 32); | |||
randombytes(msg, 32); | |||
randombytes(seed, n); | |||
randombytes(pub_seed, n); | |||
randombytes(msg, n); | |||
//randombytes(addr, 16); | |||
wots_pkgen(pk1, seed, ¶ms, pub_seed, addr); | |||
@@ -7,8 +7,7 @@ | |||
#define SIGNATURES 50 | |||
unsigned char sk[100]; | |||
unsigned char pk[64]; | |||
unsigned char mi[MLEN]; | |||
unsigned long long smlen; | |||
unsigned long long mlen; | |||
@@ -17,13 +16,16 @@ int main() | |||
{ | |||
int r; | |||
unsigned long long i; | |||
int m = 32; | |||
int n = 32; | |||
int m = 64; | |||
int n = 64; | |||
int h = 8; | |||
int w = 16; | |||
unsigned long errors = 0; | |||
unsigned char sk[3*n+4]; | |||
unsigned char pk[2*n]; | |||
xmss_params p; | |||
xmss_params *params = &p; | |||
xmss_set_params(params, m, n, h, w); | |||
@@ -75,6 +77,7 @@ int main() | |||
/* Test with modified signature */ | |||
/* Modified index */ | |||
sm[signature_length+10] ^= 1; | |||
sm[2] ^= 1; | |||
r = xmss_sign_open(mo, &mlen, sm, smlen, pk, params); | |||
printf("%d\n", r+1); | |||
@@ -8,8 +8,7 @@ | |||
#define SIGNATURES 256 | |||
unsigned char sk[100]; | |||
unsigned char pk[64]; | |||
unsigned char mi[MLEN]; | |||
unsigned long long smlen; | |||
unsigned long long mlen; | |||
@@ -26,6 +25,9 @@ int main() | |||
unsigned long errors = 0; | |||
unsigned char sk[3*n+4]; | |||
unsigned char pk[2*n]; | |||
xmss_params p; | |||
xmss_params *params = &p; | |||
xmss_set_params(params, m, n, h, w, k); | |||
@@ -34,7 +36,7 @@ int main() | |||
unsigned char stack[(h+1)*n]; | |||
unsigned int stackoffset = 0; | |||
unsigned char stacklevels[h+1]; | |||
unsigned char auth[h*n]; | |||
unsigned char auth[(h)*n]; | |||
unsigned char keep[(h >> 1)*n]; | |||
treehash_inst treehash[h-k]; | |||
unsigned char th_nodes[(h-k)*n]; | |||
@@ -64,7 +66,7 @@ int main() | |||
unsigned long idx = ((unsigned long)sk[0] << 24) | ((unsigned long)sk[1] << 16) | ((unsigned long)sk[2] << 8) | sk[3]; | |||
if(idx) printf("\nidx != 0 %lu\n",idx); | |||
for(i=0;i<(1<<h);i++){ | |||
for(i=0;i<((1<<h));i++){ | |||
printf("sign\n"); | |||
xmss_sign(sk, state, sm, &smlen, mi, MLEN, params); | |||
idx = ((unsigned long)sm[0] << 24) | ((unsigned long)sm[1] << 16) | ((unsigned long)sm[2] << 8) | sm[3]; | |||
@@ -93,6 +95,7 @@ int main() | |||
/* Test with modified signature */ | |||
/* Modified index */ | |||
sm[signature_length+10] ^= 1; | |||
sm[2] ^= 1; | |||
r = xmss_sign_open(mo, &mlen, sm, smlen, pk, params); | |||
printf("%d\n", r+1); | |||
@@ -53,7 +53,7 @@ int main() | |||
if(idx) printf("\nidx != 0: %llu\n",idx); | |||
for(i=0;i<SIGNATURES;i++){ | |||
for(i=0;i<(1<<h);i++){ | |||
printf("sign\n"); | |||
xmssmt_sign(sk, sm, &smlen, mi, MLEN, params); | |||
idx = 0; | |||
@@ -45,7 +45,7 @@ void wots_set_params(wots_params *params, int m, int n, int w) | |||
*/ | |||
static void expand_seed(unsigned char *outseeds, const unsigned char *inseed, const wots_params *params) | |||
{ | |||
prg(outseeds, params->keysize, inseed, 32); | |||
prg(outseeds, params->keysize, inseed, params->n); | |||
} | |||
/** | |||
@@ -79,16 +79,18 @@ Public domain. | |||
a[12] = (a[12] & 252) | ((v >> 22) & 3);} | |||
/** | |||
/** | |||
* Used for pseudorandom keygeneration, | |||
* generates the seed for the WOTS keypair at address addr | |||
* | |||
* takes n byte sk_seed and returns n byte seed using 16 byte address addr. | |||
*/ | |||
static void get_seed(unsigned char seed[32], const unsigned char *sk_seed, unsigned char addr[16]) | |||
static void get_seed(unsigned char *seed, const unsigned char *sk_seed, int n, unsigned char addr[16]) | |||
{ | |||
// Make sure that chain addr, hash addr, and key bit are 0! | |||
ZEROISE_OTS_ADDR(addr); | |||
// Generate pseudorandom value | |||
prg_with_counter(seed, 32, sk_seed, 32, addr); | |||
prg_with_counter(seed, sk_seed, n, addr); | |||
} | |||
/** | |||
@@ -175,10 +177,10 @@ static void l_tree(unsigned char *leaf, unsigned char *wots_pk, const xmss_param | |||
*/ | |||
static void gen_leaf_wots(unsigned char *leaf, const unsigned char *sk_seed, const xmss_params *params, const unsigned char *pub_seed, unsigned char ltree_addr[16], unsigned char ots_addr[16]) | |||
{ | |||
unsigned char seed[32]; | |||
unsigned char seed[params->n]; | |||
unsigned char pk[params->wots_par.keysize]; | |||
get_seed(seed, sk_seed, ots_addr); | |||
get_seed(seed, sk_seed, params->n, ots_addr); | |||
wots_pkgen(pk, seed, &(params->wots_par), pub_seed, ots_addr); | |||
l_tree(leaf, pk, params, pub_seed, ltree_addr); | |||
@@ -448,7 +450,7 @@ int xmss_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *sig | |||
SET_OTS_ADDRESS(ots_addr,idx); | |||
// Compute seed for OTS key pair | |||
get_seed(ots_seed, sk_seed, ots_addr); | |||
get_seed(ots_seed, sk_seed, n, ots_addr); | |||
// Compute WOTS signature | |||
wots_sign(sig_msg, msg_h, ots_seed, &(params->wots_par), pub_seed, ots_addr); | |||
@@ -673,7 +675,7 @@ int xmssmt_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *s | |||
SET_OTS_ADDRESS(ots_addr, idx_leaf); | |||
// Compute seed for OTS key pair | |||
get_seed(ots_seed, sk_seed, ots_addr); | |||
get_seed(ots_seed, sk_seed, n, ots_addr); | |||
// Compute WOTS signature | |||
wots_sign(sig_msg, msg_h, ots_seed, &(params->xmss_par.wots_par), pub_seed, ots_addr); | |||
@@ -696,7 +698,7 @@ int xmssmt_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *s | |||
SET_OTS_ADDRESS(ots_addr, idx_leaf); | |||
// Compute seed for OTS key pair | |||
get_seed(ots_seed, sk_seed, ots_addr); | |||
get_seed(ots_seed, sk_seed, n, ots_addr); | |||
// Compute WOTS signature | |||
wots_sign(sig_msg, root, ots_seed, &(params->xmss_par.wots_par), pub_seed, ots_addr); | |||
@@ -78,16 +78,18 @@ Public domain. | |||
a[13] = (v >> 14) & 255;\ | |||
a[12] = (a[12] & 252) | ((v >> 22) & 3);} | |||
/** | |||
/** | |||
* Used for pseudorandom keygeneration, | |||
* generates the seed for the WOTS keypair at address addr | |||
* | |||
* takes n byte sk_seed and returns n byte seed using 16 byte address addr. | |||
*/ | |||
static void get_seed(unsigned char seed[32], const unsigned char *sk_seed, unsigned char addr[16]) | |||
static void get_seed(unsigned char *seed, const unsigned char *sk_seed, int n, unsigned char addr[16]) | |||
{ | |||
// Make sure that chain addr, hash addr, and key bit are 0! | |||
ZEROISE_OTS_ADDR(addr); | |||
// Generate pseudorandom value | |||
prg_with_counter(seed, 32, sk_seed, 32, addr); | |||
prg_with_counter(seed, sk_seed, n, addr); | |||
} | |||
/** | |||
@@ -200,10 +202,10 @@ static void l_tree(unsigned char *leaf, unsigned char *wots_pk, const xmss_param | |||
*/ | |||
static void gen_leaf_wots(unsigned char *leaf, const unsigned char *sk_seed, const xmss_params *params, const unsigned char *pub_seed, unsigned char ltree_addr[16], unsigned char ots_addr[16]) | |||
{ | |||
unsigned char seed[32]; | |||
unsigned char seed[params->n]; | |||
unsigned char pk[params->wots_par.keysize]; | |||
get_seed(seed, sk_seed, ots_addr); | |||
get_seed(seed, sk_seed, params->n, ots_addr); | |||
wots_pkgen(pk, seed, &(params->wots_par), pub_seed, ots_addr); | |||
l_tree(leaf, pk, params, pub_seed, ltree_addr); | |||
@@ -679,7 +681,7 @@ int xmss_sign(unsigned char *sk, bds_state *state, unsigned char *sig_msg, unsig | |||
SET_OTS_ADDRESS(ots_addr,idx); | |||
// Compute seed for OTS key pair | |||
get_seed(ots_seed, sk_seed, ots_addr); | |||
get_seed(ots_seed, sk_seed, n, ots_addr); | |||
// Compute WOTS signature | |||
wots_sign(sig_msg, msg_h, ots_seed, &(params->wots_par), pub_seed, ots_addr); | |||
@@ -828,7 +830,7 @@ int xmssmt_keypair(unsigned char *pk, unsigned char *sk, bds_state *states, unsi | |||
// Compute seed for OTS key pair | |||
treehash_setup(pk, params->xmss_par.h, 0, states + i, sk+params->index_len, &(params->xmss_par), pk+n, addr); | |||
SET_LAYER_ADDRESS(addr, (i+1)); | |||
get_seed(ots_seed, sk+params->index_len, addr); | |||
get_seed(ots_seed, sk+params->index_len, n, addr); | |||
wots_sign(wots_sigs + i*params->xmss_par.wots_par.keysize, pk, ots_seed, &(params->xmss_par.wots_par), pk+n, addr); | |||
} | |||
treehash_setup(pk, params->xmss_par.h, 0, states + i, sk+params->index_len, &(params->xmss_par), pk+n, addr); | |||
@@ -927,7 +929,7 @@ int xmssmt_sign(unsigned char *sk, bds_state *states, unsigned char *wots_sigs, | |||
SET_OTS_ADDRESS(ots_addr, idx_leaf); | |||
// Compute seed for OTS key pair | |||
get_seed(ots_seed, sk_seed, ots_addr); | |||
get_seed(ots_seed, sk_seed, n, ots_addr); | |||
// Compute WOTS signature | |||
wots_sign(sig_msg, msg_h, ots_seed, &(params->xmss_par.wots_par), pub_seed, ots_addr); | |||
@@ -974,7 +976,7 @@ int xmssmt_sign(unsigned char *sk, bds_state *states, unsigned char *wots_sigs, | |||
SET_OTS_ADDRESS(ots_addr, (((idx >> ((i+1) * tree_h)) + 1) & ((1 << tree_h)-1))); | |||
SET_LAYER_ADDRESS(ots_addr, (i+1)); | |||
get_seed(ots_seed, sk+params->index_len, ots_addr); | |||
get_seed(ots_seed, sk+params->index_len, n, ots_addr); | |||
wots_sign(wots_sigs + i*params->xmss_par.wots_par.keysize, states[i].stack, ots_seed, &(params->xmss_par.wots_par), pub_seed, ots_addr); | |||
states[params->d + i].stackoffset = 0; | |||