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

CHIPCert: Update to Support Single CASE Authenticated Tag OID. #11697

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
26 changes: 26 additions & 0 deletions src/credentials/CHIPCert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -883,6 +883,32 @@ CHIP_ERROR ExtractFabricIdFromCert(const ChipCertificateData & cert, FabricId *
return CHIP_ERROR_INVALID_ARGUMENT;
}

CHIP_ERROR ExtractCATsFromOpCert(const ChipCertificateData & opcert, uint32_t * cats, uint8_t catsSize)
{
uint8_t catCount = 0;
uint8_t certType;

ReturnErrorOnFailure(opcert.mSubjectDN.GetCertType(certType));
VerifyOrReturnError(certType == kCertType_Node, CHIP_ERROR_INVALID_ARGUMENT);

const ChipDN & subjectDN = opcert.mSubjectDN;
for (uint8_t i = 0; i < subjectDN.RDNCount(); ++i)
{
const auto & rdn = subjectDN.rdn[i];
if (rdn.mAttrOID == ASN1::kOID_AttributeType_ChipCASEAuthenticatedTag)
{
ReturnErrorCodeIf(catCount == catsSize, CHIP_ERROR_BUFFER_TOO_SMALL);
cats[catCount++] = static_cast<uint32_t>(rdn.mChipVal);
}
}
for (uint8_t i = catCount; i < catsSize; ++i)
{
cats[i] = 0;
}

return CHIP_NO_ERROR;
}

