From 11947350d3b8d3151ea941212ef55b29b02edc83 Mon Sep 17 00:00:00 2001 From: Tennessee Carmel-Veilleux Date: Sat, 27 Nov 2021 12:08:31 -0500 Subject: [PATCH] Make PAA trust store configurable (#12277) * Make PAA store configurable PAA store used by DefaultDeviceAttestationVerifier could not be replaced, forcing a few fixed test roots to always be used and nothing else, unless completely forking the DefaultDeviceAttestationVerifier. - This PR introduces the `PaaRootStore` interface, which the default `DeviceAttestationVerifier` expects to get configured at in constructor. - Examples were modified to use the default test PAA root store - Unit tests updated to use the testing root store - Refactored simple array-based Root store to self-extract the SKID Testing done: added new units tests which pass, ran cert tests, validated attestation succeeds the same as before with test keys. Fixed #11913 * Restyled by clang-format * Address review comments - Rename PaaRootStore to AttestationTrustStore - Add comments about ArrayAttestationtTrustStore lifecycle - Remove debug print * Fix python build * Fix tv-app scoping issue * Attempt to debug Darwin error * Restyled by clang-format * Remove debug logging used to diagnose CI Co-authored-by: Restyled.io --- .../chip-tool/commands/common/CHIPCommand.cpp | 5 +- examples/platform/linux/AppMain.cpp | 4 +- examples/tv-casting-app/linux/main.cpp | 8 +- .../java/AndroidDeviceControllerWrapper.cpp | 4 +- .../ChipDeviceController-ScriptBinding.cpp | 4 +- .../python/chip/internal/CommissionerImpl.cpp | 8 +- src/credentials/CHIPCert.h | 2 +- src/credentials/DeviceAttestationVerifier.h | 81 +++++++ .../DefaultDeviceAttestationVerifier.cpp | 208 +++++++++--------- .../DefaultDeviceAttestationVerifier.h | 22 +- .../tests/TestCertificationDeclaration.cpp | 4 +- .../TestDeviceAttestationCredentials.cpp | 80 ++++++- src/crypto/CHIPCryptoPAL.h | 2 + src/crypto/tests/CHIPCryptoPALTest.cpp | 4 +- .../Framework/CHIP/CHIPDeviceController.mm | 4 +- src/protocols/secure_channel/CASESession.h | 2 +- 16 files changed, 314 insertions(+), 128 deletions(-) diff --git a/examples/chip-tool/commands/common/CHIPCommand.cpp b/examples/chip-tool/commands/common/CHIPCommand.cpp index 44921d77b457f9..7f39cab591b99b 100644 --- a/examples/chip-tool/commands/common/CHIPCommand.cpp +++ b/examples/chip-tool/commands/common/CHIPCommand.cpp @@ -45,7 +45,10 @@ CHIP_ERROR CHIPCommand::Run() chip::Platform::ScopedMemoryBuffer rcac; chip::Credentials::SetDeviceAttestationCredentialsProvider(chip::Credentials::Examples::GetExampleDACProvider()); - chip::Credentials::SetDeviceAttestationVerifier(chip::Credentials::GetDefaultDACVerifier()); + + // TODO: Replace testingRootStore with a AttestationTrustStore that has the necessary official PAA roots available + const chip::Credentials::AttestationTrustStore * testingRootStore = chip::Credentials::GetTestAttestationTrustStore(); + chip::Credentials::SetDeviceAttestationVerifier(chip::Credentials::GetDefaultDACVerifier(testingRootStore)); VerifyOrReturnError(noc.Alloc(chip::Controller::kMaxCHIPDERCertLength), CHIP_ERROR_NO_MEMORY); VerifyOrReturnError(icac.Alloc(chip::Controller::kMaxCHIPDERCertLength), CHIP_ERROR_NO_MEMORY); diff --git a/examples/platform/linux/AppMain.cpp b/examples/platform/linux/AppMain.cpp index 5b79f089d13674..44f9917c92e70d 100644 --- a/examples/platform/linux/AppMain.cpp +++ b/examples/platform/linux/AppMain.cpp @@ -234,7 +234,9 @@ CHIP_ERROR InitCommissioner() ReturnErrorOnFailure(gCommissioner.SetUdcListenPort(LinuxDeviceOptions::GetInstance().unsecuredCommissionerPort)); // Initialize device attestation verifier - SetDeviceAttestationVerifier(GetDefaultDACVerifier()); + // TODO: Replace testingRootStore with a AttestationTrustStore that has the necessary official PAA roots available + const chip::Credentials::AttestationTrustStore * testingRootStore = chip::Credentials::GetTestAttestationTrustStore(); + SetDeviceAttestationVerifier(GetDefaultDACVerifier(testingRootStore)); chip::Platform::ScopedMemoryBuffer noc; VerifyOrReturnError(noc.Alloc(chip::Controller::kMaxCHIPDERCertLength), CHIP_ERROR_NO_MEMORY); diff --git a/examples/tv-casting-app/linux/main.cpp b/examples/tv-casting-app/linux/main.cpp index e2b356db9ae093..7cd5934347e967 100644 --- a/examples/tv-casting-app/linux/main.cpp +++ b/examples/tv-casting-app/linux/main.cpp @@ -195,8 +195,12 @@ int main(int argc, char * argv[]) // Initialize device attestation config SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); - // Initialize device attestation verifier - SetDeviceAttestationVerifier(GetDefaultDACVerifier()); + // Initialize device attestation verifier from a constant version + { + // TODO: Replace testingRootStore with a AttestationTrustStore that has the necessary official PAA roots available + const chip::Credentials::AttestationTrustStore * testingRootStore = chip::Credentials::GetTestAttestationTrustStore(); + SetDeviceAttestationVerifier(GetDefaultDACVerifier(testingRootStore)); + } if (!chip::ArgParser::ParseArgs(argv[0], argc, argv, allOptions)) { diff --git a/src/controller/java/AndroidDeviceControllerWrapper.cpp b/src/controller/java/AndroidDeviceControllerWrapper.cpp index bb18387a38a488..4f961e0a0dec97 100644 --- a/src/controller/java/AndroidDeviceControllerWrapper.cpp +++ b/src/controller/java/AndroidDeviceControllerWrapper.cpp @@ -204,7 +204,9 @@ AndroidDeviceControllerWrapper * AndroidDeviceControllerWrapper::AllocateNew(Jav wrapper->SetJavaObjectRef(vm, deviceControllerObj); // Initialize device attestation verifier - SetDeviceAttestationVerifier(GetDefaultDACVerifier()); + // TODO: Replace testingRootStore with a AttestationTrustStore that has the necessary official PAA roots available + const chip::Credentials::AttestationTrustStore * testingRootStore = chip::Credentials::GetTestAttestationTrustStore(); + SetDeviceAttestationVerifier(GetDefaultDACVerifier(testingRootStore)); chip::Controller::FactoryInitParams initParams; chip::Controller::SetupParams setupParams; diff --git a/src/controller/python/ChipDeviceController-ScriptBinding.cpp b/src/controller/python/ChipDeviceController-ScriptBinding.cpp index 9c1b09388d0f7f..c7fc136760d8fc 100644 --- a/src/controller/python/ChipDeviceController-ScriptBinding.cpp +++ b/src/controller/python/ChipDeviceController-ScriptBinding.cpp @@ -182,7 +182,9 @@ ChipError::StorageType pychip_DeviceController_NewDeviceController(chip::Control } // Initialize device attestation verifier - SetDeviceAttestationVerifier(GetDefaultDACVerifier()); + // TODO: Replace testingRootStore with a AttestationTrustStore that has the necessary official PAA roots available + const chip::Credentials::AttestationTrustStore * testingRootStore = chip::Credentials::GetTestAttestationTrustStore(); + SetDeviceAttestationVerifier(GetDefaultDACVerifier(testingRootStore)); CHIP_ERROR err = sOperationalCredentialsIssuer.Initialize(sStorageDelegate); VerifyOrReturnError(err == CHIP_NO_ERROR, err.AsInteger()); diff --git a/src/controller/python/chip/internal/CommissionerImpl.cpp b/src/controller/python/chip/internal/CommissionerImpl.cpp index 4386fc16ab549b..8d5b129d7d1159 100644 --- a/src/controller/python/chip/internal/CommissionerImpl.cpp +++ b/src/controller/python/chip/internal/CommissionerImpl.cpp @@ -108,6 +108,11 @@ extern "C" chip::Controller::DeviceCommissioner * pychip_internal_Commissioner_N chip::Platform::ScopedMemoryBuffer rcac; chip::Crypto::P256Keypair ephemeralKey; + // Initialize device attestation verifier + // TODO: Replace testingRootStore with a AttestationTrustStore that has the necessary official PAA roots available + const chip::Credentials::AttestationTrustStore * testingRootStore = chip::Credentials::GetTestAttestationTrustStore(); + chip::Credentials::SetDeviceAttestationVerifier(chip::Credentials::GetDefaultDACVerifier(testingRootStore)); + err = gFabricStorage.Initialize(&gServerStorage); SuccessOrExit(err); @@ -116,9 +121,6 @@ extern "C" chip::Controller::DeviceCommissioner * pychip_internal_Commissioner_N commissionerParams.pairingDelegate = &gPairingDelegate; commissionerParams.storageDelegate = &gServerStorage; - // Initialize device attestation verifier - chip::Credentials::SetDeviceAttestationVerifier(chip::Credentials::GetDefaultDACVerifier()); - err = ephemeralKey.Initialize(); SuccessOrExit(err); diff --git a/src/credentials/CHIPCert.h b/src/credentials/CHIPCert.h index 762e0f25f209f6..b957e60283b638 100644 --- a/src/credentials/CHIPCert.h +++ b/src/credentials/CHIPCert.h @@ -42,7 +42,7 @@ namespace chip { namespace Credentials { -static constexpr uint32_t kKeyIdentifierLength = 20; +static constexpr uint32_t kKeyIdentifierLength = static_cast(Crypto::kSubjectKeyIdentifierLength); static constexpr uint32_t kChip32bitAttrUTF8Length = 8; static constexpr uint32_t kChip64bitAttrUTF8Length = 16; static constexpr uint16_t kX509NoWellDefinedExpirationDateYear = 9999; diff --git a/src/credentials/DeviceAttestationVerifier.h b/src/credentials/DeviceAttestationVerifier.h index 09d843153943d5..75ee5a0eb50d0e 100644 --- a/src/credentials/DeviceAttestationVerifier.h +++ b/src/credentials/DeviceAttestationVerifier.h @@ -99,6 +99,87 @@ struct DeviceInfoForAttestation uint16_t paaVendorId = VendorId::NotSpecified; }; +/** + * @brief Helper utility to model a basic trust store usable for device attestation verifiers. + * + * API is synchronous. Real commissioner implementations may entirely + * hide Product Attestation Authority cert lookup behind the DeviceAttestationVerifier and + * never use this interface at all. It is provided as a utility to help build DeviceAttestationVerifier + * implementations suitable for testing or examples. + */ +class AttestationTrustStore +{ +public: + AttestationTrustStore() = default; + virtual ~AttestationTrustStore() = default; + + // Not copyable + AttestationTrustStore(const AttestationTrustStore &) = delete; + AttestationTrustStore & operator=(const AttestationTrustStore &) = delete; + + /** + * @brief Look-up a PAA cert by SKID + * + * The implementations of this interface must have access to a set of PAAs to trust. + * + * Interface is synchronous, and therefore this should not be used unless to expose a PAA + * store that is both fully local and quick to access. + * + * @param[in] skid Buffer containing the subject key identifier (SKID) of the PAA to look-up + * @param[inout] outPaaDerBuffer Buffer to receive the contents of the PAA root cert, if found. + * Size will be updated to match actual size. + * + * @returns CHIP_NO_ERROR on success, CHIP_INVALID_ARGUMENT if `skid` or `outPaaDerBuffer` arguments + * are not usable, CHIP_BUFFER_TOO_SMALL if certificate doesn't fit in `outPaaDerBuffer` + * span, CHIP_ERROR_CA_CERT_NOT_FOUND if no PAA found that matches `skid. + * + */ + virtual CHIP_ERROR GetProductAttestationAuthorityCert(const ByteSpan & skid, MutableByteSpan & outPaaDerBuffer) const = 0; +}; + +/** + * @brief Basic AttestationTrustStore that holds all data within caller-owned memory. + * + * This is useful to wrap a fixed constant array of certificates into a trust store + * implementation. + */ + +class ArrayAttestationTrustStore : public AttestationTrustStore +{ +public: + ArrayAttestationTrustStore(const ByteSpan * derCerts, size_t numCerts) : mDerCerts(derCerts), mNumCerts(numCerts) {} + + CHIP_ERROR GetProductAttestationAuthorityCert(const ByteSpan & skid, MutableByteSpan & outPaaDerBuffer) const override + { + VerifyOrReturnError(!skid.empty() && (skid.data() != nullptr), CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(skid.size() == Crypto::kSubjectKeyIdentifierLength, CHIP_ERROR_INVALID_ARGUMENT); + + size_t paaIdx; + ByteSpan candidate; + + for (paaIdx = 0; paaIdx < mNumCerts; ++paaIdx) + { + uint8_t skidBuf[Crypto::kSubjectKeyIdentifierLength] = { 0 }; + candidate = mDerCerts[paaIdx]; + MutableByteSpan candidateSkidSpan{ skidBuf }; + VerifyOrReturnError(CHIP_NO_ERROR == Crypto::ExtractSKIDFromX509Cert(candidate, candidateSkidSpan), + CHIP_ERROR_INTERNAL); + + if (skid.data_equal(candidateSkidSpan)) + { + // Found a match + return CopySpanToMutableSpan(candidate, outPaaDerBuffer); + } + } + + return CHIP_ERROR_CA_CERT_NOT_FOUND; + } + +protected: + const ByteSpan * mDerCerts; + const size_t mNumCerts; +}; + class DeviceAttestationVerifier { public: diff --git a/src/credentials/examples/DefaultDeviceAttestationVerifier.cpp b/src/credentials/examples/DefaultDeviceAttestationVerifier.cpp index b6cf795092fd47..23acd0179f59f7 100644 --- a/src/credentials/examples/DefaultDeviceAttestationVerifier.cpp +++ b/src/credentials/examples/DefaultDeviceAttestationVerifier.cpp @@ -34,114 +34,98 @@ namespace Credentials { namespace { -CHIP_ERROR GetProductAttestationAuthorityCert(const ByteSpan & skid, MutableByteSpan & outDacBuffer) -{ - struct PAALookupTable - { - const uint8_t mPAACertificate[kMax_x509_Certificate_Length]; - const uint8_t mSKID[kKeyIdentifierLength]; - }; - - static PAALookupTable - sPAALookupTable[] = { - { /* - credentials/test/attestation/Chip-Test-PAA-FFF1-Cert.pem - -----BEGIN CERTIFICATE----- - MIIBmTCCAT+gAwIBAgIIaDhPq7kZ/N8wCgYIKoZIzj0EAwIwHzEdMBsGA1UEAwwU - TWF0dGVyIFRlc3QgUEFBIEZGRjEwIBcNMjEwNjI4MTQyMzQzWhgPOTk5OTEyMzEy - MzU5NTlaMB8xHTAbBgNVBAMMFE1hdHRlciBUZXN0IFBBQSBGRkYxMFkwEwYHKoZI - zj0CAQYIKoZIzj0DAQcDQgAEG5isW7wR3GoXVaBbCsXha6AsRu5vwrvnb/fPbKeq - Tp/R15jcvvtP6uIl03c8kTSMwm1JMTHjCWMtXp7zHRLek6NjMGEwDwYDVR0TAQH/ - BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFO8Y4OzUZgQ03w28kR7U - UhaZZoOfMB8GA1UdIwQYMBaAFO8Y4OzUZgQ03w28kR7UUhaZZoOfMAoGCCqGSM49 - BAMCA0gAMEUCIQCn+l+nZv/3tf0VjNNPYl1IkSAOBYUO8SX23udWVPmXNgIgI7Ub - bkJTKCjbCZIDNwUNcPC2tyzNPLeB5nGsIl31Rys= - -----END CERTIFICATE----- - */ - { 0x30, 0x82, 0x01, 0x99, 0x30, 0x82, 0x01, 0x3F, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x68, 0x38, 0x4F, 0xAB, - 0xB9, 0x19, 0xFC, 0xDF, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x1F, 0x31, - 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x14, 0x4D, 0x61, 0x74, 0x74, 0x65, 0x72, 0x20, 0x54, 0x65, - 0x73, 0x74, 0x20, 0x50, 0x41, 0x41, 0x20, 0x46, 0x46, 0x46, 0x31, 0x30, 0x20, 0x17, 0x0D, 0x32, 0x31, 0x30, 0x36, - 0x32, 0x38, 0x31, 0x34, 0x32, 0x33, 0x34, 0x33, 0x5A, 0x18, 0x0F, 0x39, 0x39, 0x39, 0x39, 0x31, 0x32, 0x33, 0x31, - 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5A, 0x30, 0x1F, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, - 0x14, 0x4D, 0x61, 0x74, 0x74, 0x65, 0x72, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x50, 0x41, 0x41, 0x20, 0x46, 0x46, - 0x46, 0x31, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, - 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x1B, 0x98, 0xAC, 0x5B, 0xBC, 0x11, 0xDC, 0x6A, 0x17, - 0x55, 0xA0, 0x5B, 0x0A, 0xC5, 0xE1, 0x6B, 0xA0, 0x2C, 0x46, 0xEE, 0x6F, 0xC2, 0xBB, 0xE7, 0x6F, 0xF7, 0xCF, 0x6C, - 0xA7, 0xAA, 0x4E, 0x9F, 0xD1, 0xD7, 0x98, 0xDC, 0xBE, 0xFB, 0x4F, 0xEA, 0xE2, 0x25, 0xD3, 0x77, 0x3C, 0x91, 0x34, - 0x8C, 0xC2, 0x6D, 0x49, 0x31, 0x31, 0xE3, 0x09, 0x63, 0x2D, 0x5E, 0x9E, 0xF3, 0x1D, 0x12, 0xDE, 0x93, 0xA3, 0x63, - 0x30, 0x61, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, - 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1D, 0x06, - 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0xEF, 0x18, 0xE0, 0xEC, 0xD4, 0x66, 0x04, 0x34, 0xDF, 0x0D, 0xBC, - 0x91, 0x1E, 0xD4, 0x52, 0x16, 0x99, 0x66, 0x83, 0x9F, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, - 0x16, 0x80, 0x14, 0xEF, 0x18, 0xE0, 0xEC, 0xD4, 0x66, 0x04, 0x34, 0xDF, 0x0D, 0xBC, 0x91, 0x1E, 0xD4, 0x52, 0x16, - 0x99, 0x66, 0x83, 0x9F, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, - 0x30, 0x45, 0x02, 0x21, 0x00, 0xA7, 0xFA, 0x5F, 0xA7, 0x66, 0xFF, 0xF7, 0xB5, 0xFD, 0x15, 0x8C, 0xD3, 0x4F, 0x62, - 0x5D, 0x48, 0x91, 0x20, 0x0E, 0x05, 0x85, 0x0E, 0xF1, 0x25, 0xF6, 0xDE, 0xE7, 0x56, 0x54, 0xF9, 0x97, 0x36, 0x02, - 0x20, 0x23, 0xB5, 0x1B, 0x6E, 0x42, 0x53, 0x28, 0x28, 0xDB, 0x09, 0x92, 0x03, 0x37, 0x05, 0x0D, 0x70, 0xF0, 0xB6, - 0xB7, 0x2C, 0xCD, 0x3C, 0xB7, 0x81, 0xE6, 0x71, 0xAC, 0x22, 0x5D, 0xF5, 0x47, 0x2B }, - { 0xEF, 0x18, 0xE0, 0xEC, 0xD4, 0x66, 0x04, 0x34, 0xDF, 0x0D, - 0xBC, 0x91, 0x1E, 0xD4, 0x52, 0x16, 0x99, 0x66, 0x83, 0x9F } }, - { /* - credentials/test/attestation/Chip-Test-PAA-FFF2-Cert.pem - -----BEGIN CERTIFICATE----- - MIIBnTCCAUKgAwIBAgIIA5KnZVo+bHcwCgYIKoZIzj0EAwIwHzEdMBsGA1UEAwwU - TWF0dGVyIFRlc3QgUEFBIEZGRjIwIBcNMjEwNjI4MTQyMzQzWhgPOTk5OTEyMzEy - MzU5NTlaMB8xHTAbBgNVBAMMFE1hdHRlciBUZXN0IFBBQSBGRkYyMFkwEwYHKoZI - zj0CAQYIKoZIzj0DAQcDQgAEdW4YkvnpULAOlQqilfM1sEhLh20i4m+WZZLKweUQ - 1f6Zsx1cmIgWeorWUDd+dRD7dYI8fluYuMAG7F8Gz66FSqNmMGQwEgYDVR0TAQH/ - BAgwBgEB/wIBATAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFOfv6sMzXF/Qw+Y0 - Up8WcEbEvKVcMB8GA1UdIwQYMBaAFOfv6sMzXF/Qw+Y0Up8WcEbEvKVcMAoGCCqG - SM49BAMCA0kAMEYCIQCSUQ0dYCFfARvaLqeV/ssklO+QppeHrQr8IGxhjAnMUgIh - AKA2sK+D40VcCTi5S/9HdRlyuNy+cZyfYbVW7LTqF8xX - -----END CERTIFICATE----- - */ - { 0x30, 0x82, 0x01, 0x9D, 0x30, 0x82, 0x01, 0x42, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x03, 0x92, 0xA7, 0x65, - 0x5A, 0x3E, 0x6C, 0x77, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x1F, 0x31, - 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x14, 0x4D, 0x61, 0x74, 0x74, 0x65, 0x72, 0x20, 0x54, 0x65, - 0x73, 0x74, 0x20, 0x50, 0x41, 0x41, 0x20, 0x46, 0x46, 0x46, 0x32, 0x30, 0x20, 0x17, 0x0D, 0x32, 0x31, 0x30, 0x36, - 0x32, 0x38, 0x31, 0x34, 0x32, 0x33, 0x34, 0x33, 0x5A, 0x18, 0x0F, 0x39, 0x39, 0x39, 0x39, 0x31, 0x32, 0x33, 0x31, - 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5A, 0x30, 0x1F, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, - 0x14, 0x4D, 0x61, 0x74, 0x74, 0x65, 0x72, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x50, 0x41, 0x41, 0x20, 0x46, 0x46, - 0x46, 0x32, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, - 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x75, 0x6E, 0x18, 0x92, 0xF9, 0xE9, 0x50, 0xB0, 0x0E, - 0x95, 0x0A, 0xA2, 0x95, 0xF3, 0x35, 0xB0, 0x48, 0x4B, 0x87, 0x6D, 0x22, 0xE2, 0x6F, 0x96, 0x65, 0x92, 0xCA, 0xC1, - 0xE5, 0x10, 0xD5, 0xFE, 0x99, 0xB3, 0x1D, 0x5C, 0x98, 0x88, 0x16, 0x7A, 0x8A, 0xD6, 0x50, 0x37, 0x7E, 0x75, 0x10, - 0xFB, 0x75, 0x82, 0x3C, 0x7E, 0x5B, 0x98, 0xB8, 0xC0, 0x06, 0xEC, 0x5F, 0x06, 0xCF, 0xAE, 0x85, 0x4A, 0xA3, 0x66, - 0x30, 0x64, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xFF, - 0x02, 0x01, 0x01, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, - 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0xE7, 0xEF, 0xEA, 0xC3, 0x33, 0x5C, 0x5F, 0xD0, - 0xC3, 0xE6, 0x34, 0x52, 0x9F, 0x16, 0x70, 0x46, 0xC4, 0xBC, 0xA5, 0x5C, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, - 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xE7, 0xEF, 0xEA, 0xC3, 0x33, 0x5C, 0x5F, 0xD0, 0xC3, 0xE6, 0x34, 0x52, 0x9F, - 0x16, 0x70, 0x46, 0xC4, 0xBC, 0xA5, 0x5C, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, - 0x03, 0x49, 0x00, 0x30, 0x46, 0x02, 0x21, 0x00, 0x92, 0x51, 0x0D, 0x1D, 0x60, 0x21, 0x5F, 0x01, 0x1B, 0xDA, 0x2E, - 0xA7, 0x95, 0xFE, 0xCB, 0x24, 0x94, 0xEF, 0x90, 0xA6, 0x97, 0x87, 0xAD, 0x0A, 0xFC, 0x20, 0x6C, 0x61, 0x8C, 0x09, - 0xCC, 0x52, 0x02, 0x21, 0x00, 0xA0, 0x36, 0xB0, 0xAF, 0x83, 0xE3, 0x45, 0x5C, 0x09, 0x38, 0xB9, 0x4B, 0xFF, 0x47, - 0x75, 0x19, 0x72, 0xB8, 0xDC, 0xBE, 0x71, 0x9C, 0x9F, 0x61, 0xB5, 0x56, 0xEC, 0xB4, 0xEA, 0x17, 0xCC, 0x57 }, - { 0xE7, 0xEF, 0xEA, 0xC3, 0x33, 0x5C, 0x5F, 0xD0, 0xC3, 0xE6, - 0x34, 0x52, 0x9F, 0x16, 0x70, 0x46, 0xC4, 0xBC, 0xA5, 0x5C } }, - }; +/* +credentials/test/attestation/Chip-Test-PAA-FFF1-Cert.pem +-----BEGIN CERTIFICATE----- +MIIBmTCCAT+gAwIBAgIIaDhPq7kZ/N8wCgYIKoZIzj0EAwIwHzEdMBsGA1UEAwwU +TWF0dGVyIFRlc3QgUEFBIEZGRjEwIBcNMjEwNjI4MTQyMzQzWhgPOTk5OTEyMzEy +MzU5NTlaMB8xHTAbBgNVBAMMFE1hdHRlciBUZXN0IFBBQSBGRkYxMFkwEwYHKoZI +zj0CAQYIKoZIzj0DAQcDQgAEG5isW7wR3GoXVaBbCsXha6AsRu5vwrvnb/fPbKeq +Tp/R15jcvvtP6uIl03c8kTSMwm1JMTHjCWMtXp7zHRLek6NjMGEwDwYDVR0TAQH/ +BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFO8Y4OzUZgQ03w28kR7U +UhaZZoOfMB8GA1UdIwQYMBaAFO8Y4OzUZgQ03w28kR7UUhaZZoOfMAoGCCqGSM49 +BAMCA0gAMEUCIQCn+l+nZv/3tf0VjNNPYl1IkSAOBYUO8SX23udWVPmXNgIgI7Ub +bkJTKCjbCZIDNwUNcPC2tyzNPLeB5nGsIl31Rys= +-----END CERTIFICATE----- +*/ +const uint8_t kChipTestPaaFff1[] = { + 0x30, 0x82, 0x01, 0x99, 0x30, 0x82, 0x01, 0x3F, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x68, 0x38, 0x4F, 0xAB, 0xB9, 0x19, + 0xFC, 0xDF, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x1F, 0x31, 0x1D, 0x30, 0x1B, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x14, 0x4D, 0x61, 0x74, 0x74, 0x65, 0x72, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x50, 0x41, 0x41, + 0x20, 0x46, 0x46, 0x46, 0x31, 0x30, 0x20, 0x17, 0x0D, 0x32, 0x31, 0x30, 0x36, 0x32, 0x38, 0x31, 0x34, 0x32, 0x33, 0x34, 0x33, + 0x5A, 0x18, 0x0F, 0x39, 0x39, 0x39, 0x39, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5A, 0x30, 0x1F, 0x31, + 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x14, 0x4D, 0x61, 0x74, 0x74, 0x65, 0x72, 0x20, 0x54, 0x65, 0x73, 0x74, + 0x20, 0x50, 0x41, 0x41, 0x20, 0x46, 0x46, 0x46, 0x31, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, + 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x1B, 0x98, 0xAC, 0x5B, 0xBC, 0x11, + 0xDC, 0x6A, 0x17, 0x55, 0xA0, 0x5B, 0x0A, 0xC5, 0xE1, 0x6B, 0xA0, 0x2C, 0x46, 0xEE, 0x6F, 0xC2, 0xBB, 0xE7, 0x6F, 0xF7, 0xCF, + 0x6C, 0xA7, 0xAA, 0x4E, 0x9F, 0xD1, 0xD7, 0x98, 0xDC, 0xBE, 0xFB, 0x4F, 0xEA, 0xE2, 0x25, 0xD3, 0x77, 0x3C, 0x91, 0x34, 0x8C, + 0xC2, 0x6D, 0x49, 0x31, 0x31, 0xE3, 0x09, 0x63, 0x2D, 0x5E, 0x9E, 0xF3, 0x1D, 0x12, 0xDE, 0x93, 0xA3, 0x63, 0x30, 0x61, 0x30, + 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, + 0x14, 0xEF, 0x18, 0xE0, 0xEC, 0xD4, 0x66, 0x04, 0x34, 0xDF, 0x0D, 0xBC, 0x91, 0x1E, 0xD4, 0x52, 0x16, 0x99, 0x66, 0x83, 0x9F, + 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xEF, 0x18, 0xE0, 0xEC, 0xD4, 0x66, 0x04, 0x34, + 0xDF, 0x0D, 0xBC, 0x91, 0x1E, 0xD4, 0x52, 0x16, 0x99, 0x66, 0x83, 0x9F, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, + 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0xA7, 0xFA, 0x5F, 0xA7, 0x66, 0xFF, 0xF7, 0xB5, 0xFD, 0x15, + 0x8C, 0xD3, 0x4F, 0x62, 0x5D, 0x48, 0x91, 0x20, 0x0E, 0x05, 0x85, 0x0E, 0xF1, 0x25, 0xF6, 0xDE, 0xE7, 0x56, 0x54, 0xF9, 0x97, + 0x36, 0x02, 0x20, 0x23, 0xB5, 0x1B, 0x6E, 0x42, 0x53, 0x28, 0x28, 0xDB, 0x09, 0x92, 0x03, 0x37, 0x05, 0x0D, 0x70, 0xF0, 0xB6, + 0xB7, 0x2C, 0xCD, 0x3C, 0xB7, 0x81, 0xE6, 0x71, 0xAC, 0x22, 0x5D, 0xF5, 0x47, 0x2B +}; - size_t paaLookupTableIdx; - for (paaLookupTableIdx = 0; paaLookupTableIdx < ArraySize(sPAALookupTable); ++paaLookupTableIdx) - { - if (skid.data_equal(ByteSpan(sPAALookupTable[paaLookupTableIdx].mSKID))) - { - break; - } - } +/* +credentials/test/attestation/Chip-Test-PAA-FFF2-Cert.pem +-----BEGIN CERTIFICATE----- +MIIBnTCCAUKgAwIBAgIIA5KnZVo+bHcwCgYIKoZIzj0EAwIwHzEdMBsGA1UEAwwU +TWF0dGVyIFRlc3QgUEFBIEZGRjIwIBcNMjEwNjI4MTQyMzQzWhgPOTk5OTEyMzEy +MzU5NTlaMB8xHTAbBgNVBAMMFE1hdHRlciBUZXN0IFBBQSBGRkYyMFkwEwYHKoZI +zj0CAQYIKoZIzj0DAQcDQgAEdW4YkvnpULAOlQqilfM1sEhLh20i4m+WZZLKweUQ +1f6Zsx1cmIgWeorWUDd+dRD7dYI8fluYuMAG7F8Gz66FSqNmMGQwEgYDVR0TAQH/ +BAgwBgEB/wIBATAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFOfv6sMzXF/Qw+Y0 +Up8WcEbEvKVcMB8GA1UdIwQYMBaAFOfv6sMzXF/Qw+Y0Up8WcEbEvKVcMAoGCCqG +SM49BAMCA0kAMEYCIQCSUQ0dYCFfARvaLqeV/ssklO+QppeHrQr8IGxhjAnMUgIh +AKA2sK+D40VcCTi5S/9HdRlyuNy+cZyfYbVW7LTqF8xX +-----END CERTIFICATE----- +*/ +const uint8_t kChipTestPaaFff2[] = { + 0x30, 0x82, 0x01, 0x9D, 0x30, 0x82, 0x01, 0x42, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x03, 0x92, 0xA7, 0x65, 0x5A, 0x3E, + 0x6C, 0x77, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x1F, 0x31, 0x1D, 0x30, 0x1B, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x14, 0x4D, 0x61, 0x74, 0x74, 0x65, 0x72, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x50, 0x41, 0x41, + 0x20, 0x46, 0x46, 0x46, 0x32, 0x30, 0x20, 0x17, 0x0D, 0x32, 0x31, 0x30, 0x36, 0x32, 0x38, 0x31, 0x34, 0x32, 0x33, 0x34, 0x33, + 0x5A, 0x18, 0x0F, 0x39, 0x39, 0x39, 0x39, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5A, 0x30, 0x1F, 0x31, + 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x14, 0x4D, 0x61, 0x74, 0x74, 0x65, 0x72, 0x20, 0x54, 0x65, 0x73, 0x74, + 0x20, 0x50, 0x41, 0x41, 0x20, 0x46, 0x46, 0x46, 0x32, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, + 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x75, 0x6E, 0x18, 0x92, 0xF9, 0xE9, + 0x50, 0xB0, 0x0E, 0x95, 0x0A, 0xA2, 0x95, 0xF3, 0x35, 0xB0, 0x48, 0x4B, 0x87, 0x6D, 0x22, 0xE2, 0x6F, 0x96, 0x65, 0x92, 0xCA, + 0xC1, 0xE5, 0x10, 0xD5, 0xFE, 0x99, 0xB3, 0x1D, 0x5C, 0x98, 0x88, 0x16, 0x7A, 0x8A, 0xD6, 0x50, 0x37, 0x7E, 0x75, 0x10, 0xFB, + 0x75, 0x82, 0x3C, 0x7E, 0x5B, 0x98, 0xB8, 0xC0, 0x06, 0xEC, 0x5F, 0x06, 0xCF, 0xAE, 0x85, 0x4A, 0xA3, 0x66, 0x30, 0x64, 0x30, + 0x12, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xFF, 0x02, 0x01, 0x01, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, + 0x04, 0x16, 0x04, 0x14, 0xE7, 0xEF, 0xEA, 0xC3, 0x33, 0x5C, 0x5F, 0xD0, 0xC3, 0xE6, 0x34, 0x52, 0x9F, 0x16, 0x70, 0x46, 0xC4, + 0xBC, 0xA5, 0x5C, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xE7, 0xEF, 0xEA, 0xC3, 0x33, + 0x5C, 0x5F, 0xD0, 0xC3, 0xE6, 0x34, 0x52, 0x9F, 0x16, 0x70, 0x46, 0xC4, 0xBC, 0xA5, 0x5C, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, + 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x49, 0x00, 0x30, 0x46, 0x02, 0x21, 0x00, 0x92, 0x51, 0x0D, 0x1D, 0x60, 0x21, 0x5F, + 0x01, 0x1B, 0xDA, 0x2E, 0xA7, 0x95, 0xFE, 0xCB, 0x24, 0x94, 0xEF, 0x90, 0xA6, 0x97, 0x87, 0xAD, 0x0A, 0xFC, 0x20, 0x6C, 0x61, + 0x8C, 0x09, 0xCC, 0x52, 0x02, 0x21, 0x00, 0xA0, 0x36, 0xB0, 0xAF, 0x83, 0xE3, 0x45, 0x5C, 0x09, 0x38, 0xB9, 0x4B, 0xFF, 0x47, + 0x75, 0x19, 0x72, 0xB8, 0xDC, 0xBE, 0x71, 0x9C, 0x9F, 0x61, 0xB5, 0x56, 0xEC, 0xB4, 0xEA, 0x17, 0xCC, 0x57 +}; - VerifyOrReturnError(paaLookupTableIdx < ArraySize(sPAALookupTable), CHIP_ERROR_INVALID_ARGUMENT); +const ByteSpan kTestPaaRoots[] = { + ByteSpan{ kChipTestPaaFff1 }, + ByteSpan{ kChipTestPaaFff2 }, +}; - return CopySpanToMutableSpan(ByteSpan{ sPAALookupTable[paaLookupTableIdx].mPAACertificate }, outDacBuffer); -} +const ArrayAttestationTrustStore kTestAttestationTrustStore{ &kTestPaaRoots[0], ArraySize(kTestPaaRoots) }; +/** + * @brief Look-up of well-known keys used for CD signing by CSA. + * + * Current version uses only test key/cert provided in spec. + */ CHIP_ERROR GetCertificationDeclarationCertificate(const ByteSpan & skid, MutableByteSpan & outCertificate) { struct CertChainLookupTable { const uint8_t mCertificate[kMax_x509_Certificate_Length]; - const uint8_t mSKID[kKeyIdentifierLength]; + const uint8_t mSKID[Crypto::kSubjectKeyIdentifierLength]; }; static CertChainLookupTable @@ -191,6 +175,8 @@ CHIP_ERROR GetCertificationDeclarationCertificate(const ByteSpan & skid, Mutable class DefaultDACVerifier : public DeviceAttestationVerifier { public: + DefaultDACVerifier(const AttestationTrustStore * paaRootStore) : mAttestationTrustStore(paaRootStore) {} + AttestationVerificationResult VerifyAttestationInformation(const ByteSpan & attestationInfoBuffer, const ByteSpan & attestationChallengeBuffer, const ByteSpan & attestationSignatureBuffer, @@ -203,6 +189,11 @@ class DefaultDACVerifier : public DeviceAttestationVerifier AttestationVerificationResult ValidateCertificateDeclarationPayload(const ByteSpan & certDeclBuffer, const ByteSpan & firmwareInfo, const DeviceInfoForAttestation & deviceInfo) override; + +protected: + DefaultDACVerifier() {} + + const AttestationTrustStore * mAttestationTrustStore; }; AttestationVerificationResult DefaultDACVerifier::VerifyAttestationInformation(const ByteSpan & attestationInfoBuffer, @@ -246,7 +237,7 @@ AttestationVerificationResult DefaultDACVerifier::VerifyAttestationInformation(c deviceSignature) == CHIP_NO_ERROR, AttestationVerificationResult::kAttestationSignatureInvalid); - uint8_t akidBuf[Credentials::kKeyIdentifierLength]; + uint8_t akidBuf[Crypto::kAuthorityKeyIdentifierLength]; MutableByteSpan akid(akidBuf); ExtractAKIDFromX509Cert(paiCertDerBuffer, akid); @@ -254,7 +245,7 @@ AttestationVerificationResult DefaultDACVerifier::VerifyAttestationInformation(c chip::Platform::ScopedMemoryBuffer paaCert; VerifyOrReturnError(paaCert.Alloc(paaCertAllocatedLen), AttestationVerificationResult::kNoMemory); MutableByteSpan paa(paaCert.Get(), paaCertAllocatedLen); - VerifyOrReturnError(GetProductAttestationAuthorityCert(akid, paa) == CHIP_NO_ERROR, + VerifyOrReturnError(mAttestationTrustStore->GetProductAttestationAuthorityCert(akid, paa) == CHIP_NO_ERROR, AttestationVerificationResult::kPaaNotFound); VerifyOrReturnError(ValidateCertificateChain(paa.data(), paa.size(), paiCertDerBuffer.data(), paiCertDerBuffer.size(), @@ -279,9 +270,9 @@ AttestationVerificationResult DefaultDACVerifier::VerifyAttestationInformation(c ByteSpan firmwareInfoSpan; DeviceAttestationVendorReservedDeconstructor vendorReserved; - VerifyOrReturnError(DeconstructAttestationElements(attestationInfoBuffer, certificationDeclarationSpan, attestationNonceSpan, - timestampDeconstructed, firmwareInfoSpan, vendorReserved) == CHIP_NO_ERROR, - AttestationVerificationResult::kAttestationElementsMalformed); + CHIP_ERROR status = DeconstructAttestationElements(attestationInfoBuffer, certificationDeclarationSpan, attestationNonceSpan, + timestampDeconstructed, firmwareInfoSpan, vendorReserved); + VerifyOrReturnError(status == CHIP_NO_ERROR, AttestationVerificationResult::kAttestationElementsMalformed); // Verify that Nonce matches with what we sent VerifyOrReturnError(attestationNonceSpan.data_equal(attestationNonce), @@ -397,9 +388,14 @@ AttestationVerificationResult DefaultDACVerifier::ValidateCertificateDeclaration } // namespace -DeviceAttestationVerifier * GetDefaultDACVerifier() +const AttestationTrustStore * GetTestAttestationTrustStore() +{ + return &kTestAttestationTrustStore; +} + +DeviceAttestationVerifier * GetDefaultDACVerifier(const AttestationTrustStore * paaRootStore) { - static DefaultDACVerifier defaultDACVerifier; + static DefaultDACVerifier defaultDACVerifier{ paaRootStore }; return &defaultDACVerifier; } diff --git a/src/credentials/examples/DefaultDeviceAttestationVerifier.h b/src/credentials/examples/DefaultDeviceAttestationVerifier.h index aad200fdd3e434..4198e1c147348b 100644 --- a/src/credentials/examples/DefaultDeviceAttestationVerifier.h +++ b/src/credentials/examples/DefaultDeviceAttestationVerifier.h @@ -21,14 +21,30 @@ namespace chip { namespace Credentials { +/** + * @brief Get implementation of a PAA root store containing a basic set of static PAA roots + * sufficient for *testing* only. + * + * WARNING: The PAA list known to this PAA root store is a reduced subset that will likely + * cause users of it to fail attestation procedure in some cases. This is provided + * to support tests and examples, not to be used by real commissioners, as it + * contains several test roots which are not trustworthy for certified product usage. + * + * @returns a singleton AttestationTrustStore that contains some well-known PAA test root certs. + */ +const AttestationTrustStore * GetTestAttestationTrustStore(); + /** * @brief Get implementation of a sample DAC verifier to validate device * attestation procedure. * - * @returns a singleton DeviceAttestationVerifier that relies on no - * storage abstractions. + * @param[in] paaRootStore Pointer to the AttestationTrustStore instance to be used by implementation + * of default DeviceAttestationVerifier. Caller must ensure storage is + * always available while the DeviceAttestationVerifier could be used. + * + * @returns a singleton DeviceAttestationVerifier that satisfies basic device attestation procedure requirements. */ -DeviceAttestationVerifier * GetDefaultDACVerifier(); +DeviceAttestationVerifier * GetDefaultDACVerifier(const AttestationTrustStore * paaRootStore); } // namespace Credentials } // namespace chip diff --git a/src/credentials/tests/TestCertificationDeclaration.cpp b/src/credentials/tests/TestCertificationDeclaration.cpp index 12e49518de3e8f..3d15f39f2ea02e 100644 --- a/src/credentials/tests/TestCertificationDeclaration.cpp +++ b/src/credentials/tests/TestCertificationDeclaration.cpp @@ -247,7 +247,7 @@ static void TestCD_CMSSignAndVerify(nlTestSuite * inSuite, void * inContext) { ByteSpan cdContentIn(sTestCMS_CDContent01); ByteSpan cdContentOut; - uint8_t signerKeyIdBuf[kKeyIdentifierLength]; + uint8_t signerKeyIdBuf[Crypto::kSubjectKeyIdentifierLength]; MutableByteSpan signerKeyId(signerKeyIdBuf); uint8_t signedMessageBuf[kMaxCMSSignedCDMessage]; MutableByteSpan signedMessage(signedMessageBuf); @@ -297,7 +297,7 @@ static void TestCD_CMSVerifyAndExtract(nlTestSuite * inSuite, void * inContext) NL_TEST_ASSERT(inSuite, testCase.cdContent.data_equal(cdContentOut)); // Test CMS_ExtractKeyId() - uint8_t signerKeyIdBuf[kKeyIdentifierLength]; + uint8_t signerKeyIdBuf[Crypto::kSubjectKeyIdentifierLength]; MutableByteSpan signerKeyId(signerKeyIdBuf); NL_TEST_ASSERT(inSuite, ExtractSKIDFromX509Cert(testCase.signerCert, signerKeyId) == CHIP_NO_ERROR); diff --git a/src/credentials/tests/TestDeviceAttestationCredentials.cpp b/src/credentials/tests/TestDeviceAttestationCredentials.cpp index f706582ddc087e..ea2de206212702 100644 --- a/src/credentials/tests/TestDeviceAttestationCredentials.cpp +++ b/src/credentials/tests/TestDeviceAttestationCredentials.cpp @@ -195,8 +195,7 @@ static void TestDACVerifierExample_AttestationInfoVerification(nlTestSuite * inS default_verifier->VerifyAttestationInformation(ByteSpan(), ByteSpan(), ByteSpan(), ByteSpan(), ByteSpan(), ByteSpan()); NL_TEST_ASSERT(inSuite, attestation_result == AttestationVerificationResult::kNotImplemented); - // Replace default verifier with example verifier - DeviceAttestationVerifier * example_dac_verifier = GetDefaultDACVerifier(); + DeviceAttestationVerifier * example_dac_verifier = GetDefaultDACVerifier(GetTestAttestationTrustStore()); NL_TEST_ASSERT(inSuite, example_dac_verifier != nullptr); NL_TEST_ASSERT(inSuite, default_verifier != example_dac_verifier); @@ -252,7 +251,7 @@ static void TestDACVerifierExample_CertDeclarationVerification(nlTestSuite * inS CHIP_ERROR err = CHIP_NO_ERROR; // Replace default verifier with example verifier - DeviceAttestationVerifier * example_dac_verifier = GetDefaultDACVerifier(); + DeviceAttestationVerifier * example_dac_verifier = GetDefaultDACVerifier(GetTestAttestationTrustStore()); NL_TEST_ASSERT(inSuite, example_dac_verifier != nullptr); SetDeviceAttestationVerifier(example_dac_verifier); @@ -295,6 +294,80 @@ static void TestDACVerifierExample_CertDeclarationVerification(nlTestSuite * inS NL_TEST_ASSERT(inSuite, attestation_result == AttestationVerificationResult::kSuccess); } +static void TestAttestationTrustStore(nlTestSuite * inSuite, void * inContext) +{ + uint8_t kPaaFff1Start[] = { 0x30, 0x82, 0x01, 0x99, 0x30, 0x82, 0x01, 0x3F, 0xA0, 0x03, 0x02, 0x01, 0x02, + 0x02, 0x08, 0x68, 0x38, 0x4F, 0xAB, 0xB9, 0x19, 0xFC, 0xDF, 0x30, 0x0A, 0x06, + 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x1F, 0x31 }; + uint8_t kPaaFff1Skid[] = { 0xEF, 0x18, 0xE0, 0xEC, 0xD4, 0x66, 0x04, 0x34, 0xDF, 0x0D, + 0xBC, 0x91, 0x1E, 0xD4, 0x52, 0x16, 0x99, 0x66, 0x83, 0x9F }; + + uint8_t kPaaFff2Start[] = { 0x30, 0x82, 0x01, 0x9D, 0x30, 0x82, 0x01, 0x42, 0xA0, 0x03, 0x02, 0x01, 0x02, + 0x02, 0x08, 0x03, 0x92, 0xA7, 0x65, 0x5A, 0x3E, 0x6C, 0x77, 0x30, 0x0A, 0x06, + 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x1F, 0x31 }; + uint8_t kPaaFff2Skid[] = { 0xE7, 0xEF, 0xEA, 0xC3, 0x33, 0x5C, 0x5F, 0xD0, 0xC3, 0xE6, + 0x34, 0x52, 0x9F, 0x16, 0x70, 0x46, 0xC4, 0xBC, 0xA5, 0x5C }; + + // SKID to trigger CHIP_ERROR_INVALID_ARGUMENT + uint8_t kPaaBadSkid1[] = { 0xE7, 0xEF, 0xEA, 0xC3, 0x33, 0x5C, 0xD0, 0xC3, 0xE6, 0x34, + 0x52, 0x9F, 0x16, 0x70, 0x46, 0xC4, 0xBC, 0xA5, 0x5C }; + ByteSpan kPaaBadSkidSpan1{ kPaaBadSkid1 }; + + // SKID to trigger CHIP_ERROR_INVALID_ARGUMENT + ByteSpan kPaaBadSkidSpan2{ nullptr, sizeof(kPaaFff2Skid) }; + + // SKID to trigger CHIP_ERROR_CA_CERT_NOT_FOUND + uint8_t kPaaGoodSkidNotPresent[] = { 0xE7, 0xEF, 0xEA, 0xC3, 0x33, 0x5C, 0x5F, 0xD0, 0xC3, 0xE6, + 0x34, 0x52, 0x9F, 0x16, 0x70, 0xFF, 0xFF, 0xBC, 0xA5, 0x5C }; + + struct TestCase + { + ByteSpan skidSpan; + ByteSpan startSpan; + CHIP_ERROR expectedResult; + }; + + const TestCase kTestCases[] = { + { .skidSpan = ByteSpan{ kPaaFff1Skid }, .startSpan = ByteSpan{ kPaaFff1Start }, .expectedResult = CHIP_NO_ERROR }, + { .skidSpan = ByteSpan{ kPaaFff2Skid }, .startSpan = ByteSpan{ kPaaFff2Start }, .expectedResult = CHIP_NO_ERROR }, + { .skidSpan = ByteSpan{ kPaaFff2Skid }, + .startSpan = ByteSpan{ kPaaFff2Start }, + .expectedResult = CHIP_ERROR_BUFFER_TOO_SMALL }, + { .skidSpan = kPaaBadSkidSpan1, .startSpan = ByteSpan{}, .expectedResult = CHIP_ERROR_INVALID_ARGUMENT }, + { .skidSpan = kPaaBadSkidSpan2, .startSpan = ByteSpan{}, .expectedResult = CHIP_ERROR_INVALID_ARGUMENT }, + { .skidSpan = ByteSpan{ kPaaGoodSkidNotPresent }, .startSpan = ByteSpan{}, .expectedResult = CHIP_ERROR_CA_CERT_NOT_FOUND }, + }; + + const AttestationTrustStore * testAttestationTrustStore = GetTestAttestationTrustStore(); + NL_TEST_ASSERT(inSuite, testAttestationTrustStore != nullptr); + + size_t testCaseIdx = 0; + for (const auto & testCase : kTestCases) + { + uint8_t buf[kMaxDERCertLength]; + MutableByteSpan paaCertSpan{ buf }; + if (testCase.expectedResult == CHIP_ERROR_BUFFER_TOO_SMALL) + { + // Make the output much too small if checking for size handling + paaCertSpan = paaCertSpan.SubSpan(0, 16); + } + + // Try to obtain cert + CHIP_ERROR result = testAttestationTrustStore->GetProductAttestationAuthorityCert(testCase.skidSpan, paaCertSpan); + NL_TEST_ASSERT(inSuite, result == testCase.expectedResult); + + // In success cases, make sure the start of the cert matches expectation. Not using full certs + // to avoid repeating the known constants here. + if (testCase.expectedResult == CHIP_NO_ERROR) + { + NL_TEST_ASSERT(inSuite, paaCertSpan.size() > testCase.startSpan.size()); + paaCertSpan = paaCertSpan.SubSpan(0, testCase.startSpan.size()); + NL_TEST_ASSERT(inSuite, paaCertSpan.data_equal(testCase.startSpan) == true); + } + ++testCaseIdx; + } +} + /** * Set up the test suite. */ @@ -326,6 +399,7 @@ int TestDeviceAttestation_Teardown(void * inContext) static const nlTest sTests[] = { NL_TEST_DEF("Test Example Device Attestation Credentials Providers", TestDACProvidersExample_Providers), NL_TEST_DEF("Test Example Device Attestation Signature", TestDACProvidersExample_Signature), + NL_TEST_DEF("Test the 'for testing' Paa Root Store", TestAttestationTrustStore), NL_TEST_DEF("Test Example Device Attestation Information Verification", TestDACVerifierExample_AttestationInfoVerification), NL_TEST_DEF("Test Example Device Attestation Certification Declaration Verification", TestDACVerifierExample_CertDeclarationVerification), NL_TEST_SENTINEL() diff --git a/src/crypto/CHIPCryptoPAL.h b/src/crypto/CHIPCryptoPAL.h index 1d55e72a060cbd..78a58be47eb604 100644 --- a/src/crypto/CHIPCryptoPAL.h +++ b/src/crypto/CHIPCryptoPAL.h @@ -46,6 +46,8 @@ constexpr size_t kP256_ECDSA_Signature_Length_Raw = (2 * kP256_FE_Length); constexpr size_t kP256_Point_Length = (2 * kP256_FE_Length + 1); constexpr size_t kSHA256_Hash_Length = 32; constexpr size_t kSHA1_Hash_Length = 20; +constexpr size_t kSubjectKeyIdentifierLength = kSHA1_Hash_Length; +constexpr size_t kAuthorityKeyIdentifierLength = kSHA1_Hash_Length; constexpr size_t CHIP_CRYPTO_GROUP_SIZE_BYTES = kP256_FE_Length; constexpr size_t CHIP_CRYPTO_PUBLIC_KEY_SIZE_BYTES = kP256_Point_Length; diff --git a/src/crypto/tests/CHIPCryptoPALTest.cpp b/src/crypto/tests/CHIPCryptoPALTest.cpp index df2a737913afd6..dc3989bec15880 100644 --- a/src/crypto/tests/CHIPCryptoPALTest.cpp +++ b/src/crypto/tests/CHIPCryptoPALTest.cpp @@ -1874,7 +1874,7 @@ static void TestSKID_x509Extraction(nlTestSuite * inSuite, void * inContext) HeapChecker heapChecker(inSuite); CHIP_ERROR err = CHIP_NO_ERROR; - uint8_t skidBuf[Credentials::kKeyIdentifierLength]; + uint8_t skidBuf[kSubjectKeyIdentifierLength]; MutableByteSpan skidOut(skidBuf); ByteSpan cert; @@ -1901,7 +1901,7 @@ static void TestAKID_x509Extraction(nlTestSuite * inSuite, void * inContext) HeapChecker heapChecker(inSuite); CHIP_ERROR err = CHIP_NO_ERROR; - uint8_t akidBuf[Credentials::kKeyIdentifierLength]; + uint8_t akidBuf[kAuthorityKeyIdentifierLength]; MutableByteSpan akidOut(akidBuf); ByteSpan cert; diff --git a/src/darwin/Framework/CHIP/CHIPDeviceController.mm b/src/darwin/Framework/CHIP/CHIPDeviceController.mm index 794d6ed7ccd24f..1986c664cdbcda 100644 --- a/src/darwin/Framework/CHIP/CHIPDeviceController.mm +++ b/src/darwin/Framework/CHIP/CHIPDeviceController.mm @@ -190,7 +190,9 @@ - (BOOL)startup:(_Nullable id)storageDelegate } // Initialize device attestation verifier - chip::Credentials::SetDeviceAttestationVerifier(chip::Credentials::GetDefaultDACVerifier()); + // TODO: Replace testingRootStore with a AttestationTrustStore that has the necessary official PAA roots available + const chip::Credentials::AttestationTrustStore * testingRootStore = chip::Credentials::GetTestAttestationTrustStore(); + chip::Credentials::SetDeviceAttestationVerifier(chip::Credentials::GetDefaultDACVerifier(testingRootStore)); params.fabricStorage = _fabricStorage; commissionerParams.storageDelegate = _persistentStorageDelegateBridge; diff --git a/src/protocols/secure_channel/CASESession.h b/src/protocols/secure_channel/CASESession.h index a8bbadd3cf1b75..71cda76e5eabd7 100644 --- a/src/protocols/secure_channel/CASESession.h +++ b/src/protocols/secure_channel/CASESession.h @@ -47,7 +47,7 @@ namespace chip { constexpr uint16_t kSigmaParamRandomNumberSize = 32; -constexpr uint16_t kTrustedRootIdSize = Credentials::kKeyIdentifierLength; +constexpr uint16_t kTrustedRootIdSize = Crypto::kSubjectKeyIdentifierLength; constexpr uint16_t kMaxTrustedRootIds = 5; constexpr uint16_t kIPKSize = 16;