Software APIs
params.h
1// Copyright lowRISC contributors (OpenTitan project).
2// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3// SPDX-License-Identifier: Apache-2.0
4//
5// Derived from code in the SPHINCS+ reference implementation (CC0 license):
6// https://github.com/sphincs/sphincsplus/blob/ed15dd78658f63288c7492c00260d86154b84637/ref/params/params-sphincs-shake-128s.h
7// https://github.com/sphincs/sphincsplus/blob/ed15dd78658f63288c7492c00260d86154b84637/ref/shake_offsets.h
8#ifndef OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_SIGVERIFY_SPHINCSPLUS_PARAMS_H_
9#define OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_SIGVERIFY_SPHINCSPLUS_PARAMS_H_
10
11/**
12 * This file represents the SPHINCS+ parameter set shake-128s, meaning:
13 * - The hash function is SHA2-256
14 * - >= 128 bits of security for up to 2^64 signatures
15 * - The parameter set is optimized to be small "s" rather than fast "f"
16 * - The "fast" variant is faster for signing but actually slower for
17 * verification, so "s" is a better fit given we don't care about signing
18 * speed.
19 *
20 * For more details on parameterization, see the SPHINCS+ paper:
21 * https://sphincs.org/data/sphincs+-paper.pdf
22 */
23
24enum {
25 /**
26 * Hash output length in bytes.
27 */
28 kSpxN = 16,
29 /**
30 * Height of the hypertree.
31 */
32 kSpxFullHeight = 63,
33 /**
34 * Number of subtree layers.
35 */
36 kSpxD = 7,
37 /**
38 * FORS tree dimension (height).
39 */
40 kSpxForsHeight = 12,
41 /**
42 * FORS tree dimension (number of trees).
43 */
44 kSpxForsTrees = 14,
45 /**
46 * Winternitz parameter.
47 */
48 kSpxWotsW = 16,
49 /**
50 * Whether SHA-512 is required (boolean).
51 */
52 kSpxSha512 = 0,
53 /**
54 * Number of bytes in a hypertree address (for clarity).
55 */
56 kSpxAddrBytes = 32,
57 /**
58 * Bit-length of the Winternitz parameter.
59 */
60 kSpxWotsLogW = 4,
61 /**
62 * Parameter `len1` for WOTS signatures.
63 *
64 * See section 3.1 of the SPHINCS+ NIST submission:
65 * https://sphincs.org/data/sphincs+-r3.1-specification.pdf
66 */
67 kSpxWotsLen1 = (8 * kSpxN) / kSpxWotsLogW,
68 /**
69 * Parameter `len2` for WOTS signatures.
70 *
71 * This value is precomputed and equal to:
72 * floor(log(len1 * (w - 1)) / log(w)) + 1
73 *
74 * During the WOTS computation, the maximum checksum value is `len1 * (w -
75 * 1)`. The log() functions here essentially apply the change-of-base rule;
76 * what we are actually computing is floor(log_w(len1 * (w - 1))) + 1, which
77 * expresses the number of base-w integers required to encode the checksum.
78 *
79 * Some precomputed values based on w and n:
80 * +------+----------------+----------+
81 * | w | n | len2 |
82 * +------+----------------+----------+
83 * | 256 | 0 < n <= 1 | 1 |
84 * | 256 | 1 < n <= 256 | 2 |
85 * | 16 | 0 < n <= 8 | 2 |
86 * | 16 | 8 < n <= 136 | 3 |
87 * | 16 | 136 < n <= 256 | 4 |
88 * +------+----------------+----------+
89 *
90 * See section 3.1 of the SPHINCS+ NIST submission:
91 * https://sphincs.org/data/sphincs+-r3.1-specification.pdf
92 */
93 kSpxWotsLen2 = 3,
94 /**
95 * Number of chains to compute for a WOTS signature.
96 */
97 kSpxWotsLen = kSpxWotsLen1 + kSpxWotsLen2,
98 /**
99 * WOTS signature length in bytes.
100 *
101 * The signature is composed of `kSpxWotsLen` blocks of `kSpxN` bytes each.
102 */
103 kSpxWotsBytes = kSpxWotsLen * kSpxN,
104 /**
105 * WOTS public key length in bytes.
106 */
107 kSpxWotsPkBytes = kSpxWotsBytes,
108 /**
109 * Subtree size.
110 */
111 kSpxTreeHeight = kSpxFullHeight / kSpxD,
112 /**
113 * FORS message length.
114 */
115 kSpxForsMsgBytes = ((kSpxForsHeight * kSpxForsTrees) + 7) / 8,
116 /**
117 * FORS signature length.
118 */
119 kSpxForsBytes = (kSpxForsHeight + 1) * kSpxForsTrees * kSpxN,
120 /**
121 * FORS public key length.
122 */
123 kSpxForsPkBytes = kSpxN,
124 /**
125 * SPHINCS+ signature.
126 */
127 kSpxBytes =
128 kSpxN + kSpxForsBytes + kSpxD * kSpxWotsBytes + kSpxFullHeight * kSpxN,
129 /**
130 * SPHINCS+ public key length.
131 */
132 kSpxPkBytes = 2 * kSpxN,
133 /**
134 * SPHINCS+ secret key length.
135 */
136 kSpxSkBytes = 2 * kSpxN + kSpxPkBytes,
137 /**
138 * Hash output length (n) in words.
139 */
140 kSpxNWords = kSpxN / sizeof(uint32_t),
141 /**
142 * FORS signature size in words.
143 */
144 kSpxForsWords = kSpxForsBytes / sizeof(uint32_t),
145 /**
146 * WOTS signature size in words.
147 */
148 kSpxWotsWords = kSpxWotsBytes / sizeof(uint32_t),
149 /**
150 * WOTS public key size in words.
151 */
152 kSpxWotsPkWords = kSpxWotsPkBytes / sizeof(uint32_t),
153 /**
154 * SPHINCS+ public key length in words.
155 */
156 kSpxPkWords = kSpxPkBytes / sizeof(uint32_t),
157};
158
159/**
160 * These constants are byte offsets within the hypertree address structure.
161 *
162 * It is customized for the hypertree address format that is used when SHA2 is
163 * the underlying SPHINCS+ hash function. These values should not change if
164 * parameters other than the hash function are altered.
165 */
166enum {
167 /**
168 * Byte used to specify the Merkle tree layer.
169 */
170 kSpxOffsetLayer = 0,
171 /**
172 * Starting byte of the tree field (8 bytes).
173 */
174 kSpxOffsetTree = 1,
175 /**
176 * Byte used to specify the hash type (reason).
177 */
178 kSpxOffsetType = 9,
179 /**
180 * The start of the 4 byte field used to specify the key pair address.
181 */
182 kSpxOffsetKpAddr = 10,
183 /**
184 * Byte for the chain address (i.e. which Winternitz chain).
185 */
186 kSpxOffsetChainAddr = 17,
187 /**
188 * Byte for the hash address (i.e. where in the Winternitz chain).
189 */
190 kSpxOffsetHashAddr = 21,
191 /**
192 * Byte for the height of this node in the FORS or Merkle tree.
193 */
194 kSpxOffsetTreeHeight = 17,
195 /**
196 * Starting byte for the tree index field (4 bytes) in the FORS or Merkle
197 * tree.
198 */
199 kSpxOffsetTreeIndex = 18,
200};
201
202#endif // OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_SIGVERIFY_SPHINCSPLUS_PARAMS_H_