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

mbed TLS: threading support - DRAFT - Do not merge #3150

Closed
wants to merge 2 commits into from

Conversation

yanesca
Copy link
Contributor

@yanesca yanesca commented Oct 27, 2016

Description

This is an implementation of mbed TLS threading abstraction layer using RTOS mutexes: The application developer has to call the mbedtls_threading_set_mbed() function before calling any mbed TLS functions and the library will use RTOS mutexes to provide thread safety where it is sopported. (see the corresponding Knowledge Base article).

Status

IN DEVELOPMENT

Migrations

This PR does not change any existing behaviour:
NO

Todos

  • Documentation

Description:

This is an implementation of mbed TLS threading abstraction layer
using RTOS mutexes.

Design decisions:

  • The is_valid flag is not checked in the init function, because it is a
    chance that an uninitialised variable has the value of one (it is a
    small chance, but it would result in incorrect behaviour)
  • The checks on the is_valid flag are not abbreviated because an
    uninitialised variable is nonzero in most of the cases
  • The type of a mutex is a pointer to void and not an incomplete struct,
    because we use definitions with mbedtls_threading_mutex_t in the
    library
  • There is a wrapper for mbedtls_threading_set_alt to make it more user
    friendly and to enable the use of static functions

@0xc0170
Copy link
Contributor

0xc0170 commented Oct 28, 2016

Please send this to the master branch.

I'll label this as "do not merge" for the time being.

@yanesca yanesca changed the base branch from mbed-os-5.2 to master October 28, 2016 12:24
This is an implementation of mbed TLS threading abstraction layer
using RTOS mutexes.

Design decisions:
- The is_valid flag is not checked in the init function, because it is a
  chance that an uninitialised variable has the value of one (it is a
  small chance, but it would result in incorrect behaviour)
- The checks on the is_valid flag are not abbreviated because an
  uninitialised variable is nonzero in most of the cases
- The type of a mutex is a pointer to void and not an incomplete struct,
  because we use definitions with mbedtls_threading_mutex_t in the
  library
- There is a wrapper for mbedtls_threading_set_alt to make it more user
  friendly and to enable the use of static functions
@yanesca yanesca force-pushed the mbedtls-threading-integration branch from 4cfdf7e to 66a97c7 Compare October 28, 2016 12:30
@yanesca
Copy link
Contributor Author

yanesca commented Oct 28, 2016

I have retested after the rebase on a K64F manually.

Defining threading support impacts application code, therefore the
corresponding macros shouldn't be defined by default they should be
turned on in the application specific configuration.
Copy link
Contributor

@simonbutcher simonbutcher left a comment

Choose a reason for hiding this comment

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

This isn't ready for merging yet and needs rework.

/*
* Enable mbed TLS to use mbed OS mutexes
*/
#if defined(MBEDTLS_THREADING)
Copy link
Contributor

Choose a reason for hiding this comment

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

With MBEDTLS_THREADING we're effectively defining a new mbed OS macro to control mbed TLS. I would like to put it in a separate namespace from the normal mbed TLS configuration macros to make it more obvious.

Could we use something like TLS_CONFIG_XXXX? I'm open to ideas.

Copy link
Contributor Author

