[sw/silicon_creator] Harden boot_data_digest_is_valid using shares

Signed-off-by: Alphan Ulusoy <alphan@google.com>
diff --git a/sw/device/silicon_creator/lib/boot_data.c b/sw/device/silicon_creator/lib/boot_data.c
index 54076a4..cd9438f 100644
--- a/sw/device/silicon_creator/lib/boot_data.c
+++ b/sw/device/silicon_creator/lib/boot_data.c
@@ -73,24 +73,48 @@
 }
 
 /**
+ * Shares for producing the `is_valid` value in `boot_data_digest_check()`.
+ * First 7 shares are generated using the `sparse-fsm-encode` script while the
+ * last share is `kHardenedBoolTrue ^ kHardenedBoolFalse ^ kDigestShares[0] ^
+ * ... ^ kDigestShares[7]` so that xor'ing all shares with the initial value of
+ * `is_valid`, i.e. `kHardenedBoolFalse`, produces `kHardenedBoolTrue`.
+ *
+ * Encoding generated with
+ * $ ./util/design/sparse-fsm-encode.py -d 6 -m 7 -n 32 \
+ *     -s 266012770 --language=c
+ *
+ * Minimum hamming distance: 12
+ * Maximum hamming distance: 19
+ * Minimum hamming weight: 14
+ * Maximum hamming weight: 23
+ */
+static const uint32_t kDigestShares[kHmacDigestNumWords] = {
+    0x0d0b4d17, 0xcd73e3ff, 0x07a6f2f4, 0xcedfd599,
+    0x54eac5b2, 0x0723ff0a, 0x6e234ee1, 0x34ebfb31,
+};
+
+/**
  * Checks whether the digest of a boot data entry is valid.
  *
  * @param boot_data A buffer that holds a boot data entry.
- * @param[out] is_valid Whether the digest of the entry is valid.
- * @return The result of the operation.
+ * @return Whether the digest of the entry is valid.
  */
-static rom_error_t boot_data_digest_is_valid(
-    const boot_data_buffer_t *boot_data, hardened_bool_t *is_valid) {
+static hardened_bool_t boot_data_digest_is_valid(
+    const boot_data_buffer_t *boot_data) {
   static_assert(offsetof(boot_data_t, digest) == 0,
                 "`digest` must be the first field of `boot_data_t`.");
 
-  *is_valid = kHardenedBoolFalse;
+  hardened_bool_t is_valid = kHardenedBoolFalse;
   hmac_digest_t act_digest;
   boot_data_digest_compute(boot_data, &act_digest);
-  if (memcmp(&act_digest, boot_data, sizeof(act_digest.digest)) == 0) {
-    *is_valid = kHardenedBoolTrue;
+
+  size_t i = 0;
+  for (; launder32(i) < kHmacDigestNumWords; ++i) {
+    is_valid ^= boot_data->data[i] ^ act_digest.digest[i] ^ kDigestShares[i];
   }
-  return kErrorOk;
+  HARDENED_CHECK_EQ(i, kHmacDigestNumWords);
+
+  return is_valid;
 }
 
 /**
@@ -362,10 +386,8 @@
   for (size_t i = start_index; i < kBootDataEntriesPerPage; --i) {
     // Check the digest only if this entry can be valid.
     if (sniff_results[i] == kBootDataIdentifier) {
-      hardened_bool_t is_valid;
       RETURN_IF_ERROR(boot_data_entry_read(page, i, &buf));
-      RETURN_IF_ERROR(boot_data_digest_is_valid(&buf, &is_valid));
-      if (is_valid == kHardenedBoolTrue) {
+      if (boot_data_digest_is_valid(&buf) == kHardenedBoolTrue) {
         memcpy(&page_info->last_valid_entry, &buf, sizeof(boot_data_t));
         page_info->last_valid_index = i;
         page_info->has_valid_entry = kHardenedBoolTrue;