Skip to content

Commit 1102944

Browse files
vivien-applepull[bot]
authored andcommitted
[all-clusters-app] Add some command line options to modify what is returned by the CSRResponse (#19461)
* [examples/platform/linux - Testing] Add some command line options to modify what is returned by the CSRResponse * Add additional checks related to RESP_MAX into the DefaultDeviceAttestationVerifier
1 parent 7f4a056 commit 1102944

File tree

7 files changed

+287
-25
lines changed

7 files changed

+287
-25
lines changed

examples/all-clusters-app/linux/AppOptions.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#include <app/server/CommissioningWindowManager.h>
2222
#include <app/server/Server.h>
2323

24+
using namespace chip::ArgParser;
25+
2426
using chip::ArgParser::OptionDef;
2527
using chip::ArgParser::OptionSet;
2628
using chip::ArgParser::PrintArgError;
@@ -55,8 +57,8 @@ bool AppOptions::HandleOptions(const char * program, OptionSet * options, int id
5557
OptionSet * AppOptions::GetOptions()
5658
{
5759
static OptionDef optionsDef[] = {
58-
{ "dac_provider", chip::ArgParser::kArgumentRequired, kOptionDacProviderFilePath },
59-
{ "min_commissioning_timeout", chip::ArgParser::kArgumentRequired, kOptionMinCommissioningTimeout },
60+
{ "dac_provider", kArgumentRequired, kOptionDacProviderFilePath },
61+
{ "min_commissioning_timeout", kArgumentRequired, kOptionMinCommissioningTimeout },
6062
{},
6163
};
6264

examples/platform/linux/BUILD.gn

+2
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ source_set("app-main") {
3939
"LinuxCommissionableDataProvider.h",
4040
"Options.cpp",
4141
"Options.h",
42+
"testing/CustomCSRResponse.cpp",
43+
"testing/CustomCSRResponse.h",
4244
]
4345

4446
defines = []

examples/platform/linux/Options.cpp

+73-23
Original file line numberDiff line numberDiff line change
@@ -39,29 +39,36 @@ LinuxDeviceOptions gDeviceOptions;
3939
// Follow the code style of command line arguments in case we need to add more options in the future.
4040
enum
4141
{
42-
kDeviceOption_BleDevice = 0x1000,
43-
kDeviceOption_WiFi = 0x1001,
44-
kDeviceOption_Thread = 0x1002,
45-
kDeviceOption_Version = 0x1003,
46-
kDeviceOption_VendorID = 0x1004,
47-
kDeviceOption_ProductID = 0x1005,
48-
kDeviceOption_CustomFlow = 0x1006,
49-
kDeviceOption_Capabilities = 0x1007,
50-
kDeviceOption_Discriminator = 0x1008,
51-
kDeviceOption_Passcode = 0x1009,
52-
kDeviceOption_SecuredDevicePort = 0x100a,
53-
kDeviceOption_SecuredCommissionerPort = 0x100b,
54-
kDeviceOption_UnsecuredCommissionerPort = 0x100c,
55-
kDeviceOption_Command = 0x100d,
56-
kDeviceOption_PICS = 0x100e,
57-
kDeviceOption_KVS = 0x100f,
58-
kDeviceOption_InterfaceId = 0x1010,
59-
kDeviceOption_Spake2pVerifierBase64 = 0x1011,
60-
kDeviceOption_Spake2pSaltBase64 = 0x1012,
61-
kDeviceOption_Spake2pIterations = 0x1013,
62-
kDeviceOption_TraceFile = 0x1014,
63-
kDeviceOption_TraceLog = 0x1015,
64-
kDeviceOption_TraceDecode = 0x1016,
42+
kDeviceOption_BleDevice = 0x1000,
43+
kDeviceOption_WiFi = 0x1001,
44+
kDeviceOption_Thread = 0x1002,
45+
kDeviceOption_Version = 0x1003,
46+
kDeviceOption_VendorID = 0x1004,
47+
kDeviceOption_ProductID = 0x1005,
48+
kDeviceOption_CustomFlow = 0x1006,
49+
kDeviceOption_Capabilities = 0x1007,
50+
kDeviceOption_Discriminator = 0x1008,
51+
kDeviceOption_Passcode = 0x1009,
52+
kDeviceOption_SecuredDevicePort = 0x100a,
53+
kDeviceOption_SecuredCommissionerPort = 0x100b,
54+
kDeviceOption_UnsecuredCommissionerPort = 0x100c,
55+
kDeviceOption_Command = 0x100d,
56+
kDeviceOption_PICS = 0x100e,
57+
kDeviceOption_KVS = 0x100f,
58+
kDeviceOption_InterfaceId = 0x1010,
59+
kDeviceOption_Spake2pVerifierBase64 = 0x1011,
60+
kDeviceOption_Spake2pSaltBase64 = 0x1012,
61+
kDeviceOption_Spake2pIterations = 0x1013,
62+
kDeviceOption_TraceFile = 0x1014,
63+
kDeviceOption_TraceLog = 0x1015,
64+
kDeviceOption_TraceDecode = 0x1016,
65+
kOptionCSRResponseCSRIncorrectType = 0x1017,
66+
kOptionCSRResponseCSRNonceIncorrectType = 0x1018,
67+
kOptionCSRResponseCSRNonceTooLong = 0x1019,
68+
kOptionCSRResponseCSRNonceInvalid = 0x101a,
69+
kOptionCSRResponseNOCSRElementsTooLong = 0x101b,
70+
kOptionCSRResponseAttestationSignatureIncorrectType = 0x101c,
71+
kOptionCSRResponseAttestationSignatureInvalid = 0x101d,
6572
};
6673

6774
constexpr unsigned kAppUsageLength = 64;
@@ -98,6 +105,13 @@ OptionDef sDeviceOptionDefs[] = {
98105
{ "trace_log", kArgumentRequired, kDeviceOption_TraceLog },
99106
{ "trace_decode", kArgumentRequired, kDeviceOption_TraceDecode },
100107
#endif // CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
108+
{ "cert_error_csr_incorrect_type", kNoArgument, kOptionCSRResponseCSRIncorrectType },
109+
{ "cert_error_csr_nonce_incorrect_type", kNoArgument, kOptionCSRResponseCSRNonceIncorrectType },
110+
{ "cert_error_csr_nonce_too_long", kNoArgument, kOptionCSRResponseCSRNonceTooLong },
111+
{ "cert_error_csr_nonce_invalid", kNoArgument, kOptionCSRResponseCSRNonceInvalid },
112+
{ "cert_error_nocsrelements_too_long", kNoArgument, kOptionCSRResponseNOCSRElementsTooLong },
113+
{ "cert_error_attestation_signature_incorrect_type", kNoArgument, kOptionCSRResponseAttestationSignatureIncorrectType },
114+
{ "cert_error_attestation_signature_invalid", kNoArgument, kOptionCSRResponseAttestationSignatureInvalid },
101115
{}
102116
};
103117

@@ -183,6 +197,20 @@ const char * sDeviceOptionHelp =
183197
" --trace_decode <1/0>\n"
184198
" A value of 1 enables traces decoding, 0 disables this (default 0).\n"
185199
#endif // CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
200+
" --cert_error_csr_incorrect_type\n"
201+
" Configure the CSRResponse to be built with an invalid CSR type.\n"
202+
" --cert_error_csr_nonce_incorrect_type\n"
203+
" Configure the CSRResponse to be built with an invalid CSRNonce type.\n"
204+
" --cert_error_csr_nonce_too_long\n"
205+
" Configure the CSRResponse to be built with a CSRNonce that is longer than expected.\n"
206+
" --cert_error_csr_nonce_invalid\n"
207+
" Configure the CSRResponse to be built with a CSRNonce that does not match the CSRNonce from the CSRRequest.\n"
208+
" --cert_error_nocsrelements_too_long\n"
209+
" Configure the CSRResponse to contains an NOCSRElements larger than the allowed RESP_MAX.\n"
210+
" --cert_error_attestation_signature_incorrect_type\n"
211+
" Configure the CSRResponse to be build with an invalid AttestationSignature type.\n"
212+
" --cert_error_attestation_signature_invalid\n"
213+
" Configure the CSRResponse to be build with an AttestationSignature that does not match what is expected.\n"
186214
"\n";
187215

188216
bool Base64ArgToVector(const char * arg, size_t maxSize, std::vector<uint8_t> & outVector)
@@ -386,6 +414,28 @@ bool HandleOption(const char * aProgram, OptionSet * aOptions, int aIdentifier,
386414
break;
387415
#endif // CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
388416

417+
case kOptionCSRResponseCSRIncorrectType:
418+
LinuxDeviceOptions::GetInstance().mCSRResponseOptions.csrIncorrectType = true;
419+
break;
420+
case kOptionCSRResponseCSRNonceIncorrectType:
421+
LinuxDeviceOptions::GetInstance().mCSRResponseOptions.csrNonceIncorrectType = true;
422+
break;
423+
case kOptionCSRResponseCSRNonceTooLong:
424+
LinuxDeviceOptions::GetInstance().mCSRResponseOptions.csrNonceTooLong = true;
425+
break;
426+
case kOptionCSRResponseCSRNonceInvalid:
427+
LinuxDeviceOptions::GetInstance().mCSRResponseOptions.csrNonceInvalid = true;
428+
break;
429+
case kOptionCSRResponseNOCSRElementsTooLong:
430+
LinuxDeviceOptions::GetInstance().mCSRResponseOptions.nocsrElementsTooLong = true;
431+
break;
432+
case kOptionCSRResponseAttestationSignatureIncorrectType:
433+
LinuxDeviceOptions::GetInstance().mCSRResponseOptions.attestationSignatureIncorrectType = true;
434+
break;
435+
case kOptionCSRResponseAttestationSignatureInvalid:
436+
LinuxDeviceOptions::GetInstance().mCSRResponseOptions.attestationSignatureInvalid = true;
437+
break;
438+
389439
default:
390440
PrintArgError("%s: INTERNAL ERROR: Unhandled option: %s\n", aProgram, aName);
391441
retval = false;

examples/platform/linux/Options.h

+2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include <setup_payload/SetupPayload.h>
3636

3737
#include <credentials/DeviceAttestationCredsProvider.h>
38+
#include <testing/CustomCSRResponse.h>
3839

3940
struct LinuxDeviceOptions
4041
{
@@ -57,6 +58,7 @@ struct LinuxDeviceOptions
5758
bool traceStreamToLogEnabled = false;
5859
chip::Optional<std::string> traceStreamFilename;
5960
chip::Credentials::DeviceAttestationCredentialsProvider * dacProvider = nullptr;
61+
chip::CSRResponseOptions mCSRResponseOptions;
6062

6163
static LinuxDeviceOptions & GetInstance();
6264
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
/*
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+
19+
#include "Options.h"
20+
21+
#include <algorithm>
22+
#include <app-common/zap-generated/cluster-objects.h>
23+
#include <app/data-model/Encode.h>
24+
#include <credentials/DeviceAttestationConstructor.h>
25+
#include <crypto/CHIPCryptoPAL.h>
26+
27+
using namespace chip;
28+
using namespace chip::app;
29+
using namespace chip::app::Clusters::OperationalCredentials::Commands;
30+
31+
constexpr size_t kMaxResponseLength = 900;
32+
constexpr size_t kCSRNonceLength = 32;
33+
34+
namespace {
35+
36+
CHIP_ERROR ConstructCustomNOCSRElements(TLV::TLVWriter & writer, TLV::Tag tag, const ByteSpan & nocsrElements,
37+
CSRResponseOptions & options)
38+
{
39+
ByteSpan csr;
40+
ByteSpan csrNonce;
41+
ByteSpan vendorReserved1;
42+
ByteSpan vendorReserved2;
43+
ByteSpan vendorReserved3;
44+
ReturnErrorOnFailure(
45+
Credentials::DeconstructNOCSRElements(nocsrElements, csr, csrNonce, vendorReserved1, vendorReserved2, vendorReserved3));
46+
47+
// Add 10 bytes of possible overhead to allow the generation of content longer than the allowed maximum of RESP_MAX.
48+
// 10 has been choosen to leave enough space for the possible TLV overhead when adding the additional data.
49+
uint8_t nocsrElementsData[kMaxResponseLength + 10];
50+
MutableByteSpan nocsrElementsSpan(nocsrElementsData);
51+
52+
TLV::TLVType outerContainerType = TLV::kTLVType_NotSpecified;
53+
TLV::TLVWriter tlvWriter;
54+
tlvWriter.Init(nocsrElementsSpan);
55+
56+
ReturnErrorOnFailure(tlvWriter.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerContainerType));
57+
58+
// Update CSR
59+
if (options.csrIncorrectType)
60+
{
61+
ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(1), true));
62+
}
63+
else
64+
{
65+
ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(1), csr));
66+
}
67+
68+
// Update CSRNonce
69+
if (options.csrNonceIncorrectType)
70+
{
71+
ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(2), true));
72+
}
73+
else if (options.csrNonceInvalid)
74+
{
75+
uint8_t csrNonceInvalid[kCSRNonceLength] = {};
76+
memcpy(csrNonceInvalid, csrNonce.data(), csrNonce.size());
77+
std::reverse(csrNonceInvalid, csrNonceInvalid + sizeof(csrNonceInvalid));
78+
ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(2), ByteSpan(csrNonceInvalid)));
79+
}
80+
else if (options.csrNonceTooLong)
81+
{
82+
uint8_t csrNonceTooLong[kCSRNonceLength + 1] = {};
83+
memcpy(csrNonceTooLong, csrNonce.data(), csrNonce.size());
84+
ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(2), ByteSpan(csrNonceTooLong)));
85+
}
86+
else
87+
{
88+
ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(2), csrNonce));
89+
}
90+
91+
// Add vendorReserved1 if present
92+
if (!vendorReserved1.empty())
93+
{
94+
ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(3), vendorReserved1));
95+
}
96+
97+
// Add vendorReserved2 if present
98+
if (!vendorReserved2.empty())
99+
{
100+
ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(4), vendorReserved2));
101+
}
102+
103+
// Add vendorReserved3 if present
104+
if (!vendorReserved3.empty())
105+
{
106+
ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(5), vendorReserved3));
107+
}
108+
109+
// Add additional data
110+
if (options.nocsrElementsTooLong)
111+
{
112+
size_t len = kMaxResponseLength - tlvWriter.GetLengthWritten();
113+
ReturnLogErrorOnFailure(tlvWriter.Put(TLV::ContextTag(6), ByteSpan(nocsrElementsData, len)));
114+
}
115+
116+
ReturnErrorOnFailure(tlvWriter.EndContainer(outerContainerType));
117+
ReturnErrorOnFailure(tlvWriter.Finalize());
118+
119+
return DataModel::Encode(writer, tag, nocsrElementsSpan.SubSpan(0, tlvWriter.GetLengthWritten()));
120+
}
121+
122+
CHIP_ERROR ConstructCustomAttestationSignature(TLV::TLVWriter & writer, TLV::Tag tag, const ByteSpan & attestationSignature,
123+
CSRResponseOptions & options)
124+
{
125+
if (options.attestationSignatureIncorrectType)
126+
{
127+
return DataModel::Encode(writer, tag, true);
128+
}
129+
130+
if (options.attestationSignatureInvalid)
131+
{
132+
uint8_t invalidAttestationSignature[Crypto::kP256_ECDSA_Signature_Length_Raw] = {};
133+
memcpy(invalidAttestationSignature, attestationSignature.data(), attestationSignature.size());
134+
std::reverse(invalidAttestationSignature, invalidAttestationSignature + sizeof(invalidAttestationSignature));
135+
return DataModel::Encode(writer, tag, ByteSpan(invalidAttestationSignature));
136+
}
137+
138+
return DataModel::Encode(writer, tag, attestationSignature);
139+
}
140+
141+
} // namespace
142+
143+
namespace chip {
144+
namespace app {
145+
namespace DataModel {
146+
147+
template <>
148+
CHIP_ERROR Encode(TLV::TLVWriter & writer, TLV::Tag tag, const CSRResponse::Type & responseData)
149+
{
150+
auto tag1 = TLV::ContextTag(to_underlying(CSRResponse::Fields::kNOCSRElements));
151+
auto tag2 = TLV::ContextTag(to_underlying(CSRResponse::Fields::kAttestationSignature));
152+
auto options = LinuxDeviceOptions::GetInstance().mCSRResponseOptions;
153+
154+
TLV::TLVType outer;
155+
ReturnErrorOnFailure(writer.StartContainer(tag, TLV::kTLVType_Structure, outer));
156+
ReturnErrorOnFailure(ConstructCustomNOCSRElements(writer, tag1, responseData.NOCSRElements, options));
157+
ReturnErrorOnFailure(ConstructCustomAttestationSignature(writer, tag2, responseData.attestationSignature, options));
158+
ReturnErrorOnFailure(writer.EndContainer(outer));
159+
160+
return CHIP_NO_ERROR;
161+
}
162+
163+
} // namespace DataModel
164+
} // namespace app
165+
} // namespace chip
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
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+
19+
namespace chip {
20+
21+
struct CSRResponseOptions
22+
{
23+
bool csrIncorrectType = false;
24+
bool csrNonceIncorrectType = false;
25+
bool csrNonceTooLong = false;
26+
bool csrNonceInvalid = false;
27+
bool nocsrElementsTooLong = false;
28+
bool attestationSignatureIncorrectType = false;
29+
bool attestationSignatureInvalid = false;
30+
};
31+
32+
} // namespace chip

0 commit comments

Comments
 (0)