| #include <string.h> |
| |
| #include "utilsx1.h" |
| |
| #include "address.h" |
| #include "params.h" |
| #include "thash.h" |
| #include "utils.h" |
| |
| /* |
| * Generate the entire Merkle tree, computing the authentication path for |
| * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. |
| * Expects the layer and tree parts of the tree_addr to be set, as well as the |
| * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) |
| * |
| * This expects tree_addr to be initialized to the addr structures for the |
| * Merkle tree nodes |
| * |
| * Applies the offset idx_offset to indices before building addresses, so that |
| * it is possible to continue counting indices across trees. |
| * |
| * This works by using the standard Merkle tree building algorithm, |
| */ |
| void treehashx1(unsigned char *root, unsigned char *auth_path, |
| const spx_ctx *ctx, |
| uint32_t leaf_idx, uint32_t idx_offset, |
| uint32_t tree_height, |
| void (*gen_leaf)( |
| unsigned char * /* Where to write the leaves */, |
| const spx_ctx * /* ctx */, |
| uint32_t idx, void *info), |
| uint32_t tree_addr[8], |
| void *info) { |
| /* This is where we keep the intermediate nodes */ |
| PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); |
| |
| uint32_t idx; |
| uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); |
| for (idx = 0;; idx++) { |
| unsigned char current[2 * SPX_N]; /* Current logical node is at */ |
| /* index[SPX_N]. We do this to minimize the number of copies */ |
| /* needed during a thash */ |
| gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, |
| info ); |
| |
| /* Now combine the freshly generated right node with previously */ |
| /* generated left ones */ |
| uint32_t internal_idx_offset = idx_offset; |
| uint32_t internal_idx = idx; |
| uint32_t internal_leaf = leaf_idx; |
| uint32_t h; /* The height we are in the Merkle tree */ |
| for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { |
| |
| /* Check if we hit the top of the tree */ |
| if (h == tree_height) { |
| /* We hit the root; return it */ |
| memcpy( root, ¤t[SPX_N], SPX_N ); |
| return; |
| } |
| |
| /* |
| * Check if the node we have is a part of the |
| * authentication path; if it is, write it out |
| */ |
| if ((internal_idx ^ internal_leaf) == 0x01) { |
| memcpy( &auth_path[ h * SPX_N ], |
| ¤t[SPX_N], |
| SPX_N ); |
| } |
| |
| /* |
| * Check if we're at a left child; if so, stop going up the stack |
| * Exception: if we've reached the end of the tree, keep on going |
| * (so we combine the last 4 nodes into the one root node in two |
| * more iterations) |
| */ |
| if ((internal_idx & 1) == 0 && idx < max_idx) { |
| break; |
| } |
| |
| /* Ok, we're at a right node */ |
| /* Now combine the left and right logical nodes together */ |
| |
| /* Set the address of the node we're creating. */ |
| internal_idx_offset >>= 1; |
| set_tree_height(tree_addr, h + 1); |
| set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); |
| |
| unsigned char *left = &stack[h * SPX_N]; |
| memcpy( ¤t[0], left, SPX_N ); |
| thash( ¤t[1 * SPX_N], |
| ¤t[0 * SPX_N], |
| 2, ctx, tree_addr); |
| } |
| |
| /* We've hit a left child; save the current for when we get the */ |
| /* corresponding right right */ |
| memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); |
| } |
| } |