From bb574d28b293c8418d2dd54f91aa21faf9bf8271 Mon Sep 17 00:00:00 2001 From: Eric Blankenhorn Date: Sun, 12 Aug 2018 14:53:29 -0500 Subject: [PATCH] Support for more cert subject OIDs and raw subject access (#1734) * Add businessCategory OID * Raw subject support methods * Support for jurisdiction OIDs * Wrap in WOLFSSL_CERT_EXT * Adding tests --- certs/renewcerts/wolfssl.cnf | 7 + certs/test/catalog.txt | 2 + certs/test/cert-ext-joi.pem | 76 ++++++++ certs/test/include.am | 3 +- doc/dox_comments/header_files/asn_public.h | 95 ++++++++++ src/internal.c | 4 +- src/ssl.c | 40 ++++ tests/api.c | 43 +++++ wolfcrypt/src/asn.c | 203 ++++++++++++++++++++- wolfcrypt/test/test.c | 15 +- wolfssl/wolfcrypt/asn.h | 35 +++- wolfssl/wolfcrypt/asn_public.h | 12 ++ wolfssl/wolfcrypt/memory.h | 7 +- 13 files changed, 531 insertions(+), 11 deletions(-) create mode 100644 certs/test/cert-ext-joi.pem diff --git a/certs/renewcerts/wolfssl.cnf b/certs/renewcerts/wolfssl.cnf index 421194bc2..585a46911 100644 --- a/certs/renewcerts/wolfssl.cnf +++ b/certs/renewcerts/wolfssl.cnf @@ -11,6 +11,13 @@ oid_section = new_oids tsa_policy1 = 1.2.3.4.1 tsa_policy2 = 1.2.3.4.5.6 tsa_policy3 = 1.2.3.4.5.7 +businessCategory=2.5.4.15 +streetAddress=2.5.4.9 +stateOrProvinceName=2.5.4.8 +countryName=2.5.4.6 +jurisdictionOfIncorporationLocalityName=1.3.6.1.4.1.311.60.2.1.1 +jurisdictionOfIncorporationStateOrProvinceName=1.3.6.1.4.1.311.60.2.1.2 +jurisdictionOfIncorporationCountryName=1.3.6.1.4.1.311.60.2.1.3 #################################################################### [ ca ] diff --git a/certs/test/catalog.txt b/certs/test/catalog.txt index da7c211ec..9fc982697 100644 --- a/certs/test/catalog.txt +++ b/certs/test/catalog.txt @@ -10,3 +10,5 @@ dh1024.pem, dh1024.der: digsigku.pem: ECC certificate with a KeyUsage extension without the digitalSignature bit set. +cert-ext-joi.pem: + Simple certificate that includes OIDs for JurisdictionOfIncorporation diff --git a/certs/test/cert-ext-joi.pem b/certs/test/cert-ext-joi.pem new file mode 100644 index 000000000..7ec57286e --- /dev/null +++ b/certs/test/cert-ext-joi.pem @@ -0,0 +1,76 @@ +Certificate: + Data: + Version: 1 (0x0) + Serial Number: 13085343280838917500 (0xb5987a628272bd7c) + Signature Algorithm: sha256WithRSAEncryption + Issuer: O=Example Ltd/businessCategory=Private/serialNumber=5157550/jurisdictionC=US/jurisdictionST=California, C=US/street=123 My Street, ST=California, CN=example.com/subjectAltName=DNS.1=example.com, DNS.2=www.example.com, DNS.3=billing.example.com + Validity + Not Before: Aug 10 15:20:25 2018 GMT + Not After : May 6 15:20:25 2021 GMT + Subject: O=Example Ltd/businessCategory=Private/serialNumber=5157550/jurisdictionC=US/jurisdictionST=California, C=US/street=123 My Street, ST=California, CN=example.com/subjectAltName=DNS.1=example.com, DNS.2=www.example.com, DNS.3=billing.example.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:c0:95:08:e1:57:41:f2:71:6d:b7:d2:45:41:27: + 01:65:c6:45:ae:f2:bc:24:30:b8:95:ce:2f:4e:d6: + f6:1c:88:bc:7c:9f:fb:a8:67:7f:fe:5c:9c:51:75: + f7:8a:ca:07:e7:35:2f:8f:e1:bd:7b:c0:2f:7c:ab: + 64:a8:17:fc:ca:5d:7b:ba:e0:21:e5:72:2e:6f:2e: + 86:d8:95:73:da:ac:1b:53:b9:5f:3f:d7:19:0d:25: + 4f:e1:63:63:51:8b:0b:64:3f:ad:43:b8:a5:1c:5c: + 34:b3:ae:00:a0:63:c5:f6:7f:0b:59:68:78:73:a6: + 8c:18:a9:02:6d:af:c3:19:01:2e:b8:10:e3:c6:cc: + 40:b4:69:a3:46:33:69:87:6e:c4:bb:17:a6:f3:e8: + dd:ad:73:bc:7b:2f:21:b5:fd:66:51:0c:bd:54:b3: + e1:6d:5f:1c:bc:23:73:d1:09:03:89:14:d2:10:b9: + 64:c3:2a:d0:a1:96:4a:bc:e1:d4:1a:5b:c7:a0:c0: + c1:63:78:0f:44:37:30:32:96:80:32:23:95:a1:77: + ba:13:d2:97:73:e2:5d:25:c9:6a:0d:c3:39:60:a4: + b4:b0:69:42:42:09:e9:d8:08:bc:33:20:b3:58:22: + a7:aa:eb:c4:e1:e6:61:83:c5:d2:96:df:d9:d0:4f: + ad:d7 + Exponent: 65537 (0x10001) + Signature Algorithm: sha256WithRSAEncryption + ac:5a:d1:a9:e8:ed:75:8e:87:13:38:39:c5:d7:43:fd:72:31: + 34:4d:c3:41:f4:6a:d8:64:a2:ce:cf:d8:ab:81:9f:2c:26:4d: + 69:35:42:63:f8:53:c4:c5:f6:00:15:29:4d:3b:5e:bf:2c:8b: + a8:ad:54:22:c0:93:78:34:9c:e7:79:c1:d0:fe:7c:bf:87:b9: + 21:dd:d6:f9:35:ae:17:94:90:55:99:48:c8:d3:47:b1:be:1b: + 1f:62:31:0c:3a:e5:8e:b3:93:e6:93:02:36:e9:97:1e:7f:6c: + 55:6a:b8:9a:d1:d1:36:52:cb:3f:9f:5e:95:c4:0f:03:d5:a1: + 4c:d1:7e:8a:dd:58:ec:a1:17:c7:68:fe:91:b6:e7:66:8b:f7: + b3:a8:25:ad:2d:e9:c9:55:02:a2:39:16:cc:b0:aa:65:bf:21: + b5:dc:0a:d3:92:36:ae:84:d8:a3:d3:35:ba:b9:bc:b8:7d:2e: + 64:58:db:d7:ec:86:51:a2:44:7d:ba:98:30:c2:c5:4f:3c:ea: + 9f:1d:b0:1e:87:dc:49:4f:bf:42:70:c8:a3:3e:ad:6c:47:e3: + d3:ff:17:1c:37:c1:fa:34:b5:7b:e7:07:b6:c2:66:3a:89:57: + 44:1a:f5:6e:e0:cd:93:c0:c2:13:2e:e2:67:e7:8b:27:57:c1: + 16:f3:ad:eb +-----BEGIN CERTIFICATE----- +MIIElDCCA3wCCQC1mHpignK9fDANBgkqhkiG9w0BAQsFADCCAQoxFDASBgNVBAoM +C0V4YW1wbGUgTHRkMRAwDgYDVQQPDAdQcml2YXRlMRAwDgYDVQQFEwc1MTU3NTUw +MRMwEQYLKwYBBAGCNzwCAQMMAlVTMRswGQYLKwYBBAGCNzwCAQIMCkNhbGlmb3Ju +aWExCzAJBgNVBAYTAlVTMRYwFAYDVQQJDA0xMjMgTXkgU3RyZWV0MRMwEQYDVQQI +DApDYWxpZm9ybmlhMRQwEgYDVQQDDAtleGFtcGxlLmNvbTFMMEoGA1UdEQxDRE5T +LjE9ZXhhbXBsZS5jb20sIEROUy4yPXd3dy5leGFtcGxlLmNvbSwgRE5TLjM9Ymls +bGluZy5leGFtcGxlLmNvbTAeFw0xODA4MTAxNTIwMjVaFw0yMTA1MDYxNTIwMjVa +MIIBCjEUMBIGA1UECgwLRXhhbXBsZSBMdGQxEDAOBgNVBA8MB1ByaXZhdGUxEDAO +BgNVBAUTBzUxNTc1NTAxEzARBgsrBgEEAYI3PAIBAwwCVVMxGzAZBgsrBgEEAYI3 +PAIBAgwKQ2FsaWZvcm5pYTELMAkGA1UEBhMCVVMxFjAUBgNVBAkMDTEyMyBNeSBT +dHJlZXQxEzARBgNVBAgMCkNhbGlmb3JuaWExFDASBgNVBAMMC2V4YW1wbGUuY29t +MUwwSgYDVR0RDENETlMuMT1leGFtcGxlLmNvbSwgRE5TLjI9d3d3LmV4YW1wbGUu +Y29tLCBETlMuMz1iaWxsaW5nLmV4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAwJUI4VdB8nFtt9JFQScBZcZFrvK8JDC4lc4vTtb2HIi8 +fJ/7qGd//lycUXX3isoH5zUvj+G9e8AvfKtkqBf8yl17uuAh5XIuby6G2JVz2qwb +U7lfP9cZDSVP4WNjUYsLZD+tQ7ilHFw0s64AoGPF9n8LWWh4c6aMGKkCba/DGQEu +uBDjxsxAtGmjRjNph27Euxem8+jdrXO8ey8htf1mUQy9VLPhbV8cvCNz0QkDiRTS +ELlkwyrQoZZKvOHUGlvHoMDBY3gPRDcwMpaAMiOVoXe6E9KXc+JdJclqDcM5YKS0 +sGlCQgnp2Ai8MyCzWCKnquvE4eZhg8XSlt/Z0E+t1wIDAQABMA0GCSqGSIb3DQEB +CwUAA4IBAQCsWtGp6O11jocTODnF10P9cjE0TcNB9GrYZKLOz9irgZ8sJk1pNUJj ++FPExfYAFSlNO16/LIuorVQiwJN4NJznecHQ/ny/h7kh3db5Na4XlJBVmUjI00ex +vhsfYjEMOuWOs5PmkwI26Zcef2xVaria0dE2Uss/n16VxA8D1aFM0X6K3VjsoRfH +aP6Rtudmi/ezqCWtLenJVQKiORbMsKplvyG13ArTkjauhNij0zW6uby4fS5kWNvX +7IZRokR9upgwwsVPPOqfHbAeh9xJT79CcMijPq1sR+PT/xccN8H6NLV75we2wmY6 +iVdEGvVu4M2TwMITLuJn54snV8EW863r +-----END CERTIFICATE----- diff --git a/certs/test/include.am b/certs/test/include.am index a5b0423ba..ee94f1aa7 100644 --- a/certs/test/include.am +++ b/certs/test/include.am @@ -9,7 +9,8 @@ EXTRA_DIST += \ certs/test/cert-ext-nc.der \ certs/test/cert-ext-ns.der \ certs/test/gen-ext-certs.sh \ - certs/test/server-duplicate-policy.pem + certs/test/server-duplicate-policy.pem \ + certs/test/cert-ext-joi.pem # The certs/server-cert with the last byte (signature byte) changed EXTRA_DIST += \ diff --git a/doc/dox_comments/header_files/asn_public.h b/doc/dox_comments/header_files/asn_public.h index 47014dff1..706890e0e 100644 --- a/doc/dox_comments/header_files/asn_public.h +++ b/doc/dox_comments/header_files/asn_public.h @@ -335,6 +335,101 @@ WOLFSSL_API int wc_SetIssuer(Cert*, const char*); */ WOLFSSL_API int wc_SetSubject(Cert*, const char*); + +/*! + \ingroup ASN + + \brief This function sets the raw subject for a certificate from the + subject in the provided der buffer. This method is used to set the raw + subject field prior to signing. + + \return 0 Returned on successfully setting the subject for the certificate + \return MEMORY_E Returned if there is an error allocating memory + with XMALLOC + \return ASN_PARSE_E Returned if there is an error parsing the cert + header file + \return ASN_OBJECT_ID_E Returned if there is an error parsing the + encryption type from the cert + \return ASN_EXPECT_0_E Returned if there is a formatting error in the + encryption specification of the cert file + \return ASN_BEFORE_DATE_E Returned if the date is before the certificate + start date + \return ASN_AFTER_DATE_E Returned if the date is after the certificate + expiration date + \return ASN_BITSTR_E Returned if there is an error parsing a bit string + from the certificate + \return ASN_NTRU_KEY_E Returned if there is an error parsing the NTRU key + from the certificate + \return ECC_CURVE_OID_E Returned if there is an error parsing the ECC key + from the certificate + \return ASN_UNKNOWN_OID_E Returned if the certificate is using an unknown + key object id + \return ASN_VERSION_E Returned if the ALLOW_V1_EXTENSIONS option is not + defined and the certificate is a V1 or V2 certificate + \return BAD_FUNC_ARG Returned if there is an error processing the + certificate extension + \return ASN_CRIT_EXT_E Returned if an unfamiliar critical extension is + encountered in processing the certificate + \return ASN_SIG_OID_E Returned if the signature encryption type is not + the same as the encryption type of the certificate in the provided file + \return ASN_SIG_CONFIRM_E Returned if confirming the certification + signature fails + \return ASN_NAME_INVALID_E Returned if the certificate’s name is not + permitted by the CA name constraints + \return ASN_NO_SIGNER_E Returned if there is no CA signer to verify the + certificate’s authenticity + + \param cert pointer to the cert for which to set the raw subject + \param der pointer to the buffer containing the der formatted certificate + from which to grab the subject + \param derSz size of the buffer containing the der formatted certificate + from which to grab the subject + + _Example_ + \code + Cert myCert; + // initialize myCert + byte* der; + der = (byte*)malloc(FOURK_BUF); + // initialize der + if(wc_SetSubjectRaw(&myCert, der, FOURK_BUF) != 0) { + // error setting subject + } + \endcode + + \sa wc_InitCert + \sa wc_SetSubject +*/ +WOLFSSL_API int wc_SetSubjectRaw(Cert* cert, const byte* der, int derSz); + +/*! + \ingroup ASN + + \brief This function gets the raw subject from the certificate structure. + + \return 0 Returned on successfully getting the subject from the certificate + \return BAD_FUNC_ARG Returned if there is an error processing the + certificate extension + + \param subjectRaw pointer-pointer to the raw subject upon successful return + \param cert pointer to the cert from which to get the raw subject + + _Example_ + \code + Cert myCert; + byte *subjRaw; + // initialize myCert + + if(wc_GetSubjectRaw(&subjRaw, &myCert) != 0) { + // error setting subject + } + \endcode + + \sa wc_InitCert + \sa wc_SetSubjectRaw +*/ +WOLFSSL_API int wc_GetSubjectRaw(byte **subjectRaw, Cert *cert); + /*! \ingroup ASN diff --git a/src/internal.c b/src/internal.c index 2b916b142..26db8a318 100644 --- a/src/internal.c +++ b/src/internal.c @@ -7966,8 +7966,8 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) x509->subject.x509 = x509; #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) - XMEMCPY(x509->subject.raw, dCert->subjectRaw, dCert->subjectRawLen); - x509->subject.rawLen = dCert->subjectRawLen; + x509->subject.rawLen = min(dCert->subjectRawLen, sizeof(x509->subject.raw)); + XMEMCPY(x509->subject.raw, dCert->subjectRaw, x509->subject.rawLen); #endif XMEMCPY(x509->serial, dCert->serial, EXTERNAL_SERIAL_SIZE); diff --git a/src/ssl.c b/src/ssl.c index e0cb0b0bf..7e19734cc 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -15760,6 +15760,12 @@ int wolfSSL_X509_NAME_get_text_by_NID(WOLFSSL_X509_NAME* name, text = name->fullName.fullName + name->fullName.dcIdx[0]; textSz = name->fullName.dcLen[0]; break; + #ifdef WOLFSSL_CERT_EXT + case ASN_BUS_CAT: + text = name->fullName.fullName + name->fullName.bcIdx; + textSz = name->fullName.bcLen; + break; + #endif default: WOLFSSL_MSG("Entry type not found"); return SSL_FATAL_ERROR; @@ -28924,6 +28930,14 @@ void* wolfSSL_GetDhAgreeCtx(WOLFSSL* ssl) cName->unitEnc = CTC_UTF8; cName->commonName[0] = '\0'; cName->commonNameEnc = CTC_UTF8; + #ifdef WOLFSSL_CERT_EXT + cName->busCat[0] = '\0'; + cName->busCatEnc = CTC_UTF8; + cName->joiC[0] = '\0'; + cName->joiCEnc = CTC_PRINTABLE; + cName->joiSt[0] = '\0'; + cName->joiStEnc = CTC_PRINTABLE; + #endif cName->email[0] = '\0'; @@ -28978,6 +28992,32 @@ void* wolfSSL_GetDhAgreeCtx(WOLFSSL* ssl) return BUFFER_E; } + #ifdef WOLFSSL_CERT_EXT + /* ASN_BUS_CAT */ + WOLFSSL_MSG("Copy Business Category"); + if (CopyX509NameEntry(cName->busCat, CTC_NAME_SIZE, + dn->fullName + dn->bcIdx, dn->bcLen) + != SSL_SUCCESS) { + return BUFFER_E; + } + + /* JoI Country */ + WOLFSSL_MSG("Copy Jurisdiction of Incorporation Country"); + if (CopyX509NameEntry(cName->joiC, CTC_NAME_SIZE, + dn->fullName + dn->jcIdx, dn->jcLen) + != SSL_SUCCESS) { + return BUFFER_E; + } + + /* JoI State */ + WOLFSSL_MSG("Copy Jurisdiction of Incorporation State"); + if (CopyX509NameEntry(cName->joiSt, CTC_NAME_SIZE, + dn->fullName + dn->jsIdx, dn->jsLen) + != SSL_SUCCESS) { + return BUFFER_E; + } + #endif + WOLFSSL_MSG("Copy Email"); if (CopyX509NameEntry(cName->email, CTC_NAME_SIZE, dn->fullName + dn->emailIdx, dn->emailLen) diff --git a/tests/api.c b/tests/api.c index e2b2f15c9..36e633048 100644 --- a/tests/api.c +++ b/tests/api.c @@ -19164,6 +19164,47 @@ static void test_wc_GetPkcs8TraditionalOffset(void) #endif /* NO_ASN */ } +static void test_wc_SetSubjectRaw(void) +{ +#if !defined(NO_ASN) && !defined(NO_FILESYSTEM) && \ + defined(WOLFSSL_CERT_EXT) && defined(OPENSSL_EXTRA) + char joiCertFile[] = "./certs/test/cert-ext-joi.pem"; + WOLFSSL_X509* x509; + int peerCertSz; + const byte* peerCertBuf; + Cert forgedCert; + + printf(testingFmt, "test_wc_SetSubjectRaw()"); + + AssertNotNull(x509 = wolfSSL_X509_load_certificate_file(joiCertFile, WOLFSSL_FILETYPE_PEM)); + + AssertNotNull(peerCertBuf = wolfSSL_X509_get_der(x509, &peerCertSz)); + + AssertIntEQ(0, wc_InitCert(&forgedCert)); + + AssertIntEQ(0, wc_SetSubjectRaw(&forgedCert, peerCertBuf, peerCertSz)); + + wolfSSL_FreeX509(x509); + + printf(resultFmt, passed); +#endif +} + +static void test_wc_GetSubjectRaw(void) +{ +#if !defined(NO_ASN) && !defined(NO_FILESYSTEM) && \ + defined(WOLFSSL_CERT_EXT) && defined(OPENSSL_EXTRA) + Cert cert; + byte *subjectRaw; + + printf(testingFmt, "test_wc_GetSubjectRaw()"); + + AssertIntEQ(0, wc_InitCert(&cert)); + AssertIntEQ(0, wc_GetSubjectRaw(&subjectRaw, &cert)); + + printf(resultFmt, passed); +#endif +} /*----------------------------------------------------------------------------* | wolfCrypt ECC @@ -20404,6 +20445,8 @@ void ApiTest(void) /* wolfCrypt ASN tests */ test_wc_GetPkcs8TraditionalOffset(); + test_wc_SetSubjectRaw(); + test_wc_GetSubjectRaw(); /* wolfCrypt ECC tests */ test_wc_ecc_get_curve_size_from_name(); diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 700e72ccb..fa725a66b 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -4223,6 +4223,22 @@ static int GetName(DecodedCert* cert, int nameType) dName->snLen = strLen; #endif /* OPENSSL_EXTRA */ } + #ifdef WOLFSSL_CERT_EXT + else if (id == ASN_BUS_CAT) { + copy = WOLFSSL_BUS_CAT; + #ifdef WOLFSSL_CERT_GEN + if (nameType == SUBJECT) { + cert->subjectBC = (char*)&cert->source[cert->srcIdx]; + cert->subjectBCLen = strLen; + cert->subjectBCEnc = b; + } + #endif /* WOLFSSL_CERT_GEN */ + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + dName->bcIdx = cert->srcIdx; + dName->bcLen = strLen; + #endif /* OPENSSL_EXTRA */ + } + #endif /* WOLFSSL_CERT_EXT */ if (copy && !tooBig) { XMEMCPY(&full[idx], copy, XSTRLEN(copy)); idx += (word32)XSTRLEN(copy); @@ -4236,6 +4252,77 @@ static int GetName(DecodedCert* cert, int nameType) cert->srcIdx += strLen; } + #ifdef WOLFSSL_CERT_EXT + else if ((0 == XMEMCMP(&cert->source[cert->srcIdx], ASN_JOI_PREFIX, + XSTRLEN(ASN_JOI_PREFIX))) && + ((cert->source[cert->srcIdx + XSTRLEN(ASN_JOI_PREFIX)] == + ASN_JOI_C) || + (cert->source[cert->srcIdx + XSTRLEN(ASN_JOI_PREFIX)] == + ASN_JOI_ST))) + { + int strLen; + byte id; + const char* copy = NULL; + + cert->srcIdx += 10; + id = cert->source[cert->srcIdx++]; + b = cert->source[cert->srcIdx++]; /* encoding */ + + if (GetLength(cert->source, &cert->srcIdx, &strLen, + cert->maxIdx) < 0) + return ASN_PARSE_E; + + if ((strLen + strlen(WOLFSSL_JOI_ST)) > (ASN_NAME_MAX - idx)) { + WOLFSSL_MSG("ASN Name too big, skipping"); + tooBig = TRUE; + } + + /* Check for jurisdiction of incorporation country name */ + if (id == ASN_JOI_C) { + copy = WOLFSSL_JOI_C; + #ifdef WOLFSSL_CERT_GEN + if (nameType == SUBJECT) { + cert->subjectJC = (char*)&cert->source[cert->srcIdx]; + cert->subjectJCLen = strLen; + cert->subjectJCEnc = b; + } + #endif /* WOLFSSL_CERT_GEN */ + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + dName->jcIdx = cert->srcIdx; + dName->jcLen = strLen; + #endif /* OPENSSL_EXTRA */ + } + + /* Check for jurisdiction of incorporation state name */ + else if (id == ASN_JOI_ST) { + copy = WOLFSSL_JOI_ST; + #ifdef WOLFSSL_CERT_GEN + if (nameType == SUBJECT) { + cert->subjectJS = (char*)&cert->source[cert->srcIdx]; + cert->subjectJSLen = strLen; + cert->subjectJSEnc = b; + } + #endif /* WOLFSSL_CERT_GEN */ + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + dName->jsIdx = cert->srcIdx; + dName->jsLen = strLen; + #endif /* OPENSSL_EXTRA */ + } + + if ((copy != NULL) && (tooBig != 1)) { + XMEMCPY(&full[idx], copy, XSTRLEN(copy)); + idx += (word32)XSTRLEN(copy); + #ifdef WOLFSSL_WPAS + full[idx] = '='; + idx++; + #endif + XMEMCPY(&full[idx], &cert->source[cert->srcIdx], strLen); + idx += strLen; + } + + cert->srcIdx += strLen; + } + #endif /* WOLFSSL_CERT_EXT */ else { /* skip */ byte email = FALSE; @@ -6914,6 +7001,7 @@ int ParseCert(DecodedCert* cert, int type, int verify, void* cm) return ret; } + /* from SSL proper, for locking can't do find here anymore */ #ifdef __cplusplus extern "C" { @@ -9290,7 +9378,14 @@ static const char* GetOneName(CertName* name, int idx) case 6: return name->commonName; +#ifdef WOLFSSL_CERT_EXT case 7: + return name->busCat; + + case 8: +#else + case 7: +#endif return name->email; default: @@ -9324,6 +9419,10 @@ static char GetNameType(CertName* name, int idx) case 6: return name->commonNameEnc; +#ifdef WOLFSSL_CERT_EXT + case 7: + return name->busCatEnc; +#endif default: return 0; } @@ -11084,6 +11183,18 @@ int wc_MakeSelfCert(Cert* cert, byte* buffer, word32 buffSz, #ifdef WOLFSSL_CERT_EXT +/* Get raw subject from cert, which may contain OIDs not parsed by Decode. + The raw subject pointer will only be valid while "cert" is valid. */ +int wc_GetSubjectRaw(byte **subjectRaw, Cert *cert) +{ + int rc = BAD_FUNC_ARG; + if ((subjectRaw != NULL) && (cert != NULL)) { + *subjectRaw = cert->sbjRaw; + rc = 0; + } + return rc; +} + /* Set KID from public key */ static int SetKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey, byte *ntruKey, word16 ntruKeySz, @@ -11798,6 +11909,29 @@ static int SetNameFromCert(CertName* cn, const byte* der, int derSz) cn->sur[sz] = '\0'; cn->surEnc = decoded->subjectSNEnc; } + #ifdef WOLFSSL_CERT_EXT + if (decoded->subjectBC) { + sz = (decoded->subjectBCLen < CTC_NAME_SIZE) ? decoded->subjectBCLen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->busCat, decoded->subjectBC, CTC_NAME_SIZE); + cn->busCat[sz] = '\0'; + cn->busCatEnc = decoded->subjectBCEnc; + } + if (decoded->subjectJC) { + sz = (decoded->subjectJCLen < CTC_NAME_SIZE) ? decoded->subjectJCLen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->joiC, decoded->subjectJC, CTC_NAME_SIZE); + cn->joiC[sz] = '\0'; + cn->joiCEnc = decoded->subjectJCEnc; + } + if (decoded->subjectJS) { + sz = (decoded->subjectJSLen < CTC_NAME_SIZE) ? decoded->subjectJSLen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->joiSt, decoded->subjectJS, CTC_NAME_SIZE); + cn->joiSt[sz] = '\0'; + cn->joiStEnc = decoded->subjectJSEnc; + } + #endif if (decoded->subjectEmail) { sz = (decoded->subjectEmailLen < CTC_NAME_SIZE) ? decoded->subjectEmailLen : CTC_NAME_SIZE - 1; @@ -11815,6 +11949,59 @@ static int SetNameFromCert(CertName* cn, const byte* der, int derSz) return ret < 0 ? ret : 0; } +#ifdef WOLFSSL_CERT_EXT +/* Set raw subject from der buffer, return 0 on success */ +static int SetSubjectRawFromCert(byte* sbjRaw, const byte* der, int derSz) +{ + int ret; +#ifdef WOLFSSL_SMALL_STACK + DecodedCert* decoded; +#else + DecodedCert decoded[1]; +#endif + + if ((derSz < 0) || (sbjRaw == NULL)) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (decoded == NULL) { + return MEMORY_E; + } +#endif + + InitDecodedCert(decoded, (byte*)der, derSz, NULL); + ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0); + + if (ret < 0) { + WOLFSSL_MSG("ParseCertRelative error"); + } +#ifndef IGNORE_NAME_CONSTRAINT + else { + if ((decoded->subjectRaw) && + (decoded->subjectRawLen <= (int)sizeof(CertName))) { + XMEMCPY(sbjRaw, decoded->subjectRaw, decoded->subjectRawLen); + } + } +#else + else { + /* Fields are not accessible */ + ret = -1; + WOLFSSL_MSG("IGNORE_NAME_CONSTRAINT excludes raw subject"); + } +#endif + + FreeDecodedCert(decoded); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret < 0 ? ret : 0; +} +#endif #ifndef NO_FILESYSTEM @@ -11856,7 +12043,6 @@ int wc_SetSubject(Cert* cert, const char* subjectFile) return ret; } - #ifdef WOLFSSL_ALT_NAMES /* Set alt names from file in PEM */ @@ -11888,13 +12074,26 @@ int wc_SetIssuerBuffer(Cert* cert, const byte* der, int derSz) return SetNameFromCert(&cert->issuer, der, derSz); } - /* Set cert subject from DER buffer */ int wc_SetSubjectBuffer(Cert* cert, const byte* der, int derSz) { return SetNameFromCert(&cert->subject, der, derSz); } +#ifdef WOLFSSL_CERT_EXT +/* Set cert raw subject from DER buffer */ +int wc_SetSubjectRaw(Cert* cert, const byte* der, int derSz) +{ + int ret; + if (cert == NULL) { + ret = BAD_FUNC_ARG; + } + else { + ret = SetSubjectRawFromCert(cert->sbjRaw, der, derSz); + } + return ret; +} +#endif #ifdef WOLFSSL_ALT_NAMES diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index fbeda379b..eba454fa0 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -405,6 +405,8 @@ static void myFipsCb(int ok, int err, const char* hash) #ifdef WOLFSSL_STATIC_MEMORY #ifdef BENCH_EMBEDDED static byte gTestMemory[10000]; + #elif defined(WOLFSSL_CERT_EXT) + static byte gTestMemory[140000]; #elif defined(USE_FAST_MATH) && !defined(ALT_ECC_SIZE) static byte gTestMemory[130000]; #else @@ -8358,7 +8360,7 @@ static void initDefaultName(void) { XMEMCPY(certDefaultName.country, "US", sizeof("US")); certDefaultName.countryEnc = CTC_PRINTABLE; - XMEMCPY(certDefaultName.state, "Orgeon", sizeof("Orgeon")); + XMEMCPY(certDefaultName.state, "Oregon", sizeof("Oregon")); certDefaultName.stateEnc = CTC_UTF8; XMEMCPY(certDefaultName.locality, "Portland", sizeof("Portland")); certDefaultName.localityEnc = CTC_UTF8; @@ -8370,6 +8372,10 @@ static void initDefaultName(void) certDefaultName.unitEnc = CTC_UTF8; XMEMCPY(certDefaultName.commonName, "www.wolfssl.com", sizeof("www.wolfssl.com")); certDefaultName.commonNameEnc = CTC_UTF8; +#ifdef WOLFSSL_CERT_EXT + XMEMCPY(certDefaultName.busCat, "Private Organization", sizeof("Private Organization")); + certDefaultName.busCatEnc = CTC_UTF8; +#endif XMEMCPY(certDefaultName.email, "info@wolfssl.com", sizeof("info@wolfssl.com")); #ifdef WOLFSSL_TEST_CERT @@ -8402,12 +8408,17 @@ static void initDefaultName(void) #else static const CertName certDefaultName = { "US", CTC_PRINTABLE, /* country */ - "Orgeon", CTC_UTF8, /* state */ + "Oregon", CTC_UTF8, /* state */ "Portland", CTC_UTF8, /* locality */ "Test", CTC_UTF8, /* sur */ "wolfSSL", CTC_UTF8, /* org */ "Development", CTC_UTF8, /* unit */ "www.wolfssl.com", CTC_UTF8, /* commonName */ +#ifdef WOLFSSL_CERT_EXT + "Private Organization", CTC_UTF8, /* businessCategory */ + "US", CTC_PRINTABLE, /* jurisdiction country */ + "Oregon", CTC_PRINTABLE, /* jurisdiction state */ +#endif "info@wolfssl.com" /* email */ }; #endif /* WOLFSSL_MULTI_ATTRIB */ diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index d8c3915c0..eda5cf49f 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -113,8 +113,9 @@ enum DN_Tags { ASN_LOCALITY_NAME = 0x07, /* L */ ASN_STATE_NAME = 0x08, /* ST */ ASN_ORG_NAME = 0x0a, /* O */ - ASN_ORGUNIT_NAME = 0x0b, /* OU */ - ASN_EMAIL_NAME = 0x98, /* not oid number there is 97 in 2.5.4.0-97 */ + ASN_ORGUNIT_NAME = 0x0b, /* OU */ + ASN_BUS_CAT = 0x0f, /* businessCategory */ + ASN_EMAIL_NAME = 0x98, /* not oid number there is 97 in 2.5.4.0-97 */ /* pilot attribute types * OID values of 0.9.2342.19200300.100.1.* */ @@ -132,12 +133,19 @@ enum DN_Tags { #define WOLFSSL_ORG_NAME "/O=" #define WOLFSSL_ORGUNIT_NAME "/OU=" #define WOLFSSL_DOMAIN_COMPONENT "/DC=" +#define WOLFSSL_BUS_CAT "/businessCategory=" +#define WOLFSSL_JOI_C "/jurisdictionC=" +#define WOLFSSL_JOI_ST "/jurisdictionST=" enum ECC_TYPES { ECC_PREFIX_0 = 160, ECC_PREFIX_1 = 161 }; +#define ASN_JOI_PREFIX "\x2b\x06\x01\x04\x01\x82\x37\x3c\x02\x01" +#define ASN_JOI_C 0x3 +#define ASN_JOI_ST 0x2 + #ifndef WC_ASN_NAME_MAX #define WC_ASN_NAME_MAX 256 #endif @@ -476,6 +484,14 @@ struct DecodedName { int oLen; int ouIdx; int ouLen; +#ifdef WOLFSSL_CERT_EXT + int bcIdx; + int bcLen; + int jcIdx; + int jcLen; + int jsIdx; + int jsLen; +#endif int emailIdx; int emailLen; int uidIdx; @@ -678,6 +694,17 @@ struct DecodedCert { char* subjectOU; int subjectOULen; char subjectOUEnc; +#ifdef WOLFSSL_CERT_EXT + char* subjectBC; + int subjectBCLen; + char subjectBCEnc; + char* subjectJC; + int subjectJCLen; + char subjectJCEnc; + char* subjectJS; + int subjectJSLen; + char subjectJSEnc; +#endif char* subjectEmail; int subjectEmailLen; #endif /* WOLFSSL_CERT_GEN */ @@ -922,7 +949,11 @@ WOLFSSL_LOCAL void FreeDer(DerBuffer** der); #ifdef WOLFSSL_CERT_GEN enum cert_enums { +#ifdef WOLFSSL_CERT_EXT + NAME_ENTRIES = 9, +#else NAME_ENTRIES = 8, +#endif JOINT_LEN = 2, EMAIL_JOINT_LEN = 9, PILOT_JOINT_LEN = 10, diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index 2ba25e3de..906e8d547 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -203,6 +203,14 @@ typedef struct CertName { char unitEnc; char commonName[CTC_NAME_SIZE]; char commonNameEnc; +#ifdef WOLFSSL_CERT_EXT + char busCat[CTC_NAME_SIZE]; + char busCatEnc; + char joiC[CTC_NAME_SIZE]; + char joiCEnc; + char joiSt[CTC_NAME_SIZE]; + char joiStEnc; +#endif char email[CTC_NAME_SIZE]; /* !!!! email has to be last !!!! */ #ifdef WOLFSSL_MULTI_ATTRIB NameAttrib name[CTC_MAX_ATTRIB]; @@ -246,6 +254,8 @@ typedef struct Cert { #endif char certPolicies[CTC_MAX_CERTPOL_NB][CTC_MAX_CERTPOL_SZ]; word16 certPoliciesNb; /* Number of Cert Policy */ + byte issRaw[sizeof(CertName)]; /* raw issuer info */ + byte sbjRaw[sizeof(CertName)]; /* raw subject info */ #endif #ifdef WOLFSSL_CERT_REQ char challengePw[CTC_NAME_SIZE]; @@ -286,6 +296,7 @@ WOLFSSL_API int wc_MakeSelfCert(Cert*, byte* derBuffer, word32 derSz, RsaKey*, WC_RNG*); WOLFSSL_API int wc_SetIssuer(Cert*, const char*); WOLFSSL_API int wc_SetSubject(Cert*, const char*); +WOLFSSL_API int wc_SetSubjectRaw(Cert*, const byte* der, int derSz); #ifdef WOLFSSL_ALT_NAMES WOLFSSL_API int wc_SetAltNames(Cert*, const char*); #endif @@ -311,6 +322,7 @@ WOLFSSL_API int wc_SetSubjectKeyIdFromPublicKey_ex(Cert *cert, int keyType, WOLFSSL_API int wc_SetSubjectKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey); WOLFSSL_API int wc_SetSubjectKeyId(Cert *cert, const char* file); +WOLFSSL_API int wc_GetSubjectRaw(byte **subjectRaw, Cert *cert); #ifdef HAVE_NTRU WOLFSSL_API int wc_SetSubjectKeyIdFromNtruPublicKey(Cert *cert, byte *ntruKey, diff --git a/wolfssl/wolfcrypt/memory.h b/wolfssl/wolfcrypt/memory.h index a30978187..47599bd6c 100644 --- a/wolfssl/wolfcrypt/memory.h +++ b/wolfssl/wolfcrypt/memory.h @@ -98,11 +98,14 @@ WOLFSSL_API int wolfSSL_GetAllocators(wolfSSL_Malloc_cb*, #define WOLFMEM_IO_SZ 16992 /* 16 byte aligned */ #endif #ifndef WOLFMEM_BUCKETS - /* default size of chunks of memory to seperate into - * having session certs enabled makes a 21k SSL struct */ #ifndef SESSION_CERTS + /* default size of chunks of memory to separate into */ #define WOLFMEM_BUCKETS 64,128,256,512,1024,2432,3456,4544,16128 + #elif defined (WOLFSSL_CERT_EXT) + /* certificate extensions requires 24k for the SSL struct */ + #define WOLFMEM_BUCKETS 64,128,256,512,1024,2432,3456,4544,24576 #else + /* having session certs enabled makes a 21k SSL struct */ #define WOLFMEM_BUCKETS 64,128,256,512,1024,2432,3456,4544,21920 #endif #endif