Versions are incompatible due to different address formats and differing message compression!master
@@ -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 | 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 | $(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 | $(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 | $(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 | $(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 | $(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 | $(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 | .PHONY: clean | ||||
@@ -1,10 +1,12 @@ | |||||
/* | /* | ||||
hash.c version 20151120 | |||||
hash.c version 20160210 | |||||
Andreas Hülsing | Andreas Hülsing | ||||
Joost Rijneveld | |||||
Public domain. | Public domain. | ||||
*/ | */ | ||||
#include "prg.h" | #include "prg.h" | ||||
#include "hash_address.h" | |||||
#include <stddef.h> | #include <stddef.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
@@ -14,12 +16,6 @@ Public domain. | |||||
#include <openssl/evp.h> | #include <openssl/evp.h> | ||||
#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 | * 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) | 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 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; | return 1; | ||||
} | } | ||||
for (i=0; i < m; i++) { | |||||
buf[i] = 0x00; | |||||
} | |||||
for (i=0; i < keylen; i++) { | for (i=0; i < keylen; i++) { | ||||
buf[m + i] = key[i]; | |||||
buf[i] = key[i]; | |||||
} | } | ||||
for (i=0; i < inlen; i++) { | for (i=0; i < inlen; i++) { | ||||
buf[m + keylen + i] = in[i]; | |||||
buf[keylen + i] = in[i]; | |||||
} | } | ||||
if (m == 32) { | if (m == 32) { | ||||
SHA256(buf, inlen + keylen + m, out); | |||||
SHA256(buf, inlen + keylen, out); | |||||
return 0; | return 0; | ||||
} | } | ||||
else { | else { | ||||
if (m == 64) { | if (m == 64) { | ||||
SHA512(buf, inlen + keylen + m, out); | |||||
SHA512(buf, inlen + keylen, out); | |||||
return 0; | return 0; | ||||
} | } | ||||
} | } | ||||
@@ -1,6 +1,7 @@ | |||||
/* | /* | ||||
hash.h version 20151120 | |||||
hash.h version 20160210 | |||||
Andreas Hülsing | Andreas Hülsing | ||||
Joost Rijneveld | |||||
Public domain. | Public domain. | ||||
*/ | */ | ||||
@@ -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;} | |||||
@@ -1,6 +1,7 @@ | |||||
/* | /* | ||||
prg.c version 20151120 | |||||
prg.c version 20160210 | |||||
Andreas Hülsing | Andreas Hülsing | ||||
Joost Rijneveld | |||||
Public domain. | Public domain. | ||||
*/ | */ | ||||
#include "chacha.h" | #include "chacha.h" | ||||
@@ -1,6 +1,7 @@ | |||||
/* | /* | ||||
prg.h version 20151120 | |||||
prg.h version 20160210 | |||||
Andreas Hülsing | Andreas Hülsing | ||||
Joost Rijneveld | |||||
Public domain. | Public domain. | ||||
*/ | */ | ||||
@@ -14,8 +14,8 @@ int main() | |||||
{ | { | ||||
int r; | int r; | ||||
unsigned long long i; | 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 h = 8; | ||||
unsigned int w = 16; | unsigned int w = 16; | ||||
@@ -1,6 +1,7 @@ | |||||
/* | /* | ||||
wots.c version 20151120 | |||||
wots.c version 20160210 | |||||
Andreas Hülsing | Andreas Hülsing | ||||
Joost Rijneveld | |||||
Public domain. | Public domain. | ||||
*/ | */ | ||||
@@ -11,19 +12,7 @@ Public domain. | |||||
#include "prg.h" | #include "prg.h" | ||||
#include "hash.h" | #include "hash.h" | ||||
#include "wots.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) | void wots_set_params(wots_params *params, int m, int n, int w) | ||||
@@ -1,6 +1,7 @@ | |||||
/* | /* | ||||
wots.h version 20151120 | |||||
wots.h version 20160210 | |||||
Andreas Hülsing | Andreas Hülsing | ||||
Joost Rijneveld | |||||
Public domain. | Public domain. | ||||
*/ | */ | ||||
@@ -1,6 +1,7 @@ | |||||
/* | /* | ||||
xmss.c version 20151120 | |||||
xmss.c version 20160210 | |||||
Andreas Hülsing | Andreas Hülsing | ||||
Joost Rijneveld | |||||
Public domain. | Public domain. | ||||
*/ | */ | ||||
@@ -15,69 +16,11 @@ Public domain. | |||||
#include "hash.h" | #include "hash.h" | ||||
#include "prg.h" | #include "prg.h" | ||||
#include "xmss_commons.h" | #include "xmss_commons.h" | ||||
#include "hash_address.h" | |||||
// For testing | // For testing | ||||
#include "stdio.h" | #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, | * 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); | memcpy(sk_prf, sk+4+n, m); | ||||
unsigned char pub_seed[n]; | unsigned char pub_seed[n]; | ||||
memcpy(pub_seed, sk+4+n+m, 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 | // Update SK | ||||
sk[0] = ((idx + 1) >> 24) & 255; | sk[0] = ((idx + 1) >> 24) & 255; | ||||
sk[1] = ((idx + 1) >> 16) & 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! | // -- A productive implementation should use a file handle instead and write the updated secret key at this point! | ||||
// Init working params | // Init working params | ||||
unsigned long long i; | |||||
unsigned char R[m]; | unsigned char R[m]; | ||||
unsigned char msg_h[m]; | unsigned char msg_h[m]; | ||||
unsigned char root[n]; | unsigned char root[n]; | ||||
@@ -404,10 +355,12 @@ int xmss_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *sig | |||||
// --------------------------------- | // --------------------------------- | ||||
// Message Hash: | // Message Hash: | ||||
// First compute pseudorandom key | |||||
// First compute pseudorandom value | |||||
prf_m(R, msg, msglen, sk_prf, m); | 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 | // 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 | // Start collecting signature | ||||
*sig_msg_len = 0; | *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 pkhash[n]; | ||||
unsigned char root[n]; | unsigned char root[n]; | ||||
unsigned char msg_h[m]; | unsigned char msg_h[m]; | ||||
unsigned char hash_key[2*m]; | |||||
unsigned char pub_seed[n]; | unsigned char pub_seed[n]; | ||||
memcpy(pub_seed, pk+n, 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 | // Extract index | ||||
idx = ((unsigned long)sig_msg[0] << 24) | ((unsigned long)sig_msg[1] << 16) | ((unsigned long)sig_msg[2] << 8) | sig_msg[3]; | 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); | 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; | 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 | // 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]; | unsigned char pub_seed[n]; | ||||
// Init working params | // Init working params | ||||
unsigned char R[m]; | unsigned char R[m]; | ||||
unsigned char hash_key[2*m]; | |||||
unsigned char msg_h[m]; | unsigned char msg_h[m]; | ||||
unsigned char root[n]; | unsigned char root[n]; | ||||
unsigned char ots_seed[n]; | unsigned char ots_seed[n]; | ||||
unsigned char ots_addr[16] = {0, 0, 0, 0}; | unsigned char ots_addr[16] = {0, 0, 0, 0}; | ||||
// Extract SK | // Extract SK | ||||
for(i = 0; i < m-idx_len; i++){ | |||||
hash_key[i] = 0; | |||||
} | |||||
unsigned long long idx = 0; | unsigned long long idx = 0; | ||||
for (i = 0; i < idx_len; i++) { | for (i = 0; i < idx_len; i++) { | ||||
idx |= ((unsigned long long)sk[i]) << 8*(idx_len - 1 - 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); | 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: | // Message Hash: | ||||
// First compute pseudorandom key | // First compute pseudorandom key | ||||
prf_m(R, msg, msglen, sk_prf, m); | 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 | // 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 | // Start collecting signature | ||||
*sig_msg_len = 0; | *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 pkhash[n]; | ||||
unsigned char root[n]; | unsigned char root[n]; | ||||
unsigned char msg_h[m]; | unsigned char msg_h[m]; | ||||
unsigned char hash_key[2*m]; | |||||
unsigned char pub_seed[n]; | unsigned char pub_seed[n]; | ||||
memcpy(pub_seed, pk+n, 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]; | unsigned char node_addr[16]; | ||||
// Extract index | // Extract index | ||||
for(i = 0; i < m-idx_len; i++){ | |||||
hash_key[i] = 0; | |||||
} | |||||
for (i = 0; i < idx_len; i++) { | for (i = 0; i < idx_len; i++) { | ||||
idx |= ((unsigned long long)sig_msg[i]) << (8*(idx_len - 1 - 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); | printf("verify:: idx = %llu\n", idx); | ||||
sig_msg += idx_len; | sig_msg += idx_len; | ||||
sig_msg_len -= 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 += m; | ||||
sig_msg_len -= 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 | // Verify signature | ||||
@@ -1,6 +1,7 @@ | |||||
/* | /* | ||||
xmss.h version 20151120 | |||||
xmss.h version 20160210 | |||||
Andreas Hülsing | Andreas Hülsing | ||||
Joost Rijneveld | |||||
Public domain. | Public domain. | ||||
*/ | */ | ||||
@@ -1,6 +1,7 @@ | |||||
/* | /* | ||||
xmss_commons.c version 20151120 | |||||
xmss_commons.c 20160210 | |||||
Andreas Hülsing | Andreas Hülsing | ||||
Joost Rijneveld | |||||
Public domain. | Public domain. | ||||
*/ | */ | ||||
@@ -1,6 +1,7 @@ | |||||
/* | /* | ||||
xmss_commons.h version 20151120 | |||||
xmss_commons.h 20160210 | |||||
Andreas Hülsing | Andreas Hülsing | ||||
Joost Rijneveld | |||||
Public domain. | Public domain. | ||||
*/ | */ | ||||
#ifndef XMSS_COMMONS_H | #ifndef XMSS_COMMONS_H | ||||
@@ -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. | Public domain. | ||||
*/ | */ | ||||
@@ -15,68 +16,11 @@ Public domain. | |||||
#include "hash.h" | #include "hash.h" | ||||
#include "prg.h" | #include "prg.h" | ||||
#include "xmss_commons.h" | #include "xmss_commons.h" | ||||
#include "hash_address.h" | |||||
// For testing | // For testing | ||||
#include "stdio.h" | #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, | * 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); | memcpy(sk_prf, sk+4+n, m); | ||||
unsigned char pub_seed[n]; | unsigned char pub_seed[n]; | ||||
memcpy(pub_seed, sk+4+n+m, 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 | // Update SK | ||||
sk[0] = ((idx + 1) >> 24) & 255; | 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! | // -- A productive implementation should use a file handle instead and write the updated secret key at this point! | ||||
// Init working params | // Init working params | ||||
unsigned long long i; | |||||
unsigned char R[m]; | unsigned char R[m]; | ||||
unsigned char msg_h[m]; | unsigned char msg_h[m]; | ||||
unsigned char ots_seed[n]; | 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: | // Message Hash: | ||||
// First compute pseudorandom key | // First compute pseudorandom key | ||||
prf_m(R, msg, msglen, sk_prf, m); | 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 | // 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 | // Start collecting signature | ||||
*sig_msg_len = 0; | *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 pkhash[n]; | ||||
unsigned char root[n]; | unsigned char root[n]; | ||||
unsigned char msg_h[m]; | unsigned char msg_h[m]; | ||||
unsigned char hash_key[2*m]; | |||||
unsigned char pub_seed[n]; | unsigned char pub_seed[n]; | ||||
memcpy(pub_seed, pk+n, 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 | // Extract index | ||||
idx = ((unsigned long)sig_msg[0] << 24) | ((unsigned long)sig_msg[1] << 16) | ((unsigned long)sig_msg[2] << 8) | sig_msg[3]; | 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); | 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; | 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 | // 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 | // Set address to point on the single tree on layer d-1 | ||||
unsigned char addr[16] = {0, 0, 0, 0}; | unsigned char addr[16] = {0, 0, 0, 0}; | ||||
SET_OTS_BIT(addr, 1); | SET_OTS_BIT(addr, 1); | ||||
SET_TREE_ADDRESS(addr, 0); | |||||
SET_TREE_ADDRESS(addr, (unsigned long long)0); | |||||
SET_OTS_ADDRESS(addr, 0); | SET_OTS_ADDRESS(addr, 0); | ||||
SET_LAYER_ADDRESS(addr, 0); | SET_LAYER_ADDRESS(addr, 0); | ||||
// Set up state and compute wots signatures for all but topmost tree root | // 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 | // Init working params | ||||
unsigned char R[m]; | unsigned char R[m]; | ||||
unsigned char msg_h[m]; | unsigned char msg_h[m]; | ||||
unsigned char hash_key[2*m]; | |||||
unsigned char ots_seed[n]; | unsigned char ots_seed[n]; | ||||
unsigned char addr[16] = {0, 0, 0, 0}; | unsigned char addr[16] = {0, 0, 0, 0}; | ||||
unsigned char ots_addr[16] = {0, 0, 0, 0}; | unsigned char ots_addr[16] = {0, 0, 0, 0}; | ||||
bds_state tmp; | bds_state tmp; | ||||
// Extract SK | // Extract SK | ||||
for(i = 0; i < m-idx_len; i++){ | |||||
hash_key[i] = 0; | |||||
} | |||||
unsigned long long idx = 0; | unsigned long long idx = 0; | ||||
for (i = 0; i < idx_len; i++) { | for (i = 0; i < idx_len; i++) { | ||||
idx |= ((unsigned long long)sk[i]) << 8*(idx_len - 1 - 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); | 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: | // Message Hash: | ||||
// First compute pseudorandom key | // First compute pseudorandom key | ||||
prf_m(R, msg, msglen, sk_prf, m); | 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 | // 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 | // Start collecting signature | ||||
*sig_msg_len = 0; | *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 pkhash[n]; | ||||
unsigned char root[n]; | unsigned char root[n]; | ||||
unsigned char msg_h[m]; | unsigned char msg_h[m]; | ||||
unsigned char hash_key[2*m]; | |||||
unsigned char pub_seed[n]; | unsigned char pub_seed[n]; | ||||
memcpy(pub_seed, pk+n, 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]; | unsigned char node_addr[16]; | ||||
// Extract index | // Extract index | ||||
for(i = 0; i < m-idx_len; i++){ | |||||
hash_key[i] = 0; | |||||
} | |||||
for (i = 0; i < idx_len; i++) { | for (i = 0; i < idx_len; i++) { | ||||
idx |= ((unsigned long long)sig_msg[i]) << (8*(idx_len - 1 - 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); | printf("verify:: idx = %llu\n", idx); | ||||
sig_msg += idx_len; | sig_msg += idx_len; | ||||
sig_msg_len -= 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 += m; | ||||
sig_msg_len -= 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 | // Verify signature | ||||
//----------------------- | //----------------------- | ||||
@@ -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. | Public domain. | ||||
*/ | */ | ||||