Merge pull request #8162 from yanrayw/2.28-save_stack_usage_pkwrite
Backport 2.28: pkwrite: use heap to save stack usage for writing keys in PEM string
diff --git a/ChangeLog.d/pkwrite-pem-use-heap.txt b/ChangeLog.d/pkwrite-pem-use-heap.txt
new file mode 100644
index 0000000..11db7b6
--- /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 88e6855..5e3fcc9 100644
--- a/library/pkwrite.c
+++ b/library/pkwrite.c
@@ -571,38 +571,49 @@
int mbedtls_pk_write_pubkey_pem(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;
PK_VALIDATE_RET(key != NULL);
PK_VALIDATE_RET(buf != NULL || size == 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(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;
PK_VALIDATE_RET(key != NULL);
PK_VALIDATE_RET(buf != NULL || size == 0);
- 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_RSA_C)
@@ -617,15 +628,22 @@
end = PEM_END_PRIVATE_KEY_EC;
} else
#endif
- 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_platform_zeroize(output_buf, PRV_DER_MAX_BYTES);
+ mbedtls_free(output_buf);
+ return ret;
}
#endif /* MBEDTLS_PEM_WRITE_C */