In TLS 1.3, one half of an ECDH exchange is defined as a "key entry", coded as:
struct { NamedGroup group; opaque key_exchange<1..2^16-1>; } KeyShareEntry;
The opaque data is typically encoded as a one byte format (e.g., 0x04, no compression), and then the encoding of either one or two points: 32 bytes for one point with CURVE25519, 64 bytes for two points with SECP256R1.
The encoding for the "public key" output of mbedtls_ecdh_make_params is different: 1 byte of length, followed by 2 bytes of curve ID, followed by the raw encoding of the point or points. The related encoding of the server public key output of mbedtls_ecdh_make_public is also different: 1 byte of length, followed by 2 bytes of curve ID, followed by the raw encoding of the point or points.
To make that work, I need some reformatting: strip out 3 bytes for the client public key, write a single 0x04 byte instead; strip out one byte from the key-exchange data received at the server and write 3 bytes of length and curve ID instead. Also, make sure to reset the strings to the unmodified value before calling mbedtls_ecdh_calc_secret, which probably means maintaining two copies, thus twice the memory.
This is a bit messy, and probably unnecessary. The extra parameters "length" is already passed through the API (the &olen argument) and the "group_id" could easily be passed as well.
Or maybe I am looking at the wrong API...
-- Christian Huitema
Hi Christian,
There are three ECDH APIs in Mbed TLS:
1. One of them is using low level data structures like `mbedtls_ecp_point`, `mbedtls_mpi` and `mbedtls_ecp_group` 2. The other is operating on `mbedtls_ecdh_context` and buffers 3. The last one implements PSA Crypto APIhttps://armmbed.github.io/mbed-crypto/html/api/ops/ka.html
In Mbed TLS only the TLS 1.2 implementation uses the second option and that is why it is geared towards that. The TLS 1.3 implementation in Mbed TLS uses the PSA Crypto API and in general that is the recommended/future proof option.
I hope that helps.
Best wishes, Janos (Mbed TLS developer)
From: Christian Huitema via mbed-tls mbed-tls@lists.trustedfirmware.org Date: Tuesday, 12 September 2023 at 04:50 To: mbed-tls@lists.trustedfirmware.org mbed-tls@lists.trustedfirmware.org Subject: [mbed-tls] Output format of mbedtls_ecdh_make_params does not play well with TLS 1.3 In TLS 1.3, one half of an ECDH exchange is defined as a "key entry", coded as:
struct { NamedGroup group; opaque key_exchange<1..2^16-1>; } KeyShareEntry;
The opaque data is typically encoded as a one byte format (e.g., 0x04, no compression), and then the encoding of either one or two points: 32 bytes for one point with CURVE25519, 64 bytes for two points with SECP256R1.
The encoding for the "public key" output of mbedtls_ecdh_make_params is different: 1 byte of length, followed by 2 bytes of curve ID, followed by the raw encoding of the point or points. The related encoding of the server public key output of mbedtls_ecdh_make_public is also different: 1 byte of length, followed by 2 bytes of curve ID, followed by the raw encoding of the point or points.
To make that work, I need some reformatting: strip out 3 bytes for the client public key, write a single 0x04 byte instead; strip out one byte from the key-exchange data received at the server and write 3 bytes of length and curve ID instead. Also, make sure to reset the strings to the unmodified value before calling mbedtls_ecdh_calc_secret, which probably means maintaining two copies, thus twice the memory.
This is a bit messy, and probably unnecessary. The extra parameters "length" is already passed through the API (the &olen argument) and the "group_id" could easily be passed as well.
Or maybe I am looking at the wrong API...
-- Christian Huitema -- mbed-tls mailing list -- mbed-tls@lists.trustedfirmware.org To unsubscribe send an email to mbed-tls-leave@lists.trustedfirmware.org
Thanks, Janos. It does help. I approached this by looking at the code, and I was confused by the presence of these three classes of API. I would obviously go for the generic API rather than the low level API, and I had no problem doing that for AEAD algorithms following the examples in `aead_demo.c`. But for the key exchange algorithm I stumbled onto `ecdh_curve25519.c`, which uses your class 2 algorithms.
I will move to the PSA Crypto API.
On 9/12/2023 1:05 AM, Janos Follath wrote:
Hi Christian,
There are three ECDH APIs in Mbed TLS:
- One of them is using low level data structures like `mbedtls_ecp_point`, `mbedtls_mpi` and `mbedtls_ecp_group`
- The other is operating on `mbedtls_ecdh_context` and buffers
- The last one implements PSA Crypto API https://armmbed.github.io/mbed-crypto/html/api/ops/ka.html
In Mbed TLS only the TLS 1.2 implementation uses the second option and that is why it is geared towards that. The TLS 1.3 implementation in Mbed TLS uses the PSA Crypto API and in general that is the recommended/future proof option.
I hope that helps.
Best wishes,
Janos
(Mbed TLS developer)
*From: *Christian Huitema via mbed-tls mbed-tls@lists.trustedfirmware.org *Date: *Tuesday, 12 September 2023 at 04:50 *To: *mbed-tls@lists.trustedfirmware.org mbed-tls@lists.trustedfirmware.org *Subject: *[mbed-tls] Output format of mbedtls_ecdh_make_params does not play well with TLS 1.3
In TLS 1.3, one half of an ECDH exchange is defined as a "key entry", coded as:
struct { NamedGroup group; opaque key_exchange<1..2^16-1>; } KeyShareEntry;
The opaque data is typically encoded as a one byte format (e.g., 0x04, no compression), and then the encoding of either one or two points: 32 bytes for one point with CURVE25519, 64 bytes for two points with SECP256R1.
The encoding for the "public key" output of mbedtls_ecdh_make_params is different: 1 byte of length, followed by 2 bytes of curve ID, followed by the raw encoding of the point or points. The related encoding of the server public key output of mbedtls_ecdh_make_public is also different: 1 byte of length, followed by 2 bytes of curve ID, followed by the raw encoding of the point or points.
To make that work, I need some reformatting: strip out 3 bytes for the client public key, write a single 0x04 byte instead; strip out one byte from the key-exchange data received at the server and write 3 bytes of length and curve ID instead. Also, make sure to reset the strings to the unmodified value before calling mbedtls_ecdh_calc_secret, which probably means maintaining two copies, thus twice the memory.
This is a bit messy, and probably unnecessary. The extra parameters "length" is already passed through the API (the &olen argument) and the "group_id" could easily be passed as well.
Or maybe I am looking at the wrong API...
-- Christian Huitema
mbed-tls mailing list -- mbed-tls@lists.trustedfirmware.org To unsubscribe send an email to mbed-tls-leave@lists.trustedfirmware.org
By the way, I have a similar question regarding mbedtls_ctr_drbg_random. I assume that I should use psa_generate_random instead, but I do not see the PSA equivalents of mbedtls_ctr_drbg_seed or mbedtls_entropy_func. Is it correct to assume that these are handled "under the hood", for example by psa_crypto_init?
-- Christian Huitema
On 9/12/2023 8:05 AM, Christian Huitema via mbed-tls wrote:
Thanks, Janos. It does help. I approached this by looking at the code, and I was confused by the presence of these three classes of API. I would obviously go for the generic API rather than the low level API, and I had no problem doing that for AEAD algorithms following the examples in `aead_demo.c`. But for the key exchange algorithm I stumbled onto `ecdh_curve25519.c`, which uses your class 2 algorithms.
I will move to the PSA Crypto API.
On 9/12/2023 1:05 AM, Janos Follath wrote:
Hi Christian,
There are three ECDH APIs in Mbed TLS:
1. One of them is using low level data structures like `mbedtls_ecp_point`, `mbedtls_mpi` and `mbedtls_ecp_group` 2. The other is operating on `mbedtls_ecdh_context` and buffers 3. The last one implements PSA Crypto API https://armmbed.github.io/mbed-crypto/html/api/ops/ka.html In Mbed TLS only the TLS 1.2 implementation uses the second option and that is why it is geared towards that. The TLS 1.3 implementation in Mbed TLS uses the PSA Crypto API and in general that is the recommended/future proof option.
I hope that helps.
Best wishes,
Janos
(Mbed TLS developer)
*From: *Christian Huitema via mbed-tls mbed-tls@lists.trustedfirmware.org *Date: *Tuesday, 12 September 2023 at 04:50 *To: *mbed-tls@lists.trustedfirmware.org mbed-tls@lists.trustedfirmware.org *Subject: *[mbed-tls] Output format of mbedtls_ecdh_make_params does not play well with TLS 1.3
In TLS 1.3, one half of an ECDH exchange is defined as a "key entry", coded as:
struct { NamedGroup group; opaque key_exchange<1..2^16-1>; } KeyShareEntry;
The opaque data is typically encoded as a one byte format (e.g., 0x04, no compression), and then the encoding of either one or two points: 32 bytes for one point with CURVE25519, 64 bytes for two points with SECP256R1.
The encoding for the "public key" output of mbedtls_ecdh_make_params is different: 1 byte of length, followed by 2 bytes of curve ID, followed by the raw encoding of the point or points. The related encoding of the server public key output of mbedtls_ecdh_make_public is also different: 1 byte of length, followed by 2 bytes of curve ID, followed by the raw encoding of the point or points.
To make that work, I need some reformatting: strip out 3 bytes for the client public key, write a single 0x04 byte instead; strip out one byte from the key-exchange data received at the server and write 3 bytes of length and curve ID instead. Also, make sure to reset the strings to the unmodified value before calling mbedtls_ecdh_calc_secret, which probably means maintaining two copies, thus twice the memory.
This is a bit messy, and probably unnecessary. The extra parameters "length" is already passed through the API (the &olen argument) and the "group_id" could easily be passed as well.
Or maybe I am looking at the wrong API...
-- Christian Huitema
mbed-tls mailing list -- mbed-tls@lists.trustedfirmware.org To unsubscribe send an email to mbed-tls-leave@lists.trustedfirmware.org
On 12/09/2023 19:50, Christian Huitema via mbed-tls wrote:
By the way, I have a similar question regarding mbedtls_ctr_drbg_random. I assume that I should use psa_generate_random instead, but I do not see the PSA equivalents of mbedtls_ctr_drbg_seed or mbedtls_entropy_func. Is it correct to assume that these are handled "under the hood", for example by psa_crypto_init?
That's correct. psa_crypto_init() seeds a PRNG. psa_generate_random() produces output from this PRNG and reseeds periodically.
Under the hood, by default, the entropy sources are the same as mbedtls_entropy_func() and the DRBG is the one from the CTR_DRBG module with its default configuration.
By the way, if you have working code using the mbedtls crypto API and you want to migrate to the PSA API, you may be interested in this guide (not yet reviewed): https://github.com/Mbed-TLS/mbedtls/pull/7766
Best regards,
Thanks, Gilles.
I am stumbling on a ChaCha20 issue for now. I am implementing section 5.4.4 of RFC 9001 (https://www.rfc-editor.org/rfc/rfc9001.html#name-chacha20-based-header-prote), which requires using ChaCha20 with a 32 bits counter and a 12 bytes nonce.
The PSA spec says: call to psa_cipher_set_iv() on a multi-part cipher operation can support the following IV sizes:
12 bytes: the provided IV is used as the nonce, and the counter value is set to zero. 16 bytes: the first four bytes of the IV are used as the counter value (encoded as little-endian), and the remaining 12 bytes is used as the nonce.
Good! the 16 bytes version is exactly what I need. But I get a failed check in
psa_status_t mbedtls_psa_cipher_set_iv( mbedtls_psa_cipher_operation_t *operation, const uint8_t *iv, size_t iv_length) { if (iv_length != operation->iv_length) { return PSA_ERROR_INVALID_ARGUMENT; } ...
I am setting the IV length to 16, but operation->iv_length is set to 12...
I assume that I am doing something wrong. The series of calls is:
1) ptls_mbedtls_cipher_setup_key, with PSA_ALG_STREAM_CIPHER, and PSA_KEY_TYPE_CHACHA20
2) psa_cipher_encrypt_setup, with the computed key and alg=PSA_ALG_STREAM_CIPHER
3) psa_cipher_set_iv, with 16 bytes IV, which fails.
Is there some sample that I can look at?
-- Christian Huitema
On 9/12/2023 1:12 PM, Gilles Peskine via mbed-tls wrote:
On 12/09/2023 19:50, Christian Huitema via mbed-tls wrote:
By the way, I have a similar question regarding mbedtls_ctr_drbg_random. I assume that I should use psa_generate_random instead, but I do not see the PSA equivalents of mbedtls_ctr_drbg_seed or mbedtls_entropy_func. Is it correct to assume that these are handled "under the hood", for example by psa_crypto_init?
That's correct. psa_crypto_init() seeds a PRNG. psa_generate_random() produces output from this PRNG and reseeds periodically.
Under the hood, by default, the entropy sources are the same as mbedtls_entropy_func() and the DRBG is the one from the CTR_DRBG module with its default configuration.
By the way, if you have working code using the mbedtls crypto API and you want to migrate to the PSA API, you may be interested in this guide (not yet reviewed): https://github.com/Mbed-TLS/mbedtls/pull/7766
Best regards,
Hi Christian,
Mbed TLS doesn't support the 16-byte variant yet. Currently the initial counter value is always 0 with the PSA API and with the legacy cipher API. https://github.com/Mbed-TLS/mbedtls/issues/5616
You can use a different ICV with the low-level mbedtls_chacha20_xxx API.
Best regards,
On 9/13/2023 12:28 AM, Gilles Peskine via mbed-tls wrote:
Hi Christian,
Mbed TLS doesn't support the 16-byte variant yet. Currently the initial counter value is always 0 with the PSA API and with the legacy cipher API. https://github.com/Mbed-TLS/mbedtls/issues/5616
You can use a different ICV with the low-level mbedtls_chacha20_xxx API.
Best regards,
Thanks, that's what I did.
I have verified that the PSA API work well for AES 128 and 256, ECB and CTR. I also verified that the APIs in chacha20.h for CHACHA20 work. When the 16-byte variant is supported, I will switch to using the PSA API for CHACHA20 as well.
The PSA API appears to work for all the AEAD variants that I need, including with ChaChaPoly.
-- Christian Huitema
mbed-tls@lists.trustedfirmware.org