diff --git a/ChangeLog.d/pkwrite-pem-use-heap.txt b/ChangeLog.d/pkwrite-pem-use-heap.txt new file mode 100644 index 000000000..11db7b6b0 --- /dev/null +++ b/ChangeLog.d/pkwrite-pem-use-heap.txt @@ -0,0 +1,4 @@ +Changes + * Use heap memory to allocate DER encoded public/private key. + This reduces stack usage significantly for writing a public/private + key to a PEM string. diff --git a/library/pkwrite.c b/library/pkwrite.c index 03db1454a..e38bc27de 100644 --- a/library/pkwrite.c +++ b/library/pkwrite.c @@ -756,27 +756,38 @@ int mbedtls_pk_write_key_der(const mbedtls_pk_context *key, unsigned char *buf, int mbedtls_pk_write_pubkey_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char output_buf[PUB_DER_MAX_BYTES]; + unsigned char *output_buf = NULL; + output_buf = mbedtls_calloc(1, PUB_DER_MAX_BYTES); + if (output_buf == NULL) { + return MBEDTLS_ERR_PK_ALLOC_FAILED; + } size_t olen = 0; if ((ret = mbedtls_pk_write_pubkey_der(key, output_buf, - sizeof(output_buf))) < 0) { - return ret; + PUB_DER_MAX_BYTES)) < 0) { + goto cleanup; } if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY, - output_buf + sizeof(output_buf) - ret, + output_buf + PUB_DER_MAX_BYTES - ret, ret, buf, size, &olen)) != 0) { - return ret; + goto cleanup; } - return 0; + ret = 0; +cleanup: + mbedtls_free(output_buf); + return ret; } int mbedtls_pk_write_key_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char output_buf[PRV_DER_MAX_BYTES]; + unsigned char *output_buf = NULL; + output_buf = mbedtls_calloc(1, PRV_DER_MAX_BYTES); + if (output_buf == NULL) { + return MBEDTLS_ERR_PK_ALLOC_FAILED; + } const char *begin, *end; size_t olen = 0; #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) @@ -789,8 +800,8 @@ int mbedtls_pk_write_key_pem(const mbedtls_pk_context *key, unsigned char *buf, int is_rsa_opaque = 0; #endif - if ((ret = mbedtls_pk_write_key_der(key, output_buf, sizeof(output_buf))) < 0) { - return ret; + if ((ret = mbedtls_pk_write_key_der(key, output_buf, PRV_DER_MAX_BYTES)) < 0) { + goto cleanup; } #if defined(MBEDTLS_USE_PSA_CRYPTO) @@ -833,15 +844,21 @@ int mbedtls_pk_write_key_pem(const mbedtls_pk_context *key, unsigned char *buf, } } else #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ - return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; - - if ((ret = mbedtls_pem_write_buffer(begin, end, - output_buf + sizeof(output_buf) - ret, - ret, buf, size, &olen)) != 0) { - return ret; + { + ret = MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; + goto cleanup; } - return 0; + if ((ret = mbedtls_pem_write_buffer(begin, end, + output_buf + PRV_DER_MAX_BYTES - ret, + ret, buf, size, &olen)) != 0) { + goto cleanup; + } + + ret = 0; +cleanup: + mbedtls_zeroize_and_free(output_buf, PRV_DER_MAX_BYTES); + return ret; } #endif /* MBEDTLS_PEM_WRITE_C */