Hi Dmitrii!
The reason why we focused on DTLS 1.2 + AEAD for the context serialization was because that's
what we needed to support quickly at the time, and not because we saw some fundamental
technical obstacles in implementing context serialization for TLS 1.2.
I did the same as you, commenting out DTLS checks, and ran into the same problem during
`mbedtls_cipher_auth_decrypt()`. The problem turns out to be the following: In TLS, the
context contains an incoming record counter which, while in DTLS, the record counter
is explicit and hence need not be maintained.
In particular, when using the current serialization+deserialization functions with TLS 1.2,
the incoming record counter will be corrupted.
The core of the fix is simple: You need to duplicate https://github.com/ARMmbed/mbedtls/blob/development/library/ssl_tls.c#L6228…
and https://github.com/ARMmbed/mbedtls/blob/development/library/ssl_tls.c#L6496… -- which save/load the _outgoing_ counter --
for the incoming counter `ssl->in_ctr`. I just tried this and things worked afterwards.
Could you try and see if it works for you, too? If so, please feel free to adapt the serialization
functions and file a PR to add support for serialization in TLS, and mark me as a reviewer.
Note: There will likely be other things that need fixing, too, so please be careful in
using the above patch as-is unless for experimentation.
Cheers,
Hanno
________________________________
From: mbed-tls <mbed-tls-bounces(a)lists.trustedfirmware.org> on behalf of Kuvaiskii, Dmitrii via mbed-tls <mbed-tls(a)lists.trustedfirmware.org>
Sent: Tuesday, March 31, 2020 8:58 PM
To: mbed-tls(a)lists.trustedfirmware.org <mbed-tls(a)lists.trustedfirmware.org>
Subject: [mbed-tls] TLS context serialization: can it be done?
Dear all,
I have the following question. mbedTLS v2.21.0 has support for TLS context serialization in the form of two functions: `mbedtls_ssl_context_save()` and `mbedtls_ssl_context_load()`. I'm trying to use these functions in another project (Graphene, an Intel SGX framework). Slightly oversimplifying, I want to establish a secure communication channel between two different Linux processes. I'd like to persist one of them and then re-spawn it again with the communication channel intact (so that there is no need for a new TLS handshake).
However, I notice that currently these functions support only DTLS 1.2, see e.g.: https://github.com/ARMmbed/mbedtls/blob/aaabe86ac1f47193f4fc499846a0b3abeae…
But I want to use a normal TLS channel, in particular with a ciphersuite `MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256`.
I commented out the checks on DTLS in these functions just to see what will happen. As expected, both functions serialized and then deserialized the context, but when doing a `write(ssl_ctx)` in one (not-persisted) process and a `read(loaded_ssl_ctx)` in another (re-spawned) process, I get an error in `mbedtls_cipher_auth_decrypt()`. Clearly, my deserialized context didn't restore some vital information on the TLS session, and this led to failure in decryption.
Thus, I have two questions:
1. Is there any version of this code that also works on TLS?
2. What are the additional internal objects that must be serialized for TLS (if it makes things easier, in my particular case with AES-GCM and a pre-shared key)? I looked at the code and tried to dump more fields in `mbedtls_ssl_transform`, but it didn't help much. If you'd provide me with some pointers, I could tinker more with mbedTLS code and hopefully make it work.
Thanks in advance for any pointers!
--
Dmitrii
--
mbed-tls mailing list
mbed-tls(a)lists.trustedfirmware.org
https://lists.trustedfirmware.org/mailman/listinfo/mbed-tls
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.
Dear all,
I have the following question. mbedTLS v2.21.0 has support for TLS context serialization in the form of two functions: `mbedtls_ssl_context_save()` and `mbedtls_ssl_context_load()`. I'm trying to use these functions in another project (Graphene, an Intel SGX framework). Slightly oversimplifying, I want to establish a secure communication channel between two different Linux processes. I'd like to persist one of them and then re-spawn it again with the communication channel intact (so that there is no need for a new TLS handshake).
However, I notice that currently these functions support only DTLS 1.2, see e.g.: https://github.com/ARMmbed/mbedtls/blob/aaabe86ac1f47193f4fc499846a0b3abeae…
But I want to use a normal TLS channel, in particular with a ciphersuite `MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256`.
I commented out the checks on DTLS in these functions just to see what will happen. As expected, both functions serialized and then deserialized the context, but when doing a `write(ssl_ctx)` in one (not-persisted) process and a `read(loaded_ssl_ctx)` in another (re-spawned) process, I get an error in `mbedtls_cipher_auth_decrypt()`. Clearly, my deserialized context didn't restore some vital information on the TLS session, and this led to failure in decryption.
Thus, I have two questions:
1. Is there any version of this code that also works on TLS?
2. What are the additional internal objects that must be serialized for TLS (if it makes things easier, in my particular case with AES-GCM and a pre-shared key)? I looked at the code and tried to dump more fields in `mbedtls_ssl_transform`, but it didn't help much. If you'd provide me with some pointers, I could tinker more with mbedTLS code and hopefully make it work.
Thanks in advance for any pointers!
--
Dmitrii
Dear Hanno,
Thank you for the explanations! I came to the same implementation yesterday after some extensive testing.
Just for reference, I created a repo with my testing environment: https://github.com/dimakuv/mbedtls-psk-example. The diff with a quick-and-dirty fix to mbedTLS 2.21.0 is here: https://github.com/dimakuv/mbedtls-psk-example/blob/master/mbedtls-2.21.0.d….
I'll be happy to contribute this (with proper macros, updated comments, etc.) to mbedTLS. Should I base my PR on the "development" branch? Also, how should it be tested, with a couple default config.h configurations?
--
Dmitrii
From: Hanno Becker <Hanno.Becker(a)arm.com>
Sent: Thursday, April 2, 2020 12:58 AM
To: mbed-tls(a)lists.trustedfirmware.org; Kuvaiskii, Dmitrii <dmitrii.kuvaiskii(a)intel.com>
Subject: Re: TLS context serialization: can it be done?
Hi Dmitrii!
The reason why we focused on DTLS 1.2 + AEAD for the context serialization was because that's
what we needed to support quickly at the time, and not because we saw some fundamental
technical obstacles in implementing context serialization for TLS 1.2.
I did the same as you, commenting out DTLS checks, and ran into the same problem during
`mbedtls_cipher_auth_decrypt()`. The problem turns out to be the following: In TLS, the
context contains an incoming record counter which, while in DTLS, the record counter
is explicit and hence need not be maintained.
In particular, when using the current serialization+deserialization functions with TLS 1.2,
the incoming record counter will be corrupted.
The core of the fix is simple: You need to duplicate https://github.com/ARMmbed/mbedtls/blob/development/library/ssl_tls.c#L6228…
and https://github.com/ARMmbed/mbedtls/blob/development/library/ssl_tls.c#L6496… -- which save/load the _outgoing_ counter --
for the incoming counter `ssl->in_ctr`. I just tried this and things worked afterwards.
Could you try and see if it works for you, too? If so, please feel free to adapt the serialization
functions and file a PR to add support for serialization in TLS, and mark me as a reviewer.
Note: There will likely be other things that need fixing, too, so please be careful in
using the above patch as-is unless for experimentation.
Cheers,
Hanno
________________________________
From: mbed-tls <mbed-tls-bounces(a)lists.trustedfirmware.org<mailto:mbed-tls-bounces@lists.trustedfirmware.org>> on behalf of Kuvaiskii, Dmitrii via mbed-tls <mbed-tls(a)lists.trustedfirmware.org<mailto:mbed-tls@lists.trustedfirmware.org>>
Sent: Tuesday, March 31, 2020 8:58 PM
To: mbed-tls(a)lists.trustedfirmware.org<mailto:mbed-tls@lists.trustedfirmware.org> <mbed-tls(a)lists.trustedfirmware.org<mailto:mbed-tls@lists.trustedfirmware.org>>
Subject: [mbed-tls] TLS context serialization: can it be done?
Dear all,
I have the following question. mbedTLS v2.21.0 has support for TLS context serialization in the form of two functions: `mbedtls_ssl_context_save()` and `mbedtls_ssl_context_load()`. I'm trying to use these functions in another project (Graphene, an Intel SGX framework). Slightly oversimplifying, I want to establish a secure communication channel between two different Linux processes. I'd like to persist one of them and then re-spawn it again with the communication channel intact (so that there is no need for a new TLS handshake).
However, I notice that currently these functions support only DTLS 1.2, see e.g.: https://github.com/ARMmbed/mbedtls/blob/aaabe86ac1f47193f4fc499846a0b3abeae…
But I want to use a normal TLS channel, in particular with a ciphersuite `MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256`.
I commented out the checks on DTLS in these functions just to see what will happen. As expected, both functions serialized and then deserialized the context, but when doing a `write(ssl_ctx)` in one (not-persisted) process and a `read(loaded_ssl_ctx)` in another (re-spawned) process, I get an error in `mbedtls_cipher_auth_decrypt()`. Clearly, my deserialized context didn't restore some vital information on the TLS session, and this led to failure in decryption.
Thus, I have two questions:
1. Is there any version of this code that also works on TLS?
2. What are the additional internal objects that must be serialized for TLS (if it makes things easier, in my particular case with AES-GCM and a pre-shared key)? I looked at the code and tried to dump more fields in `mbedtls_ssl_transform`, but it didn't help much. If you'd provide me with some pointers, I could tinker more with mbedTLS code and hopefully make it work.
Thanks in advance for any pointers!
--
Dmitrii
--
mbed-tls mailing list
mbed-tls(a)lists.trustedfirmware.org<mailto:mbed-tls@lists.trustedfirmware.org>
https://lists.trustedfirmware.org/mailman/listinfo/mbed-tls
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.
Dear Dmitrii,
PR https://github.com/ARMmbed/mbedtls/pull/2791 introduced testing for the existing DTLS serialization functionality,
so if you make sure that the tests introduced there are replicated also for the TLS serialization, that's a good start for sure.
The relevant test changes are in `all.sh`, `ssl-opt.sh`, `test_suite_ssl.function` and `ssl_client2.c` and `ssl_server2.c`.
That said, if you feel it's tricky to find your way through the test system, feel free to do as much as you can,
open a PR, and we'll take it from there.
The PR should be based on `development`.
Cheers,
Hanno
________________________________
From: Kuvaiskii, Dmitrii <dmitrii.kuvaiskii(a)intel.com>
Sent: Thursday, April 2, 2020 4:23 PM
To: Hanno Becker <Hanno.Becker(a)arm.com>; mbed-tls(a)lists.trustedfirmware.org <mbed-tls(a)lists.trustedfirmware.org>
Subject: RE: TLS context serialization: can it be done?
Dear Hanno,
Thank you for the explanations! I came to the same implementation yesterday after some extensive testing.
Just for reference, I created a repo with my testing environment: https://github.com/dimakuv/mbedtls-psk-example. The diff with a quick-and-dirty fix to mbedTLS 2.21.0 is here: https://github.com/dimakuv/mbedtls-psk-example/blob/master/mbedtls-2.21.0.d….
I’ll be happy to contribute this (with proper macros, updated comments, etc.) to mbedTLS. Should I base my PR on the “development” branch? Also, how should it be tested, with a couple default config.h configurations?
--
Dmitrii
From: Hanno Becker <Hanno.Becker(a)arm.com>
Sent: Thursday, April 2, 2020 12:58 AM
To: mbed-tls(a)lists.trustedfirmware.org; Kuvaiskii, Dmitrii <dmitrii.kuvaiskii(a)intel.com>
Subject: Re: TLS context serialization: can it be done?
Hi Dmitrii!
The reason why we focused on DTLS 1.2 + AEAD for the context serialization was because that's
what we needed to support quickly at the time, and not because we saw some fundamental
technical obstacles in implementing context serialization for TLS 1.2.
I did the same as you, commenting out DTLS checks, and ran into the same problem during
`mbedtls_cipher_auth_decrypt()`. The problem turns out to be the following: In TLS, the
context contains an incoming record counter which, while in DTLS, the record counter
is explicit and hence need not be maintained.
In particular, when using the current serialization+deserialization functions with TLS 1.2,
the incoming record counter will be corrupted.
The core of the fix is simple: You need to duplicate https://github.com/ARMmbed/mbedtls/blob/development/library/ssl_tls.c#L6228…
and https://github.com/ARMmbed/mbedtls/blob/development/library/ssl_tls.c#L6496… -- which save/load the _outgoing_ counter --
for the incoming counter `ssl->in_ctr`. I just tried this and things worked afterwards.
Could you try and see if it works for you, too? If so, please feel free to adapt the serialization
functions and file a PR to add support for serialization in TLS, and mark me as a reviewer.
Note: There will likely be other things that need fixing, too, so please be careful in
using the above patch as-is unless for experimentation.
Cheers,
Hanno
________________________________
From: mbed-tls <mbed-tls-bounces(a)lists.trustedfirmware.org<mailto:mbed-tls-bounces@lists.trustedfirmware.org>> on behalf of Kuvaiskii, Dmitrii via mbed-tls <mbed-tls(a)lists.trustedfirmware.org<mailto:mbed-tls@lists.trustedfirmware.org>>
Sent: Tuesday, March 31, 2020 8:58 PM
To: mbed-tls(a)lists.trustedfirmware.org<mailto:mbed-tls@lists.trustedfirmware.org> <mbed-tls(a)lists.trustedfirmware.org<mailto:mbed-tls@lists.trustedfirmware.org>>
Subject: [mbed-tls] TLS context serialization: can it be done?
Dear all,
I have the following question. mbedTLS v2.21.0 has support for TLS context serialization in the form of two functions: `mbedtls_ssl_context_save()` and `mbedtls_ssl_context_load()`. I'm trying to use these functions in another project (Graphene, an Intel SGX framework). Slightly oversimplifying, I want to establish a secure communication channel between two different Linux processes. I'd like to persist one of them and then re-spawn it again with the communication channel intact (so that there is no need for a new TLS handshake).
However, I notice that currently these functions support only DTLS 1.2, see e.g.: https://github.com/ARMmbed/mbedtls/blob/aaabe86ac1f47193f4fc499846a0b3abeae…
But I want to use a normal TLS channel, in particular with a ciphersuite `MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256`.
I commented out the checks on DTLS in these functions just to see what will happen. As expected, both functions serialized and then deserialized the context, but when doing a `write(ssl_ctx)` in one (not-persisted) process and a `read(loaded_ssl_ctx)` in another (re-spawned) process, I get an error in `mbedtls_cipher_auth_decrypt()`. Clearly, my deserialized context didn't restore some vital information on the TLS session, and this led to failure in decryption.
Thus, I have two questions:
1. Is there any version of this code that also works on TLS?
2. What are the additional internal objects that must be serialized for TLS (if it makes things easier, in my particular case with AES-GCM and a pre-shared key)? I looked at the code and tried to dump more fields in `mbedtls_ssl_transform`, but it didn't help much. If you'd provide me with some pointers, I could tinker more with mbedTLS code and hopefully make it work.
Thanks in advance for any pointers!
--
Dmitrii
--
mbed-tls mailing list
mbed-tls(a)lists.trustedfirmware.org<mailto:mbed-tls@lists.trustedfirmware.org>
https://lists.trustedfirmware.org/mailman/listinfo/mbed-tls
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.
Hi Jeremy,
Thank you for your reply.
> Having said that, on my side, I access three fields of this structure:
* sslContext.state
* sslContext.own_cid_len
* sslContext.own_cid
The first one is used to retrieve the current state, mainly MBEDTLS_SSL_HANDSHAKE_OVER, MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT.
Finally, the match between an incoming LwM2M Client encrypted message using CID and the structure mbedtls_ssl_session is done by accessing own_cid / own_cid_len. But I think this one could be done using mbedtls_ssl_get_peer_cid().
Note that you're talking about the SSL context here, not the SSL session, which the thread asked about. That said, we're intending to make the SSL context internal as well, so your feedback is very valuable.
For the SSL handshake state: I agree that we will likely want to introduce a getter function for this as we make the SSL context internal and have created https://github.com/ARMmbed/mbedtls/issues/4383 to track this.
For the CID, I am not following your use case yet: sslContext.own_cid is what you configure yourself via mbedtls_ssl_conf_cid(), so there's no need to query it from the context. The CID that the peer requested can be queried via mbedtls_ssl_get_peer_cid(), as you say. Does that make sense?
Regards,
Hanno
________________________________
From: Jérémy Audiger <jeremy.audiger(a)ioterop.com>
Sent: Monday, April 19, 2021 5:42 PM
To: mbed-tls(a)lists.trustedfirmware.org <mbed-tls(a)lists.trustedfirmware.org>; Hanno Becker <Hanno.Becker(a)arm.com>
Subject: Re: SSL session cache API in Mbed TLS 3.0
Hi Hanno,
Regarding your first point, I'm not against having the structure mbedtls_ssl_session as opaque on the application side, at least, it ensures the application is not modifying something that it shouldn't. Having said that, on my side, I access three fields of this structure:
* sslContext.state
* sslContext.own_cid_len
* sslContext.own_cid
The first one is used to retrieve the current state, mainly MBEDTLS_SSL_HANDSHAKE_OVER, MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT.
Finally, the match between an incoming LwM2M Client encrypted message using CID and the structure mbedtls_ssl_session is done by accessing own_cid / own_cid_len. But I think this one could be done using mbedtls_ssl_get_peer_cid().
Regards,
Jérémy
________________________________
From: mbed-tls <mbed-tls-bounces(a)lists.trustedfirmware.org> on behalf of Hanno Becker via mbed-tls <mbed-tls(a)lists.trustedfirmware.org>
Sent: Friday, April 16, 2021 06:37
To: mbed-tls(a)lists.trustedfirmware.org <mbed-tls(a)lists.trustedfirmware.org>
Subject: [mbed-tls] SSL session cache API in Mbed TLS 3.0
Hi Mbed TLS enthusiasts,
For Mbed TLS 3.0, we're considering to modify the API around SSL sessions and server-side SSL session caches as follows:
1) The mbedtls_ssl_session structure becomes opaque, that is, its layout, fields, size is not part of the API and thus not subject to any stability promises.
Instances of mbedtls_ssl_session may only be accessed through public function API. At the time of writing, this is mainly
mbedtls_ssl_session_load()/save() for session serialization and deserialization. In particular, user code requiring access to
specific fields of mbedtls_ssl_session won't be portable without further adjustments, e.g. the addition of getter functions.
If you access fields of mbedtls_ssl_session in your code and would like to retain the ability to do so,
now is the time to speak up and let us know about your use case.
2) The SSL session cache API gets modified as proposed in https://github.com/ARMmbed/mbedtls/issues/4333#issuecomment-820297322:
int mbedtls_ssl_cache_get( void *data,
unsigned char const *session_id,
size_t session_id_len,
mbedtls_ssl_session *dst_session );
int mbedtls_ssl_cache_set( void *data,
unsigned char const *session_id,
size_t session_id_len,
mbedtls_ssl_session const *session );
In words: The session ID becomes an explicit parameter.
This modification is necessary because the present session cache API requires custom implementations to peek into the
mbedtls_ssl_session structure, at least to inspect the session ID. With the session ID being added as an explicit parameter,
this is no longer necessary.
We propose that custom session cache implementations treat mbedtls_ssl_session instances opaquely and only use them through
the serialization and deserialization API mbedtls_ssl_session_load()/save(). The reason why the proposed API does not operate on
serialized data directly is that this would enforce unnecessary copies.
If you are using a custom SSL server-side session cache implementation which accesses fields other than the session ID and which can not
be implemented based on session serialization, now is the time to speak up and let us know about your use case.
Kind regards,
Hanno
Hi Jérémy,
Thanks for your question! Indeed, the context (de)serialization feature only support DTLS so far. We've added an enhancement request to our backlog to extend it to TLS: https://github.com/ARMmbed/mbedtls/issues/4340
However, it may take some time before we get to it, as we're currently focused on preparing Mbed TLS 3.0. Also, this enhancement may very well turn out to be more complex that it might look initially: TLS is a reliable stream protocol (as opposed to DTLS which is an unreliable datagram protocol) and there will probably be some precautions to take and corner case to handle in order to make sure the full stream is preserved.
If you or anyone else wants to open a PR for that, that would obviously help - though again, I'm afraid we'll have little review bandwidth until the end of June. (More generally, it's always a good idea to coordinate on the list before raising a large or complex PR.)
Regards,
Manuel.
________________________________
From: mbed-tls <mbed-tls-bounces(a)lists.trustedfirmware.org> on behalf of Jérémy Audiger via mbed-tls <mbed-tls(a)lists.trustedfirmware.org>
Sent: 12 April 2021 18:39
To: mbed-tls(a)lists.trustedfirmware.org <mbed-tls(a)lists.trustedfirmware.org>
Subject: [mbed-tls] TLS serialization
Hi everyone,
I'm currently trying to add the ability to serialize / deserialize a TLS security session using these APIs:
* mbedtls_ssl_context_load()
* mbedtls_ssl_context_save()
I'm on TLS Server-side (so not talking about TLS Client here). After digging through the mailing list, I discovered this previous topic: https://lists.trustedfirmware.org/pipermail/mbed-tls/2020-April/000012.html and this Github repository: https://github.com/dimakuv/mbedtls-psk-example
The scenario is the same here: using PSK with ciphersuite MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8
Once the handshake is done, I'm able to serialize the TLS session with the patch attached to this email. After that I'm able to decrypt one incoming packet and encrypt one ongoing packet. So, almost everything is fine. But, when the TLS Server is receiving another message from the TLS Client (message sent in two fragments), the Server is able to decrypt the first fragment but not the second one, getting this error:
ssl_msg.c:5475: 0x7f9aa803d288: => read
ssl_msg.c:4029: 0x7f9aa803d288: => read record
ssl_msg.c:2012: 0x7f9aa803d288: => fetch input
ssl_msg.c:2167: 0x7f9aa803d288: in_left: 0, nb_want: 5
ssl_msg.c:2192: 0x7f9aa803d288: in_left: 0, nb_want: 5
ssl_msg.c:2195: 0x7f9aa803d288: ssl->f_recv(_timeout)() returned 5 (-0xfffffffb)
ssl_msg.c:2215: 0x7f9aa803d288: <= fetch input
ssl_msg.c:3763: 0x7f9aa803d288: dumping 'input record header' (5 bytes)
ssl_msg.c:3763: 0x7f9aa803d288: 0000: 17 03 03 00 41 ....A
ssl_msg.c:3765: 0x7f9aa803d288: input record: msgtype = 23, version = [3:3], msglen = 65
ssl_msg.c:2012: 0x7f9aa803d288: => fetch input
ssl_msg.c:2167: 0x7f9aa803d288: in_left: 5, nb_want: 70
ssl_msg.c:2192: 0x7f9aa803d288: in_left: 5, nb_want: 70
ssl_msg.c:2195: 0x7f9aa803d288: ssl->f_recv(_timeout)() returned 65 (-0xffffffbf)
ssl_msg.c:2215: 0x7f9aa803d288: <= fetch input
ssl_msg.c:3874: 0x7f9aa803d288: dumping 'input record from network' (70 bytes)
ssl_msg.c:3874: 0x7f9aa803d288: 0000: 17 03 03 00 41 00 00 00 00 00 00 00 03 27 9d 1a ....A........'..
ssl_msg.c:3874: 0x7f9aa803d288: 0010: 50 14 ff e1 14 8c b0 f5 de 06 1c f0 43 5c a0 91 P...........C\..
ssl_msg.c:3874: 0x7f9aa803d288: 0020: 46 23 3e 42 86 ed 3a 48 38 3d e8 b4 05 09 50 ac F#>B..:H8=....P.
ssl_msg.c:3874: 0x7f9aa803d288: 0030: 94 6b 9c fb c6 22 7b 46 62 e0 af 08 ab 60 50 3c .k..."{Fb....`P<
ssl_msg.c:3874: 0x7f9aa803d288: 0040: 6d c6 c8 7c cb 2c m..|.,
ssl_msg.c:1301: 0x7f9aa803d288: => decrypt buf
ssl_msg.c:1414: 0x7f9aa803d288: dumping 'additional data used for AEAD' (13 bytes)
ssl_msg.c:1414: 0x7f9aa803d288: 0000: 00 00 00 00 00 00 00 02 17 03 03 00 31 ............1
ssl_msg.c:1423: 0x7f9aa803d288: dumping 'IV used' (12 bytes)
ssl_msg.c:1423: 0x7f9aa803d288: 0000: db 70 01 4b 00 00 00 00 00 00 00 03 .p.K........
ssl_msg.c:1424: 0x7f9aa803d288: dumping 'TAG used' (8 bytes)
ssl_msg.c:1424: 0x7f9aa803d288: 0000: 50 3c 6d c6 c8 7c cb 2c P<m..|.,
ssl_msg.c:1437: 0x7f9aa803d288: mbedtls_cipher_auth_decrypt() returned -25344 (-0x6300)
ssl_msg.c:3900: 0x7f9aa803d288: ssl_decrypt_buf() returned -29056 (-0x7180)
Between each emission or reception of the fragment, the TLS security context is loaded and saved into a database. The use case here is really interesting, it seems to work well except when I receive or emit a message split into multiple fragments. Something is lost during the session backup.
Maybe an interesting thing to add is when I'm loading a TLS session from the database, I'm following these steps:
* Load the session into a buffer from the database
* Init a security session with mbedtls_ssl_init() and mbedtls_ssl_setup()
* Load the session from the buffer with mbedtls_ssl_context_load()
Since I'm not an expert of mbed TLS code, I would like to know if someone could help me investigate this issue. TLS serialization/deserialization could be interesting to be part of the mbed TLS library.
Regards,
Jérémy Audiger
Hi Manuel,
At least, the issue is now tracked. Thanks for your additional feedback, this is mainly what we also thought. It would have been too easy if the patch was working with few lines of changes.
My team and I are not mbed TLS experts, not sure if we can provide help here. But if you need some testers, just let me know.
Regards,
Jérémy
________________________________
From: Manuel Pegourie-Gonnard <Manuel.Pegourie-Gonnard(a)arm.com>
Sent: Wednesday, April 14, 2021 12:16
To: mbed-tls(a)lists.trustedfirmware.org <mbed-tls(a)lists.trustedfirmware.org>; Jérémy Audiger <jeremy.audiger(a)ioterop.com>
Subject: Re: TLS serialization
Hi Jérémy,
Thanks for your question! Indeed, the context (de)serialization feature only support DTLS so far. We've added an enhancement request to our backlog to extend it to TLS: https://github.com/ARMmbed/mbedtls/issues/4340
However, it may take some time before we get to it, as we're currently focused on preparing Mbed TLS 3.0. Also, this enhancement may very well turn out to be more complex that it might look initially: TLS is a reliable stream protocol (as opposed to DTLS which is an unreliable datagram protocol) and there will probably be some precautions to take and corner case to handle in order to make sure the full stream is preserved.
If you or anyone else wants to open a PR for that, that would obviously help - though again, I'm afraid we'll have little review bandwidth until the end of June. (More generally, it's always a good idea to coordinate on the list before raising a large or complex PR.)
Regards,
Manuel.
________________________________
From: mbed-tls <mbed-tls-bounces(a)lists.trustedfirmware.org> on behalf of Jérémy Audiger via mbed-tls <mbed-tls(a)lists.trustedfirmware.org>
Sent: 12 April 2021 18:39
To: mbed-tls(a)lists.trustedfirmware.org <mbed-tls(a)lists.trustedfirmware.org>
Subject: [mbed-tls] TLS serialization
Hi everyone,
I'm currently trying to add the ability to serialize / deserialize a TLS security session using these APIs:
* mbedtls_ssl_context_load()
* mbedtls_ssl_context_save()
I'm on TLS Server-side (so not talking about TLS Client here). After digging through the mailing list, I discovered this previous topic: https://lists.trustedfirmware.org/pipermail/mbed-tls/2020-April/000012.html and this Github repository: https://github.com/dimakuv/mbedtls-psk-example
The scenario is the same here: using PSK with ciphersuite MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8
Once the handshake is done, I'm able to serialize the TLS session with the patch attached to this email. After that I'm able to decrypt one incoming packet and encrypt one ongoing packet. So, almost everything is fine. But, when the TLS Server is receiving another message from the TLS Client (message sent in two fragments), the Server is able to decrypt the first fragment but not the second one, getting this error:
ssl_msg.c:5475: 0x7f9aa803d288: => read
ssl_msg.c:4029: 0x7f9aa803d288: => read record
ssl_msg.c:2012: 0x7f9aa803d288: => fetch input
ssl_msg.c:2167: 0x7f9aa803d288: in_left: 0, nb_want: 5
ssl_msg.c:2192: 0x7f9aa803d288: in_left: 0, nb_want: 5
ssl_msg.c:2195: 0x7f9aa803d288: ssl->f_recv(_timeout)() returned 5 (-0xfffffffb)
ssl_msg.c:2215: 0x7f9aa803d288: <= fetch input
ssl_msg.c:3763: 0x7f9aa803d288: dumping 'input record header' (5 bytes)
ssl_msg.c:3763: 0x7f9aa803d288: 0000: 17 03 03 00 41 ....A
ssl_msg.c:3765: 0x7f9aa803d288: input record: msgtype = 23, version = [3:3], msglen = 65
ssl_msg.c:2012: 0x7f9aa803d288: => fetch input
ssl_msg.c:2167: 0x7f9aa803d288: in_left: 5, nb_want: 70
ssl_msg.c:2192: 0x7f9aa803d288: in_left: 5, nb_want: 70
ssl_msg.c:2195: 0x7f9aa803d288: ssl->f_recv(_timeout)() returned 65 (-0xffffffbf)
ssl_msg.c:2215: 0x7f9aa803d288: <= fetch input
ssl_msg.c:3874: 0x7f9aa803d288: dumping 'input record from network' (70 bytes)
ssl_msg.c:3874: 0x7f9aa803d288: 0000: 17 03 03 00 41 00 00 00 00 00 00 00 03 27 9d 1a ....A........'..
ssl_msg.c:3874: 0x7f9aa803d288: 0010: 50 14 ff e1 14 8c b0 f5 de 06 1c f0 43 5c a0 91 P...........C\..
ssl_msg.c:3874: 0x7f9aa803d288: 0020: 46 23 3e 42 86 ed 3a 48 38 3d e8 b4 05 09 50 ac F#>B..:H8=....P.
ssl_msg.c:3874: 0x7f9aa803d288: 0030: 94 6b 9c fb c6 22 7b 46 62 e0 af 08 ab 60 50 3c .k..."{Fb....`P<
ssl_msg.c:3874: 0x7f9aa803d288: 0040: 6d c6 c8 7c cb 2c m..|.,
ssl_msg.c:1301: 0x7f9aa803d288: => decrypt buf
ssl_msg.c:1414: 0x7f9aa803d288: dumping 'additional data used for AEAD' (13 bytes)
ssl_msg.c:1414: 0x7f9aa803d288: 0000: 00 00 00 00 00 00 00 02 17 03 03 00 31 ............1
ssl_msg.c:1423: 0x7f9aa803d288: dumping 'IV used' (12 bytes)
ssl_msg.c:1423: 0x7f9aa803d288: 0000: db 70 01 4b 00 00 00 00 00 00 00 03 .p.K........
ssl_msg.c:1424: 0x7f9aa803d288: dumping 'TAG used' (8 bytes)
ssl_msg.c:1424: 0x7f9aa803d288: 0000: 50 3c 6d c6 c8 7c cb 2c P<m..|.,
ssl_msg.c:1437: 0x7f9aa803d288: mbedtls_cipher_auth_decrypt() returned -25344 (-0x6300)
ssl_msg.c:3900: 0x7f9aa803d288: ssl_decrypt_buf() returned -29056 (-0x7180)
Between each emission or reception of the fragment, the TLS security context is loaded and saved into a database. The use case here is really interesting, it seems to work well except when I receive or emit a message split into multiple fragments. Something is lost during the session backup.
Maybe an interesting thing to add is when I'm loading a TLS session from the database, I'm following these steps:
* Load the session into a buffer from the database
* Init a security session with mbedtls_ssl_init() and mbedtls_ssl_setup()
* Load the session from the buffer with mbedtls_ssl_context_load()
Since I'm not an expert of mbed TLS code, I would like to know if someone could help me investigate this issue. TLS serialization/deserialization could be interesting to be part of the mbed TLS library.
Regards,
Jérémy Audiger
Hi everyone,
I'm currently trying to add the ability to serialize / deserialize a TLS security session using these APIs:
* mbedtls_ssl_context_load()
* mbedtls_ssl_context_save()
I'm on TLS Server-side (so not talking about TLS Client here). After digging through the mailing list, I discovered this previous topic: https://lists.trustedfirmware.org/pipermail/mbed-tls/2020-April/000012.html and this Github repository: https://github.com/dimakuv/mbedtls-psk-example
The scenario is the same here: using PSK with ciphersuite MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8
Once the handshake is done, I'm able to serialize the TLS session with the patch attached to this email. After that I'm able to decrypt one incoming packet and encrypt one ongoing packet. So, almost everything is fine. But, when the TLS Server is receiving another message from the TLS Client (message sent in two fragments), the Server is able to decrypt the first fragment but not the second one, getting this error:
ssl_msg.c:5475: 0x7f9aa803d288: => read
ssl_msg.c:4029: 0x7f9aa803d288: => read record
ssl_msg.c:2012: 0x7f9aa803d288: => fetch input
ssl_msg.c:2167: 0x7f9aa803d288: in_left: 0, nb_want: 5
ssl_msg.c:2192: 0x7f9aa803d288: in_left: 0, nb_want: 5
ssl_msg.c:2195: 0x7f9aa803d288: ssl->f_recv(_timeout)() returned 5 (-0xfffffffb)
ssl_msg.c:2215: 0x7f9aa803d288: <= fetch input
ssl_msg.c:3763: 0x7f9aa803d288: dumping 'input record header' (5 bytes)
ssl_msg.c:3763: 0x7f9aa803d288: 0000: 17 03 03 00 41 ....A
ssl_msg.c:3765: 0x7f9aa803d288: input record: msgtype = 23, version = [3:3], msglen = 65
ssl_msg.c:2012: 0x7f9aa803d288: => fetch input
ssl_msg.c:2167: 0x7f9aa803d288: in_left: 5, nb_want: 70
ssl_msg.c:2192: 0x7f9aa803d288: in_left: 5, nb_want: 70
ssl_msg.c:2195: 0x7f9aa803d288: ssl->f_recv(_timeout)() returned 65 (-0xffffffbf)
ssl_msg.c:2215: 0x7f9aa803d288: <= fetch input
ssl_msg.c:3874: 0x7f9aa803d288: dumping 'input record from network' (70 bytes)
ssl_msg.c:3874: 0x7f9aa803d288: 0000: 17 03 03 00 41 00 00 00 00 00 00 00 03 27 9d 1a ....A........'..
ssl_msg.c:3874: 0x7f9aa803d288: 0010: 50 14 ff e1 14 8c b0 f5 de 06 1c f0 43 5c a0 91 P...........C\..
ssl_msg.c:3874: 0x7f9aa803d288: 0020: 46 23 3e 42 86 ed 3a 48 38 3d e8 b4 05 09 50 ac F#>B..:H8=....P.
ssl_msg.c:3874: 0x7f9aa803d288: 0030: 94 6b 9c fb c6 22 7b 46 62 e0 af 08 ab 60 50 3c .k..."{Fb....`P<
ssl_msg.c:3874: 0x7f9aa803d288: 0040: 6d c6 c8 7c cb 2c m..|.,
ssl_msg.c:1301: 0x7f9aa803d288: => decrypt buf
ssl_msg.c:1414: 0x7f9aa803d288: dumping 'additional data used for AEAD' (13 bytes)
ssl_msg.c:1414: 0x7f9aa803d288: 0000: 00 00 00 00 00 00 00 02 17 03 03 00 31 ............1
ssl_msg.c:1423: 0x7f9aa803d288: dumping 'IV used' (12 bytes)
ssl_msg.c:1423: 0x7f9aa803d288: 0000: db 70 01 4b 00 00 00 00 00 00 00 03 .p.K........
ssl_msg.c:1424: 0x7f9aa803d288: dumping 'TAG used' (8 bytes)
ssl_msg.c:1424: 0x7f9aa803d288: 0000: 50 3c 6d c6 c8 7c cb 2c P<m..|.,
ssl_msg.c:1437: 0x7f9aa803d288: mbedtls_cipher_auth_decrypt() returned -25344 (-0x6300)
ssl_msg.c:3900: 0x7f9aa803d288: ssl_decrypt_buf() returned -29056 (-0x7180)
Between each emission or reception of the fragment, the TLS security context is loaded and saved into a database. The use case here is really interesting, it seems to work well except when I receive or emit a message split into multiple fragments. Something is lost during the session backup.
Maybe an interesting thing to add is when I'm loading a TLS session from the database, I'm following these steps:
* Load the session into a buffer from the database
* Init a security session with mbedtls_ssl_init() and mbedtls_ssl_setup()
* Load the session from the buffer with mbedtls_ssl_context_load()
Since I'm not an expert of mbed TLS code, I would like to know if someone could help me investigate this issue. TLS serialization/deserialization could be interesting to be part of the mbed TLS library.
Regards,
Jérémy Audiger
Hi Abhilash,
> I am trying to do the ECDH shared secret computation using the mbedTLS
> library. I am referring to multiple examples such as ecdh_curve25519.c
> and ecdh_main.c.
>
Ok. You should probably know a few things about those examples:
1. They both perform what's known as "ephemeral ECDH" (or sometimes ECDHE).
2. They're both using the low-level part of our ECDH API. For ecdh_curve25519,
that is because that curve is not supported by the higher-level API yet - for
the other example, I don't know what the reason is.
3. Curve25519 is quite different from other curves regarding how public keys
are represented.
> In my case, in my application firmware, I already have a device _priv
> key and I receive a server_public key; both generated using a curve
> ECP_DP_SECP256R1 in the bootloader itself. So in the application
> firmware, I would like to do generate a shared secret from here on and
> preserve it for future use.
>
Ok, so you want to do what's known as "static ECDH". So the example
ecdh_curve25519 is not a great example, due to points 1 and 3 above. Also,
since the curve you're using supports it, you may want to use the higher-level
part of our ECDH API (the functions that accept a context as an argument).
> The following is the steps that I do:
>
> 1. Create a new client context, entropy context, ctr_drbg context variables.
> 2. use mbedtls_"respective"_init() to initalize all the three variables
> 3. Seed a random number using mbedtls_ctr_drbg_seed() function.
> 4. load the P256 elliptic curve in client context using mbedtls_ecp_group_load()
All this looks absolutely correct.
> 5. Then use mbedtls_mpi_lset() to set Qp.Z =1
> 6. Then read the server pub key using mbedtls_mpi_read_binary(&ctx_cli.Qp.X, server_pub, 65);
>From the 65 I assume that the server public key as encoded as an uncompressed
point. Then you can read it with:
mbedtls_ecp_point_read_binary(&ctx_cli.grp, &ctx_cli.Qp, server_pub, 65);
(For Curve25519 mbedtls_ecp_point_read_binary() isn't implemented yet which is
why the example does a direct call to an MPI function and accesses individual
point coordinates, but Curve25519 and P-256 don't use the same coordinate
systems.)
> 7. Now the question is: Should I initialize the ctx_cli with my already generated device_priv key using
> mbedtls_mpi_read_binary(&ctx_cli.d, device_priv_key, 50) ?
That looks almost correct, except 50 does not look like a valid size for a
private key for the curve you're using.
> 8. Then I use mbedtls_ecdh_compute_shared(&ctx_cli.grp, &ctx_cli.z, &ctx_cli.Qp, &ctx_cli.d, mbedtls_ctr_drbg_random, &ctr_drbg); to compute the shared secret in z.
>
That's correct, but you could also call
mbedtls_ecdh_calc_secret( &ctx_cli, &olen, buf, blen,
mbedtls_ctr_drbg_random, &ctr_drbg );
which also serializes the secret to a buffer.
> Questions:
> 1. Do I need to generate a keypair for client context using
> mbedtls_ecdh_gen_public(&ctx_cli.grp, &ctx_cli.d, &ctx_cli.Q,
> mbedtls_ctr_drbg_random, &ctrDrbg)? And then set pvtkey as device priv
> key and pub key as service pub key?
>
I'm not sure I understand the context of the question, so I'll distinguish
two cases:
- When provisioning the device, you need to generate a key pair for it, which
can indeed be done as show.
- Once the device is working, it doesn't need to generate new key pairs, just
load the one that was provisioned as described below.
> 2. I see that ctx_cli.Q has two components, Q.x and Q.y. How do I
> extract these two values from a public key? Do I need to separately
> initialize them?
>
I don't recommend you manipulate those directly, but use the
`mbedtls_ecp_point_{read,write}_binary()` functions instead.
> Please let me know if the flow is correct. In all the examples, they
> generate a key pair and just update the public key part (Qp.X) of the
> key. They do not touch the private key part (d) of the key. Please
> confirm if I can upload my private key directly in my case.
>
Your flow looks correct, and the difference from the examples is that they're
demonstrating ephemeral ECDH while it looks like you want to do static ECDH.
> Also if my platform is a little endian, is there a recommended step
> before using mbedtls_mpi_read_binary_le functions?
Then endianness of your plaftorm should not matter, and you shouldn't need to
use that function.
Regards,
Manuel.
Hi all,
this will be a long mail. Sorry for that.
In the past weeks I've been using mbedTLS 2.16.5 for implementing
crypto on an ARM Cortex M4 (STM32F479). This was my first experience
with mbedTLS, but I have some (almost 20 years) experience with
applied and high-assurance crypto. So maybe the following thoughts fit
into the discussion of plans for version 3.0 of Mbed TLS.
In the end, I achieved everything that was required for my project with
mbedTLS, but some things surprised me or it took a while to find out.
I'll enumerate the following points for easier reference. Nothing of
the following is meant to embarrass anyone, just my personal thoughts.
1. I really missed an Initialize, Update, Finalize (IUF) interface for
CCM.
For GCM, we have mbedtls_gcm_init(), mbedtls_gcm_setkey(),
mbedtls_gcm_starts(), mbedtls_gcm_update() iterated,
mbedtls_gcm_finish(), mbedtls_gcm_free() or the comfort functions
mbedtls_gcm_crypt_and_tag() and mbedtls_gcm_auth_decrypt(). For
CCM, only mbedtls_ccm_init(), mbedtls_ccm_setkey(),
mbedtls_ccm_encrypt_and_tag() or mbedtls_ccm_auth_decrypt() and
mbedtls_ccm_free(). With this interface it was only possible to
encrypt and tag 128 kByte on my target system, while with GCM I
could encrypt much larger files.
see Github issue #662 and my comment there
2. The next step, of course, is to integrate this into the higher
mbedtls_cipher layer.
Regarding higher, abstract layers: I often didn't understand which
interface I was supposed to use. In general, I like to use the
lowest available interface, for example, #include
"mbedtls/sha512.h" when I want to use sha512. However, if I need
HMAC-SHA-512 or HKDF-HMAC-SHA-512 then I have to use the interface
in md.h. For hash functions this is fine. Almost all hash functions
are supported via md.h. (I missed SHA-512/256 which is sometimes
preferable to SHA-256 on 64bit systems).
But with cipher.h, I can only access Chacha20Poly1305 and AES-GCM,
not AES-CCM.
3. For certification and evaluation purposes I need some test vectors
for each crypto function on target. While I know about the
comprehensive self-test program I'm now talking about built-in
functions like mbedtls_sha512_self_test(), etc to be enabled with
#define MBEDTLS_SELF_TEST.
These self-tests are very different in coverage. For SHA-384 and
SHA-512 they are fine, for HMAC-SHA-384 and HMAC-SHA-512 I couldn't
find any as well as for HKDF-HMAC-SHA-256 (in RFC 5869) or
HKDF-HMAC-SHA-384/512 (official test vectors difficult to find).
AES-CTR and AES-XTS are only tested with key length 128 bit, not with
256 bit. AES-CCM is not tested with 256 bit and even for 128 bit,
the test vector from the standard NIST SP 800-38C with long
additional data is not used.
The builtin self-test for GCM is the best I've seen with mbedtls:
all three key lengths are tested as well as the IUF-interface and
the comfort function. Bravo!
4. That I couldn't configure AES-256 only, i.e. without AES-128 and
AES-192, was to be expected (and the code overhead is not that
much). But in modern modes of operations nobody needs AES
decryption, only the forward direction. Sometimes modern
publications as Schwabe/Stoffelen "All the AES you need on
Cortex-M3 and M4" provide only the forward direction.
So, it would be fine if one could configure an AES (ECB) encryption
only without decryption.
Of course, this is only possible if we don't use CBC mode, etc.
This wouldn't only save the AES decryption code but also the rather
large T-tables for decryption.
5. Regarding AES or better the AES context-type definition
typedef struct mbedtls_aes_context
{
int nr; /*!< The number of rounds. */
uint32_t *rk; /*!< AES round keys. */
uint32_t buf[68]; /*!< Unaligned data buffer. This buffer can
hold 32 extra Bytes, which can be
used for
one of the following purposes:
<ul><li>Alignment if VIA padlock is
used.</li>
<li>Simplifying key expansion in
the 256-bit
case by generating an extra
round key.
</li></ul> */
}
mbedtls_aes_context;
I really don't understand why we need additional 2176 bit in EVERY
AES context. I would understand 128 bit (one block size) or even 512
bit (for example for CTR optimization which is not used!). But 2176
bit in every AES context? The VIA padlock is not very common, I
suppose. But even if it were, this doesn't justify such memory
overhead.
How wasteful this is, one can see in the next type definition
/**
* \brief The AES XTS context-type definition.
*/
typedef struct mbedtls_aes_xts_context
{
mbedtls_aes_context crypt; /*!< The AES context to use for AES block
encryption or decryption. */
mbedtls_aes_context tweak; /*!< The AES context used for tweak
computation. */
} mbedtls_aes_xts_context;
The tweak context is for the encryption of exactly 128 bit, not
more.
6. In general, the contexts of mbedTLS are rather full of
implementation specific details. Most extreme is mbedtls_ecp_group
in ecp.h. Wouldn't it be clearer if one separates the standard
things (domain parameters in this case) from implementation
specific details?
7. While at Elliptic Curve Cryptography: I assume that some of you
know that projectives coordinates as outer interface to ECC are
dangerous, see David Naccache, Nigel P. Smart, Jacques Stern:
Projective Coordinates Leak, Eurocrypt 2004, pp. 257–267.
Therefore, the usual interface in ECC standards are either affine
points or compressed affine points (Okay, with the modern curves
Curve25519 and Curve 448 it's X only.).
Now with
/**
* \brief The ECP point structure, in Jacobian coordinates.
*
* \note All functions expect and return points satisfying
* the following condition: <code>Z == 0</code> or
* <code>Z == 1</code>. Other values of \p Z are
* used only by internal functions.
* The point is zero, or "at infinity", if <code>Z ==
0</code>.
* Otherwise, \p X and \p Y are its standard (affine)
* coordinates.
*/
typedef struct mbedtls_ecp_point
{
mbedtls_mpi X; /*!< The X coordinate of the ECP point. */
mbedtls_mpi Y; /*!< The Y coordinate of the ECP point. */
mbedtls_mpi Z; /*!< The Z coordinate of the ECP point. */
}
mbedtls_ecp_point;
you have Jacobian coordinates, i.e. projective coordinates, as outer
interface. In the comment, its is noted that only the affine part is
used, but can this be assured? In all circumstances?
8. In my personal opinion the definition
/**
* \brief The ECP key-pair structure.
*
* A generic key-pair that may be used for ECDSA and fixed ECDH, for
example.
*
* \note Members are deliberately in the same order as in the
* ::mbedtls_ecdsa_context structure.
*/
typedef struct mbedtls_ecp_keypair
{
mbedtls_ecp_group grp; /*!< Elliptic curve and base point */
mbedtls_mpi d; /*!< our secret value */
mbedtls_ecp_point Q; /*!< our public value */
}
mbedtls_ecp_keypair;
is dangerous. Why not differentiate between private and public key
and domain parameters? How often does it happen by accident with
this structure that you give the private key (unneeded and
dangerous) together with the public key to ECDSA signature
verification? Obviously this was known (and perhaps it happened) to
the authors of programs\ecdsa.c with the following comment
/*
* Transfer public information to verifying context
*
* We could use the same context for verification and signatures, but we
* chose to use a new one in order to make it clear that the verifying
* context only needs the public key (Q), and not the private key (d).
*/
What is sometimes useful, is to have the public key at hand when you
have performed a private key operation (as countermeasure against
fault attacks, verify after signing). But for ECC the verification
procedure if often too expensive (in contrast to cheap RSA verify).
9. Regarding ECC examples: I found it very difficult that there isn't
a single example with known test vectors as in the relevant crypto
standards, i.e. FIPS 186-4 and ANSI X9.62-2005, with raw public
keys. What I mean are (defined) curves, public key value Q=(Qx,Qy)
and known signature values r and s. In the example ecdsa.c you
generate your own key pair and read/write the signature in
serialized form. In the example programs/pkey/pk_sign.c and
pk_verify.c you use a higher interface pk.h and keys in PEM format.
So, it took me a while for a program to verify (all) known answer
tests in the standards (old standards as ANSI X9.62 1998 have more
detailed known answer tests). One needs this interface with raw
public keys for example for CAVP tests, see The FIPS 186-4 Elliptic
Curve Digital Signature Algorithm Validation System (ECDSA2VS).
10. While debugging mbedtls_ecdsa_verify() in my example program, I
found out, that the ECDSA, ECC and MPI operations are very, let's
say, nested. So, IMHO there is a lot of function call overhead and
special cases. It would be interesting to see what's the
performance impact of a clean, straight-forward
mbedtls_ecdsa_verify without restartable code, etc. to the current
one.
11. In the moment, there is no single known answer tests for ECDSA
(which could be activated with #define MBEDTLS_SELF_TEST). I
wouldn't say that you need an example for every curve and hash
combination, as it is done in ECDSA2VS CAVP, but one example for
one of the NIST curves and one for Curve25519 and - if I have a
wish free - one for Brainpool would be fine. And this would solve
#9 above.
12. Just a minor issue: I only needed ECDSA signature verification,
therefore I only included MBEDTLS_ASN1_PARSE_C. But it is not
possible to compile without MBEDTLS_ASN1_WRITE_C needed for ECDSA
signature generation.
13. Feature request: Since it was irrelevant for my task (only
verification, no generation) I didn't have a detailed look a your
ECC side-channel countermeasures. But obviously you use the same
protected code for scalar multiplication in verify and sign,
right? Wouldn't it be possible to use Shamir's trick in
verification with fast unprotected multi-scalar multiplication. In
the moment, mbedtls_ecdsa_verify is a factor 4-5 slower than
mbedtls_ecdsa_sign, while OpenSSLs verify is faster than sign.
14. Design question: In the moment, both GCM and CCM use their own
implementation of CTR encryption which is very simple. But then we
have mbedtls_aes_crypt_ctr() in aes.h which is very simple, too.
Let's assume at one day we have a performance optimized CTR
encryption (for example from Schwabe & Stoffelen) with all fancy
stuff like counter-mode caching etc. Then this would have to be
replaced at three places at minimum. While isn't the code at this
point more modularized? Is this a dedicated design decision?
Why do I find at so many places
for( i = 0; i < 16; i++ )
y[i] ^= b[i];
instead of a fast 128-bit XOR macro with 32bit aligned data?
So, that's it for the moment. I hope I could give some hints for the
further development of mbedTLS. Feel free to discuss any of the above
points. It's clear to me that we cannot have both: clear and simple to
understand code and performance records.
Ciao,
Torsten