Dear Mbed TLS team,
I am at the early steps of trying to integrate Mbed TLS with LWIP for our project (imx rt 1024 NXP micro, arm M7, running FreeRTOS and LWIP). I understand the basics of TLS, but I am far from an expert.
Let me first apologise for the lengthy first email. I am afraid to leave out details. Feel free to skip directly to the end marked with:
=============================
My questions:
=============================
Some background / translation of how I think it (should) work:
From a distance, I understand that LWIP has an abstraction layer on their TCP module, which can be used to integrate Mbed TLS.
In fact, LWIP already did this, all I need to do is enable some directives (LWIP_ALTCP_TLS and LWIP_ALTCP_TLS_MBEDTLS).
The implemented integration assumes a somewhat older version of Mbed TLS, so I have to adjust a couple to cope with the breaking changes from Mbed TLS 2.x to Mbed TLS 3.6.2.
But other than that, integrating Mbed TLS would mean:
- figure out which options i want to enable in Mbed TLS
- cross compile it for our arm toolchain
- extend our build scripts to compile against 3 static Mbed TLS libraries
- figure out how to read the CA certificates, and provide them to Mbed TLS
- test and fail, and hopefully be man enough to solve the challenges ahead...
I haven't achieved much yet, but at least I managed to compile Mbed TLS with our toolchain and recompile our project against the linked libraries. This steps fails though, I get a bunch of linker errors :
[100%] Linking CXX executable app.axf
/opt/gcc-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/13.2.1/../../../../arm-none-eabi/bin/ld: /home/dev/app/source/iobox-app/../../thirdparty/mbedtls/build/library/libmbedtls.a(ssl_msg.c.obj): in function `mbedtls_ssl_encrypt_buf':
/home/dev/app/thirdparty/mbedtls/library/ssl_msg.c:1211:(.text.mbedtls_ssl_encrypt_buf+0x1b4): undefined reference to `mbedtls_cipher_auth_encrypt_ext'
/opt/gcc-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/13.2.1/../../../../arm-none-eabi/bin/ld: /home/dev/app/source/iobox-app/../../thirdparty/mbedtls/build/library/libmbedtls.a(ssl_msg.c.obj): in function `mbedtls_ssl_decrypt_buf':
/home/dev/app/thirdparty/mbedtls/library/ssl_msg.c:1638:(.text.mbedtls_ssl_decrypt_buf+0x180): undefined reference to `mbedtls_cipher_auth_decrypt_ext'
/opt/gcc-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/13.2.1/../../../../arm-none-eabi/bin/ld: /home/dev/app/source/iobox-app/../../thirdparty/mbedtls/build/library/libmbedtls.a(ssl_msg.c.obj): in function `mbedtls_ssl_transform_free':
/home/dev/app/thirdparty/mbedtls/library/ssl_msg.c:6213:(.text.mbedtls_ssl_transform_free+0x14): undefined reference to `mbedtls_cipher_free'
/opt/gcc-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/13.2.1/../../../../arm-none-eabi/bin/ld: /home/dev/app/thirdparty/mbedtls/library/ssl_msg.c:6214:(.text.mbedtls_ssl_transform_free+0x1e): undefined reference to `mbedtls_cipher_free'
/opt/gcc-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/13.2.1/../../../../arm-none-eabi/bin/ld: /home/dev/app/source/iobox-app/../../thirdparty/mbedtls/build/library/libmbedtls.a(ssl_tls.c.obj): in function `mbedtls_ssl_transform_init':
/home/dev/app/thirdparty/mbedtls/library/ssl_tls.c:1028:(.text.mbedtls_ssl_transform_init+0x18): undefined reference to `mbedtls_cipher_init'
/opt/gcc-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/13.2.1/../../../../arm-none-eabi/bin/ld: /home/dev/app/thirdparty/mbedtls/library/ssl_tls.c:1029:(.text.mbedtls_ssl_transform_init+0x22): undefined reference to `mbedtls_cipher_init'
/opt/gcc-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/13.2.1/../../../../arm-none-eabi/bin/ld: /home/dev/app/source/iobox-app/../../thirdparty/mbedtls/build/library/libmbedtls.a(ssl_tls.c.obj): in function `mbedtls_ssl_get_mode_from_ciphersuite':
/home/dev/app/thirdparty/mbedtls/library/ssl_tls.c:2453:(.text.mbedtls_ssl_get_mode_from_ciphersuite+0x12): undefined reference to `mbedtls_cipher_info_from_type'
/opt/gcc-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/13.2.1/../../../../arm-none-eabi/bin/ld: /home/dev/app/source/iobox-app/../../thirdparty/mbedtls/build/library/libmbedtls.a(ssl_tls.c.obj): in function `mbedtls_ssl_parse_finished':
/home/dev/app/thirdparty/mbedtls/library/ssl_tls.c:8680:(.text.mbedtls_ssl_parse_finished+0xac): undefined reference to `mbedtls_ct_memcmp'
/opt/gcc-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/13.2.1/../../../../arm-none-eabi/bin/ld: /home/dev/app/source/iobox-app/../../thirdparty/mbedtls/build/library/libmbedtls.a(ssl_tls.c.obj): in function `ssl_tls12_populate_transform':
/home/dev/app/thirdparty/mbedtls/library/ssl_tls.c:8878:(.text.ssl_tls12_populate_transform+0xa6): undefined reference to `mbedtls_cipher_info_from_type'
/opt/gcc-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/13.2.1/../../../../arm-none-eabi/bin/ld: /home/dev/app/thirdparty/mbedtls/library/ssl_tls.c:9136:(.text.ssl_tls12_populate_transform+0x454): undefined reference to `mbedtls_cipher_setup'
/opt/gcc-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/13.2.1/../../../../arm-none-eabi/bin/ld: /home/dev/app/thirdparty/mbedtls/library/ssl_tls.c:9142:(.text.ssl_tls12_populate_transform+0x476): undefined reference to `mbedtls_cipher_setup'
/opt/gcc-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/13.2.1/../../../../arm-none-eabi/bin/ld: /home/dev/app/thirdparty/mbedtls/library/ssl_tls.c:9148:(.text.ssl_tls12_populate_transform+0x4a8): undefined reference to `mbedtls_cipher_setkey'
/opt/gcc-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/13.2.1/../../../../arm-none-eabi/bin/ld: /home/dev/app/thirdparty/mbedtls/library/ssl_tls.c:9155:(.text.ssl_tls12_populate_transform+0x4da): undefined reference to `mbedtls_cipher_setkey'
/opt/gcc-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/13.2.1/../../../../arm-none-eabi/bin/ld: CMakeFiles/app.dir/home/dev/app/thirdparty/lwip/src/apps/altcp_tls/altcp_tls_mbedtls.c.obj: in function `altcp_mbedtls_sndbuf':
/home/dev/app/thirdparty/lwip/src/apps/altcp_tls/altcp_tls_mbedtls.c:1192:(.text.altcp_mbedtls_sndbuf+0x7e): undefined reference to `mbedtls_ssl_get_max_frag_len'
/opt/gcc-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/13.2.1/../../../../arm-none-eabi/bin/ld: /home/dev/app/source/iobox-app/../../thirdparty/mbedtls/build/library/libmbedtls.a(ssl_tls12_server.c.obj): in function `ssl_parse_client_psk_identity':
/home/dev/app/thirdparty/mbedtls/library/ssl_tls12_server.c:3638:(.text.ssl_parse_client_psk_identity+0xb6): undefined reference to `mbedtls_ct_memcmp'
The distinct list undefined references of the above:
undefined reference to `mbedtls_cipher_auth_encrypt_ext'
undefined reference to `mbedtls_cipher_auth_decrypt_ext'
undefined reference to `mbedtls_cipher_free'
undefined reference to `mbedtls_cipher_init'
undefined reference to `mbedtls_cipher_info_from_type'
undefined reference to `mbedtls_ct_memcmp'
undefined reference to `mbedtls_cipher_setup'
undefined reference to `mbedtls_cipher_setup'
undefined reference to `mbedtls_cipher_setkey'
undefined reference to `mbedtls_cipher_setkey'
undefined reference to `mbedtls_ssl_get_max_frag_len'
All except the last one are coming from Mbed TSL internally, so I guess this means I am missing options? Or maybe I am still having too many?
The last one is called from the LWIP integration of Mbed TLS, and I could "sweep this under the carpet" by disabling "MBEDTLS_SSL_MAX_FRAGMENT_LENGTH". But I haven't looked further in what I cause if I do not support "RFC 6066 max_fragment_length extension in SSL"
My Mbed TLS configuration:
I followed the suggestion of your documentation, and went for a minimal example configuration. Pure on intuition, I went for "config-ccm-psk-dtls1_2.h". Because the file name suggests it brings TSL 1.2 which is basically all I need. I think.
I did had to make the following changes in order to be able to compile it:
1. Comment out two defines in order to get rid of module requiring "windows or unix"
//#define MBEDTLS_TIMING_C
2. Add a define, again to get rid of the compiler error "require windows or unix"
#define MBEDTLS_NO_PLATFORM_ENTROPY
After applying these small changes to the include/mbedtls/mbedtls_config.h I was able to cross compile (and link) Mbed TLS with arm-none-eabi toolchain.
Once I adjusted the build scripts to lnk against the Mbed TLS static libraries, I finally ended up with the earlier mentioned linker errors.
=============================
My questions:
=============================
1. Does my starting point configuration make sense?
As mentioned earlier, pure intuition made me try the "config-ccm-psk-dtls1_2.h" configuration example, which after some modifications compiled and produced 3 static libraries. but, this bit in the example header worries me a bit:
* Distinguishing features:
* - Optimized for small code size, low bandwidth (on an unreliable transport),
* and low RAM usage.
* - No asymmetric cryptography (no certificates, no Diffie-Hellman key
* exchange).
* - Fully modern and secure (provided the pre-shared keys are generated and
* stored securely).
* - Very low record overhead with CCM-8.
* - Includes several optional DTLS features typically used in IoT.
What does "no asymmetric cryptography" exactly mean? Isn't that the pure basis of TLS altogether?
If I want to achieve HTTPS using TLS, is this a good starting point?
2. Undefined references: wrong configuration, or should I supply some of the implementations?
As mentioned before, I have quite a few linking errors related to the cipher module. I tried to find answers in the documentation, but came up empty.
I assume (again...) that I should be able to get rid of these linking errors by enabling more features in Mbed TLS. But I honestly get lost in #define's. And maybe it's documented somewhere, but I couldn't find it.
3. Root CA provided by me?
I assume I need to provide at least one root CA for Mbed TLS to be able to verify the public key provided by the server, at some point, right? I would expect some callback I need to implement where such a root CA was read (in my case, i would have to read if from flash). Am I misunderstanding Mbed TLS on this aspect also? Or did I just miss the obvious spot where to Mbed TLS requests a root CA?
4. More examples available for typical microcontroller projects (FreeRTOS/LWIP)?
My experience so far is:
- Mbed TLS is well documented
- LWIP is no longer actively maintained, and lacks documentation in general
- Google finds a painful amount of LWIP/TLS integrations which are based on really old implementations of both, which does more harm than good for me
- Chat GPT knows everything, even when it doesn't, which is a really great recipe to get on the wrong track... It doesn't seem rather helpful on my integration questions for Mbed TLS/LWIP. Disclaimer: could be that my lack of knowledge is causing gpt to come up with wrong answers of course...
I understand that my email is (too?) long, and that the chance somebody will actually find the time to help me out is limited.
I expect nothing,
I hope for everything :)
ANY help is more than welcome. Good references, links to official documentation I missed, or in the best case: answers to my questions/uncertainties.
Many thanks in advance.
Best regards, Bas