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 
24 enum {
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  */
166 enum {
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_