Matter SDK Coverage Report
Current view: top level - credentials/attestation_verifier - DeviceAttestationVerifier.cpp (source / functions) Coverage Total Hit
Test: SHA:5853f10e345717417494f970a7d13b422d94af51 Lines: 18.5 % 130 24
Test Date: 2025-06-30 07:09:23 Functions: 45.5 % 11 5

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2021 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 "DeviceAttestationVerifier.h"
      18              : 
      19              : #include <credentials/DeviceAttestationConstructor.h>
      20              : #include <crypto/CHIPCryptoPAL.h>
      21              : #include <lib/support/CHIPMem.h>
      22              : 
      23              : using namespace chip::Crypto;
      24              : 
      25              : namespace chip {
      26              : namespace Credentials {
      27              : 
      28              : namespace {
      29              : 
      30              : // Version to have a default placeholder so the getter never
      31              : // returns `nullptr` by default.
      32              : class UnimplementedDACVerifier : public DeviceAttestationVerifier
      33              : {
      34              : public:
      35            0 :     void VerifyAttestationInformation(const AttestationInfo & info,
      36              :                                       Callback::Callback<OnAttestationInformationVerification> * onCompletion) override
      37              :     {
      38              :         (void) info;
      39              :         (void) onCompletion;
      40            0 :     }
      41              : 
      42            1 :     AttestationVerificationResult ValidateCertificationDeclarationSignature(const ByteSpan & cmsEnvelopeBuffer,
      43              :                                                                             ByteSpan & certDeclBuffer) override
      44              :     {
      45              :         (void) cmsEnvelopeBuffer;
      46              :         (void) certDeclBuffer;
      47            1 :         return AttestationVerificationResult::kNotImplemented;
      48              :     }
      49              : 
      50            0 :     AttestationVerificationResult ValidateCertificateDeclarationPayload(const ByteSpan & certDeclBuffer,
      51              :                                                                         const ByteSpan & firmwareInfo,
      52              :                                                                         const DeviceInfoForAttestation & deviceInfo) override
      53              :     {
      54              :         (void) certDeclBuffer;
      55              :         (void) firmwareInfo;
      56              :         (void) deviceInfo;
      57            0 :         return AttestationVerificationResult::kNotImplemented;
      58              :     }
      59              : 
      60            0 :     CHIP_ERROR VerifyNodeOperationalCSRInformation(const ByteSpan & nocsrElementsBuffer,
      61              :                                                    const ByteSpan & attestationChallengeBuffer,
      62              :                                                    const ByteSpan & attestationSignatureBuffer,
      63              :                                                    const Crypto::P256PublicKey & dacPublicKey, const ByteSpan & csrNonce) override
      64              :     {
      65              :         (void) nocsrElementsBuffer;
      66              :         (void) attestationChallengeBuffer;
      67              :         (void) attestationSignatureBuffer;
      68              :         (void) dacPublicKey;
      69              :         (void) csrNonce;
      70            0 :         return CHIP_ERROR_NOT_IMPLEMENTED;
      71              :     }
      72              : 
      73            0 :     void CheckForRevokedDACChain(const AttestationInfo & info,
      74              :                                  Callback::Callback<OnAttestationInformationVerification> * onCompletion) override
      75              :     {
      76              :         (void) info;
      77              :         (void) onCompletion;
      78            0 :         VerifyOrDie(false);
      79              :     }
      80              : };
      81              : 
      82              : // Default to avoid nullptr on getter and cleanly handle new products/clients before
      83              : // they provide their own.
      84              : UnimplementedDACVerifier gDefaultDACVerifier;
      85              : 
      86              : DeviceAttestationVerifier * gDacVerifier = &gDefaultDACVerifier;
      87              : 
      88              : } // namespace
      89              : 
      90            3 : const char * GetAttestationResultDescription(AttestationVerificationResult resultCode)
      91              : {
      92            3 :     switch (resultCode)
      93              :     {
      94            1 :     case AttestationVerificationResult::kSuccess:
      95            1 :         return "Success";
      96            0 :     case AttestationVerificationResult::kPaaUntrusted:
      97            0 :         return "PAA is untrusted (OBSOLETE: consider using a different error)";
      98            0 :     case AttestationVerificationResult::kPaaNotFound:
      99            0 :         return "PAA not found in DCL and/or local PAA trust store";
     100            0 :     case AttestationVerificationResult::kPaaExpired:
     101            0 :         return "PAA is expired";
     102            0 :     case AttestationVerificationResult::kPaaSignatureInvalid:
     103            0 :         return "PAA signature is invalid";
     104            0 :     case AttestationVerificationResult::kPaaRevoked:
     105            0 :         return "PAA is revoked (consider removing from DCL or PAA trust store!)";
     106            0 :     case AttestationVerificationResult::kPaaFormatInvalid:
     107            0 :         return "PAA format is invalid";
     108            0 :     case AttestationVerificationResult::kPaaArgumentInvalid:
     109            0 :         return "PAA argument is invalid in some way according to X.509 backend";
     110            0 :     case AttestationVerificationResult::kPaiExpired:
     111            0 :         return "PAI is expired";
     112            0 :     case AttestationVerificationResult::kPaiSignatureInvalid:
     113            0 :         return "PAI signature is invalid";
     114            0 :     case AttestationVerificationResult::kPaiRevoked:
     115            0 :         return "PAI is revoked";
     116            0 :     case AttestationVerificationResult::kPaiFormatInvalid:
     117            0 :         return "PAI format is invalid";
     118            0 :     case AttestationVerificationResult::kPaiArgumentInvalid:
     119            0 :         return "PAI argument is invalid in some way according to X.509 backend";
     120            0 :     case AttestationVerificationResult::kPaiVendorIdMismatch:
     121            0 :         return "PAI vendor ID mismatch (did not match VID present in PAA)";
     122            0 :     case AttestationVerificationResult::kPaiAuthorityNotFound:
     123            0 :         return "PAI authority not found (OBSOLETE: consider using a different error)";
     124            0 :     case AttestationVerificationResult::kPaiMissing:
     125            0 :         return "PAI is missing/empty from attestation information data";
     126            1 :     case AttestationVerificationResult::kPaiAndDacRevoked:
     127            1 :         return "Both PAI and DAC are revoked";
     128            0 :     case AttestationVerificationResult::kDacExpired:
     129            0 :         return "DAC is expired";
     130            0 :     case AttestationVerificationResult::kDacSignatureInvalid:
     131            0 :         return "DAC signature is invalid";
     132            0 :     case AttestationVerificationResult::kDacRevoked:
     133            0 :         return "DAC is revoked";
     134            0 :     case AttestationVerificationResult::kDacFormatInvalid:
     135            0 :         return "DAC format is invalid";
     136            0 :     case AttestationVerificationResult::kDacArgumentInvalid:
     137            0 :         return "DAC is invalid in some way according to X.509 backend";
     138            0 :     case AttestationVerificationResult::kDacVendorIdMismatch:
     139            0 :         return "DAC vendor ID mismatch (either between DAC and PAI, or between DAC and Basic Information cluster)";
     140            0 :     case AttestationVerificationResult::kDacProductIdMismatch:
     141            0 :         return "DAC product ID mismatch (either between DAC and PAI, or between DAC and Basic Information cluster)";
     142            0 :     case AttestationVerificationResult::kDacAuthorityNotFound:
     143            0 :         return "DAC authority not found (OBSOLETE: consider using a different error)";
     144            0 :     case AttestationVerificationResult::kFirmwareInformationMismatch:
     145            0 :         return "Firmware information mismatch";
     146            0 :     case AttestationVerificationResult::kFirmwareInformationMissing:
     147            0 :         return "Firmware information missing";
     148            0 :     case AttestationVerificationResult::kAttestationSignatureInvalid:
     149            0 :         return "Attestation signature failed to validate against DAC subject public key";
     150            0 :     case AttestationVerificationResult::kAttestationElementsMalformed:
     151            0 :         return "Attestation elements payload is malformed";
     152            0 :     case AttestationVerificationResult::kAttestationNonceMismatch:
     153            0 :         return "Attestation nonce does not match the one from Attestation Request";
     154            0 :     case AttestationVerificationResult::kAttestationSignatureInvalidFormat:
     155            0 :         return "Attestation signature format is invalid (likely wrong signature algorithm in certificate)";
     156            0 :     case AttestationVerificationResult::kCertificationDeclarationNoKeyId:
     157            0 :         return "Certification declaration missing the required key ID in CMS envelope";
     158            0 :     case AttestationVerificationResult::kCertificationDeclarationNoCertificateFound:
     159            0 :         return "Could not find matching trusted verification certificate for the certification declaration's key ID";
     160            0 :     case AttestationVerificationResult::kCertificationDeclarationInvalidSignature:
     161            0 :         return "Certification declaration signature failed to validate against the verification certificate";
     162            0 :     case AttestationVerificationResult::kCertificationDeclarationInvalidFormat:
     163            0 :         return "Certification declaration format is invalid";
     164            0 :     case AttestationVerificationResult::kCertificationDeclarationInvalidVendorId:
     165            0 :         return "Certification declaration vendor ID failed to cross-reference with DAC and/or PAI and/or Basic Information cluster";
     166            0 :     case AttestationVerificationResult::kCertificationDeclarationInvalidProductId:
     167              :         return "Certification declaration product ID failed to cross-reference with DAC and/or PAI and/or Basic Information "
     168            0 :                "cluster";
     169            0 :     case AttestationVerificationResult::kCertificationDeclarationInvalidPAA:
     170            0 :         return "Certification declaration required a fixed allowed PAA which does not match the final PAA found";
     171            0 :     case AttestationVerificationResult::kNoMemory:
     172            0 :         return "Failed to allocate memory to process attestation verification";
     173            0 :     case AttestationVerificationResult::kInvalidArgument:
     174              :         return "Some unexpected invalid argument was provided internally to the device attestation procedure (likely malformed "
     175            0 :                "input data from candidate device)";
     176            0 :     case AttestationVerificationResult::kInternalError:
     177              :         return "An internal error arose in the device attestation procedure (likely malformed input data from candidate "
     178            0 :                "device)";
     179            0 :     case AttestationVerificationResult::kNotImplemented:
     180            0 :         return "Reached a critical-but-unimplemented part of the device attestation procedure!";
     181              :     }
     182              : 
     183            1 :     return "<AttestationVerificationResult does not have a description!>";
     184              : }
     185              : 
     186           95 : CHIP_ERROR DeviceAttestationVerifier::ValidateAttestationSignature(const P256PublicKey & pubkey,
     187              :                                                                    const ByteSpan & attestationElements,
     188              :                                                                    const ByteSpan & attestationChallenge,
     189              :                                                                    const P256ECDSASignature & signature)
     190              : {
     191           95 :     Hash_SHA256_stream hashStream;
     192              :     uint8_t md[kSHA256_Hash_Length];
     193           95 :     MutableByteSpan messageDigestSpan(md);
     194              : 
     195           95 :     ReturnErrorOnFailure(hashStream.Begin());
     196           95 :     ReturnErrorOnFailure(hashStream.AddData(attestationElements));
     197           95 :     ReturnErrorOnFailure(hashStream.AddData(attestationChallenge));
     198           95 :     ReturnErrorOnFailure(hashStream.Finish(messageDigestSpan));
     199              : 
     200           95 :     ReturnErrorOnFailure(pubkey.ECDSA_validate_hash_signature(messageDigestSpan.data(), messageDigestSpan.size(), signature));
     201              : 
     202           94 :     return CHIP_NO_ERROR;
     203           95 : }
     204              : 
     205            3 : DeviceAttestationVerifier * GetDeviceAttestationVerifier()
     206              : {
     207            3 :     return gDacVerifier;
     208              : }
     209              : 
     210            2 : void SetDeviceAttestationVerifier(DeviceAttestationVerifier * verifier)
     211              : {
     212            2 :     if (verifier == nullptr)
     213              :     {
     214            0 :         return;
     215              :     }
     216              : 
     217            2 :     gDacVerifier = verifier;
     218              : }
     219              : 
     220            0 : static inline Platform::ScopedMemoryBufferWithSize<uint8_t> CopyByteSpanHelper(const ByteSpan & span_to_copy)
     221              : {
     222            0 :     Platform::ScopedMemoryBufferWithSize<uint8_t> bufferCopy;
     223            0 :     if (bufferCopy.Alloc(span_to_copy.size()))
     224              :     {
     225            0 :         memcpy(bufferCopy.Get(), span_to_copy.data(), span_to_copy.size());
     226              :     }
     227            0 :     return bufferCopy;
     228              : }
     229              : 
     230            0 : DeviceAttestationVerifier::AttestationDeviceInfo::AttestationDeviceInfo(const AttestationInfo & attestationInfo) :
     231            0 :     mPaiDerBuffer(CopyByteSpanHelper(attestationInfo.paiDerBuffer)),
     232            0 :     mDacDerBuffer(CopyByteSpanHelper(attestationInfo.dacDerBuffer)), mBasicInformationVendorId(attestationInfo.vendorId),
     233            0 :     mBasicInformationProductId(attestationInfo.productId)
     234              : {
     235            0 :     ByteSpan certificationDeclarationSpan;
     236            0 :     ByteSpan attestationNonceSpan;
     237              :     uint32_t timestampDeconstructed;
     238            0 :     ByteSpan firmwareInfoSpan;
     239            0 :     DeviceAttestationVendorReservedDeconstructor vendorReserved;
     240              : 
     241            0 :     if (DeconstructAttestationElements(attestationInfo.attestationElementsBuffer, certificationDeclarationSpan,
     242              :                                        attestationNonceSpan, timestampDeconstructed, firmwareInfoSpan,
     243            0 :                                        vendorReserved) == CHIP_NO_ERROR)
     244              :     {
     245            0 :         mCdBuffer = CopyByteSpanHelper(certificationDeclarationSpan);
     246              :     }
     247            0 : }
     248              : 
     249              : } // namespace Credentials
     250              : } // namespace chip
        

Generated by: LCOV version 2.0-1