Software APIs
address.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/address.h
7 #ifndef OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_SIGVERIFY_SPHINCSPLUS_ADDRESS_H_
8 #define OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_SIGVERIFY_SPHINCSPLUS_ADDRESS_H_
9 
10 /**
11  * This file provides an interface for working with SPHINCS+ hypertree
12  * addresses. For details, see section 2.7.3 of the round 3.1 SPHINCS+ NIST
13  * competition submission:
14  * https://sphincs.org/data/sphincs+-r3.1-specification.pdf
15  *
16  * Quick overview based on that document:
17  * - All addresses are 256 bits (= 8 32-bit words).
18  * - Numeric fields are stored in big-endian form.
19  * - Addresses have five different formats depending on their use case.
20  * - Three fields are shared across all formats (layer, tree, and type).
21  * - The type field indicates which format the address uses.
22  * - All fields are aligned to 32-bit word boundaries within the address
23  * (meaning some are oversized for the data they contain).
24  *
25  * Common format of addresses:
26  * +---------+---------------+--------------+
27  * | size | field | address bits |
28  * +=========+===============+==============+
29  * | 8 bits | layer address | 0..31 |
30  * +---------+---------------+--------------+
31  * | 64 bits | tree address | 32..127 |
32  * +---------+---------------+--------------+
33  * | 8 bits | type | 128..159 |
34  * +---------+---------------+--------------+
35  * | 96 bits | flexible | 160..255 |
36  * | | (see below) | |
37  * +---------+---------------+--------------+
38  *
39  * WOTS+ hash address flexible fields:
40  * +---------+------------------+----------+
41  * | 32 bits | key pair address | 160..191 |
42  * +---------+------------------+----------+
43  * | 8 bits | chain address | 192..223 |
44  * +---------+------------------+----------+
45  * | 8 bits | hash address | 224..255 |
46  * +---------+------------------+----------+
47  *
48  * WOTS+ public key compression flexible fields:
49  * +---------+-------------------+----------+
50  * | 32 bits | key pair address | 160..191 |
51  * +---------+-------------------+----------+
52  * | 64 bits | unused (always 0) | 192..255 |
53  * +---------+-------------------+----------+
54  *
55  * Main Merkle tree flexible fields:
56  * +---------+-------------------+----------+
57  * | 32 bits | unused (always 0) | 160..191 |
58  * +---------+-------------------+----------+
59  * | 8 bits | tree height | 192..223 |
60  * +---------+-------------------+----------+
61  * | 32 bits | tree index | 224..255 |
62  * +---------+-------------------+----------+
63  *
64  * FORS hash address flexible fields:
65  * +---------+------------------+----------+
66  * | 32 bits | key pair address | 160..191 |
67  * +---------+------------------+----------+
68  * | 8 bits | tree height | 192..223 |
69  * +---------+------------------+----------+
70  * | 32 bits | tree index | 224..255 |
71  * +---------+------------------+----------+
72  *
73  * FORS tree root compression flexible fields:
74  * +---------+-------------------+----------+
75  * | 32 bits | key pair address | 160..191 |
76  * +---------+-------------------+----------+
77  * | 64 bits | unused (always 0) | 192..255 |
78  * +---------+-------------------+----------+
79  */
80 
81 #include <stdint.h>
82 
83 #include "sw/device/silicon_creator/lib/sigverify/sphincsplus/params.h"
84 
85 #ifdef __cplusplus
86 extern "C" {
87 #endif
88 
89 /**
90  * Hash types for `spx_addr_type_set`.
91  *
92  * Note: The values here are more like compile-time constants than true enums;
93  * changing the values will cause test failures since they are hashed directly
94  * as part of the address.
95  */
96 typedef enum spx_addr_type {
97  kSpxAddrTypeWots = 0,
98  kSpxAddrTypeWotsPk = 1,
99  kSpxAddrTypeHashTree = 2,
100  kSpxAddrTypeForsTree = 3,
101  kSpxAddrTypeForsPk = 4,
102  kSpxAddrTypeWotsPrf = 5,
103  kSpxAddrTypeForsPrf = 6,
104 } spx_addr_type_t;
105 
106 /**
107  * Hypertree address.
108  */
109 typedef struct spx_addr {
110  uint32_t addr[8];
111 } spx_addr_t;
112 
113 /**
114  * Set the layer field in a hypertree address.
115  *
116  * Appears in reference code as `set_layer_addr`.
117  *
118  * @param addr Hypertree address.
119  * @param layer Layer value to set in the address.
120  */
121 void spx_addr_layer_set(spx_addr_t *addr, uint8_t layer);
122 
123 /**
124  * Set the tree field for a hypertree address.
125  *
126  * The `tree` value will be converted to big-endian form before being stored in
127  * the address.
128  *
129  * Appears in reference code as `set_tree_addr`.
130  *
131  * @param addr Hypertree address.
132  * @param tree Tree value to set in the address.
133  */
134 void spx_addr_tree_set(spx_addr_t *addr, uint64_t tree);
135 
136 /**
137  * Set the type field for a hypertree address.
138  *
139  * Appears in reference code as `set_type_addr`.
140  *
141  * @param addr Hypertree address.
142  * @param type Type value to set in the address.
143  */
144 void spx_addr_type_set(spx_addr_t *addr, spx_addr_type_t type);
145 
146 /**
147  * Copies the layer and tree parts of one address into the other.
148  *
149  * This is used to do multiple types of hashes within the same Merkle tree.
150  *
151  * Appears in reference code as `copy_subtree_addr`.
152  *
153  * @param out Address to copy to.
154  * @param in Address to copy from.
155  */
156 void spx_addr_subtree_copy(spx_addr_t *out, const spx_addr_t *in);
157 
158 /**
159  * Set the keypair field of a WOTS or FORS address.
160  *
161  * Appears in reference code as `set_keypair_addr`.
162  *
163  * @param addr Hypertree address.
164  * @param keypair Keypair value to set in the address.
165  */
166 void spx_addr_keypair_set(spx_addr_t *addr, uint32_t keypair);
167 
168 /**
169  * Set the chain field of a WOTS or FORS address.
170  *
171  * Appears in reference code as `set_chain_addr`.
172  *
173  * @param addr Hypertree address.
174  * @param chain Chain value to set in the address.
175  */
176 void spx_addr_chain_set(spx_addr_t *addr, uint8_t chain);
177 
178 /**
179  * Set the hash field of a WOTS or FORS address.
180  *
181  * Appears in reference code as `set_hash_addr`.
182  *
183  * @param addr Hypertree address.
184  * @param hash Hash value to set in the address.
185  */
186 void spx_addr_hash_set(spx_addr_t *addr, uint8_t hash);
187 
188 /**
189  * Copies the layer, tree, and keypair parts of a WOTS or FORS address.
190  *
191  * This is used to do multiple things with the same OTS keypair.
192  *
193  * Appears in reference code as `copy_keypair_addr`.
194  *
195  * @param out Address to copy to.
196  * @param in Address to copy from.
197  */
198 void spx_addr_keypair_copy(spx_addr_t *out, const spx_addr_t *in);
199 
200 /**
201  * Set the tree height field of a hash tree address.
202  *
203  * Appears in reference code as `set_tree_height`.
204  *
205  * @param addr Hypertree address.
206  * @param tree_height Tree height value to set in the address.
207  */
208 void spx_addr_tree_height_set(spx_addr_t *addr, uint8_t tree_height);
209 
210 /**
211  * Set the tree index field of a hash tree address.
212  *
213  * The `tree_index` value will be converted to big-endian form before being
214  * stored in the address.
215  *
216  * Appears in reference code as `set_tree_index`.
217  *
218  * @param addr Hypertree address.
219  * @param tree_index Tree index value to set in the address.
220  */
221 void spx_addr_tree_index_set(spx_addr_t *addr, uint32_t tree_index);
222 
223 #ifdef __cplusplus
224 }
225 #endif
226 
227 #endif // OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_SIGVERIFY_SPHINCSPLUS_ADDRESS_H_