From 2c290d39be8c6cfce27a94cd9cc9a083d1dec375 Mon Sep 17 00:00:00 2001 From: Andreas Date: Mon, 11 Jul 2016 11:15:16 +0200 Subject: [PATCH] upgraded to draft-06 --- Makefile | 27 +-- chacha.c | 204 ----------------- chacha.h | 78 ------- hash.c | 156 +++++-------- hash.h | 10 +- hash_address.h | 80 ++----- prg.c | 2 +- prg.h | 2 +- test/test_chacha.c | 36 --- test/test_wots.c | 6 +- test/test_xmss.c | 10 +- test/test_xmss_fast.c | 26 ++- test/test_xmssmt.c | 10 +- test/test_xmssmt_fast.c | 10 +- wots.c | 59 ++--- wots.h | 27 +-- xmss.c | 411 ++++++++++++++++----------------- xmss.h | 12 +- xmss_commons.c | 7 +- xmss_commons.h | 5 +- xmss_fast.c | 495 +++++++++++++++++++--------------------- xmss_fast.h | 12 +- 22 files changed, 631 insertions(+), 1054 deletions(-) delete mode 100644 chacha.c delete mode 100644 chacha.h delete mode 100644 test/test_chacha.c diff --git a/Makefile b/Makefile index d770aa9..eae3e15 100644 --- a/Makefile +++ b/Makefile @@ -1,36 +1,31 @@ CC = /usr/bin/gcc CFLAGS = -Wall -g -O3 -Wextra -all: test/test_chacha \ -test/test_wots \ +all: test/test_wots \ test/test_xmss \ test/test_xmss_fast \ test/test_xmssmt_fast \ 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 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_wots: hash.c hash_address.c randombytes.c wots.c xmss_commons.c test/test_wots.c hash.h hash_address.h randombytes.h wots.h xmss_commons.h + $(CC) $(CFLAGS) hash.c hash_address.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 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: hash.c hash_address.c randombytes.c wots.c xmss.c xmss_commons.c test/test_xmss.c hash.h hash_address.h randombytes.h wots.h xmss.h xmss_commons.h + $(CC) $(CFLAGS) hash.c hash_address.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 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_xmss_fast: hash.c hash_address.c randombytes.c wots.c xmss_fast.c xmss_commons.c test/test_xmss_fast.c hash.h hash_address.h randombytes.h wots.h xmss_fast.h xmss_commons.h + $(CC) $(CFLAGS) hash.c hash_address.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 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: hash.c hash_address.c randombytes.c wots.c xmss.c xmss_commons.c test/test_xmssmt.c hash.h hash_address.h randombytes.h wots.h xmss.h xmss_commons.h + $(CC) $(CFLAGS) hash.c hash_address.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 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 +test/test_xmssmt_fast: hash.c hash_address.c randombytes.c wots.c xmss_fast.c xmss_commons.c test/test_xmssmt_fast.c hash.h hash_address.h randombytes.h wots.h xmss_fast.h xmss_commons.h + $(CC) $(CFLAGS) hash.c hash_address.c randombytes.c wots.c xmss_fast.c xmss_commons.c test/test_xmssmt_fast.c -o $@ -lcrypto -lm .PHONY: clean clean: -rm *.o *.s - -rm test/test_chacha -rm test/test_wots -rm test/test_xmss -rm test/test_xmss_fast diff --git a/chacha.c b/chacha.c deleted file mode 100644 index d97c1fa..0000000 --- a/chacha.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - * This code is based on an OpenSSL implementation of chacha20. - * Hence, the copyright below applies. - * - */ -/* ==================================================================== - * Copyright (c) 2011-2013 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * licensing@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ - -/* Adapted from the public domain code by D. Bernstein from SUPERCOP. */ - -#include -#include -#include "chacha.h" - -/* sigma contains the ChaCha constants, which happen to be an ASCII string. */ -static const char sigma[16] = "expand 32-byte k"; - -#define ROTATE(v, n) (((v) << (n)) | ((v) >> (32 - (n)))) -#define XOR(v, w) ((v) ^ (w)) -#define PLUS(x, y) ((x) + (y)) -#define PLUSONE(v) (PLUS((v), 1)) - -#define U32TO8_LITTLE(p, v) \ - { (p)[0] = (v >> 0) & 0xff; (p)[1] = (v >> 8) & 0xff; \ - (p)[2] = (v >> 16) & 0xff; (p)[3] = (v >> 24) & 0xff; } -#define U8TO32_LITTLE(p) \ - (((uint32_t)((p)[0]) ) | ((uint32_t)((p)[1]) << 8) | \ - ((uint32_t)((p)[2]) << 16) | ((uint32_t)((p)[3]) << 24) ) - -/* QUARTERROUND updates a, b, c, d with a ChaCha "quarter" round. */ -#define QUARTERROUND(a,b,c,d) \ - x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]),16); \ - x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]),12); \ - x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]), 8); \ - x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]), 7); - -/* chacha_core performs |num_rounds| rounds of ChaCha20 on the input words in - * |input| and writes the 64 output bytes to |output|. */ -static void chacha_core(unsigned char output[64], const uint32_t input[16], - int num_rounds) -{ - uint32_t x[16]; - int i; - - memcpy(x, input, sizeof(uint32_t) * 16); - for (i = num_rounds; i > 0; i -= 2) { - QUARTERROUND( 0, 4, 8,12) - QUARTERROUND( 1, 5, 9,13) - QUARTERROUND( 2, 6,10,14) - QUARTERROUND( 3, 7,11,15) - QUARTERROUND( 0, 5,10,15) - QUARTERROUND( 1, 6,11,12) - QUARTERROUND( 2, 7, 8,13) - QUARTERROUND( 3, 4, 9,14) - } - - for (i = 0; i < 16; ++i) - x[i] = PLUS(x[i], input[i]); - for (i = 0; i < 16; ++i) - U32TO8_LITTLE(output + 4 * i, x[i]); -} - -void CRYPTO_chacha_20(unsigned char *out, - const unsigned char *in, size_t in_len, - const unsigned char key[32], - const unsigned char nonce[12], - uint32_t counter) -{ - uint32_t input[16]; - unsigned char buf[64]; - size_t todo, i; - - input[0] = U8TO32_LITTLE(sigma + 0); - input[1] = U8TO32_LITTLE(sigma + 4); - input[2] = U8TO32_LITTLE(sigma + 8); - input[3] = U8TO32_LITTLE(sigma + 12); - - input[4] = U8TO32_LITTLE(key + 0); - input[5] = U8TO32_LITTLE(key + 4); - input[6] = U8TO32_LITTLE(key + 8); - input[7] = U8TO32_LITTLE(key + 12); - - input[8] = U8TO32_LITTLE(key + 16); - input[9] = U8TO32_LITTLE(key + 20); - input[10] = U8TO32_LITTLE(key + 24); - input[11] = U8TO32_LITTLE(key + 28); - - input[12] = counter; - input[13] = U8TO32_LITTLE(nonce + 0); - input[14] = U8TO32_LITTLE(nonce + 4); - input[15] = U8TO32_LITTLE(nonce + 8); - - while (in_len > 0) { - todo = sizeof(buf); - if (in_len < todo) - todo = in_len; - - chacha_core(buf, input, 20); - for (i = 0; i < todo; i++) - out[i] = in[i] ^ buf[i]; - - out += todo; - in += todo; - in_len -= todo; - - input[12]++; - if (input[12] == 0) - input[13]++; - } -} - -void CRYPTO_chacha_20_keystream(unsigned char *out, - size_t out_len, - const unsigned char key[32], - const unsigned char nonce[12], - uint32_t counter) -{ - uint32_t input[16]; - unsigned char buf[64]; - size_t todo, i; - - input[0] = U8TO32_LITTLE(sigma + 0); - input[1] = U8TO32_LITTLE(sigma + 4); - input[2] = U8TO32_LITTLE(sigma + 8); - input[3] = U8TO32_LITTLE(sigma + 12); - - input[4] = U8TO32_LITTLE(key + 0); - input[5] = U8TO32_LITTLE(key + 4); - input[6] = U8TO32_LITTLE(key + 8); - input[7] = U8TO32_LITTLE(key + 12); - - input[8] = U8TO32_LITTLE(key + 16); - input[9] = U8TO32_LITTLE(key + 20); - input[10] = U8TO32_LITTLE(key + 24); - input[11] = U8TO32_LITTLE(key + 28); - - input[12] = counter; - input[13] = U8TO32_LITTLE(nonce + 0); - input[14] = U8TO32_LITTLE(nonce + 4); - input[15] = U8TO32_LITTLE(nonce + 8); - - while (out_len > 0) { - todo = sizeof(buf); - if (out_len < todo) - todo = out_len; - - chacha_core(buf, input, 20); - for (i = 0; i < todo; i++) - out[i] = buf[i]; - - out += todo; - out_len -= todo; - - input[12]++; - if (input[12] == 0) - input[13]++; - } -} diff --git a/chacha.h b/chacha.h deleted file mode 100644 index 87a1d46..0000000 --- a/chacha.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * This code is based on an OpenSSL implementation of chacha20. - * Hence, the copyright below applies. - * - */ -/* ==================================================================== - * Copyright (c) 2011-2013 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * licensing@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -#ifndef CHACHA_H -#define CHACHA_H - -#include - -typedef unsigned int uint32_t; -/* CRYPTO_chacha_20 encrypts |in_len| bytes from |in| with the given key and - * nonce and writes the result to |out|, which may be equal to |in|. The - * initial block counter is specified by |counter|. */ -void CRYPTO_chacha_20(unsigned char *out, - const unsigned char *in, size_t in_len, - const unsigned char key[32], - const unsigned char nonce[12], - uint32_t counter); - -/* CRYPTO_chacha_20_keystream generates |out_len| bytes from the generated keystream with the given key and - * nonce and writes the result to |out|. The - * initial block counter is specified by |counter|. */ -void CRYPTO_chacha_20_keystream(unsigned char *out, - size_t out_len, - const unsigned char key[32], - const unsigned char nonce[12], - uint32_t counter); - -#endif \ No newline at end of file diff --git a/hash.c b/hash.c index 63a4700..21b00f9 100644 --- a/hash.c +++ b/hash.c @@ -1,14 +1,15 @@ /* -hash.c version 20160210 +hash.c version 20160708 Andreas Hülsing Joost Rijneveld Public domain. */ -#include "prg.h" #include "hash_address.h" +#include "xmss_commons.h" #include +#include #include #include #include @@ -16,133 +17,96 @@ Public domain. #include -/** - * Implements PRF_m - */ -int prf_m(unsigned char *out, const unsigned char *in, size_t inlen, const unsigned char *key, unsigned int keylen) -{ - unsigned int length; - if (keylen == 32) { - HMAC(EVP_sha256(), key, keylen, in, inlen, out, &length); - if (length != 32) { - fprintf(stderr, "HMAC outputs %d bytes... That should not happen...", length); - } +int core_hash_SHA2(unsigned char *out, const unsigned int type, const unsigned char *key, unsigned int keylen, const unsigned char *in, unsigned long long inlen, unsigned int n){ + unsigned long long i = 0; + unsigned char buf[inlen + n + keylen]; + + // Input is (toByte(X, 32) || KEY || M) + + // set toByte + to_byte(buf, type, n); + + for (i=0; i < keylen; i++) { + buf[i+n] = key[i]; + } + + for (i=0; i < inlen; i++) { + buf[keylen + n + i] = in[i]; + } + + if (n == 32) { + SHA256(buf, inlen + keylen + n, out); return 0; } else { - if (keylen == 64) { - HMAC(EVP_sha512(), key, keylen, in, inlen, out, &length); - if (length != 64) { - fprintf(stderr, "HMAC outputs %d bytes... That should not happen...", length); - } + if (n == 64) { + SHA512(buf, inlen + keylen + n, out); return 0; } } return 1; } -/* - * Implemts H_m +/** + * Implements PRF */ -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 prf(unsigned char *out, const unsigned char *in, const unsigned char *key, unsigned int keylen) { - unsigned int i; - unsigned char buf[inlen + keylen]; + size_t inlen = 32; + return core_hash_SHA2(out, 3, key, keylen, in, inlen, 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); +/* + * Implemts H_msg + */ +int h_msg(unsigned char *out, const unsigned char *in, unsigned long long inlen, const unsigned char *key, const unsigned int keylen, const unsigned int n) +{ + if (keylen != 3*n){ + fprintf(stderr, "H_msg takes 3n-bit keys, we got n=%d but a keylength of %d.\n", n, keylen); return 1; - } - - for (i=0; i < keylen; i++) { - buf[i] = key[i]; - } - for (i=0; i < inlen; i++) { - buf[keylen + i] = in[i]; - } - - if (m == 32) { - SHA256(buf, inlen + keylen, out); - return 0; - } - else { - if (m == 64) { - SHA512(buf, inlen + keylen, out); - return 0; - } - } - return 1; + } + return core_hash_SHA2(out, 2, key, keylen, in, inlen, n); } /** * We assume the left half is in in[0]...in[n-1] */ -int hash_2n_n(unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, unsigned char addr[16], const unsigned int n) +int hash_h(unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, uint32_t addr[8], const unsigned int n) { - unsigned char buf[4*n]; + unsigned char buf[2*n]; unsigned char key[n]; unsigned char bitmask[2*n]; unsigned int i; - SET_KEY_BIT(addr, 1); - SET_BLOCK_BIT(addr, 0); - prg_with_counter(key, pub_seed, n, addr); - SET_KEY_BIT(addr, 0); + setKeyAndMask(addr, 0); + prf(key, (unsigned char *)addr, pub_seed, n); // Use MSB order - prg_with_counter(bitmask, pub_seed, n, addr); - SET_BLOCK_BIT(addr, 1); - prg_with_counter(bitmask+n, pub_seed, n, addr); - for (i = 0; i < n; i++) { - buf[i] = 0x00; - buf[n+i] = key[i]; - buf[2*n+i] = in[i] ^ bitmask[i]; - buf[3*n+i] = in[n+i] ^ bitmask[n+i]; - } - if (n == 32) { - SHA256(buf, 4*n, out); - return 0; - } - else { - if (n == 64) { - SHA512(buf, 4*n, out); - return 0; - } - else { - fprintf(stderr, "Hash.c:hash_2n_n: Code only supports n=32 or n=64"); - return -1; - } + setKeyAndMask(addr, 1); + prf(bitmask, (unsigned char *)addr, pub_seed, n); + setKeyAndMask(addr, 2); + prf(bitmask+n, (unsigned char *)addr, pub_seed, n); + for (i = 0; i < 2*n; i++) { + buf[i] = in[i] ^ bitmask[i]; } + return core_hash_SHA2(out, 1, key, n, buf, 2*n, n); } -int hash_n_n(unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, unsigned char addr[16], const unsigned int n) +int hash_f(unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, uint32_t addr[8], const unsigned int n) { - unsigned char buf[3*n]; + unsigned char buf[n]; unsigned char key[n]; unsigned char bitmask[n]; unsigned int i; - WOTS_SELECT_KEY(addr); - prg_with_counter(key, pub_seed, n, addr); - WOTS_SELECT_BLOCK(addr); - prg_with_counter(bitmask, pub_seed, n, addr); + setKeyAndMask(addr, 0); + prf(key, (unsigned char *)addr, pub_seed, n); + // Use MSB order + setKeyAndMask(addr, 1); + prf(bitmask, (unsigned char *)addr, pub_seed, n); + for (i = 0; i < n; i++) { - buf[i] = 0x00; - buf[n+i] = key[i]; - buf[2*n+i] = in[i] ^ bitmask[i]; - } - if (n == 32) { - SHA256(buf, 3*n, out); - return 0; - } - else { - if (n == 64) { - SHA512(buf, 3*n, out); - return 0; - } - else { - fprintf(stderr, "Hash.c:hash_n_n: Code only supports n=32 or n=64"); - return -1; - } + buf[i] = in[i] ^ bitmask[i]; } + return core_hash_SHA2(out, 0, key, n, buf, n, n); } diff --git a/hash.h b/hash.h index f4e5d9f..795b26e 100644 --- a/hash.h +++ b/hash.h @@ -1,5 +1,5 @@ /* -hash.h version 20160210 +hash.h version 20160217 Andreas Hülsing Joost Rijneveld Public domain. @@ -8,9 +8,9 @@ Public domain. #ifndef HASH_H #define HASH_H -int prf_m(unsigned char *out, const unsigned char *in, size_t inlen, const unsigned char *key, int keylen); -int hash_m(unsigned char *out,const unsigned char *in,unsigned long long inlen, const unsigned char *key, const int keylen, const int m); -int hash_2n_n(unsigned char *out,const unsigned char *in, const unsigned char *pub_seed, unsigned char addr[16], const int n); -int hash_n_n(unsigned char *out,const unsigned char *in, const unsigned char *pub_seed, unsigned char addr[16], const int n); +int prf(unsigned char *out, const unsigned char *in, const unsigned char *key, int keylen); +int h_msg(unsigned char *out,const unsigned char *in,unsigned long long inlen, const unsigned char *key, const int keylen, const int n); +int hash_h(unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, uint32_t addr[8], const unsigned int n); +int hash_f(unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, uint32_t addr[8], const unsigned int n); #endif diff --git a/hash_address.h b/hash_address.h index 3f13b4a..cce1bbe 100644 --- a/hash_address.h +++ b/hash_address.h @@ -1,83 +1,37 @@ /* -hash.c version 20160210 +hash_address.h version 20160707 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)) +#include -#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);} +void setLayerADRS(uint32_t adrs[8], uint32_t layer); -#define SET_CHAIN_ADDRESS(a, v) {\ - a[13] = (v & 255);\ - a[12] = ((v >> 8) & 255);} +void setTreeADRS(uint32_t adrs[8], uint64_t tree); -/* - * 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;} +void setType(uint32_t adrs[8], uint32_t type); -#define SET_OTS_BIT(a, b) {\ - a[6] = (b & 1);\ - a[7] = 0;\ - a[8] = 0;} +void setKeyAndMask(uint32_t adrs[8], uint32_t keyAndMask); -#define SET_OTS_ADDRESS(a, v) {\ - a[11] = (v & 255);\ - a[10] = (v >> 8) & 255;\ - a[9] = (v >> 16) & 255;} +// OTS -#define ZEROISE_OTS_ADDR(a) {\ - a[12] = 0;\ - a[13] = 0;\ - a[14] = 0;\ - a[15] = 0;} +void setOTSADRS(uint32_t adrs[8], uint32_t ots); -#define SET_LTREE_BIT(a, b) {\ - a[7] = (a[7] & 0) | (b & 1);} +void setChainADRS(uint32_t adrs[8], uint32_t chain); -#define SET_LTREE_ADDRESS(a, v) {\ - a[10] = v & 255;\ - a[9] = (v >> 8) & 255;\ - a[8] = (v >> 16) & 255;} +void setHashADRS(uint32_t adrs[8], uint32_t hash); -#define SET_LTREE_TREE_HEIGHT(a, v) {\ - a[11] = (v & 255);} +// L-tree -#define SET_LTREE_TREE_INDEX(a, v) {\ - a[14] = (v & 255);\ - a[13] = (v >> 8) & 255;\ - a[12] = (v >> 16) & 3;} +void setLtreeADRS(uint32_t adrs[8], uint32_t ltree); -#define SET_NODE_PADDING(a) {\ - a[8] = 0;\ - a[9] = 0;\ - a[10] = 0;} +// Hash Tree & L-tree + +void setTreeHeight(uint32_t adrs[8], uint32_t treeHeight); + +void setTreeIndex(uint32_t adrs[8], uint32_t treeIndex); -#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 7170f9e..cb95b86 100644 --- a/prg.c +++ b/prg.c @@ -1,5 +1,5 @@ /* -prg.c version 20160210 +prg.c version 20160217 Andreas Hülsing Joost Rijneveld Public domain. diff --git a/prg.h b/prg.h index bd25e87..28f6c4f 100644 --- a/prg.h +++ b/prg.h @@ -1,5 +1,5 @@ /* -prg.h version 20160210 +prg.h version 20160217 Andreas Hülsing Joost Rijneveld Public domain. diff --git a/test/test_chacha.c b/test/test_chacha.c deleted file mode 100644 index 6ec2ddb..0000000 --- a/test/test_chacha.c +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include "../prg.h" - -static void hexdump(unsigned char *a, size_t len) -{ - size_t i; - for (i = 0; i < len; i++) - printf("%02x", a[i]); -} - - -int main() -{ - int n = 32; - unsigned char seed[32] = {0}; -// unsigned char seed[64] = {0,0}; - - unsigned char out[2*n]; - unsigned char addr[16] = {2}; - - printf("Case 1: All 0\n"); - prg(out, 2*n, seed, n); - - printf("\n"); - hexdump(out, 2*n); - printf("\n"); - - printf("Case 2: key = 1\n"); - seed[31] = 1; - prg_with_counter(out, seed, n, addr); - - printf("\n"); - hexdump(out, n); - printf("\n"); - return 0; -} diff --git a/test/test_wots.c b/test/test_wots.c index 146db3d..03dbf39 100644 --- a/test/test_wots.c +++ b/test/test_wots.c @@ -1,4 +1,6 @@ #include +#include +#include #include "../wots.h" #include "../randombytes.h" @@ -15,14 +17,14 @@ int main() unsigned char seed[n]; unsigned char pub_seed[n]; wots_params params; - wots_set_params(¶ms, n, n, 16); + wots_set_params(¶ms, n, 16); 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}; + uint32_t addr[8] = {1,2,3,4}; unsigned char msg[n]; int i; diff --git a/test/test_xmss.c b/test/test_xmss.c index 0931370..f7bedd2 100644 --- a/test/test_xmss.c +++ b/test/test_xmss.c @@ -14,20 +14,19 @@ int main() { int r; unsigned long long i; - unsigned int m = 32; unsigned int n = 32; unsigned int h = 8; unsigned int w = 16; unsigned long errors = 0; - unsigned char sk[3*n+4]; + unsigned char sk[4*n+4]; unsigned char pk[2*n]; xmss_params p; xmss_params *params = &p; - xmss_set_params(params, m, n, h, w); - unsigned long long signature_length = 4+m+params->wots_par.keysize+h*n; + xmss_set_params(params, n, h, w); + unsigned long long signature_length = 4+n+params->wots_par.keysize+h*n; unsigned char mo[MLEN+signature_length]; unsigned char sm[MLEN+signature_length]; @@ -38,7 +37,8 @@ int main() xmss_keypair(pk, sk, params); // check pub_seed in SK for (i = 0; i < n; i++) { - if (pk[n+i] != sk[4+m+n+i]) printf("pk.pub_seed != sk.pub_seed %llu",i); + if (pk[n+i] != sk[4+2*n+i]) printf("pk.pub_seed != sk.pub_seed %llu",i); + if (pk[i] != sk[4+3*n+i]) printf("pk.root != sk.root %llu",i); } // check index diff --git a/test/test_xmss_fast.c b/test/test_xmss_fast.c index bca8e10..d983c2b 100644 --- a/test/test_xmss_fast.c +++ b/test/test_xmss_fast.c @@ -11,11 +11,19 @@ unsigned char mi[MLEN]; unsigned long long smlen; unsigned long long mlen; +unsigned long long t1, t2; + +unsigned long long cpucycles(void) +{ + unsigned long long result; + asm volatile(".byte 15;.byte 49;shlq $32,%%rdx;orq %%rdx,%%rax" : "=a" (result) :: "%rdx"); + return result; +} + int main() { int r; unsigned long long i; - unsigned int m = 32; unsigned int n = 32; unsigned int h = 8; unsigned int w = 16; @@ -23,12 +31,12 @@ int main() unsigned long errors = 0; - unsigned char sk[3*n+4]; + unsigned char sk[4*n+4]; unsigned char pk[2*n]; xmss_params p; xmss_params *params = &p; - xmss_set_params(params, m, n, h, w, k); + xmss_set_params(params, n, h, w, k); // TODO should we hide this into xmss_fast.c and just allocate a large enough chunk of memory here? unsigned char stack[(h+1)*n]; @@ -45,7 +53,7 @@ int main() treehash[i].node = &th_nodes[n*i]; xmss_set_bds_state(state, stack, stackoffset, stacklevels, auth, keep, treehash, retain, 0); - unsigned long long signature_length = 4+m+params->wots_par.keysize+h*n; + unsigned long long signature_length = 4+n+params->wots_par.keysize+h*n; unsigned char mo[MLEN+signature_length]; unsigned char sm[MLEN+signature_length]; @@ -53,10 +61,18 @@ int main() for (i = 0; i < MLEN; i++) mi[i] = fgetc(urandom); printf("keypair\n"); + t1 = cpucycles(); xmss_keypair(pk, sk, state, params); + t2 = cpucycles(); + printf("cycles = %llu\n", (t2-t1)); + double sec = (t2-t1)/3500000; + printf("ms = %f\n", sec); + int read; + read = fgetc(stdin); // check pub_seed in SK for (i = 0; i < n; i++) { - if (pk[n+i] != sk[4+m+n+i]) printf("pk.pub_seed != sk.pub_seed %llu",i); + if (pk[n+i] != sk[4+2*n+i]) printf("pk.pub_seed != sk.pub_seed %llu",i); + if (pk[i] != sk[4+3*n+i]) printf("pk.root != sk.root %llu",i); } // check index diff --git a/test/test_xmssmt.c b/test/test_xmssmt.c index f11b275..ade53fa 100644 --- a/test/test_xmssmt.c +++ b/test/test_xmssmt.c @@ -14,7 +14,6 @@ int main() { int r; unsigned long long i,j; - unsigned int m = 32; unsigned int n = 32; unsigned int h = 20; unsigned int d = 5; @@ -22,12 +21,12 @@ int main() xmssmt_params p; xmssmt_params *params = &p; - xmssmt_set_params(params, m, n, h, d, w); + xmssmt_set_params(params, n, h, d, w); - unsigned char sk[(params->index_len+2*n+m)]; + unsigned char sk[(params->index_len+4*n)]; unsigned char pk[2*n]; - unsigned long long signature_length = params->index_len + m + (d*params->xmss_par.wots_par.keysize) + h*n; + unsigned long long signature_length = params->index_len + n + (d*params->xmss_par.wots_par.keysize) + h*n; unsigned char mo[MLEN+signature_length]; unsigned char sm[MLEN+signature_length]; @@ -38,7 +37,8 @@ int main() xmssmt_keypair(pk, sk, params); // check pub_seed in SK for (i = 0; i < n; i++) { - if (pk[n+i] != sk[params->index_len+m+n+i]) printf("pk.pub_seed != sk.pub_seed %llu",i); + if (pk[n+i] != sk[params->index_len+2*n+i]) printf("pk.pub_seed != sk.pub_seed %llu",i); + if (pk[i] != sk[4+3*n+i]) printf("pk.root != sk.root %llu",i); } printf("pk checked\n"); diff --git a/test/test_xmssmt_fast.c b/test/test_xmssmt_fast.c index ce3cb1c..b4aba60 100644 --- a/test/test_xmssmt_fast.c +++ b/test/test_xmssmt_fast.c @@ -14,7 +14,6 @@ int main() { int r; unsigned long long i,j; - unsigned int m = 32; unsigned int n = 32; unsigned int h = 12; unsigned int d = 3; @@ -23,7 +22,7 @@ int main() xmssmt_params p; xmssmt_params *params = &p; - if (xmssmt_set_params(params, m, n, h, d, w, k)) { + if (xmssmt_set_params(params, n, h, d, w, k)) { return 1; } @@ -54,10 +53,10 @@ int main() ); } - unsigned char sk[(params->index_len+2*n+m)]; + unsigned char sk[(params->index_len+4*n)]; unsigned char pk[2*n]; - unsigned long long signature_length = params->index_len + m + (d*params->xmss_par.wots_par.keysize) + h*n; + unsigned long long signature_length = params->index_len + n + (d*params->xmss_par.wots_par.keysize) + h*n; unsigned char mo[MLEN+signature_length]; unsigned char sm[MLEN+signature_length]; @@ -68,7 +67,8 @@ int main() xmssmt_keypair(pk, sk, states, wots_sigs, params); // check pub_seed in SK for (i = 0; i < n; i++) { - if (pk[n+i] != sk[params->index_len+m+n+i]) printf("pk.pub_seed != sk.pub_seed %llu",i); + if (pk[n+i] != sk[params->index_len+2*n+i]) printf("pk.pub_seed != sk.pub_seed %llu",i); + if (pk[i] != sk[4+3*n+i]) printf("pk.root != sk.root %llu",i); } printf("pk checked\n"); diff --git a/wots.c b/wots.c index bed5bc0..9ea1420 100644 --- a/wots.c +++ b/wots.c @@ -1,5 +1,5 @@ /* -wots.c version 20160210 +wots.c version 20160217 Andreas Hülsing Joost Rijneveld Public domain. @@ -7,21 +7,21 @@ Public domain. #include "math.h" #include "stdio.h" +#include "stdint.h" #include "xmss_commons.h" //#include "params.h" -#include "prg.h" +//#include "prg.h" #include "hash.h" #include "wots.h" #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 n, int w) { - params->m = m; params->n = n; params->w = w; params->log_w = (int) log2(w); - params->len_1 = (int) ceil(((8*m) / params->log_w)); + params->len_1 = (int) ceil(((8*n) / params->log_w)); params->len_2 = (int) floor(log2(params->len_1*(w-1)) / params->log_w) + 1; params->len = params->len_1 + params->len_2; params->keysize = params->len*params->n; @@ -30,11 +30,16 @@ void wots_set_params(wots_params *params, int m, int n, int w) /** * Helper method for pseudorandom key generation * Expands an n-byte array into a len*n byte array - * this is done using chacha20 with nonce 0 and counter 0 + * this is done using PRF */ static void expand_seed(unsigned char *outseeds, const unsigned char *inseed, const wots_params *params) { - prg(outseeds, params->keysize, inseed, params->n); + uint32_t i = 0; + unsigned char ctr[32]; + for(i = 0; i < params->len; i++){ + to_byte(ctr, i, 32); + prf((outseeds + (i*params->n)), ctr, inseed, params->n); + } } /** @@ -44,15 +49,15 @@ static void expand_seed(unsigned char *outseeds, const unsigned char *inseed, co * interpretes in as start-th value of the chain * addr has to contain the address of the chain */ -static void gen_chain(unsigned char *out, const unsigned char *in, unsigned int start, unsigned int steps, const wots_params *params, const unsigned char *pub_seed, unsigned char addr[16]) +static void gen_chain(unsigned char *out, const unsigned char *in, unsigned int start, unsigned int steps, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8]) { - unsigned int i, j; + uint32_t i, j; for (j = 0; j < params->n; j++) out[j] = in[j]; for (i = start; i < (start+steps) && i < params->w; i++) { - SET_HASH_ADDRESS(addr, i); - hash_n_n(out, out, pub_seed, addr, params->n); + setHashADRS(addr, i); + hash_f(out, out, pub_seed, addr, params->n); } } @@ -61,15 +66,15 @@ static void gen_chain(unsigned char *out, const unsigned char *in, unsigned int * * */ -static void base_w(int *output, const unsigned char *input, int in_len, const wots_params *params) +static void base_w(int *output, const int out_len, const unsigned char *input, const wots_params *params) { int in = 0; int out = 0; - int total = 0; + uint32_t total = 0; int bits = 0; int consumed = 0; - for (consumed = 0; consumed < 8 * in_len; consumed += params->log_w) { + for (consumed = 0; consumed < out_len; consumed++) { if (bits == 0) { total = input[in]; in++; @@ -81,24 +86,24 @@ static void base_w(int *output, const unsigned char *input, int in_len, const wo } } -void wots_pkgen(unsigned char *pk, const unsigned char *sk, const wots_params *params, const unsigned char *pub_seed, unsigned char addr[16]) +void wots_pkgen(unsigned char *pk, const unsigned char *sk, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8]) { - unsigned int i; + uint32_t i; expand_seed(pk, sk, params); for (i=0; i < params->len; i++) { - SET_CHAIN_ADDRESS(addr, i); + setChainADRS(addr, i); gen_chain(pk+i*params->n, pk+i*params->n, 0, params->w-1, params, pub_seed, addr); } } -void wots_sign(unsigned char *sig, const unsigned char *msg, const unsigned char *sk, const wots_params *params, const unsigned char *pub_seed, unsigned char addr[16]) +void wots_sign(unsigned char *sig, const unsigned char *msg, const unsigned char *sk, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8]) { int basew[params->len]; int csum = 0; - unsigned int i = 0; + uint32_t i = 0; - base_w(basew, msg, params->m, params); + base_w(basew, params->len_1, msg, params); for (i=0; i < params->len_1; i++) { csum += params->w - 1 - basew[i]; @@ -112,7 +117,7 @@ void wots_sign(unsigned char *sig, const unsigned char *msg, const unsigned char to_byte(csum_bytes, csum, len_2_bytes); int csum_basew[len_2_bytes / params->log_w]; - base_w(csum_basew, csum_bytes, len_2_bytes, params); + base_w(csum_basew, params->len_2, csum_bytes, params); for (i = 0; i < params->len_2; i++) { basew[params->len_1 + i] = csum_basew[i]; @@ -121,18 +126,18 @@ void wots_sign(unsigned char *sig, const unsigned char *msg, const unsigned char expand_seed(sig, sk, params); for (i = 0; i < params->len; i++) { - SET_CHAIN_ADDRESS(addr, i); + setChainADRS(addr, i); gen_chain(sig+i*params->n, sig+i*params->n, 0, basew[i], params, pub_seed, addr); } } -void wots_pkFromSig(unsigned char *pk, const unsigned char *sig, const unsigned char *msg, const wots_params *params, const unsigned char *pub_seed, unsigned char addr[16]) +void wots_pkFromSig(unsigned char *pk, const unsigned char *sig, const unsigned char *msg, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8]) { int basew[params->len]; int csum = 0; - unsigned int i = 0; + uint32_t i = 0; - base_w(basew, msg, params->m, params); + base_w(basew, params->len_1, msg, params); for (i=0; i < params->len_1; i++) { csum += params->w - 1 - basew[i]; @@ -146,13 +151,13 @@ void wots_pkFromSig(unsigned char *pk, const unsigned char *sig, const unsigned to_byte(csum_bytes, csum, len_2_bytes); int csum_basew[len_2_bytes / params->log_w]; - base_w(csum_basew, csum_bytes, len_2_bytes, params); + base_w(csum_basew, params->len_2, csum_bytes, params); for (i = 0; i < params->len_2; i++) { basew[params->len_1 + i] = csum_basew[i]; } for (i=0; i < params->len; i++) { - SET_CHAIN_ADDRESS(addr, i); + setChainADRS(addr, i); gen_chain(pk+i*params->n, sig+i*params->n, basew[i], params->w-1-basew[i], params, pub_seed, addr); } } diff --git a/wots.h b/wots.h index a5b846c..bcce6a5 100644 --- a/wots.h +++ b/wots.h @@ -1,5 +1,5 @@ /* -wots.h version 20160210 +wots.h version 20160217 Andreas Hülsing Joost Rijneveld Public domain. @@ -8,20 +8,21 @@ Public domain. #ifndef WOTS_H #define WOTS_H +#include "stdint.h" + /** * WOTS parameter set * * Meaning as defined in draft-irtf-cfrg-xmss-hash-based-signatures-02 */ typedef struct { - unsigned int len_1; - unsigned int len_2; - unsigned int len; - unsigned int m; - unsigned int n; - unsigned int w; - unsigned int log_w; - unsigned int keysize; + uint32_t len_1; + uint32_t len_2; + uint32_t len; + uint32_t n; + uint32_t w; + uint32_t log_w; + uint32_t keysize; } wots_params; /** @@ -31,7 +32,7 @@ typedef struct { * * Assumes w is a power of 2 */ -void wots_set_params(wots_params *params, int m, int n, int w); +void wots_set_params(wots_params *params, int n, int w); /** * WOTS key generation. Takes a 32byte seed for the secret key, expands it to a full WOTS secret key and computes the corresponding public key. @@ -41,18 +42,18 @@ void wots_set_params(wots_params *params, int m, int n, int w); * * Places the computed public key at address pk. */ -void wots_pkgen(unsigned char *pk, const unsigned char *sk, const wots_params *params, const unsigned char *pub_seed, unsigned char addr[16]); +void wots_pkgen(unsigned char *pk, const unsigned char *sk, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8]); /** * Takes a m-byte message and the 32-byte seed for the secret key to compute a signature that is placed at "sig". * */ -void wots_sign(unsigned char *sig, const unsigned char *msg, const unsigned char *sk, const wots_params *params, const unsigned char *pub_seed, unsigned char addr[16]); +void wots_sign(unsigned char *sig, const unsigned char *msg, const unsigned char *sk, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8]); /** * Takes a WOTS signature, a m-byte message and computes a WOTS public key that it places at pk. * */ -void wots_pkFromSig(unsigned char *pk, const unsigned char *sig, const unsigned char *msg, const wots_params *params, const unsigned char *pub_seed, unsigned char addr[16]); +void wots_pkFromSig(unsigned char *pk, const unsigned char *sig, const unsigned char *msg, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8]); #endif diff --git a/xmss.c b/xmss.c index a5d137b..c7188e0 100644 --- a/xmss.c +++ b/xmss.c @@ -1,5 +1,5 @@ /* -xmss.c version 20160210 +xmss.c version 20160217 Andreas Hülsing Joost Rijneveld Public domain. @@ -14,7 +14,7 @@ Public domain. #include "randombytes.h" #include "wots.h" #include "hash.h" -#include "prg.h" +//#include "prg.h" #include "xmss_commons.h" #include "hash_address.h" @@ -26,27 +26,28 @@ Public domain. * 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. + * takes n byte sk_seed and returns n byte seed using 32 byte address addr. */ -static void get_seed(unsigned char *seed, const unsigned char *sk_seed, int n, unsigned char addr[16]) +static void get_seed(unsigned char *seed, const unsigned char *sk_seed, int n, uint32_t addr[8]) { // Make sure that chain addr, hash addr, and key bit are 0! - ZEROISE_OTS_ADDR(addr); + setChainADRS(addr,0); + setHashADRS(addr,0); + setKeyAndMask(addr,0); // Generate pseudorandom value - prg_with_counter(seed, sk_seed, n, addr); + prf(seed, (unsigned char*) addr, sk_seed, n); } /** * Initialize xmss params struct * parameter names are the same as in the draft */ -void xmss_set_params(xmss_params *params, int m, int n, int h, int w) +void xmss_set_params(xmss_params *params, int n, int h, int w) { params->h = h; - params->m = m; params->n = n; wots_params wots_par; - wots_set_params(&wots_par, m, n, w); + wots_set_params(&wots_par, n, w); params->wots_par = wots_par; } @@ -56,7 +57,7 @@ void xmss_set_params(xmss_params *params, int m, int n, int h, int w) * * Especially h is the total tree height, i.e. the XMSS trees have height h/d */ -void xmssmt_set_params(xmssmt_params *params, int m, int n, int h, int d, int w) +void xmssmt_set_params(xmssmt_params *params, int n, int h, int d, int w) { if (h % d) { fprintf(stderr, "d must devide h without remainder!\n"); @@ -64,34 +65,34 @@ void xmssmt_set_params(xmssmt_params *params, int m, int n, int h, int d, int w) } params->h = h; params->d = d; - params->m = m; params->n = n; params->index_len = (h + 7) / 8; xmss_params xmss_par; - xmss_set_params(&xmss_par, m, n, (h/d), w); + xmss_set_params(&xmss_par, n, (h/d), w); params->xmss_par = xmss_par; } /** * Computes a leaf from a WOTS public key using an L-tree. */ -static void l_tree(unsigned char *leaf, unsigned char *wots_pk, const xmss_params *params, const unsigned char *pub_seed, unsigned char addr[16]) +static void l_tree(unsigned char *leaf, unsigned char *wots_pk, const xmss_params *params, const unsigned char *pub_seed, uint32_t addr[8]) { unsigned int l = params->wots_par.len; unsigned int n = params->n; - unsigned long i = 0; - unsigned int height = 0; + uint32_t i = 0; + uint32_t height = 0; + uint32_t bound; //ADRS.setTreeHeight(0); - SET_LTREE_TREE_HEIGHT(addr, height); - unsigned long bound; + setTreeHeight(addr, height); + while (l > 1) { bound = l >> 1; //floor(l / 2); for (i = 0; i < bound; i++) { //ADRS.setTreeIndex(i); - SET_LTREE_TREE_INDEX(addr, i); + setTreeIndex(addr, i); //wots_pk[i] = RAND_HASH(pk[2i], pk[2i + 1], SEED, ADRS); - hash_2n_n(wots_pk+i*n, wots_pk+i*2*n, pub_seed, addr, n); + hash_h(wots_pk+i*n, wots_pk+i*2*n, pub_seed, addr, n); } //if ( l % 2 == 1 ) { if (l & 1) { @@ -106,7 +107,7 @@ static void l_tree(unsigned char *leaf, unsigned char *wots_pk, const xmss_param } //ADRS.setTreeHeight(ADRS.getTreeHeight() + 1); height++; - SET_LTREE_TREE_HEIGHT(addr, height); + setTreeHeight(addr, height); } //return pk[0]; memcpy(leaf, wots_pk, n); @@ -115,7 +116,7 @@ static void l_tree(unsigned char *leaf, unsigned char *wots_pk, const xmss_param /** * Computes the leaf at a given address. First generates the WOTS key pair, then computes leaf using l_tree. As this happens position independent, we only require that addr encodes the right ltree-address. */ -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]) +static void gen_leaf_wots(unsigned char *leaf, const unsigned char *sk_seed, const xmss_params *params, const unsigned char *pub_seed, uint32_t ltree_addr[8], uint32_t ots_addr[8]) { unsigned char seed[params->n]; unsigned char pk[params->wots_par.keysize]; @@ -131,41 +132,41 @@ static void gen_leaf_wots(unsigned char *leaf, const unsigned char *sk_seed, con * Currently only used for key generation. * */ -static void treehash(unsigned char *node, int height, int index, const unsigned char *sk_seed, const xmss_params *params, const unsigned char *pub_seed, const unsigned char addr[16]) +static void treehash(unsigned char *node, uint16_t height, uint32_t index, const unsigned char *sk_seed, const xmss_params *params, const unsigned char *pub_seed, const uint32_t addr[8]) { - unsigned int idx = index; - unsigned int n = params->n; + uint32_t idx = index; + uint16_t n = params->n; // use three different addresses because at this point we use all three formats in parallel - unsigned char ots_addr[16]; - unsigned char ltree_addr[16]; - unsigned char node_addr[16]; - memcpy(ots_addr, addr, 10); - SET_OTS_BIT(ots_addr, 1); - memcpy(ltree_addr, addr, 10); - SET_OTS_BIT(ltree_addr, 0); - SET_LTREE_BIT(ltree_addr, 1); - memcpy(node_addr, ltree_addr, 10); - SET_LTREE_BIT(node_addr, 0); - SET_NODE_PADDING(node_addr); + uint32_t ots_addr[8]; + uint32_t ltree_addr[8]; + uint32_t node_addr[8]; + // only copy layer and tree address parts + memcpy(ots_addr, addr, 12); + // type = ots + setType(ots_addr, 0); + memcpy(ltree_addr, addr, 12); + setType(ltree_addr, 1); + memcpy(node_addr, addr, 12); + setType(node_addr, 2); - unsigned int lastnode, i; + uint32_t lastnode, i; unsigned char stack[(height+1)*n]; - unsigned int stacklevels[height+1]; + uint16_t stacklevels[height+1]; unsigned int stackoffset=0; lastnode = idx+(1 << height); for (; idx < lastnode; idx++) { - SET_LTREE_ADDRESS(ltree_addr, idx); - SET_OTS_ADDRESS(ots_addr, idx); + setLtreeADRS(ltree_addr, idx); + setOTSADRS(ots_addr, idx); gen_leaf_wots(stack+stackoffset*n, sk_seed, params, pub_seed, ltree_addr, ots_addr); stacklevels[stackoffset] = 0; stackoffset++; while (stackoffset>1 && stacklevels[stackoffset-1] == stacklevels[stackoffset-2]) { - SET_NODE_TREE_HEIGHT(node_addr, stacklevels[stackoffset-1]); - SET_NODE_TREE_INDEX(node_addr, (idx >> (stacklevels[stackoffset-1]+1))); - hash_2n_n(stack+(stackoffset-2)*n, stack+(stackoffset-2)*n, pub_seed, + setTreeHeight(node_addr, stacklevels[stackoffset-1]); + setTreeIndex(node_addr, (idx >> (stacklevels[stackoffset-1]+1))); + hash_h(stack+(stackoffset-2)*n, stack+(stackoffset-2)*n, pub_seed, node_addr, n); stacklevels[stackoffset-2]++; stackoffset--; @@ -178,11 +179,11 @@ static void treehash(unsigned char *node, int height, int index, const unsigned /** * Computes a root node given a leaf and an authapth */ -static void validate_authpath(unsigned char *root, const unsigned char *leaf, unsigned long leafidx, const unsigned char *authpath, const xmss_params *params, const unsigned char *pub_seed, unsigned char addr[16]) +static void validate_authpath(unsigned char *root, const unsigned char *leaf, unsigned long leafidx, const unsigned char *authpath, const xmss_params *params, const unsigned char *pub_seed, uint32_t addr[8]) { unsigned int n = params->n; - unsigned int i, j; + uint32_t i, j; unsigned char buffer[2*n]; // If leafidx is odd (last bit = 1), current path element is a right child and authpath has to go to the left. @@ -202,25 +203,25 @@ static void validate_authpath(unsigned char *root, const unsigned char *leaf, un authpath += n; for (i=0; i < params->h-1; i++) { - SET_NODE_TREE_HEIGHT(addr, i); + setTreeHeight(addr, i); leafidx >>= 1; - SET_NODE_TREE_INDEX(addr, leafidx); + setTreeIndex(addr, leafidx); if (leafidx&1) { - hash_2n_n(buffer+n, buffer, pub_seed, addr, n); + hash_h(buffer+n, buffer, pub_seed, addr, n); for (j = 0; j < n; j++) buffer[j] = authpath[j]; } else { - hash_2n_n(buffer, buffer, pub_seed, addr, n); + hash_h(buffer, buffer, pub_seed, addr, n); for (j = 0; j < n; j++) buffer[j+n] = authpath[j]; } authpath += n; } - SET_NODE_TREE_HEIGHT(addr, (params->h-1)); + setTreeHeight(addr, (params->h-1)); leafidx >>= 1; - SET_NODE_TREE_INDEX(addr, leafidx); - hash_2n_n(root, buffer, pub_seed, addr, n); + setTreeIndex(addr, leafidx); + hash_h(root, buffer, pub_seed, addr, n); } /** @@ -228,32 +229,29 @@ static void validate_authpath(unsigned char *root, const unsigned char *leaf, un * For more efficient algorithms see e.g. the chapter on hash-based signatures in Bernstein, Buchmann, Dahmen. "Post-quantum Cryptography", Springer 2009. * It returns the authpath in "authpath" with the node on level 0 at index 0. */ -static void compute_authpath_wots(unsigned char *root, unsigned char *authpath, unsigned long leaf_idx, const unsigned char *sk_seed, const xmss_params *params, unsigned char *pub_seed, unsigned char addr[16]) +static void compute_authpath_wots(unsigned char *root, unsigned char *authpath, unsigned long leaf_idx, const unsigned char *sk_seed, const xmss_params *params, unsigned char *pub_seed, uint32_t addr[8]) { - unsigned int i, j, level; - unsigned int n = params->n; - unsigned int h = params->h; + uint32_t i, j, level; + uint32_t n = params->n; + uint32_t h = params->h; unsigned char tree[2*(1< 1; i>>=1) { - SET_NODE_TREE_HEIGHT(node_addr, level); + setTreeHeight(node_addr, level); // Inner loop: for each pair of sibling nodes for (j = 0; j < i; j+=2) { - SET_NODE_TREE_INDEX(node_addr, j>>1); - hash_2n_n(tree + (i>>1)*n + (j>>1) * n, tree + i*n + j*n, pub_seed, node_addr, n); + setTreeIndex(node_addr, j>>1); + hash_h(tree + (i>>1)*n + (j>>1) * n, tree + i*n + j*n, pub_seed, node_addr, n); } level++; } @@ -282,26 +280,27 @@ static void compute_authpath_wots(unsigned char *root, unsigned char *authpath, /* * Generates a XMSS key pair for a given parameter set. - * Format sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED] + * Format sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] omitting algo oid. */ int xmss_keypair(unsigned char *pk, unsigned char *sk, xmss_params *params) { unsigned int n = params->n; - unsigned int m = params->m; // Set idx = 0 sk[0] = 0; sk[1] = 0; sk[2] = 0; sk[3] = 0; - // Init SK_SEED (n byte), SK_PRF (m byte), and PUB_SEED (n byte) - randombytes(sk+4, 2*n+m); + // Init SK_SEED (n byte), SK_PRF (n byte), and PUB_SEED (n byte) + randombytes(sk+4, 3*n); // Copy PUB_SEED to public key - memcpy(pk+n, sk+4+n+m, n); + memcpy(pk+n, sk+4+2*n, n); - unsigned char addr[16] = {0, 0, 0, 0}; + uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; // Compute root - treehash(pk, params->h, 0, sk+4, params, sk+4+n+m, addr); + treehash(pk, params->h, 0, sk+4, params, sk+4+2*n, addr); + // copy root to sk + memcpy(sk+4+3*n, pk, n); return 0; } @@ -314,26 +313,24 @@ int xmss_keypair(unsigned char *pk, unsigned char *sk, xmss_params *params) */ int xmss_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg, unsigned long long msglen, const xmss_params *params) { - unsigned int n = params->n; - unsigned int m = params->m; + uint16_t n = params->n; + uint16_t i = 0; // Extract SK - unsigned long idx = ((unsigned long)sk[0] << 24) | ((unsigned long)sk[1] << 16) | ((unsigned long)sk[2] << 8) | sk[3]; + uint32_t idx = ((unsigned long)sk[0] << 24) | ((unsigned long)sk[1] << 16) | ((unsigned long)sk[2] << 8) | sk[3]; unsigned char sk_seed[n]; memcpy(sk_seed, sk+4, n); - unsigned char sk_prf[m]; - memcpy(sk_prf, sk+4+n, m); + unsigned char sk_prf[n]; + memcpy(sk_prf, sk+4+n, n); unsigned char pub_seed[n]; - memcpy(pub_seed, sk+4+n+m, n); + memcpy(pub_seed, sk+4+2*n, 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]; - } + // index as 32 bytes string + unsigned char idx_bytes_32[32]; + to_byte(idx_bytes_32, idx, 32); + + + unsigned char hash_key[3*n]; // Update SK sk[0] = ((idx + 1) >> 24) & 255; @@ -344,11 +341,11 @@ 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 char R[m]; - unsigned char msg_h[m]; + unsigned char R[n]; + unsigned char msg_h[n]; unsigned char root[n]; unsigned char ots_seed[n]; - unsigned char ots_addr[16] = {0, 0, 0, 0}; + uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; // --------------------------------- // Message Hashing @@ -356,11 +353,13 @@ int xmss_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *sig // Message Hash: // First compute pseudorandom value - prf_m(R, msg, msglen, sk_prf, m); - // Generate hash key (idx || R) - memcpy(hash_key+m, R, m); + prf(R, idx_bytes_32, sk_prf, n); + // Generate hash key (R || root || idx) + memcpy(hash_key, R, n); + memcpy(hash_key+n, sk+4+3*n, n); + to_byte(hash_key+2*n, idx, n); // Then use it for message digest - hash_m(msg_h, msg, msglen, hash_key, 2*m, m); + h_msg(msg_h, msg, msglen, hash_key, 3*n, n); // Start collecting signature *sig_msg_len = 0; @@ -375,19 +374,19 @@ int xmss_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *sig *sig_msg_len += 4; // Copy R to signature - for (i = 0; i < m; i++) + for (i = 0; i < n; i++) sig_msg[i] = R[i]; - sig_msg += m; - *sig_msg_len += m; + sig_msg += n; + *sig_msg_len += n; // ---------------------------------- // Now we start to "really sign" // ---------------------------------- // Prepare Address - SET_OTS_BIT(ots_addr, 1); - SET_OTS_ADDRESS(ots_addr, idx); + setType(ots_addr, 0); + setOTSADRS(ots_addr, idx); // Compute seed for OTS key pair get_seed(ots_seed, sk_seed, n, ots_addr); @@ -416,58 +415,52 @@ int xmss_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *sig */ int xmss_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigned char *sig_msg, unsigned long long sig_msg_len, const unsigned char *pk, const xmss_params *params) { - unsigned int n = params->n; - unsigned int m = params->m; - + uint16_t n = params->n; + unsigned long long i, m_len; unsigned long idx=0; unsigned char wots_pk[params->wots_par.keysize]; unsigned char pkhash[n]; unsigned char root[n]; - unsigned char msg_h[m]; - unsigned char hash_key[2*m]; + unsigned char msg_h[n]; + unsigned char hash_key[3*n]; unsigned char pub_seed[n]; memcpy(pub_seed, pk+n, n); // Init addresses - unsigned char ots_addr[16] = {0, 0, 0, 0}; - unsigned char ltree_addr[16]; - unsigned char node_addr[16]; - - SET_OTS_BIT(ots_addr, 1); - - memcpy(ltree_addr, ots_addr, 10); - SET_OTS_BIT(ltree_addr, 0); - SET_LTREE_BIT(ltree_addr, 1); - - memcpy(node_addr, ltree_addr, 10); - SET_LTREE_BIT(node_addr, 0); - SET_NODE_PADDING(node_addr); + uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + uint32_t ltree_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + uint32_t node_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + setType(ots_addr, 0); + setType(ltree_addr, 1); + setType(node_addr, 2); + // 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); - 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); + + // Generate hash key (R || root || idx) + memcpy(hash_key, sig_msg+4,n); + memcpy(hash_key+n, pk, n); + to_byte(hash_key+2*n, idx, n); + + sig_msg += (n+4); + sig_msg_len -= (n+4); + // 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, hash_key, 2*m, m); + h_msg(msg_h, sig_msg + tmp_sig_len, m_len, hash_key, 3*n, n); //----------------------- // Verify signature //----------------------- // Prepare Address - SET_OTS_ADDRESS(ots_addr, idx); + setOTSADRS(ots_addr, idx); // Check WOTS signature wots_pkFromSig(wots_pk, sig_msg, msg_h, &(params->wots_par), pub_seed, ots_addr); @@ -475,7 +468,7 @@ int xmss_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigne sig_msg_len -= params->wots_par.keysize; // Compute Ltree - SET_LTREE_ADDRESS(ltree_addr, idx); + setLtreeADRS(ltree_addr, idx); l_tree(pkhash, wots_pk, params, pub_seed, ltree_addr); // Compute root @@ -511,23 +504,23 @@ fail: int xmssmt_keypair(unsigned char *pk, unsigned char *sk, xmssmt_params *params) { unsigned int n = params->n; - unsigned int m = params->m; - unsigned int i; + uint16_t i; // Set idx = 0 for (i = 0; i < params->index_len; i++) { sk[i] = 0; } - // Init SK_SEED (n byte), SK_PRF (m byte), and PUB_SEED (n byte) - randombytes(sk+params->index_len, 2*n+m); + // Init SK_SEED (n byte), SK_PRF (n byte), and PUB_SEED (n byte) + randombytes(sk+params->index_len, 3*n); // Copy PUB_SEED to public key - memcpy(pk+n, sk+params->index_len+n+m, n); + memcpy(pk+n, sk+params->index_len+2*n, n); // Set address to point on the single tree on layer d-1 - unsigned char addr[16] = {0, 0, 0, 0}; - SET_LAYER_ADDRESS(addr, (params->d-1)); + uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + setLayerADRS(addr, (params->d-1)); // Compute root treehash(pk, params->xmss_par.h, 0, sk+params->index_len, &(params->xmss_par), pk+n, addr); + memcpy(sk+params->index_len+3*n, pk, n); return 0; } @@ -541,37 +534,33 @@ int xmssmt_keypair(unsigned char *pk, unsigned char *sk, xmssmt_params *params) int xmssmt_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg, unsigned long long msglen, const xmssmt_params *params) { unsigned int n = params->n; - unsigned int m = params->m; unsigned int tree_h = params->xmss_par.h; unsigned int idx_len = params->index_len; - unsigned long long idx_tree; - unsigned long long idx_leaf; - unsigned long long i; + uint64_t idx_tree; + uint32_t idx_leaf; + uint64_t i; unsigned char sk_seed[n]; - unsigned char sk_prf[m]; + unsigned char sk_prf[n]; 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 R[n]; + unsigned char hash_key[3*n]; + unsigned char msg_h[n]; unsigned char root[n]; unsigned char ots_seed[n]; - unsigned char ots_addr[16] = {0, 0, 0, 0}; + uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + unsigned char idx_bytes_32[32]; // 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); - memcpy(sk_prf, sk+idx_len+n, m); - memcpy(pub_seed, sk+idx_len+n+m, n); + memcpy(sk_prf, sk+idx_len+n, n); + memcpy(pub_seed, sk+idx_len+2*n, n); // Update SK for (i = 0; i < idx_len; i++) { @@ -586,14 +575,16 @@ 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); + // First compute pseudorandom value + to_byte(idx_bytes_32, idx, 32); + prf(R, idx_bytes_32, sk_prf, n); + // Generate hash key (R || root || idx) + memcpy(hash_key, R, n); + memcpy(hash_key+n, sk+idx_len+3*n, n); + to_byte(hash_key+2*n, idx, n); // Then use it for message digest - hash_m(msg_h, msg, msglen, hash_key, 2*m, m); + h_msg(msg_h, msg, msglen, hash_key, 3*n, n); // Start collecting signature *sig_msg_len = 0; @@ -607,11 +598,11 @@ int xmssmt_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *s *sig_msg_len += idx_len; // Copy R to signature - for (i=0; i < m; i++) + for (i=0; i < n; i++) sig_msg[i] = R[i]; - sig_msg += m; - *sig_msg_len += m; + sig_msg += n; + *sig_msg_len += n; // ---------------------------------- // Now we start to "really sign" @@ -620,12 +611,12 @@ int xmssmt_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *s // Handle lowest layer separately as it is slightly different... // Prepare Address - SET_OTS_BIT(ots_addr, 1); + setType(ots_addr, 0); idx_tree = idx >> tree_h; idx_leaf = (idx & ((1 << tree_h)-1)); - SET_LAYER_ADDRESS(ots_addr, 0); - SET_TREE_ADDRESS(ots_addr, idx_tree); - SET_OTS_ADDRESS(ots_addr, idx_leaf); + setLayerADRS(ots_addr, 0); + setTreeADRS(ots_addr, idx_tree); + setOTSADRS(ots_addr, idx_leaf); // Compute seed for OTS key pair get_seed(ots_seed, sk_seed, n, ots_addr); @@ -646,9 +637,9 @@ int xmssmt_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *s // Prepare Address idx_leaf = (idx_tree & ((1 << tree_h)-1)); idx_tree = idx_tree >> tree_h; - SET_LAYER_ADDRESS(ots_addr, j); - SET_TREE_ADDRESS(ots_addr, idx_tree); - SET_OTS_ADDRESS(ots_addr, idx_leaf); + setLayerADRS(ots_addr, j); + setTreeADRS(ots_addr, idx_tree); + setOTSADRS(ots_addr, idx_leaf); // Compute seed for OTS key pair get_seed(ots_seed, sk_seed, n, ots_addr); @@ -679,52 +670,48 @@ int xmssmt_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *s int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigned char *sig_msg, unsigned long long sig_msg_len, const unsigned char *pk, const xmssmt_params *params) { unsigned int n = params->n; - unsigned int m = params->m; unsigned int tree_h = params->xmss_par.h; unsigned int idx_len = params->index_len; - unsigned long long idx_tree; - unsigned long long idx_leaf; + uint64_t idx_tree; + uint32_t idx_leaf; unsigned long long i, m_len; unsigned long long idx=0; unsigned char wots_pk[params->xmss_par.wots_par.keysize]; unsigned char pkhash[n]; unsigned char root[n]; - unsigned char msg_h[m]; - unsigned char hash_key[2*m]; + unsigned char msg_h[n]; + unsigned char hash_key[3*n]; unsigned char pub_seed[n]; memcpy(pub_seed, pk+n, n); // Init addresses - unsigned char ots_addr[16] = {0, 0, 0, 0}; - unsigned char ltree_addr[16]; - unsigned char node_addr[16]; + uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + uint32_t ltree_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + uint32_t node_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; // 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; - for(i = 0; i < m; i++){ - hash_key[m+i] = sig_msg[i]; - } + // Generate hash key (R || root || idx) + memcpy(hash_key, sig_msg,n); + memcpy(hash_key+n, pk, n); + to_byte(hash_key+2*n, idx, n); - sig_msg += m; - sig_msg_len -= m; + sig_msg += n; + sig_msg_len -= n; - // hash message (recall, R is now on pole position at sig_msg + // hash message 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); + h_msg(msg_h, sig_msg + tmp_sig_len, m_len, hash_key, 3*n, n); //----------------------- @@ -734,19 +721,17 @@ int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsig // Prepare Address idx_tree = idx >> tree_h; idx_leaf = (idx & ((1 << tree_h)-1)); - SET_LAYER_ADDRESS(ots_addr, 0); - SET_TREE_ADDRESS(ots_addr, idx_tree); - SET_OTS_BIT(ots_addr, 1); + setLayerADRS(ots_addr, 0); + setTreeADRS(ots_addr, idx_tree); + setType(ots_addr, 0); - memcpy(ltree_addr, ots_addr, 10); - SET_OTS_BIT(ltree_addr, 0); - SET_LTREE_BIT(ltree_addr, 1); + memcpy(ltree_addr, ots_addr, 12); + setType(ltree_addr, 1); - memcpy(node_addr, ltree_addr, 10); - SET_LTREE_BIT(node_addr, 0); - SET_NODE_PADDING(node_addr); - - SET_OTS_ADDRESS(ots_addr, idx_leaf); + memcpy(node_addr, ltree_addr, 12); + setType(node_addr, 2); + + setOTSADRS(ots_addr, idx_leaf); // Check WOTS signature wots_pkFromSig(wots_pk, sig_msg, msg_h, &(params->xmss_par.wots_par), pub_seed, ots_addr); @@ -755,7 +740,7 @@ int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsig sig_msg_len -= params->xmss_par.wots_par.keysize; // Compute Ltree - SET_LTREE_ADDRESS(ltree_addr, idx_leaf); + setLtreeADRS(ltree_addr, idx_leaf); l_tree(pkhash, wots_pk, &(params->xmss_par), pub_seed, ltree_addr); // Compute root @@ -769,19 +754,17 @@ int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsig idx_leaf = (idx_tree & ((1 << tree_h)-1)); idx_tree = idx_tree >> tree_h; - SET_LAYER_ADDRESS(ots_addr, i); - SET_TREE_ADDRESS(ots_addr, idx_tree); - SET_OTS_BIT(ots_addr, 1); + setLayerADRS(ots_addr, i); + setTreeADRS(ots_addr, idx_tree); + setType(ots_addr, 0); - memcpy(ltree_addr, ots_addr, 10); - SET_OTS_BIT(ltree_addr, 0); - SET_LTREE_BIT(ltree_addr, 1); + memcpy(ltree_addr, ots_addr, 12); + setType(ltree_addr, 1); - memcpy(node_addr, ltree_addr, 10); - SET_LTREE_BIT(node_addr, 0); - SET_NODE_PADDING(node_addr); + memcpy(node_addr, ltree_addr, 12); + setType(node_addr, 2); - SET_OTS_ADDRESS(ots_addr, idx_leaf); + setOTSADRS(ots_addr, idx_leaf); // Check WOTS signature wots_pkFromSig(wots_pk, sig_msg, root, &(params->xmss_par.wots_par), pub_seed, ots_addr); @@ -790,7 +773,7 @@ int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsig sig_msg_len -= params->xmss_par.wots_par.keysize; // Compute Ltree - SET_LTREE_ADDRESS(ltree_addr, idx_leaf); + setLtreeADRS(ltree_addr, idx_leaf); l_tree(pkhash, wots_pk, &(params->xmss_par), pub_seed, ltree_addr); // Compute root diff --git a/xmss.h b/xmss.h index 3295db3..9ae2659 100644 --- a/xmss.h +++ b/xmss.h @@ -1,5 +1,5 @@ /* -xmss.h version 20160210 +xmss.h version 20160217 Andreas Hülsing Joost Rijneveld Public domain. @@ -18,14 +18,12 @@ typedef struct{ typedef struct{ wots_params wots_par; unsigned int n; - unsigned int m; unsigned int h; } xmss_params; typedef struct{ xmss_params xmss_par; unsigned int n; - unsigned int m; unsigned int h; unsigned int d; unsigned int index_len; @@ -34,17 +32,17 @@ typedef struct{ * Initializes parameter set. * Needed, for any of the other methods. */ -void xmss_set_params(xmss_params *params, int m, int n, int h, int w); +void xmss_set_params(xmss_params *params, int n, int h, int w); /** * Initialize xmssmt_params struct * parameter names are the same as in the draft * * Especially h is the total tree height, i.e. the XMSS trees have height h/d */ -void xmssmt_set_params(xmssmt_params *params, int m, int n, int h, int d, int w); +void xmssmt_set_params(xmssmt_params *params, int n, int h, int d, int w); /** * Generates a XMSS key pair for a given parameter set. - * Format sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED] + * Format sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] omitting algo oid. */ int xmss_keypair(unsigned char *pk, unsigned char *sk, xmss_params *params); @@ -65,7 +63,7 @@ int xmss_sign_open(unsigned char *msg,unsigned long long *msglen, const unsigned /* * Generates a XMSSMT key pair for a given parameter set. - * Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED] + * Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] omitting algo oid. */ int xmssmt_keypair(unsigned char *pk, unsigned char *sk, xmssmt_params *params); diff --git a/xmss_commons.c b/xmss_commons.c index 4c97b79..617dc7e 100644 --- a/xmss_commons.c +++ b/xmss_commons.c @@ -1,5 +1,5 @@ /* -xmss_commons.c 20160210 +xmss_commons.c 20160217 Andreas Hülsing Joost Rijneveld Public domain. @@ -8,10 +8,11 @@ Public domain. #include "xmss_commons.h" #include #include +#include -void to_byte(unsigned char *out, unsigned int in, int bytes) +void to_byte(unsigned char *out, unsigned long long in, uint32_t bytes) { - int i; + int32_t i; for (i = bytes-1; i >= 0; i--) { out[i] = in & 0xff; in = in >> 8; diff --git a/xmss_commons.h b/xmss_commons.h index 4c6b982..f5e6d7a 100644 --- a/xmss_commons.h +++ b/xmss_commons.h @@ -1,5 +1,5 @@ /* -xmss_commons.h 20160210 +xmss_commons.h 20160217 Andreas Hülsing Joost Rijneveld Public domain. @@ -8,7 +8,8 @@ Public domain. #define XMSS_COMMONS_H #include +#include -void to_byte(unsigned char *output, unsigned int in, int bytes); +void to_byte(unsigned char *output, unsigned long long in, uint32_t bytes); void hexdump(const unsigned char *a, size_t len); #endif \ No newline at end of file diff --git a/xmss_fast.c b/xmss_fast.c index f770ad5..4ef3e08 100644 --- a/xmss_fast.c +++ b/xmss_fast.c @@ -1,5 +1,5 @@ /* -xmss_fast.c version 20160210 +xmss_fast.c version 20160217 Andreas Hülsing Joost Rijneveld Public domain. @@ -14,7 +14,7 @@ Public domain. #include "randombytes.h" #include "wots.h" #include "hash.h" -#include "prg.h" + #include "xmss_commons.h" #include "hash_address.h" // For testing @@ -26,14 +26,16 @@ Public domain. * 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. + * takes n byte sk_seed and returns n byte seed using 32 byte address addr. */ -static void get_seed(unsigned char *seed, const unsigned char *sk_seed, int n, unsigned char addr[16]) +static void get_seed(unsigned char *seed, const unsigned char *sk_seed, int n, uint32_t addr[8]) { // Make sure that chain addr, hash addr, and key bit are 0! - ZEROISE_OTS_ADDR(addr); + setChainADRS(addr,0); + setHashADRS(addr,0); + setKeyAndMask(addr,0); // Generate pseudorandom value - prg_with_counter(seed, sk_seed, n, addr); + prf(seed, (unsigned char*) addr, sk_seed, n); } /** @@ -41,18 +43,17 @@ static void get_seed(unsigned char *seed, const unsigned char *sk_seed, int n, u * parameter names are the same as in the draft * parameter k is K as used in the BDS algorithm */ -int xmss_set_params(xmss_params *params, int m, int n, int h, int w, int k) +int xmss_set_params(xmss_params *params, int n, int h, int w, int k) { if (k >= h || k < 2 || (h - k) % 2) { fprintf(stderr, "For BDS traversal, H - K must be even, with H > K >= 2!\n"); return 1; } params->h = h; - params->m = m; params->n = n; params->k = k; wots_params wots_par; - wots_set_params(&wots_par, m, n, w); + wots_set_params(&wots_par, n, w); params->wots_par = wots_par; return 0; } @@ -79,7 +80,7 @@ void xmss_set_bds_state(bds_state *state, unsigned char *stack, int stackoffset, * * Especially h is the total tree height, i.e. the XMSS trees have height h/d */ -int xmssmt_set_params(xmssmt_params *params, int m, int n, int h, int d, int w, int k) +int xmssmt_set_params(xmssmt_params *params, int n, int h, int d, int w, int k) { if (h % d) { fprintf(stderr, "d must divide h without remainder!\n"); @@ -87,11 +88,10 @@ int xmssmt_set_params(xmssmt_params *params, int m, int n, int h, int d, int w, } params->h = h; params->d = d; - params->m = m; params->n = n; params->index_len = (h + 7) / 8; xmss_params xmss_par; - if (xmss_set_params(&xmss_par, m, n, (h/d), w, k)) { + if (xmss_set_params(&xmss_par, n, (h/d), w, k)) { return 1; } params->xmss_par = xmss_par; @@ -101,23 +101,24 @@ int xmssmt_set_params(xmssmt_params *params, int m, int n, int h, int d, int w, /** * Computes a leaf from a WOTS public key using an L-tree. */ -static void l_tree(unsigned char *leaf, unsigned char *wots_pk, const xmss_params *params, const unsigned char *pub_seed, unsigned char addr[16]) +static void l_tree(unsigned char *leaf, unsigned char *wots_pk, const xmss_params *params, const unsigned char *pub_seed, uint32_t addr[8]) { unsigned int l = params->wots_par.len; unsigned int n = params->n; - unsigned long i = 0; - unsigned int height = 0; + uint32_t i = 0; + uint32_t height = 0; + uint32_t bound; //ADRS.setTreeHeight(0); - SET_LTREE_TREE_HEIGHT(addr, height); - unsigned long bound; + setTreeHeight(addr, height); + while (l > 1) { bound = l >> 1; //floor(l / 2); - for (i = 0; i < bound; i = i + 1) { + for (i = 0; i < bound; i++) { //ADRS.setTreeIndex(i); - SET_LTREE_TREE_INDEX(addr, i); + setTreeIndex(addr, i); //wots_pk[i] = RAND_HASH(pk[2i], pk[2i + 1], SEED, ADRS); - hash_2n_n(wots_pk+i*n, wots_pk+i*2*n, pub_seed, addr, n); + hash_h(wots_pk+i*n, wots_pk+i*2*n, pub_seed, addr, n); } //if ( l % 2 == 1 ) { if (l & 1) { @@ -126,14 +127,13 @@ static void l_tree(unsigned char *leaf, unsigned char *wots_pk, const xmss_param //l = ceil(l / 2); l=(l>>1)+1; } - else - { + else { //l = ceil(l / 2); l=(l>>1); } //ADRS.setTreeHeight(ADRS.getTreeHeight() + 1); height++; - SET_LTREE_TREE_HEIGHT(addr, height); + setTreeHeight(addr, height); } //return pk[0]; memcpy(leaf, wots_pk, n); @@ -142,7 +142,7 @@ static void l_tree(unsigned char *leaf, unsigned char *wots_pk, const xmss_param /** * Computes the leaf at a given address. First generates the WOTS key pair, then computes leaf using l_tree. As this happens position independent, we only require that addr encodes the right ltree-address. */ -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]) +static void gen_leaf_wots(unsigned char *leaf, const unsigned char *sk_seed, const xmss_params *params, const unsigned char *pub_seed, uint32_t ltree_addr[8], uint32_t ots_addr[8]) { unsigned char seed[params->n]; unsigned char pk[params->wots_par.keysize]; @@ -168,26 +168,26 @@ static int treehash_minheight_on_stack(bds_state* state, const xmss_params *para * Currently only used for key generation. * */ -static void treehash_setup(unsigned char *node, int height, int index, bds_state *state, const unsigned char *sk_seed, const xmss_params *params, const unsigned char *pub_seed, const unsigned char addr[16]) +static void treehash_setup(unsigned char *node, int height, int index, bds_state *state, const unsigned char *sk_seed, const xmss_params *params, const unsigned char *pub_seed, const uint32_t addr[8]) { unsigned int idx = index; unsigned int n = params->n; unsigned int h = params->h; unsigned int k = params->k; // use three different addresses because at this point we use all three formats in parallel - unsigned char ots_addr[16]; - unsigned char ltree_addr[16]; - unsigned char node_addr[16]; - memcpy(ots_addr, addr, 10); - SET_OTS_BIT(ots_addr, 1); - memcpy(ltree_addr, addr, 10); - SET_OTS_BIT(ltree_addr, 0); - SET_LTREE_BIT(ltree_addr, 1); - memcpy(node_addr, ltree_addr, 10); - SET_LTREE_BIT(node_addr, 0); - SET_NODE_PADDING(node_addr); + uint32_t ots_addr[8]; + uint32_t ltree_addr[8]; + uint32_t node_addr[8]; + // only copy layer and tree address parts + memcpy(ots_addr, addr, 12); + // type = ots + setType(ots_addr, 0); + memcpy(ltree_addr, addr, 12); + setType(ltree_addr, 1); + memcpy(node_addr, addr, 12); + setType(node_addr, 2); - unsigned int lastnode, i; + uint32_t lastnode, i; unsigned char stack[(height+1)*n]; unsigned int stacklevels[height+1]; unsigned int stackoffset=0; @@ -203,8 +203,8 @@ static void treehash_setup(unsigned char *node, int height, int index, bds_state i = 0; for (; idx < lastnode; idx++) { - SET_LTREE_ADDRESS(ltree_addr, idx); - SET_OTS_ADDRESS(ots_addr, idx); + setLtreeADRS(ltree_addr, idx); + setOTSADRS(ots_addr, idx); gen_leaf_wots(stack+stackoffset*n, sk_seed, params, pub_seed, ltree_addr, ots_addr); stacklevels[stackoffset] = 0; stackoffset++; @@ -225,9 +225,9 @@ static void treehash_setup(unsigned char *node, int height, int index, bds_state memcpy(state->retain + ((1 << (h - 1 - nodeh)) + nodeh - h + (((i >> nodeh) - 3) >> 1)) * n, stack+(stackoffset-1)*n, n); } } - SET_NODE_TREE_HEIGHT(node_addr, stacklevels[stackoffset-1]); - SET_NODE_TREE_INDEX(node_addr, (idx >> (stacklevels[stackoffset-1]+1))); - hash_2n_n(stack+(stackoffset-2)*n, stack+(stackoffset-2)*n, pub_seed, + setTreeHeight(node_addr, stacklevels[stackoffset-1]); + setTreeIndex(node_addr, (idx >> (stacklevels[stackoffset-1]+1))); + hash_h(stack+(stackoffset-2)*n, stack+(stackoffset-2)*n, pub_seed, node_addr, n); stacklevels[stackoffset-2]++; stackoffset--; @@ -239,24 +239,23 @@ static void treehash_setup(unsigned char *node, int height, int index, bds_state node[i] = stack[i]; } -static void treehash_update(treehash_inst *treehash, bds_state *state, const unsigned char *sk_seed, const xmss_params *params, const unsigned char *pub_seed, const unsigned char addr[16]) { +static void treehash_update(treehash_inst *treehash, bds_state *state, const unsigned char *sk_seed, const xmss_params *params, const unsigned char *pub_seed, const uint32_t addr[8]) { int n = params->n; - unsigned char ots_addr[16]; - unsigned char ltree_addr[16]; - unsigned char node_addr[16]; + uint32_t ots_addr[8]; + uint32_t ltree_addr[8]; + uint32_t node_addr[8]; + // only copy layer and tree address parts + memcpy(ots_addr, addr, 12); + // type = ots + setType(ots_addr, 0); + memcpy(ltree_addr, addr, 12); + setType(ltree_addr, 1); + memcpy(node_addr, addr, 12); + setType(node_addr, 2); - memcpy(ots_addr, addr, 10); - SET_OTS_BIT(ots_addr, 1); - memcpy(ltree_addr, addr, 10); - SET_OTS_BIT(ltree_addr, 0); - SET_LTREE_BIT(ltree_addr, 1); - memcpy(node_addr, ltree_addr, 10); - SET_LTREE_BIT(node_addr, 0); - SET_NODE_PADDING(node_addr); - - SET_LTREE_ADDRESS(ltree_addr, treehash->next_idx); - SET_OTS_ADDRESS(ots_addr, treehash->next_idx); + setLtreeADRS(ltree_addr, treehash->next_idx); + setOTSADRS(ots_addr, treehash->next_idx); unsigned char nodebuffer[2 * n]; unsigned int nodeheight = 0; @@ -264,9 +263,9 @@ static void treehash_update(treehash_inst *treehash, bds_state *state, const uns while (treehash->stackusage > 0 && state->stacklevels[state->stackoffset-1] == nodeheight) { memcpy(nodebuffer + n, nodebuffer, n); memcpy(nodebuffer, state->stack + (state->stackoffset-1)*n, n); - SET_NODE_TREE_HEIGHT(node_addr, nodeheight); - SET_NODE_TREE_INDEX(node_addr, (treehash->next_idx >> (nodeheight+1))); - hash_2n_n(nodebuffer, nodebuffer, pub_seed, node_addr, n); + setTreeHeight(node_addr, nodeheight); + setTreeIndex(node_addr, (treehash->next_idx >> (nodeheight+1))); + hash_h(nodebuffer, nodebuffer, pub_seed, node_addr, n); nodeheight++; treehash->stackusage--; state->stackoffset--; @@ -287,11 +286,11 @@ static void treehash_update(treehash_inst *treehash, bds_state *state, const uns /** * Computes a root node given a leaf and an authapth */ -static void validate_authpath(unsigned char *root, const unsigned char *leaf, unsigned long leafidx, const unsigned char *authpath, const xmss_params *params, const unsigned char *pub_seed, unsigned char addr[16]) +static void validate_authpath(unsigned char *root, const unsigned char *leaf, unsigned long leafidx, const unsigned char *authpath, const xmss_params *params, const unsigned char *pub_seed, uint32_t addr[8]) { unsigned int n = params->n; - unsigned int i, j; + uint32_t i, j; unsigned char buffer[2*n]; // If leafidx is odd (last bit = 1), current path element is a right child and authpath has to go to the left. @@ -310,34 +309,34 @@ static void validate_authpath(unsigned char *root, const unsigned char *leaf, un } authpath += n; - for (i = 0; i < params->h-1; i++) { - SET_NODE_TREE_HEIGHT(addr, i); + for (i=0; i < params->h-1; i++) { + setTreeHeight(addr, i); leafidx >>= 1; - SET_NODE_TREE_INDEX(addr, leafidx); - if (leafidx & 1) { - hash_2n_n(buffer+n, buffer, pub_seed, addr, n); + setTreeIndex(addr, leafidx); + if (leafidx&1) { + hash_h(buffer+n, buffer, pub_seed, addr, n); for (j = 0; j < n; j++) buffer[j] = authpath[j]; } else { - hash_2n_n(buffer, buffer, pub_seed, addr, n); + hash_h(buffer, buffer, pub_seed, addr, n); for (j = 0; j < n; j++) buffer[j+n] = authpath[j]; } authpath += n; } - SET_NODE_TREE_HEIGHT(addr, (params->h-1)); + setTreeHeight(addr, (params->h-1)); leafidx >>= 1; - SET_NODE_TREE_INDEX(addr, leafidx); - hash_2n_n(root, buffer, pub_seed, addr, n); + setTreeIndex(addr, leafidx); + hash_h(root, buffer, pub_seed, addr, n); } /** * Performs one treehash update on the instance that needs it the most. * Returns 1 if such an instance was not found **/ -static char bds_treehash_update(bds_state *state, unsigned int updates, const unsigned char *sk_seed, const xmss_params *params, unsigned char *pub_seed, const unsigned char addr[16]) { - unsigned int i, j; +static char bds_treehash_update(bds_state *state, unsigned int updates, const unsigned char *sk_seed, const xmss_params *params, unsigned char *pub_seed, const uint32_t addr[8]) { + uint32_t i, j; unsigned int level, l_min, low; unsigned int h = params->h; unsigned int k = params->k; @@ -374,10 +373,10 @@ static char bds_treehash_update(bds_state *state, unsigned int updates, const un * Updates the state (typically NEXT_i) by adding a leaf and updating the stack * Returns 1 if all leaf nodes have already been processed **/ -static char bds_state_update(bds_state *state, const unsigned char *sk_seed, const xmss_params *params, unsigned char *pub_seed, const unsigned char addr[16]) { - unsigned char ltree_addr[16]; - unsigned char node_addr[16]; - unsigned char ots_addr[16]; +static char bds_state_update(bds_state *state, const unsigned char *sk_seed, const xmss_params *params, unsigned char *pub_seed, const uint32_t addr[8]) { + uint32_t ltree_addr[8]; + uint32_t node_addr[8]; + uint32_t ots_addr[8]; int n = params->n; int h = params->h; @@ -389,19 +388,17 @@ static char bds_state_update(bds_state *state, const unsigned char *sk_seed, con return 1; } - memcpy(ots_addr, addr, 10); - SET_OTS_BIT(ots_addr, 1); - SET_OTS_ADDRESS(ots_addr, idx); - - memcpy(ltree_addr, addr, 10); - SET_OTS_BIT(ltree_addr, 0); - SET_LTREE_BIT(ltree_addr, 1); - SET_LTREE_ADDRESS(ltree_addr, idx); - - memcpy(node_addr, addr, 10); - SET_LTREE_BIT(node_addr, 0); - SET_OTS_BIT(node_addr, 0); - SET_NODE_PADDING(node_addr); + // only copy layer and tree address parts + memcpy(ots_addr, addr, 12); + // type = ots + setType(ots_addr, 0); + memcpy(ltree_addr, addr, 12); + setType(ltree_addr, 1); + memcpy(node_addr, addr, 12); + setType(node_addr, 2); + + setOTSADRS(ots_addr, idx); + setLtreeADRS(ltree_addr, idx); gen_leaf_wots(state->stack+state->stackoffset*n, sk_seed, params, pub_seed, ltree_addr, ots_addr); @@ -423,9 +420,9 @@ static char bds_state_update(bds_state *state, const unsigned char *sk_seed, con memcpy(state->retain + ((1 << (h - 1 - nodeh)) + nodeh - h + (((idx >> nodeh) - 3) >> 1)) * n, state->stack+(state->stackoffset-1)*n, n); } } - SET_NODE_TREE_HEIGHT(node_addr, state->stacklevels[state->stackoffset-1]); - SET_NODE_TREE_INDEX(node_addr, (idx >> (state->stacklevels[state->stackoffset-1]+1))); - hash_2n_n(state->stack+(state->stackoffset-2)*n, state->stack+(state->stackoffset-2)*n, pub_seed, node_addr, n); + setTreeHeight(node_addr, state->stacklevels[state->stackoffset-1]); + setTreeIndex(node_addr, (idx >> (state->stacklevels[state->stackoffset-1]+1))); + hash_h(state->stack+(state->stackoffset-2)*n, state->stack+(state->stackoffset-2)*n, pub_seed, node_addr, n); state->stacklevels[state->stackoffset-2]++; state->stackoffset--; @@ -439,7 +436,7 @@ static char bds_state_update(bds_state *state, const unsigned char *sk_seed, con * next leaf node, using the algorithm described by Buchmann, Dahmen and Szydlo * in "Post Quantum Cryptography", Springer 2009. */ -static void bds_round(bds_state *state, const unsigned long leaf_idx, const unsigned char *sk_seed, const xmss_params *params, unsigned char *pub_seed, unsigned char addr[16]) +static void bds_round(bds_state *state, const unsigned long leaf_idx, const unsigned char *sk_seed, const xmss_params *params, unsigned char *pub_seed, uint32_t addr[8]) { unsigned int i; unsigned int n = params->n; @@ -451,18 +448,17 @@ static void bds_round(bds_state *state, const unsigned long leaf_idx, const unsi unsigned int offset, rowidx; unsigned char buf[2 * n]; - unsigned char ots_addr[16]; - unsigned char ltree_addr[16]; - unsigned char node_addr[16]; - - memcpy(ots_addr, addr, 10); - SET_OTS_BIT(ots_addr, 1); - memcpy(ltree_addr, addr, 10); - SET_OTS_BIT(ltree_addr, 0); - SET_LTREE_BIT(ltree_addr, 1); - memcpy(node_addr, ltree_addr, 10); - SET_LTREE_BIT(node_addr, 0); - SET_NODE_PADDING(node_addr); + uint32_t ots_addr[8]; + uint32_t ltree_addr[8]; + uint32_t node_addr[8]; + // only copy layer and tree address parts + memcpy(ots_addr, addr, 12); + // type = ots + setType(ots_addr, 0); + memcpy(ltree_addr, addr, 12); + setType(ltree_addr, 1); + memcpy(node_addr, addr, 12); + setType(node_addr, 2); for (i = 0; i < h; i++) { if (! ((leaf_idx >> i) & 1)) { @@ -480,14 +476,14 @@ static void bds_round(bds_state *state, const unsigned long leaf_idx, const unsi memcpy(state->keep + (tau >> 1)*n, state->auth + tau*n, n); } if (tau == 0) { - SET_LTREE_ADDRESS(ltree_addr, leaf_idx); - SET_OTS_ADDRESS(ots_addr, leaf_idx); + setLtreeADRS(ltree_addr, leaf_idx); + setOTSADRS(ots_addr, leaf_idx); gen_leaf_wots(state->auth, sk_seed, params, pub_seed, ltree_addr, ots_addr); } else { - SET_NODE_TREE_HEIGHT(node_addr, (tau-1)); - SET_NODE_TREE_INDEX(node_addr, leaf_idx >> tau); - hash_2n_n(state->auth + tau * n, buf, pub_seed, node_addr, n); + setTreeHeight(node_addr, (tau-1)); + setTreeIndex(node_addr, leaf_idx >> tau); + hash_h(state->auth + tau * n, buf, pub_seed, node_addr, n); for (i = 0; i < tau; i++) { if (i < h - k) { memcpy(state->auth + i * n, state->treehash[i].node, n); @@ -513,26 +509,28 @@ static void bds_round(bds_state *state, const unsigned long leaf_idx, const unsi /* * Generates a XMSS key pair for a given parameter set. - * Format sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED] + * Format sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] omitting algo oid. */ int xmss_keypair(unsigned char *pk, unsigned char *sk, bds_state *state, xmss_params *params) { unsigned int n = params->n; - unsigned int m = params->m; // Set idx = 0 sk[0] = 0; sk[1] = 0; sk[2] = 0; sk[3] = 0; - // Init SK_SEED (n byte), SK_PRF (m byte), and PUB_SEED (n byte) - randombytes(sk+4, 2*n+m); + // Init SK_SEED (n byte), SK_PRF (n byte), and PUB_SEED (n byte) + randombytes(sk+4, 3*n); // Copy PUB_SEED to public key - memcpy(pk+n, sk+4+n+m, n); + memcpy(pk+n, sk+4+2*n, n); + + uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - unsigned char addr[16] = {0, 0, 0, 0}; // Compute root - treehash_setup(pk, params->h, 0, state, sk+4, params, sk+4+n+m, addr); + treehash_setup(pk, params->h, 0, state, sk+4, params, sk+4+2*n, addr); + // copy root to sk + memcpy(sk+4+3*n, pk, n); return 0; } @@ -547,28 +545,24 @@ int xmss_sign(unsigned char *sk, bds_state *state, unsigned char *sig_msg, unsig { unsigned int h = params->h; unsigned int n = params->n; - unsigned int m = params->m; unsigned int k = params->k; + uint16_t i = 0; // Extract SK unsigned long idx = ((unsigned long)sk[0] << 24) | ((unsigned long)sk[1] << 16) | ((unsigned long)sk[2] << 8) | sk[3]; unsigned char sk_seed[n]; memcpy(sk_seed, sk+4, n); - unsigned char sk_prf[m]; - memcpy(sk_prf, sk+4+n, m); + unsigned char sk_prf[n]; + memcpy(sk_prf, sk+4+n, n); unsigned char pub_seed[n]; - memcpy(pub_seed, sk+4+n+m, n); + memcpy(pub_seed, sk+4+2*n, 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]; - } + // index as 32 bytes string + unsigned char idx_bytes_32[32]; + to_byte(idx_bytes_32, idx, 32); + + unsigned char hash_key[3*n]; - // Update SK sk[0] = ((idx + 1) >> 24) & 255; sk[1] = ((idx + 1) >> 16) & 255; @@ -578,22 +572,24 @@ 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 char R[m]; - unsigned char msg_h[m]; + unsigned char R[n]; + unsigned char msg_h[n]; unsigned char ots_seed[n]; - unsigned char ots_addr[16] = {0, 0, 0, 0}; + uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; // --------------------------------- // Message Hashing // --------------------------------- // 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); + // First compute pseudorandom value + prf(R, idx_bytes_32, sk_prf, n); + // Generate hash key (R || root || idx) + memcpy(hash_key, R, n); + memcpy(hash_key+n, sk+4+3*n, n); + to_byte(hash_key+2*n, idx, n); // Then use it for message digest - hash_m(msg_h, msg, msglen, hash_key, 2*m, m); + h_msg(msg_h, msg, msglen, hash_key, 3*n, n); // Start collecting signature *sig_msg_len = 0; @@ -608,19 +604,19 @@ int xmss_sign(unsigned char *sk, bds_state *state, unsigned char *sig_msg, unsig *sig_msg_len += 4; // Copy R to signature - for (i = 0; i < m; i++) + for (i = 0; i < n; i++) sig_msg[i] = R[i]; - sig_msg += m; - *sig_msg_len += m; + sig_msg += n; + *sig_msg_len += n; // ---------------------------------- // Now we start to "really sign" // ---------------------------------- // Prepare Address - SET_OTS_BIT(ots_addr, 1); - SET_OTS_ADDRESS(ots_addr, idx); + setType(ots_addr, 0); + setOTSADRS(ots_addr, idx); // Compute seed for OTS key pair get_seed(ots_seed, sk_seed, n, ots_addr); @@ -657,57 +653,50 @@ int xmss_sign(unsigned char *sk, bds_state *state, unsigned char *sig_msg, unsig int xmss_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigned char *sig_msg, unsigned long long sig_msg_len, const unsigned char *pk, const xmss_params *params) { unsigned int n = params->n; - unsigned int m = params->m; unsigned long long i, m_len; unsigned long idx=0; unsigned char wots_pk[params->wots_par.keysize]; unsigned char pkhash[n]; unsigned char root[n]; - unsigned char msg_h[m]; - unsigned char hash_key[2*m]; + unsigned char msg_h[n]; + unsigned char hash_key[3*n]; unsigned char pub_seed[n]; memcpy(pub_seed, pk+n, n); // Init addresses - unsigned char ots_addr[16] = {0, 0, 0, 0}; - unsigned char ltree_addr[16]; - unsigned char node_addr[16]; + uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + uint32_t ltree_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + uint32_t node_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - SET_OTS_BIT(ots_addr, 1); - - memcpy(ltree_addr, ots_addr, 10); - SET_OTS_BIT(ltree_addr, 0); - SET_LTREE_BIT(ltree_addr, 1); - - memcpy(node_addr, ltree_addr, 10); - SET_LTREE_BIT(node_addr, 0); - SET_NODE_PADDING(node_addr); + setType(ots_addr, 0); + setType(ltree_addr, 1); + setType(node_addr, 2); // 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); - 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); + + // Generate hash key (R || root || idx) + memcpy(hash_key, sig_msg+4,n); + memcpy(hash_key+n, pk, n); + to_byte(hash_key+2*n, idx, n); + + sig_msg += (n+4); + sig_msg_len -= (n+4); // 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, hash_key, 2*m, m); + h_msg(msg_h, sig_msg + tmp_sig_len, m_len, hash_key, 3*n, n); //----------------------- // Verify signature //----------------------- // Prepare Address - SET_OTS_ADDRESS(ots_addr, idx); + setOTSADRS(ots_addr, idx); // Check WOTS signature wots_pkFromSig(wots_pk, sig_msg, msg_h, &(params->wots_par), pub_seed, ots_addr); @@ -715,7 +704,7 @@ int xmss_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigne sig_msg_len -= params->wots_par.keysize; // Compute Ltree - SET_LTREE_ADDRESS(ltree_addr, idx); + setLtreeADRS(ltree_addr, idx); l_tree(pkhash, wots_pk, params, pub_seed, ltree_addr); // Compute root @@ -745,39 +734,36 @@ fail: /* * Generates a XMSSMT key pair for a given parameter set. - * Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED] + * Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] omitting algo oid. */ int xmssmt_keypair(unsigned char *pk, unsigned char *sk, bds_state *states, unsigned char *wots_sigs, xmssmt_params *params) { unsigned int n = params->n; - unsigned int m = params->m; unsigned int i; unsigned char ots_seed[params->n]; // Set idx = 0 for (i = 0; i < params->index_len; i++) { sk[i] = 0; } - // Init SK_SEED (n byte), SK_PRF (m byte), and PUB_SEED (n byte) - randombytes(sk+params->index_len, 2*n+m); + // Init SK_SEED (n byte), SK_PRF (n byte), and PUB_SEED (n byte) + randombytes(sk+params->index_len, 3*n); // Copy PUB_SEED to public key - memcpy(pk+n, sk+params->index_len+n+m, n); + memcpy(pk+n, sk+params->index_len+2*n, n); // 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, (unsigned long long)0); - SET_OTS_ADDRESS(addr, 0); - SET_LAYER_ADDRESS(addr, 0); + uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + setLayerADRS(addr, (params->d-1)); // Set up state and compute wots signatures for all but topmost tree root for (i = 0; i < params->d - 1; i++) { // 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)); + setLayerADRS(addr, (i+1)); 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); + memcpy(sk+params->index_len+3*n, pk, n); return 0; } @@ -791,42 +777,39 @@ int xmssmt_keypair(unsigned char *pk, unsigned char *sk, bds_state *states, unsi int xmssmt_sign(unsigned char *sk, bds_state *states, unsigned char *wots_sigs, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg, unsigned long long msglen, const xmssmt_params *params) { unsigned int n = params->n; - unsigned int m = params->m; + unsigned int tree_h = params->xmss_par.h; unsigned int h = params->h; unsigned int k = params->xmss_par.k; unsigned int idx_len = params->index_len; - unsigned long long idx_tree; - unsigned long long idx_leaf; - unsigned long long i, j; + uint64_t idx_tree; + uint32_t idx_leaf; + uint64_t i, j; int needswap_upto = -1; unsigned int updates; unsigned char sk_seed[n]; - unsigned char sk_prf[m]; + unsigned char sk_prf[n]; unsigned char pub_seed[n]; // Init working params - unsigned char R[m]; - unsigned char msg_h[m]; - unsigned char hash_key[2*m]; + unsigned char R[n]; + unsigned char msg_h[n]; + unsigned char hash_key[3*n]; unsigned char ots_seed[n]; - unsigned char addr[16] = {0, 0, 0, 0}; - unsigned char ots_addr[16] = {0, 0, 0, 0}; + uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + unsigned char idx_bytes_32[32]; bds_state tmp; - // Extract SK - for(i = 0; i < m-idx_len; i++){ - hash_key[i] = 0; - } + // Extract SK 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); - memcpy(sk_prf, sk+idx_len+n, m); - memcpy(pub_seed, sk+idx_len+n+m, n); + memcpy(sk_prf, sk+idx_len+n, n); + memcpy(pub_seed, sk+idx_len+2*n, n); // Update SK for (i = 0; i < idx_len; i++) { @@ -841,14 +824,16 @@ 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); + // First compute pseudorandom value + to_byte(idx_bytes_32, idx, 32); + prf(R, idx_bytes_32, sk_prf, n); + // Generate hash key (R || root || idx) + memcpy(hash_key, R, n); + memcpy(hash_key+n, sk+idx_len+3*n, n); + to_byte(hash_key+2*n, idx, n); // Then use it for message digest - hash_m(msg_h, msg, msglen, hash_key, 2*m, m); + h_msg(msg_h, msg, msglen, hash_key, 3*n, n); // Start collecting signature *sig_msg_len = 0; @@ -862,11 +847,11 @@ int xmssmt_sign(unsigned char *sk, bds_state *states, unsigned char *wots_sigs, *sig_msg_len += idx_len; // Copy R to signature - for (i = 0; i < m; i++) + for (i = 0; i < n; i++) sig_msg[i] = R[i]; - sig_msg += m; - *sig_msg_len += m; + sig_msg += n; + *sig_msg_len += n; // ---------------------------------- // Now we start to "really sign" @@ -875,12 +860,12 @@ int xmssmt_sign(unsigned char *sk, bds_state *states, unsigned char *wots_sigs, // Handle lowest layer separately as it is slightly different... // Prepare Address - SET_OTS_BIT(ots_addr, 1); + setType(ots_addr, 0); idx_tree = idx >> tree_h; idx_leaf = (idx & ((1 << tree_h)-1)); - SET_LAYER_ADDRESS(ots_addr, 0); - SET_TREE_ADDRESS(ots_addr, idx_tree); - SET_OTS_ADDRESS(ots_addr, idx_leaf); + setLayerADRS(ots_addr, 0); + setTreeADRS(ots_addr, idx_tree); + setOTSADRS(ots_addr, idx_leaf); // Compute seed for OTS key pair get_seed(ots_seed, sk_seed, n, ots_addr); @@ -911,7 +896,7 @@ int xmssmt_sign(unsigned char *sk, bds_state *states, unsigned char *wots_sigs, updates = (tree_h - k) >> 1; - SET_TREE_ADDRESS(addr, (idx_tree + 1)); + setTreeADRS(addr, (idx_tree + 1)); // mandatory update for NEXT_0 (does not count towards h-k/2) if NEXT_0 exists if ((1 + idx_tree) * (1 << tree_h) + idx_leaf < (1ULL << h)) { bds_state_update(&states[params->d], sk_seed, &(params->xmss_par), pub_seed, addr); @@ -922,13 +907,13 @@ int xmssmt_sign(unsigned char *sk, bds_state *states, unsigned char *wots_sigs, if (! (((idx + 1) & ((1ULL << ((i+1)*tree_h)) - 1)) == 0)) { idx_leaf = (idx >> (tree_h * i)) & ((1 << tree_h)-1); idx_tree = (idx >> (tree_h * (i+1))); - SET_LAYER_ADDRESS(addr, i); - SET_TREE_ADDRESS(addr, idx_tree); + setLayerADRS(addr, i); + setTreeADRS(addr, idx_tree); if (i == (unsigned int) (needswap_upto + 1)) { bds_round(&states[i], idx_leaf, sk_seed, &(params->xmss_par), pub_seed, addr); } updates = bds_treehash_update(&states[i], updates, sk_seed, &(params->xmss_par), pub_seed, addr); - SET_TREE_ADDRESS(addr, (idx_tree + 1)); + setTreeADRS(addr, (idx_tree + 1)); // if a NEXT-tree exists for this level; if ((1 + idx_tree) * (1 << tree_h) + idx_leaf < (1ULL << (h - tree_h * i))) { if (i > 0 && updates > 0 && states[params->d + i].next_leaf < (1ULL << h)) { @@ -942,9 +927,9 @@ int xmssmt_sign(unsigned char *sk, bds_state *states, unsigned char *wots_sigs, memcpy(states+params->d + i, states + i, sizeof(bds_state)); memcpy(states + i, &tmp, sizeof(bds_state)); - SET_LAYER_ADDRESS(ots_addr, (i+1)); - SET_TREE_ADDRESS(ots_addr, ((idx + 1) >> ((i+2) * tree_h))); - SET_OTS_ADDRESS(ots_addr, (((idx >> ((i+1) * tree_h)) + 1) & ((1 << tree_h)-1))); + setLayerADRS(ots_addr, (i+1)); + setTreeADRS(ots_addr, ((idx + 1) >> ((i+2) * tree_h))); + setOTSADRS(ots_addr, (((idx >> ((i+1) * tree_h)) + 1) & ((1 << tree_h)-1))); 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); @@ -975,53 +960,49 @@ int xmssmt_sign(unsigned char *sk, bds_state *states, unsigned char *wots_sigs, int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigned char *sig_msg, unsigned long long sig_msg_len, const unsigned char *pk, const xmssmt_params *params) { unsigned int n = params->n; - unsigned int m = params->m; unsigned int tree_h = params->xmss_par.h; unsigned int idx_len = params->index_len; - unsigned long long idx_tree; - unsigned long long idx_leaf; + uint64_t idx_tree; + uint32_t idx_leaf; unsigned long long i, m_len; unsigned long long idx=0; unsigned char wots_pk[params->xmss_par.wots_par.keysize]; unsigned char pkhash[n]; unsigned char root[n]; - unsigned char msg_h[m]; - unsigned char hash_key[2*m]; + unsigned char msg_h[n]; + unsigned char hash_key[3*n]; unsigned char pub_seed[n]; memcpy(pub_seed, pk+n, n); // Init addresses - unsigned char ots_addr[16] = {0, 0, 0, 0}; - unsigned char ltree_addr[16]; - unsigned char node_addr[16]; + uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + uint32_t ltree_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + uint32_t node_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; // 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; - for(i = 0; i < m; i++){ - hash_key[m+i] = sig_msg[i]; - } + // Generate hash key (R || root || idx) + memcpy(hash_key, sig_msg,n); + memcpy(hash_key+n, pk, n); + to_byte(hash_key+2*n, idx, n); - sig_msg += m; - sig_msg_len -= m; + sig_msg += n; + sig_msg_len -= n; // 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); + h_msg(msg_h, sig_msg + tmp_sig_len, m_len, hash_key, 3*n, n); //----------------------- @@ -1031,19 +1012,17 @@ int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsig // Prepare Address idx_tree = idx >> tree_h; idx_leaf = (idx & ((1 << tree_h)-1)); - SET_LAYER_ADDRESS(ots_addr, 0); - SET_TREE_ADDRESS(ots_addr, idx_tree); - SET_OTS_BIT(ots_addr, 1); + setLayerADRS(ots_addr, 0); + setTreeADRS(ots_addr, idx_tree); + setType(ots_addr, 0); - memcpy(ltree_addr, ots_addr, 10); - SET_OTS_BIT(ltree_addr, 0); - SET_LTREE_BIT(ltree_addr, 1); + memcpy(ltree_addr, ots_addr, 12); + setType(ltree_addr, 1); - memcpy(node_addr, ltree_addr, 10); - SET_LTREE_BIT(node_addr, 0); - SET_NODE_PADDING(node_addr); - - SET_OTS_ADDRESS(ots_addr, idx_leaf); + memcpy(node_addr, ltree_addr, 12); + setType(node_addr, 2); + + setOTSADRS(ots_addr, idx_leaf); // Check WOTS signature wots_pkFromSig(wots_pk, sig_msg, msg_h, &(params->xmss_par.wots_par), pub_seed, ots_addr); @@ -1052,7 +1031,7 @@ int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsig sig_msg_len -= params->xmss_par.wots_par.keysize; // Compute Ltree - SET_LTREE_ADDRESS(ltree_addr, idx_leaf); + setLtreeADRS(ltree_addr, idx_leaf); l_tree(pkhash, wots_pk, &(params->xmss_par), pub_seed, ltree_addr); // Compute root @@ -1066,19 +1045,17 @@ int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsig idx_leaf = (idx_tree & ((1 << tree_h)-1)); idx_tree = idx_tree >> tree_h; - SET_LAYER_ADDRESS(ots_addr, i); - SET_TREE_ADDRESS(ots_addr, idx_tree); - SET_OTS_BIT(ots_addr, 1); + setLayerADRS(ots_addr, i); + setTreeADRS(ots_addr, idx_tree); + setType(ots_addr, 0); - memcpy(ltree_addr, ots_addr, 10); - SET_OTS_BIT(ltree_addr, 0); - SET_LTREE_BIT(ltree_addr, 1); + memcpy(ltree_addr, ots_addr, 12); + setType(ltree_addr, 1); - memcpy(node_addr, ltree_addr, 10); - SET_LTREE_BIT(node_addr, 0); - SET_NODE_PADDING(node_addr); + memcpy(node_addr, ltree_addr, 12); + setType(node_addr, 2); - SET_OTS_ADDRESS(ots_addr, idx_leaf); + setOTSADRS(ots_addr, idx_leaf); // Check WOTS signature wots_pkFromSig(wots_pk, sig_msg, root, &(params->xmss_par.wots_par), pub_seed, ots_addr); @@ -1087,7 +1064,7 @@ int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsig sig_msg_len -= params->xmss_par.wots_par.keysize; // Compute Ltree - SET_LTREE_ADDRESS(ltree_addr, idx_leaf); + setLtreeADRS(ltree_addr, idx_leaf); l_tree(pkhash, wots_pk, &(params->xmss_par), pub_seed, ltree_addr); // Compute root diff --git a/xmss_fast.h b/xmss_fast.h index d4c4ebb..ec66910 100644 --- a/xmss_fast.h +++ b/xmss_fast.h @@ -1,5 +1,5 @@ /* -xmss_fast.h version 20160210 +xmss_fast.h version 20160217 Andreas Hülsing Joost Rijneveld Public domain. @@ -18,7 +18,6 @@ typedef struct{ typedef struct{ wots_params wots_par; unsigned int n; - unsigned int m; unsigned int h; unsigned int k; } xmss_params; @@ -26,7 +25,6 @@ typedef struct{ typedef struct{ xmss_params xmss_par; unsigned int n; - unsigned int m; unsigned int h; unsigned int d; unsigned int index_len; @@ -60,17 +58,17 @@ void xmss_set_bds_state(bds_state *state, unsigned char *stack, int stackoffset, * Initializes parameter set. * Needed, for any of the other methods. */ -int xmss_set_params(xmss_params *params, int m, int n, int h, int w, int k); +int xmss_set_params(xmss_params *params, int n, int h, int w, int k); /** * Initialize xmssmt_params struct * parameter names are the same as in the draft * * Especially h is the total tree height, i.e. the XMSS trees have height h/d */ -int xmssmt_set_params(xmssmt_params *params, int m, int n, int h, int d, int w, int k); +int xmssmt_set_params(xmssmt_params *params, int n, int h, int d, int w, int k); /** * Generates a XMSS key pair for a given parameter set. - * Format sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED] + * Format sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] omitting algo oid. */ int xmss_keypair(unsigned char *pk, unsigned char *sk, bds_state *state, xmss_params *params); @@ -91,7 +89,7 @@ int xmss_sign_open(unsigned char *msg,unsigned long long *msglen, const unsigned /* * Generates a XMSSMT key pair for a given parameter set. - * Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED] + * Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] omitting algo oid. */ int xmssmt_keypair(unsigned char *pk, unsigned char *sk, bds_state *states, unsigned char *wots_sigs, xmssmt_params *params);