Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change MbedTLS configuration to use the Mbed OS configuration system #9669

Closed

Conversation

dreemkiller
Copy link
Contributor

@dreemkiller dreemkiller commented Feb 11, 2019

Description

Change the way that MbedTLS is configured in Mbed OS.
Previously, to configure MbedTLS developers had to edit a header file.
After this change, developers can use the MBed OS configuration system for most configuration options.
Developers still have the option of creating a header file, which they will need to reference in their mbed_app.json file.

Pull request type

[ ] Fix
[ ] Refactor
[ ] Target update
[X ] Functionality change
[ ] Docs update
[ ] Test update
[ ] Breaking change

Reviewers

Release Notes

This PR changes the way that MbedTLS is configured on Mbed OS. Users can now choose the TLS ciphersuites that they want supported by adding entries in their mbed_app.json file. Users who have existing header files that they currently use to configure Mbed TLS can continue to do so by adding an "mbedtls.app-config-file" entry in their mbed_app.json file.

When configuring MbedTLS on Mbed OS, developers should add the Mbed TLS ciphersuites that the device will need to support in the target_overrides section of their mbed_app.json file. Thus, to add the ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 ciphersuite, they should include:

"mbedtls.ecdhe-ecdsa-with-aes-128-gcm-sha256": 1

in their target_overrides section. Developers should include as many ciphersuites as they deem necessary, keeping in mind that the more they add, the larger the binary footprint of MbedTLS will be on their device.

If developers have an existing configuration header file for MbedTLS that they currently use by defining MBEDTLS_USER_CONFIG_FILE, they can include that by including the path to that file in the "mbedtls.app-config-file" entry in their mbed_app.json file.

@ciarmcom ciarmcom requested review from a team February 12, 2019 00:00
@ciarmcom
Copy link
Member

@dreemkiller, thank you for your changes.
@ARMmbed/mbed-os-core @ARMmbed/mbed-os-wan @ARMmbed/mbed-os-pan @ARMmbed/mbed-os-test @ARMmbed/mbed-os-ipcore @ARMmbed/mbed-os-maintainers @ARMmbed/mbed-os-hal @ARMmbed/mbed-os-crypto @ARMmbed/mbed-os-tls please review.

@cmonr cmonr removed request for a team February 12, 2019 00:21
@cmonr
Copy link
Contributor

cmonr commented Feb 12, 2019

Removed some review groups I don't quite thing should've been included (@ciarmcom is having a day).

@ciarmcom ciarmcom requested review from a team February 12, 2019 02:00
@ciarmcom

This comment has been minimized.

@ciarmcom ciarmcom requested a review from a team February 12, 2019 02:00
@ciarmcom

This comment has been minimized.

@cmonr
Copy link
Contributor

cmonr commented Feb 12, 2019

Reviweers, appologies for the the overly... insistent, reviewbot. There's a newly discovered issue with the script but because I misplaced my credentials to the server running the bot, actions to correct the behavior will have to wait until @adbridge is up.

@ciarmcom

This comment has been minimized.

