diff --git a/src/internal.c b/src/internal.c index e3e545c2a..45e47c103 100644 --- a/src/internal.c +++ b/src/internal.c @@ -10178,7 +10178,13 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) ret = MEMORY_E; } } -#endif + if (dCert->contentType) { + if (dCert->contentTypeLen < CTC_NAME_SIZE) { + XMEMCPY(x509->contentType, dCert->contentType, dCert->contentTypeLen); + x509->contentType[dCert->contentTypeLen] = '\0'; + } + } +#endif /* WOLFSSL_CERT_REQ */ #ifdef WOLFSSL_SEP { diff --git a/src/ssl.c b/src/ssl.c index f9b553bbd..cdbd8bb8b 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -30696,9 +30696,12 @@ const WOLFSSL_ObjectInfo wolfssl_object_info[] = { "jurisdictionCountryName"}, { NID_jurisdictionStateOrProvinceName, NID_jurisdictionStateOrProvinceName, oidCertNameType, "jurisdictionST", "jurisdictionStateOrProvinceName"}, + #ifdef WOLFSSL_CERT_REQ { NID_pkcs9_challengePassword, CHALLENGE_PASSWORD_OID, oidCsrAttrType, "challengePassword", "challengePassword"}, + { NID_pkcs9_contentType, PKCS9_CONTENT_TYPE_OID, + oidCsrAttrType, "contentType", "contentType" }, #endif #endif #ifdef OPENSSL_EXTRA /* OPENSSL_EXTRA_X509_SMALL only needs the above */ @@ -50490,6 +50493,8 @@ int oid2nid(word32 oid, int grp) #ifdef WOLFSSL_CERT_REQ case oidCsrAttrType: switch (oid) { + case PKCS9_CONTENT_TYPE_OID: + return NID_pkcs9_contentType; case CHALLENGE_PASSWORD_OID: return NID_pkcs9_challengePassword; case SERIAL_NUMBER_OID: diff --git a/tests/api.c b/tests/api.c index 523b43878..a77bb55f6 100644 --- a/tests/api.c +++ b/tests/api.c @@ -36171,7 +36171,6 @@ static void test_wolfSSL_X509_NAME_ENTRY(void) X509_NAME_ENTRY* entry; unsigned char cn[] = "another name to add"; - printf(testingFmt, "wolfSSL_X509_NAME_ENTRY()"); AssertNotNull(x509 = @@ -36214,6 +36213,21 @@ static void test_wolfSSL_X509_NAME_ENTRY(void) #endif X509_NAME_ENTRY_free(entry); +#ifdef WOLFSSL_CERT_REQ + { + unsigned char srv_pkcs9p[] = "Server"; + char* subject; + AssertIntEQ(X509_NAME_add_entry_by_NID(nm, NID_pkcs9_contentType, + MBSTRING_ASC, srv_pkcs9p, -1, -1, 0), SSL_SUCCESS); + + subject = X509_NAME_oneline(nm, 0, 0); + #ifdef DEBUG_WOLFSSL + printf("\n\t%s\n", subject); + #endif + XFREE(subject, 0, DYNAMIC_TYPE_OPENSSL); + } +#endif + /* Test add entry by text */ AssertNotNull(entry = X509_NAME_ENTRY_create_by_txt(NULL, "commonName", 0x0c, cn, (int)sizeof(cn))); @@ -36227,7 +36241,7 @@ static void test_wolfSSL_X509_NAME_ENTRY(void) /* Test add entry by NID */ AssertIntEQ(X509_NAME_add_entry_by_NID(nm, NID_commonName, MBSTRING_UTF8, - cn, -1, -1, 0), WOLFSSL_SUCCESS); + cn, -1, -1, 0), SSL_SUCCESS); #ifndef NO_BIO BIO_free(bio); diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 7842e397e..e33e17d2c 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -3950,6 +3950,7 @@ static const byte extExtKeyUsageOcspSignOid[] = {43, 6, 1, 5, 5, 7, 3, 9}; #ifdef WOLFSSL_CERT_REQ /* csrAttrType */ static const byte attrUnstructuredNameOid[] = {42, 134, 72, 134, 247, 13, 1, 9, 2}; +static const byte attrPkcs9ContentTypeOid[] = {42, 134, 72, 134, 247, 13, 1, 9, 3}; static const byte attrChallengePasswordOid[] = {42, 134, 72, 134, 247, 13, 1, 9, 7}; static const byte attrExtensionRequestOid[] = {42, 134, 72, 134, 247, 13, 1, 9, 14}; static const byte attrSerialNumberOid[] = {85, 4, 5}; @@ -4740,6 +4741,10 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) oid = attrUnstructuredNameOid; *oidSz = sizeof(attrUnstructuredNameOid); break; + case PKCS9_CONTENT_TYPE_OID: + oid = attrPkcs9ContentTypeOid; + *oidSz = sizeof(attrPkcs9ContentTypeOid); + break; case CHALLENGE_PASSWORD_OID: oid = attrChallengePasswordOid; *oidSz = sizeof(attrChallengePasswordOid); @@ -16516,6 +16521,20 @@ static int DecodeCertReqAttrValue(DecodedCert* cert, int* criticalExt, ASNGetData strDataASN[strAttrASN_Length]; switch (oid) { + case PKCS9_CONTENT_TYPE_OID: + /* Clear dynamic data and specify choices acceptable. */ + XMEMSET(strDataASN, 0, sizeof(strDataASN)); + GetASN_Choice(&strDataASN[0], strAttrChoice); + /* Parse a string. */ + ret = GetASN_Items(strAttrASN, strDataASN, strAttrASN_Length, + 1, input, &idx, maxIdx); + if (ret == 0) { + /* Store references to password data. */ + cert->contentType = (char*)strDataASN[0].data.ref.data; + cert->contentTypeLen = strDataASN[0].data.ref.length; + } + break; + /* A password by which the entity may request certificate revocation. * PKCS#9: RFC 2985, 5.4.1 - Challenge password */ @@ -17499,6 +17518,21 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) return ASN_PARSE_E; } switch (oid) { + case PKCS9_CONTENT_TYPE_OID: + if (GetHeader(cert->source, &tag, + &cert->srcIdx, &len, attrMaxIdx, 1) < 0) { + WOLFSSL_MSG("attr GetHeader error"); + return ASN_PARSE_E; + } + if (tag != ASN_PRINTABLE_STRING && tag != ASN_UTF8STRING && + tag != ASN_IA5_STRING) { + WOLFSSL_MSG("Unsupported attribute value format"); + return ASN_PARSE_E; + } + cert->contentType = (char*)cert->source + cert->srcIdx; + cert->contentTypeLen = len; + cert->srcIdx += len; + break; case CHALLENGE_PASSWORD_OID: if (GetHeader(cert->source, &tag, &cert->srcIdx, &len, attrMaxIdx, 1) < 0) { diff --git a/wolfssl/internal.h b/wolfssl/internal.h index bc0fb41b2..858c5c368 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -3895,7 +3895,8 @@ struct WOLFSSL_X509 { WOLFSSL_X509_ATTRIBUTE* challengePwAttr; #endif char challengePw[CTC_NAME_SIZE]; /* for REQ certs */ -#endif + char contentType[CTC_NAME_SIZE]; +#endif /* WOLFSSL_CERT_REQ */ WOLFSSL_X509_NAME issuer; WOLFSSL_X509_NAME subject; #if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_WPAS) diff --git a/wolfssl/openssl/asn1.h b/wolfssl/openssl/asn1.h index 3d885defe..0b6975fba 100644 --- a/wolfssl/openssl/asn1.h +++ b/wolfssl/openssl/asn1.h @@ -92,6 +92,17 @@ #define ASN1_STRING_FLAG_MSTRING 0x040 #define ASN1_STRING_FLAG_EMBED 0x080 +/* X.509 PKI size limits from RFC2459 (appendix A) */ +/* internally our limit is CTC_NAME_SIZE (64) - overriden with WC_CTC_NAME_SIZE */ +#define ub_name CTC_NAME_SIZE /* 32768 */ +#define ub_common_name CTC_NAME_SIZE /* 64 */ +#define ub_locality_name CTC_NAME_SIZE /* 128 */ +#define ub_state_name CTC_NAME_SIZE /* 128 */ +#define ub_organization_name CTC_NAME_SIZE /* 64 */ +#define ub_organization_unit_name CTC_NAME_SIZE /* 64 */ +#define ub_title CTC_NAME_SIZE /* 64 */ +#define ub_email_address CTC_NAME_SIZE /* 128 */ + WOLFSSL_API WOLFSSL_ASN1_INTEGER *wolfSSL_BN_to_ASN1_INTEGER( const WOLFSSL_BIGNUM*, WOLFSSL_ASN1_INTEGER*); diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 32fda9d22..168fd775c 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -678,6 +678,7 @@ enum NID_sha512_224 = 1094, NID_sha512_256 = 1095, NID_pkcs9_unstructuredName = 49, + NID_pkcs9_contentType = 50, /* 1.2.840.113549.1.9.3 */ NID_pkcs9_challengePassword = 54, NID_hw_name_oid = 73, NID_id_pkix_OCSP_basic = 74, @@ -1097,6 +1098,7 @@ enum KeyIdType { #ifdef WOLFSSL_CERT_REQ enum CsrAttrType { UNSTRUCTURED_NAME_OID = 654, + PKCS9_CONTENT_TYPE_OID = 655, CHALLENGE_PASSWORD_OID = 659, SERIAL_NUMBER_OID = 94, EXTENSION_REQUEST_OID = 666, @@ -1477,7 +1479,9 @@ struct DecodedCert { #ifdef WOLFSSL_CERT_REQ /* CSR attributes */ - char* cPwd; /* challengePassword */ + char* contentType; /* Content Type */ + int contentTypeLen; + char* cPwd; /* Challenge Password */ int cPwdLen; char* sNum; /* Serial Number */ int sNumLen;