blob: 99a586d1b5b5b8eda2aa9eeb44a66e86687cfda7 [file] [log] [blame]
Evgeny Margolisaa2f2252022-10-03 10:13:00 -07001/*
2 *
3 * Copyright (c) 2022 Project CHIP Authors
4 * All rights reserved.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18#include <crypto/CHIPCryptoPAL.h>
19
20#include <app/tests/suites/credentials/TestHarnessDACProvider.h>
21#include <controller/CHIPDeviceController.h>
22#include <controller/CommissioneeDeviceProxy.h>
23#include <credentials/CertificationDeclaration.h>
24#include <credentials/DeviceAttestationCredsProvider.h>
25#include <credentials/attestation_verifier/DefaultDeviceAttestationVerifier.h>
26#include <credentials/attestation_verifier/DeviceAttestationVerifier.h>
27#include <credentials/examples/DeviceAttestationCredsExample.h>
28
29#include <lib/core/CHIPError.h>
30#include <lib/support/CHIPMem.h>
31#include <lib/support/Span.h>
32#include <lib/support/UnitTestExtendedAssertions.h>
33#include <lib/support/UnitTestRegistration.h>
34
35#include <nlunit-test.h>
36
37#include <dirent.h>
38#include <stdio.h>
39#include <string>
40
41using namespace chip;
42using namespace chip::Crypto;
43using namespace chip::Credentials;
44
45static void OnAttestationInformationVerificationCallback(void * context, const DeviceAttestationVerifier::AttestationInfo & info,
46 AttestationVerificationResult result)
47{
48 AttestationVerificationResult * pResult = reinterpret_cast<AttestationVerificationResult *>(context);
49 *pResult = result;
50}
51
52static void TestCommissionerDUTVectors(nlTestSuite * inSuite, void * inContext)
53{
54 DeviceAttestationVerifier * example_dac_verifier = GetDefaultDACVerifier(GetTestAttestationTrustStore());
55 NL_TEST_ASSERT(inSuite, example_dac_verifier != nullptr);
56
57 std::string dirPath("../../../../../credentials/development/commissioner_dut/");
58 DIR * dir = opendir(dirPath.c_str());
59 while (dir == nullptr && (dirPath.find("../") == 0))
60 {
61 dirPath = dirPath.substr(3);
62 dir = opendir(dirPath.c_str());
63 }
64 if (dir == nullptr)
65 {
66 ChipLogError(Crypto, "Couldn't open folder with Commissioner DUT Test Vectors.");
67 return;
68 }
69
70 dirent * entry;
71 while ((entry = readdir(dir)) != nullptr)
72 {
73 if (entry->d_name[0] == '.')
74 continue;
75
76 // Skip this test case because the code below will fail to use secp256k1 to sign attestation data.
77 if (strstr(entry->d_name, "struct_dac_sig_curve_secp256k1"))
78 continue;
79
80 std::string jsonFilePath = dirPath + std::string(entry->d_name) + std::string("/test_case_vector.json");
81
82 chip::Credentials::Examples::TestHarnessDACProvider dacProvider;
83 dacProvider.Init(jsonFilePath.c_str());
84
85 uint8_t attestationChallengeBuf[Crypto::kAES_CCM128_Key_Length];
86 MutableByteSpan attestationChallengeSpan(attestationChallengeBuf);
87 Crypto::DRBG_get_bytes(attestationChallengeBuf, sizeof(attestationChallengeBuf));
88
89 Crypto::P256ECDSASignature signature;
90 MutableByteSpan attestationSignatureSpan{ signature.Bytes(), signature.Capacity() };
91
92 uint8_t certDeclBuf[Credentials::kMaxCMSSignedCDMessage];
93 MutableByteSpan certDeclSpan(certDeclBuf);
94
95 uint8_t dacCertBuf[kMaxDERCertLength];
96 MutableByteSpan dacCertSpan(dacCertBuf);
97
98 uint8_t paiCertBuf[kMaxDERCertLength];
99 MutableByteSpan paiCertSpan(paiCertBuf);
100
101 uint8_t attestationNonceBuf[kAttestationNonceLength];
102 MutableByteSpan attestationNonceSpan(attestationNonceBuf);
103 Crypto::DRBG_get_bytes(attestationNonceBuf, sizeof(attestationNonceBuf));
104
105 VendorId vid = TestVendor1;
106 uint16_t pid = strstr(entry->d_name, "_vidpid_fallback_encoding_") ? 0x00B1 : 0x8000;
107
108 NL_TEST_ASSERT_SUCCESS(inSuite, dacProvider.GetCertificationDeclaration(certDeclSpan));
109 NL_TEST_ASSERT_SUCCESS(inSuite, dacProvider.GetDeviceAttestationCert(dacCertSpan));
110 NL_TEST_ASSERT_SUCCESS(inSuite, dacProvider.GetProductAttestationIntermediateCert(paiCertSpan));
111
112 size_t attestationElementsLen =
113 TLV::EstimateStructOverhead(certDeclSpan.size(), attestationNonceSpan.size(), sizeof(uint64_t) * 8);
114 Platform::ScopedMemoryBuffer<uint8_t> attestationElements;
115 NL_TEST_ASSERT(inSuite, attestationElements.Alloc(attestationElementsLen + attestationChallengeSpan.size()));
116 MutableByteSpan attestationElementsSpan(attestationElements.Get(), attestationElementsLen);
117
118 // Construct attestation elements
119 {
120 uint32_t timestamp = 0;
121 Credentials::DeviceAttestationVendorReservedConstructor emptyVendorReserved(nullptr, 0);
122 const ByteSpan kEmptyFirmwareInfo;
123
124 NL_TEST_ASSERT_SUCCESS(inSuite,
125 Credentials::ConstructAttestationElements(certDeclSpan, attestationNonceSpan, timestamp,
126 kEmptyFirmwareInfo, emptyVendorReserved,
127 attestationElementsSpan));
128 }
129
130 // Generate attestation signature
131 {
132 // Append attestation challenge in the back of the reserved space for the signature
133 memcpy(attestationElementsSpan.data() + attestationElementsSpan.size(), attestationChallengeSpan.data(),
134 attestationChallengeSpan.size());
135 ByteSpan tbsSpan(attestationElementsSpan.data(), attestationElementsSpan.size() + attestationChallengeSpan.size());
136
137 NL_TEST_ASSERT_SUCCESS(inSuite, dacProvider.SignWithDeviceAttestationKey(tbsSpan, attestationSignatureSpan));
138 NL_TEST_ASSERT(inSuite, attestationSignatureSpan.size() == signature.Capacity());
139 }
140
141 AttestationVerificationResult attestationResult = AttestationVerificationResult::kNotImplemented;
142 Callback::Callback<DeviceAttestationVerifier::OnAttestationInformationVerification>
143 attestationInformationVerificationCallback(OnAttestationInformationVerificationCallback, &attestationResult);
144
145 DeviceAttestationVerifier::AttestationInfo info(attestationElementsSpan, attestationChallengeSpan, attestationSignatureSpan,
146 paiCertSpan, dacCertSpan, attestationNonceSpan, vid, pid);
147
148 example_dac_verifier->VerifyAttestationInformation(info, &attestationInformationVerificationCallback);
149
150 bool isSuccessCase = dacProvider.IsSuccessCase();
151 // The DefaultDACVerifier doesn't currently check validity of CD elements values.
152 if (strstr(entry->d_name, "struct_cd_device_type_id_mismatch") || strstr(entry->d_name, "struct_cd_security_info_wrong") ||
153 strstr(entry->d_name, "struct_cd_cert_type_wrong") || strstr(entry->d_name, "struct_cd_security_level_wrong") ||
154 strstr(entry->d_name, "struct_cd_version_number_wrong") || strstr(entry->d_name, "struct_cd_format_version_2") ||
155 strstr(entry->d_name, "struct_cd_cert_id_mismatch"))
156 {
157 isSuccessCase = true;
158 }
159
160 if (isSuccessCase)
161 {
162 NL_TEST_ASSERT(inSuite, attestationResult == AttestationVerificationResult::kSuccess);
163 }
164 else
165 {
166 NL_TEST_ASSERT(inSuite, attestationResult != AttestationVerificationResult::kSuccess);
167 }
168 }
169 closedir(dir);
170}
171
172/**
173 * Set up the test suite.
174 */
175int TestCommissionerDUT_Setup(void * inContext)
176{
177 CHIP_ERROR error = chip::Platform::MemoryInit();
178
179 if (error != CHIP_NO_ERROR)
180 {
181 return FAILURE;
182 }
183
184 return SUCCESS;
185}
186
187/**
188 * Tear down the test suite.
189 */
190int TestCommissionerDUT_Teardown(void * inContext)
191{
192 chip::Platform::MemoryShutdown();
193 return SUCCESS;
194}
195
196/**
197 * Test Suite. It lists all the test functions.
198 */
199// clang-format off
200static const nlTest sTests[] = {
201 NL_TEST_DEF("Test Device Attestation Credentials Vectors", TestCommissionerDUTVectors),
202 NL_TEST_SENTINEL()
203};
204// clang-format on
205
206int TestCommissionerDUT()
207{
208 // clang-format off
209 nlTestSuite theSuite =
210 {
211 "Device Attestation Credentials Test Vectors",
212 &sTests[0],
213 TestCommissionerDUT_Setup,
214 TestCommissionerDUT_Teardown
215 };
216 // clang-format on
217 nlTestRunner(&theSuite, nullptr);
218 return (nlTestRunnerStats(&theSuite));
219}
220
221CHIP_REGISTER_TEST_SUITE(TestCommissionerDUT);