Does mbedtls has API to get the size of CSR data

I had gone through CSR generation code from programs/x509/cert_req.c, and it uses 4K buffer to get the CSR data. I had a flow in openssl, and the CSR data size was just around 500 bytes for PEM format.
So, we are allocating quite a lot.

I am looking for an API to get the size of CSR data before calling mbedtls_x509write_csr_xx.
As my requirement is DER data, so, taking an example from openssl to clarify the requirement.

int i2d_X509_REQ(X509_REQ *a, unsigned char **pp);

It returns back the size of data and also allocates the memory in case *pp is NULL.
Thanks for your help.

Hi @divneil
Thank you for your interest in Mbed TLS!
Please note, that cert_write is a sample application for reference, and in your code you can change the size of the output buffer. However, mbedtls_x509write_csr_pem() also uses 4KB of RAM, and this is something we want to avoid. If you avoid PEM and call mbedtls_x509write_csr_der() you will use only 2 KB of RAM.
As for your question, unfortunately, at the moment, we don’t have such an API.
As you can probably see in our repository, we are working on reducing RAM usage in the library, X509 being the key module as it exploits the most amount of RAM. We will take into consideration your findings.
Thanks again for your question!
regards,
Mbed TLS Team member
Ron

Hi @roneld01

Thanks for your reply.
I will reduce the buffer allocation to 2KB, since, my requirement is DER.

Can I infer that, mbedTLS uses the buffer as scratchpad, and then finally writes CSR data to the buffer?
One more question, is there any specific reason that the DER CSR data is written at the end bytes of buffer?

Regards,
Divneil

Hi @divneil

Can I infer that, mbedTLS uses the buffer as scratchpad, and then finally writes CSR data to the buffer?

I am not sure what you mean.
The buffer you give for the mbedtls_x509write_csr_der() API, is the output buffer.
Inside this API, there is another 2KB buffer, which is used as a scratchpad

One more question, is there any specific reason that the DER CSR data is written at the end bytes of buffer?

To be honest I am not sure, as it was written a long time, however I can assume it is because you know the length of the data you write only after you wrote it. THis is the way the ASN1 functionality is implemented. So, you can’t write the length of the extension, for example, until you actually wrote the extension. Does this make sense?

Of course, you can first measure the length of the data, and then write the length, and then the data, however this is an overhead in performance which is unnecessary.
Regards

Hi @roneld01

I am not sure what you mean.
The buffer you give for the mbedtls_x509write_csr_der() API, is the output buffer.
Inside this API, there is another 2KB buffer, which is used as a scratchpad

Oh! okay.
I mixed the context then. In the first reply, you mentioned about the buffer requirement as follows:
o PEM : 4KB
o DER : 2KB
I co-related it with the example code (programs/x509/cert_req.c) where the user is also allocating 4KB for PEM. So, I thought you are suggesting me to allocate 2KB for DER before giving that buffer to mbedtls_x509write_csr_der().

Since, you said, you are working on size optimizations, so, I thought of checking : Is the user allocated 4KB getting used for scratchpad, because, I want to allocate far less. So, the question changes to :slight_smile: : what is recommended buffer size which should be allocated by user?

To be honest I am not sure, as it was written a long time, however I can assume it is because you know the length of the data you write only after you wrote it. THis is the way the ASN1 functionality is implemented. So, you can’t write the length of the extension, for example, until you actually wrote the extension. Does this make sense?

I am unable to co-relate to the answer, so, likely my question was not clear :neutral_face:
I am allocating a 4KB buffer to store the CSR and after calling mbedtls_x509write_csr_der() the buffer looks like:

Data: xxxxxxxxxx........xxxxxxxcsrdata
Mem : 0123..................3k.......4k

PEM (mbedtls_x509write_csr_pem()) buffer looks like:

Data: pem header csr data pem footerxxxxxxxxxx........xxxxxxx
Mem : 0123........................................3k.......4k

DER data starts at offset = size and PEM starts at offset = 0. So, was interested to know the filling strategy, as it’s different in 2 APIs. If it’s already answered above by you, then I need to thoroughly look again. :eyes:

Regards,
Divneil

Hi ,

Is the user allocated 4KB getting used for scratchpad, because, I want to allocate far less.
Not at the moment. At the moment, the user allocated buffer is only used as an output buffer, and there is a scratchpad buffer used internally. As you can see in this PR the size optimizations are on the certificate writing, and not csr writing, but the changes should be similar.

As for your question on the filling strategy, I am not sure why there is a difference at the moment, but as mentione din the documentation:

 *                  Note: data is written at the end of the buffer! Use the
 *                        return value to determine where you should start
 *                        using the buffer

One correction on your comment, in DER, the data starts at offset = size - ret
Regards

Hi @roneld01

Thanks for sharing all the information.

Last question to close the discussion.
Are you aware of the worst case size of DER CSR? It seems to be 2KB then. Can you please confirm.

One correction on your comment, in DER, the data starts at offset = size - ret

True. My bad :wink:

Regards,
Divneil

Hi @divneil
The size is very much dependent on what extensions you wish, what key sizes are used, etc…
I cannot confirm what is the worst case in your scenario. For example, using RSA 8Kb key size, 2KB of buffer should suffice, unless you have many extensions. However, if you are using an ECC key, then 2 KB should be more than enough, but it varies according to your use case.

Thanks @roneld01 for sharing the information. :slight_smile: