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 | |||
$(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 | |||
@@ -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 <stddef.h> | |||
#include <stdio.h> | |||
@@ -14,12 +16,6 @@ Public domain. | |||
#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 | |||
*/ | |||
@@ -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; | |||
} | |||
} | |||
@@ -1,6 +1,7 @@ | |||
/* | |||
hash.h version 20151120 | |||
hash.h version 20160210 | |||
Andreas Hülsing | |||
Joost Rijneveld | |||
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 | |||
Joost Rijneveld | |||
Public domain. | |||
*/ | |||
#include "chacha.h" | |||
@@ -1,6 +1,7 @@ | |||
/* | |||
prg.h version 20151120 | |||
prg.h version 20160210 | |||
Andreas Hülsing | |||
Joost Rijneveld | |||
Public domain. | |||
*/ | |||
@@ -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; | |||
@@ -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) | |||
@@ -1,6 +1,7 @@ | |||
/* | |||
wots.h version 20151120 | |||
wots.h version 20160210 | |||
Andreas Hülsing | |||
Joost Rijneveld | |||
Public domain. | |||
*/ | |||
@@ -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 | |||
@@ -1,6 +1,7 @@ | |||
/* | |||
xmss.h version 20151120 | |||
xmss.h version 20160210 | |||
Andreas Hülsing | |||
Joost Rijneveld | |||
Public domain. | |||
*/ | |||
@@ -1,6 +1,7 @@ | |||
/* | |||
xmss_commons.c version 20151120 | |||
xmss_commons.c 20160210 | |||
Andreas Hülsing | |||
Joost Rijneveld | |||
Public domain. | |||
*/ | |||
@@ -1,6 +1,7 @@ | |||
/* | |||
xmss_commons.h version 20151120 | |||
xmss_commons.h 20160210 | |||
Andreas Hülsing | |||
Joost Rijneveld | |||
Public domain. | |||
*/ | |||
#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. | |||
*/ | |||
@@ -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 | |||
//----------------------- | |||
@@ -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. | |||
*/ | |||