/src/boringssl/crypto/fipsmodule/slhdsa/wots.cc.inc
Line | Count | Source |
1 | | // Copyright 2024 The BoringSSL Authors |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // https://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | #include <openssl/base.h> |
16 | | |
17 | | #include <assert.h> |
18 | | #include <stdint.h> |
19 | | #include <string.h> |
20 | | |
21 | | #include "../../internal.h" |
22 | | #include "./address.h" |
23 | | #include "./params.h" |
24 | | #include "./thash.h" |
25 | | #include "./wots.h" |
26 | | |
27 | | |
28 | | // Implements Algorithm 5: chain function, page 18 |
29 | | static void chain(const slh_dsa_config *config, uint8_t *output, |
30 | | const uint8_t *input, uint32_t start, uint32_t steps, |
31 | 0 | const uint8_t *pub_seed, uint8_t addr[32]) { |
32 | 0 | assert(start < config->wots_w); |
33 | 0 | assert(steps < config->wots_w); |
34 | | |
35 | 0 | OPENSSL_memcpy(output, input, config->n); |
36 | |
|
37 | 0 | for (uint32_t i = start; i < (start + steps) && i < config->wots_w; ++i) { |
38 | 0 | slhdsa_set_hash_addr(config, addr, i); |
39 | 0 | slhdsa_thash_f(config, output, output, pub_seed, addr); |
40 | 0 | } |
41 | 0 | } |
42 | | |
43 | | static void slhdsa_wots_do_chain(const slh_dsa_config *config, uint8_t *out, |
44 | | uint8_t sk_addr[32], uint8_t addr[32], |
45 | | uint8_t value, const uint8_t *sk_seed, |
46 | | const uint8_t *pub_seed, |
47 | 0 | uint32_t chain_index) { |
48 | 0 | uint8_t tmp_sk[SLHDSA_MAX_N]; |
49 | 0 | slhdsa_set_chain_addr(config, sk_addr, chain_index); |
50 | 0 | slhdsa_thash_prf(config, tmp_sk, pub_seed, sk_seed, sk_addr); |
51 | 0 | slhdsa_set_chain_addr(config, addr, chain_index); |
52 | 0 | chain(config, out, tmp_sk, 0, value, pub_seed, addr); |
53 | 0 | } |
54 | | |
55 | | // Implements Algorithm 6: wots_pkGen function, page 18 |
56 | | void slhdsa_wots_pk_gen(const slh_dsa_config *config, uint8_t *pk, |
57 | | const uint8_t *sk_seed, const uint8_t *pub_seed, |
58 | 0 | uint8_t addr[32]) { |
59 | 0 | uint8_t wots_pk_addr[32], sk_addr[32]; |
60 | 0 | OPENSSL_memcpy(wots_pk_addr, addr, sizeof(wots_pk_addr)); |
61 | 0 | OPENSSL_memcpy(sk_addr, addr, sizeof(sk_addr)); |
62 | 0 | slhdsa_set_type(config, sk_addr, SLHDSA_ADDR_TYPE_WOTSPRF); |
63 | 0 | slhdsa_copy_keypair_addr(config, sk_addr, addr); |
64 | |
|
65 | 0 | uint8_t tmp[SLHDSA_MAX_WOTS_BYTES]; |
66 | 0 | const uint32_t n = config->n; |
67 | 0 | const uint32_t wots_len = slhdsa_wots_len(config); |
68 | 0 | const uint32_t max_chain = config->wots_w - 1; |
69 | 0 | for (uint32_t i = 0; i < wots_len; ++i) { |
70 | 0 | slhdsa_wots_do_chain(config, tmp + i * n, sk_addr, addr, max_chain, sk_seed, |
71 | 0 | pub_seed, i); |
72 | 0 | } |
73 | | |
74 | | // Compress pk |
75 | 0 | slhdsa_set_type(config, wots_pk_addr, SLHDSA_ADDR_TYPE_WOTSPK); |
76 | 0 | slhdsa_copy_keypair_addr(config, wots_pk_addr, addr); |
77 | 0 | slhdsa_thash_tl(config, pk, tmp, pub_seed, wots_pk_addr); |
78 | 0 | } |
79 | | |
80 | | // Implements Algorithm 7: wots_sign function, page 20 |
81 | | void slhdsa_wots_sign(const slh_dsa_config *config, uint8_t *sig, |
82 | | const uint8_t *msg, const uint8_t *sk_seed, |
83 | 0 | const uint8_t *pub_seed, uint8_t addr[32]) { |
84 | 0 | BSSL_CHECK(config->wots_w == 16); |
85 | 0 | const size_t n = config->n; |
86 | 0 | const uint32_t max_chain = config->wots_w - 1; |
87 | |
|
88 | 0 | uint16_t csum = 0; |
89 | 0 | for (size_t i = 0; i < n; ++i) { |
90 | 0 | csum += max_chain - (msg[i] >> 4); |
91 | 0 | csum += max_chain - (msg[i] & 15); |
92 | 0 | } |
93 | | |
94 | | // Compute chains |
95 | 0 | uint8_t sk_addr[32]; |
96 | 0 | OPENSSL_memcpy(sk_addr, addr, sizeof(sk_addr)); |
97 | 0 | slhdsa_set_type(config, sk_addr, SLHDSA_ADDR_TYPE_WOTSPRF); |
98 | 0 | slhdsa_copy_keypair_addr(config, sk_addr, addr); |
99 | |
|
100 | 0 | uint32_t chain_index = 0; |
101 | 0 | for (size_t i = 0; i < n; ++i) { |
102 | 0 | slhdsa_wots_do_chain(config, sig, sk_addr, addr, msg[i] >> 4, sk_seed, |
103 | 0 | pub_seed, chain_index++); |
104 | 0 | sig += n; |
105 | |
|
106 | 0 | slhdsa_wots_do_chain(config, sig, sk_addr, addr, msg[i] & 15, sk_seed, |
107 | 0 | pub_seed, chain_index++); |
108 | 0 | sig += n; |
109 | 0 | } |
110 | | |
111 | | // Include the WOTS checksum values (len2 = 3 for the parameter sets we |
112 | | // support). |
113 | 0 | slhdsa_wots_do_chain(config, sig, sk_addr, addr, (csum >> 8) & 15, sk_seed, |
114 | 0 | pub_seed, chain_index++); |
115 | 0 | sig += n; |
116 | 0 | slhdsa_wots_do_chain(config, sig, sk_addr, addr, (csum >> 4) & 15, sk_seed, |
117 | 0 | pub_seed, chain_index++); |
118 | 0 | sig += n; |
119 | 0 | slhdsa_wots_do_chain(config, sig, sk_addr, addr, csum & 15, sk_seed, pub_seed, |
120 | 0 | chain_index++); |
121 | 0 | } |
122 | | |
123 | | static void slhdsa_wots_pk_from_sig_do_chain(const slh_dsa_config *config, |
124 | | uint8_t *out, uint8_t addr[32], |
125 | | const uint8_t *in, uint8_t value, |
126 | | const uint8_t *pub_seed, |
127 | 0 | uint32_t chain_index) { |
128 | 0 | slhdsa_set_chain_addr(config, addr, chain_index); |
129 | 0 | chain(config, out + chain_index * config->n, in + chain_index * config->n, |
130 | 0 | value, (config->wots_w - 1) - value, pub_seed, addr); |
131 | 0 | } |
132 | | |
133 | | // Implements Algorithm 8: wots_pkFromSig function, page 21 |
134 | | void slhdsa_wots_pk_from_sig(const slh_dsa_config *config, uint8_t *pk, |
135 | | const uint8_t *sig, const uint8_t *msg, |
136 | 0 | const uint8_t *pub_seed, uint8_t addr[32]) { |
137 | 0 | BSSL_CHECK(config->wots_w == 16); |
138 | 0 | const size_t n = config->n; |
139 | 0 | const uint32_t max_chain = config->wots_w - 1; |
140 | |
|
141 | 0 | uint16_t csum = 0; |
142 | 0 | for (size_t i = 0; i < n; ++i) { |
143 | 0 | csum += max_chain - (msg[i] >> 4); |
144 | 0 | csum += max_chain - (msg[i] & 15); |
145 | 0 | } |
146 | |
|
147 | 0 | uint8_t tmp[SLHDSA_MAX_WOTS_BYTES]; |
148 | 0 | uint8_t wots_pk_addr[32]; |
149 | 0 | OPENSSL_memcpy(wots_pk_addr, addr, sizeof(wots_pk_addr)); |
150 | |
|
151 | 0 | uint32_t chain_index = 0; |
152 | 0 | for (size_t i = 0; i < n; ++i) { |
153 | 0 | slhdsa_wots_pk_from_sig_do_chain(config, tmp, addr, sig, msg[i] >> 4, |
154 | 0 | pub_seed, chain_index++); |
155 | 0 | slhdsa_wots_pk_from_sig_do_chain(config, tmp, addr, sig, msg[i] & 15, |
156 | 0 | pub_seed, chain_index++); |
157 | 0 | } |
158 | |
|
159 | 0 | slhdsa_wots_pk_from_sig_do_chain(config, tmp, addr, sig, csum >> 8, pub_seed, |
160 | 0 | chain_index++); |
161 | 0 | slhdsa_wots_pk_from_sig_do_chain(config, tmp, addr, sig, (csum >> 4) & 15, |
162 | 0 | pub_seed, chain_index++); |
163 | 0 | slhdsa_wots_pk_from_sig_do_chain(config, tmp, addr, sig, csum & 15, pub_seed, |
164 | 0 | chain_index++); |
165 | | |
166 | | // Compress pk |
167 | 0 | slhdsa_set_type(config, wots_pk_addr, SLHDSA_ADDR_TYPE_WOTSPK); |
168 | 0 | slhdsa_copy_keypair_addr(config, wots_pk_addr, addr); |
169 | 0 | slhdsa_thash_tl(config, pk, tmp, pub_seed, wots_pk_addr); |
170 | 0 | } |