Skip to content

Commit

Permalink
Implemented ExtractSubjectFromX509Cert() and ExtractIssuerFromX509Cer…
Browse files Browse the repository at this point in the history
…t() Helper Function (#26588)
  • Loading branch information
emargolis authored and pull[bot] committed Nov 23, 2023
1 parent dff1c27 commit 2646913
Show file tree
Hide file tree
Showing 8 changed files with 377 additions and 76 deletions.
27 changes: 19 additions & 8 deletions src/crypto/CHIPCryptoPAL.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,15 @@ namespace Crypto {

constexpr size_t kMax_x509_Certificate_Length = 600;

constexpr size_t kP256_FE_Length = 32;
constexpr size_t kP256_ECDSA_Signature_Length_Raw = (2 * kP256_FE_Length);
constexpr size_t kP256_Point_Length = (2 * kP256_FE_Length + 1);
constexpr size_t kSHA256_Hash_Length = 32;
constexpr size_t kSHA1_Hash_Length = 20;
constexpr size_t kSubjectKeyIdentifierLength = kSHA1_Hash_Length;
constexpr size_t kAuthorityKeyIdentifierLength = kSHA1_Hash_Length;
constexpr size_t kMaxCertificateSerialNumberLength = 20;
constexpr size_t kP256_FE_Length = 32;
constexpr size_t kP256_ECDSA_Signature_Length_Raw = (2 * kP256_FE_Length);
constexpr size_t kP256_Point_Length = (2 * kP256_FE_Length + 1);
constexpr size_t kSHA256_Hash_Length = 32;
constexpr size_t kSHA1_Hash_Length = 20;
constexpr size_t kSubjectKeyIdentifierLength = kSHA1_Hash_Length;
constexpr size_t kAuthorityKeyIdentifierLength = kSHA1_Hash_Length;
constexpr size_t kMaxCertificateSerialNumberLength = 20;
constexpr size_t kMaxCertificateDistinguishedNameLength = 200;

constexpr size_t CHIP_CRYPTO_GROUP_SIZE_BYTES = kP256_FE_Length;
constexpr size_t CHIP_CRYPTO_PUBLIC_KEY_SIZE_BYTES = kP256_Point_Length;
Expand Down Expand Up @@ -1572,6 +1573,16 @@ CHIP_ERROR ExtractAKIDFromX509Cert(const ByteSpan & certificate, MutableByteSpan
**/
CHIP_ERROR ExtractSerialNumberFromX509Cert(const ByteSpan & certificate, MutableByteSpan & serialNumber);

/**
* @brief Extracts Subject Distinguished Name from X509 Certificate. The value is copied into buffer in a raw ASN.1 X.509 format.
**/
CHIP_ERROR ExtractSubjectFromX509Cert(const ByteSpan & certificate, MutableByteSpan & subject);

/**
* @brief Extracts Issuer Distinguished Name from X509 Certificate. The value is copied into buffer in a raw ASN.1 X.509 format.
**/
CHIP_ERROR ExtractIssuerFromX509Cert(const ByteSpan & certificate, MutableByteSpan & issuer);

/**
* @brief Checks for resigned version of the certificate in the list and returns it.
*
Expand Down
51 changes: 51 additions & 0 deletions src/crypto/CHIPCryptoPALOpenSSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2001,6 +2001,57 @@ CHIP_ERROR ExtractSerialNumberFromX509Cert(const ByteSpan & certificate, Mutable
return err;
}

namespace {
CHIP_ERROR ExtractRawDNFromX509Cert(bool extractSubject, const ByteSpan & certificate, MutableByteSpan & dn)
{
CHIP_ERROR err = CHIP_NO_ERROR;
int result = 1;
X509 * x509certificate = nullptr;
auto * pCertificate = Uint8::to_const_uchar(certificate.data());
const unsigned char ** ppCertificate = &pCertificate;
X509_NAME * distinguishedName = nullptr;
const uint8_t * pDistinguishedName = nullptr;
size_t distinguishedNameLen = 0;

VerifyOrReturnError(!certificate.empty() && CanCastTo<long>(certificate.size()), CHIP_ERROR_INVALID_ARGUMENT);

x509certificate = d2i_X509(nullptr, ppCertificate, static_cast<long>(certificate.size()));
VerifyOrExit(x509certificate != nullptr, err = CHIP_ERROR_NO_MEMORY);

if (extractSubject)
{
distinguishedName = X509_get_subject_name(x509certificate);
}
else
{
distinguishedName = X509_get_issuer_name(x509certificate);
}
VerifyOrExit(distinguishedName != nullptr, err = CHIP_ERROR_INTERNAL);

result = X509_NAME_get0_der(distinguishedName, &pDistinguishedName, &distinguishedNameLen);
VerifyOrExit(result == 1, err = CHIP_ERROR_INTERNAL);
VerifyOrExit(distinguishedNameLen <= dn.size(), err = CHIP_ERROR_BUFFER_TOO_SMALL);

memcpy(dn.data(), pDistinguishedName, distinguishedNameLen);
dn.reduce_size(distinguishedNameLen);

exit:
X509_free(x509certificate);

return err;
}
} // namespace

CHIP_ERROR ExtractSubjectFromX509Cert(const ByteSpan & certificate, MutableByteSpan & subject)
{
return ExtractRawDNFromX509Cert(true, certificate, subject);
}

CHIP_ERROR ExtractIssuerFromX509Cert(const ByteSpan & certificate, MutableByteSpan & issuer)
{
return ExtractRawDNFromX509Cert(false, certificate, issuer);
}

CHIP_ERROR ExtractVIDPIDFromX509Cert(const ByteSpan & certificate, AttestationCertVidPid & vidpid)
{
ASN1_OBJECT * commonNameObj = OBJ_txt2obj("2.5.4.3", 1);
Expand Down
52 changes: 36 additions & 16 deletions src/crypto/CHIPCryptoPALPSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1742,10 +1742,9 @@ CHIP_ERROR ExtractVIDPIDFromX509Cert(const ByteSpan & certificate, AttestationCe
}

namespace {

#if defined(MBEDTLS_X509_CRT_PARSE_C)
CHIP_ERROR ExtractRawSubjectFromX509Cert(const ByteSpan & certificate, MutableByteSpan & subject)
CHIP_ERROR ExtractRawDNFromX509Cert(bool extractSubject, const ByteSpan & certificate, MutableByteSpan & dn)
{
#if defined(MBEDTLS_X509_CRT_PARSE_C)
CHIP_ERROR error = CHIP_NO_ERROR;
int result = 0;
uint8_t * p = nullptr;
Expand All @@ -1758,29 +1757,50 @@ CHIP_ERROR ExtractRawSubjectFromX509Cert(const ByteSpan & certificate, MutableBy
result = mbedtls_x509_crt_parse(&mbedCertificate, Uint8::to_const_uchar(certificate.data()), certificate.size());
VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);

len = mbedCertificate.CHIP_CRYPTO_PAL_PRIVATE_X509(subject_raw).CHIP_CRYPTO_PAL_PRIVATE_X509(len);
p = mbedCertificate.CHIP_CRYPTO_PAL_PRIVATE_X509(subject_raw).CHIP_CRYPTO_PAL_PRIVATE_X509(p);
if (extractSubject)
{
len = mbedCertificate.CHIP_CRYPTO_PAL_PRIVATE_X509(subject_raw).CHIP_CRYPTO_PAL_PRIVATE_X509(len);
p = mbedCertificate.CHIP_CRYPTO_PAL_PRIVATE_X509(subject_raw).CHIP_CRYPTO_PAL_PRIVATE_X509(p);
}
else
{
len = mbedCertificate.CHIP_CRYPTO_PAL_PRIVATE_X509(issuer_raw).CHIP_CRYPTO_PAL_PRIVATE_X509(len);
p = mbedCertificate.CHIP_CRYPTO_PAL_PRIVATE_X509(issuer_raw).CHIP_CRYPTO_PAL_PRIVATE_X509(p);
}

VerifyOrExit(len <= subject.size(), error = CHIP_ERROR_BUFFER_TOO_SMALL);
memcpy(subject.data(), p, len);
subject.reduce_size(len);
VerifyOrExit(len <= dn.size(), error = CHIP_ERROR_BUFFER_TOO_SMALL);
memcpy(dn.data(), p, len);
dn.reduce_size(len);

exit:
logMbedTLSError(result);
_log_mbedTLS_error(result);
mbedtls_x509_crt_free(&mbedCertificate);

return error;
}
#else
(void) certificate;
(void) dn;
CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED;
#endif // defined(MBEDTLS_X509_CRT_PARSE_C)

return error;
}
} // namespace

CHIP_ERROR ExtractSubjectFromX509Cert(const ByteSpan & certificate, MutableByteSpan & subject)
{
return ExtractRawDNFromX509Cert(true, certificate, subject);
}

CHIP_ERROR ExtractIssuerFromX509Cert(const ByteSpan & certificate, MutableByteSpan & issuer)
{
return ExtractRawDNFromX509Cert(false, certificate, issuer);
}

CHIP_ERROR ReplaceCertIfResignedCertFound(const ByteSpan & referenceCertificate, const ByteSpan * candidateCertificates,
size_t candidateCertificatesCount, ByteSpan & outCertificate)
{
#if defined(MBEDTLS_X509_CRT_PARSE_C)
constexpr size_t kMaxCertificateSubjectLength = 150;
uint8_t referenceSubjectBuf[kMaxCertificateSubjectLength];
uint8_t referenceSubjectBuf[kMaxCertificateDistinguishedNameLength];
uint8_t referenceSKIDBuf[kSubjectKeyIdentifierLength];
MutableByteSpan referenceSubject(referenceSubjectBuf);
MutableByteSpan referenceSKID(referenceSKIDBuf);
Expand All @@ -1789,18 +1809,18 @@ CHIP_ERROR ReplaceCertIfResignedCertFound(const ByteSpan & referenceCertificate,

ReturnErrorCodeIf(candidateCertificates == nullptr || candidateCertificatesCount == 0, CHIP_NO_ERROR);

ReturnErrorOnFailure(ExtractRawSubjectFromX509Cert(referenceCertificate, referenceSubject));
ReturnErrorOnFailure(ExtractSubjectFromX509Cert(referenceCertificate, referenceSubject));
ReturnErrorOnFailure(ExtractSKIDFromX509Cert(referenceCertificate, referenceSKID));

for (size_t i = 0; i < candidateCertificatesCount; i++)
{
const ByteSpan candidateCertificate = candidateCertificates[i];
uint8_t candidateSubjectBuf[kMaxCertificateSubjectLength];
uint8_t candidateSubjectBuf[kMaxCertificateDistinguishedNameLength];
uint8_t candidateSKIDBuf[kSubjectKeyIdentifierLength];
MutableByteSpan candidateSubject(candidateSubjectBuf);
MutableByteSpan candidateSKID(candidateSKIDBuf);

ReturnErrorOnFailure(ExtractRawSubjectFromX509Cert(candidateCertificate, candidateSubject));
ReturnErrorOnFailure(ExtractSubjectFromX509Cert(candidateCertificate, candidateSubject));
ReturnErrorOnFailure(ExtractSKIDFromX509Cert(candidateCertificate, candidateSKID));

if (referenceSKID.data_equal(candidateSKID) && referenceSubject.data_equal(candidateSubject))
Expand Down
48 changes: 35 additions & 13 deletions src/crypto/CHIPCryptoPALmbedTLS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1859,9 +1859,9 @@ CHIP_ERROR ExtractVIDPIDFromX509Cert(const ByteSpan & certificate, AttestationCe
}

namespace {
#if defined(MBEDTLS_X509_CRT_PARSE_C)
CHIP_ERROR ExtractRawSubjectFromX509Cert(const ByteSpan & certificate, MutableByteSpan & subject)
CHIP_ERROR ExtractRawDNFromX509Cert(bool extractSubject, const ByteSpan & certificate, MutableByteSpan & dn)
{
#if defined(MBEDTLS_X509_CRT_PARSE_C)
CHIP_ERROR error = CHIP_NO_ERROR;
int result = 0;
uint8_t * p = nullptr;
Expand All @@ -1874,28 +1874,50 @@ CHIP_ERROR ExtractRawSubjectFromX509Cert(const ByteSpan & certificate, MutableBy
result = mbedtls_x509_crt_parse(&mbedCertificate, Uint8::to_const_uchar(certificate.data()), certificate.size());
VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);

len = mbedCertificate.CHIP_CRYPTO_PAL_PRIVATE_X509(subject_raw).CHIP_CRYPTO_PAL_PRIVATE_X509(len);
p = mbedCertificate.CHIP_CRYPTO_PAL_PRIVATE_X509(subject_raw).CHIP_CRYPTO_PAL_PRIVATE_X509(p);
if (extractSubject)
{
len = mbedCertificate.CHIP_CRYPTO_PAL_PRIVATE_X509(subject_raw).CHIP_CRYPTO_PAL_PRIVATE_X509(len);
p = mbedCertificate.CHIP_CRYPTO_PAL_PRIVATE_X509(subject_raw).CHIP_CRYPTO_PAL_PRIVATE_X509(p);
}
else
{
len = mbedCertificate.CHIP_CRYPTO_PAL_PRIVATE_X509(issuer_raw).CHIP_CRYPTO_PAL_PRIVATE_X509(len);
p = mbedCertificate.CHIP_CRYPTO_PAL_PRIVATE_X509(issuer_raw).CHIP_CRYPTO_PAL_PRIVATE_X509(p);
}

VerifyOrExit(len <= subject.size(), error = CHIP_ERROR_BUFFER_TOO_SMALL);
memcpy(subject.data(), p, len);
subject.reduce_size(len);
VerifyOrExit(len <= dn.size(), error = CHIP_ERROR_BUFFER_TOO_SMALL);
memcpy(dn.data(), p, len);
dn.reduce_size(len);

exit:
_log_mbedTLS_error(result);
mbedtls_x509_crt_free(&mbedCertificate);

#else
(void) certificate;
(void) dn;
CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED;
#endif // defined(MBEDTLS_X509_CRT_PARSE_C)

return error;
}
#endif // defined(MBEDTLS_X509_CRT_PARSE_C)
} // namespace

CHIP_ERROR ExtractSubjectFromX509Cert(const ByteSpan & certificate, MutableByteSpan & subject)
{
return ExtractRawDNFromX509Cert(true, certificate, subject);
}

CHIP_ERROR ExtractIssuerFromX509Cert(const ByteSpan & certificate, MutableByteSpan & issuer)
{
return ExtractRawDNFromX509Cert(false, certificate, issuer);
}

CHIP_ERROR ReplaceCertIfResignedCertFound(const ByteSpan & referenceCertificate, const ByteSpan * candidateCertificates,
size_t candidateCertificatesCount, ByteSpan & outCertificate)
{
#if defined(MBEDTLS_X509_CRT_PARSE_C)
constexpr size_t kMaxCertificateSubjectLength = 150;
uint8_t referenceSubjectBuf[kMaxCertificateSubjectLength];
uint8_t referenceSubjectBuf[kMaxCertificateDistinguishedNameLength];
uint8_t referenceSKIDBuf[kSubjectKeyIdentifierLength];
MutableByteSpan referenceSubject(referenceSubjectBuf);
MutableByteSpan referenceSKID(referenceSKIDBuf);
Expand All @@ -1904,18 +1926,18 @@ CHIP_ERROR ReplaceCertIfResignedCertFound(const ByteSpan & referenceCertificate,

ReturnErrorCodeIf(candidateCertificates == nullptr || candidateCertificatesCount == 0, CHIP_NO_ERROR);

ReturnErrorOnFailure(ExtractRawSubjectFromX509Cert(referenceCertificate, referenceSubject));
ReturnErrorOnFailure(ExtractSubjectFromX509Cert(referenceCertificate, referenceSubject));
ReturnErrorOnFailure(ExtractSKIDFromX509Cert(referenceCertificate, referenceSKID));

for (size_t i = 0; i < candidateCertificatesCount; i++)
{
const ByteSpan candidateCertificate = candidateCertificates[i];
uint8_t candidateSubjectBuf[kMaxCertificateSubjectLength];
uint8_t candidateSubjectBuf[kMaxCertificateDistinguishedNameLength];
uint8_t candidateSKIDBuf[kSubjectKeyIdentifierLength];
MutableByteSpan candidateSubject(candidateSubjectBuf);
MutableByteSpan candidateSKID(candidateSKIDBuf);

ReturnErrorOnFailure(ExtractRawSubjectFromX509Cert(candidateCertificate, candidateSubject));
ReturnErrorOnFailure(ExtractSubjectFromX509Cert(candidateCertificate, candidateSubject));
ReturnErrorOnFailure(ExtractSKIDFromX509Cert(candidateCertificate, candidateSKID));

if (referenceSKID.data_equal(candidateSKID) && referenceSubject.data_equal(candidateSubject))
Expand Down
Loading

0 comments on commit 2646913

Please sign in to comment.