From 96c935789d74934f74af0b7d22679909e0c38ec8 Mon Sep 17 00:00:00 2001 From: Evgeny Margolis Date: Thu, 20 Oct 2022 12:40:30 -0700 Subject: [PATCH] [SVE2] Cherry Pick Matter Official CDs and CD Trusted Storage Implementation (#23239) * Add missing pthread header (#22833) * [build] Fix #21255 - allow circular initialization of SimpleStateMachine test. (#22461) * [build] Fix #21255 - allow circular initialization of SimpleStateMachine test. * [build] Add comment per review feedback. * [Darwin][AttestationVerifier] Expose a mechanism to customise cd signing keys and use it in darwin (#22338) * Add AttestationTrustStore::GetCertificationDeclarationCert virtual method to allow controllers passing in some CD certs * Add cdCerts member to MTRControllerFactoryparams and override AttestationTrustStore::GetCertificationDeclarationCert * Implement ArrayTrustStore::GetCertificationDeclarationSigningKey and initialize the test ArrayTrustStore store with the test CD cert * Update the FileAttestationTrustStore to read a directory with der certs for certification declaration verification * Add credentials/development/cd-certs/ and update chip-tool to use it if desired * Update API to match conversation - Remove CD stuff from FileAttestationTrustStore - Refactor FileAttestationTrustStore to allow loading of any X.509 cert directory - Add a command line to chip-tool to disallow test keys (`only-allow-trusted-cd-keys`) - Add plumbing to enable CD keys lookup properly without mixing-up with PAA semantics - Add official CD verifying key and official SDK CD test key in the default CD trust store as-is * Update src/darwin to take into account the proposed changes * Add unit test for `CsaCdKeysTrustStore` Co-authored-by: Tennessee Carmel-Veilleux * [Attestation] Updated to Use CD Signed by a Valid CSA Cert (#22685) * Updated CSA Official CD Signing Certificates (#23027) * restyled. * Remove fixed versioning for git in cirque (#23257) Co-authored-by: Gene Harvey Co-authored-by: Martin Turon Co-authored-by: Vivien Nicolas Co-authored-by: Tennessee Carmel-Veilleux Co-authored-by: Andrei Litvin --- .../CSA_Matter_CD_Signing_Key_001.cert.der | Bin 0 -> 523 bytes .../CSA_Matter_CD_Signing_Key_001.cert.pem | 13 + .../CSA_Matter_CD_Signing_Key_002.cert.der | Bin 0 -> 524 bytes .../CSA_Matter_CD_Signing_Key_002.cert.pem | 13 + .../CSA_Matter_CD_Signing_Key_003.cert.der | Bin 0 -> 522 bytes .../CSA_Matter_CD_Signing_Key_003.cert.pem | 13 + .../CSA_Matter_CD_Signing_Key_004.cert.der | Bin 0 -> 522 bytes .../CSA_Matter_CD_Signing_Key_004.cert.pem | 13 + .../CSA_Matter_CD_Signing_Key_005.cert.der | Bin 0 -> 523 bytes .../CSA_Matter_CD_Signing_Key_005.cert.pem | 13 + ...tter_Certificate_and_Testing_Root.cert.der | Bin 0 -> 517 bytes ...tter_Certificate_and_Testing_Root.cert.pem | 13 + .../cd-certs/Chip-Test-CD-Cert.der | Bin 0 -> 439 bytes .../cd-certs/Chip-Test-CD-Cert.pem | 12 + .../chip-tool/commands/common/CHIPCommand.cpp | 88 +++-- .../chip-tool/commands/common/CHIPCommand.h | 10 +- .../common/CredentialIssuerCommands.h | 30 ++ .../example/ExampleCredentialIssuerCommands.h | 51 ++- .../interaction_model/DecoderCustomLog.cpp | 15 +- examples/platform/linux/NamedPipeCommands.cpp | 1 + .../chip-cirque-device-base/Dockerfile | 2 +- .../credentials/TestHarnessDACProvider.cpp | 30 +- .../DefaultDeviceAttestationVerifier.cpp | 327 ++++++++++++++---- .../DefaultDeviceAttestationVerifier.h | 36 ++ .../DeviceAttestationVerifier.h | 86 +++++ .../FileAttestationTrustStore.cpp | 75 ++-- .../FileAttestationTrustStore.h | 22 +- .../DeviceAttestationCredsExample.cpp | 34 +- .../tests/TestCertificationDeclaration.cpp | 90 +++++ .../CHIP/MTRAttestationTrustStoreBridge.mm | 5 +- .../Framework/CHIP/MTRControllerFactory.h | 6 + .../Framework/CHIP/MTRControllerFactory.mm | 18 + src/lib/core/CHIPConfig.h | 9 + src/lib/support/tests/BUILD.gn | 7 +- 34 files changed, 861 insertions(+), 171 deletions(-) create mode 100644 credentials/development/cd-certs/CSA_Matter_CD_Signing_Key_001.cert.der create mode 100644 credentials/development/cd-certs/CSA_Matter_CD_Signing_Key_001.cert.pem create mode 100644 credentials/development/cd-certs/CSA_Matter_CD_Signing_Key_002.cert.der create mode 100644 credentials/development/cd-certs/CSA_Matter_CD_Signing_Key_002.cert.pem create mode 100644 credentials/development/cd-certs/CSA_Matter_CD_Signing_Key_003.cert.der create mode 100644 credentials/development/cd-certs/CSA_Matter_CD_Signing_Key_003.cert.pem create mode 100644 credentials/development/cd-certs/CSA_Matter_CD_Signing_Key_004.cert.der create mode 100644 credentials/development/cd-certs/CSA_Matter_CD_Signing_Key_004.cert.pem create mode 100644 credentials/development/cd-certs/CSA_Matter_CD_Signing_Key_005.cert.der create mode 100644 credentials/development/cd-certs/CSA_Matter_CD_Signing_Key_005.cert.pem create mode 100644 credentials/development/cd-certs/CSA_Matter_Certificate_and_Testing_Root.cert.der create mode 100644 credentials/development/cd-certs/CSA_Matter_Certificate_and_Testing_Root.cert.pem create mode 100644 credentials/development/cd-certs/Chip-Test-CD-Cert.der create mode 100644 credentials/development/cd-certs/Chip-Test-CD-Cert.pem diff --git a/credentials/development/cd-certs/CSA_Matter_CD_Signing_Key_001.cert.der b/credentials/development/cd-certs/CSA_Matter_CD_Signing_Key_001.cert.der new file mode 100644 index 0000000000000000000000000000000000000000..0bcdc2c37db44bb15611c557ddc62233c3a18d9a GIT binary patch literal 523 zcmXqLVq!OFVqCj`nTe5!i9NYEF*zmM(144LL#xf>oGlA8lR=On50K9s%EHCN>>TW9 zsAHf7;xY3m`zDr@q!uYSrxulDre!84mSpDVDJ15lD1@XImt^LpD>yqEiWms7acQ$L zvM@F+s$pW}VR1HfG%!#Q=QT1iG%zqWv^26XHI0(sH!?6cGO#ol>e*dY6B^(A(+xBeSV5b*?9e6fbI6m(g#&drId+ zG0mMj{l9ORsku1KAO+}M=1^H-M#ldv90qJaiiwfIfDa_b4-x|gC}W#}EQrs?BE}-} z&%}P}O!qSD#CNWi!on7w{?BUr4CF!5$}AEFVhtkGpJZM*$|7GH}KS?8SVKgUQjDKdOqw4=kt?QUd!9bazS1oB&@HPAAv2q90s!u1qR{{V literal 0 HcmV?d00001 diff --git a/credentials/development/cd-certs/CSA_Matter_CD_Signing_Key_001.cert.pem b/credentials/development/cd-certs/CSA_Matter_CD_Signing_Key_001.cert.pem new file mode 100644 index 00000000000000..93697332c9f692 --- /dev/null +++ b/credentials/development/cd-certs/CSA_Matter_CD_Signing_Key_001.cert.pem @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIICBzCCAa2gAwIBAgIHY3NhY2RrMTAKBggqhkjOPQQDAjBSMQwwCgYDVQQKDAND +U0ExLDAqBgNVBAMMI01hdHRlciBDZXJ0aWZpY2F0aW9uIGFuZCBUZXN0aW5nIENB +MRQwEgYKKwYBBAGConwCAQwEQzVBMDAgFw0yMjEwMDMxOTI4NTVaGA8yMDcyMDky +MDE5Mjg1NVowWDEMMAoGA1UECgwDQ1NBMTIwMAYDVQQDDClDZXJ0aWZpY2F0aW9u +IERlY2xhcmF0aW9uIFNpZ25pbmcgS2V5IDAwMTEUMBIGCisGAQQBgqJ8AgEMBEM1 +QTAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATN7uk+RPi3K+PRqcB+IZaLmv/z +tAPwXhZp17Hlyu5vx3FLQufiNpXpLNdjVHOigK5ojze7lInhFim5uU/3sJkpo2Yw +ZDASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQU +/jQ/lZlHdjth7kU5ExM4SU/mfY4wHwYDVR0jBBgwFoAUl+Rp0MUEFMJvxwH3fpR3 +OQmN9qUwCgYIKoZIzj0EAwIDSAAwRQIgEDWOcdKsVGtUh3evHbBd1lq4aS7yQtOp +6GrOQ3/zXBsCIQDxorh2RXSaI8m2RCcoWaiWa0nLzQepNm3C2jrQVJmC2Q== +-----END CERTIFICATE----- diff --git a/credentials/development/cd-certs/CSA_Matter_CD_Signing_Key_002.cert.der b/credentials/development/cd-certs/CSA_Matter_CD_Signing_Key_002.cert.der new file mode 100644 index 0000000000000000000000000000000000000000..3e6046ac47a8b08cd49421a48961ec1c952c13e4 GIT binary patch literal 524 zcmXqLV&X7pVqCj`nTe5!i9NYEF*zmM$bgHDL#xf>oGlA8lR=On50K9s%EHCN>>TW9 zsAHf7;xY3m`zDr@q!uYSrxulDre!84mSpDVDJ15lD1@XImt^LpD>yqEiWms7acQ$L zvM@F+s$pW}VR1HfG%!#Q=QT1iG%zqWv@|v|F^iJmH!?6cGO#oct{Z3eO+J|Bx1i^yG; z+Y!-IB4HrbATs?)=7pmyB8T#iGk&j|Qf|rF`)w(5 z^e}re7`QPhGR%5+UaaQwa{fQN1TJqr`&~e~XL~{5%FuQf`Qx<~zWd97N+!Q}UZ1u0 goGlA8lR=On50K9s%EHCN>>TW9 zsAHf7;xY3m`zDr@q!uYSrxulDre!84mSpDVDJ15lD1@XImt^LpD>yqEiWms7acQ$L zvM@F+s$pW}VR1HfG%!#Q=QT1iG%zqWv@|g^FpQGmH!?6cGO#o#26n2jCmJ0?b`H<=mPnVlF|=7+~z{kuI# zUSP?6!wMW@Rikd(Mk->luB*qUC0|qE#n}IBd&&MLhBH}J! z`uu?3sulZce0_u;KRLuXb%nQqJV;uZMZ!R=L1g-q%nL_ZL=NR2XZ&6_rQDLU_uEqB z=wWteFmPc~Pzaxs+rM>YsPAgQzrPRhu%BO(`MpSCsu|O&wdsGXnSd%PrcQ0S#Z{Cu dH?O|v$6v`$`fuF66q%oGlA8lR=On50K9s%EHCN>>TW9 zsAHf7;xY3m`zDr@q!uYSrxulDre!84mSpDVDJ15lD1@XImt^LpD>yqEiWms7acQ$L zvM@F+s$pW}VR1HfG%!#Q=QT1iG%zqWv@|g`GK`YoH!?6cGO#oe;yle!^^b z%M_MsTojYxUYur-0`x9(sH`v}<9`+o12!PV#K>U42NL54i2(zYvCTjh#OGrXV-fk* z#=JOFZ-zjTUk28L+n^JDc+52rN za`Z5}GZ?rqDd;VbpSasQu|3V{sm?n{G$XuCnc8Qt;O}(fB4z fILPO_^t~LxoGlA8lR=On50K9s%EHCN>>TW9 zsAHf7;xY3m`zDr@q!uYSrxulDre!84mSpDVDJ15lD1@XImt^LpD>yqEiWms7acQ$L zvM@F+s$pW}VR1HfG%!#Q=QT1iG%zqWv@|g{G>wwrH!?6cGO#o!C>IZq{wjA-D&m{nKj-jGSf2E7;ME7+6$64$BQvWta^L?*>*z)CWT0A&(P{6 g8sAj-6+~xd#?*U%6Eb<9r*UonvX6OpoGlA8lR=On50K9s%EHCN>>TW9 zsAHf7;xY3m`zDr@q!uYSrxulDre!84mSpDVDJ15lD1@XImt^LpD>yqEiWms7acQ$L zvM@F+s$pW}VR1HfG%!#Q=QT1iFgGwav^26XFo}}jH!=hYm>C*F1!!Vxq=7ISJJ?@L zj8G3UGqN)~F|b&8Ssh*#yYF-n|1(8do3$QE`QHT>ESWTa?Tv&VkIMfaxF>J7&A7^> zr8>%rHE%^B-{kUlZ{MkkGylD5%BXs}&tq|#K?=~L%%QTvjEw(TI1Jc;6cZz(0Ut<= zA0!40N=7yVSrDI(MT|vc`jgBHM_EJ;M6VXA@%-{1@kr@SbTTNM~x-Q-QP@|_9-_Dg?Ic)VNzsxzsI1fd#8SX dO9fkF&;!v(2~CSL^DUyg<9*HFeZCo(3jkSUn}PrU literal 0 HcmV?d00001 diff --git a/credentials/development/cd-certs/CSA_Matter_Certificate_and_Testing_Root.cert.pem b/credentials/development/cd-certs/CSA_Matter_Certificate_and_Testing_Root.cert.pem new file mode 100644 index 00000000000000..5a003156fd6c65 --- /dev/null +++ b/credentials/development/cd-certs/CSA_Matter_Certificate_and_Testing_Root.cert.pem @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIICATCCAaegAwIBAgIHY3Nhcm9vdDAKBggqhkjOPQQDAjBSMQwwCgYDVQQKDAND +U0ExLDAqBgNVBAMMI01hdHRlciBDZXJ0aWZpY2F0aW9uIGFuZCBUZXN0aW5nIENB +MRQwEgYKKwYBBAGConwCAQwEQzVBMDAgFw0yMjA3MDcxOTI4MDRaGA8yMTIyMDYx +MzE5MjgwNFowUjEMMAoGA1UECgwDQ1NBMSwwKgYDVQQDDCNNYXR0ZXIgQ2VydGlm +aWNhdGlvbiBhbmQgVGVzdGluZyBDQTEUMBIGCisGAQQBgqJ8AgEMBEM1QTAwWTAT +BgcqhkjOPQIBBggqhkjOPQMBBwNCAAQ4SjrDql2+y3IP5iEdPK1IYm/3EaCkkp+t +2GD44nf/wN4fPrYzejSEe1o6BW6ocQ6Td+7t7iUXA/3ZNQEly45Io2YwZDASBgNV +HRMBAf8ECDAGAQH/AgEBMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUl+Rp0MUE +FMJvxwH3fpR3OQmN9qUwHwYDVR0jBBgwFoAUl+Rp0MUEFMJvxwH3fpR3OQmN9qUw +CgYIKoZIzj0EAwIDSAAwRQIgearlB0fCJ49UoJ6xwKPdlPEopCOL9jVCviODEleI ++mQCIQDvvDCKi7kvj4R4BoFS4BVZGCk4zJ84W4tfTTfu89lRbQ== +-----END CERTIFICATE----- diff --git a/credentials/development/cd-certs/Chip-Test-CD-Cert.der b/credentials/development/cd-certs/Chip-Test-CD-Cert.der new file mode 100644 index 0000000000000000000000000000000000000000..6a7732980d7c27cc9c00132b76e0d50da419020f GIT binary patch literal 439 zcmXqLV%%)d#2B@JnTe5!iNp2Q=ebX+7W5l%v2kd%d7QIlVP-PWHq6)$}FigP!Q)eGBhwVvM@9;GBz=elHj)l z0z)HXATqTywTvRoxJUzGHg>Q}m>8i>VrFD#c4A<$vFucG)eb%Nx${u;#XU<>GlS0T z(nRUb6Ett_~|I};k)8d%3gJc4k>#}>^zCR_m#lbDpe?dpnyK8}S-|SkPW{_ea z1oW1yFeBrC77hb8AjQPUXut;&;|GZWJieKj$HF=G4sSAZ0h%ZE=&qKAu&&$gx^^9;pWZVudls%c=um@PwuRo x&!tB4$9^3bZedagVXt^mVp$Ya_xAPrh>RqKtqv8R&iW-S&w74(r~X%;ZUDT0mhb=o literal 0 HcmV?d00001 diff --git a/credentials/development/cd-certs/Chip-Test-CD-Cert.pem b/credentials/development/cd-certs/Chip-Test-CD-Cert.pem new file mode 100644 index 00000000000000..0392cd2b6a5dd6 --- /dev/null +++ b/credentials/development/cd-certs/Chip-Test-CD-Cert.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBszCCAVqgAwIBAgIIRdrzneR6oI8wCgYIKoZIzj0EAwIwKzEpMCcGA1UEAwwg +TWF0dGVyIFRlc3QgQ0QgU2lnbmluZyBBdXRob3JpdHkwIBcNMjEwNjI4MTQyMzQz +WhgPOTk5OTEyMzEyMzU5NTlaMCsxKTAnBgNVBAMMIE1hdHRlciBUZXN0IENEIFNp +Z25pbmcgQXV0aG9yaXR5MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEPDmJIkUr +VcrzicJb0bykZWlSzLkOiGkkmthHRlMBTL+V1oeWXgNrUhxRA35rjO3vyh60QEZp +T6CIgu7WUZ3suqNmMGQwEgYDVR0TAQH/BAgwBgEB/wIBATAOBgNVHQ8BAf8EBAMC +AQYwHQYDVR0OBBYEFGL6gjNZrPqplj4c+hQK3fUE83FgMB8GA1UdIwQYMBaAFGL6 +gjNZrPqplj4c+hQK3fUE83FgMAoGCCqGSM49BAMCA0cAMEQCICxUXOTkV9im8NnZ +u+vW7OHd/n+MbZps83UyH8b6xxOEAiBUB3jodDlyUn7t669YaGIgtUB48s1OYqdq +58u5L/VMiw== +-----END CERTIFICATE----- diff --git a/examples/chip-tool/commands/common/CHIPCommand.cpp b/examples/chip-tool/commands/common/CHIPCommand.cpp index 663ebee8257d61..b6f8dfc8b47f3d 100644 --- a/examples/chip-tool/commands/common/CHIPCommand.cpp +++ b/examples/chip-tool/commands/common/CHIPCommand.cpp @@ -36,27 +36,47 @@ std::set CHIPCommand::sDeferredCleanups; using DeviceControllerFactory = chip::Controller::DeviceControllerFactory; -constexpr chip::FabricId kIdentityNullFabricId = chip::kUndefinedFabricId; -constexpr chip::FabricId kIdentityAlphaFabricId = 1; -constexpr chip::FabricId kIdentityBetaFabricId = 2; -constexpr chip::FabricId kIdentityGammaFabricId = 3; -constexpr chip::FabricId kIdentityOtherFabricId = 4; -constexpr const char * kTrustStorePathVariable = "CHIPTOOL_PAA_TRUST_STORE_PATH"; - -const chip::Credentials::AttestationTrustStore * CHIPCommand::sPaaTrustStore = nullptr; +constexpr chip::FabricId kIdentityNullFabricId = chip::kUndefinedFabricId; +constexpr chip::FabricId kIdentityAlphaFabricId = 1; +constexpr chip::FabricId kIdentityBetaFabricId = 2; +constexpr chip::FabricId kIdentityGammaFabricId = 3; +constexpr chip::FabricId kIdentityOtherFabricId = 4; +constexpr const char * kPAATrustStorePathVariable = "CHIPTOOL_PAA_TRUST_STORE_PATH"; +constexpr const char * kCDTrustStorePathVariable = "CHIPTOOL_CD_TRUST_STORE_PATH"; + +const chip::Credentials::AttestationTrustStore * CHIPCommand::sTrustStore = nullptr; chip::Credentials::GroupDataProviderImpl CHIPCommand::sGroupDataProvider{ kMaxGroupsPerFabric, kMaxGroupKeysPerFabric }; namespace { -const chip::Credentials::AttestationTrustStore * GetTestFileAttestationTrustStore(const char * paaTrustStorePath) +const CHIP_ERROR GetAttestationTrustStore(const char * paaTrustStorePath, + const chip::Credentials::AttestationTrustStore ** trustStore) { + if (paaTrustStorePath == nullptr) + { + paaTrustStorePath = getenv(kPAATrustStorePathVariable); + } + + if (paaTrustStorePath == nullptr) + { + *trustStore = chip::Credentials::GetTestAttestationTrustStore(); + return CHIP_NO_ERROR; + } + static chip::Credentials::FileAttestationTrustStore attestationTrustStore{ paaTrustStorePath }; - if (attestationTrustStore.IsInitialized()) + if (paaTrustStorePath != nullptr && attestationTrustStore.paaCount() == 0) { - return &attestationTrustStore; + ChipLogError(chipTool, "No PAAs found in path: %s", paaTrustStorePath); + ChipLogError(chipTool, + "Please specify a valid path containing trusted PAA certificates using " + "the argument [--paa-trust-store-path paa/file/path] " + "or environment variable [%s=paa/file/path]", + kPAATrustStorePathVariable); + return CHIP_ERROR_INVALID_ARGUMENT; } - return nullptr; + *trustStore = &attestationTrustStore; + return CHIP_NO_ERROR; } } // namespace @@ -103,29 +123,33 @@ CHIP_ERROR CHIPCommand::MaybeSetUpStack() factoryInitParams.listenPort = port; ReturnLogErrorOnFailure(DeviceControllerFactory::GetInstance().Init(factoryInitParams)); - if (!mPaaTrustStorePath.HasValue()) + ReturnErrorOnFailure(GetAttestationTrustStore(mPaaTrustStorePath.ValueOr(nullptr), &sTrustStore)); + + ReturnLogErrorOnFailure(InitializeCommissioner(kIdentityNull, kIdentityNullFabricId)); + + // After initializing first commissioner, add the additional CD certs once { - char * const trust_store_path = getenv(kTrustStorePathVariable); - if (trust_store_path != nullptr) + const char * cdTrustStorePath = mCDTrustStorePath.ValueOr(nullptr); + if (cdTrustStorePath == nullptr) { - mPaaTrustStorePath.SetValue(trust_store_path); + cdTrustStorePath = getenv(kCDTrustStorePathVariable); } - } - sPaaTrustStore = mPaaTrustStorePath.HasValue() ? GetTestFileAttestationTrustStore(mPaaTrustStorePath.Value()) - : chip::Credentials::GetTestAttestationTrustStore(); - ; - if (mPaaTrustStorePath.HasValue() && sPaaTrustStore == nullptr) - { - ChipLogError(chipTool, "No PAAs found in path: %s", mPaaTrustStorePath.Value()); - ChipLogError(chipTool, - "Please specify a valid path containing trusted PAA certificates using" - "the argument [--paa-trust-store-path paa/file/path]" - "or environment variable [%s=paa/file/path]", - kTrustStorePathVariable); - return CHIP_ERROR_INVALID_ARGUMENT; - } - ReturnLogErrorOnFailure(InitializeCommissioner(kIdentityNull, kIdentityNullFabricId)); + auto additionalCdCerts = chip::Credentials::LoadAllX509DerCerts(cdTrustStorePath); + if (cdTrustStorePath != nullptr && additionalCdCerts.size() == 0) + { + ChipLogError(chipTool, "Warning: no CD signing certs found in path: %s, only defaults will be used", cdTrustStorePath); + ChipLogError(chipTool, + "Please specify a path containing trusted CD verifying key certificates using " + "the argument [--cd-trust-store-path cd/file/path] " + "or environment variable [%s=cd/file/path]", + kCDTrustStorePathVariable); + } + ReturnErrorOnFailure(mCredIssuerCmds->AddAdditionalCDVerifyingCerts(additionalCdCerts)); + } + bool allowTestCdSigningKey = !mOnlyAllowTrustedCdKeys.ValueOr(false); + mCredIssuerCmds->SetCredentialIssuerOption(CredentialIssuerCommands::CredentialIssuerOptions::kAllowTestCdSigningKey, + allowTestCdSigningKey); return CHIP_NO_ERROR; } @@ -343,7 +367,7 @@ CHIP_ERROR CHIPCommand::InitializeCommissioner(std::string key, chip::FabricId f std::unique_ptr commissioner = std::make_unique(); chip::Controller::SetupParams commissionerParams; - ReturnLogErrorOnFailure(mCredIssuerCmds->SetupDeviceAttestation(commissionerParams, sPaaTrustStore)); + ReturnLogErrorOnFailure(mCredIssuerCmds->SetupDeviceAttestation(commissionerParams, sTrustStore)); VerifyOrReturnError(noc.Alloc(chip::Controller::kMaxCHIPDERCertLength), CHIP_ERROR_NO_MEMORY); VerifyOrReturnError(icac.Alloc(chip::Controller::kMaxCHIPDERCertLength), CHIP_ERROR_NO_MEMORY); diff --git a/examples/chip-tool/commands/common/CHIPCommand.h b/examples/chip-tool/commands/common/CHIPCommand.h index 1714928ea1096c..89e114f73da54b 100644 --- a/examples/chip-tool/commands/common/CHIPCommand.h +++ b/examples/chip-tool/commands/common/CHIPCommand.h @@ -65,11 +65,17 @@ class CHIPCommand : public Command AddArgument("paa-trust-store-path", &mPaaTrustStorePath, "Path to directory holding PAA certificate information. Can be absolute or relative to the current working " "directory."); + AddArgument("cd-trust-store-path", &mCDTrustStorePath, + "Path to directory holding CD certificate information. Can be absolute or relative to the current working " + "directory."); AddArgument("commissioner-name", &mCommissionerName, "Name of fabric to use. Valid values are \"alpha\", \"beta\", \"gamma\", and integers greater than or equal to " "4. The default if not specified is \"alpha\"."); AddArgument("commissioner-nodeid", 0, UINT64_MAX, &mCommissionerNodeId, "The node id to use for chip-tool. If not provided, kTestControllerNodeId (112233, 0x1B669) will be used."); + AddArgument("only-allow-trusted-cd-keys", 0, 1, &mOnlyAllowTrustedCdKeys, + "Only allow trusted CD verifying keys (disallow test keys). If not provided or 0 (\"false\"), untrusted CD " + "verifying keys are allowed. If 1 (\"true\"), test keys are disallowed."); #if CHIP_CONFIG_TRANSPORT_TRACE_ENABLED AddArgument("trace_file", &mTraceFile); AddArgument("trace_log", 0, 1, &mTraceLog); @@ -153,10 +159,12 @@ class CHIPCommand : public Command chip::Optional mCommissionerNodeId; chip::Optional mBleAdapterId; chip::Optional mPaaTrustStorePath; + chip::Optional mCDTrustStorePath; + chip::Optional mOnlyAllowTrustedCdKeys; // Cached trust store so commands other than the original startup command // can spin up commissioners as needed. - static const chip::Credentials::AttestationTrustStore * sPaaTrustStore; + static const chip::Credentials::AttestationTrustStore * sTrustStore; static void RunQueuedCommand(intptr_t commandArg); diff --git a/examples/chip-tool/commands/common/CredentialIssuerCommands.h b/examples/chip-tool/commands/common/CredentialIssuerCommands.h index 951ef86efceb40..3beb86995e4517 100644 --- a/examples/chip-tool/commands/common/CredentialIssuerCommands.h +++ b/examples/chip-tool/commands/common/CredentialIssuerCommands.h @@ -23,6 +23,7 @@ #include #include #include +#include class CredentialIssuerCommands { @@ -54,6 +55,16 @@ class CredentialIssuerCommands virtual CHIP_ERROR SetupDeviceAttestation(chip::Controller::SetupParams & setupParams, const chip::Credentials::AttestationTrustStore * trustStore) = 0; + /** + * @brief Add a list of additional non-default CD verifying keys (by certificate) + * + * Must be called AFTER SetupDeviceAttestation. + * + * @param additionalCdCerts - vector of X.509 DER verifying cert bodies + * @return CHIP_NO_ERROR on succes, another CHIP_ERROR on internal failures. + */ + virtual CHIP_ERROR AddAdditionalCDVerifyingCerts(const std::vector> & additionalCdCerts) = 0; + virtual chip::Controller::OperationalCredentialsDelegate * GetCredentialIssuer() = 0; /** @@ -74,4 +85,23 @@ class CredentialIssuerCommands virtual CHIP_ERROR GenerateControllerNOCChain(chip::NodeId nodeId, chip::FabricId fabricId, const chip::CATValues & cats, chip::Crypto::P256Keypair & keypair, chip::MutableByteSpan & rcac, chip::MutableByteSpan & icac, chip::MutableByteSpan & noc) = 0; + + // All options must start false + enum CredentialIssuerOptions : uint8_t + { + kAllowTestCdSigningKey = 1, // If set, allow development/test SDK CD verifying key to be used + }; + + virtual void SetCredentialIssuerOption(CredentialIssuerOptions option, bool isEnabled) + { + // Do nothing + (void) option; + (void) isEnabled; + } + + virtual bool GetCredentialIssuerOption(CredentialIssuerOptions option) + { + // All options always start false + return false; + } }; diff --git a/examples/chip-tool/commands/example/ExampleCredentialIssuerCommands.h b/examples/chip-tool/commands/example/ExampleCredentialIssuerCommands.h index 74646c8b5f10ba..d5bad3ddd72d81 100644 --- a/examples/chip-tool/commands/example/ExampleCredentialIssuerCommands.h +++ b/examples/chip-tool/commands/example/ExampleCredentialIssuerCommands.h @@ -37,7 +37,9 @@ class ExampleCredentialIssuerCommands : public CredentialIssuerCommands { chip::Credentials::SetDeviceAttestationCredentialsProvider(chip::Credentials::Examples::GetExampleDACProvider()); - setupParams.deviceAttestationVerifier = chip::Credentials::GetDefaultDACVerifier(trustStore); + mDacVerifier = chip::Credentials::GetDefaultDACVerifier(trustStore); + setupParams.deviceAttestationVerifier = mDacVerifier; + mDacVerifier->EnableCdTestKeySupport(mAllowTestCdSigningKey); return CHIP_NO_ERROR; } @@ -49,6 +51,53 @@ class ExampleCredentialIssuerCommands : public CredentialIssuerCommands return mOpCredsIssuer.GenerateNOCChainAfterValidation(nodeId, fabricId, cats, keypair.Pubkey(), rcac, icac, noc); } + CHIP_ERROR AddAdditionalCDVerifyingCerts(const std::vector> & additionalCdCerts) override + { + VerifyOrReturnError(mDacVerifier != nullptr, CHIP_ERROR_INCORRECT_STATE); + + for (const auto & cert : additionalCdCerts) + { + auto cdTrustStore = mDacVerifier->GetCertificationDeclarationTrustStore(); + VerifyOrReturnError(cdTrustStore != nullptr, CHIP_ERROR_INCORRECT_STATE); + ReturnErrorOnFailure(cdTrustStore->AddTrustedKey(chip::ByteSpan(cert.data(), cert.size()))); + } + + return CHIP_NO_ERROR; + } + + void SetCredentialIssuerOption(CredentialIssuerOptions option, bool isEnabled) override + { + switch (option) + { + case CredentialIssuerOptions::kAllowTestCdSigningKey: + mAllowTestCdSigningKey = isEnabled; + if (mDacVerifier != nullptr) + { + mDacVerifier->EnableCdTestKeySupport(isEnabled); + } + + default: + break; + } + } + + bool GetCredentialIssuerOption(CredentialIssuerOptions option) override + { + switch (option) + { + case CredentialIssuerOptions::kAllowTestCdSigningKey: + return mAllowTestCdSigningKey; + default: + return false; + } + } + +protected: + bool mUsesMaxSizedCerts = false; + // Starts true for legacy purposes + bool mAllowTestCdSigningKey = true; + private: chip::Controller::ExampleOperationalCredentialsIssuer mOpCredsIssuer; + chip::Credentials::DeviceAttestationVerifier * mDacVerifier; }; diff --git a/examples/common/tracing/decoder/interaction_model/DecoderCustomLog.cpp b/examples/common/tracing/decoder/interaction_model/DecoderCustomLog.cpp index e516a74c4ce93e..c2f73187cac3ff 100644 --- a/examples/common/tracing/decoder/interaction_model/DecoderCustomLog.cpp +++ b/examples/common/tracing/decoder/interaction_model/DecoderCustomLog.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -66,13 +67,15 @@ CHIP_ERROR LogCertificationDeclaration(const ByteSpan & cd) // TODO Add an option to load a TrustStore so the subjectKeyId can be extracted from the CMS envelope in order // to select the proper public key. - ByteSpan cdContentOut; - uint8_t pubKey[] = { 0x04, 0x3c, 0x39, 0x89, 0x22, 0x45, 0x2b, 0x55, 0xca, 0xf3, 0x89, 0xc2, 0x5b, 0xd1, 0xbc, 0xa4, 0x65, - 0x69, 0x52, 0xcc, 0xb9, 0x0e, 0x88, 0x69, 0x24, 0x9a, 0xd8, 0x47, 0x46, 0x53, 0x01, 0x4c, 0xbf, 0x95, - 0xd6, 0x87, 0x96, 0x5e, 0x03, 0x6b, 0x52, 0x1c, 0x51, 0x03, 0x7e, 0x6b, 0x8c, 0xed, 0xef, 0xca, 0x1e, - 0xb4, 0x40, 0x46, 0x69, 0x4f, 0xa0, 0x88, 0x82, 0xee, 0xd6, 0x51, 0x9d, 0xec, 0xba }; + ByteSpan kid; + ReturnErrorOnFailure(Credentials::CMS_ExtractKeyId(cd, kid)); + + Crypto::P256PublicKey verifyingKey; + Credentials::CsaCdKeysTrustStore cdKeysTrustStore; + ReturnErrorOnFailure(cdKeysTrustStore.LookupVerifyingKey(kid, verifyingKey)); - ReturnErrorOnFailure(Credentials::CMS_Verify(cd, Crypto::P256PublicKey(pubKey), cdContentOut)); + ByteSpan cdContentOut; + ReturnErrorOnFailure(Credentials::CMS_Verify(cd, verifyingKey, cdContentOut)); constexpr uint8_t kTag_FormatVersion = 0; /**< [ unsigned int ] Format version. */ constexpr uint8_t kTag_VendorId = 1; /**< [ unsigned int ] Vedor identifier. */ diff --git a/examples/platform/linux/NamedPipeCommands.cpp b/examples/platform/linux/NamedPipeCommands.cpp index 4d78cd4c87aab6..7eea3ebbb6b8a2 100644 --- a/examples/platform/linux/NamedPipeCommands.cpp +++ b/examples/platform/linux/NamedPipeCommands.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include #include diff --git a/integrations/docker/ci-only-images/chip-cirque-device-base/Dockerfile b/integrations/docker/ci-only-images/chip-cirque-device-base/Dockerfile index 405ce537ba1c93..3fe1dfe7e7b3d4 100644 --- a/integrations/docker/ci-only-images/chip-cirque-device-base/Dockerfile +++ b/integrations/docker/ci-only-images/chip-cirque-device-base/Dockerfile @@ -21,7 +21,7 @@ RUN apt-get update \ ca-certificates=20211016~20.04.1 \ dhcpcd5=7.1.0-2build1 \ gdb=9.2-0ubuntu1~20.04.1 \ - git=1:2.25.1-1ubuntu3.5 \ + git \ iproute2=5.5.0-1ubuntu1 \ libavahi-client3=0.7-4ubuntu7.1 \ libcairo2-dev=1.16.0-4ubuntu1 \ diff --git a/src/app/tests/suites/credentials/TestHarnessDACProvider.cpp b/src/app/tests/suites/credentials/TestHarnessDACProvider.cpp index 1d8ef2461fd679..c9732447c8ec3d 100644 --- a/src/app/tests/suites/credentials/TestHarnessDACProvider.cpp +++ b/src/app/tests/suites/credentials/TestHarnessDACProvider.cpp @@ -38,18 +38,18 @@ // 0x8048, 0x8049, 0x804A, 0x804B, 0x804C, 0x804D, 0x804E, 0x804F, 0x8050, 0x8051, 0x8052, 0x8053, 0x8054, 0x8055, 0x8056, // 0x8057, 0x8058, 0x8059, 0x805A, 0x805B, 0x805C, 0x805D, 0x805E, 0x805F, 0x8060, 0x8061, 0x8062, 0x8063 ] //-> device_type_id = 0x0016 -//-> certificate_id = "ZIG20142ZB330003-24" +//-> certificate_id = "CSA00000SWC00000-00" //-> security_level = 0 //-> security_information = 0 -//-> version_number = 0x2694 +//-> version_number = 1 //-> certification_type = 0 //-> dac_origin_vendor_id is not present //-> dac_origin_product_id is not present -constexpr const uint8_t kCdForAllExamples[541] = { - 0x30, 0x82, 0x02, 0x19, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x02, 0x0a, 0x30, 0x82, - 0x02, 0x06, 0x02, 0x01, 0x03, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, - 0x82, 0x01, 0x71, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, 0x01, 0x62, 0x04, 0x82, 0x01, - 0x5e, 0x15, 0x24, 0x00, 0x01, 0x25, 0x01, 0xf1, 0xff, 0x36, 0x02, 0x05, 0x00, 0x80, 0x05, 0x01, 0x80, 0x05, 0x02, 0x80, 0x05, +constexpr const uint8_t kCdForAllExamples[540] = { + 0x30, 0x82, 0x02, 0x17, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x02, 0x08, 0x30, 0x82, + 0x02, 0x04, 0x02, 0x01, 0x03, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, + 0x82, 0x01, 0x70, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, 0x01, 0x61, 0x04, 0x82, 0x01, + 0x5d, 0x15, 0x24, 0x00, 0x01, 0x25, 0x01, 0xf1, 0xff, 0x36, 0x02, 0x05, 0x00, 0x80, 0x05, 0x01, 0x80, 0x05, 0x02, 0x80, 0x05, 0x03, 0x80, 0x05, 0x04, 0x80, 0x05, 0x05, 0x80, 0x05, 0x06, 0x80, 0x05, 0x07, 0x80, 0x05, 0x08, 0x80, 0x05, 0x09, 0x80, 0x05, 0x0a, 0x80, 0x05, 0x0b, 0x80, 0x05, 0x0c, 0x80, 0x05, 0x0d, 0x80, 0x05, 0x0e, 0x80, 0x05, 0x0f, 0x80, 0x05, 0x10, 0x80, 0x05, 0x11, 0x80, 0x05, 0x12, 0x80, 0x05, 0x13, 0x80, 0x05, 0x14, 0x80, 0x05, 0x15, 0x80, 0x05, 0x16, 0x80, 0x05, 0x17, 0x80, 0x05, @@ -64,14 +64,14 @@ constexpr const uint8_t kCdForAllExamples[541] = { 0x50, 0x80, 0x05, 0x51, 0x80, 0x05, 0x52, 0x80, 0x05, 0x53, 0x80, 0x05, 0x54, 0x80, 0x05, 0x55, 0x80, 0x05, 0x56, 0x80, 0x05, 0x57, 0x80, 0x05, 0x58, 0x80, 0x05, 0x59, 0x80, 0x05, 0x5a, 0x80, 0x05, 0x5b, 0x80, 0x05, 0x5c, 0x80, 0x05, 0x5d, 0x80, 0x05, 0x5e, 0x80, 0x05, 0x5f, 0x80, 0x05, 0x60, 0x80, 0x05, 0x61, 0x80, 0x05, 0x62, 0x80, 0x05, 0x63, 0x80, 0x18, 0x24, 0x03, 0x16, - 0x2c, 0x04, 0x13, 0x5a, 0x49, 0x47, 0x32, 0x30, 0x31, 0x34, 0x32, 0x5a, 0x42, 0x33, 0x33, 0x30, 0x30, 0x30, 0x33, 0x2d, 0x32, - 0x34, 0x24, 0x05, 0x00, 0x24, 0x06, 0x00, 0x25, 0x07, 0x94, 0x26, 0x24, 0x08, 0x00, 0x18, 0x31, 0x7d, 0x30, 0x7b, 0x02, 0x01, - 0x03, 0x80, 0x14, 0x62, 0xfa, 0x82, 0x33, 0x59, 0xac, 0xfa, 0xa9, 0x96, 0x3e, 0x1c, 0xfa, 0x14, 0x0a, 0xdd, 0xf5, 0x04, 0xf3, - 0x71, 0x60, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, - 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x04, 0x47, 0x30, 0x45, 0x02, 0x20, 0x24, 0xe5, 0xd1, 0xf4, 0x7a, 0x7d, 0x7b, 0x0d, 0x20, - 0x6a, 0x26, 0xef, 0x69, 0x9b, 0x7c, 0x97, 0x57, 0xb7, 0x2d, 0x46, 0x90, 0x89, 0xde, 0x31, 0x92, 0xe6, 0x78, 0xc7, 0x45, 0xe7, - 0xf6, 0x0c, 0x02, 0x21, 0x00, 0xf8, 0xaa, 0x2f, 0xa7, 0x11, 0xfc, 0xb7, 0x9b, 0x97, 0xe3, 0x97, 0xce, 0xda, 0x66, 0x7b, 0xae, - 0x46, 0x4e, 0x2b, 0xd3, 0xff, 0xdf, 0xc3, 0xcc, 0xed, 0x7a, 0xa8, 0xca, 0x5f, 0x4c, 0x1a, 0x7c, + 0x2c, 0x04, 0x13, 0x43, 0x53, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x53, 0x57, 0x43, 0x30, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, + 0x30, 0x24, 0x05, 0x00, 0x24, 0x06, 0x00, 0x24, 0x07, 0x01, 0x24, 0x08, 0x00, 0x18, 0x31, 0x7c, 0x30, 0x7a, 0x02, 0x01, 0x03, + 0x80, 0x14, 0xfe, 0x34, 0x3f, 0x95, 0x99, 0x47, 0x76, 0x3b, 0x61, 0xee, 0x45, 0x39, 0x13, 0x13, 0x38, 0x49, 0x4f, 0xe6, 0x7d, + 0x8e, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, + 0xce, 0x3d, 0x04, 0x03, 0x02, 0x04, 0x46, 0x30, 0x44, 0x02, 0x20, 0x4a, 0x12, 0xf8, 0xd4, 0x2f, 0x90, 0x23, 0x5c, 0x05, 0xa7, + 0x71, 0x21, 0xcb, 0xeb, 0xae, 0x15, 0xd5, 0x90, 0x14, 0x65, 0x58, 0xe9, 0xc9, 0xb4, 0x7a, 0x1a, 0x38, 0xf7, 0xa3, 0x6a, 0x7d, + 0xc5, 0x02, 0x20, 0x20, 0xa4, 0x74, 0x28, 0x97, 0xc3, 0x0a, 0xed, 0xa0, 0xa5, 0x6b, 0x36, 0xe1, 0x4e, 0xbb, 0xc8, 0x5b, 0xbd, + 0xb7, 0x44, 0x93, 0xf9, 0x93, 0x58, 0x1e, 0xb0, 0x44, 0x4e, 0xd6, 0xca, 0x94, 0x0b }; namespace chip { diff --git a/src/credentials/attestation_verifier/DefaultDeviceAttestationVerifier.cpp b/src/credentials/attestation_verifier/DefaultDeviceAttestationVerifier.cpp index 07db1d3726d9b9..dae687b4102727 100644 --- a/src/credentials/attestation_verifier/DefaultDeviceAttestationVerifier.cpp +++ b/src/credentials/attestation_verifier/DefaultDeviceAttestationVerifier.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -50,6 +51,177 @@ static const ByteSpan kTestPaaRoots[] = { TestCerts::sTestCert_PAA_NoVID_Cert, }; +// Test CD Signing Key from `credentials/test/certification-declaration/Chip-Test-CD-Signing-Cert.pem` +// used to verify any in-SDK development CDs. The associated keypair to do actual signing is in +// `credentials/test/certification-declaration/Chip-Test-CD-Signing-Key.pem`. +// +// -----BEGIN CERTIFICATE----- +// MIIBszCCAVqgAwIBAgIIRdrzneR6oI8wCgYIKoZIzj0EAwIwKzEpMCcGA1UEAwwg +// TWF0dGVyIFRlc3QgQ0QgU2lnbmluZyBBdXRob3JpdHkwIBcNMjEwNjI4MTQyMzQz +// WhgPOTk5OTEyMzEyMzU5NTlaMCsxKTAnBgNVBAMMIE1hdHRlciBUZXN0IENEIFNp +// Z25pbmcgQXV0aG9yaXR5MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEPDmJIkUr +// VcrzicJb0bykZWlSzLkOiGkkmthHRlMBTL+V1oeWXgNrUhxRA35rjO3vyh60QEZp +// T6CIgu7WUZ3suqNmMGQwEgYDVR0TAQH/BAgwBgEB/wIBATAOBgNVHQ8BAf8EBAMC +// AQYwHQYDVR0OBBYEFGL6gjNZrPqplj4c+hQK3fUE83FgMB8GA1UdIwQYMBaAFGL6 +// gjNZrPqplj4c+hQK3fUE83FgMAoGCCqGSM49BAMCA0cAMEQCICxUXOTkV9im8NnZ +// u+vW7OHd/n+MbZps83UyH8b6xxOEAiBUB3jodDlyUn7t669YaGIgtUB48s1OYqdq +// 58u5L/VMiw== +// -----END CERTIFICATE----- +// +constexpr uint8_t gTestCdPubkeyBytes[65] = { 0x04, 0x3c, 0x39, 0x89, 0x22, 0x45, 0x2b, 0x55, 0xca, 0xf3, 0x89, 0xc2, 0x5b, + 0xd1, 0xbc, 0xa4, 0x65, 0x69, 0x52, 0xcc, 0xb9, 0x0e, 0x88, 0x69, 0x24, 0x9a, + 0xd8, 0x47, 0x46, 0x53, 0x01, 0x4c, 0xbf, 0x95, 0xd6, 0x87, 0x96, 0x5e, 0x03, + 0x6b, 0x52, 0x1c, 0x51, 0x03, 0x7e, 0x6b, 0x8c, 0xed, 0xef, 0xca, 0x1e, 0xb4, + 0x40, 0x46, 0x69, 0x4f, 0xa0, 0x88, 0x82, 0xee, 0xd6, 0x51, 0x9d, 0xec, 0xba }; + +constexpr uint8_t gTestCdPubkeyKid[20] = { 0x62, 0xfa, 0x82, 0x33, 0x59, 0xac, 0xfa, 0xa9, 0x96, 0x3e, + 0x1c, 0xfa, 0x14, 0x0a, 0xdd, 0xf5, 0x04, 0xf3, 0x71, 0x60 }; + +// Official CD "Signing Key 001" +// +// -----BEGIN CERTIFICATE----- +// MIICBzCCAa2gAwIBAgIHY3NhY2RrMTAKBggqhkjOPQQDAjBSMQwwCgYDVQQKDAND +// U0ExLDAqBgNVBAMMI01hdHRlciBDZXJ0aWZpY2F0aW9uIGFuZCBUZXN0aW5nIENB +// MRQwEgYKKwYBBAGConwCAQwEQzVBMDAgFw0yMjEwMDMxOTI4NTVaGA8yMDcyMDky +// MDE5Mjg1NVowWDEMMAoGA1UECgwDQ1NBMTIwMAYDVQQDDClDZXJ0aWZpY2F0aW9u +// IERlY2xhcmF0aW9uIFNpZ25pbmcgS2V5IDAwMTEUMBIGCisGAQQBgqJ8AgEMBEM1 +// QTAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATN7uk+RPi3K+PRqcB+IZaLmv/z +// tAPwXhZp17Hlyu5vx3FLQufiNpXpLNdjVHOigK5ojze7lInhFim5uU/3sJkpo2Yw +// ZDASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQU +// /jQ/lZlHdjth7kU5ExM4SU/mfY4wHwYDVR0jBBgwFoAUl+Rp0MUEFMJvxwH3fpR3 +// OQmN9qUwCgYIKoZIzj0EAwIDSAAwRQIgEDWOcdKsVGtUh3evHbBd1lq4aS7yQtOp +// 6GrOQ3/zXBsCIQDxorh2RXSaI8m2RCcoWaiWa0nLzQepNm3C2jrQVJmC2Q== +// -----END CERTIFICATE----- +// +constexpr uint8_t gCdSigningKey001PubkeyBytes[65] = { + 0x04, 0xcd, 0xee, 0xe9, 0x3e, 0x44, 0xf8, 0xb7, 0x2b, 0xe3, 0xd1, 0xa9, 0xc0, 0x7e, 0x21, 0x96, 0x8b, + 0x9a, 0xff, 0xf3, 0xb4, 0x03, 0xf0, 0x5e, 0x16, 0x69, 0xd7, 0xb1, 0xe5, 0xca, 0xee, 0x6f, 0xc7, 0x71, + 0x4b, 0x42, 0xe7, 0xe2, 0x36, 0x95, 0xe9, 0x2c, 0xd7, 0x63, 0x54, 0x73, 0xa2, 0x80, 0xae, 0x68, 0x8f, + 0x37, 0xbb, 0x94, 0x89, 0xe1, 0x16, 0x29, 0xb9, 0xb9, 0x4f, 0xf7, 0xb0, 0x99, 0x29 +}; + +constexpr uint8_t gCdSigningKey001Kid[20] = { 0xFE, 0x34, 0x3F, 0x95, 0x99, 0x47, 0x76, 0x3B, 0x61, 0xEE, + 0x45, 0x39, 0x13, 0x13, 0x38, 0x49, 0x4F, 0xE6, 0x7D, 0x8E }; + +// Official CD "Signing Key 002" +// +// -----BEGIN CERTIFICATE----- +// MIICCDCCAa2gAwIBAgIHY3NhY2RrMjAKBggqhkjOPQQDAjBSMQwwCgYDVQQKDAND +// U0ExLDAqBgNVBAMMI01hdHRlciBDZXJ0aWZpY2F0aW9uIGFuZCBUZXN0aW5nIENB +// MRQwEgYKKwYBBAGConwCAQwEQzVBMDAgFw0yMjEwMDMxOTM2NDZaGA8yMDcyMDky +// MDE5MzY0NlowWDEMMAoGA1UECgwDQ1NBMTIwMAYDVQQDDClDZXJ0aWZpY2F0aW9u +// IERlY2xhcmF0aW9uIFNpZ25pbmcgS2V5IDAwMjEUMBIGCisGAQQBgqJ8AgEMBEM1 +// QTAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQDGTfo+UJRBF3ydFe7RiU+43VO +// jBKuKFV9gCe51MNW2RtAjP8yJ1AXsl+Mi6IFFtXIOvK3JBKAE9/Mj5XSAKkLo2Yw +// ZDASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQU +// 3QTbWFshTBxYFYfmVo30h7bdxwEwHwYDVR0jBBgwFoAUl+Rp0MUEFMJvxwH3fpR3 +// OQmN9qUwCgYIKoZIzj0EAwIDSQAwRgIhAJruzxZ806cP/LoQ07PN9xAbjLdwUalV +// h0Qfx304Tb92AiEAk+jnf2qtyfKyTEHpT3Xf3bfekqUOA+8ikB1yjL5oTsI= +// -----END CERTIFICATE----- +// +constexpr uint8_t gCdSigningKey002PubkeyBytes[65] = { + 0x04, 0x03, 0x19, 0x37, 0xe8, 0xf9, 0x42, 0x51, 0x04, 0x5d, 0xf2, 0x74, 0x57, 0xbb, 0x46, 0x25, 0x3e, + 0xe3, 0x75, 0x4e, 0x8c, 0x12, 0xae, 0x28, 0x55, 0x7d, 0x80, 0x27, 0xb9, 0xd4, 0xc3, 0x56, 0xd9, 0x1b, + 0x40, 0x8c, 0xff, 0x32, 0x27, 0x50, 0x17, 0xb2, 0x5f, 0x8c, 0x8b, 0xa2, 0x05, 0x16, 0xd5, 0xc8, 0x3a, + 0xf2, 0xb7, 0x24, 0x12, 0x80, 0x13, 0xdf, 0xcc, 0x8f, 0x95, 0xd2, 0x00, 0xa9, 0x0b +}; + +constexpr uint8_t gCdSigningKey002Kid[20] = { 0xDD, 0x04, 0xDB, 0x58, 0x5B, 0x21, 0x4C, 0x1C, 0x58, 0x15, + 0x87, 0xE6, 0x56, 0x8D, 0xF4, 0x87, 0xB6, 0xDD, 0xC7, 0x01 }; + +// Official CD "Signing Key 003" +// +// -----BEGIN CERTIFICATE----- +// MIICBjCCAa2gAwIBAgIHY3NhY2RrMzAKBggqhkjOPQQDAjBSMQwwCgYDVQQKDAND +// U0ExLDAqBgNVBAMMI01hdHRlciBDZXJ0aWZpY2F0aW9uIGFuZCBUZXN0aW5nIENB +// MRQwEgYKKwYBBAGConwCAQwEQzVBMDAgFw0yMjEwMDMxOTQxMDFaGA8yMDcyMDky +// MDE5NDEwMVowWDEMMAoGA1UECgwDQ1NBMTIwMAYDVQQDDClDZXJ0aWZpY2F0aW9u +// IERlY2xhcmF0aW9uIFNpZ25pbmcgS2V5IDAwMzEUMBIGCisGAQQBgqJ8AgEMBEM1 +// QTAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASfV1zV/bdSHxCk3zHwc5ErYUco +// 8tN/W2uWvCy/fAsRlpBXfVVdIaCWYKiwgqM56lMPeoEthpO1b9dkGF+rzTL1o2Yw +// ZDASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQU +// RxA158BOqqi+fE1ME+PkwgmVqEswHwYDVR0jBBgwFoAUl+Rp0MUEFMJvxwH3fpR3 +// OQmN9qUwCgYIKoZIzj0EAwIDRwAwRAIgIFecbY+1mVVNqxH9+8IMB8+safdyIJU2 +// AqqtZ/w7AkQCIHiVlYTaCnJsnW5/cvj9GfIv7Eb0cjdmcAkrYGbnPQzX +// -----END CERTIFICATE----- +// +constexpr uint8_t gCdSigningKey003PubkeyBytes[65] = { + 0x04, 0x9f, 0x57, 0x5c, 0xd5, 0xfd, 0xb7, 0x52, 0x1f, 0x10, 0xa4, 0xdf, 0x31, 0xf0, 0x73, 0x91, 0x2b, + 0x61, 0x47, 0x28, 0xf2, 0xd3, 0x7f, 0x5b, 0x6b, 0x96, 0xbc, 0x2c, 0xbf, 0x7c, 0x0b, 0x11, 0x96, 0x90, + 0x57, 0x7d, 0x55, 0x5d, 0x21, 0xa0, 0x96, 0x60, 0xa8, 0xb0, 0x82, 0xa3, 0x39, 0xea, 0x53, 0x0f, 0x7a, + 0x81, 0x2d, 0x86, 0x93, 0xb5, 0x6f, 0xd7, 0x64, 0x18, 0x5f, 0xab, 0xcd, 0x32, 0xf5 +}; + +constexpr uint8_t gCdSigningKey003Kid[20] = { 0x47, 0x10, 0x35, 0xE7, 0xC0, 0x4E, 0xAA, 0xA8, 0xBE, 0x7C, + 0x4D, 0x4C, 0x13, 0xE3, 0xE4, 0xC2, 0x09, 0x95, 0xA8, 0x4B }; + +// Official CD "Signing Key 004" +// +// -----BEGIN CERTIFICATE----- +// MIICBjCCAa2gAwIBAgIHY3NhY2RrNDAKBggqhkjOPQQDAjBSMQwwCgYDVQQKDAND +// U0ExLDAqBgNVBAMMI01hdHRlciBDZXJ0aWZpY2F0aW9uIGFuZCBUZXN0aW5nIENB +// MRQwEgYKKwYBBAGConwCAQwEQzVBMDAgFw0yMjEwMDMxOTQzMjFaGA8yMDcyMDky +// MDE5NDMyMVowWDEMMAoGA1UECgwDQ1NBMTIwMAYDVQQDDClDZXJ0aWZpY2F0aW9u +// IERlY2xhcmF0aW9uIFNpZ25pbmcgS2V5IDAwNDEUMBIGCisGAQQBgqJ8AgEMBEM1 +// QTAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAR8/I2IEKic9PoZF3jyr+x4+FF6 +// l6Plf8ITutiI42EedP+2hL3rqKaLJSNKXDWPNzurm20wThMG3XYgpSjRFhwLo2Yw +// ZDASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQU +// 9oYDo2kumBByQZ6h4as4VL13ldMwHwYDVR0jBBgwFoAUl+Rp0MUEFMJvxwH3fpR3 +// OQmN9qUwCgYIKoZIzj0EAwIDRwAwRAIgLqAfkbtLYYdmQsnbn0CWv3G1/lbE36nz +// HbLbW5t6PY4CIE8oyIHsVhNSTPcb3mwRp+Vxhs8tKhbAdwv5BGgDaAHj +// -----END CERTIFICATE----- +// +constexpr uint8_t gCdSigningKey004PubkeyBytes[65] = { + 0x04, 0x7c, 0xfc, 0x8d, 0x88, 0x10, 0xa8, 0x9c, 0xf4, 0xfa, 0x19, 0x17, 0x78, 0xf2, 0xaf, 0xec, 0x78, + 0xf8, 0x51, 0x7a, 0x97, 0xa3, 0xe5, 0x7f, 0xc2, 0x13, 0xba, 0xd8, 0x88, 0xe3, 0x61, 0x1e, 0x74, 0xff, + 0xb6, 0x84, 0xbd, 0xeb, 0xa8, 0xa6, 0x8b, 0x25, 0x23, 0x4a, 0x5c, 0x35, 0x8f, 0x37, 0x3b, 0xab, 0x9b, + 0x6d, 0x30, 0x4e, 0x13, 0x06, 0xdd, 0x76, 0x20, 0xa5, 0x28, 0xd1, 0x16, 0x1c, 0x0b +}; + +constexpr uint8_t gCdSigningKey004Kid[20] = { 0xF6, 0x86, 0x03, 0xA3, 0x69, 0x2E, 0x98, 0x10, 0x72, 0x41, + 0x9E, 0xA1, 0xE1, 0xAB, 0x38, 0x54, 0xBD, 0x77, 0x95, 0xD3 }; + +// Official CD "Signing Key 005" +// +// -----BEGIN CERTIFICATE----- +// MIICBzCCAa2gAwIBAgIHY3NhY2RrNTAKBggqhkjOPQQDAjBSMQwwCgYDVQQKDAND +// U0ExLDAqBgNVBAMMI01hdHRlciBDZXJ0aWZpY2F0aW9uIGFuZCBUZXN0aW5nIENB +// MRQwEgYKKwYBBAGConwCAQwEQzVBMDAgFw0yMjEwMDMxOTQ3MTVaGA8yMDcyMDky +// MDE5NDcxNVowWDEMMAoGA1UECgwDQ1NBMTIwMAYDVQQDDClDZXJ0aWZpY2F0aW9u +// IERlY2xhcmF0aW9uIFNpZ25pbmcgS2V5IDAwNTEUMBIGCisGAQQBgqJ8AgEMBEM1 +// QTAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARDilLGYqKm1yZH+V63UxNu5K4P +// 2zqpwWkxQms9CGf5EDrn16G4h+n4E6byb3a7zak1k3h8EneMqPKXXcRaIEL5o2Yw +// ZDASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQU +// Y38mNK1i6v5q9mLvuW9v0vy//C8wHwYDVR0jBBgwFoAUl+Rp0MUEFMJvxwH3fpR3 +// OQmN9qUwCgYIKoZIzj0EAwIDSAAwRQIhAM1HQpvkHKxLJByWaSYAPRZgh3Bis18W +// AViq7c/mtzEAAiBZO0lVe6Qo9iQPIBWZaVx/S/YSNO9uKNa/pvFu3V+nIg== +// -----END CERTIFICATE----- +// +constexpr uint8_t gCdSigningKey005PubkeyBytes[65] = { + 0x04, 0x43, 0x8a, 0x52, 0xc6, 0x62, 0xa2, 0xa6, 0xd7, 0x26, 0x47, 0xf9, 0x5e, 0xb7, 0x53, 0x13, 0x6e, + 0xe4, 0xae, 0x0f, 0xdb, 0x3a, 0xa9, 0xc1, 0x69, 0x31, 0x42, 0x6b, 0x3d, 0x08, 0x67, 0xf9, 0x10, 0x3a, + 0xe7, 0xd7, 0xa1, 0xb8, 0x87, 0xe9, 0xf8, 0x13, 0xa6, 0xf2, 0x6f, 0x76, 0xbb, 0xcd, 0xa9, 0x35, 0x93, + 0x78, 0x7c, 0x12, 0x77, 0x8c, 0xa8, 0xf2, 0x97, 0x5d, 0xc4, 0x5a, 0x20, 0x42, 0xf9 +}; + +constexpr uint8_t gCdSigningKey005Kid[20] = { 0x63, 0x7F, 0x26, 0x34, 0xAD, 0x62, 0xEA, 0xFE, 0x6A, 0xF6, + 0x62, 0xEF, 0xB9, 0x6F, 0x6F, 0xD2, 0xFC, 0xBF, 0xFC, 0x2F }; + +struct MatterCDSigningKey +{ + const CertificateKeyId mKid; + const P256PublicKeySpan mPubkey; +}; + +std::array gCdSigningKeys = { { + { FixedByteSpan<20>{ gTestCdPubkeyKid }, FixedByteSpan<65>{ gTestCdPubkeyBytes } }, + { FixedByteSpan<20>{ gCdSigningKey001Kid }, FixedByteSpan<65>{ gCdSigningKey001PubkeyBytes } }, + { FixedByteSpan<20>{ gCdSigningKey002Kid }, FixedByteSpan<65>{ gCdSigningKey002PubkeyBytes } }, + { FixedByteSpan<20>{ gCdSigningKey003Kid }, FixedByteSpan<65>{ gCdSigningKey003PubkeyBytes } }, + { FixedByteSpan<20>{ gCdSigningKey004Kid }, FixedByteSpan<65>{ gCdSigningKey004PubkeyBytes } }, + { FixedByteSpan<20>{ gCdSigningKey005Kid }, FixedByteSpan<65>{ gCdSigningKey005PubkeyBytes } }, +} }; + const ArrayAttestationTrustStore kTestAttestationTrustStore{ &kTestPaaRoots[0], ArraySize(kTestPaaRoots) }; AttestationVerificationResult MapError(CertificateChainValidationResult certificateChainValidationResult) @@ -87,64 +259,6 @@ AttestationVerificationResult MapError(CertificateChainValidationResult certific return AttestationVerificationResult::kInternalError; } } - -/** - * @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[Crypto::kSubjectKeyIdentifierLength]; - }; - - static CertChainLookupTable - sCertChainLookupTable[] = { - { { 0x30, 0x82, 0x01, 0xb3, 0x30, 0x82, 0x01, 0x5a, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x45, 0xda, 0xf3, 0x9d, - 0xe4, 0x7a, 0xa0, 0x8f, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x2b, 0x31, - 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x20, 0x4d, 0x61, 0x74, 0x74, 0x65, 0x72, 0x20, 0x54, 0x65, - 0x73, 0x74, 0x20, 0x43, 0x44, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, - 0x72, 0x69, 0x74, 0x79, 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, 0x2b, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x20, 0x4d, 0x61, 0x74, 0x74, 0x65, 0x72, - 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x44, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x41, 0x75, - 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 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, 0x3c, 0x39, 0x89, 0x22, - 0x45, 0x2b, 0x55, 0xca, 0xf3, 0x89, 0xc2, 0x5b, 0xd1, 0xbc, 0xa4, 0x65, 0x69, 0x52, 0xcc, 0xb9, 0x0e, 0x88, 0x69, - 0x24, 0x9a, 0xd8, 0x47, 0x46, 0x53, 0x01, 0x4c, 0xbf, 0x95, 0xd6, 0x87, 0x96, 0x5e, 0x03, 0x6b, 0x52, 0x1c, 0x51, - 0x03, 0x7e, 0x6b, 0x8c, 0xed, 0xef, 0xca, 0x1e, 0xb4, 0x40, 0x46, 0x69, 0x4f, 0xa0, 0x88, 0x82, 0xee, 0xd6, 0x51, - 0x9d, 0xec, 0xba, 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, 0x62, 0xfa, 0x82, - 0x33, 0x59, 0xac, 0xfa, 0xa9, 0x96, 0x3e, 0x1c, 0xfa, 0x14, 0x0a, 0xdd, 0xf5, 0x04, 0xf3, 0x71, 0x60, 0x30, 0x1f, - 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x62, 0xfa, 0x82, 0x33, 0x59, 0xac, 0xfa, 0xa9, - 0x96, 0x3e, 0x1c, 0xfa, 0x14, 0x0a, 0xdd, 0xf5, 0x04, 0xf3, 0x71, 0x60, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, - 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x47, 0x00, 0x30, 0x44, 0x02, 0x20, 0x2c, 0x54, 0x5c, 0xe4, 0xe4, 0x57, 0xd8, - 0xa6, 0xf0, 0xd9, 0xd9, 0xbb, 0xeb, 0xd6, 0xec, 0xe1, 0xdd, 0xfe, 0x7f, 0x8c, 0x6d, 0x9a, 0x6c, 0xf3, 0x75, 0x32, - 0x1f, 0xc6, 0xfa, 0xc7, 0x13, 0x84, 0x02, 0x20, 0x54, 0x07, 0x78, 0xe8, 0x74, 0x39, 0x72, 0x52, 0x7e, 0xed, 0xeb, - 0xaf, 0x58, 0x68, 0x62, 0x20, 0xb5, 0x40, 0x78, 0xf2, 0xcd, 0x4e, 0x62, 0xa7, 0x6a, 0xe7, 0xcb, 0xb9, 0x2f, 0xf5, - 0x4c, 0x8b }, - { 0x62, 0xfa, 0x82, 0x33, 0x59, 0xac, 0xfa, 0xa9, 0x96, 0x3e, - 0x1c, 0xfa, 0x14, 0x0a, 0xdd, 0xf5, 0x04, 0xf3, 0x71, 0x60 } } - }; - - size_t certChainLookupTableIdx; - for (certChainLookupTableIdx = 0; certChainLookupTableIdx < ArraySize(sCertChainLookupTable); ++certChainLookupTableIdx) - { - if (skid.data_equal(ByteSpan(sCertChainLookupTable[certChainLookupTableIdx].mSKID))) - { - break; - } - } - - VerifyOrReturnError(certChainLookupTableIdx < ArraySize(sCertChainLookupTable), CHIP_ERROR_INVALID_ARGUMENT); - - return CopySpanToMutableSpan(ByteSpan{ sCertChainLookupTable[certChainLookupTableIdx].mCertificate }, outCertificate); -} - } // namespace void DefaultDACVerifier::VerifyAttestationInformation(const DeviceAttestationVerifier::AttestationInfo & info, @@ -166,6 +280,9 @@ void DefaultDACVerifier::VerifyAttestationInformation(const DeviceAttestationVer VerifyOrExit(info.attestationElementsBuffer.size() <= kMaxResponseLength, attestationError = AttestationVerificationResult::kInvalidArgument); + // Ensure PAI is present + VerifyOrExit(!info.paiDerBuffer.empty(), attestationError = AttestationVerificationResult::kPaiMissing); + // match DAC and PAI VIDs { VerifyOrExit(ExtractVIDPIDFromX509Cert(info.dacDerBuffer, dacVidPid) == CHIP_NO_ERROR, @@ -203,6 +320,7 @@ void DefaultDACVerifier::VerifyAttestationInformation(const DeviceAttestationVer uint8_t akidBuf[Crypto::kAuthorityKeyIdentifierLength]; MutableByteSpan akid(akidBuf); constexpr size_t paaCertAllocatedLen = kMaxDERCertLength; + CHIP_ERROR err = CHIP_NO_ERROR; VerifyOrExit(ExtractAKIDFromX509Cert(info.paiDerBuffer, akid) == CHIP_NO_ERROR, attestationError = AttestationVerificationResult::kPaiFormatInvalid); @@ -210,9 +328,16 @@ void DefaultDACVerifier::VerifyAttestationInformation(const DeviceAttestationVer VerifyOrExit(paaCert.Alloc(paaCertAllocatedLen), attestationError = AttestationVerificationResult::kNoMemory); paaDerBuffer = MutableByteSpan(paaCert.Get(), paaCertAllocatedLen); - VerifyOrExit(mAttestationTrustStore->GetProductAttestationAuthorityCert(akid, paaDerBuffer) == CHIP_NO_ERROR, + err = mAttestationTrustStore->GetProductAttestationAuthorityCert(akid, paaDerBuffer); + VerifyOrExit(err == CHIP_NO_ERROR || err == CHIP_ERROR_NOT_IMPLEMENTED, attestationError = AttestationVerificationResult::kPaaNotFound); + if (err == CHIP_ERROR_NOT_IMPLEMENTED) + { + VerifyOrExit(kTestAttestationTrustStore.GetProductAttestationAuthorityCert(akid, paaDerBuffer) == CHIP_NO_ERROR, + attestationError = AttestationVerificationResult::kPaaNotFound); + } + VerifyOrExit(ExtractVIDPIDFromX509Cert(paaDerBuffer, paaVidPid) == CHIP_NO_ERROR, attestationError = AttestationVerificationResult::kPaaFormatInvalid); @@ -283,17 +408,21 @@ void DefaultDACVerifier::VerifyAttestationInformation(const DeviceAttestationVer AttestationVerificationResult DefaultDACVerifier::ValidateCertificationDeclarationSignature(const ByteSpan & cmsEnvelopeBuffer, ByteSpan & certDeclBuffer) { - uint8_t certificate[Credentials::kMaxDERCertLength]; - MutableByteSpan certificateSpan(certificate); - ByteSpan skid; - - VerifyOrReturnError(CMS_ExtractKeyId(cmsEnvelopeBuffer, skid) == CHIP_NO_ERROR, + ByteSpan kid; + VerifyOrReturnError(CMS_ExtractKeyId(cmsEnvelopeBuffer, kid) == CHIP_NO_ERROR, AttestationVerificationResult::kCertificationDeclarationNoKeyId); - VerifyOrReturnError(GetCertificationDeclarationCertificate(skid, certificateSpan) == CHIP_NO_ERROR, - AttestationVerificationResult::kCertificationDeclarationNoCertificateFound); + Crypto::P256PublicKey verifyingKey; + CHIP_ERROR err = mCdKeysTrustStore.LookupVerifyingKey(kid, verifyingKey); + VerifyOrReturnError(err == CHIP_NO_ERROR, AttestationVerificationResult::kCertificationDeclarationNoCertificateFound); + + // Disallow test key if support not enabled + if (mCdKeysTrustStore.IsCdTestKey(kid) && !IsCdTestKeySupported()) + { + return AttestationVerificationResult::kCertificationDeclarationNoCertificateFound; + } - VerifyOrReturnError(CMS_Verify(cmsEnvelopeBuffer, certificateSpan, certDeclBuffer) == CHIP_NO_ERROR, + VerifyOrReturnError(CMS_Verify(cmsEnvelopeBuffer, verifyingKey, certDeclBuffer) == CHIP_NO_ERROR, AttestationVerificationResult::kCertificationDeclarationInvalidSignature); return AttestationVerificationResult::kSuccess; @@ -310,7 +439,7 @@ AttestationVerificationResult DefaultDACVerifier::ValidateCertificateDeclaration if (!firmwareInfo.empty()) { - // TODO: check if version_number field in Certification Declaration matches the one in Firmware Information. + // TODO: validate contents based on DCL } // The vendor_id field in the Certification Declaration SHALL match the VendorID attribute found in the Basic Information @@ -413,6 +542,68 @@ CHIP_ERROR DefaultDACVerifier::VerifyNodeOperationalCSRInformation(const ByteSpa return CHIP_NO_ERROR; } +bool CsaCdKeysTrustStore::IsCdTestKey(const ByteSpan & kid) const +{ + return kid.data_equal(ByteSpan{ gTestCdPubkeyKid }); +} + +CHIP_ERROR CsaCdKeysTrustStore::AddTrustedKey(const ByteSpan & kid, const Crypto::P256PublicKey & pubKey) +{ + ReturnErrorCodeIf(kid.size() > SingleKeyEntry::kMaxKidSize, CHIP_ERROR_INVALID_ARGUMENT); + ReturnErrorCodeIf(kid.empty(), CHIP_ERROR_INVALID_ARGUMENT); + ReturnErrorCodeIf(mNumTrustedKeys == kMaxNumTrustedKeys, CHIP_ERROR_NO_MEMORY); + + auto & entry = mTrustedKeys[mNumTrustedKeys]; + + entry.kidSize = kid.size(); + memcpy(&entry.kidBuffer[0], kid.data(), kid.size()); + entry.publicKey = pubKey; + + ++mNumTrustedKeys; + return CHIP_NO_ERROR; +} + +CHIP_ERROR CsaCdKeysTrustStore::AddTrustedKey(const ByteSpan & derCertBytes) +{ + // TODO: Verify cert against CD root of trust (i.e. verify signatures). To do so, + // we are missing primitives to validate X.509 paths of total length 2. + + uint8_t kidBuf[Crypto::kSubjectKeyIdentifierLength] = { 0 }; + MutableByteSpan kidSpan{ kidBuf }; + P256PublicKey pubKey; + + VerifyOrReturnError(CHIP_NO_ERROR == Crypto::ExtractSKIDFromX509Cert(derCertBytes, kidSpan), CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(CHIP_NO_ERROR == Crypto::ExtractPubkeyFromX509Cert(derCertBytes, pubKey), CHIP_ERROR_INVALID_ARGUMENT); + return AddTrustedKey(kidSpan, pubKey); +} + +CHIP_ERROR CsaCdKeysTrustStore::LookupVerifyingKey(const ByteSpan & kid, Crypto::P256PublicKey & outPubKey) const +{ + // First, search for the well known keys + for (size_t keyIdx = 0; keyIdx < gCdSigningKeys.size(); keyIdx++) + { + if (kid.data_equal(gCdSigningKeys[keyIdx].mKid)) + { + outPubKey = gCdSigningKeys[keyIdx].mPubkey; + return CHIP_NO_ERROR; + } + } + + // Seconds, search externally added keys + for (size_t keyIdx = 0; keyIdx < mNumTrustedKeys; keyIdx++) + { + auto & entry = mTrustedKeys[keyIdx]; + if (kid.data_equal(entry.GetKid())) + { + outPubKey = entry.publicKey; + return CHIP_NO_ERROR; + } + } + + // If we get here, the desired key was not found + return CHIP_ERROR_KEY_NOT_FOUND; +} + const AttestationTrustStore * GetTestAttestationTrustStore() { return &kTestAttestationTrustStore; diff --git a/src/credentials/attestation_verifier/DefaultDeviceAttestationVerifier.h b/src/credentials/attestation_verifier/DefaultDeviceAttestationVerifier.h index 99f2fb5f2b85ae..bdf7f705dbd0f1 100644 --- a/src/credentials/attestation_verifier/DefaultDeviceAttestationVerifier.h +++ b/src/credentials/attestation_verifier/DefaultDeviceAttestationVerifier.h @@ -16,11 +16,44 @@ */ #pragma once +#include #include +#include +#include +#include +#include +#include namespace chip { namespace Credentials { +class CsaCdKeysTrustStore : public WellKnownKeysTrustStore +{ +public: + CsaCdKeysTrustStore() = default; + virtual ~CsaCdKeysTrustStore() = default; + + CHIP_ERROR AddTrustedKey(const ByteSpan & kid, const Crypto::P256PublicKey & pubKey) override; + CHIP_ERROR AddTrustedKey(const ByteSpan & derCertBytes) override; + CHIP_ERROR LookupVerifyingKey(const ByteSpan & kid, Crypto::P256PublicKey & outPubKey) const override; + bool IsCdTestKey(const ByteSpan & kid) const override; + +protected: + struct SingleKeyEntry + { + static constexpr size_t kMaxKidSize = 32u; + uint8_t kidBuffer[kMaxKidSize]; + size_t kidSize; + Crypto::P256PublicKey publicKey; + + ByteSpan GetKid() const { return ByteSpan{ &kidBuffer[0], kidSize }; } + }; + + static constexpr size_t kMaxNumTrustedKeys = CHIP_CONFIG_NUM_CD_KEY_SLOTS; + std::array mTrustedKeys; + size_t mNumTrustedKeys = 0; +}; + class DefaultDACVerifier : public DeviceAttestationVerifier { public: @@ -41,9 +74,12 @@ class DefaultDACVerifier : public DeviceAttestationVerifier const ByteSpan & attestationSignatureBuffer, const Crypto::P256PublicKey & dacPublicKey, const ByteSpan & csrNonce) override; + CsaCdKeysTrustStore * GetCertificationDeclarationTrustStore() override { return &mCdKeysTrustStore; } + protected: DefaultDACVerifier() {} + CsaCdKeysTrustStore mCdKeysTrustStore; const AttestationTrustStore * mAttestationTrustStore; }; diff --git a/src/credentials/attestation_verifier/DeviceAttestationVerifier.h b/src/credentials/attestation_verifier/DeviceAttestationVerifier.h index 756759d32ebe03..6f12afed6189b7 100644 --- a/src/credentials/attestation_verifier/DeviceAttestationVerifier.h +++ b/src/credentials/attestation_verifier/DeviceAttestationVerifier.h @@ -21,6 +21,7 @@ #include #include #include +#include namespace chip { namespace Credentials { @@ -44,6 +45,7 @@ enum class AttestationVerificationResult : uint16_t kPaiArgumentInvalid = 204, kPaiVendorIdMismatch = 205, kPaiAuthorityNotFound = 206, + kPaiMissing = 207, kDacExpired = 300, kDacSignatureInvalid = 301, @@ -148,6 +150,73 @@ class AttestationTrustStore virtual CHIP_ERROR GetProductAttestationAuthorityCert(const ByteSpan & skid, MutableByteSpan & outPaaDerBuffer) const = 0; }; +/** + * @brief Helper utility to model obtaining verifying keys by Key ID + * + * API is synchronous. Real commissioner implementations may entirely + * hide key 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 WellKnownKeysTrustStore +{ +public: + WellKnownKeysTrustStore() = default; + virtual ~WellKnownKeysTrustStore() = default; + + // Not copyable + WellKnownKeysTrustStore(const WellKnownKeysTrustStore &) = delete; + WellKnownKeysTrustStore & operator=(const WellKnownKeysTrustStore &) = delete; + + /** + * @brief Add a trusted key directly + * + * @param[in] kid - Key ID to use. Usually 20 bytes long, max 32 bytes. + * @param[in] pubKey - Verifying public key to attach to the key ID. + * + * @return CHIP_NO_ERROR on success, CHIP_INVALID_ARGUMENT if `kid` or `pubKey` arguments + * are not usable. CHIP_ERROR_NO_MEMORY if the trust store is full. + */ + virtual CHIP_ERROR AddTrustedKey(const ByteSpan & kid, const Crypto::P256PublicKey & pubKey) = 0; + + /** + * @brief Add a trusted key via a public certificate. + * + * The subject public key of the certificate will be used. + * The subject key ID extensions of the certificate will be the `kid`. + * + * Verification of trust chaining is at the discretion of the implementation. + * + * @param[in] derCertBytes - Certificate containing the X.509 DER certificate with the key. + * + * @return CHIP_NO_ERROR on success, CHIP_INVALID_ARGUMENT if derCertBytes is improperly + * formatted or not trusted. CHIP_ERROR_NO_MEMORY if the trust store is full. + */ + virtual CHIP_ERROR AddTrustedKey(const ByteSpan & derCertBytes) = 0; + + /** + * @brief Look-up a verifying key by Key ID + * + * Interface is synchronous. + * + * @param[in] kid Buffer containing the key identifier (KID) of the verifying key to look-up. Usually + * a SHA-1-sized buffer (20 bytes). + * @param[out] outPubKey Reference to where the verifying key found will be stored on CHIP_NO_ERROR + * + * @returns CHIP_NO_ERROR on success, CHIP_INVALID_ARGUMENT if `kid` or `pubKey` arguments + * are not usable, CHIP_ERROR_KEY_NOT_FOUND if no key is found that matches `kid`. + */ + virtual CHIP_ERROR LookupVerifyingKey(const ByteSpan & kid, Crypto::P256PublicKey & outPubKey) const = 0; + + /** + * @brief Returns true if `kid` identifies a known test key. + * + * @param kid - Key ID to use. Usually 20 bytes long, max 32 bytes. + * @return true if it's a test/development-only signing key identifier, false otherwise + */ + virtual bool IsCdTestKey(const ByteSpan & kid) const = 0; +}; + /** * @brief Basic AttestationTrustStore that holds all data within caller-owned memory. * @@ -276,9 +345,26 @@ class DeviceAttestationVerifier const Crypto::P256PublicKey & dacPublicKey, const ByteSpan & csrNonce) = 0; + /** + * @brief Get the trust store used for the attestation verifier. + * + * Returns nullptr if not supported. Be careful not to hold-on to the trust store + * for too long. It is only expected to have same lifetime as the DeviceAttestationVerifier. + * + * @return a pointer to the trust store or nullptr if none is directly accessible. + */ + virtual WellKnownKeysTrustStore * GetCertificationDeclarationTrustStore() { return nullptr; } + + void EnableCdTestKeySupport(bool enabled) { mEnableCdTestKeySupport = enabled; } + bool IsCdTestKeySupported() const { return mEnableCdTestKeySupport; } + protected: CHIP_ERROR ValidateAttestationSignature(const Crypto::P256PublicKey & pubkey, const ByteSpan & attestationElements, const ByteSpan & attestationChallenge, const Crypto::P256ECDSASignature & signature); + + // Default to support the "development" test key for legacy purposes (since the DefaultDACVerifier) + // always supported development keys. + bool mEnableCdTestKeySupport = true; }; /** diff --git a/src/credentials/attestation_verifier/FileAttestationTrustStore.cpp b/src/credentials/attestation_verifier/FileAttestationTrustStore.cpp index 922f2c9521de0a..eeb752d40a66d2 100644 --- a/src/credentials/attestation_verifier/FileAttestationTrustStore.cpp +++ b/src/credentials/attestation_verifier/FileAttestationTrustStore.cpp @@ -16,6 +16,7 @@ */ #include "FileAttestationTrustStore.h" +#include #include #include #include @@ -41,9 +42,28 @@ const char * GetFilenameExtension(const char * filename) FileAttestationTrustStore::FileAttestationTrustStore(const char * paaTrustStorePath) { + VerifyOrReturn(paaTrustStorePath != nullptr); + + if (paaTrustStorePath != nullptr) + { + mPAADerCerts = LoadAllX509DerCerts(paaTrustStorePath); + VerifyOrReturn(paaCount()); + } + + mIsInitialized = true; +} + +std::vector> LoadAllX509DerCerts(const char * trustStorePath) +{ + std::vector> certs; + if (trustStorePath == nullptr) + { + return certs; + } + DIR * dir; - dir = opendir(paaTrustStorePath); + dir = opendir(trustStorePath); if (dir != nullptr) { // Nested directories are not handled. @@ -53,33 +73,41 @@ FileAttestationTrustStore::FileAttestationTrustStore(const char * paaTrustStoreP const char * fileExtension = GetFilenameExtension(entry->d_name); if (strncmp(fileExtension, "der", strlen("der")) == 0) { - FILE * file; - - std::array certificate; - std::string filename(paaTrustStorePath); + std::vector certificate(kMaxDERCertLength + 1); + std::string filename(trustStorePath); filename += std::string("/") + std::string(entry->d_name); - file = fopen(filename.c_str(), "rb"); - if (file != nullptr) + FILE * file = fopen(filename.c_str(), "rb"); + if (file == nullptr) { - uint32_t certificateLength = fread(certificate.data(), sizeof(uint8_t), kMaxDERCertLength, file); - if (certificateLength > 0) - { - mDerCerts.push_back(certificate); - mIsInitialized = true; - } - fclose(file); + // On bad files, just skip. + continue; } - else + + size_t certificateLength = fread(certificate.data(), sizeof(uint8_t), certificate.size(), file); + if ((certificateLength > 0) && (certificateLength <= kMaxDERCertLength)) { - Cleanup(); - break; + certificate.resize(certificateLength); + // Only accumulate certificate if it has a subject key ID extension + { + uint8_t kidBuf[Crypto::kSubjectKeyIdentifierLength] = { 0 }; + MutableByteSpan kidSpan{ kidBuf }; + ByteSpan certSpan{ certificate.data(), certificate.size() }; + + if (CHIP_NO_ERROR == Crypto::ExtractSKIDFromX509Cert(certSpan, kidSpan)) + { + certs.push_back(certificate); + } + } } + fclose(file); } } closedir(dir); } + + return certs; } FileAttestationTrustStore::~FileAttestationTrustStore() @@ -89,18 +117,25 @@ FileAttestationTrustStore::~FileAttestationTrustStore() void FileAttestationTrustStore::Cleanup() { - mDerCerts.clear(); + mPAADerCerts.clear(); mIsInitialized = false; } CHIP_ERROR FileAttestationTrustStore::GetProductAttestationAuthorityCert(const ByteSpan & skid, MutableByteSpan & outPaaDerBuffer) const { - VerifyOrReturnError(!mDerCerts.empty(), CHIP_ERROR_CA_CERT_NOT_FOUND); + // If the constructor has not tried to initialize the PAA certificates database, return CHIP_ERROR_NOT_IMPLEMENTED to use the + // testing trust store if the DefaultAttestationVerifier is in use. + if (mIsInitialized && paaCount() == 0) + { + return CHIP_ERROR_NOT_IMPLEMENTED; + } + + VerifyOrReturnError(!mPAADerCerts.empty(), CHIP_ERROR_CA_CERT_NOT_FOUND); VerifyOrReturnError(!skid.empty() && (skid.data() != nullptr), CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(skid.size() == Crypto::kSubjectKeyIdentifierLength, CHIP_ERROR_INVALID_ARGUMENT); - for (auto candidate : mDerCerts) + for (auto candidate : mPAADerCerts) { uint8_t skidBuf[Crypto::kSubjectKeyIdentifierLength] = { 0 }; MutableByteSpan candidateSkidSpan{ skidBuf }; diff --git a/src/credentials/attestation_verifier/FileAttestationTrustStore.h b/src/credentials/attestation_verifier/FileAttestationTrustStore.h index 090be169367c63..0446d7a6ebb6b8 100644 --- a/src/credentials/attestation_verifier/FileAttestationTrustStore.h +++ b/src/credentials/attestation_verifier/FileAttestationTrustStore.h @@ -25,19 +25,31 @@ namespace chip { namespace Credentials { +/** + * @brief Load all X.509 DER certificates in a given path. + * + * Silently ignores non-X.509 files and X.509 files without a subject key identifier. + * + * Returns an empty vector if no files are found or unrecoverable errors arise. + * + * @param trustStorePath - path from where to search for certificates. + * @return a vector of certificate DER data + */ +std::vector> LoadAllX509DerCerts(const char * trustStorePath); + class FileAttestationTrustStore : public AttestationTrustStore { public: - FileAttestationTrustStore(const char * paaTrustStorePath); + FileAttestationTrustStore(const char * paaTrustStorePath = nullptr); ~FileAttestationTrustStore(); - bool IsInitialized() { return mIsInitialized; } - CHIP_ERROR GetProductAttestationAuthorityCert(const ByteSpan & skid, MutableByteSpan & outPaaDerBuffer) const override; - size_t size() const { return mDerCerts.size(); } + + bool IsInitialized() const { return mIsInitialized; } + size_t paaCount() const { return mPAADerCerts.size(); }; protected: - std::vector> mDerCerts; + std::vector> mPAADerCerts; private: bool mIsInitialized = false; diff --git a/src/credentials/examples/DeviceAttestationCredsExample.cpp b/src/credentials/examples/DeviceAttestationCredsExample.cpp index e96e36b59bd65b..bd09e11df67623 100644 --- a/src/credentials/examples/DeviceAttestationCredsExample.cpp +++ b/src/credentials/examples/DeviceAttestationCredsExample.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2021 Project CHIP Authors + * Copyright (c) 2021-2022 Project CHIP Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -72,18 +72,18 @@ CHIP_ERROR ExampleDACProvider::GetCertificationDeclaration(MutableByteSpan & out // 0x8048, 0x8049, 0x804A, 0x804B, 0x804C, 0x804D, 0x804E, 0x804F, 0x8050, 0x8051, 0x8052, 0x8053, 0x8054, 0x8055, 0x8056, // 0x8057, 0x8058, 0x8059, 0x805A, 0x805B, 0x805C, 0x805D, 0x805E, 0x805F, 0x8060, 0x8061, 0x8062, 0x8063 ] //-> device_type_id = 0x0016 - //-> certificate_id = "ZIG20142ZB330003-24" + //-> certificate_id = "CSA00000SWC00000-00" //-> security_level = 0 //-> security_information = 0 - //-> version_number = 0x2694 + //-> version_number = 1 //-> certification_type = 0 //-> dac_origin_vendor_id is not present //-> dac_origin_product_id is not present - const uint8_t kCdForAllExamples[541] = { - 0x30, 0x82, 0x02, 0x19, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x02, 0x0a, 0x30, - 0x82, 0x02, 0x06, 0x02, 0x01, 0x03, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, - 0x01, 0x30, 0x82, 0x01, 0x71, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, 0x01, 0x62, - 0x04, 0x82, 0x01, 0x5e, 0x15, 0x24, 0x00, 0x01, 0x25, 0x01, 0xf1, 0xff, 0x36, 0x02, 0x05, 0x00, 0x80, 0x05, 0x01, 0x80, + const uint8_t kCdForAllExamples[539] = { + 0x30, 0x82, 0x02, 0x17, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x02, 0x08, 0x30, + 0x82, 0x02, 0x04, 0x02, 0x01, 0x03, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, + 0x01, 0x30, 0x82, 0x01, 0x70, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, 0x01, 0x61, + 0x04, 0x82, 0x01, 0x5d, 0x15, 0x24, 0x00, 0x01, 0x25, 0x01, 0xf1, 0xff, 0x36, 0x02, 0x05, 0x00, 0x80, 0x05, 0x01, 0x80, 0x05, 0x02, 0x80, 0x05, 0x03, 0x80, 0x05, 0x04, 0x80, 0x05, 0x05, 0x80, 0x05, 0x06, 0x80, 0x05, 0x07, 0x80, 0x05, 0x08, 0x80, 0x05, 0x09, 0x80, 0x05, 0x0a, 0x80, 0x05, 0x0b, 0x80, 0x05, 0x0c, 0x80, 0x05, 0x0d, 0x80, 0x05, 0x0e, 0x80, 0x05, 0x0f, 0x80, 0x05, 0x10, 0x80, 0x05, 0x11, 0x80, 0x05, 0x12, 0x80, 0x05, 0x13, 0x80, 0x05, 0x14, 0x80, 0x05, 0x15, 0x80, @@ -99,17 +99,15 @@ CHIP_ERROR ExampleDACProvider::GetCertificationDeclaration(MutableByteSpan & out 0x05, 0x52, 0x80, 0x05, 0x53, 0x80, 0x05, 0x54, 0x80, 0x05, 0x55, 0x80, 0x05, 0x56, 0x80, 0x05, 0x57, 0x80, 0x05, 0x58, 0x80, 0x05, 0x59, 0x80, 0x05, 0x5a, 0x80, 0x05, 0x5b, 0x80, 0x05, 0x5c, 0x80, 0x05, 0x5d, 0x80, 0x05, 0x5e, 0x80, 0x05, 0x5f, 0x80, 0x05, 0x60, 0x80, 0x05, 0x61, 0x80, 0x05, 0x62, 0x80, 0x05, 0x63, 0x80, 0x18, 0x24, 0x03, 0x16, 0x2c, 0x04, - 0x13, 0x5a, 0x49, 0x47, 0x32, 0x30, 0x31, 0x34, 0x32, 0x5a, 0x42, 0x33, 0x33, 0x30, 0x30, 0x30, 0x33, 0x2d, 0x32, 0x34, - 0x24, 0x05, 0x00, 0x24, 0x06, 0x00, 0x25, 0x07, 0x94, 0x26, 0x24, 0x08, 0x00, 0x18, 0x31, 0x7d, 0x30, 0x7b, 0x02, 0x01, - 0x03, 0x80, 0x14, 0x62, 0xfa, 0x82, 0x33, 0x59, 0xac, 0xfa, 0xa9, 0x96, 0x3e, 0x1c, 0xfa, 0x14, 0x0a, 0xdd, 0xf5, 0x04, - 0xf3, 0x71, 0x60, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, 0x0a, 0x06, 0x08, - 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x04, 0x47, 0x30, 0x45, 0x02, 0x20, 0x24, 0xe5, 0xd1, 0xf4, 0x7a, 0x7d, - 0x7b, 0x0d, 0x20, 0x6a, 0x26, 0xef, 0x69, 0x9b, 0x7c, 0x97, 0x57, 0xb7, 0x2d, 0x46, 0x90, 0x89, 0xde, 0x31, 0x92, 0xe6, - 0x78, 0xc7, 0x45, 0xe7, 0xf6, 0x0c, 0x02, 0x21, 0x00, 0xf8, 0xaa, 0x2f, 0xa7, 0x11, 0xfc, 0xb7, 0x9b, 0x97, 0xe3, 0x97, - 0xce, 0xda, 0x66, 0x7b, 0xae, 0x46, 0x4e, 0x2b, 0xd3, 0xff, 0xdf, 0xc3, 0xcc, 0xed, 0x7a, 0xa8, 0xca, 0x5f, 0x4c, 0x1a, - 0x7c, + 0x13, 0x43, 0x53, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x53, 0x57, 0x43, 0x30, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, + 0x24, 0x05, 0x00, 0x24, 0x06, 0x00, 0x24, 0x07, 0x01, 0x24, 0x08, 0x00, 0x18, 0x31, 0x7c, 0x30, 0x7a, 0x02, 0x01, 0x03, + 0x80, 0x14, 0xfe, 0x34, 0x3f, 0x95, 0x99, 0x47, 0x76, 0x3b, 0x61, 0xee, 0x45, 0x39, 0x13, 0x13, 0x38, 0x49, 0x4f, 0xe6, + 0x7d, 0x8e, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, 0x0a, 0x06, 0x08, 0x2a, + 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x04, 0x46, 0x30, 0x44, 0x02, 0x20, 0x4a, 0x12, 0xf8, 0xd4, 0x2f, 0x90, 0x23, + 0x5c, 0x05, 0xa7, 0x71, 0x21, 0xcb, 0xeb, 0xae, 0x15, 0xd5, 0x90, 0x14, 0x65, 0x58, 0xe9, 0xc9, 0xb4, 0x7a, 0x1a, 0x38, + 0xf7, 0xa3, 0x6a, 0x7d, 0xc5, 0x02, 0x20, 0x20, 0xa4, 0x74, 0x28, 0x97, 0xc3, 0x0a, 0xed, 0xa0, 0xa5, 0x6b, 0x36, 0xe1, + 0x4e, 0xbb, 0xc8, 0x5b, 0xbd, 0xb7, 0x44, 0x93, 0xf9, 0x93, 0x58, 0x1e, 0xb0, 0x44, 0x4e, 0xd6, 0xca, 0x94, 0x0b }; - return CopySpanToMutableSpan(ByteSpan{ kCdForAllExamples }, out_cd_buffer); } diff --git a/src/credentials/tests/TestCertificationDeclaration.cpp b/src/credentials/tests/TestCertificationDeclaration.cpp index cda5f90b05124e..0a1d3aa33c9a3f 100644 --- a/src/credentials/tests/TestCertificationDeclaration.cpp +++ b/src/credentials/tests/TestCertificationDeclaration.cpp @@ -27,7 +27,10 @@ #include #include +#include +#include #include +#include #include #include @@ -150,6 +153,45 @@ static constexpr uint8_t sTestCMS_SignedMessage02[] = { 0x36, 0x5c, 0x6e, 0xd5, 0x44, 0x08, 0x6d, 0x10, 0x1a, 0xfd, 0xaf, 0x07, 0x9a, 0x2c, 0x23, 0xe0, 0xde }; +// Generated an untrusted CD key, and then a CD +// +// openssl ecparam -name prime256v1 -genkey -noout -out UntrustedCDKey.pem +// openssl req -x509 -key UntrustedCDKey.pem -keyform PEM -out UntrustedCDCert.pem -sha256 -days 3650 +// out/host/chip-cert gen-cd -C UntrustedCDCert.pem -K UntrustedCDKey.pem --out UntrustedCD.bin -f 1 -V FFF1 -p 8000 -p 8001 -p 8002 +// -p 8003 -p 8004 -p 8005 -p 8006 -p 8007 -p 8008 -p 8009 -p 800a -p 800b -p 800c -p 800d -p 800e -p 800f -p 8010 -p 8011 -p 8012 +// -p 8013 -p 8014 -p 8015 -p 8016 -p 8017 -p 8018 -p 8019 -p 801a -p 801b -p 801c -p 801d -p 801e -p 801f -d 0016 -c +// "ZIG0000000000000000" -l 0 -i 0 -n 0001 -t 0 +// +static constexpr uint8_t gUntrustedCd[333] = { + 0x30, 0x82, 0x01, 0x49, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x01, 0x3a, 0x30, 0x82, + 0x01, 0x36, 0x02, 0x01, 0x03, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, + 0x81, 0xa2, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x81, 0x94, 0x04, 0x81, 0x91, 0x15, 0x24, + 0x00, 0x01, 0x25, 0x01, 0xf1, 0xff, 0x36, 0x02, 0x05, 0x00, 0x80, 0x05, 0x01, 0x80, 0x05, 0x02, 0x80, 0x05, 0x03, 0x80, 0x05, + 0x04, 0x80, 0x05, 0x05, 0x80, 0x05, 0x06, 0x80, 0x05, 0x07, 0x80, 0x05, 0x08, 0x80, 0x05, 0x09, 0x80, 0x05, 0x0a, 0x80, 0x05, + 0x0b, 0x80, 0x05, 0x0c, 0x80, 0x05, 0x0d, 0x80, 0x05, 0x0e, 0x80, 0x05, 0x0f, 0x80, 0x05, 0x10, 0x80, 0x05, 0x11, 0x80, 0x05, + 0x12, 0x80, 0x05, 0x13, 0x80, 0x05, 0x14, 0x80, 0x05, 0x15, 0x80, 0x05, 0x16, 0x80, 0x05, 0x17, 0x80, 0x05, 0x18, 0x80, 0x05, + 0x19, 0x80, 0x05, 0x1a, 0x80, 0x05, 0x1b, 0x80, 0x05, 0x1c, 0x80, 0x05, 0x1d, 0x80, 0x05, 0x1e, 0x80, 0x05, 0x1f, 0x80, 0x18, + 0x24, 0x03, 0x16, 0x2c, 0x04, 0x13, 0x5a, 0x49, 0x47, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x24, 0x05, 0x00, 0x24, 0x06, 0x00, 0x24, 0x07, 0x01, 0x24, 0x08, 0x00, 0x18, 0x31, 0x7d, 0x30, 0x7b, + 0x02, 0x01, 0x03, 0x80, 0x14, 0x75, 0xe3, 0x06, 0x0e, 0x0f, 0xce, 0x28, 0x69, 0x5d, 0x19, 0x75, 0x43, 0x32, 0xbb, 0xc7, 0x9b, + 0xeb, 0x3d, 0x60, 0x6c, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, 0x0a, 0x06, 0x08, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x04, 0x47, 0x30, 0x45, 0x02, 0x21, 0x00, 0xf9, 0xd5, 0x91, 0x66, 0xca, 0xab, + 0x43, 0x82, 0xa7, 0x47, 0x24, 0xe6, 0x06, 0xbf, 0x1e, 0x2b, 0x4e, 0x7a, 0xb4, 0xf3, 0x04, 0x29, 0x21, 0x2b, 0x60, 0xfd, 0xa0, + 0x16, 0xea, 0xdc, 0x7d, 0x25, 0x02, 0x20, 0x62, 0xf1, 0x89, 0xfe, 0x4e, 0x60, 0x28, 0xd5, 0xc8, 0x42, 0x6a, 0xb7, 0x7e, 0xe5, + 0x1e, 0xf5, 0x68, 0x00, 0x23, 0x86, 0xba, 0x39, 0xe7, 0xab, 0x2d, 0xe5, 0x71, 0xe5, 0x36, 0x4e, 0xd0, 0x38, +}; + +static constexpr uint8_t gUntrustedCdVerifyingKeyBytes[65] = { 0x04, 0xbc, 0x87, 0x13, 0x3a, 0x19, 0x16, 0x87, 0x04, 0x34, 0x1b, + 0x78, 0xc5, 0x70, 0x41, 0x21, 0x14, 0xbb, 0xe5, 0x3f, 0x62, 0x45, + 0x70, 0xe8, 0xf2, 0x37, 0x78, 0x77, 0x1a, 0xf3, 0x5c, 0xd8, 0x04, + 0x21, 0xc8, 0x2d, 0x40, 0x7f, 0xee, 0x37, 0xf5, 0xa5, 0x9f, 0x17, + 0x26, 0x33, 0x00, 0x4d, 0xf7, 0x66, 0xa3, 0x3a, 0x50, 0x75, 0x9f, + 0xcf, 0xd2, 0xb2, 0x1b, 0x5e, 0x58, 0x75, 0x08, 0x82, 0x3e }; +static const P256PublicKey gUntrustedCdVerifyingKey(gUntrustedCdVerifyingKeyBytes); + +static constexpr uint8_t gUntrustedCdKid[20] = { 0x75, 0xE3, 0x06, 0x0E, 0x0F, 0xCE, 0x28, 0x69, 0x5D, 0x19, + 0x75, 0x43, 0x32, 0xBB, 0xC7, 0x9B, 0xEB, 0x3D, 0x60, 0x6C }; + struct TestCase { ByteSpan signerCert; @@ -464,6 +506,53 @@ static void TestCD_EncodeDecode_Random(nlTestSuite * inSuite, void * inContext) } } +static void TestCD_DefaultCdTrustStore(nlTestSuite * inSuite, void * inContext) +{ + chip::Credentials::CsaCdKeysTrustStore trustStore; + + // Make sure that for an untrusted CD, whose key is not in truststore, we cannot find the key. + { + ByteSpan signerKeyIdOut; + NL_TEST_ASSERT_SUCCESS(inSuite, CMS_ExtractKeyId(ByteSpan(gUntrustedCd), signerKeyIdOut)); + NL_TEST_ASSERT(inSuite, !trustStore.IsCdTestKey(signerKeyIdOut)); + + P256PublicKey pubKey; + NL_TEST_ASSERT(inSuite, CHIP_ERROR_KEY_NOT_FOUND == trustStore.LookupVerifyingKey(signerKeyIdOut, pubKey)); + } + + // Verify that a payload known to use the test key passes verification w/ default truststore + { + const auto & testCase = sTestCases[0]; + ByteSpan signerKeyIdOut; + NL_TEST_ASSERT_SUCCESS(inSuite, CMS_ExtractKeyId(testCase.cdCMSSigned, signerKeyIdOut)); + NL_TEST_ASSERT(inSuite, trustStore.IsCdTestKey(signerKeyIdOut)); + + P256PublicKey pubKey; + ByteSpan cdContentOut; + NL_TEST_ASSERT_SUCCESS(inSuite, trustStore.LookupVerifyingKey(signerKeyIdOut, pubKey)); + + NL_TEST_ASSERT(inSuite, CMS_Verify(testCase.cdCMSSigned, pubKey, cdContentOut) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, testCase.cdContent.data_equal(cdContentOut)); + } + + // Verify that after adding the verifying key to the trust store, it is now possible to + // verify the CD signature. + { + P256PublicKey pubKey; + ByteSpan cdContentOut; + NL_TEST_ASSERT_SUCCESS(inSuite, trustStore.AddTrustedKey(ByteSpan(gUntrustedCdKid), gUntrustedCdVerifyingKey)); + + ByteSpan signerKeyIdOut; + NL_TEST_ASSERT_SUCCESS(inSuite, CMS_ExtractKeyId(ByteSpan(gUntrustedCd), signerKeyIdOut)); + NL_TEST_ASSERT(inSuite, signerKeyIdOut.data_equal(ByteSpan(gUntrustedCdKid))); + + NL_TEST_ASSERT_SUCCESS(inSuite, trustStore.LookupVerifyingKey(signerKeyIdOut, pubKey)); + NL_TEST_ASSERT(inSuite, pubKey.Matches(gUntrustedCdVerifyingKey)); + + NL_TEST_ASSERT_SUCCESS(inSuite, CMS_Verify(ByteSpan(gUntrustedCd), pubKey, cdContentOut)); + } +} + #define NL_TEST_DEF_FN(fn) NL_TEST_DEF("Test " #fn, fn) /** * Test Suite. It lists all the test functions. @@ -474,6 +563,7 @@ static const nlTest sTests[] = { NL_TEST_DEF_FN(TestCD_EncodeDecode), NL_TEST_DEF_FN(TestCD_CMSVerifyAndExtract), NL_TEST_DEF_FN(TestCD_CertificationElementsDecoder), NL_TEST_DEF_FN(TestCD_EncodeDecode_Random), + NL_TEST_DEF_FN(TestCD_DefaultCdTrustStore), NL_TEST_SENTINEL() }; int TestCertificationDeclaration(void) diff --git a/src/darwin/Framework/CHIP/MTRAttestationTrustStoreBridge.mm b/src/darwin/Framework/CHIP/MTRAttestationTrustStoreBridge.mm index ee88d420624d4a..f968ca4d617de9 100644 --- a/src/darwin/Framework/CHIP/MTRAttestationTrustStoreBridge.mm +++ b/src/darwin/Framework/CHIP/MTRAttestationTrustStoreBridge.mm @@ -16,8 +16,7 @@ */ #import "MTRAttestationTrustStoreBridge.h" - -static chip::ByteSpan asByteSpan(NSData * value) { return chip::ByteSpan(static_cast(value.bytes), value.length); } +#import "NSDataSpanConversion.h" CHIP_ERROR MTRAttestationTrustStoreBridge::GetProductAttestationAuthorityCert( const chip::ByteSpan & skid, chip::MutableByteSpan & outPaaDerBuffer) const @@ -29,7 +28,7 @@ for (paaIdx = 0; paaIdx < mPaaCerts.count; ++paaIdx) { uint8_t skidBuf[chip::Crypto::kSubjectKeyIdentifierLength] = { 0 }; - candidate = asByteSpan(mPaaCerts[paaIdx]); + candidate = AsByteSpan(mPaaCerts[paaIdx]); chip::MutableByteSpan candidateSkidSpan { skidBuf }; VerifyOrReturnError( CHIP_NO_ERROR == chip::Crypto::ExtractSKIDFromX509Cert(candidate, candidateSkidSpan), CHIP_ERROR_INTERNAL); diff --git a/src/darwin/Framework/CHIP/MTRControllerFactory.h b/src/darwin/Framework/CHIP/MTRControllerFactory.h index 8e8eb8a9fcf318..508cf369374bae 100644 --- a/src/darwin/Framework/CHIP/MTRControllerFactory.h +++ b/src/darwin/Framework/CHIP/MTRControllerFactory.h @@ -51,6 +51,12 @@ NS_ASSUME_NONNULL_BEGIN * */ @property (nonatomic, copy, nullable) NSArray * paaCerts; +/* + * The Certificate Declaration certificates that are trusted to sign + * device attestation information. Defaults to nil. + * + */ +@property (nonatomic, copy, nullable) NSArray * cdCerts; /* * The network port to bind to. If not specified, an ephemeral port will be * used. diff --git a/src/darwin/Framework/CHIP/MTRControllerFactory.mm b/src/darwin/Framework/CHIP/MTRControllerFactory.mm index 337299bde13570..f769548a2d7f24 100644 --- a/src/darwin/Framework/CHIP/MTRControllerFactory.mm +++ b/src/darwin/Framework/CHIP/MTRControllerFactory.mm @@ -54,6 +54,7 @@ static NSString * const kErrorControllerFactoryInit = @"Init failure while initializing controller factory"; static NSString * const kErrorKeystoreInit = @"Init failure while initializing persistent storage keystore"; static NSString * const kErrorCertStoreInit = @"Init failure while initializing persistent storage operational certificate store"; +static NSString * const kErrorCDCertStoreInit = @"Init failure while initializing Certificate Declaration Signing Keys store"; static NSString * const kErrorOtaProviderInit = @"Init failure while creating an OTA provider delegate"; @interface MTRControllerFactory () @@ -274,6 +275,22 @@ - (BOOL)startup:(MTRControllerFactoryParams *)startupParams return; } + if (startupParams.cdCerts) { + auto cdTrustStore = _deviceAttestationVerifier->GetCertificationDeclarationTrustStore(); + if (cdTrustStore == nullptr) { + MTR_LOG_ERROR("Error: %@", kErrorCDCertStoreInit); + return; + } + + for (NSData * cdSigningCert in startupParams.cdCerts) { + errorCode = cdTrustStore->AddTrustedKey(AsByteSpan(cdSigningCert)); + if (errorCode != CHIP_NO_ERROR) { + MTR_LOG_ERROR("Error: %@", kErrorCDCertStoreInit); + return; + } + } + } + chip::Controller::FactoryInitParams params; if (startupParams.port != nil) { params.listenPort = [startupParams.port unsignedShortValue]; @@ -612,6 +629,7 @@ - (instancetype)initWithStorage:(id)storageDelegat _storageDelegate = storageDelegate; _otaProviderDelegate = nil; _paaCerts = nil; + _cdCerts = nil; _port = nil; _startServer = NO; diff --git a/src/lib/core/CHIPConfig.h b/src/lib/core/CHIPConfig.h index 95fea208f584b2..60865613b45efe 100644 --- a/src/lib/core/CHIPConfig.h +++ b/src/lib/core/CHIPConfig.h @@ -1282,6 +1282,15 @@ extern const char CHIP_NON_PRODUCTION_MARKER[]; #define CHIP_CONFIG_SETUP_CODE_PAIRER_DISCOVERY_TIMEOUT_SECS 30 #endif // CHIP_CONFIG_SETUP_CODE_PAIRER_DISCOVERY_TIMEOUT_SECS +/** + * @def CHIP_CONFIG_NUM_CD_KEY_SLOTS + * + * @brief Number of custom CD signing keys supported by default CD keystore + * + */ +#ifndef CHIP_CONFIG_NUM_CD_KEY_SLOTS +#define CHIP_CONFIG_NUM_CD_KEY_SLOTS 5 +#endif // CHIP_CONFIG_NUM_CD_KEY_SLOTS /** * @} */ diff --git a/src/lib/support/tests/BUILD.gn b/src/lib/support/tests/BUILD.gn index 99cc2801355119..866fd6391feabd 100644 --- a/src/lib/support/tests/BUILD.gn +++ b/src/lib/support/tests/BUILD.gn @@ -60,7 +60,12 @@ chip_test_suite("tests") { test_sources += [ "TestCHIPArgParser.cpp" ] } - cflags = [ "-Wconversion" ] + cflags = [ + "-Wconversion", + + # TODO(#21255): work-around for SimpleStateMachine constructor issue. + "-Wno-error=uninitialized", + ] public_deps = [ "${chip_root}/src/credentials",