From ba70da9189f05976e4dace98f6594ea9dbaaf6ad Mon Sep 17 00:00:00 2001 From: Joost Rijneveld Date: Tue, 9 Apr 2019 18:11:50 +0200 Subject: [PATCH] Fix variable-length arrays using wrappers --- .../sphincs-shake256-128f-simple/clean/fors.c | 17 +++-- .../sphincs-shake256-128f-simple/clean/sign.c | 16 ++--- .../clean/thash.h | 16 ++++- .../clean/thash_shake256_simple.c | 44 ++++++++++++- .../clean/utils.c | 62 +++++++++++++++---- .../clean/utils.h | 15 ++++- .../sphincs-shake256-128f-simple/clean/wots.c | 4 +- 7 files changed, 137 insertions(+), 37 deletions(-) diff --git a/crypto_sign/sphincs-shake256-128f-simple/clean/fors.c b/crypto_sign/sphincs-shake256-128f-simple/clean/fors.c index 6eacf1a3..74090621 100644 --- a/crypto_sign/sphincs-shake256-128f-simple/clean/fors.c +++ b/crypto_sign/sphincs-shake256-128f-simple/clean/fors.c @@ -17,8 +17,8 @@ static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, const unsigned char *pub_seed, uint32_t fors_leaf_addr[8]) { - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash( - leaf, sk, 1, pub_seed, fors_leaf_addr); + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_1( + leaf, sk, pub_seed, fors_leaf_addr); } static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, @@ -97,16 +97,15 @@ void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_fors_sign( sig += SPX_N; /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_treehash( + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_treehash_FORS_HEIGHT( roots + i * SPX_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leaf, - fors_tree_addr); + indices[i], idx_offset, fors_gen_leaf, fors_tree_addr); sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash( - pk, roots, SPX_FORS_TREES, pub_seed, fors_pk_addr); + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_FORS_TREES( + pk, roots, pub_seed, fors_pk_addr); } /** @@ -160,6 +159,6 @@ void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_fors_pk_from_sig( } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash( - pk, roots, SPX_FORS_TREES, pub_seed, fors_pk_addr); + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_FORS_TREES( + pk, roots, pub_seed, fors_pk_addr); } diff --git a/crypto_sign/sphincs-shake256-128f-simple/clean/sign.c b/crypto_sign/sphincs-shake256-128f-simple/clean/sign.c index 156157db..16523460 100644 --- a/crypto_sign/sphincs-shake256-128f-simple/clean/sign.c +++ b/crypto_sign/sphincs-shake256-128f-simple/clean/sign.c @@ -37,8 +37,8 @@ static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_copy_keypair_addr( wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash( - leaf, pk, SPX_WOTS_LEN, pub_seed, wots_pk_addr); + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_WOTS_LEN( + leaf, pk, pub_seed, wots_pk_addr); } /* @@ -97,8 +97,8 @@ int PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_crypto_sign_seed_keypair( PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_initialize_hash_function(pk, sk); /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_treehash( - sk + 3 * SPX_N, auth_path, sk, sk + 2 * SPX_N, 0, 0, SPX_TREE_HEIGHT, + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_treehash_TREE_HEIGHT( + sk + 3 * SPX_N, auth_path, sk, sk + 2 * SPX_N, 0, 0, wots_gen_leaf, top_tree_addr); memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); @@ -188,9 +188,9 @@ int PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_crypto_sign_signature( sig += SPX_WOTS_BYTES; /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_treehash( + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_treehash_TREE_HEIGHT( root, sig, sk_seed, pub_seed, idx_leaf, 0, - SPX_TREE_HEIGHT, wots_gen_leaf, tree_addr); + wots_gen_leaf, tree_addr); sig += SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ @@ -274,8 +274,8 @@ int PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_crypto_sign_verify( sig += SPX_WOTS_BYTES; /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash( - leaf, wots_pk, SPX_WOTS_LEN, pub_seed, wots_pk_addr); + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_WOTS_LEN( + leaf, wots_pk, pub_seed, wots_pk_addr); /* Compute the root node of this subtree. */ PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_compute_root( diff --git a/crypto_sign/sphincs-shake256-128f-simple/clean/thash.h b/crypto_sign/sphincs-shake256-128f-simple/clean/thash.h index bad72599..605de340 100644 --- a/crypto_sign/sphincs-shake256-128f-simple/clean/thash.h +++ b/crypto_sign/sphincs-shake256-128f-simple/clean/thash.h @@ -3,8 +3,20 @@ #include -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash( - unsigned char *out, const unsigned char *in, unsigned int inblocks, +void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_1( + unsigned char *out, const unsigned char *in, + const unsigned char *pub_seed, uint32_t addr[8]); + +void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_2( + unsigned char *out, const unsigned char *in, + const unsigned char *pub_seed, uint32_t addr[8]); + +void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_WOTS_LEN( + unsigned char *out, const unsigned char *in, + const unsigned char *pub_seed, uint32_t addr[8]); + +void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_FORS_TREES( + unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, uint32_t addr[8]); #endif diff --git a/crypto_sign/sphincs-shake256-128f-simple/clean/thash_shake256_simple.c b/crypto_sign/sphincs-shake256-128f-simple/clean/thash_shake256_simple.c index 71729727..7c2cdb63 100644 --- a/crypto_sign/sphincs-shake256-128f-simple/clean/thash_shake256_simple.c +++ b/crypto_sign/sphincs-shake256-128f-simple/clean/thash_shake256_simple.c @@ -10,10 +10,10 @@ /** * Takes an array of inblocks concatenated arrays of SPX_N bytes. */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash( - unsigned char *out, const unsigned char *in, unsigned int inblocks, +static void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash( + unsigned char *out, unsigned char *buf, + const unsigned char *in, unsigned int inblocks, const unsigned char *pub_seed, uint32_t addr[8]) { - unsigned char buf[SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N]; memcpy(buf, pub_seed, SPX_N); PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_addr_to_bytes(buf + SPX_N, addr); @@ -21,3 +21,41 @@ void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash( shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); } + +/* The wrappers below ensure that we use fixed-size buffers on the stack */ + +void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_1( + unsigned char *out, const unsigned char *in, + const unsigned char *pub_seed, uint32_t addr[8]) { + + unsigned char buf[SPX_N + SPX_ADDR_BYTES + 1 * SPX_N]; + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash( + out, buf, in, 1, pub_seed, addr); +} + +void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_2( + unsigned char *out, const unsigned char *in, + const unsigned char *pub_seed, uint32_t addr[8]) { + + unsigned char buf[SPX_N + SPX_ADDR_BYTES + 2 * SPX_N]; + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash( + out, buf, in, 2, pub_seed, addr); +} + +void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_WOTS_LEN( + unsigned char *out, const unsigned char *in, + const unsigned char *pub_seed, uint32_t addr[8]) { + + unsigned char buf[SPX_N + SPX_ADDR_BYTES + SPX_WOTS_LEN * SPX_N]; + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash( + out, buf, in, SPX_WOTS_LEN, pub_seed, addr); +} + +void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_FORS_TREES( + unsigned char *out, const unsigned char *in, + const unsigned char *pub_seed, uint32_t addr[8]) { + + unsigned char buf[SPX_N + SPX_ADDR_BYTES + SPX_FORS_TREES * SPX_N]; + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash( + out, buf, in, SPX_FORS_TREES, pub_seed, addr); +} diff --git a/crypto_sign/sphincs-shake256-128f-simple/clean/utils.c b/crypto_sign/sphincs-shake256-128f-simple/clean/utils.c index 89bc884c..2a367645 100644 --- a/crypto_sign/sphincs-shake256-128f-simple/clean/utils.c +++ b/crypto_sign/sphincs-shake256-128f-simple/clean/utils.c @@ -66,12 +66,12 @@ void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_compute_root( /* Pick the right or left neighbor, depending on parity of the node. */ if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash( - buffer + SPX_N, buffer, 2, pub_seed, addr); + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_2( + buffer + SPX_N, buffer, pub_seed, addr); memcpy(buffer, auth_path, SPX_N); } else { - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash( - buffer, buffer, 2, pub_seed, addr); + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_2( + buffer, buffer, pub_seed, addr); memcpy(buffer + SPX_N, auth_path, SPX_N); } auth_path += SPX_N; @@ -83,8 +83,8 @@ void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_compute_root( PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_tree_height(addr, tree_height); PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_tree_index( addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash( - root, buffer, 2, pub_seed, addr); + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_2( + root, buffer, pub_seed, addr); } /** @@ -95,8 +95,9 @@ void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_compute_root( * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_treehash( +static void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_treehash( unsigned char *root, unsigned char *auth_path, + unsigned char *stack, unsigned int *heights, const unsigned char *sk_seed, const unsigned char *pub_seed, uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, void (*gen_leaf)( @@ -105,8 +106,7 @@ void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_treehash( const unsigned char * /* pub_seed */, uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), uint32_t tree_addr[8]) { - unsigned char stack[(tree_height + 1)*SPX_N]; - unsigned int heights[tree_height + 1]; + unsigned int offset = 0; uint32_t idx; uint32_t tree_idx; @@ -134,8 +134,8 @@ void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_treehash( PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_tree_index( tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash( - stack + (offset - 2)*SPX_N, stack + (offset - 2)*SPX_N, 2, + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_2( + stack + (offset - 2)*SPX_N, stack + (offset - 2)*SPX_N, pub_seed, tree_addr); offset--; /* Note that the top-most node is now one layer higher. */ @@ -150,3 +150,43 @@ void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_treehash( } memcpy(root, stack, SPX_N); } + +/* The wrappers below ensure that we use fixed-size buffers on the stack */ + +void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_treehash_FORS_HEIGHT( + unsigned char *root, unsigned char *auth_path, + const unsigned char *sk_seed, const unsigned char *pub_seed, + uint32_t leaf_idx, uint32_t idx_offset, + void (*gen_leaf)( + unsigned char * /* leaf */, + const unsigned char * /* sk_seed */, + const unsigned char * /* pub_seed */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + + unsigned char stack[(SPX_FORS_HEIGHT + 1)*SPX_N]; + unsigned int heights[SPX_FORS_HEIGHT + 1]; + + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_treehash( + root, auth_path, stack, heights, sk_seed, pub_seed, + leaf_idx, idx_offset, SPX_FORS_HEIGHT, gen_leaf, tree_addr); +} + +void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_treehash_TREE_HEIGHT( + unsigned char *root, unsigned char *auth_path, + const unsigned char *sk_seed, const unsigned char *pub_seed, + uint32_t leaf_idx, uint32_t idx_offset, + void (*gen_leaf)( + unsigned char * /* leaf */, + const unsigned char * /* sk_seed */, + const unsigned char * /* pub_seed */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + + unsigned char stack[(SPX_TREE_HEIGHT + 1)*SPX_N]; + unsigned int heights[SPX_TREE_HEIGHT + 1]; + + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_treehash( + root, auth_path, stack, heights, sk_seed, pub_seed, + leaf_idx, idx_offset, SPX_TREE_HEIGHT, gen_leaf, tree_addr); +} diff --git a/crypto_sign/sphincs-shake256-128f-simple/clean/utils.h b/crypto_sign/sphincs-shake256-128f-simple/clean/utils.h index 05c32eb7..dd89b4fc 100644 --- a/crypto_sign/sphincs-shake256-128f-simple/clean/utils.h +++ b/crypto_sign/sphincs-shake256-128f-simple/clean/utils.h @@ -35,10 +35,21 @@ void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_compute_root( * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_treehash( +void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_treehash_FORS_HEIGHT( unsigned char *root, unsigned char *auth_path, const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + uint32_t leaf_idx, uint32_t idx_offset, + void (*gen_leaf)( + unsigned char * /* leaf */, + const unsigned char * /* sk_seed */, + const unsigned char * /* pub_seed */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + +void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_treehash_TREE_HEIGHT( + unsigned char *root, unsigned char *auth_path, + const unsigned char *sk_seed, const unsigned char *pub_seed, + uint32_t leaf_idx, uint32_t idx_offset, void (*gen_leaf)( unsigned char * /* leaf */, const unsigned char * /* sk_seed */, diff --git a/crypto_sign/sphincs-shake256-128f-simple/clean/wots.c b/crypto_sign/sphincs-shake256-128f-simple/clean/wots.c index 16e41af4..f88b3a69 100644 --- a/crypto_sign/sphincs-shake256-128f-simple/clean/wots.c +++ b/crypto_sign/sphincs-shake256-128f-simple/clean/wots.c @@ -43,8 +43,8 @@ static void gen_chain(unsigned char *out, const unsigned char *in, /* Iterate 'steps' calls to the hash function. */ for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash( - out, out, 1, pub_seed, addr); + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_1( + out, out, pub_seed, addr); } }