diff --git a/src/x509.c b/src/x509.c index eaec2a2d8..d60b17e08 100644 --- a/src/x509.c +++ b/src/x509.c @@ -11578,12 +11578,8 @@ int wolfSSL_PEM_write_bio_X509(WOLFSSL_BIO *bio, WOLFSSL_X509 *cert) byte* pem = NULL; int pemSz = 0; /* Get large buffer to hold cert der */ + const byte* der = NULL; int derSz = X509_BUFFER_SZ; -#ifdef WOLFSSL_SMALL_STACK - byte* der; -#else - byte der[X509_BUFFER_SZ]; -#endif int ret; WOLFSSL_ENTER("wolfSSL_PEM_write_bio_X509()"); @@ -11593,15 +11589,11 @@ int wolfSSL_PEM_write_bio_X509(WOLFSSL_BIO *bio, WOLFSSL_X509 *cert) return WOLFSSL_FAILURE; } -#ifdef WOLFSSL_SMALL_STACK - der = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (!der) { - WOLFSSL_MSG("malloc failed"); - return WOLFSSL_FAILURE; - } -#endif - - if (wolfssl_x509_make_der(cert, 0, der, &derSz, 1) != WOLFSSL_SUCCESS) { + /* Do not call wolfssl_x509_make_der() here. If we did, then need to re-sign + * because we don't know the original order of the extensions and so we must + * assume our extensions are in a different order, thus need to re-sign. */ + der = wolfSSL_X509_get_der(cert, &derSz); + if (der == NULL) { goto error; } @@ -11623,17 +11615,11 @@ int wolfSSL_PEM_write_bio_X509(WOLFSSL_BIO *bio, WOLFSSL_X509 *cert) /* write the PEM to BIO */ ret = wolfSSL_BIO_write(bio, pem, pemSz); XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #ifdef WOLFSSL_SMALL_STACK - XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif if (ret <= 0) return WOLFSSL_FAILURE; return WOLFSSL_SUCCESS; error: - #ifdef WOLFSSL_SMALL_STACK - XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif if (pem) XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); return WOLFSSL_FAILURE; diff --git a/tests/api.c b/tests/api.c index ea0df1598..79ba0a15d 100644 --- a/tests/api.c +++ b/tests/api.c @@ -39512,22 +39512,33 @@ static int test_wolfSSL_i2t_ASN1_OBJECT(void) static int test_wolfSSL_PEM_write_bio_X509(void) { int res = TEST_SKIPPED; -#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_AKID_NAME) && \ - defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN) && \ - !defined(NO_BIO) && !defined(NO_RSA) +#if defined(OPENSSL_EXTRA) && defined(OPENSSL_ALL) && \ + defined(WOLFSSL_AKID_NAME) && defined(WOLFSSL_CERT_EXT) && \ + defined(WOLFSSL_CERT_GEN) && !defined(NO_BIO) && !defined(NO_RSA) && \ + !defined(NO_FILESYSTEM) /* This test contains the hard coded expected * lengths. Update if necessary */ + FILE* fp = NULL; + WOLFSSL_EVP_PKEY *priv = NULL; - BIO* input; - BIO* output; + BIO* input = NULL; + BIO* output = NULL; X509* x509a = NULL; X509* x509b = NULL; + ASN1_TIME* notBeforeA = NULL; ASN1_TIME* notAfterA = NULL; ASN1_TIME* notBeforeB = NULL; ASN1_TIME* notAfterB = NULL; int expectedLen; + fp = XFOPEN("certs/server-key.pem", "rb"); + AssertNotNull(fp); + priv = wolfSSL_PEM_read_PrivateKey(fp, NULL, NULL, NULL); + XFCLOSE(fp); + fp = NULL; + AssertNotNull(priv); + AssertNotNull(input = BIO_new_file( "certs/test/cert-ext-multiple.pem", "rb")); AssertIntEQ(wolfSSL_BIO_get_len(input), 2000); @@ -39537,7 +39548,7 @@ static int test_wolfSSL_PEM_write_bio_X509(void) AssertNotNull(notBeforeA = X509_get_notBefore(x509a)); AssertNotNull(notAfterA = X509_get_notAfter(x509a)); - /* write X509 back to PEM BIO */ + /* write X509 back to PEM BIO; no need to sign as nothing changed. */ AssertNotNull(output = BIO_new(wolfSSL_BIO_s_mem())); AssertIntEQ(PEM_write_bio_X509(output, x509a), WOLFSSL_SUCCESS); /* compare length against expected */ @@ -39545,12 +39556,13 @@ static int test_wolfSSL_PEM_write_bio_X509(void) AssertIntEQ(wolfSSL_BIO_get_len(output), expectedLen); /* read exported X509 PEM back into struct, sanity check on export, - * make sure notBefore/notAfter are the same. */ + * make sure notBefore/notAfter are the same and certs are identical. */ AssertNotNull(PEM_read_bio_X509(output, &x509b, NULL, NULL)); AssertNotNull(notBeforeB = X509_get_notBefore(x509b)); AssertNotNull(notAfterB = X509_get_notAfter(x509b)); AssertIntEQ(ASN1_TIME_compare(notBeforeA, notBeforeB), 0); AssertIntEQ(ASN1_TIME_compare(notAfterA, notAfterB), 0); + AssertIntEQ(0, wolfSSL_X509_cmp(x509a, x509b)); X509_free(x509b); /* Reset output buffer */ @@ -39565,6 +39577,9 @@ static int test_wolfSSL_PEM_write_bio_X509(void) x509a->authKeyIdSrcSz = 0; } + /* Resign to re-generate the der */ + AssertIntGT(wolfSSL_X509_sign(x509a, priv, EVP_sha256()), 0); + AssertIntEQ(PEM_write_bio_X509(output, x509a), WOLFSSL_SUCCESS); /* Check that we generate a smaller output since the AKID will @@ -39588,15 +39603,16 @@ static int test_wolfSSL_PEM_write_bio_X509(void) /* read PEM into X509 struct */ AssertNotNull(PEM_read_bio_X509(input, &x509a, NULL, NULL)); - /* write X509 back to PEM BIO */ + /* write X509 back to PEM BIO; no need to sign as nothing changed */ AssertNotNull(output = BIO_new(wolfSSL_BIO_s_mem())); AssertIntEQ(PEM_write_bio_X509(output, x509a), WOLFSSL_SUCCESS); - /* read exported X509 PEM back into struct, ensure isCa and - * basicConstSet values are maintained */ + /* read exported X509 PEM back into struct, ensure isCa and basicConstSet + * values are maintained and certs are identical.*/ AssertNotNull(PEM_read_bio_X509(output, &x509b, NULL, NULL)); AssertIntEQ(x509b->isCa, 1); AssertIntEQ(x509b->basicConstSet, 1); + AssertIntEQ(0, wolfSSL_X509_cmp(x509a, x509b)); X509_free(x509a); X509_free(x509b); @@ -39611,16 +39627,18 @@ static int test_wolfSSL_PEM_write_bio_X509(void) /* read PEM into X509 struct */ AssertNotNull(PEM_read_bio_X509(input, &x509a, NULL, NULL)); - /* write X509 back to PEM BIO */ + /* write X509 back to PEM BIO; no need to sign as nothing changed */ AssertNotNull(output = BIO_new(wolfSSL_BIO_s_mem())); AssertIntEQ(PEM_write_bio_X509(output, x509a), WOLFSSL_SUCCESS); /* read exported X509 PEM back into struct, ensure isCa and - * basicConstSet values are maintained */ + * basicConstSet values are maintained and certs are identical */ AssertNotNull(PEM_read_bio_X509(output, &x509b, NULL, NULL)); AssertIntEQ(x509b->isCa, 0); AssertIntEQ(x509b->basicConstSet, 1); + AssertIntEQ(0, wolfSSL_X509_cmp(x509a, x509b)); + wolfSSL_EVP_PKEY_free(priv); X509_free(x509a); X509_free(x509b); BIO_free(input);