diff --git a/src/x509.c b/src/x509.c index d85d8db968..8da2ffdf57 100644 --- a/src/x509.c +++ b/src/x509.c @@ -7526,11 +7526,24 @@ int wolfSSL_i2d_X509(WOLFSSL_X509* x509, unsigned char** out) int wc_GeneratePreTBS(DecodedCert* cert, byte *der, int derSz) { int ret = 0; WOLFSSL_X509 *x = NULL; + byte certOwnsAltNames = 0; + byte certIsCSR = 0; if ((cert == NULL) || (der == NULL) || (derSz <= 0)) { return BAD_FUNC_ARG; } + /* The call to CopyDecodedToX509() transfers ownership of the altNames in + * the DecodedCert to the temporary X509 object, causing the list to be + * freed in wolfSSL_X509_free(). As this is an unintended side-effect, we + * have to save the ownerFlag here and transfer ownership back to the + * DecodedCert prior to freeing the X509 object. */ + certOwnsAltNames = cert->weOwnAltNames; + +#ifdef WOLFSSL_CERT_REQ + certIsCSR = cert->isCSR; +#endif + x = wolfSSL_X509_new(); if (x == NULL) { ret = MEMORY_E; @@ -7539,6 +7552,9 @@ int wc_GeneratePreTBS(DecodedCert* cert, byte *der, int derSz) { ret = CopyDecodedToX509(x, cert); } + /* CopyDecodedToX509() clears cert->weOwnAltNames. Restore it. */ + cert->weOwnAltNames = certOwnsAltNames; + if (ret == 0) { /* Remove the altsigval extension. */ XFREE(x->altSigValDer, x->heap, DYNAMIC_TYPE_X509_EXT); @@ -7547,13 +7563,16 @@ int wc_GeneratePreTBS(DecodedCert* cert, byte *der, int derSz) { /* Remove sigOID so it won't be encoded. */ x->sigOID = 0; /* We now have a PreTBS. Encode it. */ - ret = wolfssl_x509_make_der(x, 0, der, &derSz, 0); + ret = wolfssl_x509_make_der(x, certIsCSR, der, &derSz, 0); if (ret == WOLFSSL_SUCCESS) { ret = derSz; } } if (x != NULL) { + /* Safe the altNames list from being freed unitentionally. */ + x->altNames = NULL; + wolfSSL_X509_free(x); } diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index b444af94cb..f5ed8804ff 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -23864,13 +23864,12 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) #ifndef WOLFSSL_SMALL_STACK byte der[MAX_CERT_VERIFY_SZ]; #else - byte *der = (byte*)XMALLOC(MAX_CERT_VERIFY_SZ, ssl->heap, + byte *der = (byte*)XMALLOC(MAX_CERT_VERIFY_SZ, cert->heap, DYNAMIC_TYPE_DCERT); if (der == NULL) { ret = MEMORY_E; } else #endif /* ! WOLFSSL_SMALL_STACK */ - { ret = wc_GeneratePreTBS(cert, der, MAX_CERT_VERIFY_SZ); @@ -23882,7 +23881,7 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) NULL, 0, NULL); } #ifdef WOLFSSL_SMALL_STACK - XFREE(der, ssl->heap, DYNAMIC_TYPE_DCERT); + XFREE(der, cert->heap, DYNAMIC_TYPE_DCERT); #endif /* WOLFSSL_SMALL_STACK */ if (ret != 0) { @@ -23912,6 +23911,7 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) } #ifdef WOLFSSL_CERT_REQ else if (type == CERTREQ_TYPE) { + /* try to confirm/verify signature */ if ((ret = ConfirmSignature(&cert->sigCtx, cert->source + cert->certBegin, cert->sigIndex - cert->certBegin, @@ -23930,6 +23930,44 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) WOLFSSL_ERROR_VERBOSE(ret); return ret; } + + #ifdef WOLFSSL_DUAL_ALG_CERTS + if ((ret == 0) && cert->extAltSigAlgSet && + cert->extAltSigValSet) { + #ifndef WOLFSSL_SMALL_STACK + byte der[MAX_CERT_VERIFY_SZ]; + #else + byte *der = (byte*)XMALLOC(MAX_CERT_VERIFY_SZ, cert->heap, + DYNAMIC_TYPE_DCERT); + if (der == NULL) { + ret = MEMORY_E; + } else + #endif /* ! WOLFSSL_SMALL_STACK */ + { + ret = wc_GeneratePreTBS(cert, der, MAX_CERT_VERIFY_SZ); + + if (ret > 0) { + ret = ConfirmSignature(&cert->sigCtx, der, ret, + cert->sapkiDer, cert->sapkiLen, + cert->sapkiOID, cert->altSigValDer, + cert->altSigValLen, cert->altSigAlgOID, + NULL, 0, NULL); + } + #ifdef WOLFSSL_SMALL_STACK + XFREE(der, cert->heap, DYNAMIC_TYPE_DCERT); + #endif /* WOLFSSL_SMALL_STACK */ + + if (ret != 0) { + WOLFSSL_MSG("Confirm alternative signature failed"); + WOLFSSL_ERROR_VERBOSE(ret); + return ret; + } + else { + WOLFSSL_MSG("Alt signature has been verified!"); + } + } + } + #endif /* WOLFSSL_DUAL_ALG_CERTS */ } #endif else {