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

Add reference counter for platform context #7099

Merged
merged 8 commits into from
Sep 3, 2018

Conversation

RonEld
Copy link
Contributor

@RonEld RonEld commented Jun 4, 2018

Description

  1. Move the mbedtls_platform_context to be platform code, in features/mbedtls/platfrom/.
  2. Add static refernce counter, to setup and teardown the platform code only once.
  3. Adjust Cryptocell porting accordingly.

Should work with system modules using Mbed TLS, such as BLE, that wouldn't terminate the cryptographic driver for the application, in the middle of operation.
Adresses first part of #7069

CC @sbutcher-arm @Patater @pan-

Question: Should we protect the reference counter with a mutex?

Pull request type

[x] Fix
[ ] Refactor
[ ] New target
[ ] Feature
[ ] Breaking change

1. Move the `mbedtls_platform_context` to be platform code, in `features/mbedtls/platfrom/`.
2. Add static refernce counter, to setup and teardown the platform code only once.
3. Adjust Cryptocell porting accordingly.
Copy link
Member

@pan- pan- left a comment

Choose a reason for hiding this comment

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

Hi Ron,

Thanks for this submission that intend to solves #7069. Unfortunately reference
counting
is not the right tool to solve the issue; not at the mbed tls level.

Reference counting implies that a single instance/context is shared across multiple
parts of the program. In our case, it is expected that application code using mbed
tls submit a different/specific context every time mbedtls_platform_setup is
called.

With the code as it is proposed, a context will never be initialized if their is at least
another context initialized. This can have dramatic consequences if crypto_platform_ctx
actually contains valuable informations like CRYS_RND_State_t: The code may setup one
instance and teardown one that hasn't been initialized.

I strongly believe that keeping track of initialization is an implementation detail
and this as no place in the platform code at mbed tls level.

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.

I think we need to consider the interface changes carefully before we make this change.

cc: @Patater

