[sw/silicon_creator] Read usage constraints from hardware during ROM_EXT verification Fixes #5956. Signed-off-by: Alphan Ulusoy <alphan@google.com>
diff --git a/sw/device/silicon_creator/lib/manifest.c b/sw/device/silicon_creator/lib/manifest.c index aead7c2..3bbfcff 100644 --- a/sw/device/silicon_creator/lib/manifest.c +++ b/sw/device/silicon_creator/lib/manifest.c
@@ -6,7 +6,7 @@ // Extern declarations for the inline functions in the manifest header. extern rom_error_t manifest_check(const manifest_t *manifest); -extern manifest_signed_region_t manifest_signed_region_get( +extern manifest_digest_region_t manifest_digest_region_get( const manifest_t *manifest); extern epmp_region_t manifest_code_region_get(const manifest_t *manifest); extern uintptr_t manifest_entry_point_get(const manifest_t *manifest);
diff --git a/sw/device/silicon_creator/lib/manifest.h b/sw/device/silicon_creator/lib/manifest.h index bf774b8..e1ab6c0 100644 --- a/sw/device/silicon_creator/lib/manifest.h +++ b/sw/device/silicon_creator/lib/manifest.h
@@ -125,9 +125,19 @@ * * RSASSA-PKCS1-v1_5 signature of the image generated using a 3072-bit RSA * private key and the SHA-256 hash function. The signed region of an image - * starts immediately after this field and ends at the end of the image. The - * start and the length of the signed region can be obtained using - * `manifest_signed_region_get`. + * starts immediately after this field and ends at the end of the image. + * + * On-target verification should also integrate usage constraints comparison + * to signature verification to harden it against potential attacks. During + * verification, the digest of an image should be computed by first reading + * the usage constraints from the hardware and then concatenating the rest of + * the image: + * + * digest = SHA256(usage_constraints_from_hw || rest_of_the_image) + * + * The start and the length of the region that should be concatenated to the + * usage constraints read from the hardware can be obtained using + * `manifest_digest_region_get()`. */ sigverify_rsa_buffer_t signature; /** @@ -219,18 +229,18 @@ OT_ASSERT_SIZE(manifest_t, MANIFEST_SIZE); /** - * Signed region of an image. + * Region of an image that should be included in the digest computation. */ -typedef struct manifest_signed_region { +typedef struct manifest_digest_region { /** - * Start of the signed region of an image. + * Start of the region. */ const void *start; /** - * Length of the signed region of an image in bytes. + * Length of the region in bytes. */ size_t length; -} manifest_signed_region_t; +} manifest_digest_region_t; /** * Allowed bounds for the `length` field. @@ -279,16 +289,25 @@ } /** - * Gets the signed region of an image. + * Gets the region of the image that should be included in the digest + * computation. * - * @param manifest A manifest - * return signed_region Signed region of an image. + * Digest region of an image starts immediately after the `usage_constraints` + * field of its manifest and ends at the end of the image. + * + * @param manifest A manifest. + * return digest_region Region of the image that should be included in the + * digest computation. */ -inline manifest_signed_region_t manifest_signed_region_get( +inline manifest_digest_region_t manifest_digest_region_get( const manifest_t *manifest) { - return (manifest_signed_region_t){ - .start = (const char *)manifest + sizeof(manifest->signature), - .length = manifest->length - sizeof(manifest->signature), + enum { + kDigestRegionOffset = + sizeof(manifest->signature) + sizeof(manifest->usage_constraints), + }; + return (manifest_digest_region_t){ + .start = (const char *)manifest + kDigestRegionOffset, + .length = manifest->length - kDigestRegionOffset, }; } @@ -324,7 +343,7 @@ * Declarations for the functions above that should be defined in tests. */ rom_error_t manifest_check(const manifest_t *manifest); -manifest_signed_region_t manifest_signed_region_get(const manifest_t *manifest); +manifest_digest_region_t manifest_digest_region_get(const manifest_t *manifest); epmp_region_t manifest_code_region_get(const manifest_t *manifest); uintptr_t manifest_entry_point_get(const manifest_t *manifest); #endif
diff --git a/sw/device/silicon_creator/lib/manifest_unittest.cc b/sw/device/silicon_creator/lib/manifest_unittest.cc index b2824dc..010de21 100644 --- a/sw/device/silicon_creator/lib/manifest_unittest.cc +++ b/sw/device/silicon_creator/lib/manifest_unittest.cc
@@ -22,15 +22,17 @@ manifest_t manifest_{}; }; -TEST_F(ManifestTest, SignedRegionGet) { - manifest_signed_region_t signed_region = - manifest_signed_region_get(&manifest_); +TEST_F(ManifestTest, DigestRegionGet) { + manifest_digest_region_t digest_region = + manifest_digest_region_get(&manifest_); - // Signed region starts after `signature` and ends at the end of the image. - EXPECT_EQ(signed_region.start, reinterpret_cast<const char *>(&manifest_) + - sizeof(manifest_t::signature)); - EXPECT_EQ(signed_region.length, - manifest_.length - sizeof(manifest_t::signature)); + // Digest region starts immediately after `usage_constraints` and ends at the + // end of the image. + size_t digest_region_offset = + sizeof(manifest_t::signature) + sizeof(manifest_t::usage_constraints); + EXPECT_EQ(digest_region.start, + reinterpret_cast<const char *>(&manifest_) + digest_region_offset); + EXPECT_EQ(digest_region.length, manifest_.length - digest_region_offset); } TEST_F(ManifestTest, CodeRegionGet) {
diff --git a/sw/device/silicon_creator/lib/mock_manifest.h b/sw/device/silicon_creator/lib/mock_manifest.h index 40be0cb..821e4ee 100644 --- a/sw/device/silicon_creator/lib/mock_manifest.h +++ b/sw/device/silicon_creator/lib/mock_manifest.h
@@ -17,7 +17,7 @@ class MockManifest : public GlobalMock<MockManifest> { public: MOCK_METHOD(rom_error_t, Check, (const manifest_t *)); - MOCK_METHOD(manifest_signed_region_t, SignedRegion, (const manifest_t *)); + MOCK_METHOD(manifest_digest_region_t, DigestRegion, (const manifest_t *)); MOCK_METHOD(epmp_region_t, CodeRegion, (const manifest_t *)); MOCK_METHOD(uintptr_t, EntryPoint, (const manifest_t *)); }; @@ -32,9 +32,9 @@ return MockManifest::Instance().Check(manifest); } -manifest_signed_region_t manifest_signed_region_get( +manifest_digest_region_t manifest_digest_region_get( const manifest_t *manifest) { - return MockManifest::Instance().SignedRegion(manifest); + return MockManifest::Instance().DigestRegion(manifest); } epmp_region_t manifest_code_region_get(const manifest_t *manifest) {
diff --git a/sw/device/silicon_creator/mask_rom/mask_rom.c b/sw/device/silicon_creator/mask_rom/mask_rom.c index 3a96741..0e60ea4 100644 --- a/sw/device/silicon_creator/mask_rom/mask_rom.c +++ b/sw/device/silicon_creator/mask_rom/mask_rom.c
@@ -110,11 +110,18 @@ RETURN_IF_ERROR(sigverify_rsa_key_get( sigverify_rsa_key_id_get(&manifest->modulus), lc_state, &key)); - // TODO(#5956): Manifest usage constraints. - manifest_signed_region_t signed_region = manifest_signed_region_get(manifest); hmac_sha256_init(); + // Hash usage constraints. + manifest_usage_constraints_t usage_constraints_from_hw; + sigverify_usage_constraints_get(manifest->usage_constraints.selector_bits, + &usage_constraints_from_hw); + RETURN_IF_ERROR(hmac_sha256_update(&usage_constraints_from_hw, + sizeof(usage_constraints_from_hw))); + // Hash the remaining part of the image. + manifest_digest_region_t digest_region = manifest_digest_region_get(manifest); RETURN_IF_ERROR( - hmac_sha256_update(signed_region.start, signed_region.length)); + hmac_sha256_update(digest_region.start, digest_region.length)); + // Verify signature hmac_digest_t act_digest; RETURN_IF_ERROR(hmac_sha256_final(&act_digest)); RETURN_IF_ERROR(