mbedtls icon indicating copy to clipboard operation
mbedtls copied to clipboard

No mechanism to find size for mbedtls_x509write_crt_pem

Open jamespicone opened this issue 5 years ago • 8 comments

Description

  • Type: Bug
  • Priority: Minor

Bug

mbed TLS build:
Version: 2.16.1

There appears to be no API call to find the size in bytes for a PEM-encoded certificate, and the function mbedtls_x509write_crt_pem does not return the size it requires; the only possible way to use the function is to either continually reallocate larger buffers until it reports that it succeeded at writing, or by picking a buffer that's 'large enough' and erroring-out if the certificate is somehow larger. And even with that solution it doesn't appear possible to find out the actual size used in the buffer and it's not clear if the returned PEM is null-terminated.

A proposed fix would be for mbedtls_x509write_crt_pem to take size as a size_t*, and for it to write the required size to that pointer on success or failure due to insufficient space.

jamespicone avatar Jun 03 '20 05:06 jamespicone

This is a general problem with all the DER and PEM writing functions: mbedtls_pk_write_key_der, mbedtls_pk_write_key_pem, mbedtls_pk_write_pubkey_der, mbedtls_pk_write_pubkey_pem, mbedtls_x509write_crt_der, mbedtls_x509write_crt_pem, mbedtls_x509write_csr_der, mbedtls_x509write_csr_pem. For the key writing functions, it isn't so bad because it's relatively easy to find a sensible buffer size knowing the key size and the key type. But for certificates and certificate signing requests, the data includes variable-length strings so you have to know exactly what's in the data to calculate the size.

We can change the functions to take an extra parameter to return the needed size in Mbed TLS 3.0. But we may want to add new functions before 3.0 comes out (we wouldn't change the signature of an existing function within the same major version of Mbed TLS).

Regardless of the interface, this requires a non-negligible amount of new code, so we wouldn't add it to the long-time support branches (2.7 and 2.16), only to a 2.x.

gilles-peskine-arm avatar Jun 03 '20 08:06 gilles-peskine-arm

By the way, all the write_xxx_pem functions do write a terminating 0 (unless they fail, in which case the content of the output buffer is indeterminate). You're right, this should be documented.

gilles-peskine-arm avatar Jun 03 '20 08:06 gilles-peskine-arm

The method that mbed TLS its base64 uses (pass a null buffer pointer/len) and have ret return the actual length needed - works generally well. And limits the API signature changes.

dirkx avatar Oct 23 '21 08:10 dirkx

We can change the functions to take an extra parameter to return the needed size in Mbed TLS 3.0.

Just informing it is not yet implemented.

filimonic avatar Nov 18 '23 19:11 filimonic

Thanks for the bump. It definitely missed the boat for 3.0. I've added it to the 4.0 list.

gilles-peskine-arm avatar Nov 20 '23 12:11 gilles-peskine-arm

This is a general problem with all the DER and PEM writing functions: mbedtls_pk_write_key_der, mbedtls_pk_write_key_pem, mbedtls_pk_write_pubkey_der, mbedtls_pk_write_pubkey_pem, mbedtls_x509write_crt_der, mbedtls_x509write_crt_pem, mbedtls_x509write_csr_der, mbedtls_x509write_csr_pem. For the key writing functions, it isn't so bad because it's relatively easy to find a sensible buffer size knowing the key size and the key type. But for certificates and certificate signing requests, the data includes variable-length strings so you have to know exactly what's in the data to calculate the size.

We can change the functions to take an extra parameter to return the needed size in Mbed TLS 3.0. But we may want to add new functions before 3.0 comes out (we wouldn't change the signature of an existing function within the same major version of Mbed TLS).

Regardless of the interface, this requires a non-negligible amount of new code, so we wouldn't add it to the long-time support branches (2.7 and 2.16), only to a 2.x.

Hi. Could you help me to recognize how i can calculate buffer size for key using mbedtls_pk_write_pubkey_der function. Thank you.

TemplateVoid avatar Jan 18 '24 09:01 TemplateVoid

@TemplateVoid What I wrote above may have been misleading. It's possible to find a buffer size, because for a key of the given type and size, there's a fixed amount of data in the DER, and the only variation on size comes from integers with leading zeros. (DER requires leading zeros to be stripped.) So it would be possible to define a macro MBEDTLS_PK_PUBKEY_DER_MAX_SIZE like there is MBEDTLS_PK_SIGNATURE_MAX_SIZE and PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE. This is in contrast with certificates, where there's no meaningful maximum size since it depends on variable data, such as the length and count of names that are signed.

However, Mbed TLS does not currently define a macro like this. So if you need one, you'll have to define it yourself. In practice, generate a few keys and look at the maximum size and round up a bit. (For RSA, a larger modulus bit-size means a larger public key. For ECC, it's a bit more complicated because the metadata includes a curve name, and larger curves don't necessarily have larger names.)

gilles-peskine-arm avatar Jan 18 '24 12:01 gilles-peskine-arm

I'd not be overly optimistic here - X509 certificates can contain a lot of metadata; many kilo-bytes in common scenarios around cross-signing, policy statements (esp. for IOT stuff near medical and payments), SAML and multi-CA/root certificates. The latter getting increasingly common as the CA market consolidates/ACME certs become the norm. And IoT is disproportionately affected here.

dirkx avatar Jan 18 '24 13:01 dirkx