diff --git a/hash.c b/hash.c index 7d043f3..d574921 100644 --- a/hash.c +++ b/hash.c @@ -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 - +#include +#include +#include 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"); } diff --git a/prg.h b/prg.h index d95c787..750414e 100644 --- a/prg.h +++ b/prg.h @@ -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 diff --git a/test/test_chacha.c b/test/test_chacha.c index 606617f..5392fdd 100644 --- a/test/test_chacha.c +++ b/test/test_chacha.c @@ -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; } diff --git a/test/test_wots.c b/test/test_wots.c index cf21b3b..794db0c 100644 --- a/test/test_wots.c +++ b/test/test_wots.c @@ -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); diff --git a/test/test_xmss.c b/test/test_xmss.c index 46c07a6..1407b6a 100644 --- a/test/test_xmss.c +++ b/test/test_xmss.c @@ -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); diff --git a/test/test_xmss_fast.c b/test/test_xmss_fast.c index dd26167..34b5977 100644 --- a/test/test_xmss_fast.c +++ b/test/test_xmss_fast.c @@ -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<keysize, inseed, 32); + prg(outseeds, params->keysize, inseed, params->n); } /** diff --git a/xmss.c b/xmss.c index 0dbc733..1c77305 100644 --- a/xmss.c +++ b/xmss.c @@ -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); diff --git a/xmss_fast.c b/xmss_fast.c index 62a6f48..f833029 100644 --- a/xmss_fast.c +++ b/xmss_fast.c @@ -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;