1*8fb009dcSAndroid Build Coastguard Worker /* Copyright (c) 2023, Google LLC
2*8fb009dcSAndroid Build Coastguard Worker *
3*8fb009dcSAndroid Build Coastguard Worker * Permission to use, copy, modify, and/or distribute this software for any
4*8fb009dcSAndroid Build Coastguard Worker * purpose with or without fee is hereby granted, provided that the above
5*8fb009dcSAndroid Build Coastguard Worker * copyright notice and this permission notice appear in all copies.
6*8fb009dcSAndroid Build Coastguard Worker *
7*8fb009dcSAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8*8fb009dcSAndroid Build Coastguard Worker * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9*8fb009dcSAndroid Build Coastguard Worker * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10*8fb009dcSAndroid Build Coastguard Worker * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11*8fb009dcSAndroid Build Coastguard Worker * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12*8fb009dcSAndroid Build Coastguard Worker * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13*8fb009dcSAndroid Build Coastguard Worker * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14*8fb009dcSAndroid Build Coastguard Worker
15*8fb009dcSAndroid Build Coastguard Worker #include <openssl/base.h>
16*8fb009dcSAndroid Build Coastguard Worker
17*8fb009dcSAndroid Build Coastguard Worker #include <assert.h>
18*8fb009dcSAndroid Build Coastguard Worker #include <stdio.h>
19*8fb009dcSAndroid Build Coastguard Worker #include <string.h>
20*8fb009dcSAndroid Build Coastguard Worker
21*8fb009dcSAndroid Build Coastguard Worker #include <openssl/sha.h>
22*8fb009dcSAndroid Build Coastguard Worker
23*8fb009dcSAndroid Build Coastguard Worker #include "./params.h"
24*8fb009dcSAndroid Build Coastguard Worker #include "./spx_util.h"
25*8fb009dcSAndroid Build Coastguard Worker #include "./thash.h"
26*8fb009dcSAndroid Build Coastguard Worker
spx_thash(uint8_t * output,const uint8_t * input,size_t input_blocks,const uint8_t pk_seed[SPX_N],uint8_t addr[32])27*8fb009dcSAndroid Build Coastguard Worker static void spx_thash(uint8_t *output, const uint8_t *input,
28*8fb009dcSAndroid Build Coastguard Worker size_t input_blocks, const uint8_t pk_seed[SPX_N],
29*8fb009dcSAndroid Build Coastguard Worker uint8_t addr[32]) {
30*8fb009dcSAndroid Build Coastguard Worker uint8_t hash[32];
31*8fb009dcSAndroid Build Coastguard Worker SHA256_CTX sha256;
32*8fb009dcSAndroid Build Coastguard Worker SHA256_Init(&sha256);
33*8fb009dcSAndroid Build Coastguard Worker
34*8fb009dcSAndroid Build Coastguard Worker // Process pubseed with padding to full block.
35*8fb009dcSAndroid Build Coastguard Worker // TODO: This could be precomputed instead as it will be the same across all
36*8fb009dcSAndroid Build Coastguard Worker // hash calls.
37*8fb009dcSAndroid Build Coastguard Worker uint8_t padded_pk_seed[64] = {0};
38*8fb009dcSAndroid Build Coastguard Worker memcpy(padded_pk_seed, pk_seed, SPX_N);
39*8fb009dcSAndroid Build Coastguard Worker
40*8fb009dcSAndroid Build Coastguard Worker SHA256_Update(&sha256, padded_pk_seed, sizeof(padded_pk_seed));
41*8fb009dcSAndroid Build Coastguard Worker SHA256_Update(&sha256, addr, SPX_SHA256_ADDR_BYTES);
42*8fb009dcSAndroid Build Coastguard Worker SHA256_Update(&sha256, input, input_blocks * SPX_N);
43*8fb009dcSAndroid Build Coastguard Worker
44*8fb009dcSAndroid Build Coastguard Worker SHA256_Final(hash, &sha256);
45*8fb009dcSAndroid Build Coastguard Worker memcpy(output, hash, SPX_N);
46*8fb009dcSAndroid Build Coastguard Worker }
47*8fb009dcSAndroid Build Coastguard Worker
spx_thash_f(uint8_t * output,const uint8_t input[SPX_N],const uint8_t pk_seed[SPX_N],uint8_t addr[32])48*8fb009dcSAndroid Build Coastguard Worker void spx_thash_f(uint8_t *output, const uint8_t input[SPX_N],
49*8fb009dcSAndroid Build Coastguard Worker const uint8_t pk_seed[SPX_N], uint8_t addr[32]) {
50*8fb009dcSAndroid Build Coastguard Worker spx_thash(output, input, 1, pk_seed, addr);
51*8fb009dcSAndroid Build Coastguard Worker }
52*8fb009dcSAndroid Build Coastguard Worker
spx_thash_h(uint8_t * output,const uint8_t input[2* SPX_N],const uint8_t pk_seed[SPX_N],uint8_t addr[32])53*8fb009dcSAndroid Build Coastguard Worker void spx_thash_h(uint8_t *output, const uint8_t input[2 * SPX_N],
54*8fb009dcSAndroid Build Coastguard Worker const uint8_t pk_seed[SPX_N], uint8_t addr[32]) {
55*8fb009dcSAndroid Build Coastguard Worker spx_thash(output, input, 2, pk_seed, addr);
56*8fb009dcSAndroid Build Coastguard Worker }
57*8fb009dcSAndroid Build Coastguard Worker
spx_thash_hmsg(uint8_t * output,const uint8_t r[SPX_N],const uint8_t pk_seed[SPX_N],const uint8_t pk_root[SPX_N],const uint8_t * msg,size_t msg_len)58*8fb009dcSAndroid Build Coastguard Worker void spx_thash_hmsg(uint8_t *output, const uint8_t r[SPX_N],
59*8fb009dcSAndroid Build Coastguard Worker const uint8_t pk_seed[SPX_N], const uint8_t pk_root[SPX_N],
60*8fb009dcSAndroid Build Coastguard Worker const uint8_t *msg, size_t msg_len) {
61*8fb009dcSAndroid Build Coastguard Worker // MGF1-SHA-256(R || PK.seed || SHA-256(R || PK.seed || PK.root || M), m)
62*8fb009dcSAndroid Build Coastguard Worker // input_buffer stores R || PK_SEED || SHA256(..) || 4-byte index
63*8fb009dcSAndroid Build Coastguard Worker uint8_t input_buffer[2 * SPX_N + 32 + 4] = {0};
64*8fb009dcSAndroid Build Coastguard Worker memcpy(input_buffer, r, SPX_N);
65*8fb009dcSAndroid Build Coastguard Worker memcpy(input_buffer + SPX_N, pk_seed, SPX_N);
66*8fb009dcSAndroid Build Coastguard Worker
67*8fb009dcSAndroid Build Coastguard Worker // Inner hash
68*8fb009dcSAndroid Build Coastguard Worker SHA256_CTX ctx;
69*8fb009dcSAndroid Build Coastguard Worker SHA256_Init(&ctx);
70*8fb009dcSAndroid Build Coastguard Worker SHA256_Update(&ctx, r, SPX_N);
71*8fb009dcSAndroid Build Coastguard Worker SHA256_Update(&ctx, pk_seed, SPX_N);
72*8fb009dcSAndroid Build Coastguard Worker SHA256_Update(&ctx, pk_root, SPX_N);
73*8fb009dcSAndroid Build Coastguard Worker SHA256_Update(&ctx, msg, msg_len);
74*8fb009dcSAndroid Build Coastguard Worker // Write directly into the input buffer
75*8fb009dcSAndroid Build Coastguard Worker SHA256_Final(input_buffer + 2 * SPX_N, &ctx);
76*8fb009dcSAndroid Build Coastguard Worker
77*8fb009dcSAndroid Build Coastguard Worker // MGF1-SHA-256
78*8fb009dcSAndroid Build Coastguard Worker uint8_t output_buffer[3 * 32];
79*8fb009dcSAndroid Build Coastguard Worker // Need to call SHA256 3 times for message digest.
80*8fb009dcSAndroid Build Coastguard Worker static_assert(SPX_DIGEST_SIZE <= sizeof(output_buffer),
81*8fb009dcSAndroid Build Coastguard Worker "not enough room for hashes");
82*8fb009dcSAndroid Build Coastguard Worker SHA256(input_buffer, sizeof(input_buffer), output_buffer);
83*8fb009dcSAndroid Build Coastguard Worker input_buffer[2 * SPX_N + 32 + 3] = 1;
84*8fb009dcSAndroid Build Coastguard Worker SHA256(input_buffer, sizeof(input_buffer), output_buffer + 32);
85*8fb009dcSAndroid Build Coastguard Worker input_buffer[2 * SPX_N + 32 + 3] = 2;
86*8fb009dcSAndroid Build Coastguard Worker SHA256(input_buffer, sizeof(input_buffer), output_buffer + 64);
87*8fb009dcSAndroid Build Coastguard Worker
88*8fb009dcSAndroid Build Coastguard Worker memcpy(output, output_buffer, SPX_DIGEST_SIZE);
89*8fb009dcSAndroid Build Coastguard Worker }
90*8fb009dcSAndroid Build Coastguard Worker
spx_thash_prf(uint8_t * output,const uint8_t pk_seed[SPX_N],const uint8_t sk_seed[SPX_N],uint8_t addr[32])91*8fb009dcSAndroid Build Coastguard Worker void spx_thash_prf(uint8_t *output, const uint8_t pk_seed[SPX_N],
92*8fb009dcSAndroid Build Coastguard Worker const uint8_t sk_seed[SPX_N], uint8_t addr[32]) {
93*8fb009dcSAndroid Build Coastguard Worker spx_thash(output, sk_seed, 1, pk_seed, addr);
94*8fb009dcSAndroid Build Coastguard Worker }
95*8fb009dcSAndroid Build Coastguard Worker
spx_thash_prfmsg(uint8_t * output,const uint8_t sk_prf[SPX_N],const uint8_t opt_rand[SPX_N],const uint8_t * msg,size_t msg_len)96*8fb009dcSAndroid Build Coastguard Worker void spx_thash_prfmsg(uint8_t *output, const uint8_t sk_prf[SPX_N],
97*8fb009dcSAndroid Build Coastguard Worker const uint8_t opt_rand[SPX_N], const uint8_t *msg,
98*8fb009dcSAndroid Build Coastguard Worker size_t msg_len) {
99*8fb009dcSAndroid Build Coastguard Worker // Compute HMAC-SHA256(sk_prf, opt_rand || msg). We inline HMAC to avoid an
100*8fb009dcSAndroid Build Coastguard Worker // allocation.
101*8fb009dcSAndroid Build Coastguard Worker uint8_t hmac_key[SHA256_CBLOCK] = {0};
102*8fb009dcSAndroid Build Coastguard Worker static_assert(SPX_N <= SHA256_CBLOCK, "HMAC key is larger than block size");
103*8fb009dcSAndroid Build Coastguard Worker memcpy(hmac_key, sk_prf, SPX_N);
104*8fb009dcSAndroid Build Coastguard Worker for (size_t i = 0; i < sizeof(hmac_key); i++) {
105*8fb009dcSAndroid Build Coastguard Worker hmac_key[i] ^= 0x36;
106*8fb009dcSAndroid Build Coastguard Worker }
107*8fb009dcSAndroid Build Coastguard Worker
108*8fb009dcSAndroid Build Coastguard Worker uint8_t hash[SHA256_DIGEST_LENGTH];
109*8fb009dcSAndroid Build Coastguard Worker SHA256_CTX ctx;
110*8fb009dcSAndroid Build Coastguard Worker SHA256_Init(&ctx);
111*8fb009dcSAndroid Build Coastguard Worker SHA256_Update(&ctx, hmac_key, sizeof(hmac_key));
112*8fb009dcSAndroid Build Coastguard Worker SHA256_Update(&ctx, opt_rand, SPX_N);
113*8fb009dcSAndroid Build Coastguard Worker SHA256_Update(&ctx, msg, msg_len);
114*8fb009dcSAndroid Build Coastguard Worker SHA256_Final(hash, &ctx);
115*8fb009dcSAndroid Build Coastguard Worker
116*8fb009dcSAndroid Build Coastguard Worker for (size_t i = 0; i < sizeof(hmac_key); i++) {
117*8fb009dcSAndroid Build Coastguard Worker hmac_key[i] ^= 0x36 ^ 0x5c;
118*8fb009dcSAndroid Build Coastguard Worker }
119*8fb009dcSAndroid Build Coastguard Worker SHA256_Init(&ctx);
120*8fb009dcSAndroid Build Coastguard Worker SHA256_Update(&ctx, hmac_key, sizeof(hmac_key));
121*8fb009dcSAndroid Build Coastguard Worker SHA256_Update(&ctx, hash, sizeof(hash));
122*8fb009dcSAndroid Build Coastguard Worker SHA256_Final(hash, &ctx);
123*8fb009dcSAndroid Build Coastguard Worker
124*8fb009dcSAndroid Build Coastguard Worker // Truncate to SPX_N bytes
125*8fb009dcSAndroid Build Coastguard Worker memcpy(output, hash, SPX_N);
126*8fb009dcSAndroid Build Coastguard Worker }
127*8fb009dcSAndroid Build Coastguard Worker
spx_thash_tl(uint8_t * output,const uint8_t input[SPX_WOTS_BYTES],const uint8_t pk_seed[SPX_N],uint8_t addr[32])128*8fb009dcSAndroid Build Coastguard Worker void spx_thash_tl(uint8_t *output, const uint8_t input[SPX_WOTS_BYTES],
129*8fb009dcSAndroid Build Coastguard Worker const uint8_t pk_seed[SPX_N], uint8_t addr[32]) {
130*8fb009dcSAndroid Build Coastguard Worker spx_thash(output, input, SPX_WOTS_LEN, pk_seed, addr);
131*8fb009dcSAndroid Build Coastguard Worker }
132*8fb009dcSAndroid Build Coastguard Worker
spx_thash_tk(uint8_t * output,const uint8_t input[SPX_FORS_TREES * SPX_N],const uint8_t pk_seed[SPX_N],uint8_t addr[32])133*8fb009dcSAndroid Build Coastguard Worker void spx_thash_tk(uint8_t *output, const uint8_t input[SPX_FORS_TREES * SPX_N],
134*8fb009dcSAndroid Build Coastguard Worker const uint8_t pk_seed[SPX_N], uint8_t addr[32]) {
135*8fb009dcSAndroid Build Coastguard Worker spx_thash(output, input, SPX_FORS_TREES, pk_seed, addr);
136*8fb009dcSAndroid Build Coastguard Worker }
137