From 4927875fc56e04c1d04908b5d3d63108192db291 Mon Sep 17 00:00:00 2001 From: Evgeny Margolis Date: Mon, 12 Sep 2022 08:13:28 -0700 Subject: [PATCH] chip-cert: Added Support for Multiple Subject Name Attributes in Operational Certificates. (#22201) --- src/tools/chip-cert/CertUtils.cpp | 87 +++++++-- src/tools/chip-cert/Cmd_GenCert.cpp | 290 +++++++++++++++++++++++++++- 2 files changed, 356 insertions(+), 21 deletions(-) diff --git a/src/tools/chip-cert/CertUtils.cpp b/src/tools/chip-cert/CertUtils.cpp index 5afaa3c29d561f..a7558fb812f3fb 100644 --- a/src/tools/chip-cert/CertUtils.cpp +++ b/src/tools/chip-cert/CertUtils.cpp @@ -51,6 +51,51 @@ bool ToolChipDN::SetCertName(X509_NAME * name) const case kOID_AttributeType_CommonName: attrNID = NID_commonName; break; + case kOID_AttributeType_Surname: + attrNID = NID_surname; + break; + case kOID_AttributeType_SerialNumber: + attrNID = NID_serialNumber; + break; + case kOID_AttributeType_CountryName: + attrNID = NID_countryName; + break; + case kOID_AttributeType_LocalityName: + attrNID = NID_localityName; + break; + case kOID_AttributeType_StateOrProvinceName: + attrNID = NID_stateOrProvinceName; + break; + case kOID_AttributeType_OrganizationName: + attrNID = NID_organizationName; + break; + case kOID_AttributeType_OrganizationalUnitName: + attrNID = NID_organizationalUnitName; + break; + case kOID_AttributeType_Title: + attrNID = NID_title; + break; + case kOID_AttributeType_Name: + attrNID = NID_name; + break; + case kOID_AttributeType_GivenName: + attrNID = NID_givenName; + break; + case kOID_AttributeType_Initials: + attrNID = NID_initials; + break; + case kOID_AttributeType_GenerationQualifier: + attrNID = NID_generationQualifier; + break; + case kOID_AttributeType_DNQualifier: + attrNID = NID_dnQualifier; + break; + case kOID_AttributeType_Pseudonym: + attrNID = NID_pseudonym; + break; + case kOID_AttributeType_DomainComponent: + attrNID = NID_domainComponent; + break; case kOID_AttributeType_MatterNodeId: attrNID = gNIDChipNodeId; break; @@ -73,40 +118,42 @@ bool ToolChipDN::SetCertName(X509_NAME * name) const ExitNow(res = false); } + char chipAttrStr[std::max(kChip64bitAttrUTF8Length, kChip32bitAttrUTF8Length)] = { 0 }; + int type = V_ASN1_UTF8STRING; + uint8_t * attrStr = reinterpret_cast(chipAttrStr); + int attrLen = 0; + if (IsChip64bitDNAttr(rdn[i].mAttrOID)) { - char chipAttrStr[kChip64bitAttrUTF8Length]; - VerifyOrReturnError(Encoding::Uint64ToHex(rdn[i].mChipVal, chipAttrStr, sizeof(chipAttrStr), + VerifyOrReturnError(Encoding::Uint64ToHex(rdn[i].mChipVal, chipAttrStr, kChip64bitAttrUTF8Length, Encoding::HexFlags::kUppercase) == CHIP_NO_ERROR, false); - - if (!X509_NAME_add_entry_by_NID(name, attrNID, MBSTRING_UTF8, reinterpret_cast(chipAttrStr), - sizeof(chipAttrStr), -1, 0)) - { - ReportOpenSSLErrorAndExit("X509_NAME_add_entry_by_NID", res = false); - } + attrLen = kChip64bitAttrUTF8Length; } else if (IsChip32bitDNAttr(rdn[i].mAttrOID)) { - char chipAttrStr[kChip32bitAttrUTF8Length]; - VerifyOrReturnError(Encoding::Uint32ToHex(static_cast(rdn[i].mChipVal), chipAttrStr, sizeof(chipAttrStr), + VerifyOrReturnError(Encoding::Uint32ToHex(static_cast(rdn[i].mChipVal), chipAttrStr, kChip32bitAttrUTF8Length, Encoding::HexFlags::kUppercase) == CHIP_NO_ERROR, false); - - if (!X509_NAME_add_entry_by_NID(name, attrNID, MBSTRING_UTF8, reinterpret_cast(chipAttrStr), - sizeof(chipAttrStr), -1, 0)) - { - ReportOpenSSLErrorAndExit("X509_NAME_add_entry_by_NID", res = false); - } + attrLen = kChip32bitAttrUTF8Length; } else { - if (!X509_NAME_add_entry_by_NID(name, attrNID, MBSTRING_UTF8, - reinterpret_cast(const_cast(rdn[i].mString.data())), - static_cast(rdn[i].mString.size()), -1, 0)) + if (rdn[i].mAttrOID == kOID_AttributeType_DomainComponent) { - ReportOpenSSLErrorAndExit("X509_NAME_add_entry_by_NID", res = false); + type = V_ASN1_IA5STRING; + } + else if (rdn[i].mAttrIsPrintableString) + { + type = V_ASN1_PRINTABLESTRING; } + attrStr = reinterpret_cast(const_cast(rdn[i].mString.data())); + attrLen = static_cast(rdn[i].mString.size()); + } + + if (!X509_NAME_add_entry_by_NID(name, attrNID, type, attrStr, attrLen, -1, 0)) + { + ReportOpenSSLErrorAndExit("X509_NAME_add_entry_by_NID", res = false); } } diff --git a/src/tools/chip-cert/Cmd_GenCert.cpp b/src/tools/chip-cert/Cmd_GenCert.cpp index ab0bc0c63587c6..32be5bdcbaf589 100644 --- a/src/tools/chip-cert/Cmd_GenCert.cpp +++ b/src/tools/chip-cert/Cmd_GenCert.cpp @@ -48,6 +48,36 @@ OptionDef gCmdOptionDefs[] = { "subject-fab-id", kArgumentRequired, 'f' }, { "subject-cat", kArgumentRequired, 'a' }, { "subject-cn-u", kArgumentRequired, 'c' }, + { "subject-cn-p", kArgumentRequired, 'b' }, + { "subject-su-u", kArgumentRequired, 'd' }, + { "subject-su-p", kArgumentRequired, 'e' }, + { "subject-sn-u", kArgumentRequired, 'g' }, + { "subject-sn-p", kArgumentRequired, 'j' }, + { "subject-co-u", kArgumentRequired, 'm' }, + { "subject-co-p", kArgumentRequired, 'n' }, + { "subject-ln-u", kArgumentRequired, 'q' }, + { "subject-ln-p", kArgumentRequired, 'r' }, + { "subject-pn-u", kArgumentRequired, 's' }, + { "subject-pn-p", kArgumentRequired, 'u' }, + { "subject-on-u", kArgumentRequired, 'w' }, + { "subject-on-p", kArgumentRequired, 'y' }, + { "subject-un-u", kArgumentRequired, 'z' }, + { "subject-un-p", kArgumentRequired, 'U' }, + { "subject-ti-u", kArgumentRequired, 'W' }, + { "subject-ti-p", kArgumentRequired, 'S' }, + { "subject-na-u", kArgumentRequired, 'T' }, + { "subject-na-p", kArgumentRequired, 'A' }, + { "subject-gn-u", kArgumentRequired, 'B' }, + { "subject-gn-p", kArgumentRequired, 'D' }, + { "subject-in-u", kArgumentRequired, 'G' }, + { "subject-in-p", kArgumentRequired, 'H' }, + { "subject-gq-u", kArgumentRequired, 'J' }, + { "subject-gq-p", kArgumentRequired, 'L' }, + { "subject-dq-u", kArgumentRequired, 'M' }, + { "subject-dq-p", kArgumentRequired, 'N' }, + { "subject-ps-u", kArgumentRequired, 'P' }, + { "subject-ps-p", kArgumentRequired, 'Q' }, + { "subject-dc-i", kArgumentRequired, 'R' }, { "path-len-constraint", kArgumentRequired, 'p' }, { "future-ext-sub", kArgumentRequired, 'x' }, { "future-ext-info", kArgumentRequired, '2' }, @@ -93,7 +123,25 @@ const char * const gCmdOptionHelp = " Subject DN CHIP CASE Authentication Tag in hexadecimal format with upto 4 octets with or without '0x' prefix.\n" " The version subfield (lower 16 bits) should be different from 0.\n" "\n" - " -c, --subject-cn-u \n" + " Variety of DN attributes are also supported and can be added to the subject DN of the certificate.\n" + " These attributes can be encoded as UTF8String, PrintableString or IA5String as specified below:\n" + "\n" + " -, --subject-cn- - commonName attribute \n" + " -, --subject-su- - surname attribute \n" + " -, --subject-sn- - serialNumber attribute \n" + " -, --subject-co- - countryName attribute \n" + " -, --subject-ln- - localityName attribute \n" + " -, --subject-pn- - stateOrProvinceName attribute \n" + " -, --subject-on- - organizationName attribute \n" + " -, --subject-un- - organizationalUnitName attribute \n" + " -, --subject-ti- - title attribute \n" + " -, --subject-na- - name attribute \n" + " -, --subject-gn- - givenName attribute \n" + " -, --subject-in- - initials attribute \n" + " -, --subject-gq- - generationQualifier attribute \n" + " -, --subject-dq- - dnQualifier attribute \n" + " -

, --subject-ps- - pseudonym attribute \n" + " -R, --subject-dc-i - domainComponent attribute \n" "\n" " Subject DN Common Name attribute encoded as UTF8String.\n" "\n" @@ -417,6 +465,246 @@ bool HandleOption(const char * progName, OptionSet * optSet, int id, const char return false; } break; + case 'b': + err = gSubjectDN.AddAttribute_CommonName(chip::CharSpan::fromCharString(arg), true); + if (err != CHIP_NO_ERROR) + { + fprintf(stderr, "Failed to add Common Name attribute to the subject DN: %s\n", chip::ErrorStr(err)); + return false; + } + break; + case 'd': + err = gSubjectDN.AddAttribute_Surname(chip::CharSpan::fromCharString(arg), false); + if (err != CHIP_NO_ERROR) + { + fprintf(stderr, "Failed to add Surname attribute to the subject DN: %s\n", chip::ErrorStr(err)); + return false; + } + break; + case 'e': + err = gSubjectDN.AddAttribute_Surname(chip::CharSpan::fromCharString(arg), true); + if (err != CHIP_NO_ERROR) + { + fprintf(stderr, "Failed to add Surname attribute to the subject DN: %s\n", chip::ErrorStr(err)); + return false; + } + break; + case 'g': + err = gSubjectDN.AddAttribute_SerialNumber(chip::CharSpan::fromCharString(arg), false); + if (err != CHIP_NO_ERROR) + { + fprintf(stderr, "Failed to add Serial Number attribute to the subject DN: %s\n", chip::ErrorStr(err)); + return false; + } + break; + case 'j': + err = gSubjectDN.AddAttribute_SerialNumber(chip::CharSpan::fromCharString(arg), true); + if (err != CHIP_NO_ERROR) + { + fprintf(stderr, "Failed to add Serial Number attribute to the subject DN: %s\n", chip::ErrorStr(err)); + return false; + } + break; + case 'm': + err = gSubjectDN.AddAttribute_CountryName(chip::CharSpan::fromCharString(arg), false); + if (err != CHIP_NO_ERROR) + { + fprintf(stderr, "Failed to add Country Name attribute to the subject DN: %s\n", chip::ErrorStr(err)); + return false; + } + break; + case 'n': + err = gSubjectDN.AddAttribute_CountryName(chip::CharSpan::fromCharString(arg), true); + if (err != CHIP_NO_ERROR) + { + fprintf(stderr, "Failed to add Country Name attribute to the subject DN: %s\n", chip::ErrorStr(err)); + return false; + } + break; + case 'q': + err = gSubjectDN.AddAttribute_LocalityName(chip::CharSpan::fromCharString(arg), false); + if (err != CHIP_NO_ERROR) + { + fprintf(stderr, "Failed to add Locality Name attribute to the subject DN: %s\n", chip::ErrorStr(err)); + return false; + } + break; + case 'r': + err = gSubjectDN.AddAttribute_LocalityName(chip::CharSpan::fromCharString(arg), true); + if (err != CHIP_NO_ERROR) + { + fprintf(stderr, "Failed to add Locality Name attribute to the subject DN: %s\n", chip::ErrorStr(err)); + return false; + } + break; + case 's': + err = gSubjectDN.AddAttribute_StateOrProvinceName(chip::CharSpan::fromCharString(arg), false); + if (err != CHIP_NO_ERROR) + { + fprintf(stderr, "Failed to add stateOrProvinceName attribute to the subject DN: %s\n", chip::ErrorStr(err)); + return false; + } + break; + case 'u': + err = gSubjectDN.AddAttribute_StateOrProvinceName(chip::CharSpan::fromCharString(arg), true); + if (err != CHIP_NO_ERROR) + { + fprintf(stderr, "Failed to add stateOrProvinceName attribute to the subject DN: %s\n", chip::ErrorStr(err)); + return false; + } + break; + case 'w': + err = gSubjectDN.AddAttribute_OrganizationName(chip::CharSpan::fromCharString(arg), false); + if (err != CHIP_NO_ERROR) + { + fprintf(stderr, "Failed to add Organization Name attribute to the subject DN: %s\n", chip::ErrorStr(err)); + return false; + } + break; + case 'y': + err = gSubjectDN.AddAttribute_OrganizationName(chip::CharSpan::fromCharString(arg), true); + if (err != CHIP_NO_ERROR) + { + fprintf(stderr, "Failed to add Organization Name attribute to the subject DN: %s\n", chip::ErrorStr(err)); + return false; + } + break; + case 'z': + err = gSubjectDN.AddAttribute_OrganizationalUnitName(chip::CharSpan::fromCharString(arg), false); + if (err != CHIP_NO_ERROR) + { + fprintf(stderr, "Failed to add Organizational Unit Name attribute to the subject DN: %s\n", chip::ErrorStr(err)); + return false; + } + break; + case 'U': + err = gSubjectDN.AddAttribute_OrganizationalUnitName(chip::CharSpan::fromCharString(arg), true); + if (err != CHIP_NO_ERROR) + { + fprintf(stderr, "Failed to add Organizational Unit Name attribute to the subject DN: %s\n", chip::ErrorStr(err)); + return false; + } + break; + case 'W': + err = gSubjectDN.AddAttribute_Title(chip::CharSpan::fromCharString(arg), false); + if (err != CHIP_NO_ERROR) + { + fprintf(stderr, "Failed to add Title attribute to the subject DN: %s\n", chip::ErrorStr(err)); + return false; + } + break; + case 'S': + err = gSubjectDN.AddAttribute_Title(chip::CharSpan::fromCharString(arg), true); + if (err != CHIP_NO_ERROR) + { + fprintf(stderr, "Failed to add Title attribute to the subject DN: %s\n", chip::ErrorStr(err)); + return false; + } + break; + case 'T': + err = gSubjectDN.AddAttribute_Name(chip::CharSpan::fromCharString(arg), false); + if (err != CHIP_NO_ERROR) + { + fprintf(stderr, "Failed to add Name attribute to the subject DN: %s\n", chip::ErrorStr(err)); + return false; + } + break; + case 'A': + err = gSubjectDN.AddAttribute_Name(chip::CharSpan::fromCharString(arg), true); + if (err != CHIP_NO_ERROR) + { + fprintf(stderr, "Failed to add Name attribute to the subject DN: %s\n", chip::ErrorStr(err)); + return false; + } + break; + case 'B': + err = gSubjectDN.AddAttribute_GivenName(chip::CharSpan::fromCharString(arg), false); + if (err != CHIP_NO_ERROR) + { + fprintf(stderr, "Failed to add Given Name attribute to the subject DN: %s\n", chip::ErrorStr(err)); + return false; + } + break; + case 'D': + err = gSubjectDN.AddAttribute_GivenName(chip::CharSpan::fromCharString(arg), true); + if (err != CHIP_NO_ERROR) + { + fprintf(stderr, "Failed to add Given Name attribute to the subject DN: %s\n", chip::ErrorStr(err)); + return false; + } + break; + case 'G': + err = gSubjectDN.AddAttribute_Initials(chip::CharSpan::fromCharString(arg), false); + if (err != CHIP_NO_ERROR) + { + fprintf(stderr, "Failed to add Initials attribute to the subject DN: %s\n", chip::ErrorStr(err)); + return false; + } + break; + case 'H': + err = gSubjectDN.AddAttribute_Initials(chip::CharSpan::fromCharString(arg), true); + if (err != CHIP_NO_ERROR) + { + fprintf(stderr, "Failed to add Initials attribute to the subject DN: %s\n", chip::ErrorStr(err)); + return false; + } + break; + case 'J': + err = gSubjectDN.AddAttribute_GenerationQualifier(chip::CharSpan::fromCharString(arg), false); + if (err != CHIP_NO_ERROR) + { + fprintf(stderr, "Failed to add Generation Qualifier attribute to the subject DN: %s\n", chip::ErrorStr(err)); + return false; + } + break; + case 'L': + err = gSubjectDN.AddAttribute_GenerationQualifier(chip::CharSpan::fromCharString(arg), true); + if (err != CHIP_NO_ERROR) + { + fprintf(stderr, "Failed to add Generation Qualifier attribute to the subject DN: %s\n", chip::ErrorStr(err)); + return false; + } + break; + case 'M': + err = gSubjectDN.AddAttribute_DNQualifier(chip::CharSpan::fromCharString(arg), false); + if (err != CHIP_NO_ERROR) + { + fprintf(stderr, "Failed to add DN Qualifier attribute to the subject DN: %s\n", chip::ErrorStr(err)); + return false; + } + break; + case 'N': + err = gSubjectDN.AddAttribute_DNQualifier(chip::CharSpan::fromCharString(arg), true); + if (err != CHIP_NO_ERROR) + { + fprintf(stderr, "Failed to add DN Qualifier attribute to the subject DN: %s\n", chip::ErrorStr(err)); + return false; + } + break; + case 'P': + err = gSubjectDN.AddAttribute_Pseudonym(chip::CharSpan::fromCharString(arg), false); + if (err != CHIP_NO_ERROR) + { + fprintf(stderr, "Failed to add Pseudonym attribute to the subject DN: %s\n", chip::ErrorStr(err)); + return false; + } + break; + case 'Q': + err = gSubjectDN.AddAttribute_Pseudonym(chip::CharSpan::fromCharString(arg), true); + if (err != CHIP_NO_ERROR) + { + fprintf(stderr, "Failed to add Pseudonym attribute to the subject DN: %s\n", chip::ErrorStr(err)); + return false; + } + break; + case 'R': + err = gSubjectDN.AddAttribute_DomainComponent(chip::CharSpan::fromCharString(arg), true); + if (err != CHIP_NO_ERROR) + { + fprintf(stderr, "Failed to add Domain Component attribute to the subject DN: %s\n", chip::ErrorStr(err)); + return false; + } + break; case 'x': gFutureExtensions[gFutureExtensionsCount].nid = NID_subject_alt_name; gFutureExtensions[gFutureExtensionsCount].info = arg;