Skip to content

Commit

Permalink
Move VerifySignature out of ChipCertificateSet as VerifyCertSignature…
Browse files Browse the repository at this point in the history
…() (#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.
  • Loading branch information
ksperling-apple authored Oct 26, 2023
1 parent f0b5c68 commit 9b07f01
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 21 deletions.
31 changes: 18 additions & 13 deletions src/credentials/CHIPCert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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<uint8_t>(depth + 1), &caCert);
Expand All @@ -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:
Expand Down Expand Up @@ -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)
Expand Down
15 changes: 15 additions & 0 deletions src/credentials/CHIPCert.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 1 addition & 8 deletions src/credentials/CHIPCertificateSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down

0 comments on commit 9b07f01

Please sign in to comment.