{
int ret = 0;
if( ctx == NULL )
return ( -1 );
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think we should be returning -1, however, we have failed to define in Mbed TLS any error codes for function.

Maybe we should define error codes now locally in Mbed OS, and upstream them to Mbed TLS in time for the following release of Mbed OS? Possibly INVALID_INPUT for the case above, and HW_FAILURE in case of failure from the accelerator. What do you think?

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 agree, but as you said, there is currently no error codes available

Copy link
Contributor

Choose a reason for hiding this comment

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

You could define some locally in Mbed OS, and also submit a PR to upstream the same codes.

As and when the version of Mbed TLS with the new codes becomes available, we can remove the local definitions.

We control both sides (upstream and downstream) so there's no risk of reusing the same values.

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 created Mbed-TLS/mbedtls#1993 to add the platform error code

if( reference_count == 1 )
{
/* call platform specific code to setup crypto driver*/
ret = crypto_platform_setup( &ctx->platform_impl_ctx );
Copy link
Contributor

Choose a reason for hiding this comment

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

This makes crypto_platform_setup() part of the API for crypto drivers. That will need documenting in the Mbed OS Porting Guide, and also as an interface change will need wider review.

Is there anyway of avoiding this interface change? I'm not sure there is, but we should consider alternatives if we can.

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 agree it needs documenting in the handbook.

As for interface change, it's basically only a change in the existing name of the function ( cc_platform_setup renamed to crypto+platform_setup, and a bit of who is responsible of implementing CC initialization has changed). Although it is an API change, I believe it is a minor one
Unfortunately, I don't see any other way to have initialization of the platform, in an opaque way, and make it portable to other APIs. ( we can have the whole mbedtls_platform_setup() functino implemented in driver code, but then we guideusers to implement the reference count , which is very common to all the drivers )

if( ctx == NULL )
return;

if( reference_count == 0 )
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think you need two if statements, and it looks a bit odd.

Have you considered using a less than operator? eg.

    reference_count--;
    if( reference_count <= 0 )
    {
        crypto_platform_teardown();
    }

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 agree it looks a bit odd, but what you are suggesting is prone to errors:

  1. crypto_platform_teardown() might be called twice, if reference_count is 0 or -1.
  2. corner cases where we get the reference counter to -2, and then when some chooses to setup, it won't initialize the platform, because the counter will be increased to -1.

Perhaps assigning reference_count to 0 after calling crypto_platform_teardown()?

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree, it would be safer to reassign reference_count.

So...

    reference_count--;
    if( reference_count <= 0 )
    {
        crypto_platform_teardown();
        reference_count = 0;
    }

@RonEld
Copy link
Contributor Author

RonEld commented Jun 4, 2018

@pan- The idea in the mbedtls layer, is the platform itslef is shared across all the modules.
It's basically telling: " start cryptography operations" and "stop cryptography operations".

Specifically for NRF53840, there shouldn't be a problem, as the driver is initialized once, and terminated once. The CRYS_RND_State_t holds the trng data for seeding the DRBG. It is used in the CC initialization because the API requires it, but in actual usage, this struct is used in the trng function, for gathering the entropy.

I agree there might be a need for additional tweaking, such as protecting the CRYS_RND_State_t in trng_api.c with a mutex, and protecting the reference coutner with a mutex, or maybe additional changes, but I think it could be postponed,

@pan-
Copy link
Member

pan- commented Jun 4, 2018

The idea in the mbedtls layer, is the platform itslef is shared across all the modules.

Thanks for the clarification.

In that case wouldn't it make sense to remove crypto_platform_ctx from mbedtls_platform_context and declare a single instance of crypto_platform_ctx alongside reference_count ? That instance would be the only one passed to crypto_platform_setup and crypto_platform_teardown. It would prevent calling teardown on an uninitialized crypto_platform_ctx.

@simonbutcher
Copy link
Contributor

Hi @pan-

That's not really how we intended the platform context to be used. It's not well documented, mainly because no one has provided an implementation until now, but the context is supposed to be a one-per-platform singleton.

The intention was you should initialise once.

The implication of what you're suggesting is that the API we're providing isn't adequate, and you actually need a mbedtls_platform_setup(), that takes no context as parameter (as you can't track them), and possibly returns one instead?

1. Add error codes for platform setup \ teardown.
2. Reassign `reference_count` to 0 after terminating platform,
and remove condition for 0
@RonEld
Copy link
Contributor Author

RonEld commented Jun 4, 2018

@sbutcher-arm I addressed your comments

@pan-
Copy link
Member

pan- commented Jun 4, 2018

Hi @sbutcher-arm

I agree that if the context passed into mbedtls_platform_setup and mbedtls_platform_teardown is a singleton then reference counting is an adequate solution. Thanks for the clarification.

Given that in the current design the platform context singleton lives outside mbed tls platform layer; library and system code API using mbed tls must be updated to accept the platform context singleton instantiated by the application. In some cases - like BLE - that would force us to expose implementation details that are target specific in our abstract interfaces.

I wonder if it wouldn't be easier to encapsulate the platform context singleton into mbed tls platform layer and completely hide its existence and management from the API exposed to applications. In other words remove the context parameter in setup and teardown.

What do you think ?

PS: If the context is a singleton it may be better to add a reference counter field in the platform context structure rather than having another singleton in the global scope.

@0xc0170
Copy link
Contributor

0xc0170 commented Jun 8, 2018

@RonEld What is the status of this PR? Are there any outstanding issues to be resolved (the changes requested in the review for instance) ?

@RonEld
Copy link
Contributor Author

RonEld commented Jun 10, 2018

@0xc0170 I have addressed all the issues. The current status is that there is an architectural decision on how the API should actually look.
I can't really do much until the decision will be made.

@cmonr
Copy link
Contributor

cmonr commented Jun 18, 2018

@pan- @sbutcher-arm @RonEld Are there conversations happening offline somewhere, or has discussion on this PR simply become stale?

@cmonr
Copy link
Contributor

cmonr commented Jun 29, 2018

Since no progress has been made on this PR for over two weeks, and there's no sign of external conversations, I'm going to close this PR.

Once updates are available, it can be opened.

@cmonr cmonr closed this Jun 29, 2018
Make the platform context a global variable,
adding the refernce counter to it.
@RonEld
Copy link
Contributor Author

RonEld commented Aug 28, 2018

@cmonr I have available update for this PR. Do you want me to create a new PR or should this one be opened?

@cmonr
Copy link
Contributor

cmonr commented Aug 28, 2018

@RonEld You can commit it to this PR and it can be reopened.

@cmonr cmonr reopened this Aug 28, 2018
@RonEld
Copy link
Contributor Author

RonEld commented Aug 29, 2018

@pan- I have updated the context to be a global one, holding the reference counter within. You can now call the mbedtls_platform_setup() and mbedtls_platform_teardown() with a NULL argument, as it's being ignored for Mbed OS now.
Note I haven't made it exactly a singleton ( not static ), as it needs to be accessed by other modules. For example, by the trng module, in cryptocell.
Does this fit your needs?

@RonEld
Copy link
Contributor Author

RonEld commented Aug 29, 2018

cc @sbutcher-arm @Patater

1. Rename error codes to fit Mbed TLS error code names.
2. Remove the Invalid input error code, as it's not used anymore.
@RonEld
Copy link
Contributor Author

RonEld commented Aug 30, 2018

@0xc0170

currently 5.10 PR in the queue

To my understanding, this PR is targeting 5.10

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.

Minor comments only. My only real concern is your use of the word 'blocker' which I think is misleading.



int mbedtls_platform_setup( mbedtls_platform_context *ctx )
int mbedtls_platform_setup( mbedtls_platform_context *obsolete_ctx )
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is the context called obsolete? I think that's misleading. It's simply unused.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's obsolete, because it's not used and ignored anymore. I can rename

Copy link
Contributor

Choose a reason for hiding this comment

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

If it were obsolete it would no longer be used in any context - but that's not true. We're just choosing not to use it in Mbed OS. It could be used in other OS's and platforms.

I really think it's misleading still. Thanks for changing it.



int mbedtls_platform_setup( mbedtls_platform_context *ctx )
int mbedtls_platform_setup( mbedtls_platform_context *obsolete_ctx )
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we check obsolete_ctx is NULL?

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 don't think so, it is just being ignored. This way, it will be backwards compatible to applications \ modules using this function, that are still sending a content as parameter. Note the example applications weren't updated yet with NULL as parameter


extern CRYS_RND_State_t rndState;
extern CRYS_RND_WorkBuff_t rndWorkBuff;
extern mbedtls_platform_context ctx;
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this still needed?

Copy link
Contributor Author

@RonEld RonEld Aug 31, 2018

Choose a reason for hiding this comment

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

yes. Since there isn't any getter function for the context, we still need access to members of it. The RNG functions need the rndState, which is now member of the context

@RonEld
Copy link
Contributor Author

RonEld commented Aug 31, 2018

@sbutcher-arm Thank you for your comments. Please refer me to where I use the word "blocker" so i will rephrase.

Rename `obsolete_ctx` to `unused_ctx` as it is simply unused.
@RonEld
Copy link
Contributor Author

RonEld commented Aug 31, 2018

@sbutcher-arm i renamed the parameter name to unused_ctx

@0xc0170
Copy link
Contributor

0xc0170 commented Sep 2, 2018

/morph build

@mbed-ci
Copy link

mbed-ci commented Sep 2, 2018

Build : FAILURE

Build number : 2986
Build artifacts/logs : http://mbed-os.s3-website-eu-west-1.amazonaws.com/?prefix=builds/7099/

IAR fails to build when a variable is initialized with empty curly braces.
Added `{ { 0 } }` to fix that.
@RonEld
Copy link
Contributor Author

RonEld commented Sep 2, 2018

build failure on IAR was fixed

@NirSonnenschein
Copy link
Contributor

/morph build

@mbed-ci
Copy link

mbed-ci commented Sep 2, 2018

Build : SUCCESS

Build number : 2988
Build artifacts/logs : http://mbed-os.s3-website-eu-west-1.amazonaws.com/?prefix=builds/7099/

Triggering tests

/morph test
/morph export-build
/morph mbed2-build

@mbed-ci
Copy link

mbed-ci commented Sep 2, 2018

@mbed-ci
Copy link

mbed-ci commented Sep 2, 2018

@0xc0170
Copy link
Contributor

0xc0170 commented Sep 2, 2018

Waiting for the last approval from @sbutcher-arm

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

Successfully merging this pull request may close these issues.

8 participants