From 62cb2b4ca945bd2d6c24c5bba98df6e5df398d10 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 19 May 2022 14:25:49 -0700 Subject: [PATCH 01/12] ASN.1 Additions for FPKI/CAC 1. Add some OIDs used in the Federal PKI Policy Authority standard. 2. Added the SubjectDirectoryAttributes extension to certificate parsing. (limited to country of citizenship) 3. Rename constant label SUBJECT_INFO_ACCESS to SUBJ_INFO_ACC_OID 4. Added the SubjectInfoAccess extension to certificate parsing. (limited to one URL) 5. Add the SSH extended key usage flags. 6. Use some of the template changes on the new certificate items. --- src/x509.c | 2 +- wolfcrypt/src/asn.c | 305 +++++++++++++++++++++++++++++++++++++++- wolfssl/wolfcrypt/asn.h | 74 +++++++++- 3 files changed, 373 insertions(+), 8 deletions(-) diff --git a/src/x509.c b/src/x509.c index a117a4308..9a3ccb727 100644 --- a/src/x509.c +++ b/src/x509.c @@ -2198,7 +2198,7 @@ void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509, int nid, int* c, WOLFSSL_MSG("Private Key Usage Period extension not supported"); break; - case SUBJECT_INFO_ACCESS: + case SUBJ_INFO_ACC_OID: WOLFSSL_MSG("Subject Info Access extension not supported"); break; diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index a84df1f52..8316c7828 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -80,6 +80,9 @@ ASN Options: extensions * WOLFSSL_HAVE_ISSUER_NAMES: Store pointers to issuer name components and their lengths and encodings. + * WOLFSSL_SUBJ_DIR_ATTR: Enable support for SubjectDirectoryAttributes + extension. + * WOLFSSL_SUBJ_INFO_ACC: Enable support for SubjectInfoAccess extension. */ #ifndef NO_ASN @@ -4053,13 +4056,33 @@ static const byte extExtKeyUsageOid[] = {85, 29, 37}; #ifdef HAVE_CRL static const byte extCrlNumberOid[] = {85, 29, 20}; #endif +#ifdef WOLFSSL_SUBJ_DIR_ATTR + static const byte extSubjDirAttrOid[] = {85, 29, 9}; +#endif +#ifdef WOLFSSL_SUBJ_INFO_ACC + static const byte extSubjInfoAccessOid[] = {43, 6, 1, 5, 5, 7, 1, 11}; +#endif /* certAuthInfoType */ static const byte extAuthInfoOcspOid[] = {43, 6, 1, 5, 5, 7, 48, 1}; static const byte extAuthInfoCaIssuerOid[] = {43, 6, 1, 5, 5, 7, 48, 2}; +#ifdef WOLFSSL_SUBJ_INFO_ACC + static const byte extAuthInfoCaRespOid[] = {43, 6, 1, 5, 5, 7, 48, 5}; +#endif /* WOLFSSL_SUBJ_INFO_ACC */ /* certPolicyType */ static const byte extCertPolicyAnyOid[] = {85, 29, 32, 0}; +#ifdef WOLFSSL_FPKI +#define CERT_POLICY_TYPE_OID_BASE(num) {96, 134, 72, 1, 101, 3, 2, 1, 3, num} + static const byte extCertPolicyFpkiCommonAuthOid[] = + CERT_POLICY_TYPE_OID_BASE(13); + static const byte extCertPolicyFpkiPivAuthOid[] = + CERT_POLICY_TYPE_OID_BASE(40); + static const byte extCertPolicyFpkiPivAuthHwOid[] = + CERT_POLICY_TYPE_OID_BASE(41); + static const byte extCertPolicyFpkiPiviAuthOid[] = + CERT_POLICY_TYPE_OID_BASE(45); +#endif /* WOLFSSL_FPKI */ /* certAltNameType */ static const byte extAltNamesHwNameOid[] = {43, 6, 1, 5, 5, 7, 8, 4}; @@ -4072,6 +4095,25 @@ static const byte extExtKeyUsageCodeSigningOid[] = {43, 6, 1, 5, 5, 7, 3, 3}; static const byte extExtKeyUsageEmailProtectOid[] = {43, 6, 1, 5, 5, 7, 3, 4}; static const byte extExtKeyUsageTimestampOid[] = {43, 6, 1, 5, 5, 7, 3, 8}; static const byte extExtKeyUsageOcspSignOid[] = {43, 6, 1, 5, 5, 7, 3, 9}; +#ifdef WOLFSSL_WOLFSSH +#define EXT_KEY_USAGE_OID_BASE(num) {43, 6, 1, 5, 5, 7, 3, num} + static const byte extExtKeyUsageSshClientAuthOid[] = + EXT_KEY_USAGE_OID_BASE(21); + static const byte extExtKeyUsageSshMSCLOid[] = + {43, 6, 1, 4, 1, 130, 55, 20, 2, 2}; + static const byte extExtKeyUsageSshKpClientAuthOid[] = + {43, 6, 1, 5, 2, 3, 4}; +#endif /* WOLFSSL_WOLFSSH */ + +#ifdef WOLFSSL_SUBJ_DIR_ATTR +#define SUBJ_DIR_ATTR_TYPE_OID_BASE(num) {43, 6, 1, 5, 5, 7, 9, num} + static const byte extSubjDirAttrDobOid[] = SUBJ_DIR_ATTR_TYPE_OID_BASE(1); + static const byte extSubjDirAttrPobOid[] = SUBJ_DIR_ATTR_TYPE_OID_BASE(2); + static const byte extSubjDirAttrGenderOid[] = + SUBJ_DIR_ATTR_TYPE_OID_BASE(3); + static const byte extSubjDirAttrCocOid[] = SUBJ_DIR_ATTR_TYPE_OID_BASE(4); + static const byte extSubjDirAttrCorOid[] = SUBJ_DIR_ATTR_TYPE_OID_BASE(5); +#endif #if defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_GEN) || \ defined(WOLFSSL_ASN_TEMPLATE) || defined(OPENSSL_EXTRA) || \ @@ -4627,6 +4669,18 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) oid = ocspNoCheckOid; *oidSz = sizeof(ocspNoCheckOid); break; + #endif + #ifdef WOLFSSL_SUBJ_DIR_ATTR + case SUBJ_DIR_ATTR_OID: + oid = extSubjDirAttrOid; + *oidSz = sizeof(extSubjDirAttrOid); + break; + #endif + #ifdef WOLFSSL_SUBJ_INFO_ACC + case SUBJ_INFO_ACC_OID: + oid = extSubjInfoAccessOid; + *oidSz = sizeof(extSubjInfoAccessOid); + break; #endif default: break; @@ -4660,6 +4714,11 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) oid = extAuthInfoCaIssuerOid; *oidSz = sizeof(extAuthInfoCaIssuerOid); break; + #ifdef WOLFSSL_SUBJ_INFO_ACC + case AIA_CA_REPO_OID: + oid = extAuthInfoCaRespOid; + *oidSz = sizeof(extAuthInfoCaRespOid); + #endif /* WOLFSSL_SUBJ_INFO_ACC */ default: break; } @@ -4671,6 +4730,24 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) oid = extCertPolicyAnyOid; *oidSz = sizeof(extCertPolicyAnyOid); break; + #if defined(WOLFSSL_FPKI) + case CP_FPKI_COMMON_AUTH_OID: + oid = extCertPolicyFpkiCommonAuthOid; + *oidSz = sizeof(extCertPolicyFpkiCommonAuthOid); + break; + case CP_FPKI_PIV_AUTH_OID: + oid = extCertPolicyFpkiPivAuthOid; + *oidSz = sizeof(extCertPolicyFpkiPivAuthOid); + break; + case CP_FPKI_PIV_AUTH_HW_OID: + oid = extCertPolicyFpkiPivAuthHwOid; + *oidSz = sizeof(extCertPolicyFpkiPivAuthHwOid); + break; + case CP_FPKI_PIVI_AUTH_OID: + oid = extCertPolicyFpkiPiviAuthOid; + *oidSz = sizeof(extCertPolicyFpkiPiviAuthOid); + break; + #endif /* WOLFSSL_FPKI */ default: break; } @@ -4717,6 +4794,20 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) oid = extExtKeyUsageOcspSignOid; *oidSz = sizeof(extExtKeyUsageOcspSignOid); break; + #ifdef WOLFSSL_WOLFSSH + case EKU_SSH_CLIENT_AUTH_OID: + oid = extExtKeyUsageSshClientAuthOid; + *oidSz = sizeof(extExtKeyUsageSshClientAuthOid); + break; + case EKU_SSH_MSCL_OID: + oid = extExtKeyUsageSshMSCLOid; + *oidSz = sizeof(extExtKeyUsageSshMSCLOid); + break; + case EKU_SSH_KP_CLIENT_AUTH_OID: + oid = extExtKeyUsageSshKpClientAuthOid; + *oidSz = sizeof(extExtKeyUsageSshKpClientAuthOid); + break; + #endif /* WOLFSSL_WOLFSSH */ default: break; } @@ -4942,6 +5033,34 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) } break; #endif +#ifdef WOLFSSL_SUBJ_DIR_ATTR + case oidSubjDirAttrType: + switch (id) { + case SDA_DOB_OID: + oid = extSubjDirAttrDobOid; + *oidSz = sizeof(extSubjDirAttrDobOid); + break; + case SDA_POB_OID: + oid = extSubjDirAttrPobOid; + *oidSz = sizeof(extSubjDirAttrPobOid); + break; + case SDA_GENDER_OID: + oid = extSubjDirAttrGenderOid; + *oidSz = sizeof(extSubjDirAttrGenderOid); + break; + case SDA_COC_OID: + oid = extSubjDirAttrCocOid; + *oidSz = sizeof(extSubjDirAttrCocOid); + break; + case SDA_COR_OID: + oid = extSubjDirAttrCorOid; + *oidSz = sizeof(extSubjDirAttrCorOid); + break; + default: + break; + } + break; +#endif /* WOLFSSL_SUBJ_DIR_ATTR */ case oidIgnoreType: default: break; @@ -15961,6 +16080,17 @@ static int DecodeExtKeyUsage(const byte* input, int sz, DecodedCert* cert) case EKU_OCSP_SIGN_OID: cert->extExtKeyUsage |= EXTKEYUSE_OCSP_SIGN; break; + #ifdef WOLFSSL_WOLFSSH + case EKU_SSH_CLIENT_AUTH_OID: + cert->extExtKeyUsageSsh |= EXTKEYUSE_SSH_CLIENT_AUTH; + break; + case EKU_SSH_MSCL_OID: + cert->extExtKeyUsageSsh |= EXTKEYUSE_SSH_MSCL; + break; + case EKU_SSH_KP_CLIENT_AUTH_OID: + cert->extExtKeyUsageSsh |= EXTKEYUSE_SSH_KP_CLIENT_AUTH; + break; + #endif /* WOLFSSL_WOLFSSH */ default: break; } @@ -16696,6 +16826,163 @@ exit: } #endif /* WOLFSSL_SEP */ +#ifdef WOLFSSL_SUBJ_DIR_ATTR +/* Decode subject directory attributes extension in a certificate. + * + * X.509: RFC 5280, 4.2.1.8 - Subject Directory Attributes. + * + * @param [in] input Buffer holding data. + * @param [in] sz Size of data in buffer. + * @param [in, out] cert Certificate object. + * @return 0 on success. + * @return ASN_PARSE_E when BER encoded data does not match ASN.1 items or + * is invalid. + */ +static int DecodeSubjDirAttr(const byte* input, int sz, DecodedCert* cert) +{ + word32 idx = 0; + int length = 0; + int ret = 0; + + WOLFSSL_ENTER("DecodeSubjDirAttr"); + +#ifdef OPENSSL_ALL + cert->extSubjDirAttrSrc = input; + cert->extSubjDirAttrSz = sz; +#endif /* OPENSSL_ALL */ + + /* Unwrap the list of Attributes */ + if (GetSequence(input, &idx, &length, sz) < 0) + return ASN_PARSE_E; + + if (length == 0) { + /* RFC 5280 4.2.1.8. Subject Directory Attributes + If the subjectDirectoryAttributes extension is present, the + sequence MUST contain at least one entry. */ + return ASN_PARSE_E; + } + + /* length is the length of the list contents */ + while (idx < (word32)sz) { + word32 oid; + + if (GetSequence(input, &idx, &length, sz) < 0) + return ASN_PARSE_E; + + if (GetObjectId(input, &idx, &oid, oidSubjDirAttrType, sz) < 0) + return ASN_PARSE_E; + + if (GetSet(input, &idx, &length, sz) < 0) + return ASN_PARSE_E; + + /* There may be more than one countryOfCitizenship, but save the + * first one for now. */ + if (oid == SDA_COC_OID) { + byte tag; + + if (GetHeader(input, &tag, &idx, &length, sz, 1) < 0) + return ASN_PARSE_E; + + if (length != COUNTRY_CODE_LEN) + return ASN_PARSE_E; + + if (tag == ASN_PRINTABLE_STRING) { + XMEMCPY(cert->countryOfCitizenship, + input + idx, COUNTRY_CODE_LEN); + cert->countryOfCitizenship[COUNTRY_CODE_LEN] = 0; + } + } + idx += length; + } + + return ret; +} +#endif /* WOLFSSL_SUBJ_DIR_ATTR */ + +#ifdef WOLFSSL_SUBJ_INFO_ACC +/* Decode subject infomation access extension in a certificate. + * + * X.509: RFC 5280, 4.2.2.2 - Subject Information Access. + * + * @param [in] input Buffer holding data. + * @param [in] sz Size of data in buffer. + * @param [in, out] cert Certificate object. + * @return 0 on success. + * @return ASN_BITSTR_E when the expected BIT_STRING tag is not found. + * @return ASN_PARSE_E when BER encoded data does not match ASN.1 items or + * is invalid. + * @return MEMORY_E on dynamic memory allocation failure. + */ +static int DecodeSubjInfoAcc(const byte* input, int sz, DecodedCert* cert) +{ + word32 idx = 0; + int length = 0; + int ret = 0; + + WOLFSSL_ENTER("DecodeSubjInfoAcc"); + +#ifdef OPENSSL_ALL + cert->extSubjAltNameSrc = input; + cert->extSubjAltNameSz = sz; +#endif /* OPENSSL_ALL */ + + /* Unwrap SubjectInfoAccessSyntax, the list of AccessDescriptions */ + if (GetSequence(input, &idx, &length, sz) < 0) + return ASN_PARSE_E; + + if (length == 0) { + /* RFC 5280 4.2.2.2. Subject Information Access + If the subjectInformationAccess extension is present, the + sequence MUST contain at least one entry. */ + return ASN_PARSE_E; + } + + /* Per fpkx-x509-cert-profile-common... section 5.3. + * [The] subjectInfoAccess extension must contain at least one + * instance of the id-ad-caRepository access method containing a + * publicly accessible HTTP URI which returns as certs-only + * CMS. + */ + + while (idx < (word32)sz) { + word32 oid; + byte b; + + /* Unwrap an AccessDescription */ + if (GetSequence(input, &idx, &length, sz) < 0) + return ASN_PARSE_E; + + /* Get the accessMethod */ + if (GetObjectId(input, &idx, &oid, oidCertAuthInfoType, sz) < 0) + return ASN_PARSE_E; + + /* Only supporting URIs right now. */ + if (GetASNTag(input, &idx, &b, sz) < 0) + return ASN_PARSE_E; + + if (GetLength(input, &idx, &length, sz) < 0) + return ASN_PARSE_E; + + /* Set ocsp entry */ + if (b == GENERALNAME_URI && oid == AIA_OCSP_OID) { + cert->extSubjInfoAccCaRepoSz = length; + cert->extSubjInfoAccCaRepo = input + idx; + break; + } + idx += length; + } + + if (cert->extSubjInfoAccCaRepo == NULL || + cert->extSubjInfoAccCaRepoSz == 0) { + WOLFSSL_MSG("SubjectInfoAccess missing an URL."); + ret = ASN_PARSE_E; + } + + WOLFSSL_LEAVE("DecodeSubjInfoAcc", ret); + return ret; +} +#endif /* WOLFSSL_SUBJ_INFO_ACC */ + /* Macro to check if bit is set, if not sets and return success. Otherwise returns failure */ /* Macro required here because bit-field operation */ @@ -16726,13 +17013,13 @@ exit: * Inhibit anyPolicy - INHIBIT_ANY_OID * Netscape Certificate Type - NETSCAPE_CT_OID (able to be excluded) * OCSP no check - OCSP_NOCHECK_OID (when compiling OCSP) + * Subject Directory Attributes - SUBJ_DIR_ATTR_OID + * Subject Information Access - SUBJ_INFO_ACC_OID * Unsupported extensions from RFC 5280: * 4.2.1.5 - Policy mappings * 4.2.1.7 - Issuer Alternative Name - * 4.2.1.8 - Subject Directory Attributes * 4.2.1.11 - Policy Constraints * 4.2.1.15 - Freshest CRL - * 4.2.2.2 - Subject Information Access * * @param [in] input Buffer containing extension type specific data. * @param [in] length Length of data. @@ -16916,6 +17203,20 @@ static int DecodeExtensionType(const byte* input, int length, word32 oid, if (DecodePolicyConstraints(&input[idx], length, cert) < 0) return ASN_PARSE_E; break; + #ifdef WOLFSSL_SUBJ_DIR_ATTR + case SUBJ_DIR_ATTR_OID: + VERIFY_AND_SET_OID(cert->extSubjDirAttrSet); + if (DecodeSubjDirAttr(&input[idx], length, cert) < 0) + return ASN_PARSE_E; + break; + #endif + #ifdef WOLFSSL_SUBJ_INFO_ACC + case SUBJ_INFO_ACC_OID: + VERIFY_AND_SET_OID(cert->extSubjInfoAccSet); + if (DecodeSubjInfoAcc(&input[idx], length, cert) < 0) + return ASN_PARSE_E; + break; + #endif default: if (isUnknownExt != NULL) *isUnknownExt = 1; diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 97d154a0f..1a20e349b 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -974,6 +974,8 @@ enum Misc_ASN { PEM_LINE_SZ = 64, /* Length of Base64 encoded line, not including new line */ PEM_LINE_LEN = PEM_LINE_SZ + 12, /* PEM line max + fudge */ + + COUNTRY_CODE_LEN = 2, /* RFC 3739 */ }; #ifndef WC_MAX_NAME_ENTRIES @@ -1009,6 +1011,9 @@ enum Oid_Types { oidTlsExtType = 18, oidCrlExtType = 19, oidCsrAttrType = 20, +#ifdef WOLFSSL_SUBJ_DIR_ATTR + oidSubjDirAttrType = 21, +#endif oidIgnoreType }; @@ -1128,7 +1133,7 @@ enum Extensions_Sum { EXT_KEY_USAGE_OID = 151, /* 2.5.29.37 */ NAME_CONS_OID = 144, /* 2.5.29.30 */ PRIV_KEY_USAGE_PERIOD_OID = 130, /* 2.5.29.16 */ - SUBJECT_INFO_ACCESS = 79, /* 1.3.6.1.5.5.7.1.11 */ + SUBJ_INFO_ACC_OID = 79, /* 1.3.6.1.5.5.7.1.11 */ POLICY_MAP_OID = 147, /* 2.5.29.33 */ POLICY_CONST_OID = 150, /* 2.5.29.36 */ ISSUE_ALT_NAMES_OID = 132, /* 2.5.29.18 */ @@ -1136,13 +1141,20 @@ enum Extensions_Sum { NETSCAPE_CT_OID = 753, /* 2.16.840.1.113730.1.1 */ OCSP_NOCHECK_OID = 121, /* 1.3.6.1.5.5.7.48.1.5 id-pkix-ocsp-nocheck */ + SUBJ_DIR_ATTR_OID = 123, /* 2.5.29.9 */ AKEY_PACKAGE_OID = 1048 /* 2.16.840.1.101.2.1.2.78.5 RFC 5958 - Asymmetric Key Packages */ }; enum CertificatePolicy_Sum { - CP_ANY_OID = 146 /* id-ce 32 0 */ + CP_ANY_OID = 146, /* id-ce 32 0 */ +#ifdef WOLFSSL_FPKI + CP_FPKI_COMMON_AUTH_OID = 426, /* 2.16.840.1.101.3.2.1.3.13 */ + CP_FPKI_PIV_AUTH_OID = 453, /* 2.16.840.1.101.3.2.1.3.40 */ + CP_FPKI_PIV_AUTH_HW_OID = 454, /* 2.16.840.1.101.3.2.1.3.41 */ + CP_FPKI_PIVI_AUTH_OID = 458 /* 2.16.840.1.101.3.2.1.3.45 */ +#endif /* WOLFSSL_FPKI */ }; enum SepHardwareName_Sum { @@ -1150,10 +1162,15 @@ enum SepHardwareName_Sum { }; enum AuthInfo_Sum { - AIA_OCSP_OID = 116, /* 1.3.6.1.5.5.7.48.1 */ - AIA_CA_ISSUER_OID = 117 /* 1.3.6.1.5.5.7.48.2 */ + AIA_OCSP_OID = 116, /* 1.3.6.1.5.5.7.48.1, id-ad-ocsp */ + AIA_CA_ISSUER_OID = 117, /* 1.3.6.1.5.5.7.48.2, id-ad-caIssuers */ + #ifdef WOLFSSL_SUBJ_INFO_ACC + AIA_CA_REPO_OID = 120 /* 1.3.6.1.5.5.7.48.5, id-ad-caRepository */ + #endif /* WOLFSSL_SUBJ_INFO_ACC */ }; +#define ID_PKIX(num) (67+(num)) /* 1.3.6.1.5.5.7.num, id-pkix num */ +#define ID_KP(num) (ID_PKIX(3)+(num)) /* 1.3.6.1.5.5.7.3.num, id-kp num */ enum ExtKeyUsage_Sum { /* From RFC 5280 */ EKU_ANY_OID = 151, /* 2.5.29.37.0, anyExtendedKeyUsage */ EKU_SERVER_AUTH_OID = 71, /* 1.3.6.1.5.5.7.3.1, id-kp-serverAuth */ @@ -1161,9 +1178,27 @@ enum ExtKeyUsage_Sum { /* From RFC 5280 */ EKU_CODESIGNING_OID = 73, /* 1.3.6.1.5.5.7.3.3, id-kp-codeSigning */ EKU_EMAILPROTECT_OID = 74, /* 1.3.6.1.5.5.7.3.4, id-kp-emailProtection */ EKU_TIMESTAMP_OID = 78, /* 1.3.6.1.5.5.7.3.8, id-kp-timeStamping */ - EKU_OCSP_SIGN_OID = 79 /* 1.3.6.1.5.5.7.3.9, id-kp-OCSPSigning */ + EKU_OCSP_SIGN_OID = 79, /* 1.3.6.1.5.5.7.3.9, id-kp-OCSPSigning */ + + /* From RFC 6187: X.509v3 Certificates for Secure Shell Authenticaiton */ + EKU_SSH_CLIENT_AUTH_OID = ID_KP(21), /* id-kp-secureShellClient */ + EKU_SSH_MSCL_OID = 264, + /* 1.3.6.1.4.1.311.20.2.2, MS Smart Card Logon */ + EKU_SSH_KP_CLIENT_AUTH_OID = 64 + /* 1.3.6.1.5.2.3.4, id-pkinit-KPClientAuth*/ }; +#ifdef WOLFSSL_SUBJ_DIR_ATTR +#define ID_PDA(num) (ID_PKIX(9)+(num)) /* 1.3.6.1.5.5.7.9.num, id-pda num */ +enum SubjDirAttr_Sum { /* From RFC 3739, section 3.3.2 */ + SDA_DOB_OID = ID_PDA(1), /* id-pda-dateOfBirth */ + SDA_POB_OID = ID_PDA(2), /* id-pda-placeOfBirth */ + SDA_GENDER_OID = ID_PDA(3), /* id-pda-gender */ + SDA_COC_OID = ID_PDA(4), /* id-pda-countryOfCitizenship */ + SDA_COR_OID = ID_PDA(5) /* id-pda-countryOfResidence */ +}; +#endif /* WOLFSSL_SUBJ_DIR_ATTR */ + #ifdef HAVE_LIBZ enum CompressAlg_Sum { ZLIBc = 679 /* 1.2.840.113549.1.9.16.3.8, id-alg-zlibCompress */ @@ -1218,6 +1253,11 @@ enum CsrAttrType { #define EXTKEYUSE_CLIENT_AUTH 0x04 #define EXTKEYUSE_SERVER_AUTH 0x02 #define EXTKEYUSE_ANY 0x01 +#ifdef WOLFSSL_WOLFSSH + #define EXTKEYUSE_SSH_CLIENT_AUTH 0x01 + #define EXTKEYUSE_SSH_MSCL 0x02 + #define EXTKEYUSE_SSH_KP_CLIENT_AUTH 0x04 +#endif /* WOLFSSL_WOLFSSH */ #define WC_NS_SSL_CLIENT 0x80 #define WC_NS_SSL_SERVER 0x40 @@ -1530,6 +1570,9 @@ struct DecodedCert { byte policyConstSkip; /* Policy Constraints skip certs value */ word16 extKeyUsage; /* Key usage bitfield */ byte extExtKeyUsage; /* Extended Key usage bitfield */ +#ifdef WOLFSSL_WOLFSSH + byte extExtKeyUsageSsh; /* Extended Key Usage bitfield for SSH */ +#endif /* WOLFSSL_WOLFSSH */ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) const byte* extExtKeyUsageSrc; @@ -1548,6 +1591,21 @@ struct DecodedCert { const byte* extSubjAltNameSrc; word32 extSubjAltNameSz; #endif +#ifdef WOLFSSL_SUBJ_DIR_ATTR + char countryOfCitizenship[COUNTRY_CODE_LEN+1]; /* ISO 3166 Country Code */ + #ifdef OPENSSL_ALL + const byte* extSubjDirAttrSrc; + word32 extSubjDirAttrSz; + #endif +#endif /* WOLFSSL_SUBJ_DIR_ATTR */ +#ifdef WOLFSSL_SUBJ_INFO_ACC + const byte* extSubjInfoAccCaRepo; + word32 extSubjInfoAccCaRepoSz; + #ifdef OPENSSL_ALL + const byte* extSubjInfoAccSrc; + word32 extSubjInfoAccSz; + #endif +#endif /* WOLFSSL_SUBJ_INFO_ACC */ #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) word32 pkCurveOID; /* Public Key's curve OID */ @@ -1717,6 +1775,12 @@ struct DecodedCert { byte extSubjKeyIdCrit : 1; byte extKeyUsageCrit : 1; byte extExtKeyUsageCrit : 1; +#ifdef WOLFSSL_SUBJ_DIR_ATTR + byte extSubjDirAttrSet : 1; +#endif +#ifdef WOLFSSL_SUBJ_INFO_ACC + byte extSubjInfoAccSet : 1; +#endif #if defined(WOLFSSL_SEP) || defined(WOLFSSL_QT) byte extCertPolicyCrit : 1; #endif From 9e4de4bfc8241e1e343e4af1dbce88192b5426b0 Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Sun, 22 May 2022 08:18:36 -0700 Subject: [PATCH 02/12] add FASC-N and UUID alt. name support --- wolfcrypt/src/asn.c | 301 +++++++++++++++++++++++++-------- wolfssl/wolfcrypt/asn.h | 6 +- wolfssl/wolfcrypt/asn_public.h | 6 + 3 files changed, 244 insertions(+), 69 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 8316c7828..0dac03e07 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -14815,6 +14815,130 @@ enum { #define altNameASN_Length (sizeof(altNameASN) / sizeof(ASNItem)) #endif /* WOLFSSL_ASN_TEMPLATE */ +#ifdef WOLFSSL_SEP +/* return 0 on success */ +static int DecodeSepHwAltName(DecodedCert* cert, const byte* input, + word32* idxIn, int sz) +{ + word32 idx = *idxIn; + int strLen; + int ret; + byte tag; + + /* Certificates issued with this OID in the subject alt name are for + * verifying signatures created on a module. + * RFC 4108 Section 5. */ + if (cert->hwType != NULL) { + WOLFSSL_MSG("\tAlready seen Hardware Module Name"); + return ASN_PARSE_E; + } + + if (GetASNTag(input, &idx, &tag, sz) < 0) { + return ASN_PARSE_E; + } + + if (tag != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) { + WOLFSSL_MSG("\twrong type"); + return ASN_PARSE_E; + } + + if (GetLength(input, &idx, &strLen, sz) < 0) { + WOLFSSL_MSG("\tfail: str len"); + return ASN_PARSE_E; + } + + if (GetSequence(input, &idx, &strLen, sz) < 0) { + WOLFSSL_MSG("\tBad Sequence"); + return ASN_PARSE_E; + } + + ret = GetASNObjectId(input, &idx, &strLen, sz); + if (ret != 0) { + WOLFSSL_MSG("\tbad OID"); + return ret; + } + + cert->hwType = (byte*)XMALLOC(strLen, cert->heap, + DYNAMIC_TYPE_X509_EXT); + if (cert->hwType == NULL) { + WOLFSSL_MSG("\tOut of Memory"); + return MEMORY_E; + } + + XMEMCPY(cert->hwType, &input[idx], strLen); + cert->hwTypeSz = strLen; + idx += strLen; + + ret = GetOctetString(input, &idx, &strLen, sz); + if (ret < 0) + return ret; + + cert->hwSerialNum = (byte*)XMALLOC(strLen + 1, cert->heap, + DYNAMIC_TYPE_X509_EXT); + if (cert->hwSerialNum == NULL) { + WOLFSSL_MSG("\tOut of Memory"); + return MEMORY_E; + } + + XMEMCPY(cert->hwSerialNum, &input[idx], strLen); + cert->hwSerialNum[strLen] = '\0'; + cert->hwSerialNumSz = strLen; + idx += strLen; + + *idxIn = idx; + return 0; +} +#endif /* WOLFSSL_SEP */ + +#ifdef WOLFSSL_FPKI +/* return 0 on success */ +static int DecodeFascNAltName(DecodedCert* cert, const byte* input, word32* idx, + int sz) +{ + int ret; + int strLen; + DNS_entry* dnsEntry; + byte tag; + + if (GetASNTag(input, idx, &tag, sz) < 0) { + return ASN_PARSE_E; + } + + if (tag != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) { + return ASN_PARSE_E; + } + + if (GetLength(input, idx, &strLen, sz) < 0) + return ASN_PARSE_E; + + ret = GetOctetString(input, idx, &strLen, sz); + if (ret < 0) + return ret; + + dnsEntry = AltNameNew(cert->heap); + if (dnsEntry == NULL) { + WOLFSSL_MSG("\tOut of Memory"); + return MEMORY_E; + } + + dnsEntry->type = ASN_OTHER_TYPE; + dnsEntry->name = (char*)XMALLOC(strLen + 1, cert->heap, + DYNAMIC_TYPE_ALTNAME); + if (dnsEntry->name == NULL) { + WOLFSSL_MSG("\tOut of Memory"); + XFREE(dnsEntry, cert->heap, DYNAMIC_TYPE_ALTNAME); + return MEMORY_E; + } + dnsEntry->len = strLen; + XMEMCPY(dnsEntry->name, &input[*idx], strLen); + dnsEntry->name[strLen] = '\0'; + dnsEntry->oidSum = FASCN_OID; + AddAltName(cert, dnsEntry); + *idx += strLen; + return 0; +} +#endif /* WOLFSSL_FPKI */ + /* Decode subject alternative names extension. * * RFC 5280 4.2.1.6. Subject Alternative Name @@ -14931,7 +15055,6 @@ static int DecodeAltNames(const byte* input, int sz, DecodedCert* cert) dirEntry->len = strLen; XMEMCPY(dirEntry->name, &input[idx], strLen); dirEntry->name[strLen] = '\0'; - dirEntry->next = cert->altDirNames; cert->altDirNames = dirEntry; @@ -14990,7 +15113,7 @@ static int DecodeAltNames(const byte* input, int sz, DecodedCert* cert) return BUFFER_E; } - #ifndef WOLFSSL_NO_ASN_STRICT + #if !defined(WOLFSSL_NO_ASN_STRICT) && !defined(WOLFSSL_FPKI) /* Verify RFC 5280 Sec 4.2.1.6 rule: "The name MUST NOT be a relative URI" */ @@ -15091,14 +15214,12 @@ static int DecodeAltNames(const byte* input, int sz, DecodedCert* cert) } #endif /* WOLFSSL_QT || OPENSSL_ALL */ #endif /* IGNORE_NAME_CONSTRAINTS */ -#ifdef WOLFSSL_SEP else if (b == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | ASN_OTHER_TYPE)) { int strLen; word32 lenStartIdx = idx; word32 oid = 0; int ret; - byte tag; if (GetLength(input, &idx, &strLen, sz) < 0) { WOLFSSL_MSG("\tfail: other name length"); @@ -15112,72 +15233,34 @@ static int DecodeAltNames(const byte* input, int sz, DecodedCert* cert) return ASN_PARSE_E; } - if (oid != HW_NAME_OID) { - WOLFSSL_MSG("\tincorrect OID"); - return ASN_PARSE_E; + /* handle parsing other type alt names */ + switch (oid) { + #ifdef WOLFSSL_SEP + case HW_NAME_OID: + ret = DecodeSepHwAltName(cert, input, &idx, sz); + if (ret != 0) + return ret; + break; + #endif /* WOLFSSL_SEP */ + #ifdef WOLFSSL_FPKI + case FASCN_OID: + ret = DecodeFascNAltName(cert, input, &idx, sz); + if (ret != 0) + return ret; + break; + #endif /* WOLFSSL_FPKI */ + + default: + WOLFSSL_MSG("\tUnsupported other name type, skipping"); + if (GetLength(input, &idx, &strLen, sz) < 0) { + WOLFSSL_MSG("\tfail: unsupported other name length"); + return ASN_PARSE_E; + } + length -= (strLen + idx - lenStartIdx); + idx += strLen; } - - /* Certificates issued with this OID in the subject alt name are for - * verifying signatures created on a module. - * RFC 4108 Section 5. */ - if (cert->hwType != NULL) { - WOLFSSL_MSG("\tAlready seen Hardware Module Name"); - return ASN_PARSE_E; - } - - if (GetASNTag(input, &idx, &tag, sz) < 0) { - return ASN_PARSE_E; - } - - if (tag != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) { - WOLFSSL_MSG("\twrong type"); - return ASN_PARSE_E; - } - - if (GetLength(input, &idx, &strLen, sz) < 0) { - WOLFSSL_MSG("\tfail: str len"); - return ASN_PARSE_E; - } - - if (GetSequence(input, &idx, &strLen, sz) < 0) { - WOLFSSL_MSG("\tBad Sequence"); - return ASN_PARSE_E; - } - - ret = GetASNObjectId(input, &idx, &strLen, sz); - if (ret != 0) { - WOLFSSL_MSG("\tbad OID"); - return ret; - } - - cert->hwType = (byte*)XMALLOC(strLen, cert->heap, - DYNAMIC_TYPE_X509_EXT); - if (cert->hwType == NULL) { - WOLFSSL_MSG("\tOut of Memory"); - return MEMORY_E; - } - - XMEMCPY(cert->hwType, &input[idx], strLen); - cert->hwTypeSz = strLen; - idx += strLen; - - ret = GetOctetString(input, &idx, &strLen, sz); - if (ret < 0) - return ret; - - cert->hwSerialNum = (byte*)XMALLOC(strLen + 1, cert->heap, - DYNAMIC_TYPE_X509_EXT); - if (cert->hwSerialNum == NULL) { - WOLFSSL_MSG("\tOut of Memory"); - return MEMORY_E; - } - - XMEMCPY(cert->hwSerialNum, &input[idx], strLen); - cert->hwSerialNum[strLen] = '\0'; - cert->hwSerialNumSz = strLen; - idx += strLen; + (void)ret; } - #endif /* WOLFSSL_SEP */ else { int strLen; word32 lenStartIdx = idx; @@ -20997,6 +21080,88 @@ int wc_GetPubKeyDerFromCert(struct DecodedCert* cert, return ret; } +#ifdef WOLFSSL_FPKI +/* Search through list for first matching alt name of the same type + * If 'current' is null then the search starts at the head of the list + * otherwise the search starts from the node after 'current' alt name. + * Returns 0 on success + */ +static DNS_entry* wc_GetAltName(struct DecodedCert* cert, int nameType, + DNS_entry* current) +{ + DNS_entry* entry; + + if (current == NULL) { + entry = cert->altNames; + } + else { + entry = current->next; + } + + /* cycle through alt names to check for needed types */ + while (entry != NULL) { + if (entry->type == nameType) { + break; + } + entry = entry->next; + } + + return entry; +} + + +/* returns 0 on success */ +int wc_GetUUIDFromCert(struct DecodedCert* cert, byte* uuid, word32* uuidSz) +{ + int ret = ALT_NAME_E; + DNS_entry* id = NULL; + + id = wc_GetAltName(cert, ASN_URI_TYPE, id); + if (id != NULL) { + if (uuid == NULL) { + *uuidSz = id->len; + return LENGTH_ONLY_E; + } + + if ((int)*uuidSz < id->len) { + return BUFFER_E; + } + + XMEMCPY(uuid, id->name, id->len); + ret = 0; /* success */ + } + + return ret; +} + + +/* reutrns 0 on success */ +int wc_GetFASCNFromCert(struct DecodedCert* cert, byte* fascn, word32* fascnSz) +{ + int ret = ALT_NAME_E; + DNS_entry* id = NULL; + + do { + id = wc_GetAltName(cert, ASN_OTHER_TYPE, id); + if (id != NULL && id->oidSum == FASCN_OID) { + if (fascn == NULL) { + *fascnSz = id->len; + return LENGTH_ONLY_E; + } + + if ((int)*fascnSz < id->len) { + return BUFFER_E; + } + + XMEMCPY(fascn, id->name, id->len); + ret = 0; /* success */ + } + } while (id != NULL); + + return ret; +} +#endif /* WOLFSSL_FPKI */ + #if !defined(NO_RSA) && (defined(WOLFSSL_CERT_GEN) || \ defined(WOLFSSL_KCAPI_RSA) || \ ((defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)) && !defined(HAVE_USER_RSA))) diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 1a20e349b..cdb481d81 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -1143,8 +1143,9 @@ enum Extensions_Sum { id-pkix-ocsp-nocheck */ SUBJ_DIR_ATTR_OID = 123, /* 2.5.29.9 */ - AKEY_PACKAGE_OID = 1048 /* 2.16.840.1.101.2.1.2.78.5 + AKEY_PACKAGE_OID = 1048, /* 2.16.840.1.101.2.1.2.78.5 RFC 5958 - Asymmetric Key Packages */ + FASCN_OID = 419 /* 2.16.840.1.101.3.6.6 Federal PKI Policy FASC-N */ }; enum CertificatePolicy_Sum { @@ -1287,6 +1288,9 @@ struct DNS_entry { #if defined(OPENSSL_ALL) || defined(WOLFSSL_IP_ALT_NAME) char* ipString; /* human readable form of IP address */ #endif +#ifdef WOLFSSL_FPKI + int oidSum; /* provid oid sum for verification */ +#endif }; diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index 58ddf6476..eec95a387 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -826,6 +826,12 @@ WOLFSSL_API int wc_ParseCert( WOLFSSL_API int wc_GetPubKeyDerFromCert(struct DecodedCert* cert, byte* derKey, word32* derKeySz); +#ifdef WOLFSSL_FPKI +WOLFSSL_API int wc_GetUUIDFromCert(struct DecodedCert* cert, + byte* uuid, word32* uuidSz); +WOLFSSL_API int wc_GetFASCNFromCert(struct DecodedCert* cert, + byte* fascn, word32* fascnSz); +#endif /* WOLFSSL_FPKI */ #ifdef __cplusplus } /* extern "C" */ #endif From cdfdefe9afd9a480b11a05b823d4881198994d8c Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Sun, 22 May 2022 14:09:14 -0700 Subject: [PATCH 03/12] improve checking on UUID getter function --- wolfcrypt/src/asn.c | 36 ++++++++++++++++++++++++------------ wolfssl/wolfcrypt/asn.h | 4 ++++ 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 0dac03e07..2bb458466 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -21116,20 +21116,32 @@ int wc_GetUUIDFromCert(struct DecodedCert* cert, byte* uuid, word32* uuidSz) int ret = ALT_NAME_E; DNS_entry* id = NULL; - id = wc_GetAltName(cert, ASN_URI_TYPE, id); - if (id != NULL) { - if (uuid == NULL) { - *uuidSz = id->len; - return LENGTH_ONLY_E; - } + do { + id = wc_GetAltName(cert, ASN_URI_TYPE, id); + if (id != NULL) { + /* check if URI string matches expected format for UUID */ + if (id->len != DEFAULT_UUID_SZ) { + continue; /* size not right not a UUID URI */ + } - if ((int)*uuidSz < id->len) { - return BUFFER_E; - } + if (XMEMCMP(id->name, "urn:uuid:", 9) != 0) { + continue; /* beginning text not right for a UUID URI */ + } - XMEMCPY(uuid, id->name, id->len); - ret = 0; /* success */ - } + if (uuid == NULL) { + *uuidSz = id->len; + return LENGTH_ONLY_E; + } + + if ((int)*uuidSz < id->len) { + return BUFFER_E; + } + + XMEMCPY(uuid, id->name, id->len); + ret = 0; /* success */ + break; + } + } while (id != NULL); return ret; } diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index cdb481d81..6c053e8fc 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -1293,6 +1293,10 @@ struct DNS_entry { #endif }; +#ifdef WOLFSSL_FPKI + /* RFC4122 i.e urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6 */ + #define DEFAULT_UUID_SZ 45 +#endif typedef struct Base_entry Base_entry; From 36db5ef9290510b8860e71afd078503841e0f41e Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Mon, 23 May 2022 09:17:42 -0700 Subject: [PATCH 04/12] add test case for UUID and FASC-N --- certs/fpki-cert.der | Bin 0 -> 1327 bytes certs/include.am | 3 ++- certs/renewcerts.sh | 15 +++++++++++++ certs/renewcerts/wolfssl.cnf | 36 ++++++++++++++++++++++++++++++ configure.ac | 3 +++ tests/api.c | 42 ++++++++++++++++++++++++++++++++++- 6 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 certs/fpki-cert.der diff --git a/certs/fpki-cert.der b/certs/fpki-cert.der new file mode 100644 index 0000000000000000000000000000000000000000..9d35ad9d5132816e2d173fa025bfae698476ff4c GIT binary patch literal 1327 zcmXqLV%0WiVi8`z%*4pV#K>sC%f_kI=F#?@mywa1mBFBKiXpcFCmVAp3!5-gXt1Gx z0UwCN!NcyGpI4HYmk1MK=V5osuS(5L%rg`;;0LMU;^7EREHBB=FUc?zHV^~}ar1CF z=jRod=9FaSr5j2Zh=Bx|dHBoA%k|3hbJB{7bM%t)a}DJUWZ}->WE2y~%uCC6KvG~J zC(dhRWMFD!Y-nm?WMUpA&TC|9U}R_pk`xx>XaDyDk&BNjr z;O$9?dz%=QkVBS{m4Ug5k)Oe!iIIz`iII`vz*LTh;f|jQbGKh|byR0eJ?6UZ(;gLr z9aGQg`(67c)3K*!{_hp(_5Wh#1eSj9I>r9nRKNe>-s%JTHLFuri2peiTfOUn;?p9% ze7&|CQ;Tn{kq+J&Z+~5qSJnSva&lldcZ&U5=N(IBVoWx#V_1-U^jkf5WJX2tvL1<* zOu6e1OET*15O{p-jKh}9#csx#?RiIbi!b~9;_lkwJ=OY(TmPm7^6U-S{4h6OW{-05 zMNZ~UkxK$QQx0ogSUAmV&%-NH(Z?4YIG9|)?_zFXG_Ao%dFsOQUBZ{97e9(sJ(eAVkC51%DAAH6i~{>=;iYp*jgGcqtPZer{m3hWG=$Q#KsO1WnyN5ON$yLg0u;;L>WXZP-o*vX!Br9WoBbrAk89q z(L&&c#(Eur7E{rM84()mnFQJvwLG^x{JKrIv?$N2v@|otD$T+$#Uw2;Ro6TvHCflt zFvUPO(cH{b*T5jrAlcF|)hsE^%)k+3g#wF}frSAN8yCb1CPrpn6rKhOPZNcwYak6W zf|EtWK*&G<=6FsPLl#ixg@mgLC|nyD84TpvI3ZTBaWS$88Gw>MOn{S-k?}urg5?G$ zSVo4Zh1J2P1py&)t zO;`N%%P&0tJo#a=gIz@?PC);9l#7lGZ*|e1xj&MgSU)mK^u1@1x!WaV)1vTGO)@st zEoQFrGZbS|H0(w8yyCIiCQxb_p7UhC^@sHr!?N$a_+b+?Q7>Iw;f|4n#-GL7p_*Go zwj5b#HN#an;-84Ao4ueVs1( z=KPYX^9#fy8BW%Q=FV^bu>a`)e`ntuoxXd;y57Xx>n*v@4sAOsdU-R$J=Z+;cg99{ QPGyL{SXrVKw9=Rh02O?rnE(I) literal 0 HcmV?d00001 diff --git a/certs/include.am b/certs/include.am index 78b432ef2..3ab8337a5 100644 --- a/certs/include.am +++ b/certs/include.am @@ -63,7 +63,8 @@ EXTRA_DIST += \ certs/csr.ext.der \ certs/entity-no-ca-bool-cert.pem \ certs/entity-no-ca-bool-key.pem \ - certs/x942dh2048.pem + certs/x942dh2048.pem \ + certs/fpki-cert.der EXTRA_DIST += \ certs/ca-key.der \ diff --git a/certs/renewcerts.sh b/certs/renewcerts.sh index ebef14a7f..208fc1a58 100755 --- a/certs/renewcerts.sh +++ b/certs/renewcerts.sh @@ -27,6 +27,7 @@ # client-relative-uri.pem # client-crl-dist.pem # entity-no-ca-bool-cert.pem +# fpki-cert.der # updates the following crls: # crl/cliCrl.pem # crl/crl.pem @@ -344,6 +345,20 @@ run_renewcerts(){ echo "End of section" echo "---------------------------------------------------------------------" ########################################################### + ########## update and sign fpki-cert.der ################ + ########################################################### + echo "Updating fpki-cert.der" + echo "" + #pipe the following arguments to openssl req... + echo -e "US\\nMontana\\nBozeman\\nwolfSSL\\nFPKI\\nwww.wolfssl.com\\ninfo@wolfssl.com\\n.\\n.\\n" | openssl req -new -key server-key.pem -config ./wolfssl.cnf -nodes > fpki-req.pem + check_result $? "Step 1" + + openssl x509 -req -in fpki-req.pem -extfile wolfssl.cnf -extensions fpki_ext -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out fpki-cert.der -outform DER + check_result $? "Step 2" + rm fpki-req.pem + echo "End of section" + echo "---------------------------------------------------------------------" + ########################################################### ########## update and sign server-cert.pem ################ ########################################################### echo "Updating server-cert.pem" diff --git a/certs/renewcerts/wolfssl.cnf b/certs/renewcerts/wolfssl.cnf index faea03f5d..9f082b47e 100644 --- a/certs/renewcerts/wolfssl.cnf +++ b/certs/renewcerts/wolfssl.cnf @@ -335,3 +335,39 @@ clock_precision_digits = 0 # (optional) ordering = yes # timestamps? tsa_name = yes # include? ess_cert_id_chain = no # include chain? + + +[fpki_ext] +basicConstraints = CA:FALSE,pathlen:0 +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid +keyUsage = critical, digitalSignature +extendedKeyUsage = critical, clientAuth, 1.3.6.1.4.1.311.20.2.2, 1.3.6.1.5.2.3.4, 1.3.6.1.5.5.7.3.21 +subjectAltName = @FASC_UUID_altname +certificatePolicies = 2.16.840.1.101.3.2.1.3.13, 2.16.840.1.101.3.2.1.3.40, 2.16.840.1.101.3.2.1.3.41, 2.16.840.1.101.3.2.1.3.45 +subjectDirectoryAttributes = ASN1:SEQUENCE:SubjDirAttr +policyConstraints = requireExplicitPolicy:0 +2.16.840.1.101.3.6.10.1 = ASN1:SEQUENCE:PIVCertExt + +# using example UUID from RFC4122 +[FASC_UUID_altname] +otherName = 2.16.840.1.101.3.6.6;FORMAT:HEX,OCT:D1:38:10:D8:28:AF:2C:10:84:35:15:A1:68:58:28:AF:02:10:86:A2:84:E7:39:C3:EB +URI = urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6 + +[SubjDirAttr] +attribute = SEQUENCE:SDA_attr + +[SDA_attr] +type = OID:1.3.6.1.5.5.7.9.4 +values = SET:SDA_coc + +[SDA_coc] +value = PRINTABLESTRING:US + +[PIVCertExt] +attribute = SEQUENCE:PCE_attr + +[PCE_attr] +type = OID:2.16.840.1.101.3.6.9.1 +value = BOOLEAN:true + diff --git a/configure.ac b/configure.ac index 0235f4592..5d2f3c670 100644 --- a/configure.ac +++ b/configure.ac @@ -712,6 +712,9 @@ then # Store issuer name components when parsing certificates. AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_HAVE_ISSUER_NAMES" + + # Certificate extensions and alt. names for FPKI use + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SUBJ_DIR_ATTR -DWOLFSSL_FPKI -DWOLFSSL_SUBJ_INFO_ACC" fi diff --git a/tests/api.c b/tests/api.c index d9d1a5cae..a83e2f1b5 100644 --- a/tests/api.c +++ b/tests/api.c @@ -2260,6 +2260,44 @@ static void test_wolfSSL_CertManagerNameConstraint5(void) #endif } +static void test_wolfSSL_FPKI(void) +{ +#if defined(WOLFSSL_FPKI) + XFILE f; + const char* fpkiCert = "./certs/fpki-cert.der"; + DecodedCert cert; + byte buf[4096]; + byte* uuid; + byte* fascn; + word32 fascnSz; + word32 uuidSz; + int bytes; + + printf(testingFmt, "test_wolfSSL_FPKI"); + f = XFOPEN(fpkiCert, "rb"); + AssertTrue((f != XBADFILE)); + bytes = (int)XFREAD(buf, 1, sizeof(buf), f); + XFCLOSE(f); +printf("size of file = %d\n", bytes); + + wc_InitDecodedCert(&cert, buf, bytes, NULL); + AssertIntEQ(wc_ParseCert(&cert, CERT_TYPE, 0, NULL), 0); + AssertIntEQ(wc_GetFASCNFromCert(&cert, NULL, &fascnSz), LENGTH_ONLY_E) ; + fascn = (byte*)XMALLOC(fascnSz, DYNAMIC_TYPE_TMP_BUFFER, NULL); + AssertNotNull(fascn); + AssertIntEQ(wc_GetFASCNFromCert(&cert, fascn, &fascnSz), 0); + XFREE(fascn, DYNAMIC_TYPE_TMP_BUFFER, NULL); + + AssertIntEQ(wc_GetUUIDFromCert(&cert, NULL, &uuidSz), LENGTH_ONLY_E); + uuid = (byte*)XMALLOC(uuidSz, DYNAMIC_TYPE_TMP_BUFFER, NULL); + AssertNotNull(uuid); + AssertIntEQ(wc_GetUUIDFromCert(&cert, uuid, &uuidSz), 0); + XFREE(uuid, DYNAMIC_TYPE_TMP_BUFFER, NULL); + + printf(resultFmt, passed); +#endif +} + static void test_wolfSSL_CertManagerCRL(void) { #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && defined(HAVE_CRL) && \ @@ -8982,7 +9020,8 @@ static void test_wolfSSL_URI(void) wolfSSL_FreeX509(x509); x509 = wolfSSL_X509_load_certificate_file(badUri, WOLFSSL_FILETYPE_PEM); -#if !defined(IGNORE_NAME_CONSTRAINTS) && !defined(WOLFSSL_NO_ASN_STRICT) +#if !defined(IGNORE_NAME_CONSTRAINTS) && !defined(WOLFSSL_NO_ASN_STRICT) \ + && !defined(WOLFSSL_FPKI) AssertNull(x509); #else AssertNotNull(x509); @@ -54100,6 +54139,7 @@ void ApiTest(void) test_wolfSSL_CertManagerNameConstraint3(); test_wolfSSL_CertManagerNameConstraint4(); test_wolfSSL_CertManagerNameConstraint5(); + test_wolfSSL_FPKI(); test_wolfSSL_CertManagerCRL(); test_wolfSSL_CTX_load_verify_locations_ex(); test_wolfSSL_CTX_load_verify_buffer_ex(); From 2cd9ca0c8f2b3986f4277b392f699326a2cf3414 Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Mon, 6 Jun 2022 09:42:03 -0700 Subject: [PATCH 05/12] add support for asn template build --- wolfcrypt/src/asn.c | 273 ++++++++++++++++++++++++++++++++------------ 1 file changed, 199 insertions(+), 74 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 2bb458466..063d0db55 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -4739,7 +4739,7 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) oid = extCertPolicyFpkiPivAuthOid; *oidSz = sizeof(extCertPolicyFpkiPivAuthOid); break; - case CP_FPKI_PIV_AUTH_HW_OID: + case CP_FPKI_PIV_AUTH_HW_OID: /* collision with AES256CBCb */ oid = extCertPolicyFpkiPivAuthHwOid; *oidSz = sizeof(extCertPolicyFpkiPivAuthHwOid); break; @@ -5384,6 +5384,22 @@ static int GetOID(const byte* input, word32* inOutIdx, word32* oid, /* Get the OID data for the id-type. */ checkOid = OidFromId(*oid, oidType, &checkOidSz); + #if defined(WOLFSSL_FPKI) + /* Handle OID sum collision of + AES256CBCb (454) 2.16.840.1.101.3.4.1.42 + CP_FPKI_PIV_AUTH_HW_OID (454) 2.16.840.1.101.3.2.1.3.41 + */ + #if defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_256) + if ((actualOidSz == (word32)sizeof(blkAes256CbcOid)) && + (XMEMCMP(actualOid, blkAes256CbcOid, + sizeof(blkAes256CbcOid)) == 0)) { + + checkOid = blkAes256CbcOid; + checkOidSz = sizeof(blkAes256CbcOid); + } + #endif /* HAVE_AES_CBC */ + #endif /* WOLFSSL_FPKI */ + #ifdef ASN_DUMP_OID /* Dump out the data for debug. */ ret = DumpOID(actualOid, actualOidSz, *oid, oidType); @@ -11074,6 +11090,40 @@ static int GenerateDNSEntryIPString(DNS_entry* entry, void* heap) #ifdef WOLFSSL_ASN_TEMPLATE #if defined(WOLFSSL_CERT_GEN) || \ (!defined(NO_CERTS) && !defined(IGNORE_NAME_CONSTRAINTS)) + +/* Adds a DNS entry to a list of DNS entries + * + * @param [in, out] lst Linked list of DNS name entries. + * @param [in] entry Entry to add to the list + * @return 0 on success. + */ +static int AddDNSEntryToList(DNS_entry** lst, DNS_entry* entry) +{ +#if defined(OPENSSL_EXTRA) && !defined(WOLFSSL_ALT_NAMES_NO_REV) + entry->next = NULL; + if (*lst == NULL) { + /* First on list */ + *lst = entry; + } + else { + DNS_entry* temp = *lst; + + /* Find end */ + for (; (temp->next != NULL); temp = temp->next); + + /* Add to end */ + temp->next = entry; + } +#else + /* Prepend entry to linked list. */ + entry->next = *lst; + *lst = entry; +#endif + + return 0; +} + + /* Allocate a DNS entry and set the fields. * * @param [in] cert Certificate object. @@ -11127,26 +11177,7 @@ static int SetDNSEntry(DecodedCert* cert, const char* str, int strLen, } if (ret == 0) { - #if defined(OPENSSL_EXTRA) && !defined(WOLFSSL_ALT_NAMES_NO_REV) - dnsEntry->next = NULL; - if (*entries == NULL) { - /* First on list */ - *entries = dnsEntry; - } - else { - DNS_entry* temp = *entries; - - /* Find end */ - for (; (temp->next != NULL); temp = temp->next); - - /* Add to end */ - temp->next = dnsEntry; - } - #else - /* Prepend entry to linked list. */ - dnsEntry->next = *entries; - *entries = dnsEntry; - #endif + ret = AddDNSEntryToList(entries, dnsEntry); } return ret; @@ -14557,7 +14588,7 @@ static void AddAltName(DecodedCert* cert, DNS_entry* dnsEntry) #endif #ifdef WOLFSSL_ASN_TEMPLATE -#ifdef WOLFSSL_SEP +#if defined(WOLFSSL_SEP) || defined(WOLFSSL_FPKI) /* ASN.1 template for OtherName of an X.509 certificate. * X.509: RFC 5280, 4.2.1.6 - OtherName (without implicit outer SEQUENCE). * HW Name: RFC 4108, 5 - Hardware Module Name @@ -14565,14 +14596,16 @@ static void AddAltName(DecodedCert* cert, DNS_entry* dnsEntry) */ static const ASNItem otherNameASN[] = { /* TYPEID */ { 0, ASN_OBJECT_ID, 0, 0, 0 }, -/* VALUE */ { 0, ASN_CONTEXT_SPECIFIC | ASN_OTHERNAME_VALUE, 1, 0, 0 }, -/* HWN_SEQ */ { 1, ASN_SEQUENCE, 1, 0, 0 }, +/* VALUE */ { 0, ASN_CONTEXT_SPECIFIC | ASN_OTHERNAME_VALUE, 1, 1, 0 }, +/* FASC-N */ { 1, ASN_OCTET_STRING, 0, 0, 2 }, +/* HWN_SEQ */ { 1, ASN_SEQUENCE, 1, 0, 2 }, /* HWN_TYPE */ { 2, ASN_OBJECT_ID, 0, 0, 0 }, /* HWN_NUM */ { 2, ASN_OCTET_STRING, 0, 0, 0 } }; enum { OTHERNAMEASN_IDX_TYPEID = 0, OTHERNAMEASN_IDX_VALUE, + OTHERNAMEASN_IDX_FASCN, OTHERNAMEASN_IDX_HWN_SEQ, OTHERNAMEASN_IDX_HWN_TYPE, OTHERNAMEASN_IDX_HWN_NUM, @@ -14581,57 +14614,21 @@ enum { /* Number of items in ASN.1 template for OtherName of an X.509 certificate. */ #define otherNameASN_Length (sizeof(otherNameASN) / sizeof(ASNItem)) -/* Decode data with OtherName format from after implicit SEQUENCE. - * - * @param [in, out] cert Certificate object. - * @param [in] input Buffer containing encoded OtherName. - * @param [in, out] inOutIdx On in, the index of the start of the OtherName. - * On out, index after OtherName. - * @param [in] maxIdx Maximum index of data in buffer. - * @return 0 on success. - * @return MEMORY_E on dynamic memory allocation failure. - * @return ASN_PARSE_E when BER encoded data does not match ASN.1 items or - * is invalid. - * @return ASN_PARSE_E when OID does is not HW Name. - * @return ASN_UNKNOWN_OID_E when the OID cannot be verified. - * @return BUFFER_E when data in buffer is too small. - */ -static int DecodeOtherName(DecodedCert* cert, const byte* input, - word32* inOutIdx, word32 maxIdx) +#ifdef WOLFSSL_SEP +static int DecodeSEP(ASNGetData* dataASN, DecodedCert* cert) { - DECL_ASNGETDATA(dataASN, otherNameASN_Length); int ret = 0; word32 oidLen, serialLen; - CALLOC_ASNGETDATA(dataASN, otherNameASN_Length, ret, cert->heap); + oidLen = dataASN[OTHERNAMEASN_IDX_HWN_TYPE].data.oid.length; + serialLen = dataASN[OTHERNAMEASN_IDX_HWN_NUM].data.ref.length; - if (ret == 0) { - /* Check the first OID is a recognized Alt Cert Name type. */ - GetASN_OID(&dataASN[OTHERNAMEASN_IDX_TYPEID], oidCertAltNameType); - /* Only support HW serial number. */ - GetASN_OID(&dataASN[OTHERNAMEASN_IDX_HWN_TYPE], oidIgnoreType); - /* Parse OtherName. */ - ret = GetASN_Items(otherNameASN, dataASN, otherNameASN_Length, 1, input, - inOutIdx, maxIdx); - } - if (ret == 0) { - /* Ensure expected OID. */ - if (dataASN[OTHERNAMEASN_IDX_TYPEID].data.oid.sum != HW_NAME_OID) { - WOLFSSL_MSG("\tunsupported OID"); - ret = ASN_PARSE_E; - } - } + /* Allocate space for HW type OID. */ + cert->hwType = (byte*)XMALLOC(oidLen, cert->heap, + DYNAMIC_TYPE_X509_EXT); + if (cert->hwType == NULL) + ret = MEMORY_E; - if (ret == 0) { - oidLen = dataASN[OTHERNAMEASN_IDX_HWN_TYPE].data.oid.length; - serialLen = dataASN[OTHERNAMEASN_IDX_HWN_NUM].data.ref.length; - - /* Allocate space for HW type OID. */ - cert->hwType = (byte*)XMALLOC(oidLen, cert->heap, - DYNAMIC_TYPE_X509_EXT); - if (cert->hwType == NULL) - ret = MEMORY_E; - } if (ret == 0) { /* Copy, into cert HW type OID */ XMEMCPY(cert->hwType, @@ -14654,11 +14651,86 @@ static int DecodeOtherName(DecodedCert* cert, const byte* input, cert->hwSerialNum[serialLen] = '\0'; cert->hwSerialNumSz = serialLen; } + return ret; +} +#endif /* WOLFSSL_SEP */ + +#ifdef WOLFSSL_FPKI +static int DecodeFASCN(ASNGetData* dataASN, DecodedCert* cert) +{ + int ret; + word32 fascnLen; + DNS_entry* entry = NULL; + + fascnLen = dataASN[OTHERNAMEASN_IDX_FASCN].data.ref.length; + ret = SetDNSEntry(cert, + (const char*)dataASN[OTHERNAMEASN_IDX_FASCN].data.ref.data, + fascnLen, ASN_OTHER_TYPE, &entry); + + if (ret == 0) { + entry->oidSum = FASCN_OID; + AddDNSEntryToList(&cert->altNames, entry); + } + + return ret; +} +#endif /* WOLFSSL_FPKI */ + +/* Decode data with OtherName format from after implicit SEQUENCE. + * + * @param [in, out] cert Certificate object. + * @param [in] input Buffer containing encoded OtherName. + * @param [in, out] inOutIdx On in, the index of the start of the OtherName. + * On out, index after OtherName. + * @param [in] maxIdx Maximum index of data in buffer. + * @return 0 on success. + * @return MEMORY_E on dynamic memory allocation failure. + * @return ASN_PARSE_E when BER encoded data does not match ASN.1 items or + * is invalid. + * @return ASN_PARSE_E when OID does is not HW Name. + * @return ASN_UNKNOWN_OID_E when the OID cannot be verified. + * @return BUFFER_E when data in buffer is too small. + */ +static int DecodeOtherName(DecodedCert* cert, const byte* input, + word32* inOutIdx, word32 maxIdx) +{ + DECL_ASNGETDATA(dataASN, otherNameASN_Length); + int ret = 0; + + CALLOC_ASNGETDATA(dataASN, otherNameASN_Length, ret, cert->heap); + + if (ret == 0) { + /* Check the first OID is a recognized Alt Cert Name type. */ + GetASN_OID(&dataASN[OTHERNAMEASN_IDX_TYPEID], oidCertAltNameType); + /* Parse OtherName. */ + ret = GetASN_Items(otherNameASN, dataASN, otherNameASN_Length, 1, input, + inOutIdx, maxIdx); + } + if (ret == 0) { + /* Ensure expected OID. */ + switch (dataASN[OTHERNAMEASN_IDX_TYPEID].data.oid.sum) { + #ifdef WOLFSSL_SEP + case HW_NAME_OID: + /* Only support HW serial number. */ + GetASN_OID(&dataASN[OTHERNAMEASN_IDX_HWN_TYPE], oidIgnoreType); + ret = DecodeSEP(dataASN, cert); + break; + #endif /* WOLFSSL_SEP */ + #ifdef WOLFSSL_FPKI + case FASCN_OID: + ret = DecodeFASCN(dataASN, cert); + break; + #endif /* WOLFSSL_FPKI */ + default: + WOLFSSL_MSG("\tunsupported OID"); + ret = ASN_PARSE_E; + } + } FREE_ASNGETDATA(dataASN, cert->heap); return ret; } -#endif /* WOLFSSL_SEP */ +#endif /* WOLFSSL_SEP || WOLFSSL_FPKI */ /* Decode a GeneralName. * @@ -14718,7 +14790,7 @@ static int DecodeGeneralName(const byte* input, word32* inOutIdx, byte tag, else if (tag == (ASN_CONTEXT_SPECIFIC | ASN_URI_TYPE)) { WOLFSSL_MSG("\tPutting URI into list but not using"); - #ifndef WOLFSSL_NO_ASN_STRICT + #if !defined(WOLFSSL_NO_ASN_STRICT) && !defined(WOLFSSL_FPKI) /* Verify RFC 5280 Sec 4.2.1.6 rule: "The name MUST NOT be a relative URI" */ { @@ -14764,7 +14836,7 @@ static int DecodeGeneralName(const byte* input, word32* inOutIdx, byte tag, } #endif /* WOLFSSL_QT || OPENSSL_ALL */ #endif /* IGNORE_NAME_CONSTRAINTS */ -#ifdef WOLFSSL_SEP +#if defined(WOLFSSL_SEP) || defined(WOLFSSL_FPKI) /* GeneralName choice: otherName */ else if (tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | ASN_OTHER_TYPE)) { /* TODO: test data for code path */ @@ -14815,7 +14887,7 @@ enum { #define altNameASN_Length (sizeof(altNameASN) / sizeof(ASNItem)) #endif /* WOLFSSL_ASN_TEMPLATE */ -#ifdef WOLFSSL_SEP +#if defined(WOLFSSL_SEP) && !defined(WOLFSSL_ASN_TEMPLATE) /* return 0 on success */ static int DecodeSepHwAltName(DecodedCert* cert, const byte* input, word32* idxIn, int sz) @@ -14890,7 +14962,7 @@ static int DecodeSepHwAltName(DecodedCert* cert, const byte* input, } #endif /* WOLFSSL_SEP */ -#ifdef WOLFSSL_FPKI +#if defined(WOLFSSL_FPKI) && !defined(WOLFSSL_ASN_TEMPLATE) /* return 0 on success */ static int DecodeFascNAltName(DecodedCert* cert, const byte* input, word32* idx, int sz) @@ -16910,6 +16982,28 @@ exit: #endif /* WOLFSSL_SEP */ #ifdef WOLFSSL_SUBJ_DIR_ATTR +#ifdef WOLFSSL_ASN_TEMPLATE +/* ASN.1 template for subject dir attribute. + * X.509: RFC 5280, 4.2.1.8 - Subject Directory Attributes. + */ +static const ASNItem subjDirAttrASN[] = { +/* SEQ */ { 0, ASN_SEQUENCE, 1, 1, 0 }, +/* SEQ */ { 1, ASN_SEQUENCE, 1, 1, 0 }, +/* OID */ { 2, ASN_OBJECT_ID, 0, 0, 0 }, +/* PLEN */ { 2, ASN_SET, 1, 1, 0 }, +/* BIT_STR */ { 2, ASN_PRINTABLE_STRING, 0, 0, 0 } +}; +enum { + SUBJDIRATTRASN_IDX_SEQ = 0, + SUBJDIRATTRASN_IDX_SEQ2, + SUBJDIRATTRASN_IDX_OID, + SUBJDIRATTRASN_IDX_SET, + SUBJDIRATTRASN_IDX_STRING, +}; + +/* Number of items in ASN.1 template for BasicContraints. */ +#define subjDirAttrASN_Length (sizeof(subjDirAttrASN) / sizeof(ASNItem)) +#endif /* Decode subject directory attributes extension in a certificate. * * X.509: RFC 5280, 4.2.1.8 - Subject Directory Attributes. @@ -16923,6 +17017,7 @@ exit: */ static int DecodeSubjDirAttr(const byte* input, int sz, DecodedCert* cert) { +#ifndef WOLFSSL_ASN_TEMPLATE word32 idx = 0; int length = 0; int ret = 0; @@ -16979,6 +17074,36 @@ static int DecodeSubjDirAttr(const byte* input, int sz, DecodedCert* cert) } return ret; +#else + DECL_ASNGETDATA(dataASN, subjDirAttrASN_Length); + int ret = 0; + word32 idx = 0; + + WOLFSSL_ENTER("DecodeSubjDirAttr"); + + CALLOC_ASNGETDATA(dataASN, subjDirAttrASN_Length, ret, cert->heap); + + if (ret == 0) { + ret = GetASN_Items(subjDirAttrASN, dataASN, subjDirAttrASN_Length, 1, + input, &idx, sz); + } + + /* There may be more than one countryOfCitizenship, but save the + * first one for now. */ + if (dataASN[SUBJDIRATTRASN_IDX_OID].data.oid.sum == SDA_COC_OID) { + word32 cuLen; + + cuLen = dataASN[SUBJDIRATTRASN_IDX_STRING].data.ref.length; + if (cuLen != COUNTRY_CODE_LEN) + return ASN_PARSE_E; + + XMEMCPY(cert->countryOfCitizenship, + dataASN[SUBJDIRATTRASN_IDX_STRING].data.ref.data, cuLen); + cert->countryOfCitizenship[COUNTRY_CODE_LEN] = 0; + } + FREE_ASNGETDATA(dataASN, cert->heap); + return ret; +#endif /* WOLFSSL_ASN_TEMPLATE */ } #endif /* WOLFSSL_SUBJ_DIR_ATTR */ From 86023378f82688d224ca9950aced0cc78246a4af Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Mon, 6 Jun 2022 14:31:41 -0700 Subject: [PATCH 06/12] free decoded cert in test case and x509 --- tests/api.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/api.c b/tests/api.c index a83e2f1b5..9a560eb06 100644 --- a/tests/api.c +++ b/tests/api.c @@ -2278,7 +2278,6 @@ static void test_wolfSSL_FPKI(void) AssertTrue((f != XBADFILE)); bytes = (int)XFREAD(buf, 1, sizeof(buf), f); XFCLOSE(f); -printf("size of file = %d\n", bytes); wc_InitDecodedCert(&cert, buf, bytes, NULL); AssertIntEQ(wc_ParseCert(&cert, CERT_TYPE, 0, NULL), 0); @@ -2293,6 +2292,7 @@ printf("size of file = %d\n", bytes); AssertNotNull(uuid); AssertIntEQ(wc_GetUUIDFromCert(&cert, uuid, &uuidSz), 0); XFREE(uuid, DYNAMIC_TYPE_TMP_BUFFER, NULL); + wc_FreeDecodedCert(&cert); printf(resultFmt, passed); #endif @@ -9016,7 +9016,6 @@ static void test_wolfSSL_URI(void) x509 = wolfSSL_X509_load_certificate_file(uri, WOLFSSL_FILETYPE_PEM); AssertNotNull(x509); - wolfSSL_FreeX509(x509); x509 = wolfSSL_X509_load_certificate_file(badUri, WOLFSSL_FILETYPE_PEM); @@ -9025,6 +9024,7 @@ static void test_wolfSSL_URI(void) AssertNull(x509); #else AssertNotNull(x509); + wolfSSL_FreeX509(x509); #endif printf(resultFmt, passed); From ba20f54b5b36fdc7247f23b5feaf33ecdffa8fce Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Thu, 9 Jun 2022 21:32:55 -0600 Subject: [PATCH 07/12] add UPN other name parsing and updating skip --- certs/fpki-cert.der | Bin 1327 -> 1363 bytes certs/renewcerts/wolfssl.cnf | 3 +- wolfcrypt/src/asn.c | 170 ++++++++++++++++++++++++----------- wolfssl/wolfcrypt/asn.h | 3 +- 4 files changed, 124 insertions(+), 52 deletions(-) diff --git a/certs/fpki-cert.der b/certs/fpki-cert.der index 9d35ad9d5132816e2d173fa025bfae698476ff4c..2b88caf247f8583bf37266876ff46bb8a3898074 100644 GIT binary patch delta 365 zcmZ3_b(xF9po!JrpoztNBF9z(9bvfOaV{!Pm?<^76N$_x1Xrd?1LO=8L4>MHX&aN;7NNV~qU``K~70>b_j TGW$BIrDt4zb4_F-)4{m_6ak=9 delta 329 zcmcc2wVsQ^povx6pov9zBF9zH5qfH;fF;d#$bRDXq-mOtE8=6A7MF zDINVM?DKW@8PW&WIwc=@(-lAc@(a&DPkxx}U{{fe6VSgN<)S0QTV3>L?vJD=){l%5 zeeYRh?sf^;v?%;klZ=gZiih!nNQRTOp}F(hKkPsH|KHg+N2l*zv932U_j*h2 ivqRgCieBE#aL+Z5{hhJVol_a&FIJXl1+8Q<<^li*+KQ+E diff --git a/certs/renewcerts/wolfssl.cnf b/certs/renewcerts/wolfssl.cnf index 9f082b47e..af26cdc23 100644 --- a/certs/renewcerts/wolfssl.cnf +++ b/certs/renewcerts/wolfssl.cnf @@ -351,7 +351,8 @@ policyConstraints = requireExplicitPolicy:0 # using example UUID from RFC4122 [FASC_UUID_altname] -otherName = 2.16.840.1.101.3.6.6;FORMAT:HEX,OCT:D1:38:10:D8:28:AF:2C:10:84:35:15:A1:68:58:28:AF:02:10:86:A2:84:E7:39:C3:EB +otherName.1 = 1.3.6.1.4.1.311.20.2.3;UTF8:facts@wolfssl.com +otherName.2 = 2.16.840.1.101.3.6.6;FORMAT:HEX,OCT:D1:38:10:D8:28:AF:2C:10:84:35:15:A1:68:58:28:AF:02:10:86:A2:84:E7:39:C3:EB URI = urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6 [SubjDirAttr] diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 063d0db55..c52991f32 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -14597,6 +14597,7 @@ static void AddAltName(DecodedCert* cert, DNS_entry* dnsEntry) static const ASNItem otherNameASN[] = { /* TYPEID */ { 0, ASN_OBJECT_ID, 0, 0, 0 }, /* VALUE */ { 0, ASN_CONTEXT_SPECIFIC | ASN_OTHERNAME_VALUE, 1, 1, 0 }, +/* UPN */ { 1, ASN_UTF8STRING, 0, 0, 2 }, /* FASC-N */ { 1, ASN_OCTET_STRING, 0, 0, 2 }, /* HWN_SEQ */ { 1, ASN_SEQUENCE, 1, 0, 2 }, /* HWN_TYPE */ { 2, ASN_OBJECT_ID, 0, 0, 0 }, @@ -14605,6 +14606,7 @@ static const ASNItem otherNameASN[] = { enum { OTHERNAMEASN_IDX_TYPEID = 0, OTHERNAMEASN_IDX_VALUE, + OTHERNAMEASN_IDX_UPN, OTHERNAMEASN_IDX_FASCN, OTHERNAMEASN_IDX_HWN_SEQ, OTHERNAMEASN_IDX_HWN_TYPE, @@ -14656,22 +14658,29 @@ static int DecodeSEP(ASNGetData* dataASN, DecodedCert* cert) #endif /* WOLFSSL_SEP */ #ifdef WOLFSSL_FPKI -static int DecodeFASCN(ASNGetData* dataASN, DecodedCert* cert) +static int DecodeOtherHelper(ASNGetData* dataASN, DecodedCert* cert, int oid) { - int ret; - word32 fascnLen; DNS_entry* entry = NULL; + int ret; + word32 bufLen; + const char* buf; - fascnLen = dataASN[OTHERNAMEASN_IDX_FASCN].data.ref.length; - ret = SetDNSEntry(cert, - (const char*)dataASN[OTHERNAMEASN_IDX_FASCN].data.ref.data, - fascnLen, ASN_OTHER_TYPE, &entry); - - if (ret == 0) { - entry->oidSum = FASCN_OID; - AddDNSEntryToList(&cert->altNames, entry); + switch (oid) { + case FASCN_OID: + bufLen = dataASN[OTHERNAMEASN_IDX_FASCN].data.ref.length; + buf = (const char*)dataASN[OTHERNAMEASN_IDX_FASCN].data.ref.data; + break; + case UPN_OID: + bufLen = dataASN[OTHERNAMEASN_IDX_UPN].data.ref.length; + buf = (const char*)dataASN[OTHERNAMEASN_IDX_UPN].data.ref.data; + break; } + ret = SetDNSEntry(cert, buf, bufLen, ASN_OTHER_TYPE, &entry); + if (ret == 0) { + entry->oidSum = oid; + AddDNSEntryToList(&cert->altNames, entry); + } return ret; } #endif /* WOLFSSL_FPKI */ @@ -14718,7 +14727,9 @@ static int DecodeOtherName(DecodedCert* cert, const byte* input, #endif /* WOLFSSL_SEP */ #ifdef WOLFSSL_FPKI case FASCN_OID: - ret = DecodeFASCN(dataASN, cert); + case UPN_OID: + ret = DecodeOtherHelper(dataASN, cert, + dataASN[OTHERNAMEASN_IDX_TYPEID].data.oid.sum); break; #endif /* WOLFSSL_FPKI */ default: @@ -14962,54 +14973,101 @@ static int DecodeSepHwAltName(DecodedCert* cert, const byte* input, } #endif /* WOLFSSL_SEP */ -#if defined(WOLFSSL_FPKI) && !defined(WOLFSSL_ASN_TEMPLATE) +#if !defined(WOLFSSL_ASN_TEMPLATE) /* return 0 on success */ -static int DecodeFascNAltName(DecodedCert* cert, const byte* input, word32* idx, - int sz) +static int DecodeConstructedOtherName(DecodedCert* cert, const byte* input, + word32* idx, int sz, int oid) { - int ret; + int ret = 0; int strLen; - DNS_entry* dnsEntry; byte tag; + DNS_entry* dnsEntry = NULL; if (GetASNTag(input, idx, &tag, sz) < 0) { - return ASN_PARSE_E; + ret = ASN_PARSE_E; } - if (tag != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) { - return ASN_PARSE_E; + if (ret == 0 && (tag != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED))) { + ret = ASN_PARSE_E; } - if (GetLength(input, idx, &strLen, sz) < 0) - return ASN_PARSE_E; - - ret = GetOctetString(input, idx, &strLen, sz); - if (ret < 0) - return ret; - - dnsEntry = AltNameNew(cert->heap); - if (dnsEntry == NULL) { - WOLFSSL_MSG("\tOut of Memory"); - return MEMORY_E; + if (ret == 0 && (GetLength(input, idx, &strLen, sz) < 0)) { + ret = ASN_PARSE_E; } - dnsEntry->type = ASN_OTHER_TYPE; - dnsEntry->name = (char*)XMALLOC(strLen + 1, cert->heap, - DYNAMIC_TYPE_ALTNAME); - if (dnsEntry->name == NULL) { - WOLFSSL_MSG("\tOut of Memory"); + if (ret == 0) { + dnsEntry = AltNameNew(cert->heap); + if (dnsEntry == NULL) { + WOLFSSL_MSG("\tOut of Memory"); + return MEMORY_E; + } + } + + if (ret == 0) { + switch (oid) { + #ifdef WOLFSSL_FPKI + case FASCN_OID: + ret = GetOctetString(input, idx, &strLen, sz); + if (ret > 0) { + ret = 0; + } + break; + #endif /* WOLFSSL_FPKI */ + case UPN_OID: + if (GetASNTag(input, idx, &tag, sz) < 0) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && + tag != ASN_PRINTABLE_STRING && tag != ASN_UTF8STRING && + tag != ASN_IA5_STRING) { + WOLFSSL_MSG("Was expecting a string for UPN"); + ret = ASN_PARSE_E; + } + + if (ret == 0 && (GetLength(input, idx, &strLen, sz) < 0)) { + WOLFSSL_MSG("Was expecting a string for UPN"); + ret = ASN_PARSE_E; + } + break; + + default: + WOLFSSL_MSG("Unknown constructed other name, skipping"); + *idx += strLen; + XFREE(dnsEntry, cert->heap, DYNAMIC_TYPE_ALTNAME); + dnsEntry = NULL; + } + } + + if (ret == 0 && dnsEntry != NULL) { + dnsEntry->type = ASN_OTHER_TYPE; + dnsEntry->len = strLen; + dnsEntry->name = (char*)XMALLOC(strLen + 1, cert->heap, + DYNAMIC_TYPE_ALTNAME); + #ifdef WOLFSSL_FPKI + dnsEntry->oidSum = oid; + #endif /* WOLFSSL_FPKI */ + if (dnsEntry->name == NULL) { + WOLFSSL_MSG("\tOut of Memory"); + ret = MEMORY_E; + } + else { + XMEMCPY(dnsEntry->name, &input[*idx], strLen); + dnsEntry->name[strLen] = '\0'; + AddAltName(cert, dnsEntry); + } + } + + if (ret == 0) { + *idx += strLen; + } + else { XFREE(dnsEntry, cert->heap, DYNAMIC_TYPE_ALTNAME); - return MEMORY_E; } - dnsEntry->len = strLen; - XMEMCPY(dnsEntry->name, &input[*idx], strLen); - dnsEntry->name[strLen] = '\0'; - dnsEntry->oidSum = FASCN_OID; - AddAltName(cert, dnsEntry); - *idx += strLen; - return 0; + + return ret; } -#endif /* WOLFSSL_FPKI */ +#endif /* Decode subject alternative names extension. * @@ -15316,7 +15374,9 @@ static int DecodeAltNames(const byte* input, int sz, DecodedCert* cert) #endif /* WOLFSSL_SEP */ #ifdef WOLFSSL_FPKI case FASCN_OID: - ret = DecodeFascNAltName(cert, input, &idx, sz); + case UPN_OID: + ret = DecodeConstructedOtherName(cert, input, &idx, sz, + oid); if (ret != 0) return ret; break; @@ -15325,11 +15385,21 @@ static int DecodeAltNames(const byte* input, int sz, DecodedCert* cert) default: WOLFSSL_MSG("\tUnsupported other name type, skipping"); if (GetLength(input, &idx, &strLen, sz) < 0) { - WOLFSSL_MSG("\tfail: unsupported other name length"); - return ASN_PARSE_E; + /* check to skip constructed other names too */ + if (DecodeConstructedOtherName(cert, input, &idx, sz, + oid) != 0) { + WOLFSSL_MSG("\tfail: unsupported other name length"); + return ASN_PARSE_E; + } + else { + /* idx will have been advanced to end of alt name */ + length -= (idx - lenStartIdx); + } + } + else { + length -= (strLen + idx - lenStartIdx); + idx += strLen; } - length -= (strLen + idx - lenStartIdx); - idx += strLen; } (void)ret; } diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 6c053e8fc..3995f3b19 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -1145,7 +1145,8 @@ enum Extensions_Sum { AKEY_PACKAGE_OID = 1048, /* 2.16.840.1.101.2.1.2.78.5 RFC 5958 - Asymmetric Key Packages */ - FASCN_OID = 419 /* 2.16.840.1.101.3.6.6 Federal PKI Policy FASC-N */ + FASCN_OID = 419, /* 2.16.840.1.101.3.6.6 Federal PKI Policy FASC-N */ + UPN_OID = 265 /* 1.3.6.1.4.1.311.20.2.3 UPN */ }; enum CertificatePolicy_Sum { From c59ec54713cb353db3a1a071fd8ed71407d0355a Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Fri, 10 Jun 2022 06:22:54 -0600 Subject: [PATCH 08/12] initialize variable to fix warning --- wolfcrypt/src/asn.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index c52991f32..37908ea62 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -14978,8 +14978,8 @@ static int DecodeSepHwAltName(DecodedCert* cert, const byte* input, static int DecodeConstructedOtherName(DecodedCert* cert, const byte* input, word32* idx, int sz, int oid) { - int ret = 0; - int strLen; + int ret = 0; + int strLen = 0; byte tag; DNS_entry* dnsEntry = NULL; From 40dda7e80faa483f02ed30c9c976d2bf38728e2c Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Tue, 21 Jun 2022 17:24:14 -0600 Subject: [PATCH 09/12] fix XMALLOC in test and add filesystem macro guard --- tests/api.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/api.c b/tests/api.c index 9a560eb06..77ee95c5f 100644 --- a/tests/api.c +++ b/tests/api.c @@ -2262,7 +2262,7 @@ static void test_wolfSSL_CertManagerNameConstraint5(void) static void test_wolfSSL_FPKI(void) { -#if defined(WOLFSSL_FPKI) +#if defined(WOLFSSL_FPKI) && !defined(NO_FILESYSTEM) XFILE f; const char* fpkiCert = "./certs/fpki-cert.der"; DecodedCert cert; @@ -2282,16 +2282,16 @@ static void test_wolfSSL_FPKI(void) wc_InitDecodedCert(&cert, buf, bytes, NULL); AssertIntEQ(wc_ParseCert(&cert, CERT_TYPE, 0, NULL), 0); AssertIntEQ(wc_GetFASCNFromCert(&cert, NULL, &fascnSz), LENGTH_ONLY_E) ; - fascn = (byte*)XMALLOC(fascnSz, DYNAMIC_TYPE_TMP_BUFFER, NULL); + fascn = (byte*)XMALLOC(fascnSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); AssertNotNull(fascn); AssertIntEQ(wc_GetFASCNFromCert(&cert, fascn, &fascnSz), 0); - XFREE(fascn, DYNAMIC_TYPE_TMP_BUFFER, NULL); + XFREE(fascn, NULL, DYNAMIC_TYPE_TMP_BUFFER); AssertIntEQ(wc_GetUUIDFromCert(&cert, NULL, &uuidSz), LENGTH_ONLY_E); - uuid = (byte*)XMALLOC(uuidSz, DYNAMIC_TYPE_TMP_BUFFER, NULL); + uuid = (byte*)XMALLOC(uuidSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); AssertNotNull(uuid); AssertIntEQ(wc_GetUUIDFromCert(&cert, uuid, &uuidSz), 0); - XFREE(uuid, DYNAMIC_TYPE_TMP_BUFFER, NULL); + XFREE(uuid, NULL, DYNAMIC_TYPE_TMP_BUFFER); wc_FreeDecodedCert(&cert); printf(resultFmt, passed); From 79ea30a957af5435f3293e17c61e6cd957c6882b Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Thu, 23 Jun 2022 13:40:45 -0600 Subject: [PATCH 10/12] memory free on failure, spelling, better function name --- wolfcrypt/src/asn.c | 14 ++++++++++---- wolfssl/wolfcrypt/asn.h | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 37908ea62..4c6abe818 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -83,6 +83,7 @@ ASN Options: * WOLFSSL_SUBJ_DIR_ATTR: Enable support for SubjectDirectoryAttributes extension. * WOLFSSL_SUBJ_INFO_ACC: Enable support for SubjectInfoAccess extension. + * WOLFSSL_FPKI: Enable support for FPKI (Federal PKI) extensions. */ #ifndef NO_ASN @@ -14953,13 +14954,18 @@ static int DecodeSepHwAltName(DecodedCert* cert, const byte* input, idx += strLen; ret = GetOctetString(input, &idx, &strLen, sz); - if (ret < 0) + if (ret < 0) { + XFREE(cert->hwType, cert->heap, DYNAMIC_TYPE_X509_EXT); + cert->hwType = NULL; return ret; + } cert->hwSerialNum = (byte*)XMALLOC(strLen + 1, cert->heap, DYNAMIC_TYPE_X509_EXT); if (cert->hwSerialNum == NULL) { WOLFSSL_MSG("\tOut of Memory"); + XFREE(cert->hwType, cert->heap, DYNAMIC_TYPE_X509_EXT); + cert->hwType = NULL; return MEMORY_E; } @@ -21281,7 +21287,7 @@ int wc_GetPubKeyDerFromCert(struct DecodedCert* cert, * otherwise the search starts from the node after 'current' alt name. * Returns 0 on success */ -static DNS_entry* wc_GetAltName(struct DecodedCert* cert, int nameType, +static DNS_entry* FindAltName(struct DecodedCert* cert, int nameType, DNS_entry* current) { DNS_entry* entry; @@ -21312,7 +21318,7 @@ int wc_GetUUIDFromCert(struct DecodedCert* cert, byte* uuid, word32* uuidSz) DNS_entry* id = NULL; do { - id = wc_GetAltName(cert, ASN_URI_TYPE, id); + id = FindAltName(cert, ASN_URI_TYPE, id); if (id != NULL) { /* check if URI string matches expected format for UUID */ if (id->len != DEFAULT_UUID_SZ) { @@ -21349,7 +21355,7 @@ int wc_GetFASCNFromCert(struct DecodedCert* cert, byte* fascn, word32* fascnSz) DNS_entry* id = NULL; do { - id = wc_GetAltName(cert, ASN_OTHER_TYPE, id); + id = FindAltName(cert, ASN_OTHER_TYPE, id); if (id != NULL && id->oidSum == FASCN_OID) { if (fascn == NULL) { *fascnSz = id->len; diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 3995f3b19..df5490afb 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -1290,7 +1290,7 @@ struct DNS_entry { char* ipString; /* human readable form of IP address */ #endif #ifdef WOLFSSL_FPKI - int oidSum; /* provid oid sum for verification */ + int oidSum; /* provide oid sum for verification */ #endif }; From 1977a1375453444965b0bfcbb5f45087e4f2340a Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Fri, 24 Jun 2022 12:04:26 -0600 Subject: [PATCH 11/12] improve comment for FPKI additions --- wolfcrypt/src/asn.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 4c6abe818..f95d5ea0c 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -14594,6 +14594,12 @@ static void AddAltName(DecodedCert* cert, DNS_entry* dnsEntry) * X.509: RFC 5280, 4.2.1.6 - OtherName (without implicit outer SEQUENCE). * HW Name: RFC 4108, 5 - Hardware Module Name * Only support HW Name where the type is a HW serial number. + * + * Other Names handled for FPKI (Federal PKI) use: + * UPN (Universal Principal Name), a non-standard Other Name + * (RFC3280 sec 4.2.1.7). Often used with FIPS 201 smartcard login. + * FASC-N (Federal Agency Smart Credential Number), defined in the document + * fpki-x509-cert-policy-common.pdf. Used for a smart card ID. */ static const ASNItem otherNameASN[] = { /* TYPEID */ { 0, ASN_OBJECT_ID, 0, 0, 0 }, From 49740c5543b288e43acb3870482082e323e15b69 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Fri, 24 Jun 2022 15:21:20 -0600 Subject: [PATCH 12/12] initialize variables --- wolfcrypt/src/asn.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index f95d5ea0c..79d106ada 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -14668,9 +14668,9 @@ static int DecodeSEP(ASNGetData* dataASN, DecodedCert* cert) static int DecodeOtherHelper(ASNGetData* dataASN, DecodedCert* cert, int oid) { DNS_entry* entry = NULL; - int ret; - word32 bufLen; - const char* buf; + int ret = 0; + word32 bufLen = 0; + const char* buf = NULL; switch (oid) { case FASCN_OID: @@ -14681,12 +14681,16 @@ static int DecodeOtherHelper(ASNGetData* dataASN, DecodedCert* cert, int oid) bufLen = dataASN[OTHERNAMEASN_IDX_UPN].data.ref.length; buf = (const char*)dataASN[OTHERNAMEASN_IDX_UPN].data.ref.data; break; + default: + ret = ASN_UNKNOWN_OID_E; } - ret = SetDNSEntry(cert, buf, bufLen, ASN_OTHER_TYPE, &entry); if (ret == 0) { - entry->oidSum = oid; - AddDNSEntryToList(&cert->altNames, entry); + ret = SetDNSEntry(cert, buf, bufLen, ASN_OTHER_TYPE, &entry); + if (ret == 0) { + entry->oidSum = oid; + AddDNSEntryToList(&cert->altNames, entry); + } } return ret; }