Software APIs
address.c
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 
8 #include "sw/device/silicon_creator/lib/sigverify/sphincsplus/address.h"
9 
11 #include "sw/device/silicon_creator/lib/sigverify/sphincsplus/params.h"
12 
13 static_assert(kSpxTreeHeight * (kSpxD - 1) <= 64,
14  "Subtree addressing is currently limited to at most 2^64 trees.");
15 
16 /**
17  * Sets a single byte within the internal buffer of an address.
18  *
19  * Use with the `kSpxOffset...` constant offsets.
20  *
21  * @param addr Adress in which to set a byte.
22  * @param offset Byte-offset within the internal buffer.
23  * @param value New value of byte.
24  */
25 static void spx_addr_set_byte(spx_addr_t *addr, size_t offset,
26  unsigned char value) {
27  unsigned char *buf = (unsigned char *)addr->addr;
28  buf[offset] = value;
29 }
30 
31 void spx_addr_layer_set(spx_addr_t *addr, uint8_t layer) {
32  spx_addr_set_byte(addr, kSpxOffsetLayer, layer);
33 }
34 
35 void spx_addr_tree_set(spx_addr_t *addr, uint64_t tree) {
36  unsigned char *buf = (unsigned char *)addr->addr;
37  // Reverse bytes in the integer so it will appear in big-endian form.
38  uint64_t tree_be = __builtin_bswap64(tree);
39  memcpy(buf + kSpxOffsetTree, &tree_be, sizeof(uint64_t));
40 }
41 
42 void spx_addr_type_set(spx_addr_t *addr, spx_addr_type_t type) {
43  spx_addr_set_byte(addr, kSpxOffsetType, (unsigned char)type);
44 }
45 
46 void spx_addr_subtree_copy(spx_addr_t *out, const spx_addr_t *in) {
47  unsigned char *in_buf = (unsigned char *)in->addr;
48  unsigned char *out_buf = (unsigned char *)out->addr;
49 
50  // Copy the entire 32-bit field representing the layer, even though only one
51  // byte is used.
52  size_t layer_field_offset =
53  (kSpxOffsetLayer / sizeof(uint32_t)) * sizeof(uint32_t);
54  memcpy(out_buf + layer_field_offset, in_buf + layer_field_offset,
55  sizeof(uint32_t));
56 
57  // Copy the entire 64-bit field representing the tree.
58  memcpy(out_buf + kSpxOffsetTree, in_buf + kSpxOffsetTree, sizeof(uint64_t));
59 }
60 
61 void spx_addr_keypair_set(spx_addr_t *addr, uint32_t keypair) {
62  unsigned char *buf = (unsigned char *)addr->addr;
63  // Reverse bytes in the integer so it will be in big-endian form.
64  uint32_t keypair_be = __builtin_bswap32(keypair);
65  memcpy(buf + kSpxOffsetKpAddr, &keypair_be, sizeof(uint32_t));
66 }
67 
68 void spx_addr_keypair_copy(spx_addr_t *out, const spx_addr_t *in) {
69  spx_addr_subtree_copy(out, in);
70  unsigned char *in_buf = (unsigned char *)in->addr;
71  unsigned char *out_buf = (unsigned char *)out->addr;
72  memcpy(out_buf + kSpxOffsetKpAddr, in_buf + kSpxOffsetKpAddr,
73  sizeof(uint32_t));
74 }
75 
76 void spx_addr_chain_set(spx_addr_t *addr, uint8_t chain) {
77  spx_addr_set_byte(addr, kSpxOffsetChainAddr, chain);
78 }
79 
80 void spx_addr_hash_set(spx_addr_t *addr, uint8_t hash) {
81  spx_addr_set_byte(addr, kSpxOffsetHashAddr, hash);
82 }
83 
84 void spx_addr_tree_height_set(spx_addr_t *addr, uint8_t tree_height) {
85  spx_addr_set_byte(addr, kSpxOffsetTreeHeight, tree_height);
86 }
87 
88 void spx_addr_tree_index_set(spx_addr_t *addr, uint32_t tree_index) {
89  unsigned char *buf = (unsigned char *)addr->addr;
90  // Reverse bytes in the integer so it will appear in big-endian form.
91  uint32_t index_be = __builtin_bswap32(tree_index);
92  memcpy(buf + kSpxOffsetTreeIndex, &index_be, sizeof(uint32_t));
93 }