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