Software APIs
manifest.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_MANIFEST_H_
6 #define OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_MANIFEST_H_
7 
8 #include <stddef.h>
9 
12 #include "sw/device/silicon_creator/lib/drivers/lifecycle.h"
13 #include "sw/device/silicon_creator/lib/epmp_state.h"
14 #include "sw/device/silicon_creator/lib/error.h"
15 #include "sw/device/silicon_creator/lib/keymgr_binding_value.h"
16 #include "sw/device/silicon_creator/lib/sigverify/ecdsa_p256_key.h"
17 #include "sw/device/silicon_creator/lib/sigverify/rsa_key.h"
18 #include "sw/device/silicon_creator/lib/sigverify/spx_key.h"
19 
20 #ifdef __cplusplus
21 extern "C" {
22 #endif // __cplusplus
23 
24 /**
25  * Usage constraints.
26  *
27  * This struct is used to constrain a boot stage image to a set of devices based
28  * on their device IDs, creator and/or owner manufacturing states, and life
29  * cycle states. Bits of `selector_bits` determine which fields (or individual
30  * words of a field as in the case of `device_id`) must be read from the
31  * hardware during verification. Unselected fields must be set to
32  * `MANIFEST_USAGE_CONSTRAINT_UNSELECTED_WORD_VAL` to be able to generate a
33  * consistent value during verification.
34  */
36  /**
37  * Usage constraint selector bits.
38  *
39  * The bits of this field are mapped to the remaining fields as follows:
40  * - Bits 0-7: `device_id[0-7]`
41  * - Bit 8 : `manuf_state_creator`
42  * - Bit 9 : `manuf_state_owner`
43  * - Bit 10 : `life_cycle_state`
44  */
45  uint32_t selector_bits;
46  /**
47  * Device identifier value which is compared against the `DEVICE_ID` value
48  * stored in the `HW_CFG0` partition in OTP.
49  *
50  * Mapped to bits 0-7 of `selector_bits`.
51  */
53  /**
54  * Device Silicon Creator manufacting status compared against the
55  * `CREATOR_SW_MANUF_STATUS` value stored in the `CREATOR_SW_CFG` partition in
56  * OTP.
57  *
58  * Mapped to bit 8 of `selector_bits`.
59  */
61  /**
62  * Device Silicon Owner manufacturing status compared against the
63  * `OWNER_SW_MANUF_STATUS` value stored in the `OWNER_SW_CFG` partition in
64  * OTP.
65  *
66  * Mapped to bit 9 of `selector_bits`.
67  */
69  /**
70  * Device life cycle status compared against the status reported by the life
71  * cycle controller.
72  *
73  * Mapped to bit 10 of `selector_bits`.
74  */
75  uint32_t life_cycle_state;
77 
78 /**
79  * Value to use for unselected usage constraint words.
80  */
81 #define MANIFEST_USAGE_CONSTRAINT_UNSELECTED_WORD_VAL 0xA5A5A5A5
82 
83 /**
84  * `selector_bits` bit indices for usage constraints fields.
85  */
86 enum {
87  /**
88  * Bits mapped to the `device_id` field.
89  */
90  kManifestSelectorBitDeviceIdFirst = 0,
91  kManifestSelectorBitDeviceIdLast = 7,
92 
93  /**
94  * Bit mapped to the `manuf_state_creator` field.
95  */
96  kManifestSelectorBitManufStateCreator = 8,
97  /**
98  * Bit mapped to the `manuf_state_owner` field.
99  */
100  kManifestSelectorBitManufStateOwner = 9,
101  /**
102  * Bit mapped to the `life_cycle_state` field.
103  */
104  kManifestSelectorBitLifeCycleState = 10,
105 };
106 
107 /**
108  * Manifest timestamp.
109  */
110 typedef struct manifest_timestamp {
111  /**
112  * Least significant word of the timestamp.
113  */
114  uint32_t timestamp_low;
115  /**
116  * Most significant word of the timestamp.
117  */
118  uint32_t timestamp_high;
120 
121 /**
122  * Manifest extensions table entry.
123  *
124  * An extension with index `i` exists if the `identifier` of the `i`th entry in
125  * the extension table matches the `identifier` of the extension and its
126  * `offset` is greater than zero.
127  */
128 typedef struct manifest_ext_table_entry {
129  /**
130  * Extension identifier.
131  *
132  * Must match the `identifier` value in the extension's header.
133  */
134  uint32_t identifier;
135  /**
136  * Offset of this extension relative to the start of the manifest.
137  */
138  uint32_t offset;
140 
141 /**
142  * Manifest extensions table.
143  */
144 typedef struct manifest_ext_table {
147 
148 /**
149  * Manifest version.
150  */
151 typedef struct manifest_version {
152  /**
153  * Minor manifest format version.
154  *
155  * ROM doesn't check this field. Thus, this field can be used to update the
156  * manifest format without breaking the forward compatibility of ROM.
157  */
158  uint16_t minor;
159  /**
160  * Major manifest format version.
161  *
162  * This field can be used to maintain or break forward compatibility in ROM
163  * while preserving backward compatibility in ROM_EXT. ROM requires the major
164  * version to be `kManifestFormatVersionMajor1`.
165  */
166  uint16_t major;
168 
169 /**
170  * Manifest versions.
171  */
172 enum {
173  kManifestVersionMajor1 = CHIP_MANIFEST_VERSION_MAJOR_1,
174  kManifestVersionMajor2 = CHIP_MANIFEST_VERSION_MAJOR_2,
175  kManifestVersionMinor1 = CHIP_MANIFEST_VERSION_MINOR_1,
176 };
177 
178 /**
179  * Manifest for boot stage images stored in flash.
180  *
181  * OpenTitan secure boot, at a minimum, consists of three boot stages: ROM,
182  * ROM_EXT, and the first owner boot stage, e.g. BL0. ROM is stored in the
183  * read-only ROM while remaining stages are stored in flash. This structure
184  * must be placed at the start of ROM_EXT and first owner boot stage images so
185  * that ROM and ROM_EXT can verify the integrity and authenticity of the next
186  * stage and configure peripherals as needed before handing over execution.
187  *
188  * Use of this struct for stages following the first owner boot stage is
189  * optional.
190  *
191  * Note: The definitions in
192  * sw/host/rom_ext_image_tools/signer/image/src/manifest.rs must be updated if
193  * this struct is modified. Please see the instructions in that file.
194  */
195 typedef struct manifest {
196  /**
197  * The manifest only supports one of the following signatures:
198  *
199  * - For `kManifestVersionMajor1`: `rsa_signature`.
200  * - For `kManifestVersionMajor2`: `ecdsa_signature`.
201  *
202  * Both signatures use SHA-256 as the hash function.
203  *
204  * On-target verification should also integrate usage constraints comparison
205  * to signature verification to harden it against potential attacks. During
206  * verification, the digest of an image should be computed by first reading
207  * the usage constraints from the hardware and then concatenating the rest of
208  * the image:
209  *
210  * digest = SHA256(usage_constraints_from_hw || rest_of_the_image)
211  *
212  * The start and the length of the region that should be concatenated to the
213  * usage constraints read from the hardware can be obtained using
214  * `manifest_digest_region_get()`.
215  */
216  union {
217  /**
218  * RSA signature of the image.
219  *
220  * RSASSA-PKCS1-v1_5 signature of the image generated using a 3072-bit RSA
221  * private key and the SHA-256 hash function. The signed region of an image
222  * starts immediately after this field and ends at the end of the image.
223  */
224  sigverify_rsa_buffer_t rsa_signature;
225 
226  /**
227  * ECDSA P256 signature of the image.
228  *
229  * ECDSA P256 signature of the image generated using a NIST P256 ECC key
230  * and the SHA-256 hash function. The signed region of an image starts
231  * immediately after the end of the union encapsulating this field and ends
232  * at the end of the image.
233  */
234  ecdsa_p256_signature_t ecdsa_signature;
235  };
236  /**
237  * Usage constraints.
238  */
240  /**
241  * The manifest only supports one of the following public key types:
242  *
243  * - For `kManifestVersionMajor1`: `rsa_modulus`.
244  * - For `kManifestVersionMajor2`: `ecdsa_public_key`.
245  */
246  union {
247  /**
248  * Modulus of the signer's 3072-bit RSA public key.
249  */
250  sigverify_rsa_buffer_t rsa_modulus;
251  /**
252  * Signer's ECDSA NIST P256 ECC public key.
253  */
254  ecdsa_p256_public_key_t ecdsa_public_key;
255  };
256  /**
257  * Address translation (hardened boolean).
258  */
260  /**
261  * Manifest identifier.
262  */
263  uint32_t identifier;
264  /**
265  * Manifest format major and minor version.
266  *
267  * These version values can be used to maintain or break forward compatibility
268  * in ROM while preserving backward compatibility in ROM_EXT. ROM requires the
269  * major version to be `kManifestVersionMajor2`.
270  */
272  /**
273  * Offset of the end of the signed region relative to the start of the
274  * manifest.
275  */
277  /**
278  * Length of the image including the manifest in bytes.
279  *
280  * Note that the length includes the signature but the signature is excluded
281  * from the signed region.
282  */
283  uint32_t length;
284  /**
285  * Image major version.
286  */
287  uint32_t version_major;
288  /**
289  * Image minor version.
290  */
291  uint32_t version_minor;
292  /**
293  * Security version of the image used for anti-rollback protection.
294  */
296  /**
297  * Image timestamp.
298  *
299  * Unix timestamp that gives the creation time of the image, seconds since
300  * 00:00:00 on January 1, 1970 UTC (the Unix Epoch).
301  */
303  /**
304  * Binding value used by key manager to derive secret values.
305  *
306  * A change in this value changes the secret value of key manager, and
307  * consequently, the versioned keys and identity seeds generated at subsequent
308  * boot stages.
309  */
311  /**
312  * Maximum allowed version for keys generated at the next boot stage.
313  */
314  uint32_t max_key_version;
315  /**
316  * Offset of the start of the executable region of the image from the start
317  * of the manifest in bytes.
318  */
319  uint32_t code_start;
320  /**
321  * Offset of the end of the executable region (exclusive) of the image from
322  * the start of the manifest in bytes.
323  */
324  uint32_t code_end;
325  /**
326  * Offset of the first instruction to execute in the image from the start of
327  * the manifest in bytes.
328  */
329  uint32_t entry_point;
330  /**
331  * Extensions.
332  */
334 } manifest_t;
335 
336 OT_ASSERT_MEMBER_OFFSET(manifest_t, rsa_signature, 0);
337 OT_ASSERT_MEMBER_OFFSET(manifest_t, ecdsa_signature, 0);
338 OT_ASSERT_MEMBER_OFFSET(manifest_t, usage_constraints, 384);
339 OT_ASSERT_MEMBER_OFFSET(manifest_t, rsa_modulus, 432);
340 OT_ASSERT_MEMBER_OFFSET(manifest_t, ecdsa_public_key, 432);
341 OT_ASSERT_MEMBER_OFFSET(manifest_t, address_translation, 816);
342 OT_ASSERT_MEMBER_OFFSET(manifest_t, identifier, 820);
344 OT_ASSERT_MEMBER_OFFSET(manifest_t, signed_region_end, 828);
345 OT_ASSERT_MEMBER_OFFSET(manifest_t, length, 832);
346 OT_ASSERT_MEMBER_OFFSET(manifest_t, version_major, 836);
347 OT_ASSERT_MEMBER_OFFSET(manifest_t, version_minor, 840);
348 OT_ASSERT_MEMBER_OFFSET(manifest_t, security_version, 844);
349 OT_ASSERT_MEMBER_OFFSET(manifest_t, timestamp, 848);
350 OT_ASSERT_MEMBER_OFFSET(manifest_t, binding_value, 856);
351 OT_ASSERT_MEMBER_OFFSET(manifest_t, max_key_version, 888);
352 OT_ASSERT_MEMBER_OFFSET(manifest_t, code_start, 892);
353 OT_ASSERT_MEMBER_OFFSET(manifest_t, code_end, 896);
354 OT_ASSERT_MEMBER_OFFSET(manifest_t, entry_point, 900);
355 OT_ASSERT_MEMBER_OFFSET(manifest_t, extensions, 904);
357 
358 /**
359  * Region of an image that should be included in the digest computation.
360  */
361 typedef struct manifest_digest_region {
362  /**
363  * Start of the region.
364  */
365  const void *start;
366  /**
367  * Length of the region in bytes.
368  */
369  size_t length;
371 
372 /**
373  * Required manifest extension header.
374  */
375 typedef struct manifest_ext_header {
376  /**
377  * Identifier.
378  *
379  * A high HW constant with a realively high HD from other extensions'
380  * identifiers.
381  */
382  uint32_t identifier;
383  /**
384  * Name.
385  *
386  * 4 ASCII characters for ease of debugging.
387  */
388  uint32_t name;
390 
391 /**
392  * Extension identifiers and names.
393  */
394 enum {
395  /**
396  * Identifiers.
397  *
398  * These are high HW constants with a relatively high HD from each other.
399  */
400  kManifestExtIdSpxKey = 0x94ac01ec,
401  kManifestExtIdSpxSignature = 0xad77f84a,
402  /**
403  * ASCII "EXT0.
404  */
405  kManifestExtNameSpxKey = 0x30545845,
406  /**
407  * ASCII "EXT1.
408  */
409  kManifestExtNameSpxSignature = 0x31545845,
410 };
411 
412 /**
413  * Manifest extension: SPHINCS+ public key.
414  */
415 typedef struct manifest_ext_spx_key {
416  /**
417  * Required manifest header.
418  */
420  /**
421  * SPHINCS+ public key used to sign the image.
422  */
425 
426 /**
427  * Manifest extension: SPHINCS+ signature.
428  */
430  /**
431  * Required manifest header.
432  */
434  /**
435  * SPHINCS+ signature of the image.
436  */
439 
440 /**
441  * Table of manifest extensions.
442  *
443  * Columns: Table index, type name, extenstion name, identifier, signed or not.
444  */
445 // clang-format off
446 #define MANIFEST_EXTENSIONS(X) \
447  X(0, manifest_ext_spx_key_t, spx_key, kManifestExtIdSpxKey, true ) \
448  X(1, manifest_ext_spx_signature_t, spx_signature, kManifestExtIdSpxSignature, false)
449 // clang-format on
450 
451 #if defined(OT_PLATFORM_RV32) || defined(MANIFEST_UNIT_TEST_)
452 /**
453  * Checks the fields of a manifest.
454  *
455  * This function performs several basic checks to ensure that
456  * - Executable region is non-empty, inside the image, located after the
457  * manifest, and word aligned, and
458  * - Entry point is inside the executable region and word aligned.
459  *
460  * @param manfiest A manifest.
461  * @return Result of the operation.
462  */
464 inline rom_error_t manifest_check(const manifest_t *manifest) {
465  // Major version must be `kManifestVersionMajor2`.
466  if (manifest->manifest_version.major != kManifestVersionMajor2) {
467  return kErrorManifestBadVersionMajor;
468  }
469 
470  // Signed region must be inside the image.
472  return kErrorManifestBadSignedRegion;
473  }
474 
475  // Executable region must be non-empty, inside the signed region, located
476  // after the manifest, and word aligned.
478  manifest->code_start < sizeof(manifest_t) ||
480  (manifest->code_start & 0x3) != 0 || (manifest->code_end & 0x3) != 0) {
481  return kErrorManifestBadCodeRegion;
482  }
483 
484  // Entry point must be inside the executable region and word aligned.
487  (manifest->entry_point & 0x3) != 0) {
488  return kErrorManifestBadEntryPoint;
489  }
490 
491  // Manifest extension offset must be word aligned.
492  for (size_t i = 0; i < CHIP_MANIFEST_EXT_TABLE_ENTRY_COUNT; ++i) {
493  if ((manifest->extensions.entries[i].offset & 0x3) != 0) {
494  return kErrorManifestBadExtension;
495  }
496  }
497 
498  return kErrorOk;
499 }
500 
501 /**
502  * Gets the region of the image that should be included in the digest
503  * computation.
504  *
505  * Digest region of an image starts immediately after the `usage_constraints`
506  * field of its manifest and ends at the end of the image.
507  *
508  * @param manifest A manifest.
509  * return digest_region Region of the image that should be included in the
510  * digest computation.
511  */
513 inline manifest_digest_region_t manifest_digest_region_get(
514  const manifest_t *manifest) {
515  enum {
516  kDigestRegionOffset = offsetof(manifest_t, usage_constraints) +
517  sizeof(manifest->usage_constraints),
518  };
519  return (manifest_digest_region_t){
520  .start = (const char *)manifest + kDigestRegionOffset,
521  .length = manifest->signed_region_end - kDigestRegionOffset,
522  };
523 }
524 
525 /**
526  * Gets the executable region of the image.
527  *
528  * @param manifest A manifest.
529  * return Executable region of the image.
530  */
532 inline epmp_region_t manifest_code_region_get(const manifest_t *manifest) {
533  return (epmp_region_t){
534  .start = (uintptr_t)manifest + manifest->code_start,
535  .end = (uintptr_t)manifest + manifest->code_end,
536  };
537 }
538 
539 /**
540  * Gets the entry point of an image.
541  *
542  * Entry point is the address that a boot stage jumps to transfer execution to
543  * the next stage in the boot chain. This function returns a `uintptr_t` instead
544  * of a function pointer to accommodate for entry points with different
545  * parameters and return types.
546  *
547  * @param manfiest A manifest.
548  * return Entry point address.
549  */
551 inline uintptr_t manifest_entry_point_get(const manifest_t *manifest) {
552  return (uintptr_t)manifest + manifest->entry_point;
553 }
554 
555 #define DEFINE_GETTER(index_, type_, name_, id_, _) \
556  OT_WARN_UNUSED_RESULT \
557  \
558  inline rom_error_t manifest_ext_get_##name_(const manifest_t *manifest, \
559  const type_ **name_) { \
560  enum { \
561  kMinSize = CHIP_MANIFEST_SIZE, \
562  kMaxSize = CHIP_ROM_EXT_RESIZABLE_SIZE_MAX - sizeof(type_), \
563  }; \
564  const manifest_ext_table_entry_t *entry = \
565  &manifest->extensions.entries[index_]; \
566  uint32_t table_id = entry->identifier; \
567  uint32_t offset = entry->offset; \
568  if (launder32(table_id) == id_) { \
569  HARDENED_CHECK_EQ(table_id, id_); \
570  if (launder32(offset) >= kMinSize && launder32(offset) < kMaxSize) { \
571  HARDENED_CHECK_GE(offset, kMinSize); \
572  HARDENED_CHECK_LT(offset, kMaxSize); \
573  uintptr_t ext_address = (uintptr_t)((char *)manifest + entry->offset); \
574  uint32_t header_id = \
575  ((manifest_ext_header_t *)ext_address)->identifier; \
576  if (launder32(header_id) == id_) { \
577  HARDENED_CHECK_EQ(header_id, id_); \
578  *name_ = (const type_ *)ext_address; \
579  return kErrorOk; \
580  } \
581  } \
582  } \
583  return kErrorManifestBadExtension; \
584  }
585 
586 /**
587  * Getters for manifest extensions.
588  */
589 MANIFEST_EXTENSIONS(DEFINE_GETTER)
590 
591 #else // defined(OT_PLATFORM_RV32) || defined(MANIFEST_UNIT_TEST_)
592 /**
593  * Declarations for the functions above that should be defined in tests.
594  */
595 rom_error_t manifest_check(const manifest_t *manifest);
596 manifest_digest_region_t manifest_digest_region_get(const manifest_t *manifest);
597 epmp_region_t manifest_code_region_get(const manifest_t *manifest);
598 uintptr_t manifest_entry_point_get(const manifest_t *manifest);
599 
600 // Manifest extension getters.
601 rom_error_t manifest_ext_get_spx_key(const manifest_t *manifest,
602  const manifest_ext_spx_key_t **spx_key);
603 rom_error_t manifest_ext_get_spx_signature(
604  const manifest_t *manifest,
605  const manifest_ext_spx_signature_t **spx_signature);
606 
607 #endif // defined(OT_PLATFORM_RV32) || defined(MANIFEST_UNIT_TEST_)
608 
609 #ifdef __cplusplus
610 } // extern "C"
611 #endif // __cplusplus
612 
613 #endif // OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_MANIFEST_H_