Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented ExtractSerialNumberFromX509Cert() Method #26485

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 14 additions & 8 deletions src/crypto/CHIPCryptoPAL.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
*
* Copyright (c) 2020-2022 Project CHIP Authors
* Copyright (c) 2020-2023 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -43,13 +43,14 @@ 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 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 CHIP_CRYPTO_GROUP_SIZE_BYTES = kP256_FE_Length;
constexpr size_t CHIP_CRYPTO_PUBLIC_KEY_SIZE_BYTES = kP256_Point_Length;
Expand Down Expand Up @@ -1566,6 +1567,11 @@ CHIP_ERROR ExtractSKIDFromX509Cert(const ByteSpan & certificate, MutableByteSpan
**/
CHIP_ERROR ExtractAKIDFromX509Cert(const ByteSpan & certificate, MutableByteSpan & akid);

/**
* @brief Extracts Serial Number from X509 Certificate.
**/
CHIP_ERROR ExtractSerialNumberFromX509Cert(const ByteSpan & certificate, MutableByteSpan & serialNumber);

/**
* @brief Checks for resigned version of the certificate in the list and returns it.
*
Expand Down
33 changes: 32 additions & 1 deletion src/crypto/CHIPCryptoPALOpenSSL.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
*
* Copyright (c) 2020-2022 Project CHIP Authors
* Copyright (c) 2020-2023 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -1970,6 +1970,37 @@ CHIP_ERROR ExtractAKIDFromX509Cert(const ByteSpan & certificate, MutableByteSpan
return ExtractKIDFromX509Cert(false, certificate, akid);
}

CHIP_ERROR ExtractSerialNumberFromX509Cert(const ByteSpan & certificate, MutableByteSpan & serialNumber)
{
CHIP_ERROR err = CHIP_NO_ERROR;
X509 * x509certificate = nullptr;
auto * pCertificate = Uint8::to_const_uchar(certificate.data());
const unsigned char ** ppCertificate = &pCertificate;
const ASN1_INTEGER * serialNumberASN1 = nullptr;
size_t serialNumberLen = 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);

serialNumberASN1 = X509_get_serialNumber(x509certificate);
VerifyOrExit(serialNumberASN1 != nullptr, err = CHIP_ERROR_INTERNAL);
VerifyOrExit(serialNumberASN1->data != nullptr, err = CHIP_ERROR_INTERNAL);
VerifyOrExit(CanCastTo<size_t>(serialNumberASN1->length), err = CHIP_ERROR_INTERNAL);

serialNumberLen = static_cast<size_t>(serialNumberASN1->length);
VerifyOrExit(serialNumberLen <= serialNumber.size(), err = CHIP_ERROR_BUFFER_TOO_SMALL);

memcpy(serialNumber.data(), serialNumberASN1->data, serialNumberLen);
serialNumber.reduce_size(serialNumberLen);

exit:
X509_free(x509certificate);

return err;
}

CHIP_ERROR ExtractVIDPIDFromX509Cert(const ByteSpan & certificate, AttestationCertVidPid & vidpid)
{
ASN1_OBJECT * commonNameObj = OBJ_txt2obj("2.5.4.3", 1);
Expand Down
36 changes: 35 additions & 1 deletion src/crypto/CHIPCryptoPALPSA.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
*
* Copyright (c) 2022 Project CHIP Authors
* Copyright (c) 2022-2023 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -1651,6 +1651,40 @@ CHIP_ERROR ExtractAKIDFromX509Cert(const ByteSpan & certificate, MutableByteSpan
return ExtractKIDFromX509Cert(false, certificate, akid);
}

CHIP_ERROR ExtractSerialNumberFromX509Cert(const ByteSpan & certificate, MutableByteSpan & serialNumber)
{
#if defined(MBEDTLS_X509_CRT_PARSE_C)
CHIP_ERROR error = CHIP_NO_ERROR;
int result = 0;
uint8_t * p = nullptr;
size_t len = 0;
mbedtls_x509_crt mbed_cert;

mbedtls_x509_crt_init(&mbed_cert);

result = mbedtls_x509_crt_parse(&mbed_cert, Uint8::to_const_uchar(certificate.data()), certificate.size());
VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);

p = mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(serial).CHIP_CRYPTO_PAL_PRIVATE_X509(p);
len = mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(serial).CHIP_CRYPTO_PAL_PRIVATE_X509(len);
VerifyOrExit(len <= serialNumber.size(), error = CHIP_ERROR_BUFFER_TOO_SMALL);

memcpy(serialNumber.data(), p, len);
serialNumber.reduce_size(len);

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

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

return error;
}

CHIP_ERROR ExtractVIDPIDFromX509Cert(const ByteSpan & certificate, AttestationCertVidPid & vidpid)
{
#if defined(MBEDTLS_X509_CRT_PARSE_C)
Expand Down
36 changes: 35 additions & 1 deletion src/crypto/CHIPCryptoPALmbedTLS.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
*
* Copyright (c) 2020-2022 Project CHIP Authors
* Copyright (c) 2020-2023 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -1768,6 +1768,40 @@ CHIP_ERROR ExtractAKIDFromX509Cert(const ByteSpan & certificate, MutableByteSpan
return ExtractKIDFromX509Cert(false, certificate, akid);
}

CHIP_ERROR ExtractSerialNumberFromX509Cert(const ByteSpan & certificate, MutableByteSpan & serialNumber)
{
#if defined(MBEDTLS_X509_CRT_PARSE_C)
CHIP_ERROR error = CHIP_NO_ERROR;
int result = 0;
uint8_t * p = nullptr;
size_t len = 0;
mbedtls_x509_crt mbed_cert;

mbedtls_x509_crt_init(&mbed_cert);

result = mbedtls_x509_crt_parse(&mbed_cert, Uint8::to_const_uchar(certificate.data()), certificate.size());
VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);

p = mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(serial).CHIP_CRYPTO_PAL_PRIVATE_X509(p);
len = mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(serial).CHIP_CRYPTO_PAL_PRIVATE_X509(len);
VerifyOrExit(len <= serialNumber.size(), error = CHIP_ERROR_BUFFER_TOO_SMALL);

memcpy(serialNumber.data(), p, len);
serialNumber.reduce_size(len);

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

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

return error;
}

CHIP_ERROR ExtractVIDPIDFromX509Cert(const ByteSpan & certificate, AttestationCertVidPid & vidpid)
{
#if defined(MBEDTLS_X509_CRT_PARSE_C)
Expand Down
44 changes: 43 additions & 1 deletion src/crypto/tests/CHIPCryptoPALTest.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
*
* Copyright (c) 2020-2022 Project CHIP Authors
* Copyright (c) 2020-2023 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -2133,6 +2133,47 @@ static void TestAKID_x509Extraction(nlTestSuite * inSuite, void * inContext)
}
}

static void TestSerialNumber_x509Extraction(nlTestSuite * inSuite, void * inContext)
{
using namespace TestCerts;

HeapChecker heapChecker(inSuite);
CHIP_ERROR err = CHIP_NO_ERROR;

struct SerialNumberTestCase
{
uint8_t Cert;
ByteSpan mExpectedResult;
};

const uint8_t serialNumberRoot01[] = { 0x53, 0x4c, 0x45, 0x82, 0x73, 0x62, 0x35, 0x14 };
const uint8_t serialNumberICA01[] = { 0x69, 0xd8, 0x6a, 0x8d, 0x80, 0xfc, 0x8f, 0x5d };
const uint8_t serialNumberNode02_08[] = { 0x3e, 0x67, 0x94, 0x70, 0x7a, 0xec, 0xb8, 0x15 };

// clang-format off
static SerialNumberTestCase sSerialNumberTestCases[] = {
// Cert Expected Output
// ====================================================
{ TestCert::kRoot01, ByteSpan(serialNumberRoot01) },
{ TestCert::kICA01, ByteSpan(serialNumberICA01) },
{ TestCert::kNode02_08, ByteSpan(serialNumberNode02_08) },
};
// clang-format on

for (auto & testCase : sSerialNumberTestCases)
{
ByteSpan cert;
err = GetTestCert(testCase.Cert, TestCertLoadFlags::kDERForm, cert);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);

uint8_t serialNumberBuf[kMaxCertificateSerialNumberLength] = { 0 };
MutableByteSpan serialNumber(serialNumberBuf);
err = ExtractSerialNumberFromX509Cert(cert, serialNumber);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, serialNumber.data_equal(testCase.mExpectedResult));
}
}

static void TestVIDPID_StringExtraction(nlTestSuite * inSuite, void * inContext)
{
HeapChecker heapChecker(inSuite);
Expand Down Expand Up @@ -2560,6 +2601,7 @@ static const nlTest sTests[] = {
NL_TEST_DEF("Test x509 Certificate Timestamp Validation", TestX509_IssuingTimestampValidation),
NL_TEST_DEF("Test Subject Key Id Extraction from x509 Certificate", TestSKID_x509Extraction),
NL_TEST_DEF("Test Authority Key Id Extraction from x509 Certificate", TestAKID_x509Extraction),
NL_TEST_DEF("Test Serial Number Extraction from x509 Certificate", TestSerialNumber_x509Extraction),
NL_TEST_DEF("Test Vendor ID and Product ID Extraction from Attribute String", TestVIDPID_StringExtraction),
NL_TEST_DEF("Test Vendor ID and Product ID Extraction from x509 Attestation Certificate", TestVIDPID_x509Extraction),
NL_TEST_DEF("Test Replace Resigned Certificate Version if Found", TestX509_ReplaceCertIfResignedCertFound),
Expand Down
36 changes: 35 additions & 1 deletion src/platform/nxp/common/crypto/CHIPCryptoPALTinyCrypt.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
*
* Copyright (c) 2020-2022 Project CHIP Authors
* Copyright (c) 2020-2023 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -1604,6 +1604,40 @@ CHIP_ERROR ExtractAKIDFromX509Cert(const ByteSpan & certificate, MutableByteSpan
return ExtractKIDFromX509Cert(false, certificate, akid);
}

CHIP_ERROR ExtractSerialNumberFromX509Cert(const ByteSpan & certificate, MutableByteSpan & serialNumber)
{
#if defined(MBEDTLS_X509_CRT_PARSE_C)
CHIP_ERROR error = CHIP_NO_ERROR;
int result = 0;
uint8_t * p = nullptr;
size_t len = 0;
mbedtls_x509_crt mbed_cert;

mbedtls_x509_crt_init(&mbed_cert);

result = mbedtls_x509_crt_parse(&mbed_cert, Uint8::to_const_uchar(certificate.data()), certificate.size());
VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);

p = mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(serial).CHIP_CRYPTO_PAL_PRIVATE_X509(p);
len = mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(serial).CHIP_CRYPTO_PAL_PRIVATE_X509(len);
VerifyOrExit(len <= serialNumber.size(), error = CHIP_ERROR_BUFFER_TOO_SMALL);

memcpy(serialNumber.data(), p, len);
serialNumber.reduce_size(len);

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

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

return error;
}

CHIP_ERROR ExtractVIDPIDFromX509Cert(const ByteSpan & certificate, AttestationCertVidPid & vidpid)
{
#if defined(MBEDTLS_X509_CRT_PARSE_C)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
*
* Copyright (c) 2020-2022 Project CHIP Authors
* Copyright (c) 2020-2023 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -1573,6 +1573,40 @@ CHIP_ERROR ExtractAKIDFromX509Cert(const ByteSpan & certificate, MutableByteSpan
return ExtractKIDFromX509Cert(false, certificate, akid);
}

CHIP_ERROR ExtractSerialNumberFromX509Cert(const ByteSpan & certificate, MutableByteSpan & serialNumber)
{
#if defined(MBEDTLS_X509_CRT_PARSE_C)
CHIP_ERROR error = CHIP_NO_ERROR;
int result = 0;
uint8_t * p = nullptr;
size_t len = 0;
mbedtls_x509_crt mbed_cert;

mbedtls_x509_crt_init(&mbed_cert);

result = mbedtls_x509_crt_parse(&mbed_cert, Uint8::to_const_uchar(certificate.data()), certificate.size());
VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);

p = mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(serial).CHIP_CRYPTO_PAL_PRIVATE_X509(p);
len = mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(serial).CHIP_CRYPTO_PAL_PRIVATE_X509(len);
VerifyOrExit(len <= serialNumber.size(), error = CHIP_ERROR_BUFFER_TOO_SMALL);

memcpy(serialNumber.data(), p, len);
serialNumber.reduce_size(len);

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

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

return error;
}

CHIP_ERROR ExtractVIDPIDFromX509Cert(const ByteSpan & certificate, AttestationCertVidPid & vidpid)
{
#if defined(MBEDTLS_X509_CRT_PARSE_C)
Expand Down
36 changes: 35 additions & 1 deletion src/platform/silabs/SiWx917/CHIPCryptoPALTinyCrypt.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
*
* Copyright (c) 2020-2022 Project CHIP Authors
* Copyright (c) 2020-2023 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -1604,6 +1604,40 @@ CHIP_ERROR ExtractAKIDFromX509Cert(const ByteSpan & certificate, MutableByteSpan
return ExtractKIDFromX509Cert(false, certificate, akid);
}

CHIP_ERROR ExtractSerialNumberFromX509Cert(const ByteSpan & certificate, MutableByteSpan & serialNumber)
{
#if defined(MBEDTLS_X509_CRT_PARSE_C)
CHIP_ERROR error = CHIP_NO_ERROR;
int result = 0;
uint8_t * p = nullptr;
size_t len = 0;
mbedtls_x509_crt mbed_cert;

mbedtls_x509_crt_init(&mbed_cert);

result = mbedtls_x509_crt_parse(&mbed_cert, Uint8::to_const_uchar(certificate.data()), certificate.size());
VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);

p = mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(serial).CHIP_CRYPTO_PAL_PRIVATE_X509(p);
len = mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(serial).CHIP_CRYPTO_PAL_PRIVATE_X509(len);
VerifyOrExit(len <= serialNumber.size(), error = CHIP_ERROR_BUFFER_TOO_SMALL);

memcpy(serialNumber.data(), p, len);
serialNumber.reduce_size(len);

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

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

return error;
}

CHIP_ERROR ExtractVIDPIDFromX509Cert(const ByteSpan & certificate, AttestationCertVidPid & vidpid)
{
#if defined(MBEDTLS_X509_CRT_PARSE_C)
Expand Down
Loading
Loading