├── README.md ├── memory_compare.h ├── hmac.h ├── mock_hmac.c ├── mask_rom.h ├── memory_compare.c ├── hmac.c └── mask_rom.c /README.md: -------------------------------------------------------------------------------- 1 | Not mine. 2 | 3 | Copy of code out of thesis to peruse more easily 4 | 5 | - 6 | - 7 | - 8 | - 9 | # copyboot 10 | -------------------------------------------------------------------------------- /memory_compare.h: -------------------------------------------------------------------------------- 1 | #ifndef MEMORY_COMPARE_H 2 | #define MEMORY_COMPARE_H 3 | 4 | int cmp_key(const void *buf1, const void *buf2, unsigned int size); 5 | int cmp_image_len(const void *buf1, const void *buf2, unsigned int size); 6 | int cmp_image_code(const void *buf1, const void *buf2, unsigned int size); 7 | int cmp_modulus(const void *buf1, const void *buf2, unsigned int size); 8 | int cmp_signature(const void *buf1, const void *buf2, unsigned int size); 9 | int cmp_hash_decrypt(const void *buf1, const void *buf2, unsigned int size); 10 | 11 | #endif // MEMORY_COMPARE_H 12 | -------------------------------------------------------------------------------- /hmac.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * Filename: sha256.h 3 | * Author: Brad Conte (brad AT bradconte.com) 4 | * Copyright: 5 | * Disclaimer: This code is presented "as is" without any guarantees. 6 | * Details: Defines the API for the corresponding SHA1 implementation. 7 | *********************************************************************/ 8 | 9 | #ifndef SHA256_H 10 | #define SHA256_H 11 | 12 | /*************************** HEADER FILES ***************************/ 13 | #include "mask_rom.h" 14 | #include 15 | 16 | /****************************** MACROS ******************************/ 17 | #define SHA2_256_BLOCK_SIZE 32 // SHA256 outputs a 32 byte digest 18 | #define HMAC_KEY_SIZE 32 // HMAC key is 32 bytes 19 | 20 | /**************************** DATA TYPES ****************************/ 21 | typedef unsigned char BYTE; // 8-bit byte 22 | typedef unsigned int WORD; // 32-bit word, change to "long" for 16-bit machines 23 | 24 | typedef struct { 25 | BYTE data[64]; 26 | WORD datalen; 27 | unsigned long long bitlen; 28 | WORD state[8]; 29 | } SHA2_256_CTX; 30 | 31 | /*********************** FUNCTION DECLARATIONS **********************/ 32 | void HMAC_SHA2_256_init(SHA2_256_CTX *ctx); 33 | void HMAC_SHA2_256_update(SHA2_256_CTX *ctx, const BYTE data[], size_t len); 34 | void HMAC_SHA2_256_final(SHA2_256_CTX *ctx, BYTE hash[]); 35 | BYTE *HMAC_SHA2_256(BYTE key[], BYTE mes[], int size, 36 | rom_ext_manifest_t __current_rom_ext_mf); 37 | 38 | #endif // SHA256_H 39 | -------------------------------------------------------------------------------- /mock_hmac.c: -------------------------------------------------------------------------------- 1 | #include "hmac.h" 2 | #include "memory_compare.h" 3 | 4 | BYTE *HMAC_SHA2_256(BYTE key[], BYTE mes[], int size, 5 | rom_ext_manifest_t __current_rom_ext_mf) { 6 | int __expected_size = sizeof(__current_rom_ext_mf.pub_signature_key) + 7 | sizeof(__current_rom_ext_mf.image_length) + 8 | __current_rom_ext_mf.image_length; 9 | 10 | __CPROVER_assert(cmp_key(mes, &__current_rom_ext_mf.pub_signature_key, 11 | sizeof(__current_rom_ext_mf.pub_signature_key)) == 0, 12 | "PROPERTY 4: Message contains the key"); 13 | 14 | __CPROVER_assert( 15 | cmp_image_len(mes + sizeof(__current_rom_ext_mf.pub_signature_key), 16 | &__current_rom_ext_mf.image_length, 17 | sizeof(__current_rom_ext_mf.image_length)) == 0, 18 | "PROPERTY 4: Message contains the Image length"); 19 | 20 | __CPROVER_assert( 21 | cmp_image_code(mes + sizeof(__current_rom_ext_mf.pub_signature_key) + 22 | sizeof(__current_rom_ext_mf.image_length), 23 | __current_rom_ext_mf.image_code, 24 | __current_rom_ext_mf.image_length) == 0, 25 | "PROPERTY 4: Message contains the Image code"); 26 | 27 | __CPROVER_assert(size == __expected_size, 28 | "PROPERTY 4: Message size parameter is as expected."); 29 | 30 | __CPROVER_assert(__CPROVER_OBJECT_SIZE(mes) == __expected_size, 31 | "PROPERTY 4: Size of message is as expected."); 32 | 33 | char *hash = malloc(256 / 8); // Model it to be ok for PROPERTY 5 34 | 35 | __CPROVER_assert(__CPROVER_OBJECT_SIZE(hash) == 256 / 8, 36 | "PROPERTY 3: Hash is 256 bits"); 37 | 38 | __CPROVER_assert(__CPROVER_r_ok(hash, 256 / 8), 39 | "PROPERTY 3: hash is in readable address"); 40 | 41 | __REACHABILITY_CHECK 42 | 43 | return hash; 44 | } 45 | -------------------------------------------------------------------------------- /mask_rom.h: -------------------------------------------------------------------------------- 1 | #ifndef MASK_ROM_H 2 | #define MASK_ROM_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define __REACHABILITY_CHECK \ 11 | __CPROVER_assert( \ 12 | 0, "Reachability check , should always → \033[0;31mFAIL\033[0m"); 13 | #define MAX_ROM_EXTS 1 14 | #define RSA_SIZE 96 15 | #define PMP_REGIONS 16 16 | #define MAX_IMAGE_LENGTH \ 17 | 2 // necessary constraint in order to terminate CBMC verification 18 | 19 | // Represents a signature. Needed for CBMC OBJECT_SIZE to see if signature is of 20 | // ok size 21 | typedef struct signature_t { 22 | int32_t value[RSA_SIZE]; 23 | // something else 24 | } signature_t; 25 | 26 | // Represents a public key 27 | typedef struct pub_key_t { 28 | int32_t exponent; 29 | int32_t modulus[RSA_SIZE]; 30 | // something else 31 | } pub_key_t; 32 | 33 | // Struct representing rom_ext_manifest 34 | typedef struct rom_ext_manifest_t { 35 | uint32_t identifier; 36 | signature_t signature; 37 | // public part of signature key 38 | pub_key_t pub_signature_key; 39 | uint32_t image_length; 40 | char *image_code; 41 | } rom_ext_manifest_t; 42 | 43 | // Returned by rom_ext_manifests_to_try 44 | typedef struct rom_exts_manifests_t { 45 | int size; 46 | rom_ext_manifest_t rom_exts_mfs[MAX_ROM_EXTS]; 47 | } rom_exts_manifests_t; 48 | 49 | // Represents boot policy 50 | typedef struct boot_policy_t { 51 | int identifier; 52 | // which rom_ext_slot to boot 53 | int rom_ext_slot; 54 | // what to do if all ROM Ext are invalid 55 | char *fail; 56 | // what to do if the ROM Ext unexpectedly returns 57 | char *fail_rom_ext_terminated; 58 | } boot_policy_t; 59 | 60 | // Represents a pmp region 61 | typedef struct __PMP_region_t { 62 | int identifier; 63 | // Locked , Read , Write , Execute 64 | int R; 65 | int W; 66 | int E; 67 | int L; 68 | } __PMP_region_t; 69 | 70 | typedef struct __PMP_regions_t { 71 | // There are 16 PMP regions (0...15) 72 | __PMP_region_t pmp_regions[PMP_REGIONS]; 73 | } __PMP_regions_t; 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /memory_compare.c: -------------------------------------------------------------------------------- 1 | #include "mask_rom.h" 2 | 3 | int cmp_key(const void *buf1, const void *buf2, unsigned int size) { 4 | __CPROVER_assert( 5 | size == (3072 + 32) / 8, 6 | "Assert: Size should be equal to size of modulus and exponent"); 7 | 8 | const char *cbuf1 = (char *)buf1; 9 | const char *cbuf2 = (char *)buf2; 10 | 11 | int mismatch = 0; 12 | for (int i = 0; i < size; i++) { 13 | if (*cbuf1 != *cbuf2) { 14 | mismatch = 1; 15 | break; 16 | } 17 | cbuf1++; 18 | cbuf2++; 19 | } 20 | 21 | return mismatch; // 0 is equal, 1 is not equal. 22 | } 23 | 24 | int cmp_image_len(const void *buf1, const void *buf2, unsigned int size) { 25 | __CPROVER_assert( 26 | size == 4, 27 | "Assert: Size should be equal to size of image_len variable type"); 28 | 29 | const char *cbuf1 = (char *)buf1; 30 | const char *cbuf2 = (char *)buf2; 31 | 32 | int mismatch = 0; 33 | for (int i = 0; i < size; i++) { 34 | if (*cbuf1 != *cbuf2) { 35 | mismatch = 1; 36 | break; 37 | } 38 | cbuf1++; 39 | cbuf2++; 40 | } 41 | 42 | return mismatch; // 0 is equal, 1 is not equal. 43 | } 44 | 45 | int cmp_image_code(const void *buf1, const void *buf2, unsigned int size) { 46 | __CPROVER_assert( 47 | size <= MAX_IMAGE_LENGTH && size > 0, 48 | "Assert: Size should be less than or equal to MAX_IMAGE_LENGTH"); 49 | 50 | const char *cbuf1 = (char *)buf1; 51 | const char *cbuf2 = (char *)buf2; 52 | 53 | int mismatch = 0; 54 | for (int i = 0; i < size; i++) { 55 | if (*cbuf1 != *cbuf2) { 56 | mismatch = 1; 57 | break; 58 | } 59 | cbuf1++; 60 | cbuf2++; 61 | } 62 | 63 | return mismatch; // 0 is equal, 1 is not equal. 64 | } 65 | 66 | int cmp_modulus(const void *buf1, const void *buf2, unsigned int size) { 67 | __CPROVER_assert(size == 3072 / 8, 68 | "Assert: Size should be equal to size of modulus"); 69 | 70 | const char *cbuf1 = (char *)buf1; 71 | const char *cbuf2 = (char *)buf2; 72 | 73 | int mismatch = 0; 74 | for (int i = 0; i < size; i++) { 75 | if (*cbuf1 != *cbuf2) { 76 | mismatch = 1; 77 | break; 78 | } 79 | cbuf1++; 80 | cbuf2++; 81 | } 82 | 83 | return mismatch; // 0 is equal, 1 is not equal. 84 | } 85 | 86 | int cmp_signature(const void *buf1, const void *buf2, unsigned int size) { 87 | __CPROVER_assert(size == 3072 / 8, 88 | "Assert: Size should be equal to size of signature"); 89 | 90 | const char *cbuf1 = (char *)buf1; 91 | const char *cbuf2 = (char *)buf2; 92 | 93 | int mismatch = 0; 94 | for (int i = 0; i < size; i++) { 95 | if (*cbuf1 != *cbuf2) { 96 | mismatch = 1; 97 | break; 98 | } 99 | cbuf1++; 100 | cbuf2++; 101 | } 102 | 103 | return mismatch; // 0 is equal, 1 is not equal. 104 | } 105 | 106 | int cmp_hash_decrypt(const void *buf1, const void *buf2, unsigned int size) { 107 | __CPROVER_assert(size == 256 / 8, 108 | "Assert: Size should be equal to size of hash"); 109 | 110 | const char *cbuf1 = (char *)buf1; 111 | const char *cbuf2 = (char *)buf2; 112 | 113 | int mismatch = 0; 114 | for (int i = 0; i < size; i++) { 115 | if (*cbuf1 != *cbuf2) { 116 | mismatch = 1; 117 | break; 118 | } 119 | cbuf1++; 120 | cbuf2++; 121 | } 122 | 123 | return mismatch; // 0 is equal, 1 is not equal. 124 | } 125 | -------------------------------------------------------------------------------- /hmac.c: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | //////////////////////// ORIGINAL FILE /////////////////////////////// 3 | * Filename: sha2_256.c 4 | * Original 5 | * Author: Brad Conte (brad AT bradconte.com) 6 | * Copyright: 7 | * Disclaimer: This code is presented "as is" without any guarantees. 8 | * Details: Implementation of the SHA-256 hashing algorithm. 9 | SHA-256 is one of the three algorithms in the SHA2 10 | specification. The others, SHA-384 and SHA-512, are not 11 | offered in this implementation. 12 | Algorithm specification can be found here: 13 | * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf 14 | This implementation uses little endian byte order. 15 | * Modified By: Jacob Gosch and Kristoffer Jensen 16 | *********************************************************************/ 17 | 18 | /*************************** HEADER FILES ***************************/ 19 | #include "hmac.h" 20 | #include "memory_compare.h" 21 | #include 22 | #include 23 | 24 | /****************************** MACROS ******************************/ 25 | #define ROTLEFT(a, b) (((a) << (b)) | ((a) >> (32 - (b)))) 26 | #define ROTRIGHT(a, b) (((a) >> (b)) | ((a) << (32 - (b)))) 27 | 28 | #define CH(x, y, z) (((x) & (y)) ^ (~(x) & (z))) 29 | #define MAJ(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) 30 | #define EP0(x) (ROTRIGHT(x, 2) ^ ROTRIGHT(x, 13) ^ ROTRIGHT(x, 22)) 31 | #define EP1(x) (ROTRIGHT(x, 6) ^ ROTRIGHT(x, 11) ^ ROTRIGHT(x, 25)) 32 | #define SIG0(x) (ROTRIGHT(x, 7) ^ ROTRIGHT(x, 18) ^ ((x) >> 3)) 33 | #define SIG1(x) (ROTRIGHT(x, 17) ^ ROTRIGHT(x, 19) ^ ((x) >> 10)) 34 | 35 | /**************************** VARIABLES *****************************/ 36 | static const WORD k[64] = { 37 | 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 38 | 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 39 | 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 40 | 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 41 | 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 42 | 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 43 | 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 44 | 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 45 | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 46 | 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 47 | 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2}; 48 | 49 | /*********************** FUNCTION DEFINITIONS ***********************/ 50 | void HMAC_SHA2_256_transform(SHA2_256_CTX *ctx, const BYTE data[]) { 51 | WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64]; 52 | 53 | for (i = 0, j = 0; i < 16; ++i, j += 4) 54 | m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | 55 | (data[j + 3]); 56 | for (; i < 64; ++i) 57 | m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16]; 58 | 59 | a = ctx->state[0]; 60 | b = ctx->state[1]; 61 | c = ctx->state[2]; 62 | d = ctx->state[3]; 63 | e = ctx->state[4]; 64 | f = ctx->state[5]; 65 | g = ctx->state[6]; 66 | h = ctx->state[7]; 67 | 68 | for (i = 0; i < 64; ++i) { 69 | t1 = h + EP1(e) + CH(e, f, g) + k[i] + m[i]; 70 | t2 = EP0(a) + MAJ(a, b, c); 71 | h = g; 72 | g = f; 73 | f = e; 74 | e = d + t1; 75 | d = c; 76 | c = b; 77 | b = a; 78 | a = t1 + t2; 79 | } 80 | 81 | ctx->state[0] += a; 82 | ctx->state[1] += b; 83 | ctx->state[2] += c; 84 | ctx->state[3] += d; 85 | ctx->state[4] += e; 86 | ctx->state[5] += f; 87 | ctx->state[6] += g; 88 | ctx->state[7] += h; 89 | } 90 | 91 | void HMAC_SHA2_256_init(SHA2_256_CTX *ctx) { 92 | ctx->datalen = 0; 93 | ctx->bitlen = 0; 94 | ctx->state[0] = 0x6a09e667; 95 | ctx->state[1] = 0xbb67ae85; 96 | ctx->state[2] = 0x3c6ef372; 97 | ctx->state[3] = 0xa54ff53a; 98 | ctx->state[4] = 0x510e527f; 99 | ctx->state[5] = 0x9b05688c; 100 | ctx->state[6] = 0x1f83d9ab; 101 | ctx->state[7] = 0x5be0cd19; 102 | } 103 | 104 | void HMAC_SHA2_256_update(SHA2_256_CTX *ctx, const BYTE data[], size_t len) { 105 | WORD i; 106 | 107 | for (i = 0; i < len; ++i) { 108 | ctx->data[ctx->datalen] = data[i]; 109 | ctx->datalen++; 110 | if (ctx->datalen == 64) { 111 | HMAC_SHA2_256_transform(ctx, ctx->data); 112 | ctx->bitlen += 512; 113 | ctx->datalen = 0; 114 | } 115 | } 116 | } 117 | 118 | void HMAC_SHA2_256_final(SHA2_256_CTX *ctx, BYTE hash[]) { 119 | WORD i; 120 | 121 | i = ctx->datalen; 122 | 123 | // Pad whatever data is left in the buffer. 124 | if (ctx->datalen < 56) { 125 | ctx->data[i++] = 0x80; 126 | while (i < 56) 127 | ctx->data[i++] = 0x00; 128 | } else { 129 | ctx->data[i++] = 0x80; 130 | while (i < 64) 131 | ctx->data[i++] = 0x00; 132 | HMAC_SHA2_256_transform(ctx, ctx->data); 133 | memset(ctx->data, 0, 56); 134 | } 135 | 136 | // Append to the padding the total message's length in bits and transform. 137 | ctx->bitlen += ctx->datalen * 8; 138 | ctx->data[63] = ctx->bitlen; 139 | ctx->data[62] = ctx->bitlen >> 8; 140 | ctx->data[61] = ctx->bitlen >> 16; 141 | ctx->data[60] = ctx->bitlen >> 24; 142 | ctx->data[59] = ctx->bitlen >> 32; 143 | ctx->data[58] = ctx->bitlen >> 40; 144 | ctx->data[57] = ctx->bitlen >> 48; 145 | ctx->data[56] = ctx->bitlen >> 56; 146 | HMAC_SHA2_256_transform(ctx, ctx->data); 147 | 148 | // Since this implementation uses little endian byte ordering and SHA uses big 149 | // endian, reverse all the bytes when copying the final state to the output 150 | // hash. 151 | for (i = 0; i < 4; ++i) { 152 | hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff; 153 | hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff; 154 | hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff; 155 | hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff; 156 | hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff; 157 | hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff; 158 | hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff; 159 | hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff; 160 | } 161 | } 162 | 163 | BYTE *HMAC_SHA2_256(BYTE key[], BYTE mes[], int mes_size, 164 | rom_ext_manifest_t __current_rom_ext_mf) { 165 | int __expected_size = sizeof(__current_rom_ext_mf.pub_signature_key) + 166 | sizeof(__current_rom_ext_mf.image_length) + 167 | __current_rom_ext_mf.image_length; 168 | 169 | __CPROVER_assert(cmp_key(mes, &__current_rom_ext_mf.pub_signature_key, 170 | sizeof(__current_rom_ext_mf.pub_signature_key)) == 0, 171 | "PROPERTY 4: Message contains the key"); 172 | 173 | __CPROVER_assert( 174 | cmp_image_len(mes + sizeof(__current_rom_ext_mf.pub_signature_key), 175 | &__current_rom_ext_mf.image_length, 176 | sizeof(__current_rom_ext_mf.image_length)) == 0, 177 | "PROPERTY 4: Message contains the Image length"); 178 | 179 | __CPROVER_assert( 180 | cmp_image_code(mes + sizeof(__current_rom_ext_mf.pub_signature_key) + 181 | sizeof(__current_rom_ext_mf.image_length), 182 | __current_rom_ext_mf.image_code, 183 | __current_rom_ext_mf.image_length) == 0, 184 | "PROPERTY 4: Message contains the Image code"); 185 | 186 | __CPROVER_assert(mes_size == __expected_size, 187 | "PROPERTY 4: Message size parameter is as expected."); 188 | 189 | __CPROVER_assert(__CPROVER_OBJECT_SIZE(mes) == __expected_size, 190 | "PROPERTY 4: Size of message is as expected."); 191 | 192 | BYTE *buff = malloc(SHA2_256_BLOCK_SIZE * sizeof(BYTE)); 193 | SHA2_256_CTX ctx; 194 | 195 | BYTE *key_mes_pad = 196 | malloc(HMAC_KEY_SIZE * sizeof(BYTE) + mes_size * sizeof(BYTE)); 197 | memcpy(key_mes_pad, key, HMAC_KEY_SIZE); 198 | memcpy(key_mes_pad + HMAC_KEY_SIZE, mes, mes_size); 199 | 200 | HMAC_SHA2_256_init(&ctx); 201 | HMAC_SHA2_256_update(&ctx, key_mes_pad, HMAC_KEY_SIZE + mes_size); 202 | HMAC_SHA2_256_final(&ctx, buff); 203 | 204 | __CPROVER_assert(__CPROVER_OBJECT_SIZE(buff) == 256 / 8, 205 | "PROPERTY 3: Hash is 256 bits"); 206 | 207 | __CPROVER_assert(__CPROVER_r_ok(buff, 256 / 8), 208 | "PROPERTY 3: hash is in readable address"); 209 | 210 | __REACHABILITY_CHECK 211 | 212 | return buff; 213 | } 214 | -------------------------------------------------------------------------------- /mask_rom.c: -------------------------------------------------------------------------------- 1 | /* 2 | CBMC Verification of OpenTitan bootcode, 3 | written based on: 4 | sw/device/rom_ext/docs/manifest.md 5 | sw/device/mask_rom/mask_rom.c 6 | sw/device/mask_rom/docs/index.md 7 | doc/security/specs/secure_boot/index.md 8 | */ 9 | 10 | #include "hmac.h" 11 | #include "mask_rom.h" 12 | #include "memory_compare.h" 13 | 14 | // HMAC key in OTP/Keymanager 15 | BYTE __hmac_key[HMAC_KEY_SIZE]; 16 | 17 | // Whitelist in ROM 18 | #define __PKEY_WHITELIST_SIZE 1 19 | pub_key_t __pkey_whitelist[__PKEY_WHITELIST_SIZE]; 20 | 21 | // for CBMC 22 | int __current_rom_ext = 0; 23 | rom_ext_manifest_t __current_rom_ext_mf; 24 | int __boot_policy_stop = 0; 25 | int __rom_ext_called[MAX_ROM_EXTS] = {}; 26 | int __rom_ext_fail_func[MAX_ROM_EXTS] = {}; 27 | int __boot_failed_called[MAX_ROM_EXTS] = {}; 28 | int __validated_rom_exts[MAX_ROM_EXTS] = {}; 29 | int __rom_ext_returned[MAX_ROM_EXTS] = {}; 30 | int __verify_signature_called[MAX_ROM_EXTS] = {}; 31 | int __imply(int a, int b) { return a ? b : 1; } 32 | int __valid_signature[MAX_ROM_EXTS] = {}; 33 | 34 | // The configured PMP regions for each rom ext. 35 | __PMP_regions_t __rom_ext_pmp_region[MAX_ROM_EXTS]; 36 | 37 | // Function type used to define function pointer to the entry of the ROM_EXT 38 | // stage. 39 | typedef void(rom_ext_boot_func)(void); 40 | 41 | // Function type for entry point of boot policy fail function 42 | typedef void(fail_func)(void); 43 | 44 | // Function type for entry point of boot policy fail rom ext terminated 45 | // function. 46 | typedef void(fail_rom_ext_terminated_func)(rom_ext_manifest_t); 47 | 48 | int verify_rom_ext_signature(pub_key_t rom_ext_pub_key, 49 | rom_ext_manifest_t manifest) { 50 | __CPROVER_precondition( 51 | MAX_IMAGE_LENGTH >= manifest.image_length && manifest.image_length > 0, 52 | "Precondition: Assumes rom ext image code is < 10 and > 0"); 53 | __CPROVER_precondition( 54 | __CPROVER_r_ok(manifest.image_code, manifest.image_length), 55 | "Precondition: Assumes rom ext image code is readable"); 56 | 57 | __verify_signature_called[__current_rom_ext] = 1; 58 | 59 | int bytes = sizeof(manifest.pub_signature_key) + 60 | sizeof(manifest.image_length) + manifest.image_length; 61 | 62 | char message[bytes]; 63 | 64 | memcpy(message, &manifest.pub_signature_key, 65 | sizeof(manifest.pub_signature_key)); 66 | memcpy(message + sizeof(manifest.pub_signature_key), &manifest.image_length, 67 | sizeof(manifest.image_length)); 68 | memcpy(message + sizeof(manifest.pub_signature_key) + 69 | sizeof(manifest.image_length), 70 | manifest.image_code, manifest.image_length); 71 | 72 | // Otherwise OBJECT_SIZE returns size of manifest and not signature. 73 | signature_t signature = manifest.signature; 74 | 75 | int result = OTBN_RSASSA_PKCS1_V1_5_VERIFY( 76 | rom_ext_pub_key.exponent, rom_ext_pub_key.modulus, message, bytes, 77 | signature.value, RSA_SIZE, manifest); 78 | 79 | return result; // 0 or 1 80 | } 81 | 82 | int __is_valid_params(int32_t exponent, int32_t *modulus, char *message, 83 | int message_len, int32_t *signature, int signature_len, 84 | rom_ext_manifest_t __current_rom_ext_mf) { 85 | 86 | if (exponent != __current_rom_ext_mf.pub_signature_key.exponent) 87 | return 0; 88 | 89 | if (cmp_modulus(modulus, __current_rom_ext_mf.pub_signature_key.modulus, 90 | RSA_SIZE * sizeof(int32_t)) != 0) 91 | return 0; 92 | 93 | if (cmp_signature(signature, __current_rom_ext_mf.signature.value, 94 | RSA_SIZE * sizeof(int32_t)) != 0) 95 | return 0; 96 | 97 | // Message is: pkey+image_length+image_code 98 | if (cmp_key(message, &__current_rom_ext_mf.pub_signature_key, 99 | sizeof(__current_rom_ext_mf.pub_signature_key)) != 0) 100 | return 0; 101 | 102 | if (cmp_image_len(message + sizeof(__current_rom_ext_mf.pub_signature_key), 103 | &__current_rom_ext_mf.image_length, 104 | sizeof(__current_rom_ext_mf.image_length)) != 0) 105 | return 0; 106 | 107 | if (cmp_image_code(message + sizeof(__current_rom_ext_mf.pub_signature_key) + 108 | sizeof(__current_rom_ext_mf.image_length), 109 | __current_rom_ext_mf.image_code, 110 | __current_rom_ext_mf.image_length) != 0) 111 | return 0; 112 | 113 | return 1; 114 | } 115 | 116 | char *OTBN_RSA_3072_DECRYPT(int32_t *signature, int signature_len, 117 | int32_t exponent, int32_t *modulus) { 118 | char *decrypt = malloc(256 / 8); // Model it to be ok for PROPERTY 5 119 | return decrypt; 120 | } 121 | 122 | int OTBN_RSASSA_PKCS1_V1_5_VERIFY(int32_t exponent, int32_t *modulus, 123 | char *message, int message_len, 124 | int32_t *signature, int signature_len, 125 | rom_ext_manifest_t __current_rom_ext_mf) { 126 | __CPROVER_assert(__CPROVER_OBJECT_SIZE(message) == message_len, 127 | "PROPERTY 5: Formal parameter message_len length matches " 128 | "actual message length."); 129 | __CPROVER_assert(__CPROVER_OBJECT_SIZE(signature) == 3072 / 8, 130 | "PROPERTY 5: Signature to be verified is 3072-bits."); 131 | __CPROVER_assert(__CPROVER_OBJECT_SIZE(signature) == 132 | signature_len * sizeof(int32_t), 133 | "PROPERTY 5: Formal parameter signature length matches " 134 | "actual signature length."); 135 | __CPROVER_assert(sizeof(exponent) == 32 / 8, 136 | "PROPERTY 5: Public key exponent is 32 bits."); 137 | __CPROVER_assert((sizeof(pub_key_t) - sizeof(exponent)) == 3072 / 8, 138 | "PROPERTY 5: Public key modulus is 3072-bits."); 139 | __CPROVER_assert(__is_valid_params(exponent, modulus, message, message_len, 140 | signature, signature_len, 141 | __current_rom_ext_mf), 142 | "PROPERTY 5: Check that key, signature, and message match " 143 | "those from the manifest."); 144 | 145 | __REACHABILITY_CHECK 146 | 147 | if (signature_len != RSA_SIZE) { 148 | __CPROVER_assert(signature_len * 32 != 3072, 149 | "PROPERTY 5: Length checking: If the length of the " 150 | "signature is not 3072-bits, stop."); 151 | __REACHABILITY_CHECK // Not reachable atm 152 | 153 | return 0; 154 | } 155 | __REACHABILITY_CHECK 156 | 157 | char *decrypt = 158 | OTBN_RSA_3072_DECRYPT(signature, signature_len, exponent, modulus); 159 | char *hash = HMAC_SHA2_256(__hmac_key, message, message_len, 160 | __current_rom_ext_mf); // message_len in bytes 161 | 162 | __CPROVER_assert( 163 | !__CPROVER_array_equal(decrypt, signature), 164 | "PROPERTY 5: Decrypted signature is different from signature"); 165 | __CPROVER_assert(!__CPROVER_array_equal(hash, message), 166 | "PROPERTY 5: Hash is different from original message"); 167 | __CPROVER_assert(__CPROVER_OBJECT_SIZE(decrypt) == 256 / 8, 168 | "PROPERTY 5: Decrypted message is 256 bits"); 169 | __CPROVER_assert(__CPROVER_r_ok(decrypt, 256 / 8), 170 | "PROPERTY 5: Decrypted message is in readable address"); 171 | __CPROVER_assert(__CPROVER_OBJECT_SIZE(hash) == 256 / 8, 172 | "PROPERTY 3: Hash is 256 bits"); 173 | __CPROVER_assert(__CPROVER_r_ok(hash, 256 / 8), 174 | "PROPERTY 3: hash is in readable address"); 175 | 176 | if (cmp_hash_decrypt(hash, decrypt, 256 / 8) == 0) { 177 | __valid_signature[__current_rom_ext] = 1; 178 | return 1; // verified 179 | } else { 180 | __valid_signature[__current_rom_ext] = 0; 181 | return 0; 182 | } 183 | } 184 | 185 | boot_policy_t FLASH_CTRL_read_boot_policy() {} 186 | 187 | rom_exts_manifests_t 188 | FLASH_CTRL_rom_ext_manifests_to_try(boot_policy_t boot_policy) {} 189 | 190 | pub_key_t read_pub_key(rom_ext_manifest_t current_rom_ext_manifest) { 191 | return current_rom_ext_manifest.pub_signature_key; 192 | } 193 | 194 | // Mocked function for reading pkey whitelist from maskrom. 195 | pub_key_t *ROM_CTRL_get_whitelist() { return __pkey_whitelist; } 196 | 197 | extern int check_pub_key_valid(pub_key_t rom_ext_pub_key) { 198 | pub_key_t *pkey_whitelist = ROM_CTRL_get_whitelist(); 199 | 200 | for (int i = 0; i < __PKEY_WHITELIST_SIZE; i++) { 201 | if (pkey_whitelist[i].exponent != rom_ext_pub_key.exponent) 202 | continue; 203 | 204 | int j = 0; 205 | for (j = 0; j < RSA_SIZE; j++) { 206 | if (pkey_whitelist[i].modulus[j] != rom_ext_pub_key.modulus[j]) 207 | break; 208 | } 209 | 210 | // if j == RSA_SIZE, then loop ran to completion and all entries were equal 211 | if (j == RSA_SIZE) 212 | return 1; 213 | } 214 | 215 | return 0; 216 | } 217 | 218 | extern void PMP_WRITE_REGION(uint8_t reg, uint8_t r, uint8_t w, uint8_t e, 219 | uint8_t l) { 220 | __REACHABILITY_CHECK 221 | } 222 | 223 | void PMP_unlock_rom_ext() { 224 | // Read, Execute, Locked the address space of the ROM extension image 225 | PMP_WRITE_REGION(0, 1, 0, 1, 1); 226 | // Region Read Write Execute Locked 227 | __register_pmp_region(__current_rom_ext, 0, 1, 0, 1, 1); 228 | __REACHABILITY_CHECK 229 | } 230 | 231 | void PMP_enable_memory_protection() { 232 | // Apply PMP region 15 to cover entire flash 233 | PMP_WRITE_REGION(15, 1, 0, 0, 1); 234 | // Region Read Write Execute Locked 235 | __register_pmp_region(-1, 15, 1, 0, 0, 1); 236 | __REACHABILITY_CHECK 237 | } 238 | 239 | void __register_pmp_region(int rom_ext, int pmp_id, int r, int w, int e, 240 | int l) { 241 | if (rom_ext == -1) { 242 | // register PMP region for all rom exts. 243 | for (int i = 0; i < MAX_ROM_EXTS; i++) { 244 | __rom_ext_pmp_region[i].pmp_regions[pmp_id].identifier = pmp_id; 245 | __rom_ext_pmp_region[i].pmp_regions[pmp_id].R = r; 246 | __rom_ext_pmp_region[i].pmp_regions[pmp_id].W = w; 247 | __rom_ext_pmp_region[i].pmp_regions[pmp_id].E = e; 248 | __rom_ext_pmp_region[i].pmp_regions[pmp_id].L = l; 249 | } 250 | } else { 251 | __rom_ext_pmp_region[rom_ext].pmp_regions[pmp_id].identifier = pmp_id; 252 | __rom_ext_pmp_region[rom_ext].pmp_regions[pmp_id].R = r; 253 | __rom_ext_pmp_region[rom_ext].pmp_regions[pmp_id].W = w; 254 | __rom_ext_pmp_region[rom_ext].pmp_regions[pmp_id].E = e; 255 | __rom_ext_pmp_region[rom_ext].pmp_regions[pmp_id].L = l; 256 | } 257 | } 258 | 259 | void __some_entry_func() { __rom_ext_called[__current_rom_ext] = 1; } 260 | 261 | int final_jump_to_rom_ext(rom_ext_manifest_t current_rom_ext_manifest) { 262 | current_rom_ext_manifest.image_code = &__some_entry_func; 263 | rom_ext_boot_func *rom_ext_entry = 264 | (rom_ext_boot_func *)current_rom_ext_manifest.image_code; 265 | 266 | __CPROVER_assert(rom_ext_entry == current_rom_ext_manifest.image_code, 267 | "PROPERTY 6: Correct entry point address."); 268 | 269 | __REACHABILITY_CHECK 270 | 271 | rom_ext_entry(); 272 | 273 | __rom_ext_returned[__current_rom_ext] = 1; 274 | 275 | return 0; 276 | } 277 | 278 | void boot_failed(boot_policy_t boot_policy) { 279 | __REACHABILITY_CHECK 280 | fail_func *fail_func_entry = (fail_func *)boot_policy.fail; 281 | fail_func_entry(); 282 | } 283 | 284 | void boot_failed_rom_ext_terminated( 285 | boot_policy_t boot_policy, rom_ext_manifest_t current_rom_ext_manifest) { 286 | __REACHABILITY_CHECK 287 | fail_rom_ext_terminated_func *fail_func_entry = 288 | (fail_rom_ext_terminated_func *)boot_policy.fail_rom_ext_terminated; 289 | fail_func_entry(current_rom_ext_manifest); 290 | } 291 | 292 | int check_rom_ext_manifest(rom_ext_manifest_t manifest) { 293 | if (manifest.identifier == 0) 294 | return 0; 295 | for (int i = 0; i < RSA_SIZE; i++) { 296 | if (manifest.signature.value[i] != 0) 297 | return 1; 298 | } 299 | return 0; 300 | } 301 | 302 | int __help_check_rom_ext_manifest(rom_ext_manifest_t manifest) { 303 | if (manifest.identifier == 0) 304 | return 0; 305 | 306 | signature_t signature = manifest.signature; 307 | 308 | if (__CPROVER_OBJECT_SIZE(signature.value) != 3072 / 8) 309 | return 0; 310 | 311 | for (int i = 0; i < RSA_SIZE; i++) { 312 | if (manifest.signature.value[i] != 0) 313 | return 1; 314 | } 315 | return 0; 316 | } 317 | 318 | int __help_pkey_valid(pub_key_t pkey) { 319 | if (sizeof(pkey.exponent) * 8 != 32) 320 | return 0; 321 | 322 | if ((sizeof(pkey) - sizeof(pkey.exponent)) * 8 != 3072) 323 | return 0; 324 | 325 | pub_key_t *pkey_whitelist = ROM_CTRL_get_whitelist(); 326 | 327 | for (int i = 0; i < __PKEY_WHITELIST_SIZE; i++) { 328 | if (pkey_whitelist[i].exponent != pkey.exponent) 329 | continue; 330 | 331 | int j = 0; 332 | for (j = 0; j < RSA_SIZE; j++) { 333 | if (pkey_whitelist[i].modulus[j] != pkey.modulus[j]) 334 | break; 335 | } 336 | 337 | if (j == RSA_SIZE) 338 | return 1; 339 | } 340 | 341 | return 0; 342 | } 343 | 344 | int __help_check_pmp_region(int rom_ext, int pmp_id, int r, int w, int e, 345 | int l) { 346 | if (rom_ext == -1) { 347 | for (int i = 0; i < MAX_ROM_EXTS; i++) { 348 | if (__rom_ext_pmp_region[i].pmp_regions[pmp_id].R != r || 349 | __rom_ext_pmp_region[i].pmp_regions[pmp_id].W != w || 350 | __rom_ext_pmp_region[i].pmp_regions[pmp_id].E != e || 351 | __rom_ext_pmp_region[i].pmp_regions[pmp_id].L != l) 352 | return 0; 353 | } 354 | return 1; 355 | } else { 356 | return __rom_ext_pmp_region[rom_ext].pmp_regions[pmp_id].R == r && 357 | __rom_ext_pmp_region[rom_ext].pmp_regions[pmp_id].W == w && 358 | __rom_ext_pmp_region[rom_ext].pmp_regions[pmp_id].E == e && 359 | __rom_ext_pmp_region[rom_ext].pmp_regions[pmp_id].L == l; 360 | } 361 | } 362 | 363 | int __help_all_pmp_inactive() { 364 | for (int i = 0; i < MAX_ROM_EXTS; i++) { 365 | for (int j = 0; j < PMP_REGIONS; j++) { 366 | if (__rom_ext_pmp_region[i].pmp_regions[j].R != 0 || 367 | __rom_ext_pmp_region[i].pmp_regions[j].W != 0 || 368 | __rom_ext_pmp_region[i].pmp_regions[j].E != 0 || 369 | __rom_ext_pmp_region[i].pmp_regions[j].L != 0) 370 | return 0; 371 | } 372 | } 373 | return 1; 374 | } 375 | 376 | void __func_fail() { __boot_failed_called[__current_rom_ext] = 1; } 377 | void __func_fail_rom_ext(rom_ext_manifest_t _) { 378 | __rom_ext_fail_func[__current_rom_ext] = 1; 379 | } 380 | 381 | void PROOF_HARNESS() { 382 | boot_policy_t boot_policy = FLASH_CTRL_read_boot_policy(); 383 | rom_exts_manifests_t rom_exts_to_try = 384 | FLASH_CTRL_rom_ext_manifests_to_try(boot_policy); 385 | 386 | __CPROVER_assume(rom_exts_to_try.size <= MAX_ROM_EXTS && 387 | rom_exts_to_try.size > 0); 388 | 389 | __CPROVER_assume(boot_policy.fail == &__func_fail); 390 | __CPROVER_assume(boot_policy.fail_rom_ext_terminated == &__func_fail_rom_ext); 391 | 392 | for (int i = 0; i < rom_exts_to_try.size; i++) { 393 | __CPROVER_assume(MAX_IMAGE_LENGTH >= 394 | rom_exts_to_try.rom_exts_mfs[i].image_length && 395 | rom_exts_to_try.rom_exts_mfs[i].image_length > 0); 396 | rom_exts_to_try.rom_exts_mfs[i].image_code = 397 | malloc(sizeof(char) * rom_exts_to_try.rom_exts_mfs[i].image_length); 398 | } 399 | 400 | mask_rom_boot(boot_policy, rom_exts_to_try); 401 | 402 | __CPROVER_postcondition( 403 | __current_rom_ext + 1 <= rom_exts_to_try.size, 404 | "Postcondition: Should never check more rom_ext than there exist"); 405 | 406 | for (int i = 0; i < rom_exts_to_try.size; i++) { 407 | 408 | __CPROVER_postcondition( 409 | __imply( 410 | !__help_check_rom_ext_manifest(rom_exts_to_try.rom_exts_mfs[i]) || 411 | !__help_pkey_valid( 412 | rom_exts_to_try.rom_exts_mfs[i].pub_signature_key), 413 | !__verify_signature_called[i]), 414 | "Postcondition PROPERTY 5: If identifier, sign, or key is invalid then " 415 | "verify signature function is not called"); 416 | 417 | __CPROVER_postcondition( 418 | __imply( 419 | __help_check_rom_ext_manifest(rom_exts_to_try.rom_exts_mfs[i]) && 420 | __help_pkey_valid( 421 | rom_exts_to_try.rom_exts_mfs[i].pub_signature_key), 422 | __verify_signature_called[i]), 423 | "Postcondition PROPERTY 5: If identifier, sign, and key are valid then " 424 | "the signature verification function is called"); 425 | 426 | if (__validated_rom_exts[i]) { 427 | __REACHABILITY_CHECK 428 | 429 | __CPROVER_postcondition( 430 | __help_check_rom_ext_manifest(rom_exts_to_try.rom_exts_mfs[i]), 431 | "Postcondition PROPERTY 1: rom_ext VALIDATED => valid signature"); 432 | 433 | __CPROVER_postcondition( 434 | __help_pkey_valid(rom_exts_to_try.rom_exts_mfs[i].pub_signature_key), 435 | "Postcondition PROPERTY 2: rom_ext VALIDATED => valid key"); 436 | 437 | __CPROVER_postcondition(__verify_signature_called[i], 438 | "Postcondition PROPERTY 5: iff manifest is valid " 439 | "then verify signature function is called"); 440 | 441 | __CPROVER_postcondition( 442 | __valid_signature[i], 443 | "Postcondition PROPERTY 5: rom_ext VALIDATED => signature valid"); 444 | 445 | __CPROVER_postcondition(__rom_ext_called[i], 446 | "Postcondition PROPERTY 6: rom_ext VALIDATED => " 447 | "rom ext code initiated"); 448 | 449 | __CPROVER_postcondition( 450 | __imply(__rom_ext_returned[i], __rom_ext_fail_func[i]), 451 | "Postcondition PROPERTY 6: (valid rom_ext and rom_ext code return) " 452 | "=> that rom_ext term func is called"); 453 | 454 | __CPROVER_postcondition( 455 | __imply(!__rom_ext_returned[i], !__rom_ext_fail_func[i]), 456 | "Postcondition PROPERTY 6: (valid rom_ext and rom_ext code !return) " 457 | "=> that rom_ext term func not called"); 458 | 459 | __CPROVER_postcondition(__help_check_pmp_region(i, 15, 1, 0, 0, 1), 460 | "Postcondition PROPERTY 9: PMP region 15 should " 461 | "be R and L, when rom_ext was validated."); 462 | 463 | __CPROVER_postcondition( 464 | __help_check_pmp_region(i, 0, 1, 0, 1, 1), 465 | "Postcondition PROPERTY 10: If rom_ext was validated, then PMP " 466 | "region 0 should be R, E, and L."); 467 | } else { 468 | __REACHABILITY_CHECK 469 | 470 | __CPROVER_postcondition( 471 | !__help_check_rom_ext_manifest(rom_exts_to_try.rom_exts_mfs[i]) || 472 | !__help_pkey_valid( 473 | rom_exts_to_try.rom_exts_mfs[i].pub_signature_key) || 474 | !__valid_signature[i], 475 | "Postcondition: rom_ext INVALIDATED => identifier, signature, or key " 476 | "is invalid"); 477 | 478 | __CPROVER_postcondition(!__valid_signature[i], 479 | "Postcondition PROPERTY 5: rom_ext INVALIDATED " 480 | "=> signature invalid or not checked"); 481 | 482 | __CPROVER_postcondition(!__rom_ext_fail_func[i], 483 | "Postcondition PROPERTY 6: invalid rom_ext => " 484 | "that rom_ext term func not called"); 485 | 486 | __CPROVER_postcondition(!__rom_ext_called[i], 487 | "Postcondition PROPERTY 7: rom_ext INVALIDATED " 488 | "=> rom ext code not executed"); 489 | 490 | __CPROVER_postcondition( 491 | __current_rom_ext > i || (i + 1) == rom_exts_to_try.size || 492 | __boot_policy_stop, 493 | "Postcondition PROPERTY 7: rom_ext INVALIDATED => we check the next " 494 | "rom_ext if any left and no boot policy instructed stop"); 495 | 496 | __CPROVER_postcondition( 497 | __imply(i < __current_rom_ext, !__boot_failed_called[i]), 498 | "Postcondition PROPERTY 8: A rom_ext (not the last one) fails => " 499 | "fail func is not called"); 500 | 501 | __CPROVER_postcondition( 502 | __imply(i == __current_rom_ext, __boot_failed_called[i]), 503 | "Postcondition PROPERTY 8: Last rom_ext fail => fail func has been " 504 | "called"); 505 | 506 | __CPROVER_postcondition(__help_check_pmp_region(i, 15, 1, 0, 0, 1), 507 | "Postcondition PROPERTY 9: PMP region 15 should " 508 | "be R and L. Even if rom_ext was invalidated."); 509 | 510 | __CPROVER_postcondition( 511 | __help_check_pmp_region(i, 0, 0, 0, 0, 0), 512 | "Postcondition PROPERTY 10: If rom_ext was invalid, PMP region 0 " 513 | "should not be R, E, W, and L."); 514 | } 515 | } 516 | __REACHABILITY_CHECK 517 | } 518 | 519 | void mask_rom_boot(boot_policy_t boot_policy, 520 | rom_exts_manifests_t rom_exts_to_try) { 521 | __CPROVER_precondition(rom_exts_to_try.size <= MAX_ROM_EXTS && 522 | rom_exts_to_try.size > 0, 523 | "Precondition: Assumes MAX_ROM_EXTS >= rom_exts > 0"); 524 | 525 | __CPROVER_precondition( 526 | boot_policy.fail == &__func_fail, 527 | "Precondition: Assumes boot_policy.fail has ok address"); 528 | 529 | __CPROVER_precondition(boot_policy.fail_rom_ext_terminated == 530 | &__func_fail_rom_ext, 531 | "Precondition: Assumes " 532 | "boot_policy.fail_rom_ext_terminated has ok address"); 533 | 534 | __CPROVER_precondition(__help_all_pmp_inactive(), 535 | "Precondition PROPERTY 9: All PMP regions should be " 536 | "unset at beginning of mask_rom."); 537 | 538 | PMP_enable_memory_protection(); 539 | 540 | for (int i = 0; i < rom_exts_to_try.size; i++) { 541 | __CPROVER_assert(__help_check_pmp_region(i, 15, 1, 0, 0, 1), 542 | "PROPERTY 9: PMP region 15 should be R and L."); 543 | 544 | __current_rom_ext = i; 545 | rom_ext_manifest_t current_rom_ext_manifest = 546 | rom_exts_to_try.rom_exts_mfs[i]; 547 | 548 | signature_t __signature = current_rom_ext_manifest.signature; 549 | 550 | if (!check_rom_ext_manifest(current_rom_ext_manifest)) { 551 | __REACHABILITY_CHECK 552 | __CPROVER_assert(!__help_check_rom_ext_manifest(current_rom_ext_manifest), 553 | "PROPERTY 1: Stop verification if signature or " 554 | "identifier is invalid"); 555 | continue; 556 | } 557 | 558 | __REACHABILITY_CHECK 559 | __CPROVER_assert(__help_check_rom_ext_manifest(current_rom_ext_manifest), 560 | "PROPERTY 1: Continue verification if signature and " 561 | "identifier are valid"); 562 | 563 | pub_key_t rom_ext_pub_key = read_pub_key(current_rom_ext_manifest); 564 | 565 | if (!check_pub_key_valid(rom_ext_pub_key)) { 566 | __REACHABILITY_CHECK 567 | __CPROVER_assert(!__help_pkey_valid(rom_ext_pub_key), 568 | "PROPERTY 2: Stop verification if key is invalid"); 569 | continue; 570 | } 571 | 572 | __REACHABILITY_CHECK 573 | __CPROVER_assert(__help_pkey_valid(rom_ext_pub_key), 574 | "PROPERTY 2: Continue verification if key is valid"); 575 | 576 | if (!verify_rom_ext_signature(rom_ext_pub_key, current_rom_ext_manifest)) { 577 | __REACHABILITY_CHECK 578 | __CPROVER_assert(!__valid_signature[i], 579 | "PROPERTY 5: Stop verification if signature is invalid"); 580 | continue; 581 | } 582 | __REACHABILITY_CHECK 583 | __CPROVER_assert(__valid_signature[i], 584 | "PROPERTY 5: Continue verification if signature is valid"); 585 | __validated_rom_exts[i] = 1; 586 | 587 | PMP_unlock_rom_ext(); 588 | 589 | __CPROVER_assert(__help_check_pmp_region(i, 0, 1, 0, 1, 1), 590 | "PROPERTY 10: PMP region 0 should be R, E, and L."); 591 | 592 | if (!final_jump_to_rom_ext(current_rom_ext_manifest)) { 593 | __REACHABILITY_CHECK 594 | 595 | boot_failed_rom_ext_terminated(boot_policy, current_rom_ext_manifest); 596 | __boot_policy_stop = 1; 597 | return; 598 | } 599 | } 600 | 601 | __REACHABILITY_CHECK 602 | boot_failed(boot_policy); 603 | } 604 | --------------------------------------------------------------------------------