1 #include <stdint.h>
2 #include <string.h>
3 
4 #include "address.h"
5 #include "hash.h"
6 #include "params.h"
7 #include "utils.h"
8 
9 #include "fips202.h"
10 
11 /* For SHAKE256, there is no immediate reason to initialize at the start,
12    so this function is an empty operation. */
13 void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_initialize_hash_function(
14     hash_state *hash_state_seeded, // NOLINT(readability-non-const-parameter)
15     const unsigned char *pub_seed, const unsigned char *sk_seed) {
16     (void)hash_state_seeded; /* Suppress an 'unused parameter' warning. */
17     (void)pub_seed; /* Suppress an 'unused parameter' warning. */
18     (void)sk_seed; /* Suppress an 'unused parameter' warning. */
19 }
20 
21 /* This is not necessary for SHAKE256, so we don't do anything */
22 void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_destroy_hash_function(
23     hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter)
24     (void)hash_state_seeded;
25 }
26 
27 /*
28  * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N bytes and an address
29  */
30 void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_prf_addr(
31     unsigned char *out, const unsigned char *key, const uint32_t addr[8],
32     const hash_state *hash_state_seeded) {
33     unsigned char buf[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ADDR_BYTES];
34 
35     memcpy(buf, key, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N);
36     PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N, addr);
37 
38     shake256(out, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N, buf, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ADDR_BYTES);
39 
40     (void)hash_state_seeded; /* Prevent unused parameter warning. */
41 }
42 
43 /**
44  * Computes the message-dependent randomness R, using a secret seed and an
45  * optional randomization value as well as the message.
46  */
47 void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_gen_message_random(
48     unsigned char *R,
49     const unsigned char *sk_prf, const unsigned char *optrand,
50     const unsigned char *m, size_t mlen,
51     const hash_state *hash_state_seeded) {
52     shake256incctx state;
53 
54     shake256_inc_init(&state);
55     shake256_inc_absorb(&state, sk_prf, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N);
56     shake256_inc_absorb(&state, optrand, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N);
57     shake256_inc_absorb(&state, m, mlen);
58     shake256_inc_finalize(&state);
59     shake256_inc_squeeze(R, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N, &state);
60     shake256_inc_ctx_release(&state);
61 
62     (void)hash_state_seeded; /* Prevent unused parameter warning. */
63 }
64 
65 /**
66  * Computes the message hash using R, the public key, and the message.
67  * Outputs the message digest and the index of the leaf. The index is split in
68  * the tree index and the leaf index, for convenient copying to an address.
69  */
70 void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_hash_message(
71     unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx,
72     const unsigned char *R, const unsigned char *pk,
73     const unsigned char *m, size_t mlen,
74     const hash_state *hash_state_seeded) {
75 #define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_TREE_BITS (PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_D - 1))
76 #define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_TREE_BITS + 7) / 8)
77 #define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_LEAF_BITS PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_TREE_HEIGHT
78 #define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_LEAF_BITS + 7) / 8)
79 #define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_LEAF_BYTES)
80 
81     unsigned char buf[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_DGST_BYTES];
82     unsigned char *bufp = buf;
83     shake256incctx state;
84 
85     shake256_inc_init(&state);
86     shake256_inc_absorb(&state, R, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N);
87     shake256_inc_absorb(&state, pk, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_PK_BYTES);
88     shake256_inc_absorb(&state, m, mlen);
89     shake256_inc_finalize(&state);
90     shake256_inc_squeeze(buf, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_DGST_BYTES, &state);
91     shake256_inc_ctx_release(&state);
92 
93     memcpy(digest, bufp, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_MSG_BYTES);
94     bufp += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_MSG_BYTES;
95 
96     *tree = PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_bytes_to_ull(
97                 bufp, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_TREE_BYTES);
98     *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_TREE_BITS);
99     bufp += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_TREE_BYTES;
100 
101     *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_bytes_to_ull(
102                     bufp, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_LEAF_BYTES);
103     *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_LEAF_BITS);
104 
105     (void)hash_state_seeded; /* Prevent unused parameter warning. */
106 }
107