Don't read beyond end of BccHandover

Check that there are still map entries remaining before trying to read
further entries. Allow, but ignore, unknown entries for forward
compatibility.

Change-Id: I71be0b480c83d65ddb3cb5a087e0586fb817ae02
Reviewed-on: https://pigweed-review.googlesource.com/c/open-dice/+/93560
Reviewed-by: Hasini Gunasinghe <hasinitg@google.com>
Commit-Queue: Darren Krahn <dkrahn@google.com>
Reviewed-by: Darren Krahn <dkrahn@google.com>
diff --git a/src/android/bcc.c b/src/android/bcc.c
index 8855f71..d58e80a 100644
--- a/src/android/bcc.c
+++ b/src/android/bcc.c
@@ -215,9 +215,10 @@
   // }
   struct CborIn in;
   int64_t label;
+  size_t num_pairs;
   size_t item_size;
   CborInInit(bcc_handover, bcc_handover_size, &in);
-  if (CborReadMap(&in, &item_size) != CBOR_READ_RESULT_OK || item_size < 2 ||
+  if (CborReadMap(&in, &num_pairs) != CBOR_READ_RESULT_OK || num_pairs < 2 ||
       // Read the attestation CDI.
       CborReadInt(&in, &label) != CBOR_READ_RESULT_OK ||
       label != kCdiAttestLabel ||
@@ -233,17 +234,16 @@
   }
 
   size_t bcc_size = 0;
-  // Calculate the BCC size, if the BCC is present in the BccHandover.
-  if (CborReadInt(&in, &label) == CBOR_READ_RESULT_OK) {
-    if (label != kBccLabel) {
-      return kDiceResultInvalidInput;
+  if (num_pairs >= 3 && CborReadInt(&in, &label) == CBOR_READ_RESULT_OK) {
+    if (label == kBccLabel) {
+      // Calculate the BCC size, if the BCC is present in the BccHandover.
+      size_t bcc_start = CborInOffset(&in);
+      if (CborReadSkip(&in) != CBOR_READ_RESULT_OK) {
+        return kDiceResultInvalidInput;
+      }
+      bcc = bcc_handover + bcc_start;
+      bcc_size = CborInOffset(&in) - bcc_start;
     }
-    size_t bcc_start = CborInOffset(&in);
-    bcc = bcc_handover + bcc_start;
-    if (CborReadSkip(&in) != CBOR_READ_RESULT_OK) {
-      return kDiceResultInvalidInput;
-    }
-    bcc_size = CborInOffset(&in) - bcc_start;
   }
 
   // Write the new handover data.
diff --git a/src/android/bcc_test.cc b/src/android/bcc_test.cc
index 44dce5b..397eee7 100644
--- a/src/android/bcc_test.cc
+++ b/src/android/bcc_test.cc
@@ -115,7 +115,7 @@
                       sizeof(bcc_handover) - 8 - 73));
 }
 
-TEST(BccHandoverNoCertTest, InHandoverWithoutBccOutHandoverWithBcc) {
+TEST(BccHandoverTest, InHandoverWithoutBccOutHandoverWithBcc) {
   const uint8_t bcc_handover[] = {
       0xa2,
       // CDI attest
@@ -126,7 +126,34 @@
       0x02, 0x58, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  };
+      // 8-bytes of trailing data that aren't part of the BCC.
+      0x00, 0x41, 0x55, 0xa0, 0x42, 0x11, 0x22, 0x40};
+  DiceInputValues input_values = {};
+  uint8_t next_bcc_handover[1024] = {};
+  size_t next_bcc_handover_size;
+  DiceResult result = BccHandoverMainFlow(
+      /*context=*/NULL, bcc_handover, sizeof(bcc_handover), &input_values,
+      sizeof(next_bcc_handover), next_bcc_handover, &next_bcc_handover_size);
+  EXPECT_EQ(kDiceResultOk, result);
+  EXPECT_GT(next_bcc_handover_size, sizeof(bcc_handover));
+  EXPECT_EQ(0xa3, next_bcc_handover[0]);
+}
+
+TEST(BccHandoverTest, InHandoverWithoutBccButUnknownFieldOutHandoverWithBcc) {
+  const uint8_t bcc_handover[] = {
+      0xa3,
+      // CDI attest
+      0x01, 0x58, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      // CDI seal
+      0x02, 0x58, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      // Ignored unknown field
+      0x04, 0x01,
+      // 8-bytes of trailing data that aren't part of the BCC.
+      0x00, 0x41, 0x55, 0xa0, 0x42, 0x11, 0x22, 0x40};
   DiceInputValues input_values = {};
   uint8_t next_bcc_handover[1024] = {};
   size_t next_bcc_handover_size;