@yanesca yanesca Nov 18, 2016

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 separating the namespaces. If we decide to do it, then I think we should be careful and stay consistent while doing so. For example, we should rename the hardware acceleration macro accordingly (now it is still in the library's namespace MBEDTLS_HW_SUPPORT)

I would suggest the MBED_TLS_ prefix. This way we can take into account that mbed TLS won't always be the TLS stack in an mbed OS application, respect the application developers choice and avoid confusions. I would omit the CONFIG part, because feel it a little bit redundant, since the aim of all of these macros is to configure the mbed TLS library within mbed OS. Also I think that if the macro names are shorter, then they are less intimidating and easier to use.

Choose a reason for hiding this comment

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

According to this, threading is turned off by default? While I can see some of the benefits for this to happen, I would prefer to have the opposite default behaviour. Furthermore, I am not sure why we need the MBEDTLS_THREADING macro at all, it only seems to be a short hand for two defines i.e. MBEDTLS_THREADING_C and MBEDTLS_THREADING_ALT that would have to be declared somewhere anyways. I would prefer if the user just had to define/undefine the macros manually in the mbedtls user config. Also this would enable us to remove the MBEDTLS_THREADING macro.

return;

delete mutex->mutex;

Copy link
Contributor

Choose a reason for hiding this comment

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

Need to add mutex->mutex = NULL;

Copy link
Contributor Author

@yanesca yanesca Nov 18, 2016

Choose a reason for hiding this comment

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

I am sorry but I can't see any scenario where this would make any difference. Could you please give an example when it might be useful to set that pointer to NULL?

Copy link
Contributor

Choose a reason for hiding this comment

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

This is just good defensive programming, and shouldn't need justification.

However - a scenario - imagine initialising the library, then tearing it down, because the application software encounters an error. The software then tries restarting the library, and because the mutex is statically allocated it and is only zeroed at boot, it will still contain the pointer to the old mutex. On calling threading_mutex_init_mbed() nothing is allocated because it's already non-zero - but the pointer is stale.

Now expect a failure.

This is artificial and may not work in real life - but the point remains - it's good practice to zero it after use.

{
if( mutex == NULL || mutex->is_valid != true )
return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA );

Copy link
Contributor

Choose a reason for hiding this comment

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

You're checking if mutex is NULL, but you should also check if mutex->mutex is NULL just to be safe.

Copy link
Contributor Author

@yanesca yanesca Nov 18, 2016

Choose a reason for hiding this comment

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

I think that the only case mutex->mutex can be NULL is when

  • mutex is uninitialised OR
  • the memory is corrupted / the structure has been accessed with some means other than these functions

In these cases if we suppose that the memory content is uniformly distributed, then the chance of not catching this with is_valid is 1:2^8 and therefore detecting this by checking for NULL is 1:2^40 or 1:2^72, depending on the architecture (it can be higher on architectures with smaller address space).

The check probably wouldn't help against an active adversary at all, because an active adversary would probably set the pointer value to something other than NULL if he can.

I think if we want to make it more robust then changing the type of is_valid to int would be much more effective, than adding this check for NULL.

What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

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

Again, this is defensive programming to me. However, the case for testing for NULL is much weaker, because as you say, the chance of the pointer being NULL is logically improbable. I can accept not making the change.

{
if( mutex == NULL || mutex->is_valid != true )
return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA );

Copy link
Contributor

Choose a reason for hiding this comment

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

Again, you're checking if mutex is NULL, but you should also check if mutex->mutex is NULL just to be safe.

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 have a same concerns here as I had above.

Copy link
Contributor

Choose a reason for hiding this comment

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

Comments as above.

return( 0 );
}

void mbedtls_threading_set_mbed( void )
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this function is confusingly named, and I'd prefer we didn't have it. Really the library should self-configure and this function causes life time issues, because now something has to call it during initialisation to allow the library to use the primitives. Currently the caller would be the mbed OS application developer - and that is unacceptable as it means we're adding a breaking API change that extends the mbed TLS library interface, but is also outside the library.

This is a library problem, which I'll raise separately and will need to be fixed elsewhere before we can merge this PR.

Back to the point - while we have to have the function, can we call it something like mbedtls_rtx_threading_init()?

_rtx_ because we're using the RTX primitives, and _init because it's more natural than _set_alt().

Choose a reason for hiding this comment

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

As @sbutcher-arm mentioned, this is needed because of a library problem and should be fixed before the threading PR is merged.

/*
* Enable mbed TLS to use mbed OS mutexes
*/
#if defined(MBEDTLS_THREADING)

Choose a reason for hiding this comment

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

According to this, threading is turned off by default? While I can see some of the benefits for this to happen, I would prefer to have the opposite default behaviour. Furthermore, I am not sure why we need the MBEDTLS_THREADING macro at all, it only seems to be a short hand for two defines i.e. MBEDTLS_THREADING_C and MBEDTLS_THREADING_ALT that would have to be declared somewhere anyways. I would prefer if the user just had to define/undefine the macros manually in the mbedtls user config. Also this would enable us to remove the MBEDTLS_THREADING macro.

void* mutex;
char is_valid;
} mbedtls_threading_mutex_t;
#endif

Choose a reason for hiding this comment

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

Could you please add the comment next to the #endif with the condition of the matching #if?

*/
#if defined(MBEDTLS_THREADING)
#define MBEDTLS_THREADING_C
#define MBEDTLS_THREADING_ALT

Choose a reason for hiding this comment

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

I would like to point out that defining MBEDTLS_THREADING_ALT also defines MUTEX_INIT which might not be what we want, and perhaps should be handled?

return( 0 );
}

void mbedtls_threading_set_mbed( void )

Choose a reason for hiding this comment

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

As @sbutcher-arm mentioned, this is needed because of a library problem and should be fixed before the threading PR is merged.

@sg-
Copy link
Contributor

sg- commented Jan 9, 2017

@yanesca wondering what the status of this is. Any updates? Please close if not planning to complete or if it will be completed in a different version.

@yanesca
Copy link
Contributor Author

yanesca commented Jan 10, 2017

There are no updates yet, but we are going to complete it. In case there will be a decision to complete it in a different version, I will close this PR down.

@stevew817
Copy link
Contributor

@yanesca @sg- With the growing use of threads in mbed OS, what is the status of making mbedTLS itself support threading?

@theotherjimmy
Copy link
Contributor

please reopen when unblocked.

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.

7 participants