diff --git a/doc/dox_comments/header_files/asn_public.h b/doc/dox_comments/header_files/asn_public.h index 706890e0e..b7943a849 100644 --- a/doc/dox_comments/header_files/asn_public.h +++ b/doc/dox_comments/header_files/asn_public.h @@ -557,6 +557,72 @@ WOLFSSL_API int wc_SetAltNames(Cert*, const char*); */ WOLFSSL_API int wc_SetIssuerBuffer(Cert*, const byte*, int); +/*! + \ingroup ASN + + \brief This function sets the raw issuer for a certificate from the + issuer in the provided der buffer. This method is used to set the raw + issuer field prior to signing. + + \return 0 Returned on successfully setting the issuer 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 issuer + \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_SetIssuerRaw(&myCert, der, FOURK_BUF) != 0) { + // error setting subject + } + \endcode + + \sa wc_InitCert + \sa wc_SetIssuer +*/ +WOLFSSL_API int wc_SetIssuerRaw(Cert* cert, const byte* der, int derSz); + /*! \ingroup ASN diff --git a/src/internal.c b/src/internal.c index 90564b200..f375157e3 100644 --- a/src/internal.c +++ b/src/internal.c @@ -8081,6 +8081,10 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) x509->subject.rawLen = min(dCert->subjectRawLen, sizeof(x509->subject.raw)); XMEMCPY(x509->subject.raw, dCert->subjectRaw, x509->subject.rawLen); +#ifdef WOLFSSL_CERT_EXT + x509->issuer.rawLen = min(dCert->issuerRawLen, sizeof(x509->issuer.raw)); + XMEMCPY(x509->issuer.raw, dCert->issuerRaw, x509->issuer.rawLen); +#endif #endif XMEMCPY(x509->serial, dCert->serial, EXTERNAL_SERIAL_SIZE); diff --git a/tests/api.c b/tests/api.c index 07d477e1d..dc5779a42 100644 --- a/tests/api.c +++ b/tests/api.c @@ -19587,6 +19587,32 @@ static void test_wc_GetSubjectRaw(void) #endif } +static void test_wc_SetIssuerRaw(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_SetIssuerRaw()"); + + 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_SetIssuerRaw(&forgedCert, peerCertBuf, peerCertSz)); + + wolfSSL_FreeX509(x509); + + printf(resultFmt, passed); +#endif +} + static void test_CheckCertSignature(void) { #if !defined(NO_CERTS) && defined(WOLFSSL_SMALL_CERT_VERIFY) @@ -20901,6 +20927,7 @@ void ApiTest(void) test_wc_GetPkcs8TraditionalOffset(); test_wc_SetSubjectRaw(); test_wc_GetSubjectRaw(); + test_wc_SetIssuerRaw(); test_CheckCertSignature(); /* wolfCrypt ECC tests */ diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 9368190c5..139ae039d 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -4108,7 +4108,7 @@ static int GetName(DecodedCert* cert, int nameType) length += cert->srcIdx; idx = 0; -#ifdef HAVE_PKCS7 +#if defined(HAVE_PKCS7) || defined(WOLFSSL_CERT_EXT) /* store pointer to raw issuer */ if (nameType == ISSUER) { cert->issuerRaw = &cert->source[cert->srcIdx]; @@ -10581,13 +10581,58 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, } /* subject name */ - der->subjectSz = SetName(der->subject, sizeof(der->subject), &cert->subject); +#ifdef WOLFSSL_CERT_EXT + if (XSTRLEN((const char*)cert->sbjRaw) > 0) { + /* Use the raw subject */ + int idx; + + der->subjectSz = min(sizeof(der->subject), + (word32)XSTRLEN((const char*)cert->sbjRaw)); + /* header */ + idx = SetSequence(der->subjectSz, der->subject); + if (der->subjectSz + idx > (int)sizeof(der->subject)) { + return SUBJECT_E; + } + + XMEMCPY((char*)der->subject + idx, (const char*)cert->sbjRaw, + der->subjectSz); + der->subjectSz += idx; + } + else +#endif + { + /* Use the name structure */ + der->subjectSz = SetName(der->subject, sizeof(der->subject), + &cert->subject); + } if (der->subjectSz <= 0) return SUBJECT_E; /* issuer name */ - der->issuerSz = SetName(der->issuer, sizeof(der->issuer), cert->selfSigned ? - &cert->subject : &cert->issuer); +#ifdef WOLFSSL_CERT_EXT + if (XSTRLEN((const char*)cert->issRaw) > 0) { + /* Use the raw issuer */ + int idx; + + der->issuerSz = min(sizeof(der->issuer), + (word32)XSTRLEN((const char*)cert->issRaw)); + /* header */ + idx = SetSequence(der->issuerSz, der->issuer); + if (der->issuerSz + idx > (int)sizeof(der->issuer)) { + return ISSUER_E; + } + + XMEMCPY((char*)der->issuer + idx, (const char*)cert->issRaw, + der->issuerSz); + der->issuerSz += idx; + } + else +#endif + { + /* Use the name structure */ + der->issuerSz = SetName(der->issuer, sizeof(der->issuer), + cert->selfSigned ? &cert->subject : &cert->issuer); + } if (der->issuerSz <= 0) return ISSUER_E; @@ -12292,8 +12337,60 @@ static int SetSubjectRawFromCert(byte* sbjRaw, const byte* der, int derSz) return ret < 0 ? ret : 0; } + +/* Set raw issuer from der buffer, return 0 on success */ +static int SetIssuerRawFromCert(byte* issuerRaw, const byte* der, int derSz) +{ + int ret; +#ifdef WOLFSSL_SMALL_STACK + DecodedCert* decoded; +#else + DecodedCert decoded[1]; #endif + if ((derSz < 0) || (issuerRaw == 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->issuerRaw) && + (decoded->issuerRawLen <= (int)sizeof(CertName))) { + XMEMCPY(issuerRaw, decoded->issuerRaw, decoded->issuerRawLen); + } + } +#else + else { + /* Fields are not accessible */ + ret = -1; + WOLFSSL_MSG("IGNORE_NAME_CONSTRAINT excludes raw issuer"); + } +#endif + + FreeDecodedCert(decoded); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret < 0 ? ret : 0; +} +#endif /* WOLFSSL_CERT_EXT */ + #ifndef NO_FILESYSTEM /* Set cert issuer from issuerFile in PEM */ @@ -12384,6 +12481,20 @@ int wc_SetSubjectRaw(Cert* cert, const byte* der, int derSz) } return ret; } + +/* Set cert raw issuer from DER buffer */ +int wc_SetIssuerRaw(Cert* cert, const byte* der, int derSz) +{ + int ret; + + if (cert == NULL) { + ret = BAD_FUNC_ARG; + } + else { + ret = SetIssuerRawFromCert(cert->issRaw, der, derSz); + } + return ret; +} #endif #ifdef WOLFSSL_ALT_NAMES diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index c76d52b4c..32da055db 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -673,7 +673,7 @@ struct DecodedCert { int beforeDateLen; byte* afterDate; int afterDateLen; -#ifdef HAVE_PKCS7 +#if defined(HAVE_PKCS7) || defined(WOLFSSL_CERT_EXT) byte* issuerRaw; /* pointer to issuer inside source */ int issuerRawLen; #endif diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index cf35e0204..6d10e6e2c 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -297,7 +297,6 @@ 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 @@ -324,6 +323,8 @@ 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); +WOLFSSL_API int wc_SetSubjectRaw(Cert* cert, const byte* der, int derSz); +WOLFSSL_API int wc_SetIssuerRaw(Cert* cert, const byte* der, int derSz); #ifdef HAVE_NTRU WOLFSSL_API int wc_SetSubjectKeyIdFromNtruPublicKey(Cert *cert, byte *ntruKey,