| // Copyright 2021 Google LLC |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| // use this file except in compliance with the License. You may obtain a copy of |
| // the License at |
| // |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| // License for the specific language governing permissions and limitations under |
| // the License. |
| |
| #include "dice/android/bcc.h" |
| |
| #include "dice/test_framework.h" |
| |
| namespace { |
| |
| extern "C" { |
| |
| TEST(BccConfigTest, NoInputs) { |
| BccConfigValues input_values = {}; |
| uint8_t buffer[10]; |
| size_t buffer_size; |
| DiceResult result = BccFormatConfigDescriptor(&input_values, sizeof(buffer), |
| buffer, &buffer_size); |
| EXPECT_EQ(kDiceResultOk, result); |
| EXPECT_EQ(1u, buffer_size); |
| EXPECT_EQ(0xa0, buffer[0]); |
| } |
| |
| TEST(BccConfigTest, NoInputsMeasurement) { |
| BccConfigValues input_values = {}; |
| size_t buffer_size; |
| DiceResult result = |
| BccFormatConfigDescriptor(&input_values, 0, NULL, &buffer_size); |
| EXPECT_EQ(kDiceResultBufferTooSmall, result); |
| EXPECT_EQ(1u, buffer_size); |
| } |
| |
| TEST(BccConfigTest, AllInputs) { |
| BccConfigValues input_values = { |
| .inputs = BCC_INPUT_COMPONENT_NAME | BCC_INPUT_COMPONENT_VERSION | |
| BCC_INPUT_RESETTABLE, |
| .component_name = "Test Component Name", |
| .component_version = 0x232a13dec90f42b5, |
| }; |
| size_t buffer_size; |
| DiceResult result = |
| BccFormatConfigDescriptor(&input_values, 0, NULL, &buffer_size); |
| EXPECT_EQ(kDiceResultBufferTooSmall, result); |
| std::vector<uint8_t> buffer(buffer_size); |
| const uint8_t expected[] = { |
| 0xa3, 0x3a, 0x00, 0x01, 0x11, 0x71, 0x73, 'T', 'e', 's', 't', ' ', |
| 'C', 'o', 'm', 'p', 'o', 'n', 'e', 'n', 't', ' ', 'N', 'a', |
| 'm', 'e', 0x3a, 0x00, 0x01, 0x11, 0x72, 0x1b, 0x23, 0x2a, 0x13, 0xde, |
| 0xc9, 0x0f, 0x42, 0xb5, 0x3a, 0x00, 0x01, 0x11, 0x73, 0xf6}; |
| EXPECT_EQ(sizeof(expected), buffer.size()); |
| result = BccFormatConfigDescriptor(&input_values, buffer.size(), |
| buffer.data(), &buffer_size); |
| EXPECT_EQ(sizeof(expected), buffer_size); |
| EXPECT_EQ(0, memcmp(expected, buffer.data(), buffer.size())); |
| } |
| |
| TEST(BccTest, PreservesPreviousEntries) { |
| const uint8_t bcc[] = { |
| // Fake BCC with the root public key and two entries. |
| 0x83, |
| // Fake public key. |
| 0xa6, 0x01, 0x02, 0x03, 0x27, 0x04, 0x02, 0x20, 0x01, 0x21, 0x40, 0x22, |
| 0x40, |
| // Fake BCC entry. |
| 0x84, 0x40, 0xa0, 0x40, 0x40, |
| // Fake BCC entry. |
| 0x84, 0x41, 0x55, 0xa0, 0x42, 0x11, 0x22, 0x40, |
| // 8-bytes of trailing data that aren't part of the BCC. |
| 0x84, 0x41, 0x55, 0xa0, 0x42, 0x11, 0x22, 0x40}; |
| const uint8_t fake_cdi_attest[DICE_CDI_SIZE] = {}; |
| const uint8_t fake_cdi_seal[DICE_CDI_SIZE] = {}; |
| DiceInputValues input_values = {}; |
| size_t next_bcc_size; |
| uint8_t next_cdi_attest[DICE_CDI_SIZE]; |
| uint8_t next_cdi_seal[DICE_CDI_SIZE]; |
| DiceResult result = BccMainFlow( |
| /*context=*/NULL, fake_cdi_attest, fake_cdi_seal, bcc, sizeof(bcc), |
| &input_values, 0, NULL, &next_bcc_size, next_cdi_attest, next_cdi_seal); |
| EXPECT_EQ(kDiceResultBufferTooSmall, result); |
| EXPECT_GT(next_bcc_size, sizeof(bcc)); |
| std::vector<uint8_t> next_bcc(next_bcc_size); |
| result = |
| BccMainFlow(/*context=*/NULL, fake_cdi_attest, fake_cdi_seal, bcc, |
| sizeof(bcc), &input_values, next_bcc.size(), next_bcc.data(), |
| &next_bcc_size, next_cdi_attest, next_cdi_seal); |
| EXPECT_EQ(kDiceResultOk, result); |
| EXPECT_EQ(next_bcc_size, next_bcc.size()); |
| EXPECT_EQ(0x84, next_bcc[0]); |
| EXPECT_NE(0, memcmp(next_bcc.data() + 1, bcc + 1, sizeof(bcc) - 1)); |
| EXPECT_EQ(0, memcmp(next_bcc.data() + 1, bcc + 1, sizeof(bcc) - 8 - 1)); |
| } |
| |
| TEST(BccHandoverTest, PreservesPreviousEntries) { |
| 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, |
| // BCC |
| 0x03, 0x82, 0xa6, 0x01, 0x02, 0x03, 0x27, 0x04, 0x02, 0x20, 0x01, 0x21, |
| 0x40, 0x22, 0x40, 0x84, 0x40, 0xa0, 0x40, 0x40, |
| // 8-bytes of trailing data that aren't part of the BCC. |
| 0x84, 0x41, 0x55, 0xa0, 0x42, 0x11, 0x22, 0x40}; |
| DiceInputValues input_values = {}; |
| size_t next_bcc_handover_size; |
| DiceResult result = BccHandoverMainFlow( |
| /*context=*/NULL, bcc_handover, sizeof(bcc_handover), &input_values, 0, |
| NULL, &next_bcc_handover_size); |
| EXPECT_EQ(kDiceResultBufferTooSmall, result); |
| EXPECT_GT(next_bcc_handover_size, sizeof(bcc_handover)); |
| std::vector<uint8_t> next_bcc_handover(next_bcc_handover_size); |
| result = BccHandoverMainFlow( |
| /*context=*/NULL, bcc_handover, sizeof(bcc_handover), &input_values, |
| next_bcc_handover.size(), next_bcc_handover.data(), |
| &next_bcc_handover_size); |
| EXPECT_EQ(kDiceResultOk, result); |
| EXPECT_EQ(next_bcc_handover_size, next_bcc_handover.size()); |
| EXPECT_EQ(0xa3, next_bcc_handover[0]); |
| EXPECT_EQ(0x83, next_bcc_handover[72]); |
| EXPECT_NE(0, memcmp(next_bcc_handover.data() + 73, bcc_handover + 73, |
| sizeof(bcc_handover) - 73)); |
| EXPECT_EQ(0, memcmp(next_bcc_handover.data() + 73, bcc_handover + 73, |
| sizeof(bcc_handover) - 8 - 73)); |
| } |
| |
| TEST(BccHandoverTest, InHandoverWithoutBccOutHandoverWithBcc) { |
| const uint8_t bcc_handover[] = { |
| 0xa2, |
| // 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, |
| // 8-bytes of trailing data that aren't part of the BCC. |
| 0x00, 0x41, 0x55, 0xa0, 0x42, 0x11, 0x22, 0x40}; |
| DiceInputValues input_values = {}; |
| size_t next_bcc_handover_size; |
| DiceResult result = BccHandoverMainFlow( |
| /*context=*/NULL, bcc_handover, sizeof(bcc_handover), &input_values, 0, |
| NULL, &next_bcc_handover_size); |
| EXPECT_EQ(kDiceResultBufferTooSmall, result); |
| EXPECT_GT(next_bcc_handover_size, sizeof(bcc_handover)); |
| std::vector<uint8_t> next_bcc_handover(next_bcc_handover_size); |
| result = BccHandoverMainFlow( |
| /*context=*/NULL, bcc_handover, sizeof(bcc_handover), &input_values, |
| next_bcc_handover.size(), next_bcc_handover.data(), |
| &next_bcc_handover_size); |
| EXPECT_EQ(kDiceResultOk, result); |
| EXPECT_EQ(next_bcc_handover_size, next_bcc_handover.size()); |
| 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 = {}; |
| size_t next_bcc_handover_size; |
| DiceResult result = BccHandoverMainFlow( |
| /*context=*/NULL, bcc_handover, sizeof(bcc_handover), &input_values, 0, |
| NULL, &next_bcc_handover_size); |
| EXPECT_EQ(kDiceResultBufferTooSmall, result); |
| EXPECT_GT(next_bcc_handover_size, sizeof(bcc_handover)); |
| std::vector<uint8_t> next_bcc_handover(next_bcc_handover_size); |
| result = BccHandoverMainFlow( |
| /*context=*/NULL, bcc_handover, sizeof(bcc_handover), &input_values, |
| next_bcc_handover.size(), next_bcc_handover.data(), |
| &next_bcc_handover_size); |
| EXPECT_EQ(kDiceResultOk, result); |
| EXPECT_EQ(next_bcc_handover_size, next_bcc_handover.size()); |
| EXPECT_EQ(0xa3, next_bcc_handover[0]); |
| } |
| |
| TEST(BccHandoverTest, ParseHandover) { |
| 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, |
| // BCC |
| 0x03, 0x82, 0xa6, 0x01, 0x02, 0x03, 0x27, 0x04, 0x02, 0x20, 0x01, 0x21, |
| 0x40, 0x22, 0x40, 0x84, 0x40, 0xa0, 0x40, 0x40, |
| // 8-bytes of trailing data that aren't part of the BCC. |
| 0x00, 0x41, 0x55, 0xa0, 0x42, 0x11, 0x22, 0x40}; |
| const uint8_t *cdi_attest; |
| const uint8_t *cdi_seal; |
| const uint8_t *bcc; |
| size_t bcc_size; |
| DiceResult result = BccHandoverParse(bcc_handover, sizeof(bcc_handover), |
| &cdi_attest, &cdi_seal, &bcc, &bcc_size); |
| EXPECT_EQ(kDiceResultOk, result); |
| EXPECT_EQ(bcc_handover + 4, cdi_attest); |
| EXPECT_EQ(bcc_handover + 39, cdi_seal); |
| EXPECT_EQ(bcc_handover + 72, bcc); |
| EXPECT_EQ(19u, bcc_size); |
| } |
| |
| TEST(BccHandoverTest, ParseHandoverWithoutBcc) { |
| const uint8_t bcc_handover[] = { |
| 0xa2, |
| // 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, |
| // 8-bytes of trailing data that aren't part of the BCC. |
| 0x00, 0x41, 0x55, 0xa0, 0x42, 0x11, 0x22, 0x40}; |
| const uint8_t *cdi_attest; |
| const uint8_t *cdi_seal; |
| const uint8_t *bcc; |
| size_t bcc_size; |
| DiceResult result = BccHandoverParse(bcc_handover, sizeof(bcc_handover), |
| &cdi_attest, &cdi_seal, &bcc, &bcc_size); |
| EXPECT_EQ(kDiceResultOk, result); |
| EXPECT_EQ(bcc_handover + 4, cdi_attest); |
| EXPECT_EQ(bcc_handover + 39, cdi_seal); |
| EXPECT_EQ(nullptr, bcc); |
| EXPECT_EQ(0u, bcc_size); |
| } |
| |
| TEST(BccHandoverTest, ParseHandoverWithoutBccButUnknownField) { |
| 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}; |
| const uint8_t *cdi_attest; |
| const uint8_t *cdi_seal; |
| const uint8_t *bcc; |
| size_t bcc_size; |
| DiceResult result = BccHandoverParse(bcc_handover, sizeof(bcc_handover), |
| &cdi_attest, &cdi_seal, &bcc, &bcc_size); |
| EXPECT_EQ(kDiceResultOk, result); |
| EXPECT_EQ(bcc_handover + 4, cdi_attest); |
| EXPECT_EQ(bcc_handover + 39, cdi_seal); |
| EXPECT_EQ(nullptr, bcc); |
| EXPECT_EQ(0u, bcc_size); |
| } |
| |
| TEST(BccHandoverTest, ParseHandoverCdiTooLarge) { |
| const uint8_t bcc_handover[] = { |
| 0xa2, |
| // 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, 0x21, 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, 0x00, |
| // 8-bytes of trailing data that aren't part of the BCC. |
| 0x00, 0x41, 0x55, 0xa0, 0x42, 0x11, 0x22, 0x40}; |
| const uint8_t *cdi_attest; |
| const uint8_t *cdi_seal; |
| const uint8_t *bcc; |
| size_t bcc_size; |
| DiceResult result = BccHandoverParse(bcc_handover, sizeof(bcc_handover), |
| &cdi_attest, &cdi_seal, &bcc, &bcc_size); |
| EXPECT_EQ(kDiceResultInvalidInput, result); |
| } |
| } |
| |
| } // namespace |