1 /*
2  * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #pragma once
8 
9 #include <stdint.h>
10 #include <stdbool.h>
11 #include "ets_sys.h"
12 #include "ecdsa.h"
13 #include "rsa_pss.h"
14 #include "esp_assert.h"
15 
16 #ifdef __cplusplus
17 extern "C" {
18 #endif
19 
20 #if CONFIG_SECURE_BOOT_V2_ENABLED || CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT
21 
22 typedef struct ets_secure_boot_sig_block ets_secure_boot_sig_block_t;
23 typedef struct ets_secure_boot_signature ets_secure_boot_signature_t;
24 typedef struct ets_secure_boot_key_digests ets_secure_boot_key_digests_t;
25 
26 /* Anti-FI measure: use full words for success/fail, instead of
27    0/non-zero
28 */
29 typedef enum {
30     SB_SUCCESS = 0x3A5A5AA5,
31     SB_FAILED = 0x7533885E,
32 } ets_secure_boot_status_t;
33 
34 /* Verify bootloader image (reconfigures cache to map),
35    with key digests provided as parameters.)
36 
37    Can be used to verify secure boot status before enabling
38    secure boot permanently.
39 
40    If stage_load parameter is true, bootloader is copied into staging
41    buffer in RAM at the same time.
42 
43    If result is SB_SUCCESS, the "simple hash" of the bootloader is
44    copied into verified_hash.
45 */
46 ets_secure_boot_status_t ets_secure_boot_verify_bootloader_with_keys(uint8_t *verified_hash, const ets_secure_boot_key_digests_t *trusted_keys, bool stage_load);
47 
48 /* Read key digests from efuse. Any revoked/missing digests will be
49    marked as NULL
50 */
51 ETS_STATUS ets_secure_boot_read_key_digests(ets_secure_boot_key_digests_t *trusted_keys);
52 
53 /* Verify supplied signature against supplied digest, using
54    supplied trusted key digests.
55 
56    Doesn't reconfigure cache or any other hardware access except for RSA peripheral.
57 
58    If result is SB_SUCCESS, the image_digest value is copied into verified_digest.
59 */
60 ets_secure_boot_status_t ets_secure_boot_verify_signature(const ets_secure_boot_signature_t *sig, const uint8_t *image_digest, const ets_secure_boot_key_digests_t *trusted_keys, uint8_t *verified_digest);
61 
62 /* Revoke a public key digest in efuse.
63    @param index Digest to revoke. Must be 0, 1 or 2.
64  */
65 void ets_secure_boot_revoke_public_key_digest(int index);
66 
67 #define CRC_SIGN_BLOCK_LEN 1196
68 #define SIG_BLOCK_PADDING 4096
69 #define ETS_SECURE_BOOT_V2_SIGNATURE_MAGIC 0xE7
70 
71 /* Secure Boot V2 signature block
72 
73    (Up to 3 in a signature sector are appended to the image)
74  */
75 #if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
76 
77 struct ets_secure_boot_sig_block {
78     uint8_t magic_byte;
79     uint8_t version;
80     uint8_t _reserved1;
81     uint8_t _reserved2;
82     uint8_t image_digest[32];
83     ets_rsa_pubkey_t key;
84     uint8_t signature[384];
85     uint32_t block_crc;
86     uint8_t _padding[16];
87 };
88 
89 #elif CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
90 
91 struct __attribute((packed)) ets_secure_boot_sig_block {
92     uint8_t magic_byte;
93     uint8_t version;
94     uint8_t _reserved1;
95     uint8_t _reserved2;
96     uint8_t image_digest[32];
97     struct {
98         struct {
99             uint8_t curve_id; /* ETS_ECDSA_CURVE_P192 / ETS_ECDSA_CURVE_P256 */
100             uint8_t point[64]; /* X followed by Y (both little-endian), plus zero bytes if P192 */
101         } key;
102         uint8_t signature[64]; /* r followed by s (both little-endian) */
103         uint8_t padding[1031];
104     } ecdsa;
105     uint32_t block_crc; /* note: crc covers all bytes in the structure before it, regardless of version field */
106     uint8_t _padding[16];
107 };
108 #endif
109 
110 ESP_STATIC_ASSERT(sizeof(ets_secure_boot_sig_block_t) == 1216, "invalid sig block size");
111 
112 #define SECURE_BOOT_NUM_BLOCKS 3
113 
114 /* V2 Secure boot signature sector (up to 3 blocks) */
115 struct ets_secure_boot_signature {
116     ets_secure_boot_sig_block_t block[SECURE_BOOT_NUM_BLOCKS];
117     uint8_t _padding[4096 - (sizeof(ets_secure_boot_sig_block_t) * SECURE_BOOT_NUM_BLOCKS)];
118 };
119 
120 ESP_STATIC_ASSERT(sizeof(ets_secure_boot_signature_t) == 4096, "invalid sig sector size");
121 
122 #define MAX_KEY_DIGESTS 3
123 
124 struct ets_secure_boot_key_digests {
125     const void *key_digests[MAX_KEY_DIGESTS];
126     bool allow_key_revoke;
127 };
128 
129 #endif /* CONFIG_SECURE_BOOT_V2_ENABLED || CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT */
130 
131 #ifdef __cplusplus
132 }
133 #endif
134