/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 | | using namespace bssl; |
29 | | |
30 | | // Implements Algorithm 5: chain function, page 18 |
31 | | static void chain(const slh_dsa_config *config, uint8_t *output, |
32 | | const uint8_t *input, uint32_t start, uint32_t steps, |
33 | 0 | const uint8_t *pub_seed, uint8_t addr[32]) { |
34 | 0 | assert(start < config->wots_w); |
35 | 0 | assert(steps < config->wots_w); |
36 | | |
37 | 0 | OPENSSL_memcpy(output, input, config->n); |
38 | |
|
39 | 0 | for (uint32_t i = start; i < (start + steps) && i < config->wots_w; ++i) { |
40 | 0 | slhdsa_set_hash_addr(config, addr, i); |
41 | 0 | slhdsa_thash_f(config, output, output, pub_seed, addr); |
42 | 0 | } |
43 | 0 | } |
44 | | |
45 | | static void slhdsa_wots_do_chain(const slh_dsa_config *config, uint8_t *out, |
46 | | uint8_t sk_addr[32], uint8_t addr[32], |
47 | | uint8_t value, const uint8_t *sk_seed, |
48 | | const uint8_t *pub_seed, |
49 | 0 | uint32_t chain_index) { |
50 | 0 | uint8_t tmp_sk[SLHDSA_MAX_N]; |
51 | 0 | slhdsa_set_chain_addr(config, sk_addr, chain_index); |
52 | 0 | slhdsa_thash_prf(config, tmp_sk, pub_seed, sk_seed, sk_addr); |
53 | 0 | slhdsa_set_chain_addr(config, addr, chain_index); |
54 | 0 | chain(config, out, tmp_sk, 0, value, pub_seed, addr); |
55 | 0 | } |
56 | | |
57 | | // Implements Algorithm 6: wots_pkGen function, page 18 |
58 | | void bssl::slhdsa_wots_pk_gen(const slh_dsa_config *config, uint8_t *pk, |
59 | | const uint8_t *sk_seed, const uint8_t *pub_seed, |
60 | 0 | uint8_t addr[32]) { |
61 | 0 | uint8_t wots_pk_addr[32], sk_addr[32]; |
62 | 0 | OPENSSL_memcpy(wots_pk_addr, addr, sizeof(wots_pk_addr)); |
63 | 0 | OPENSSL_memcpy(sk_addr, addr, sizeof(sk_addr)); |
64 | 0 | slhdsa_set_type(config, sk_addr, SLHDSA_ADDR_TYPE_WOTSPRF); |
65 | 0 | slhdsa_copy_keypair_addr(config, sk_addr, addr); |
66 | |
|
67 | 0 | uint8_t tmp[SLHDSA_MAX_WOTS_BYTES]; |
68 | 0 | const uint32_t n = config->n; |
69 | 0 | const uint32_t wots_len = slhdsa_wots_len(config); |
70 | 0 | const uint32_t max_chain = config->wots_w - 1; |
71 | 0 | for (uint32_t i = 0; i < wots_len; ++i) { |
72 | 0 | slhdsa_wots_do_chain(config, tmp + i * n, sk_addr, addr, max_chain, sk_seed, |
73 | 0 | pub_seed, i); |
74 | 0 | } |
75 | | |
76 | | // Compress pk |
77 | 0 | slhdsa_set_type(config, wots_pk_addr, SLHDSA_ADDR_TYPE_WOTSPK); |
78 | 0 | slhdsa_copy_keypair_addr(config, wots_pk_addr, addr); |
79 | 0 | slhdsa_thash_tl(config, pk, tmp, pub_seed, wots_pk_addr); |
80 | 0 | } |
81 | | |
82 | | // Implements Algorithm 7: wots_sign function, page 20 |
83 | | void bssl::slhdsa_wots_sign(const slh_dsa_config *config, uint8_t *sig, |
84 | | const uint8_t *msg, const uint8_t *sk_seed, |
85 | 0 | const uint8_t *pub_seed, uint8_t addr[32]) { |
86 | 0 | BSSL_CHECK(config->wots_w == 16); |
87 | 0 | const size_t n = config->n; |
88 | 0 | const uint32_t max_chain = config->wots_w - 1; |
89 | |
|
90 | 0 | uint16_t csum = 0; |
91 | 0 | for (size_t i = 0; i < n; ++i) { |
92 | 0 | csum += max_chain - (msg[i] >> 4); |
93 | 0 | csum += max_chain - (msg[i] & 15); |
94 | 0 | } |
95 | | |
96 | | // Compute chains |
97 | 0 | uint8_t sk_addr[32]; |
98 | 0 | OPENSSL_memcpy(sk_addr, addr, sizeof(sk_addr)); |
99 | 0 | slhdsa_set_type(config, sk_addr, SLHDSA_ADDR_TYPE_WOTSPRF); |
100 | 0 | slhdsa_copy_keypair_addr(config, sk_addr, addr); |
101 | |
|
102 | 0 | uint32_t chain_index = 0; |
103 | 0 | for (size_t i = 0; i < n; ++i) { |
104 | 0 | slhdsa_wots_do_chain(config, sig, sk_addr, addr, msg[i] >> 4, sk_seed, |
105 | 0 | pub_seed, chain_index++); |
106 | 0 | sig += n; |
107 | |
|
108 | 0 | slhdsa_wots_do_chain(config, sig, sk_addr, addr, msg[i] & 15, sk_seed, |
109 | 0 | pub_seed, chain_index++); |
110 | 0 | sig += n; |
111 | 0 | } |
112 | | |
113 | | // Include the WOTS checksum values (len2 = 3 for the parameter sets we |
114 | | // support). |
115 | 0 | slhdsa_wots_do_chain(config, sig, sk_addr, addr, (csum >> 8) & 15, sk_seed, |
116 | 0 | pub_seed, chain_index++); |
117 | 0 | sig += n; |
118 | 0 | slhdsa_wots_do_chain(config, sig, sk_addr, addr, (csum >> 4) & 15, sk_seed, |
119 | 0 | pub_seed, chain_index++); |
120 | 0 | sig += n; |
121 | 0 | slhdsa_wots_do_chain(config, sig, sk_addr, addr, csum & 15, sk_seed, pub_seed, |
122 | 0 | chain_index++); |
123 | 0 | } |
124 | | |
125 | | static void slhdsa_wots_pk_from_sig_do_chain(const slh_dsa_config *config, |
126 | | uint8_t *out, uint8_t addr[32], |
127 | | const uint8_t *in, uint8_t value, |
128 | | const uint8_t *pub_seed, |
129 | 0 | uint32_t chain_index) { |
130 | 0 | slhdsa_set_chain_addr(config, addr, chain_index); |
131 | 0 | chain(config, out + chain_index * config->n, in + chain_index * config->n, |
132 | 0 | value, (config->wots_w - 1) - value, pub_seed, addr); |
133 | 0 | } |
134 | | |
135 | | // Implements Algorithm 8: wots_pkFromSig function, page 21 |
136 | | void bssl::slhdsa_wots_pk_from_sig(const slh_dsa_config *config, uint8_t *pk, |
137 | | const uint8_t *sig, const uint8_t *msg, |
138 | 0 | const uint8_t *pub_seed, uint8_t addr[32]) { |
139 | 0 | BSSL_CHECK(config->wots_w == 16); |
140 | 0 | const size_t n = config->n; |
141 | 0 | const uint32_t max_chain = config->wots_w - 1; |
142 | |
|
143 | 0 | uint16_t csum = 0; |
144 | 0 | for (size_t i = 0; i < n; ++i) { |
145 | 0 | csum += max_chain - (msg[i] >> 4); |
146 | 0 | csum += max_chain - (msg[i] & 15); |
147 | 0 | } |
148 | |
|
149 | 0 | uint8_t tmp[SLHDSA_MAX_WOTS_BYTES]; |
150 | 0 | uint8_t wots_pk_addr[32]; |
151 | 0 | OPENSSL_memcpy(wots_pk_addr, addr, sizeof(wots_pk_addr)); |
152 | |
|
153 | 0 | uint32_t chain_index = 0; |
154 | 0 | for (size_t i = 0; i < n; ++i) { |
155 | 0 | slhdsa_wots_pk_from_sig_do_chain(config, tmp, addr, sig, msg[i] >> 4, |
156 | 0 | pub_seed, chain_index++); |
157 | 0 | slhdsa_wots_pk_from_sig_do_chain(config, tmp, addr, sig, msg[i] & 15, |
158 | 0 | pub_seed, chain_index++); |
159 | 0 | } |
160 | |
|
161 | 0 | slhdsa_wots_pk_from_sig_do_chain(config, tmp, addr, sig, csum >> 8, pub_seed, |
162 | 0 | chain_index++); |
163 | 0 | slhdsa_wots_pk_from_sig_do_chain(config, tmp, addr, sig, (csum >> 4) & 15, |
164 | 0 | pub_seed, chain_index++); |
165 | 0 | slhdsa_wots_pk_from_sig_do_chain(config, tmp, addr, sig, csum & 15, pub_seed, |
166 | 0 | chain_index++); |
167 | | |
168 | | // Compress pk |
169 | 0 | slhdsa_set_type(config, wots_pk_addr, SLHDSA_ADDR_TYPE_WOTSPK); |
170 | 0 | slhdsa_copy_keypair_addr(config, wots_pk_addr, addr); |
171 | 0 | slhdsa_thash_tl(config, pk, tmp, pub_seed, wots_pk_addr); |
172 | 0 | } |