diff --git a/Makefile b/Makefile index 4eb165f..d770aa9 100644 --- a/Makefile +++ b/Makefile @@ -11,19 +11,19 @@ test/test_xmssmt test/test_chacha: chacha.c prg.c randombytes.c test/test_chacha.c chacha.h prg.h randombytes.h $(CC) $(CFLAGS) chacha.c prg.c randombytes.c test/test_chacha.c -o $@ -lcrypto -lm -test/test_wots: chacha.c hash.c prg.c randombytes.c wots.c xmss_commons.c test/test_wots.c chacha.h hash.h prg.h randombytes.h wots.h xmss_commons.h +test/test_wots: chacha.c hash.c prg.c randombytes.c wots.c xmss_commons.c test/test_wots.c chacha.h hash.h hash_address.h prg.h randombytes.h wots.h xmss_commons.h $(CC) $(CFLAGS) chacha.c hash.c prg.c randombytes.c wots.c xmss_commons.c test/test_wots.c -o $@ -lcrypto -lm -test/test_xmss: chacha.c hash.c prg.c randombytes.c wots.c xmss.c xmss_commons.c test/test_xmss.c chacha.h hash.h prg.h randombytes.h wots.h xmss.h xmss_commons.h +test/test_xmss: chacha.c hash.c prg.c randombytes.c wots.c xmss.c xmss_commons.c test/test_xmss.c chacha.h hash.h hash_address.h prg.h randombytes.h wots.h xmss.h xmss_commons.h $(CC) $(CFLAGS) chacha.c hash.c prg.c randombytes.c wots.c xmss.c xmss_commons.c test/test_xmss.c -o $@ -lcrypto -lm -test/test_xmss_fast: chacha.c hash.c prg.c randombytes.c wots.c xmss_fast.c xmss_commons.c test/test_xmss_fast.c chacha.h hash.h prg.h randombytes.h wots.h xmss_fast.h xmss_commons.h +test/test_xmss_fast: chacha.c hash.c prg.c randombytes.c wots.c xmss_fast.c xmss_commons.c test/test_xmss_fast.c chacha.h hash.h hash_address.h prg.h randombytes.h wots.h xmss_fast.h xmss_commons.h $(CC) $(CFLAGS) chacha.c hash.c prg.c randombytes.c wots.c xmss_fast.c xmss_commons.c test/test_xmss_fast.c -o $@ -lcrypto -lm -test/test_xmssmt: chacha.c hash.c prg.c randombytes.c wots.c xmss.c xmss_commons.c test/test_xmssmt.c chacha.h hash.h prg.h randombytes.h wots.h xmss.h xmss_commons.h +test/test_xmssmt: chacha.c hash.c prg.c randombytes.c wots.c xmss.c xmss_commons.c test/test_xmssmt.c chacha.h hash.h hash_address.h prg.h randombytes.h wots.h xmss.h xmss_commons.h $(CC) $(CFLAGS) chacha.c hash.c prg.c randombytes.c wots.c xmss.c xmss_commons.c test/test_xmssmt.c -o $@ -lcrypto -lm -test/test_xmssmt_fast: chacha.c hash.c prg.c randombytes.c wots.c xmss_fast.c xmss_commons.c test/test_xmssmt_fast.c chacha.h hash.h prg.h randombytes.h wots.h xmss_fast.h xmss_commons.h +test/test_xmssmt_fast: chacha.c hash.c prg.c randombytes.c wots.c xmss_fast.c xmss_commons.c test/test_xmssmt_fast.c chacha.h hash.h hash_address.h prg.h randombytes.h wots.h xmss_fast.h xmss_commons.h $(CC) $(CFLAGS) chacha.c hash.c prg.c randombytes.c wots.c xmss_fast.c xmss_commons.c test/test_xmssmt_fast.c -o $@ -lcrypto -lm .PHONY: clean diff --git a/hash.c b/hash.c index 1acc1d2..63a4700 100644 --- a/hash.c +++ b/hash.c @@ -1,10 +1,12 @@ /* -hash.c version 20151120 +hash.c version 20160210 Andreas Hülsing +Joost Rijneveld Public domain. */ #include "prg.h" +#include "hash_address.h" #include #include @@ -14,12 +16,6 @@ Public domain. #include -#define SET_KEY_BIT(a, b) (a[15] = (a[15] & 253) | ((b << 1) & 2)) -#define SET_BLOCK_BIT(a, b) (a[15] = (a[15] & 254) | (b & 1)) - -#define WOTS_SELECT_KEY(a) (a[15] = (a[15] & 254) | 1) -#define WOTS_SELECT_BLOCK(a) (a[15] = (a[15] & 254) | 0) - /** * Implements PRF_m */ @@ -51,29 +47,27 @@ int prf_m(unsigned char *out, const unsigned char *in, size_t inlen, const unsig int hash_m(unsigned char *out, const unsigned char *in, unsigned long long inlen, const unsigned char *key, const unsigned int keylen, const unsigned int m) { unsigned int i; - unsigned char buf[inlen + keylen + m]; + unsigned char buf[inlen + keylen]; - if (keylen != m){ - fprintf(stderr, "H_m takes m-bit keys, we got m=%d but a keylength of %d.\n", m, keylen); + if (keylen != 2*m){ + fprintf(stderr, "H_m takes 2m-bit keys, we got m=%d but a keylength of %d.\n", m, keylen); return 1; } - for (i=0; i < m; i++) { - buf[i] = 0x00; - } + for (i=0; i < keylen; i++) { - buf[m + i] = key[i]; + buf[i] = key[i]; } for (i=0; i < inlen; i++) { - buf[m + keylen + i] = in[i]; + buf[keylen + i] = in[i]; } if (m == 32) { - SHA256(buf, inlen + keylen + m, out); + SHA256(buf, inlen + keylen, out); return 0; } else { if (m == 64) { - SHA512(buf, inlen + keylen + m, out); + SHA512(buf, inlen + keylen, out); return 0; } } diff --git a/hash.h b/hash.h index bd6638f..f4e5d9f 100644 --- a/hash.h +++ b/hash.h @@ -1,6 +1,7 @@ /* -hash.h version 20151120 +hash.h version 20160210 Andreas Hülsing +Joost Rijneveld Public domain. */ diff --git a/hash_address.h b/hash_address.h new file mode 100644 index 0000000..3f13b4a --- /dev/null +++ b/hash_address.h @@ -0,0 +1,83 @@ +/* +hash.c version 20160210 +Andreas Hülsing +Joost Rijneveld +Public domain. +*/ + +/* + * Used in hash.c + */ +#define SET_BLOCK_BIT(a, b) (a[15] = (a[15] & 1) | ((b << 1) & 2)) +#define SET_KEY_BIT(a, b) (a[15] = (a[15] & 2) | (b & 1)) + +#define WOTS_SELECT_KEY(a) (a[15] = 1) +#define WOTS_SELECT_BLOCK(a) (a[15] = 0) +/* + * Used in wots.c + */ +#define SET_HASH_ADDRESS(a, v) {\ + a[14] = (v & 255);} + +#define SET_CHAIN_ADDRESS(a, v) {\ + a[13] = (v & 255);\ + a[12] = ((v >> 8) & 255);} + +/* + * Used in xmss_fast.c and xmss.c + */ +#define SET_LAYER_ADDRESS(a, v) {\ + a[0] = (v & 255);} + +#define SET_TREE_ADDRESS(a, v) {\ + a[5] = (v & 255);\ + a[4] = (v >> 8) & 255;\ + a[3] = (v >> 16) & 255;\ + a[2] = (v >> 24) & 255;\ + a[1] = (v >> 32) & 255;} + +#define SET_OTS_BIT(a, b) {\ + a[6] = (b & 1);\ + a[7] = 0;\ + a[8] = 0;} + +#define SET_OTS_ADDRESS(a, v) {\ + a[11] = (v & 255);\ + a[10] = (v >> 8) & 255;\ + a[9] = (v >> 16) & 255;} + +#define ZEROISE_OTS_ADDR(a) {\ + a[12] = 0;\ + a[13] = 0;\ + a[14] = 0;\ + a[15] = 0;} + +#define SET_LTREE_BIT(a, b) {\ + a[7] = (a[7] & 0) | (b & 1);} + +#define SET_LTREE_ADDRESS(a, v) {\ + a[10] = v & 255;\ + a[9] = (v >> 8) & 255;\ + a[8] = (v >> 16) & 255;} + +#define SET_LTREE_TREE_HEIGHT(a, v) {\ + a[11] = (v & 255);} + +#define SET_LTREE_TREE_INDEX(a, v) {\ + a[14] = (v & 255);\ + a[13] = (v >> 8) & 255;\ + a[12] = (v >> 16) & 3;} + +#define SET_NODE_PADDING(a) {\ + a[8] = 0;\ + a[9] = 0;\ + a[10] = 0;} + +#define SET_NODE_TREE_HEIGHT(a, v) {\ + a[11] = (v & 255);} + +#define SET_NODE_TREE_INDEX(a, v) {\ + a[14] = v & 255;\ + a[13] = (v >> 8) & 255;\ + a[12] = (v >> 16) & 255;} + diff --git a/prg.c b/prg.c index 5a14ec6..7170f9e 100644 --- a/prg.c +++ b/prg.c @@ -1,6 +1,7 @@ /* -prg.c version 20151120 +prg.c version 20160210 Andreas Hülsing +Joost Rijneveld Public domain. */ #include "chacha.h" diff --git a/prg.h b/prg.h index b74afdb..bd25e87 100644 --- a/prg.h +++ b/prg.h @@ -1,6 +1,7 @@ /* -prg.h version 20151120 +prg.h version 20160210 Andreas Hülsing +Joost Rijneveld Public domain. */ diff --git a/test/test_xmss.c b/test/test_xmss.c index 3895867..0931370 100644 --- a/test/test_xmss.c +++ b/test/test_xmss.c @@ -14,8 +14,8 @@ int main() { int r; unsigned long long i; - unsigned int m = 64; - unsigned int n = 64; + unsigned int m = 32; + unsigned int n = 32; unsigned int h = 8; unsigned int w = 16; diff --git a/wots.c b/wots.c index 80ab3f8..6df49ff 100644 --- a/wots.c +++ b/wots.c @@ -1,6 +1,7 @@ /* -wots.c version 20151120 +wots.c version 20160210 Andreas Hülsing +Joost Rijneveld Public domain. */ @@ -11,19 +12,7 @@ Public domain. #include "prg.h" #include "hash.h" #include "wots.h" - -/** - * Macros used to manipulate the respective fields - * in the 16byte hash address - */ -#define SET_HASH_ADDRESS(a, v) {\ - a[15] = (a[15] & 1) | ((v << 1) & 254);\ - a[14] = (a[14] & 254) | ((v >> 7) & 1);} - -#define SET_CHAIN_ADDRESS(a, v) {\ - a[14] = (a[14] & 1) | ((v << 1) & 254);\ - a[13] = (v >> 7) & 255;\ - a[12] = (a[12] & 254) | ((v >> 15) & 1);} +#include "hash_address.h" void wots_set_params(wots_params *params, int m, int n, int w) diff --git a/wots.h b/wots.h index b9585eb..a5b846c 100644 --- a/wots.h +++ b/wots.h @@ -1,6 +1,7 @@ /* -wots.h version 20151120 +wots.h version 20160210 Andreas Hülsing +Joost Rijneveld Public domain. */ diff --git a/xmss.c b/xmss.c index e626166..a5d137b 100644 --- a/xmss.c +++ b/xmss.c @@ -1,6 +1,7 @@ /* -xmss.c version 20151120 +xmss.c version 20160210 Andreas Hülsing +Joost Rijneveld Public domain. */ @@ -15,69 +16,11 @@ Public domain. #include "hash.h" #include "prg.h" #include "xmss_commons.h" +#include "hash_address.h" // For testing #include "stdio.h" -/** - * Macros used to manipulate the respective fields - * in the 16byte hash address - */ -#define SET_LAYER_ADDRESS(a, v) {\ - a[6] = (a[6] & 3) | ((v << 2) & 252);\ - a[5] = (a[5] & 252) | ((v >> 6) & 3);} - -#define SET_TREE_ADDRESS(a, v) {\ - a[9] = (a[9] & 3) | ((v << 2) & 252);\ - a[8] = (v >> 6) & 255;\ - a[7] = (v >> 14) & 255;\ - a[6] = (a[6] & 252) | ((v >> 22) & 3);} - -#define SET_OTS_BIT(a, b) {\ - a[9] = (a[9] & 253) | ((b << 1) & 2);} - -#define SET_OTS_ADDRESS(a, v) {\ - a[12] = (a[12] & 1) | ((v << 1) & 254);\ - a[11] = (v >> 7) & 255;\ - a[10] = (v >> 15) & 255;\ - a[9] = (a[9] & 254) | ((v >> 23) & 1);} - -#define ZEROISE_OTS_ADDR(a) {\ - a[12] = (a[12] & 254);\ - a[13] = 0;\ - a[14] = 0;\ - a[15] = 0;} - -#define SET_LTREE_BIT(a, b) {\ - a[9] = (a[9] & 254) | (b & 1);} - -#define SET_LTREE_ADDRESS(a, v) {\ - a[12] = v & 255;\ - a[11] = (v >> 8) & 255;\ - a[10] = (v >> 16) & 255;} - -#define SET_LTREE_TREE_HEIGHT(a, v) {\ - a[13] = (a[13] & 3) | ((v << 2) & 252);} - -#define SET_LTREE_TREE_INDEX(a, v) {\ - a[15] = (a[15] & 3) | ((v << 2) & 252);\ - a[14] = (v >> 6) & 255;\ - a[13] = (a[13] & 252) | ((v >> 14) & 3);} - -#define SET_NODE_PADDING(a) {\ - a[10] = 0;\ - a[11] = a[11] & 3;} - -#define SET_NODE_TREE_HEIGHT(a, v) {\ - a[12] = (a[12] & 3) | ((v << 2) & 252);\ - a[11] = (a[11] & 252) | ((v >> 6) & 3);} - -#define SET_NODE_TREE_INDEX(a, v) {\ - a[15] = (a[15] & 3) | ((v << 2) & 252);\ - a[14] = (v >> 6) & 255;\ - a[13] = (v >> 14) & 255;\ - a[12] = (a[12] & 252) | ((v >> 22) & 3);} - /** * Used for pseudorandom keygeneration, @@ -382,7 +325,16 @@ int xmss_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *sig memcpy(sk_prf, sk+4+n, m); unsigned char pub_seed[n]; memcpy(pub_seed, sk+4+n+m, n); - + + unsigned char hash_key[2*m]; + unsigned long long i; + for(i = 0; i < m-4; i++){ + hash_key[i] = 0; + } + for(i = 0; i < 4; i++){ + hash_key[i+m-4] = sk[i]; + } + // Update SK sk[0] = ((idx + 1) >> 24) & 255; sk[1] = ((idx + 1) >> 16) & 255; @@ -392,7 +344,6 @@ int xmss_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *sig // -- A productive implementation should use a file handle instead and write the updated secret key at this point! // Init working params - unsigned long long i; unsigned char R[m]; unsigned char msg_h[m]; unsigned char root[n]; @@ -404,10 +355,12 @@ int xmss_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *sig // --------------------------------- // Message Hash: - // First compute pseudorandom key + // First compute pseudorandom value prf_m(R, msg, msglen, sk_prf, m); + // Generate hash key (idx || R) + memcpy(hash_key+m, R, m); // Then use it for message digest - hash_m(msg_h, msg, msglen, R, m, m); + hash_m(msg_h, msg, msglen, hash_key, 2*m, m); // Start collecting signature *sig_msg_len = 0; @@ -472,6 +425,7 @@ int xmss_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigne unsigned char pkhash[n]; unsigned char root[n]; unsigned char msg_h[m]; + unsigned char hash_key[2*m]; unsigned char pub_seed[n]; memcpy(pub_seed, pk+n, n); @@ -494,16 +448,19 @@ int xmss_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigne // Extract index idx = ((unsigned long)sig_msg[0] << 24) | ((unsigned long)sig_msg[1] << 16) | ((unsigned long)sig_msg[2] << 8) | sig_msg[3]; printf("verify:: idx = %lu\n", idx); - sig_msg += 4; - sig_msg_len -= 4; + for(i = 0; i < m-4; i++){ + hash_key[i] = 0; + } + for(i = 0; i < m+4; i++){ + hash_key[i+m-4] = sig_msg[i]; + } + sig_msg += (m+4); + sig_msg_len -= (m+4); - // hash message (recall, R is now on pole position at sig_msg - unsigned long long tmp_sig_len = m+params->wots_par.keysize+params->h*n; + // hash message + unsigned long long tmp_sig_len = params->wots_par.keysize+params->h*n; m_len = sig_msg_len - tmp_sig_len; - hash_m(msg_h, sig_msg + tmp_sig_len, m_len, sig_msg, m, m); - - sig_msg += m; - sig_msg_len -= m; + hash_m(msg_h, sig_msg + tmp_sig_len, m_len, hash_key, 2*m, m); //----------------------- // Verify signature @@ -596,15 +553,20 @@ int xmssmt_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *s unsigned char pub_seed[n]; // Init working params unsigned char R[m]; + unsigned char hash_key[2*m]; unsigned char msg_h[m]; unsigned char root[n]; unsigned char ots_seed[n]; unsigned char ots_addr[16] = {0, 0, 0, 0}; // Extract SK + for(i = 0; i < m-idx_len; i++){ + hash_key[i] = 0; + } unsigned long long idx = 0; for (i = 0; i < idx_len; i++) { idx |= ((unsigned long long)sk[i]) << 8*(idx_len - 1 - i); + hash_key[m-idx_len+i] = sk[i]; } memcpy(sk_seed, sk+idx_len, n); @@ -626,8 +588,12 @@ int xmssmt_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *s // Message Hash: // First compute pseudorandom key prf_m(R, msg, msglen, sk_prf, m); + + // Generate hash key (idx || R) + memcpy(hash_key+m, R, m); + // Then use it for message digest - hash_m(msg_h, msg, msglen, R, m, m); + hash_m(msg_h, msg, msglen, hash_key, 2*m, m); // Start collecting signature *sig_msg_len = 0; @@ -726,6 +692,7 @@ int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsig unsigned char pkhash[n]; unsigned char root[n]; unsigned char msg_h[m]; + unsigned char hash_key[2*m]; unsigned char pub_seed[n]; memcpy(pub_seed, pk+n, n); @@ -736,20 +703,29 @@ int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsig unsigned char node_addr[16]; // Extract index + for(i = 0; i < m-idx_len; i++){ + hash_key[i] = 0; + } for (i = 0; i < idx_len; i++) { idx |= ((unsigned long long)sig_msg[i]) << (8*(idx_len - 1 - i)); + hash_key[m-idx_len+i] = sig_msg[i]; } printf("verify:: idx = %llu\n", idx); sig_msg += idx_len; sig_msg_len -= idx_len; - // hash message (recall, R is now on pole position at sig_msg - unsigned long long tmp_sig_len = m+ (params->d * params->xmss_par.wots_par.keysize) + (params->h * n); - m_len = sig_msg_len - tmp_sig_len; - hash_m(msg_h, sig_msg + tmp_sig_len, m_len, sig_msg, m, m); + for(i = 0; i < m; i++){ + hash_key[m+i] = sig_msg[i]; + } sig_msg += m; sig_msg_len -= m; + + // hash message (recall, R is now on pole position at sig_msg + unsigned long long tmp_sig_len = (params->d * params->xmss_par.wots_par.keysize) + (params->h * n); + m_len = sig_msg_len - tmp_sig_len; + hash_m(msg_h, sig_msg + tmp_sig_len, m_len, hash_key, 2*m, m); + //----------------------- // Verify signature diff --git a/xmss.h b/xmss.h index d00403e..3295db3 100644 --- a/xmss.h +++ b/xmss.h @@ -1,6 +1,7 @@ /* -xmss.h version 20151120 +xmss.h version 20160210 Andreas Hülsing +Joost Rijneveld Public domain. */ diff --git a/xmss_commons.c b/xmss_commons.c index f80bb73..ce8a465 100644 --- a/xmss_commons.c +++ b/xmss_commons.c @@ -1,6 +1,7 @@ /* -xmss_commons.c version 20151120 +xmss_commons.c 20160210 Andreas Hülsing +Joost Rijneveld Public domain. */ diff --git a/xmss_commons.h b/xmss_commons.h index b378e50..4c6b982 100644 --- a/xmss_commons.h +++ b/xmss_commons.h @@ -1,6 +1,7 @@ /* -xmss_commons.h version 20151120 +xmss_commons.h 20160210 Andreas Hülsing +Joost Rijneveld Public domain. */ #ifndef XMSS_COMMONS_H diff --git a/xmss_fast.c b/xmss_fast.c index 17074f9..f770ad5 100644 --- a/xmss_fast.c +++ b/xmss_fast.c @@ -1,6 +1,7 @@ /* -xmss_fast.c version 20151120 -Andreas Hülsing and Joost Rijneveld +xmss_fast.c version 20160210 +Andreas Hülsing +Joost Rijneveld Public domain. */ @@ -15,68 +16,11 @@ Public domain. #include "hash.h" #include "prg.h" #include "xmss_commons.h" - +#include "hash_address.h" // For testing #include "stdio.h" -/** - * Macros used to manipulate the respective fields - * in the 16byte hash address - */ -#define SET_LAYER_ADDRESS(a, v) {\ - a[6] = (a[6] & 3) | ((v << 2) & 252);\ - a[5] = (a[5] & 252) | ((v >> 6) & 3);} -#define SET_TREE_ADDRESS(a, v) {\ - a[9] = (a[9] & 3) | ((v << 2) & 252);\ - a[8] = (v >> 6) & 255;\ - a[7] = (v >> 14) & 255;\ - a[6] = (a[6] & 252) | ((v >> 22) & 3);} - -#define SET_OTS_BIT(a, b) {\ - a[9] = (a[9] & 253) | ((b << 1) & 2);} - -#define SET_OTS_ADDRESS(a, v) {\ - a[12] = (a[12] & 1) | ((v << 1) & 254);\ - a[11] = (v >> 7) & 255;\ - a[10] = (v >> 15) & 255;\ - a[9] = (a[9] & 254) | ((v >> 23) & 1);} - -#define ZEROISE_OTS_ADDR(a) {\ - a[12] = (a[12] & 254);\ - a[13] = 0;\ - a[14] = 0;\ - a[15] = 0;} - -#define SET_LTREE_BIT(a, b) {\ - a[9] = (a[9] & 254) | (b & 1);} - -#define SET_LTREE_ADDRESS(a, v) {\ - a[12] = v & 255;\ - a[11] = (v >> 8) & 255;\ - a[10] = (v >> 16) & 255;} - -#define SET_LTREE_TREE_HEIGHT(a, v) {\ - a[13] = (a[13] & 3) | ((v << 2) & 252);} - -#define SET_LTREE_TREE_INDEX(a, v) {\ - a[15] = (a[15] & 3) | ((v << 2) & 252);\ - a[14] = (v >> 6) & 255;\ - a[13] = (a[13] & 252) | ((v >> 14) & 3);} - -#define SET_NODE_PADDING(a) {\ - a[10] = 0;\ - a[11] = a[11] & 3;} - -#define SET_NODE_TREE_HEIGHT(a, v) {\ - a[12] = (a[12] & 3) | ((v << 2) & 252);\ - a[11] = (a[11] & 252) | ((v >> 6) & 3);} - -#define SET_NODE_TREE_INDEX(a, v) {\ - a[15] = (a[15] & 3) | ((v << 2) & 252);\ - a[14] = (v >> 6) & 255;\ - a[13] = (v >> 14) & 255;\ - a[12] = (a[12] & 252) | ((v >> 22) & 3);} /** * Used for pseudorandom keygeneration, @@ -614,6 +558,16 @@ int xmss_sign(unsigned char *sk, bds_state *state, unsigned char *sig_msg, unsig memcpy(sk_prf, sk+4+n, m); unsigned char pub_seed[n]; memcpy(pub_seed, sk+4+n+m, n); + + unsigned char hash_key[2*m]; + unsigned long long i; + for(i = 0; i < m-4; i++){ + hash_key[i] = 0; + } + for(i = 0; i < 4; i++){ + hash_key[i+m-4] = sk[i]; + } + // Update SK sk[0] = ((idx + 1) >> 24) & 255; @@ -624,7 +578,6 @@ int xmss_sign(unsigned char *sk, bds_state *state, unsigned char *sig_msg, unsig // -- A productive implementation should use a file handle instead and write the updated secret key at this point! // Init working params - unsigned long long i; unsigned char R[m]; unsigned char msg_h[m]; unsigned char ots_seed[n]; @@ -637,8 +590,10 @@ int xmss_sign(unsigned char *sk, bds_state *state, unsigned char *sig_msg, unsig // Message Hash: // First compute pseudorandom key prf_m(R, msg, msglen, sk_prf, m); + // Generate hash key (idx || R) + memcpy(hash_key+m, R, m); // Then use it for message digest - hash_m(msg_h, msg, msglen, R, m, m); + hash_m(msg_h, msg, msglen, hash_key, 2*m, m); // Start collecting signature *sig_msg_len = 0; @@ -710,6 +665,7 @@ int xmss_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigne unsigned char pkhash[n]; unsigned char root[n]; unsigned char msg_h[m]; + unsigned char hash_key[2*m]; unsigned char pub_seed[n]; memcpy(pub_seed, pk+n, n); @@ -732,16 +688,19 @@ int xmss_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigne // Extract index idx = ((unsigned long)sig_msg[0] << 24) | ((unsigned long)sig_msg[1] << 16) | ((unsigned long)sig_msg[2] << 8) | sig_msg[3]; printf("verify:: idx = %lu\n", idx); - sig_msg += 4; - sig_msg_len -= 4; + for(i = 0; i < m-4; i++){ + hash_key[i] = 0; + } + for(i = 0; i < m+4; i++){ + hash_key[i+m-4] = sig_msg[i]; + } + sig_msg += (m+4); + sig_msg_len -= (m+4); - // hash message (recall, R is now on pole position at sig_msg - unsigned long long tmp_sig_len = m+params->wots_par.keysize+params->h*n; + // hash message + unsigned long long tmp_sig_len = params->wots_par.keysize+params->h*n; m_len = sig_msg_len - tmp_sig_len; - hash_m(msg_h, sig_msg + tmp_sig_len, m_len, sig_msg, m, m); - - sig_msg += m; - sig_msg_len -= m; + hash_m(msg_h, sig_msg + tmp_sig_len, m_len, hash_key, 2*m, m); //----------------------- // Verify signature @@ -807,7 +766,7 @@ int xmssmt_keypair(unsigned char *pk, unsigned char *sk, bds_state *states, unsi // Set address to point on the single tree on layer d-1 unsigned char addr[16] = {0, 0, 0, 0}; SET_OTS_BIT(addr, 1); - SET_TREE_ADDRESS(addr, 0); + SET_TREE_ADDRESS(addr, (unsigned long long)0); SET_OTS_ADDRESS(addr, 0); SET_LAYER_ADDRESS(addr, 0); // Set up state and compute wots signatures for all but topmost tree root @@ -849,15 +808,20 @@ int xmssmt_sign(unsigned char *sk, bds_state *states, unsigned char *wots_sigs, // Init working params unsigned char R[m]; unsigned char msg_h[m]; + unsigned char hash_key[2*m]; unsigned char ots_seed[n]; unsigned char addr[16] = {0, 0, 0, 0}; unsigned char ots_addr[16] = {0, 0, 0, 0}; bds_state tmp; // Extract SK + for(i = 0; i < m-idx_len; i++){ + hash_key[i] = 0; + } unsigned long long idx = 0; for (i = 0; i < idx_len; i++) { idx |= ((unsigned long long)sk[i]) << 8*(idx_len - 1 - i); + hash_key[m-idx_len+i] = sk[i]; } memcpy(sk_seed, sk+idx_len, n); @@ -879,8 +843,12 @@ int xmssmt_sign(unsigned char *sk, bds_state *states, unsigned char *wots_sigs, // Message Hash: // First compute pseudorandom key prf_m(R, msg, msglen, sk_prf, m); + + // Generate hash key (idx || R) + memcpy(hash_key+m, R, m); + // Then use it for message digest - hash_m(msg_h, msg, msglen, R, m, m); + hash_m(msg_h, msg, msglen, hash_key, 2*m, m); // Start collecting signature *sig_msg_len = 0; @@ -1020,6 +988,7 @@ int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsig unsigned char pkhash[n]; unsigned char root[n]; unsigned char msg_h[m]; + unsigned char hash_key[2*m]; unsigned char pub_seed[n]; memcpy(pub_seed, pk+n, n); @@ -1030,21 +999,31 @@ int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsig unsigned char node_addr[16]; // Extract index + for(i = 0; i < m-idx_len; i++){ + hash_key[i] = 0; + } for (i = 0; i < idx_len; i++) { idx |= ((unsigned long long)sig_msg[i]) << (8*(idx_len - 1 - i)); + hash_key[m-idx_len+i] = sig_msg[i]; } printf("verify:: idx = %llu\n", idx); sig_msg += idx_len; sig_msg_len -= idx_len; - - // hash message (recall, R is now on pole position at sig_msg - unsigned long long tmp_sig_len = m+ (params->d * params->xmss_par.wots_par.keysize) + (params->h * n); - m_len = sig_msg_len - tmp_sig_len; - hash_m(msg_h, sig_msg + tmp_sig_len, m_len, sig_msg, m, m); + + for(i = 0; i < m; i++){ + hash_key[m+i] = sig_msg[i]; + } sig_msg += m; sig_msg_len -= m; + + // hash message (recall, R is now on pole position at sig_msg + unsigned long long tmp_sig_len = (params->d * params->xmss_par.wots_par.keysize) + (params->h * n); + m_len = sig_msg_len - tmp_sig_len; + hash_m(msg_h, sig_msg + tmp_sig_len, m_len, hash_key, 2*m, m); + + //----------------------- // Verify signature //----------------------- diff --git a/xmss_fast.h b/xmss_fast.h index 97d1310..d4c4ebb 100644 --- a/xmss_fast.h +++ b/xmss_fast.h @@ -1,6 +1,7 @@ /* -xmss_fast.h version 20151120 -Andreas Hülsing and Joost Rijneveld +xmss_fast.h version 20160210 +Andreas Hülsing +Joost Rijneveld Public domain. */