diff options
author | Alan Stokes <alanstokes@google.com> | 2023-11-02 11:19:22 +0000 |
---|---|---|
committer | CQ Bot Account <pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2023-11-02 11:19:22 +0000 |
commit | e1e1bbdb625a21b376dee2eb8128adf4b800008a (patch) | |
tree | 256d41edeffefc53ef26195d07d8389c78b0c266 | |
parent | 5cf594d08549fcea0ccbee5b54e386f129ed18b3 (diff) | |
download | open-dice-e1e1bbdb625a21b376dee2eb8128adf4b800008a.tar.gz |
Add a test for CoseSignAndEncodeSign1
This used to be exercised via DiceMainFlow, but it is no longer used
there.
Add a test to make sure it produces a correctly-signed CoseSign1 with
the expected payload.
Change-Id: Ia3f8f8540dab27058964028d6b53af7dc6b2d53e
Reviewed-on: https://pigweed-review.googlesource.com/c/open-dice/+/178650
Commit-Queue: Auto-Submit <auto-submit@pigweed-service-accounts.iam.gserviceaccount.com>
Reviewed-by: Andrew Scull <ascull@google.com>
Pigweed-Auto-Submit: Alan Stokes <alanstokes@google.com>
Presubmit-Verified: CQ Bot Account <pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com>
-rw-r--r-- | include/dice/test_utils.h | 9 | ||||
-rw-r--r-- | src/cbor_cert_op_test.cc | 48 | ||||
-rw-r--r-- | src/test_utils.cc | 64 |
3 files changed, 113 insertions, 8 deletions
diff --git a/include/dice/test_utils.h b/include/dice/test_utils.h index 70469c4..7e403b9 100644 --- a/include/dice/test_utils.h +++ b/include/dice/test_utils.h @@ -58,6 +58,15 @@ void CreateFakeUdsCertificate(void* context, const uint8_t uds[32], uint8_t certificate[kTestCertSize], size_t* certificate_size); +// Verify that a single CDI certificate is properly signed with the given key +// and contains the expected payload. +bool VerifyCoseSign1(const uint8_t* certificate, size_t certificate_size, + const uint8_t* external_aad, size_t external_aad_size, + const uint8_t* encoded_public_key, + size_t encoded_public_key_size, + const uint8_t* expected_payload, + size_t expected_payload_size); + // Verifies a chain of CDI certificates given by |states| against // |root_certificate|. If |is_partial_chain| is set, then root_certificate does // not need to be self signed. For X.509 certificate chains, only the standard diff --git a/src/cbor_cert_op_test.cc b/src/cbor_cert_op_test.cc index c94c6c1..46ae094 100644 --- a/src/cbor_cert_op_test.cc +++ b/src/cbor_cert_op_test.cc @@ -20,6 +20,8 @@ #include "dice/dice.h" #include "dice/known_test_values.h" +#include "dice/ops.h" +#include "dice/ops/trait/cose.h" #include "dice/test_framework.h" #include "dice/test_utils.h" #include "dice/utils.h" @@ -31,6 +33,7 @@ using dice::test::CertificateType_Cbor; using dice::test::DeriveFakeInputValue; using dice::test::DiceStateForTest; using dice::test::KeyType_Ed25519; +using dice::test::VerifyCoseSign1; TEST(DiceOpsTest, KnownAnswerZeroInput) { DiceStateForTest current_state = {}; @@ -232,6 +235,51 @@ TEST(DiceOpsTest, InvalidConfigType) { EXPECT_EQ(kDiceResultInvalidInput, result); } +TEST(DiceOpsTest, CoseSignAndEncodeSign1) { + DiceStateForTest current_state = {}; + DiceStateForTest next_state = {}; + DiceInputValues input_values = {}; + DiceResult result = DiceMainFlow( + NULL, current_state.cdi_attest, current_state.cdi_seal, &input_values, + sizeof(next_state.certificate), next_state.certificate, + &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal); + ASSERT_EQ(kDiceResultOk, result); + + uint8_t private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE]; + result = DiceDeriveCdiPrivateKeySeed(NULL, next_state.cdi_attest, + private_key_seed); + ASSERT_EQ(kDiceResultOk, result); + + uint8_t private_key[DICE_PRIVATE_KEY_SIZE]; + uint8_t public_key[DICE_PUBLIC_KEY_SIZE]; + result = DiceKeypairFromSeed(NULL, private_key_seed, public_key, private_key); + ASSERT_EQ(kDiceResultOk, result); + + uint8_t encoded_public_key[DICE_PUBLIC_KEY_SIZE + 32]; + size_t encoded_public_key_size = 0; + result = + DiceCoseEncodePublicKey(NULL, public_key, sizeof(encoded_public_key), + encoded_public_key, &encoded_public_key_size); + ASSERT_EQ(kDiceResultOk, result); + + uint8_t payload[500]; + DeriveFakeInputValue("payload", sizeof(payload), payload); + + uint8_t aad[100]; + DeriveFakeInputValue("aad", sizeof(aad), aad); + + uint8_t sign1[1000]; + size_t sign1_size; + result = DiceCoseSignAndEncodeSign1(NULL, payload, sizeof(payload), aad, + sizeof(aad), private_key, sizeof(sign1), + sign1, &sign1_size); + ASSERT_EQ(kDiceResultOk, result); + + EXPECT_TRUE(VerifyCoseSign1(sign1, sign1_size, aad, sizeof(aad), + encoded_public_key, encoded_public_key_size, + payload, sizeof(payload))); +} + TEST(DiceOpsTest, PartialCertChain) { constexpr size_t kNumLayers = 7; DiceStateForTest states[kNumLayers + 1] = {}; diff --git a/src/test_utils.cc b/src/test_utils.cc index 12663cc..f8899e0 100644 --- a/src/test_utils.cc +++ b/src/test_utils.cc @@ -628,13 +628,11 @@ bool ValidateCborCertificateCdiFields(const cn_cbor* cwt, return true; } -bool VerifySingleCborCertificate(const uint8_t* certificate, - size_t certificate_size, - const cn_cbor* authority_public_key, - const char authority_id_hex[40], - bool expect_cdi_certificate, - ScopedCbor* subject_public_key, - char subject_id_hex[40]) { +bool VerifyCoseSign1Signature(const uint8_t* certificate, + size_t certificate_size, + const uint8_t* external_aad, + size_t external_aad_size, + const cn_cbor* authority_public_key) { // Use the COSE-C library to decode and validate. cose_errback error; int struct_type = 0; @@ -643,12 +641,26 @@ bool VerifySingleCborCertificate(const uint8_t* certificate, if (!sign1) { return false; } - (void)authority_public_key; + COSE_Sign1_SetExternal(sign1, external_aad, external_aad_size, &error); bool result = COSE_Sign1_validate(sign1, authority_public_key, &error); COSE_Sign1_Free(sign1); if (!result) { return false; } + return true; +} + +bool VerifySingleCborCertificate(const uint8_t* certificate, + size_t certificate_size, + const cn_cbor* authority_public_key, + const char authority_id_hex[40], + bool expect_cdi_certificate, + ScopedCbor* subject_public_key, + char subject_id_hex[40]) { + if (!VerifyCoseSign1Signature(certificate, certificate_size, /*aad=*/NULL, + /*aad_size=*/0, authority_public_key)) { + return false; + } ScopedCbor cwt(ExtractCwtFromCborCertificate(certificate, certificate_size)); if (!cwt) { @@ -785,6 +797,42 @@ void CreateFakeUdsCertificate(void* context, const uint8_t uds[32], DumpToFile(filename, certificate, *certificate_size); } +[[maybe_unused]] bool VerifyCoseSign1( + const uint8_t* certificate, size_t certificate_size, + const uint8_t* external_aad, size_t external_aad_size, + const uint8_t* encoded_public_key, size_t encoded_public_key_size, + const uint8_t* expected_cwt, size_t expected_cwt_size) { + cn_cbor_errback error; + ScopedCbor public_key( + cn_cbor_decode(encoded_public_key, encoded_public_key_size, &error)); + if (!public_key) { + return false; + } + + if (!VerifyCoseSign1Signature(certificate, certificate_size, external_aad, + external_aad_size, public_key.get())) { + return false; + } + + ScopedCbor sign1(cn_cbor_decode(certificate, certificate_size, &error)); + if (!sign1 || sign1->type != CN_CBOR_ARRAY || sign1->length != 4) { + return false; + } + cn_cbor* payload = cn_cbor_index(sign1.get(), 2); + if (!payload || payload->type != CN_CBOR_BYTES) { + return false; + } + + if (payload->length != expected_cwt_size) { + return false; + } + + if (memcmp(payload->v.bytes, expected_cwt, expected_cwt_size) != 0) { + return false; + } + return true; +} + bool VerifyCertificateChain(CertificateType cert_type, const uint8_t* root_certificate, size_t root_certificate_size, |