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_NET_C //#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