Software APIs
boot_data.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 #ifndef OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_BOOT_DATA_H_
6 #define OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_BOOT_DATA_H_
7 
9 #include "sw/device/silicon_creator/lib/drivers/hmac.h"
10 #include "sw/device/silicon_creator/lib/drivers/lifecycle.h"
11 #include "sw/device/silicon_creator/lib/error.h"
12 #include "sw/device/silicon_creator/lib/nonce.h"
13 
14 #ifdef __cplusplus
15 extern "C" {
16 #endif // __cplusplus
17 
18 /**
19  * Boot data stored in the flash info partition.
20  */
21 typedef struct boot_data {
22  /**
23  * SHA-256 digest of boot data.
24  *
25  * The region covered by this digest starts immediately after this field and
26  * ends at the end of the entry.
27  */
29  /**
30  * Invalidation field.
31  *
32  * This field is used to invalidate the previous entry after writing a new
33  * entry. When writing a new entry, the value of this field is assumed to be
34  * `kBootDataValidEntry`, which matches the value of unwritten flash words,
35  * but it is skipped so that the entry can be invalidated at a later time. An
36  * entry can be invalidated by writing `kBootDataInvalidEntry` to this field
37  * resulting in a digest mismatch.
38  */
39  uint64_t is_valid;
40  /**
41  * Boot data identifier.
42  */
43  uint32_t identifier;
44  /**
45  * Boot data format version.
46  *
47  * This field must be set to the latest version for new entries but is not
48  * enforced during reads for forward compatibility in ROM and backward
49  * compatibility in ROM_EXT.
50  */
51  uint32_t version;
52  /**
53  * Counter.
54  *
55  * This is a monotonically increasing counter that is used to determine the
56  * newest entry across both boot data pages.
57  */
58  uint32_t counter;
59  /**
60  * Minimum required security version for ROM_EXT.
61  */
63  /**
64  * Minimum required security version for BL0.
65  */
67  /**
68  * The BL0 slot that is prioritized during boot.
69  */
70  uint32_t primary_bl0_slot;
71  /**
72  * Next owner key (ECDSA). Only relevant in the UNLOCKED_ENDORSED ownership
73  * state.
74  */
75  uint32_t next_owner[8];
76  /**
77  * Challenge/response nonce for signed boot_svc commands.
78  */
80  /**
81  * Ownership state. One of LOCKED_OWNER, LOCKED_UPDATE, UNLOCKED_ANY,
82  * UNLOCKED_ENDORSED, LOCKED_NONE.
83  */
84  uint32_t ownership_state;
85  /**
86  * Number of ownership transfers this chip has had.
87  */
89 
90  /**
91  * Padding for future enhancements and to make the size of `boot_data_t` a
92  * power of two.
93  */
94  uint32_t padding[4];
95 } boot_data_t;
96 
99 OT_ASSERT_MEMBER_OFFSET(boot_data_t, identifier, 40);
102 OT_ASSERT_MEMBER_OFFSET(boot_data_t, min_security_version_rom_ext, 52);
103 OT_ASSERT_MEMBER_OFFSET(boot_data_t, min_security_version_bl0, 56);
104 OT_ASSERT_MEMBER_OFFSET(boot_data_t, primary_bl0_slot, 60);
105 OT_ASSERT_MEMBER_OFFSET(boot_data_t, next_owner, 64);
107 OT_ASSERT_MEMBER_OFFSET(boot_data_t, ownership_state, 104);
108 OT_ASSERT_MEMBER_OFFSET(boot_data_t, ownership_transfers, 108);
109 OT_ASSERT_MEMBER_OFFSET(boot_data_t, padding, 112);
111 
112 enum {
113  /**
114  * Boot data identifier value (ASCII "BODA").
115  */
116  kBootDataIdentifier = 0x41444f42,
117  /**
118  * Boot data version 1 value.
119  */
120  kBootDataVersion1 = 0xd4ce468e,
121  /**
122  * Boot data version 2 value.
123  */
124  kBootDataVersion2 = 0xad51e729,
125  /**
126  * Value of the `is_valid` field for valid entries.
127  */
128  kBootDataValidEntry = UINT64_MAX,
129  /**
130  * Value of the `is_valid` field for invalidated entries.
131  *
132  * This value is used to invalidate the previous entry after writing a new
133  * entry.
134  */
135  kBootDataInvalidEntry = 0,
136  /**
137  * Value of the counter field of the default boot data entry.
138  *
139  * This starts from 5 to have a slightly less trivial value in case we need to
140  * distinguish the default entry.
141  */
142  kBootDataDefaultCounterVal = 5,
143  /**
144  * Size of `boot_data_t` in words.
145  */
146  kBootDataNumWords = sizeof(boot_data_t) / sizeof(uint32_t),
147  /**
148  * Number of boot data entries per info page.
149  *
150  * Boot data pages are used as append-only logs where new data is written to
151  * the first empty entry of the active page. If all entries of the currently
152  * active page are used when `boot_data_write()` is called, the other page
153  * will be erased and new data will be written to its first entry, making it
154  * the new active page.
155  */
156  kBootDataEntriesPerPage = 16,
157 };
158 static_assert(kBootDataInvalidEntry != kBootDataValidEntry,
159  "Invalidation values cannot be equal.");
160 
161 /**
162  * Constants referring to EFLASH slots A and B.
163  */
164 typedef enum boot_slot {
165  /** Slot A: `AA__`. */
166  kBootSlotA = 0x5f5f4141,
167  /** Slot B: `__BB`. */
168  kBootSlotB = 0x42425f5f,
169  /** Slot Unspecified: `UUUU`. */
170  kBootSlotUnspecified = 0x55555555,
171 } boot_slot_t;
172 
173 /**
174  * Reads the boot data stored in the flash info partition.
175  *
176  * The flash controller must be initialized with proper permissions for the
177  * first and second info pages of the second flash bank before calling this
178  * function.
179  *
180  * If there is no valid boot data in the flash info partition, this function
181  * returns the default boot data in non-production life cycle states
182  * (TEST_UNLOCKED, DEV, RMA).
183  *
184  * @param lc_state Life cycle state of the device.
185  * @param boot_data[out] Boot data.
186  * @return The result of the operation.
187  */
189 rom_error_t boot_data_read(lifecycle_state_t lc_state, boot_data_t *boot_data);
190 
191 /**
192  * Writes the given boot data to the flash info partition.
193  *
194  * This function updates the `identifier`, `counter`, and `digest` fields of the
195  * given `boot_data` before writing it to the flash.
196  *
197  * @param boot_data[out] Boot data.
198  * @return The result of the operation.
199  */
201 rom_error_t boot_data_write(const boot_data_t *boot_data);
202 
203 /**
204  * Checks whether a boot data entry is valid.
205  *
206  * This function checks the `identifier` and `digest` fields of the given
207  * `boot_data` entry.
208  *
209  * @param boot_data A buffer that holds a boot data entry.
210  * @return Whether the digest of the entry is valid.
211  */
213 rom_error_t boot_data_check(const boot_data_t *boot_data);
214 
215 #ifdef __cplusplus
216 } // extern "C"
217 #endif // __cplusplus
218 
219 #endif // OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_BOOT_DATA_H_