CHIP_ERROR ExtractNodeIdFabricIdFromOpCert(const ByteSpan & opcert, NodeId * nodeId, FabricId * fabricId)
{
ChipCertificateSet certSet;
Expand Down
16 changes: 15 additions & 1 deletion src/credentials/CHIPCert.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ static constexpr uint32_t kMaxDERCertLength = 600;
// The decode buffer is used to reconstruct TBS section of X.509 certificate, which doesn't include signature.
static constexpr uint32_t kMaxCHIPCertDecodeBufLength = kMaxDERCertLength - Crypto::kMax_ECDSA_Signature_Length_Der;

// Muximum number of CASE Authenticated Tags (CAT) in the CHIP certificate subject.
static constexpr size_t kMaxSubjectCATAttributeCount = CHIP_CONFIG_CERT_MAX_RDN_ATTRIBUTES - 2;

/** Data Element Tags for the CHIP Certificate
*/
enum
Expand Down Expand Up @@ -715,7 +718,7 @@ inline bool IsChip64bitDNAttr(chip::ASN1::OID oid)
**/
inline bool IsChip32bitDNAttr(chip::ASN1::OID oid)
{
return (oid == chip::ASN1::kOID_AttributeType_ChipAuthTag1 || oid == chip::ASN1::kOID_AttributeType_ChipAuthTag2);
return (oid == chip::ASN1::kOID_AttributeType_ChipCASEAuthenticatedTag);
}

/**
Expand Down Expand Up @@ -796,6 +799,17 @@ CHIP_ERROR ExtractFabricIdFromCert(const ChipCertificateData & cert, FabricId *
*/
CHIP_ERROR ExtractNodeIdFabricIdFromOpCert(const ChipCertificateData & opcert, NodeId * nodeId, FabricId * fabricId);

/**
* Extract CASE Authenticated Tags from an operational certificate that has already been
* parsed.
*
* All values in the 'cats' array will be set either to a valid CAT value or zero (undefined) value.
*
* @return CHIP_ERROR_INVALID_ARGUMENT if the passed-in cert is not NOC.
* @return CHIP_ERROR_BUFFER_TOO_SMALL if the passed-in CATs array is too small.
*/
CHIP_ERROR ExtractCATsFromOpCert(const ChipCertificateData & opcert, uint32_t * cats, uint8_t catsSize);

/**
* Extract Node ID and Fabric ID from an operational certificate in ByteSpan TLV-encoded
* form. This does not perform any sort of validation on the certificate
Expand Down
2,084 changes: 1,115 additions & 969 deletions src/credentials/tests/CHIPCert_test_vectors.cpp

Large diffs are not rendered by default.

196 changes: 105 additions & 91 deletions src/credentials/tests/CHIPCert_test_vectors.h

Large diffs are not rendered by default.

77 changes: 77 additions & 0 deletions src/credentials/tests/TestChipCert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1039,6 +1039,7 @@ static void TestChipCert_ExtractPeerId(nlTestSuite * inSuite, void * inContext)
{ TestCert::kNode02_05, TestCert::kICA02, 0xDEDEDEDE00020005, 0xFAB000000000001D },
{ TestCert::kNode02_06, TestCert::kICA02, 0xDEDEDEDE00020006, 0xFAB000000000001D },
{ TestCert::kNode02_07, TestCert::kICA02, 0xDEDEDEDE00020007, 0xFAB000000000001D },
{ TestCert::kNode02_08, TestCert::kICA02, 0xDEDEDEDE00020008, 0xFAB000000000001D },
};
// clang-format on

Expand Down Expand Up @@ -1107,6 +1108,80 @@ static void TestChipCert_ExtractPeerId(nlTestSuite * inSuite, void * inContext)
}
}

static void TestChipCert_ExtractCATsFromOpCert(nlTestSuite * inSuite, void * inContext)
{
struct TestCase
{
uint8_t Cert;
uint32_t ExpectedCAT[kMaxSubjectCATAttributeCount];
};

// clang-format off
static constexpr TestCase sTestCases[] = {
// Cert CATs
// =============================================================
{ TestCert::kNode01_01, { 0, 0, 0 } },
{ TestCert::kNode01_02, { 0, 0, 0 } },
{ TestCert::kNode02_01, { 0, 0, 0 } },
{ TestCert::kNode02_02, { 0, 0, 0 } },
{ TestCert::kNode02_03, { 0xABCD0001, 0, 0 } },
{ TestCert::kNode02_04, { 0xABCE1002, 0xABCD0003, 0 } },
{ TestCert::kNode02_05, { 0xABCD0010, 0xABCE1008, 0 } },
{ TestCert::kNode02_06, { 0, 0, 0 } },
{ TestCert::kNode02_07, { 0, 0, 0 } },
{ TestCert::kNode02_08, { 0xABCF00A0, 0xABCD0020, 0xABCE0100 } },
};
// clang-format on

// Test extraction from the raw ByteSpan form.
ChipCertificateSet certSet;
for (auto & testCase : sTestCases)
{
CHIP_ERROR err = certSet.Init(1);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);

err = LoadTestCert(certSet, testCase.Cert, sNullLoadFlag, sNullDecodeFlag);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);

uint32_t cats[kMaxSubjectCATAttributeCount];
err = ExtractCATsFromOpCert(certSet.GetCertSet()[0], cats, ArraySize(cats));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, memcmp(cats, testCase.ExpectedCAT, sizeof(cats)) == 0);

certSet.Release();
}

// Error case: trying to extract CAT from Root Cert.
{
CHIP_ERROR err = certSet.Init(1);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);

err = LoadTestCert(certSet, TestCert::kRoot01, sNullLoadFlag, sNullDecodeFlag);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);

uint32_t cats[kMaxSubjectCATAttributeCount];
err = ExtractCATsFromOpCert(certSet.GetCertSet()[0], cats, ArraySize(cats));
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_INVALID_ARGUMENT);

certSet.Release();
}

// Error case: CAT array is too small.
{
CHIP_ERROR err = certSet.Init(1);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);

err = LoadTestCert(certSet, TestCert::kNode02_08, sNullLoadFlag, sNullDecodeFlag);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);

uint32_t cats[kMaxSubjectCATAttributeCount - 1];
err = ExtractCATsFromOpCert(certSet.GetCertSet()[0], cats, ArraySize(cats));
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BUFFER_TOO_SMALL);

certSet.Release();
}
}

static void TestChipCert_ExtractPublicKeyAndSKID(nlTestSuite * inSuite, void * inContext)
{
struct TestCase
Expand Down Expand Up @@ -1134,6 +1209,7 @@ static void TestChipCert_ExtractPublicKeyAndSKID(nlTestSuite * inSuite, void * i
{ TestCert::kNode02_05, sTestCert_Node02_05_PublicKey, sTestCert_Node02_05_SubjectKeyId },
{ TestCert::kNode02_06, sTestCert_Node02_06_PublicKey, sTestCert_Node02_06_SubjectKeyId },
{ TestCert::kNode02_07, sTestCert_Node02_07_PublicKey, sTestCert_Node02_07_SubjectKeyId },
{ TestCert::kNode02_08, sTestCert_Node02_08_PublicKey, sTestCert_Node02_08_SubjectKeyId },
};
// clang-format on

Expand Down Expand Up @@ -1200,6 +1276,7 @@ static const nlTest sTests[] = {
NL_TEST_DEF("Test CHIP Verify Generated Cert Chain", TestChipCert_VerifyGeneratedCerts),
NL_TEST_DEF("Test CHIP Verify Generated Cert Chain No ICA", TestChipCert_VerifyGeneratedCertsNoICA),
NL_TEST_DEF("Test extracting PeerId from node certificate", TestChipCert_ExtractPeerId),
NL_TEST_DEF("Test extracting CAST Authenticated Tags from node certificate", TestChipCert_ExtractCATsFromOpCert),
NL_TEST_DEF("Test extracting PublicKey and SKID from chip certificate", TestChipCert_ExtractPublicKeyAndSKID),
NL_TEST_SENTINEL()
};
Expand Down
4 changes: 1 addition & 3 deletions src/lib/asn1/gen_asn1oid.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,8 @@ def identity(n):
3), dod(6), internet(1), private(4), enterprise(1), zigbee(37244), chip(1), 4]),
("AttributeType", "ChipFabricId", 21, [iso(1), organization(
3), dod(6), internet(1), private(4), enterprise(1), zigbee(37244), chip(1), 5]),
("AttributeType", "ChipAuthTag1", 22, [iso(1), organization(
("AttributeType", "ChipCASEAuthenticatedTag", 22, [iso(1), organization(
3), dod(6), internet(1), private(4), enterprise(1), zigbee(37244), chip(1), 6]),
("AttributeType", "ChipAuthTag2", 23, [iso(1), organization(
3), dod(6), internet(1), private(4), enterprise(1), zigbee(37244), chip(1), 7]),

# Elliptic Curves
("EllipticCurve", "prime256v1", 1, [
Expand Down
7 changes: 2 additions & 5 deletions src/tools/chip-cert/CertUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,8 @@ bool ToolChipDN::SetCertSubjectDN(X509 * cert) const
case kOID_AttributeType_ChipFabricId:
attrNID = gNIDChipFabricId;
break;
case kOID_AttributeType_ChipAuthTag1:
attrNID = gNIDChipAuthTag1;
break;
case kOID_AttributeType_ChipAuthTag2:
attrNID = gNIDChipAuthTag2;
case kOID_AttributeType_ChipCASEAuthenticatedTag:
attrNID = gNIDChipCASEAuthenticatedTag;
break;
default:
ExitNow(res = false);
Expand Down
21 changes: 4 additions & 17 deletions src/tools/chip-cert/Cmd_GenCert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ OptionDef gCmdOptionDefs[] =
{ "type", kArgumentRequired, 't' },
{ "subject-chip-id", kArgumentRequired, 'i' },
{ "subject-fab-id", kArgumentRequired, 'f' },
{ "subject-at", kArgumentRequired, 'a' },
{ "subject-cat", kArgumentRequired, 'a' },
{ "subject-cn-u", kArgumentRequired, 'c' },
{ "path-len-constraint", kArgumentRequired, 'p' },
{ "future-ext-sub", kArgumentRequired, 'x' },
Expand Down Expand Up @@ -83,9 +83,9 @@ const char * const gCmdOptionHelp =
"\n"
" Subject DN Fabric Id attribute (in hex).\n"
"\n"
" -a, --subject-at <hex-digits>\n"
" -a, --subject-cat <hex-digits>\n"
"\n"
" Subject DN CHIP Authentication Tag (in hex).\n"
" Subject DN CHIP CASE Authentication Tag (in hex).\n"
"\n"
" -c, --subject-cn-u <string>\n"
"\n"
Expand Down Expand Up @@ -266,20 +266,7 @@ bool HandleOption(const char * progName, OptionSet * optSet, int id, const char
PrintArgError("%s: Invalid value specified for the subject authentication tag attribute: %s\n", progName, arg);
return false;
}

if (!gSubjectDN.HasAttr(kOID_AttributeType_ChipAuthTag1))
{
attrOID = kOID_AttributeType_ChipAuthTag1;
}
else if (!gSubjectDN.HasAttr(kOID_AttributeType_ChipAuthTag2))
{
attrOID = kOID_AttributeType_ChipAuthTag2;
}
else
{
PrintArgError("%s: Too many authentication tag attributes are specified: %s\n", progName, arg);
return false;
}
attrOID = kOID_AttributeType_ChipCASEAuthenticatedTag;

err = gSubjectDN.AddAttribute(attrOID, chip32bitAttr);
if (err != CHIP_NO_ERROR)
Expand Down
16 changes: 4 additions & 12 deletions src/tools/chip-cert/GeneralUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ int gNIDChipFirmwareSigningId;
int gNIDChipICAId;
int gNIDChipRootId;
int gNIDChipFabricId;
int gNIDChipAuthTag1;
int gNIDChipAuthTag2;
int gNIDChipCASEAuthenticatedTag;
int gNIDChipAttAttrVID;
int gNIDChipAttAttrPID;
int gNIDChipCurveP256 = EC_curve_nist2nid("P-256");
Expand Down Expand Up @@ -83,14 +82,8 @@ bool InitOpenSSL()
ReportOpenSSLErrorAndExit("OBJ_create", res = false);
}

gNIDChipAuthTag1 = OBJ_create("1.3.6.1.4.1.37244.1.6", "ChipAuthTag1", "ChipAuthTag1");
if (gNIDChipAuthTag1 == 0)
{
ReportOpenSSLErrorAndExit("OBJ_create", res = false);
}

gNIDChipAuthTag2 = OBJ_create("1.3.6.1.4.1.37244.1.7", "ChipAuthTag2", "ChipAuthTag2");
if (gNIDChipAuthTag2 == 0)
gNIDChipCASEAuthenticatedTag = OBJ_create("1.3.6.1.4.1.37244.1.6", "ChipCASEAuthenticatedTag", "ChipCASEAuthenticatedTag");
if (gNIDChipCASEAuthenticatedTag == 0)
{
ReportOpenSSLErrorAndExit("OBJ_create", res = false);
}
Expand All @@ -112,8 +105,7 @@ bool InitOpenSSL()
ASN1_STRING_TABLE_add(gNIDChipICAId, 16, 16, B_ASN1_UTF8STRING, 0);
ASN1_STRING_TABLE_add(gNIDChipRootId, 16, 16, B_ASN1_UTF8STRING, 0);
ASN1_STRING_TABLE_add(gNIDChipFabricId, 16, 16, B_ASN1_UTF8STRING, 0);
ASN1_STRING_TABLE_add(gNIDChipAuthTag1, 8, 8, B_ASN1_UTF8STRING, 0);
ASN1_STRING_TABLE_add(gNIDChipAuthTag2, 8, 8, B_ASN1_UTF8STRING, 0);
ASN1_STRING_TABLE_add(gNIDChipCASEAuthenticatedTag, 8, 8, B_ASN1_UTF8STRING, 0);
ASN1_STRING_TABLE_add(gNIDChipAttAttrVID, 4, 4, B_ASN1_UTF8STRING, 0);
ASN1_STRING_TABLE_add(gNIDChipAttAttrPID, 4, 4, B_ASN1_UTF8STRING, 0);

Expand Down
3 changes: 1 addition & 2 deletions src/tools/chip-cert/chip-cert.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,7 @@ extern int gNIDChipFirmwareSigningId;
extern int gNIDChipICAId;
extern int gNIDChipRootId;
extern int gNIDChipFabricId;
extern int gNIDChipAuthTag1;
extern int gNIDChipAuthTag2;
extern int gNIDChipCASEAuthenticatedTag;
extern int gNIDChipCurveP256;
extern int gNIDChipAttAttrVID;
extern int gNIDChipAttAttrPID;
Expand Down