Mbed TLS is now part of TrustedFirmware.org.

Howto determine exact buffer len for mbedtls_pk_write_pubkey_der?


Jan 4, 2016 21:07
Thomas Glanzmann

Hello, I'm writing a patch for curl to allow public key pinning for the mbedtls backend. My patch used a static buffer. One reviewer told me that I should allocate the necessary memory. I tried to find a function which returns to me the necessary size. I was not able to hence this post? Which function can I use to determine the exact buffer size necessary to store a x509 key in der format?

Until I have something better I use the following:

    pubkey_len = mbedtls_pk_get_len(&crt->pk);
    /* FIXME: How to determine the exact size necessary? */
    pubkey_len *= 2;
    pubkey = malloc(pubkey_len);
    size = mbedtls_pk_write_pubkey_der(&crt->pk, pubkey, pubkey_len);

The pull request with the current state is here:

https://github.com/bagder/curl/pull/589

Cheers, Thomas

 
Jan 5, 2016 10:24
Manuel Pégourié-Gonnard

Good question! I'm afraid we currently don't offer the function you're looking for. Unfortunately, I'm not sure it would be easy to add.

The code you're currently using is a good idea and should work with most real-world RSA keys (that use a short public exponent), but it will unfortunately not work with EC keys as is (not tested, but I don't think it will work). For formulas that should work of all keys (that is, unless I made a mistake), you can look here for RSA and here for ECC.

Actually I'm starting to wonder if we should just move those definitions from pkwrite.c to pk.h so that you can use them directly...

You can either use that as the size of a static buffer as we do in pk_write_pubkey_pem() or replace the MAX_SIZE part of the formulas with the return value of pk_get_len() for your particular key and then allocate a buffer of the corresponding size. Please note that this will not be the optimal size, especially for RSA keys (the public exponent is usually 24 bits tough it can be as large as the size of the key in theory).

Another, entirely different approach, is to start by allocating a buffer of a reasonable size, try writing the key to it, if it works you're done, otherwise double the size of the buffer and iterate.

 
Jan 5, 2016 10:34
Zdenek OGAR Skalak

Could it be possible to implement mbedtls_pk_write_pubkey_der() to accept the (xx,NULL,0) paramaters and just calculate (not so hard for ASN1) the length and return it?

On the second round, you will allocate the buffer and call the function again with REAL arguments ....

 
Jan 5, 2016 11:16
Manuel Pégourié-Gonnard

Yes, that's possible and that's probably the right thing to do. However, we've already quite a lot on our plate, so I can't make any guarantees as to when this will happen, so in the meantime you might want to implement one of the other strategies.

 
Jan 5, 2016 12:15
Thomas Glanzmann

Hello Manual, I used your approach. But there is something you should change in the source code. The defines are not surrounded by brackets. So when I used them first it failed for me and I wondered why until I realized that. So I strongly advise to use brackets when you put them in the public header file:

#define RSA_PUB_DER_MAX_BYTES   (38 + 2 * MBEDTLS_MPI_MAX_SIZE)
#define ECP_PUB_DER_MAX_BYTES   (30 + 2 * MBEDTLS_ECP_MAX_BYTES)

#define PUB_DER_MAX_BYTES   (RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
                            RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES)

If I should make a patch ready, let me know. Zdenek, this is how openssl does it btw. :-)

Cheers, Thomas

 
Jan 7, 2016 11:25
Manuel Pégourié-Gonnard

Good point! If I make those define public, I'll use brackets.

Anyway, glad it now works for you!