Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2021-2022 Project CHIP Authors
4 : *
5 : * Licensed under the Apache License, Version 2.0 (the "License");
6 : * you may not use this file except in compliance with the License.
7 : * You may obtain a copy of the License at
8 : *
9 : * http://www.apache.org/licenses/LICENSE-2.0
10 : *
11 : * Unless required by applicable law or agreed to in writing, software
12 : * distributed under the License is distributed on an "AS IS" BASIS,
13 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 : * See the License for the specific language governing permissions and
15 : * limitations under the License.
16 : */
17 : #include "DacOnlyPartialAttestationVerifier.h"
18 :
19 : #include <controller/OperationalCredentialsDelegate.h>
20 : #include <credentials/CHIPCert.h>
21 : #include <credentials/CertificationDeclaration.h>
22 : #include <credentials/DeviceAttestationConstructor.h>
23 : #include <credentials/DeviceAttestationVendorReserved.h>
24 : #include <crypto/CHIPCryptoPAL.h>
25 :
26 : #include <lib/core/CHIPError.h>
27 : #include <lib/support/CodeUtils.h>
28 : #include <lib/support/ScopedBuffer.h>
29 : #include <lib/support/Span.h>
30 :
31 : using namespace chip::Crypto;
32 :
33 : namespace chip {
34 : namespace Credentials {
35 :
36 : // As per specifications section 11.22.5.1. Constant RESP_MAX
37 : constexpr size_t kMaxResponseLength = 900;
38 :
39 : /**
40 : * The implementation should track DefaultDACVerifier::VerifyAttestationInformation but with the checks
41 : * disabled that are outlined at the top of DacOnlyPartialAttestationVerifier.h.
42 : */
43 0 : void PartialDACVerifier::VerifyAttestationInformation(const DeviceAttestationVerifier::AttestationInfo & info,
44 : Callback::Callback<OnAttestationInformationVerification> * onCompletion)
45 : {
46 0 : AttestationVerificationResult attestationError = AttestationVerificationResult::kSuccess;
47 :
48 0 : AttestationCertVidPid dacVidPid;
49 0 : AttestationCertVidPid paiVidPid;
50 0 : AttestationCertVidPid paaVidPid;
51 :
52 0 : DeviceInfoForAttestation deviceInfo{
53 0 : .vendorId = info.vendorId,
54 0 : .productId = info.productId,
55 0 : };
56 :
57 0 : VerifyOrExit(!info.attestationElementsBuffer.empty() && !info.attestationChallengeBuffer.empty() &&
58 : !info.attestationSignatureBuffer.empty() && !info.paiDerBuffer.empty() && !info.dacDerBuffer.empty() &&
59 : !info.attestationNonceBuffer.empty() && onCompletion != nullptr,
60 : attestationError = AttestationVerificationResult::kInvalidArgument);
61 :
62 0 : VerifyOrExit(info.attestationElementsBuffer.size() <= kMaxResponseLength,
63 : attestationError = AttestationVerificationResult::kInvalidArgument);
64 :
65 : // match DAC and PAI VIDs
66 : {
67 0 : VerifyOrExit(ExtractVIDPIDFromX509Cert(info.dacDerBuffer, dacVidPid) == CHIP_NO_ERROR,
68 : attestationError = AttestationVerificationResult::kDacFormatInvalid);
69 0 : VerifyOrExit(ExtractVIDPIDFromX509Cert(info.paiDerBuffer, paiVidPid) == CHIP_NO_ERROR,
70 : attestationError = AttestationVerificationResult::kPaiFormatInvalid);
71 0 : VerifyOrExit(paiVidPid.mVendorId.HasValue() && paiVidPid.mVendorId == dacVidPid.mVendorId,
72 : attestationError = AttestationVerificationResult::kDacVendorIdMismatch);
73 0 : VerifyOrExit(dacVidPid.mProductId.HasValue(), attestationError = AttestationVerificationResult::kDacProductIdMismatch);
74 0 : if (paiVidPid.mProductId.HasValue())
75 : {
76 0 : VerifyOrExit(paiVidPid.mProductId == dacVidPid.mProductId,
77 : attestationError = AttestationVerificationResult::kDacProductIdMismatch);
78 : }
79 : }
80 :
81 : {
82 0 : P256PublicKey remoteManufacturerPubkey;
83 0 : P256ECDSASignature deviceSignature;
84 :
85 0 : VerifyOrExit(ExtractPubkeyFromX509Cert(info.dacDerBuffer, remoteManufacturerPubkey) == CHIP_NO_ERROR,
86 : attestationError = AttestationVerificationResult::kDacFormatInvalid);
87 :
88 : // Validate overall attestation signature on attestation information
89 : // SetLength will fail if signature doesn't fit
90 0 : VerifyOrExit(deviceSignature.SetLength(info.attestationSignatureBuffer.size()) == CHIP_NO_ERROR,
91 : attestationError = AttestationVerificationResult::kAttestationSignatureInvalidFormat);
92 0 : memcpy(deviceSignature.Bytes(), info.attestationSignatureBuffer.data(), info.attestationSignatureBuffer.size());
93 0 : VerifyOrExit(ValidateAttestationSignature(remoteManufacturerPubkey, info.attestationElementsBuffer,
94 : info.attestationChallengeBuffer, deviceSignature) == CHIP_NO_ERROR,
95 : attestationError = AttestationVerificationResult::kAttestationSignatureInvalid);
96 0 : }
97 :
98 : {
99 0 : MutableByteSpan akid(deviceInfo.paaSKID);
100 :
101 0 : VerifyOrExit(ExtractAKIDFromX509Cert(info.paiDerBuffer, akid) == CHIP_NO_ERROR,
102 : attestationError = AttestationVerificationResult::kPaiFormatInvalid);
103 :
104 0 : ChipLogProgress(Support, "PartialDACVerifier::CheckPAA skipping vid-scoped PAA check - PAARootStore disabled");
105 : }
106 :
107 : #if !defined(CURRENT_TIME_NOT_IMPLEMENTED)
108 0 : VerifyOrExit(IsCertificateValidAtCurrentTime(info.dacDerBuffer) == CHIP_NO_ERROR,
109 : attestationError = AttestationVerificationResult::kDacExpired);
110 : #endif
111 :
112 0 : ChipLogProgress(Support, "PartialDACVerifier::CheckCertChain skipping cert chain check - PAARootStore disabled");
113 :
114 : {
115 0 : ByteSpan certificationDeclarationSpan;
116 0 : ByteSpan attestationNonceSpan;
117 : uint32_t timestampDeconstructed;
118 0 : ByteSpan firmwareInfoSpan;
119 0 : DeviceAttestationVendorReservedDeconstructor vendorReserved;
120 0 : ByteSpan certificationDeclarationPayload;
121 :
122 0 : deviceInfo.dacVendorId = dacVidPid.mVendorId.Value();
123 0 : deviceInfo.dacProductId = dacVidPid.mProductId.Value();
124 0 : deviceInfo.paiVendorId = paiVidPid.mVendorId.Value();
125 0 : deviceInfo.paiProductId = paiVidPid.mProductId.ValueOr(0);
126 0 : deviceInfo.paaVendorId = paaVidPid.mVendorId.ValueOr(VendorId::NotSpecified);
127 :
128 0 : ChipLogProgress(
129 : Support,
130 : "PartialDACVerifier::VerifyAttestationInformation skipping PAA subject key id extraction - PAARootStore disabled");
131 :
132 0 : VerifyOrExit(DeconstructAttestationElements(info.attestationElementsBuffer, certificationDeclarationSpan,
133 : attestationNonceSpan, timestampDeconstructed, firmwareInfoSpan,
134 : vendorReserved) == CHIP_NO_ERROR,
135 : attestationError = AttestationVerificationResult::kAttestationElementsMalformed);
136 :
137 : // Verify that Nonce matches with what we sent
138 0 : VerifyOrExit(attestationNonceSpan.data_equal(info.attestationNonceBuffer),
139 : attestationError = AttestationVerificationResult::kAttestationNonceMismatch);
140 :
141 0 : ChipLogProgress(Support,
142 : "PartialDACVerifier::VerifyAttestationInformation skipping CD signature check - LocalCSAStore disabled");
143 0 : VerifyOrExit(CMS_ExtractCDContent(certificationDeclarationSpan, certificationDeclarationPayload) == CHIP_NO_ERROR,
144 : attestationError = AttestationVerificationResult::kPaaFormatInvalid);
145 :
146 0 : attestationError = ValidateCertificateDeclarationPayload(certificationDeclarationPayload, firmwareInfoSpan, deviceInfo);
147 0 : VerifyOrExit(attestationError == AttestationVerificationResult::kSuccess, attestationError = attestationError);
148 : }
149 :
150 0 : exit:
151 0 : onCompletion->mCall(onCompletion->mContext, info, attestationError);
152 0 : }
153 :
154 : } // namespace Credentials
155 : } // namespace chip
|