"config": {
"MBED_CLOUD_CLIENT": {
"help": "Include support for ciphersuites required by the Mbed Cloud Client",
"value": 1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Turning on the cipher-suites by default for cloud client applications would mean that all other applications who do not require these cipher-suites must explicitly disable these configs in their mbed_app.json.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably, by default nothing should be turned on. On-demand application can choose to turn on features as required.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see your point to a degree. However, if an developer does not change the default configuration, and does not use any TLS features, the linker should optimize all of MbedTLS out anyway, correct?
I've tried to leave the default settings as close as possible to the current default settings to cause as little disruption to developers as possible.

Copy link
Member

@pan- pan- Feb 12, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've tried to leave the default settings as close as possible to the current default settings to cause as little disruption to developers as possible.

What are the differences ? Could you detail the breaking change made to the default configuration ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dreemkiller For example LoRaWAN will need AES and CMAC from MbedTLS. However it doesn't require a collection of ciphersuites which are necessary for CLOUD client applications. If we take your current proposal as it is at the moment, a LoRaWAN developer has to set MBED_CLOUD_CLIENT = 0 for example. This step wouldn't be needed if we let the appropriate application to choose for itself, i.e., the CLOUD_CLIENT application could set the MBED_CLOUD_CLINET = 1 on demand. Hope you understand what I mean. We can take this offline if you wish.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, I will take a look at that and try to resolve your problems.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hasnainvirk Thanks so much for this use-case.

From what I can tell, the mbedtls_lora_config.h file is not a complete specification of what you need, but just a subset. You were relying on the Mbed TLS configuration file to provide the rest.
This is different from what I expected, so I am very glad you brought this up.

I've submitted a change that takes this into account, and I've compiled your example app with no issues (it required removing the MBEDTLS_USER_CONFIG define from the mbed_app.json file and replacing it with: "mbedtls.app-config-file": ""mbedtls_lora_config.h"" in the "*" target_overrides).

Since I don't have a test set up for that application, I was unable to run it, but it did compile. Could you take a look to ensure that what I've done is consistent with your expectations?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dreemkiller Thanks. I will take your PR and test, and then update you asap.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dreemkiller I have tested your PR with our setup and everything works fine.
However, I am seeing an increase in flash footprint by 1K (1048 bytes precisely).
Compiler used is GCC. Maybe its just coding overhead. If anything comes into your head other than coding overhead, please let me know.

Numbers with your PR:

Elf2Bin: mbed-os-example-lorawan
| Module                     |         .text |    .data |      .bss |
|----------------------------|---------------|----------|-----------|
| [fill]                     |       220(-2) |    4(+0) |  2106(+0) |
| [lib]/c.a                  |     28951(+0) | 2472(+0) |    89(+0) |
| [lib]/gcc.a                |      3232(+0) |    0(+0) |     0(+0) |
| [lib]/m.a                  |       652(+0) |    0(+0) |     0(+0) |
| [lib]/misc                 |       248(+0) |    8(+0) |    28(+0) |
| [lib]/nosys.a              |        32(+0) |    0(+0) |     0(+0) |
| main.o                     |      1828(-4) |    0(+0) |  3892(+0) |
| mbed-lora-radio-drv/SX1272 |       383(+0) |    0(+0) |     0(+0) |
| mbed-lora-radio-drv/SX1276 |      8381(+0) |    0(+0) |     0(+0) |
| mbed-os/cmsis              |      1033(+0) |    0(+0) |     0(+0) |
| mbed-os/components         |       290(+0) |    0(+0) |     0(+0) |
| mbed-os/drivers            |      1532(+0) |    0(+0) |    52(+0) |
| mbed-os/events             |      1490(+0) |    0(+0) |     0(+0) |
| mbed-os/features           |  32252(+1046) |    4(+0) |   184(+0) |
| mbed-os/hal                |      1878(+0) |    8(+0) |   130(+0) |
| mbed-os/platform           |      4310(+0) |  260(+0) |   293(+0) |
| mbed-os/rtos               |     11166(+0) |  168(+0) |  5973(+0) |
| mbed-os/targets            |     13886(+0) |   12(+0) |  1029(+0) |
| trace_helper.o             |         2(+0) |    0(+0) |     0(+0) |
| Subtotals                  | 111766(+1040) | 2936(+0) | 13776(+0) |
Total Static RAM memory (data + bss): 16712(+0) bytes
Total Flash memory (text + data): 114702(+1040) bytes



Numbers with Mbed OS master

Elf2Bin: mbed-os-example-lorawan
| Module                     |         .text |    .data |      .bss |
|----------------------------|---------------|----------|-----------|
| [fill]                     |       218(-2) |    4(+0) |  2106(+0) |
| [lib]/c.a                  |     28951(+0) | 2472(+0) |    89(+0) |
| [lib]/gcc.a                |      3232(+0) |    0(+0) |     0(+0) |
| [lib]/m.a                  |       652(+0) |    0(+0) |     0(+0) |
| [lib]/misc                 |       248(+0) |    8(+0) |    28(+0) |
| [lib]/nosys.a              |        32(+0) |    0(+0) |     0(+0) |
| main.o                     |      1828(+0) |    0(+0) |  3892(+0) |
| mbed-lora-radio-drv/SX1272 |       383(+0) |    0(+0) |     0(+0) |
| mbed-lora-radio-drv/SX1276 |      8381(+0) |    0(+0) |     0(+0) |
| mbed-os/cmsis              |      1033(+0) |    0(+0) |     0(+0) |
| mbed-os/components         |       290(+0) |    0(+0) |     0(+0) |
| mbed-os/drivers            |      1532(+0) |    0(+0) |    52(+0) |
| mbed-os/events             |      1490(+0) |    0(+0) |     0(+0) |
| mbed-os/features           |  31206(-1046) |    4(+0) |   184(+0) |
| mbed-os/hal                |      1878(+0) |    8(+0) |   130(+0) |
| mbed-os/platform           |      4310(+0) |  260(+0) |   293(+0) |
| mbed-os/rtos               |     11166(+0) |  168(+0) |  5973(+0) |
| mbed-os/targets            |     13886(+0) |   12(+0) |  1029(+0) |
| trace_helper.o             |         2(+0) |    0(+0) |     0(+0) |
| Subtotals                  | 110718(-1048) | 2936(+0) | 13776(+0) |
Total Static RAM memory (data + bss): 16712(+0) bytes
Total Flash memory (text + data): 113654(-1048) bytes

``

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very interesting. Thanks for the feedback.

Here's the diagnosis: I coded the app-config-file option to be included first, before the rest of the defines. This meant that any undefs in the file might get overridden by the rest of the configuration options, including the default ones.

I have now moved the app-config-file option to be last, so it has "supremacy" and can override any of the other options. The size is now smaller than the previous settings (there are a few options that were previously default that have been optimized out when users don't select things).

@AnttiKauppila
Copy link

@yogpan01 Can you check this from client perspective?

Copy link
Contributor

@hasnainvirk hasnainvirk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a minor comment. It's better to rebase on top of master rather than merging master into your work. It will give a cleaner baseline if you rebase.

Copy link

@AnttiKauppila AnttiKauppila left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM +1

Copy link
Contributor

@0xc0170 0xc0170 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mbed-http.lib Outdated Show resolved Hide resolved
@@ -0,0 +1,23 @@
/*
* Copyright (c) 2013-2018, ARM Limited, All Rights Reserved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New files should have 2019 only here (or 2018 if work started the previous year)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The work was started last year, but finished up this year. Should I change it or leave it as is?

TESTS/mbedtls/config/connection_test.cpp Outdated Show resolved Hide resolved
Copy link
Contributor

@SeppoTakalo SeppoTakalo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the idea of this.

I'm just proposing that we do not duplicate the effort of connectivity tests.

TESTS/mbedtls/config/connection_test.cpp Outdated Show resolved Hide resolved
features/mbedtls/mbed_lib.json Outdated Show resolved Hide resolved
mbed-http.lib Outdated Show resolved Hide resolved
@dreemkiller
Copy link
Contributor Author

@RonEld You are correct, I have not addressed #9669 (comment) yet. Stay tuned.
Regarding conflicts between a chosen ciphersuite and a custom header file, that's certainly a risk with this system, but it's not new. The existing system could result in the same problem.
In the future when we add more functionality, the need for custom header files will be reduced.
In general, as before, check_config.h is still our bulwark against conflicting configurations.

@cmonr cmonr dismissed 0xc0170’s stale review February 21, 2019 18:00

Release notes added. Please re-review.

Copy link

@andresag01 andresag01 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @dreemkiller,

Thanks for looking at improving the Mbed TLS integration with Mbed OS. Changes like this are much needed to make the Mbed TLS configuration options more approachable and easier to use for developers.

In general, I like the idea of the work proposed in this PR, but I have a few comments/questions:

  • There are many new files in this PR that add test code. As far as I can tell, most of this is to check that the new configuration is working. For example, if I enable ciphersuite X using the new JSON configuration options, there is a test for X to ensure that the relevant functions are actually included in the compiled binary. Is this correct? If not, could you please explain the purpose of this code? If my explanation was correct, could you please explain why do we need such verbose tests? I mean, Mbed TLS has a few ways using well defined macros to test that these features are available in the compiled binary. Why not use those? Do we really need to duplicate most of the AES self test code just for checking this?
  • There are multiple mechanisms in Mbed TLS to change the library configuration. (1) The first is to use the MBEDTLS_USER_CONFIG_FILE that you are relying on here. It allows you to modify the default config the library has. (2) The other way is to use the MBEDTLS_CONFIG_FILE macro that allows users to completely replace the default config with their own. After the changes in this PR, one could use an option in the json config (e.g. mbedtls.ecdhe-ecdsa-with-aes-128-gcm-sha256) and also set (2). But I think that (1) will have no effect and (2) will be used exclusively. Perhaps we could add a compile-time check to ensure that (1) and (2) are not set at the same time?
  • I think in a previous conversation in this PR there was a conversation about conflicting configurations from different components of the application. I agree that this is a pre-existing issue and I do not expect this problem to be solved here. However, could you please comment regarding how you think the changes in this PR help us get closer to addressing that problem? My concern is that we approve and merge these changes. Then, when we want to fix the other issue, we realise that the new changes we have to apply conflict with the mechanism introduced in this PR and then we have to deprecate or add a breaking change.
  • I left a few other comments as I read through some of the code. Please note that I did not conduct a very thorough check, just tried to look at the design of the new feature.

#if !defined(MBEDTLS_ENTROPY_HARDWARE_ALT) && !defined(MBEDTLS_TEST_NULL_ENTROPY) && \
!defined(MBEDTLS_ENTROPY_NV_SEED)
// for platforms that don't have entropy,none of the ciphersuites will
// work, so don't bother

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From a usability point of view, I would prefer if we threw and error here instead of silently disabling the whole of Mbed TLS and then just throwing a linker error if the user's program relies on one of the library functions. What is the motivation for the existing behaviour instead or throwing an error (or at least a warning)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Throwing an error for each of these adds approximately 100 lines of code that need to be maintained.
I will add them, however.

#undef MBED_CONF_MBEDTLS_PSK_WITH_AES_128_CBC_SHA256
#define MBED_CONF_MBEDTLS_PSK_WITH_AES_128_CBC_SHA256 1
#endif
#if MBED_CONF_MBEDTLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style: Please be consistent. If there is a new line in between everyone of this blocks, please make sure there is always a newline.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will fix

#define MBEDTLS_SSL_RENEGOTIATION
#define MBEDTLS_SSL_TLS_C

#endif // #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) || defined(MBEDTLS_TEST_NULL_ENTROPY) || defined(MBEDTLS_ENTROPY_NV_SEED)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style: Normally in Mbed TLS we drop the define, redundant brackets and the #if.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a holdover from when it was an if/else.
Will remove

#define MBEDTLS_ECDH_C
#define MBEDTLS_X509_CRT_PARSE_C
#define MBEDTLS_SSL_SERVER_NAME_INDICATION
#endif

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please be consistent, some of these blocks have a comment in the matching #endif with the conditional. Could you please add the same comment to all the other blocks?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The style I've chosen to follow here is if an #if/#endif block will span farther than approximately half of the screen, to add the comment for clarity.
In the case where it doesn't, brevity is preferred, as it is clear where the #if for a given #endif occurs.

#endif

#define MBED_TLS_HAVE_ASM
#define MBED_TLS_HAVE_TIME

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think that either MBED_TLS_HAVE_ASM or MBED_TLS_HAVE_TIME are Mbed TLS macros. What is the purpose of these?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typos. will fix.

#define MBEDTLS_X509_CHECK_KEY_USAGE
#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE
#define MBEDTLS_VERSION_C
#define MBEDTLS_SELF_TEST

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the purpose of this "default" options? Are they meant for prototyping? production? something else? For example, what is the point of enabling MBEDTLS_SELF_TEST in a production build? Or the MBEDTLS_VERSION_C could probably be removed depending on what you want. How about MBEDTLS_DEBUG_C and MBEDTLS_ERROR_C?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are meant for prototyping, and they are included to allow the default configuration provided by the new system to be as close as possible to the default configuration as before.
For production, we expect people to customize the configuration using a header file to achieve optimum code size/performance/ whatever metric they choose.

/*
* Only use features that do not require an entropy source when
* DEVICE_ENTROPY_SOURCE is not defined in mbed OS.
*/
#if !defined(MBEDTLS_ENTROPY_HARDWARE_ALT) && !defined(MBEDTLS_TEST_NULL_ENTROPY) && \
!defined(MBEDTLS_ENTROPY_NV_SEED)
#include "mbedtls/config-no-entropy.h"

#if defined(MBEDTLS_USER_CONFIG_FILE)
#include MBEDTLS_USER_CONFIG_FILE
#endif

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we keeping this lines just for backwards compatibility?

@@ -0,0 +1,39 @@
/*
* Copyright (c) 2013-2018, ARM Limited, All Rights Reserved

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: Please update the copyright date in all the new files.

@dreemkiller
Copy link
Contributor Author

You are correct, these tests exist to ensure that the configuration code is working as intended. I am not aware of the well-defined macros that you are speaking of. If they would in fact reduce the size of the test code, I would be happy to use them instead. Could you point me to them?

Regarding adding an additional compile-time check to check for MBEDTLS_USER_CONFIG_FILE and MBEDTLS_CONFIG_FILE both being set, I will do that.

Regarding your question about resolving configuration conflicts: As things currently stand, users must create a custom configuration file to make any changes to Mbed TLS configuration. This is error-prone and requires quite a bit of expertise. Under this new system, most users will never need to do this. When they do have to, however, they are still protected by the checks run in the check_config.h file. Also, since this moves the bulk of the Mbed OS configuration of Mbed TLS outside of existing Mbed TLS code, this should be more maintainable and flexible than our current system of modifying a script that edits an existing Mbed TLS file. As with all changes, of course, time will tell.

@cmonr
Copy link
Contributor

cmonr commented Mar 1, 2019

@dreemkiller Does this need to be prioritized and come in for 5.12?

@dreemkiller
Copy link
Contributor Author

dreemkiller commented Mar 1, 2019 via email

dreemkiller added a commit to ARMmbed/mbed-os-5-docs that referenced this pull request Mar 1, 2019
The ARMmbed/mbed-os#9669 PR changes the way MbedTLS is configured on Mbed OS. This PR documents that change.
@simonbutcher
Copy link
Contributor

@dreemkiller - I've discussed this with the those members of the team engaged in reviewing, and one of the challenges of reviewing this PR, is that we're reviewing the implementation, and have to work backwards to work out what your intended design is, and in some places second guess what design choices you have made and why.

Would it be possible to provide a high-level design document for this PR, that we can review and give feedback on? I think that's the fastest way to progress this.

@cmonr
Copy link
Contributor

cmonr commented Mar 19, 2019

@dreemkiller Any thoughts on how we can progress this PR?

@dreemkiller
Copy link
Contributor Author

dreemkiller commented Mar 19, 2019 via email

@0xc0170
Copy link
Contributor

0xc0170 commented Mar 19, 2019

If that is the case, I'll propose to close this PR (discussion, updates still can happen here). Reopening once it's ready for review

@adbridge
Copy link
Contributor

Closing this for now, please re-open when it is ready to be updated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet