From 10350439d1f0aa09d45ac0edf1dd89b74957b585 Mon Sep 17 00:00:00 2001 From: Karsten Sperling <113487422+ksperling-apple@users.noreply.github.com> Date: Fri, 27 Oct 2023 06:46:20 +1300 Subject: [PATCH] Move VerifySignature out of ChipCertificateSet as VerifyCertSignature() (#30012) It just operates on ChipCertificateData structs directly and is useful outside of ChipCertificateSet. Also move the check for kTBSHashPresent and the signature algorithm into the function. --- src/credentials/CHIPCert.cpp | 31 ++++++++++++++++------------ src/credentials/CHIPCert.h | 15 ++++++++++++++ src/credentials/CHIPCertificateSet.h | 9 +------- 3 files changed, 34 insertions(+), 21 deletions(-) diff --git a/src/credentials/CHIPCert.cpp b/src/credentials/CHIPCert.cpp index 32b66c45e8e9e6..8a651e78b7b21b 100644 --- a/src/credentials/CHIPCert.cpp +++ b/src/credentials/CHIPCert.cpp @@ -284,20 +284,29 @@ CHIP_ERROR ChipCertificateSet::FindValidCert(const ChipDN & subjectDN, const Cer CHIP_ERROR ChipCertificateSet::VerifySignature(const ChipCertificateData * cert, const ChipCertificateData * caCert) { + VerifyOrReturnError((cert != nullptr) && (caCert != nullptr), CHIP_ERROR_INVALID_ARGUMENT); + return VerifyCertSignature(*cert, *caCert); +} + +CHIP_ERROR VerifyCertSignature(const ChipCertificateData & cert, const ChipCertificateData & signer) +{ + VerifyOrReturnError(cert.mCertFlags.Has(CertFlags::kTBSHashPresent), CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(cert.mSigAlgoOID == kOID_SigAlgo_ECDSAWithSHA256, CHIP_ERROR_UNSUPPORTED_SIGNATURE_TYPE); + #ifdef ENABLE_HSM_ECDSA_VERIFY - P256PublicKeyHSM caPublicKey; + P256PublicKeyHSM signerPublicKey; #else - P256PublicKey caPublicKey; + P256PublicKey signerPublicKey; #endif P256ECDSASignature signature; - VerifyOrReturnError((cert != nullptr) && (caCert != nullptr), CHIP_ERROR_INVALID_ARGUMENT); - ReturnErrorOnFailure(signature.SetLength(cert->mSignature.size())); - memcpy(signature.Bytes(), cert->mSignature.data(), cert->mSignature.size()); + ReturnErrorOnFailure(signature.SetLength(cert.mSignature.size())); + memcpy(signature.Bytes(), cert.mSignature.data(), cert.mSignature.size()); - memcpy(caPublicKey, caCert->mPublicKey.data(), caCert->mPublicKey.size()); + memcpy(signerPublicKey, signer.mPublicKey.data(), signer.mPublicKey.size()); - ReturnErrorOnFailure(caPublicKey.ECDSA_validate_hash_signature(cert->mTBSHash, chip::Crypto::kSHA256_Hash_Length, signature)); + ReturnErrorOnFailure( + signerPublicKey.ECDSA_validate_hash_signature(cert.mTBSHash, chip::Crypto::kSHA256_Hash_Length, signature)); return CHIP_NO_ERROR; } @@ -454,10 +463,6 @@ CHIP_ERROR ChipCertificateSet::ValidateCert(const ChipCertificateData * cert, Va // recursion in such a case. VerifyOrExit(depth < mCertCount, err = CHIP_ERROR_CERT_PATH_TOO_LONG); - // Verify that a hash of the 'to-be-signed' portion of the certificate has been computed. We will need this to - // verify the cert's signature below. - VerifyOrExit(cert->mCertFlags.Has(CertFlags::kTBSHashPresent), err = CHIP_ERROR_INVALID_ARGUMENT); - // Search for a valid CA certificate that matches the Issuer DN and Authority Key Id of the current certificate. // Fail if no acceptable certificate is found. err = FindValidCert(cert->mIssuerDN, cert->mAuthKeyId, context, static_cast(depth + 1), &caCert); @@ -468,7 +473,7 @@ CHIP_ERROR ChipCertificateSet::ValidateCert(const ChipCertificateData * cert, Va // Verify signature of the current certificate against public key of the CA certificate. If signature verification // succeeds, the current certificate is valid. - err = VerifySignature(cert, caCert); + err = VerifyCertSignature(*cert, *caCert); SuccessOrExit(err); exit: @@ -1166,7 +1171,7 @@ CHIP_ERROR ValidateChipRCAC(const ByteSpan & rcac) VerifyOrReturnError(certData.mKeyUsageFlags.Has(KeyUsageFlags::kKeyCertSign), CHIP_ERROR_CERT_USAGE_NOT_ALLOWED); - return ChipCertificateSet::VerifySignature(&certData, &certData); + return VerifyCertSignature(certData, certData); } CHIP_ERROR ConvertIntegerDERToRaw(ByteSpan derInt, uint8_t * rawInt, const uint16_t rawIntLen) diff --git a/src/credentials/CHIPCert.h b/src/credentials/CHIPCert.h index f0b78df9ea2ec7..caa47babae7375 100644 --- a/src/credentials/CHIPCert.h +++ b/src/credentials/CHIPCert.h @@ -504,6 +504,21 @@ CHIP_ERROR ConvertX509CertToChipCert(const ByteSpan x509Cert, MutableByteSpan & **/ CHIP_ERROR ConvertChipCertToX509Cert(const ByteSpan chipCert, MutableByteSpan & x509Cert); +/** + * @brief Verifies the signature of a certificate. + * + * @param cert The certificate to be verified. + * @param signer The certificate containing the public key used to verify the signature. + * + * @return Returns a CHIP_ERROR on validation or other error, CHIP_NO_ERROR otherwise + * + * The certificate to be verified must have been decoded with TBS hash calculation enabled. + * + * Note that this function performs ONLY signature verification. No Subject and Issuer DN + * comparison, Key Usage extension checks or similar validation is performed. + **/ +CHIP_ERROR VerifyCertSignature(const ChipCertificateData & cert, const ChipCertificateData & signer); + /** * Validate CHIP Root CA Certificate (RCAC) in ByteSpan TLV-encoded form. * This function performs RCAC parsing, checks SubjectDN validity, verifies that SubjectDN diff --git a/src/credentials/CHIPCertificateSet.h b/src/credentials/CHIPCertificateSet.h index 3c119a6c2ae718..cb53622720b56d 100644 --- a/src/credentials/CHIPCertificateSet.h +++ b/src/credentials/CHIPCertificateSet.h @@ -246,14 +246,7 @@ class DLL_EXPORT ChipCertificateSet CHIP_ERROR FindValidCert(const ChipDN & subjectDN, const CertificateKeyId & subjectKeyId, ValidationContext & context, const ChipCertificateData ** certData); - /** - * @brief Verify CHIP certificate signature. - * - * @param cert Pointer to the CHIP certificate which signature should be validated. - * @param caCert Pointer to the CA certificate of the verified certificate. - * - * @return Returns a CHIP_ERROR on validation or other error, CHIP_NO_ERROR otherwise - **/ + // Deprecated, use the equivalent free function VerifyCertSignature() static CHIP_ERROR VerifySignature(const ChipCertificateData * cert, const ChipCertificateData * caCert); private: