Skip to content

Commit

Permalink
Updated Certificate Extensions Encoding to Match the Spec. (#6015)
Browse files Browse the repository at this point in the history
-- CHIP certificate extensions should be encoded as TLV List
  -- Updated extension tags
  • Loading branch information
emargolis authored Apr 19, 2021
1 parent ca83379 commit e09e11b
Show file tree
Hide file tree
Showing 4 changed files with 689 additions and 697 deletions.
19 changes: 9 additions & 10 deletions src/credentials/CHIPCert.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,15 @@ enum
kTag_PublicKeyAlgorithm = 7, /**< [ unsigned int ] Identifies the algorithm with which the public key can be used. */
kTag_EllipticCurveIdentifier = 8, /**< [ unsigned int ] For EC certs, identifies the elliptic curve used. */
kTag_EllipticCurvePublicKey = 9, /**< [ byte string ] The elliptic curve public key, in X9.62 encoded format. */
kTag_ECDSASignature = 10, /**< [ structure ] The ECDSA signature for the certificate. */
// ---- Tags identifying certificate extensions (tag numbers 128 - 255) ----
kCertificateExtensionTagsStart = 128,
kTag_BasicConstraints = 128, /**< [ structure ] Identifies whether the subject of the certificate is a CA. */
kTag_KeyUsage = 129, /**< [ unsigned int ] Bits identifying key usage, per RFC5280. */
kTag_ExtendedKeyUsage = 130, /**< [ array ] Array of enumerated values giving the purposes for which
the public key can be used, per RFC5280. */
kTag_SubjectKeyIdentifier = 131, /**< [ byte string ] Identifier of the certificate's public key. */
kTag_AuthorityKeyIdentifier = 132, /**< [ byte string ] Identifier of the public key used to sign the certificate. */
kCertificateExtensionTagsEnd = 255,
kTag_Extensions = 10, /**< [ list ] Certificate extensions. */
kTag_ECDSASignature = 11, /**< [ structure ] The ECDSA signature for the certificate. */

// ---- Context-specific Tags for certificate extensions ----
kTag_BasicConstraints = 1, /**< [ structure ] Identifies whether the subject of the certificate is a CA. */
kTag_KeyUsage = 2, /**< [ unsigned int ] Bits identifying key usage, per RFC5280. */
kTag_ExtendedKeyUsage = 3, /**< [ array ] Enumerated values giving the purposes for which the public key can be used. */
kTag_SubjectKeyIdentifier = 4, /**< [ byte string ] Identifier of the certificate's public key. */
kTag_AuthorityKeyIdentifier = 5, /**< [ byte string ] Identifier of the public key used to sign the certificate. */

// ---- Context-specific Tags for ECDSASignature Structure ----
kTag_ECDSASignature_r = 1, /**< [ byte string ] ECDSA r value, in ASN.1 integer encoding. */
Expand Down
7 changes: 7 additions & 0 deletions src/credentials/CHIPCertFromX509.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,10 @@ static CHIP_ERROR ConvertExtension(ASN1Reader & reader, TLVWriter & writer)
static CHIP_ERROR ConvertExtensions(ASN1Reader & reader, TLVWriter & writer)
{
CHIP_ERROR err;
TLVType containerType;

err = writer.StartContainer(ContextTag(kTag_Extensions), kTLVType_List, containerType);
SuccessOrExit(err);

// Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
ASN1_PARSE_ENTER_SEQUENCE
Expand All @@ -493,6 +497,9 @@ static CHIP_ERROR ConvertExtensions(ASN1Reader & reader, TLVWriter & writer)
}
ASN1_EXIT_SEQUENCE;

err = writer.EndContainer(containerType);
SuccessOrExit(err);

exit:
return err;
}
Expand Down
53 changes: 19 additions & 34 deletions src/credentials/CHIPCertToX509.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,6 @@ using namespace chip::ASN1;
using namespace chip::TLV;
using namespace chip::Protocols;

inline bool IsCertificateExtensionTag(uint64_t tag)
{
if (IsContextTag(tag))
{
uint32_t tagNum = TagNumFromTag(tag);
return (tagNum >= kCertificateExtensionTagsStart && tagNum <= kCertificateExtensionTagsEnd);
}

return false;
}

static CHIP_ERROR DecodeConvertDN(TLVReader & reader, ASN1Writer & writer, ChipDN & dn)
{
CHIP_ERROR err;
Expand Down Expand Up @@ -609,33 +598,37 @@ static CHIP_ERROR DecodeConvertExtension(TLVReader & reader, ASN1Writer & writer
static CHIP_ERROR DecodeConvertExtensions(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
{
CHIP_ERROR err;
uint64_t tag;
TLVType outerContainer;

err = reader.Next(kTLVType_List, ContextTag(kTag_Extensions));
SuccessOrExit(err);

err = reader.EnterContainer(outerContainer);
SuccessOrExit(err);

// extensions [3] EXPLICIT Extensions OPTIONAL
ASN1_START_CONSTRUCTED(kASN1TagClass_ContextSpecific, 3)
{
// Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
ASN1_START_SEQUENCE
{
while (true)
// Read certificate extension in the List.
while ((err = reader.Next()) == CHIP_NO_ERROR)
{
err = DecodeConvertExtension(reader, writer, certData);
SuccessOrExit(err);

// Break the loop if the next certificate element is NOT an extension.
err = reader.Next();
SuccessOrExit(err);
tag = reader.GetTag();
if (!IsCertificateExtensionTag(tag))
{
break;
}
}
}
ASN1_END_SEQUENCE;
}
ASN1_END_CONSTRUCTED;

err = reader.VerifyEndOfContainer();
SuccessOrExit(err);

err = reader.ExitContainer(outerContainer);
SuccessOrExit(err);

exit:
return err;
}
Expand All @@ -646,9 +639,8 @@ CHIP_ERROR DecodeECDSASignature(TLVReader & reader, ChipCertificateData & certDa
TLVType containerType;
uint32_t len;

// Verify the tag and type
VerifyOrExit(reader.GetType() == kTLVType_Structure, err = CHIP_ERROR_WRONG_TLV_TYPE);
VerifyOrExit(reader.GetTag() == ContextTag(kTag_ECDSASignature), err = CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);
err = reader.Next(kTLVType_Structure, ContextTag(kTag_ECDSASignature));
SuccessOrExit(err);

err = reader.EnterContainer(containerType);
SuccessOrExit(err);
Expand Down Expand Up @@ -737,7 +729,6 @@ static CHIP_ERROR DecodeConvertECDSASignature(TLVReader & reader, ASN1Writer & w
CHIP_ERROR DecodeConvertTBSCert(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
{
CHIP_ERROR err;
uint64_t tag;

// tbsCertificate TBSCertificate,
// TBSCertificate ::= SEQUENCE
Expand Down Expand Up @@ -801,15 +792,9 @@ CHIP_ERROR DecodeConvertTBSCert(TLVReader & reader, ASN1Writer & writer, ChipCer
err = DecodeConvertSubjectPublicKeyInfo(reader, writer, certData);
SuccessOrExit(err);

// If the next element is a certificate extension...
err = reader.Next();
// certificate extensions
err = DecodeConvertExtensions(reader, writer, certData);
SuccessOrExit(err);
tag = reader.GetTag();
if (IsCertificateExtensionTag(tag))
{
err = DecodeConvertExtensions(reader, writer, certData);
SuccessOrExit(err);
}
}
ASN1_END_SEQUENCE;

Expand Down
Loading

0 comments on commit e09e11b

Please sign in to comment.