Skip to content

Disallow use of invalid contexts #58

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

Merged
merged 8 commits into from
Feb 21, 2019

Conversation

Patater
Copy link
Contributor

@Patater Patater commented Feb 15, 2019

Disallow use of MAC, hash, and cipher contexts that haven't been set up (i.e. has a *_setup() function called on them).

@Patater Patater added bug Something isn't working needs: review The pull request is ready for review. This generally means that it has no known issues. compliance Discrepancy between the library and the PSA Crypto API specification labels Feb 15, 2019
Copy link
Collaborator

@gilles-peskine-arm gilles-peskine-arm left a comment

Choose a reason for hiding this comment

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

  • The implementation needs a design discussion about how to cope with bad-state errors. We have an unresolved question about the API spec at https://github.com/ARMmbed/psa-crypto/issues/45 (private link).
  • The tests don't cover all the cases that I'd expect. They're missing some bad-state cases for MAC and cipher.
  • Some of the tests need restructuring.

Copy link
Contributor

@NirSonnenschein NirSonnenschein left a comment

Choose a reason for hiding this comment

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

Looks ok to me besides the comments already made by Gilles. Are there any additional dependencies that need to be updated (e.g. example repo , usage by tls, etc..)?

@Patater
Copy link
Contributor Author

Patater commented Feb 19, 2019

Rebasing to address review feedback, extend tests, and fix #10.

@Patater Patater force-pushed the disallow-invalid-context branch from 0b2f1f2 to 5d0a2d3 Compare February 19, 2019 12:22
@Patater
Copy link
Contributor Author

Patater commented Feb 19, 2019

@Patater
Copy link
Contributor Author

Patater commented Feb 19, 2019

I'm looking into some memory leaks.

In general, if you start a cipher operation, and some internal memory is allocated on your behalf (e.g. AES context created), and then you call finish twice and get a PSA_ERROR_BAD_STATE error, there is no way to free that lost memory anymore, is there? You can't call abort, since after you get an PSA_ERROR_BAD_STATE, all bets are off.

@NirSonnenschein
Copy link
Contributor

wouldn't the first call to finish de-allocate the resources?

@gilles-peskine-arm
Copy link
Collaborator

after you get an PSA_ERROR_BAD_STATE, all bets are off.

That's not true. All bets are off if you have a bad state because the object was corrupted or never initialized. But if you've correctly initialized the object and subsequently only ever modified it through API functions, then abort is guaranteed to succeed.

@Patater
Copy link
Contributor Author

Patater commented Feb 19, 2019

@NirSonnenschein Yes, it likely would. Good point.

I'll change my example. How about if you call cipher finish without first setting an IV? Finish would fail with PSA_ERROR_BAD_STATE, but memory would have been allocated during cipher setup.

@Patater
Copy link
Contributor Author

Patater commented Feb 19, 2019

Thanks for the clarification, Gilles. I'll switch from using memset to all 0 between bad order tests and use abort instead.

Also note that one isn't guaranteed to get BAD_STATE if the context is corrupt or never initialized, so I'm not sure why we should be concerned, as per your comment: #58 (comment), about calling abort if BAD_STATE is encountered in these sorts of "well-formed" situations.

Can we conclude that it is OK to call abort on BAD_STATE? Are there cases we shouldn't call abort given we've gotten a BAD_STATE?

@gilles-peskine-arm
Copy link
Collaborator

gilles-peskine-arm commented Feb 19, 2019

#58 (comment) was about calling abort internally, not about calling it from the application. I distinguished two cases: well-formed situations, where it's debatable whether the right behavior is to abort or to not modify the object, and non-well-formed situations, where abort could make things worse.

In application code, you should always initialize your memory, and you should always call abort unless you have a guarantee that the object is in its initial state (e.g. because you never set it up or the last function that you applied to it was a finish function).

@Patater
Copy link
Contributor Author

Patater commented Feb 19, 2019

Rebase incoming to switch from memset to abort between bad order tests.

@Patater Patater force-pushed the disallow-invalid-context branch from 5d0a2d3 to 1128d08 Compare February 19, 2019 14:10
@Patater
Copy link
Contributor Author

Patater commented Feb 19, 2019

@Patater
Copy link
Contributor Author

Patater commented Feb 19, 2019

Forgot to apply a fixup commit. Rebasing again.

@Patater Patater force-pushed the disallow-invalid-context branch from 1128d08 to ace8e02 Compare February 19, 2019 14:13
@Patater
Copy link
Contributor Author

Patater commented Feb 19, 2019

Rebased to apply fixup commit. Previous branch at https://github.com/Patater/mbed-crypto/tree/disallow-invalid-context-4

@Patater
Copy link
Contributor Author

Patater commented Feb 19, 2019

All done rebasing. Ready to review.

@Patater
Copy link
Contributor Author

Patater commented Feb 19, 2019

Added commits to address #58 (comment)

Will apply as fixup with a rebase if review goes well

@Patater
Copy link
Contributor Author

Patater commented Feb 19, 2019

This is getting a bit too messy. I'm going to have to rebase before review.

@Patater Patater force-pushed the disallow-invalid-context branch from fbea691 to 53d9509 Compare February 19, 2019 16:11
@Patater
Copy link
Contributor Author

Patater commented Feb 19, 2019

Rebased to apply fixups and make some style improvements. Previous branch at https://github.com/Patater/mbed-crypto/tree/disallow-invalid-context-5

@Patater
Copy link
Contributor Author

Patater commented Feb 19, 2019

Rebasing done.

@Patater
Copy link
Contributor Author

Patater commented Feb 20, 2019

Will rebase to apply fixup commit now

@Patater Patater force-pushed the disallow-invalid-context branch from 2cad8f1 to ff9d2bc Compare February 20, 2019 09:19
@Patater Patater added needs: ci Needs a passing full CI run and removed needs: review The pull request is ready for review. This generally means that it has no known issues. labels Feb 20, 2019
@Patater Patater added needs: review The pull request is ready for review. This generally means that it has no known issues. and removed needs: ci Needs a passing full CI run labels Feb 20, 2019
@Patater
Copy link
Contributor Author

Patater commented Feb 20, 2019

CI passed. Ready for review.

Copy link
Collaborator

@gilles-peskine-arm gilles-peskine-arm left a comment

Choose a reason for hiding this comment

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

psa_mac_update is not consistent with the other update/finish functions wrt an argument in initial state: it calls abort. This is not an absolute blocker because we still haven't decided what behavior the specification will mandate, but I'd prefer the implementation to be consistent.

PSA_ERROR_BAD_STATE );
PSA_ASSERT( psa_hash_abort( &operation ) );

/* Call update without calling setup beforehand. */
Copy link
Collaborator

Choose a reason for hiding this comment

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

Technically, you're calling update after abort. This is equivalent to update without setup only if abort behaves correctly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Would you recommend we call both abort and memset the context to 0? I'm depending on abort setting the context to 0, and if it doesn't, the test will fail.

Copy link
Collaborator

Choose a reason for hiding this comment

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

If abort works properly, it doesn't matter. It's only a matter of how hard it will be to investigate a test failure that is ultimately due to abort returning the expected status but not having done its job properly.

I would prefer to make each unit test independent. But it's also good to have a stress test where a single object is reused.

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've raised #66 to add targeted abort tests.

@Patater Patater added needs: work The pull request needs rework before it can be merged. and removed needs: review The pull request is ready for review. This generally means that it has no known issues. labels Feb 20, 2019
Ensure that when doing MAC operations out of order, PSA_ERROR_BAD_STATE
is returned as documented in crypto.h and the PSA Crypto specification.
Ensure that when doing cipher operations out of order,
PSA_ERROR_BAD_STATE is returned as documented in crypto.h and the PSA
Crypto specification.
If a hash context has not been set up, fail with PSA_ERROR_BAD_STATE as
documented in crypto.h and the PSA Crypto specification.
Extend hash bad order test in line with the new bad order tests for MAC
and cipher, covering more cases and making comments and test layout
consistent.

Ensure that when doing hash operations out of order, PSA_ERROR_BAD_STATE
is returned as documented in crypto.h and the PSA Crypto specification.
Calling psa_*_setup() twice on a MAC, cipher, or hash context should
result in a PSA_ERROR_BAD_STATE error because the operation has already
been set up.

Fixes ARMmbed#10
@Patater
Copy link
Contributor Author

Patater commented Feb 20, 2019

Rebasing to address review feedback.

@Patater Patater force-pushed the disallow-invalid-context branch from 0cbb8c7 to 36ee5d0 Compare February 20, 2019 15:33
@Patater
Copy link
Contributor Author

Patater commented Feb 20, 2019

In places where we detect a context is in a bad state and there is no
sensitive data to clear, simply return PSA_ERROR_BAD_STATE and don't
abort on behalf of the application. The application will choose what to
do when it gets a bad state error.

The motivation for this change is that an application should decide what
to do when it misuses the API and encounters a PSA_ERROR_BAD_STATE
error. The library should not attempt to abort on behalf of the
application, as that may not be the correct thing to do in all
circumstances.
@Patater Patater force-pushed the disallow-invalid-context branch from ee32d9f to e236c2a Compare February 20, 2019 17:39
@Patater
Copy link
Contributor Author

Patater commented Feb 20, 2019

Rebased to add a commit that returns bad state without aborting in more cases. Previous branch at https://github.com/Patater/mbed-crypto/tree/disallow-invalid-context-12

@Patater Patater added needs: review The pull request is ready for review. This generally means that it has no known issues. needs: ci Needs a passing full CI run and removed needs: work The pull request needs rework before it can be merged. needs: ci Needs a passing full CI run labels Feb 20, 2019
@@ -6529,7 +6529,7 @@ static void ssl_calc_finished_tls_sha256(
unsigned char padbuf[32];
#if defined(MBEDTLS_USE_PSA_CRYPTO)
size_t hash_size;
psa_hash_operation_t sha256_psa;
psa_hash_operation_t sha256_psa = PSA_HASH_OPERATION_INIT;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Using PSA_HASH_OPERATION_INIT, psa_hash_operation_init(); or simply = 0 are all valid ways to do initialisation, right?

What are the advantages of different methods? In particular, why are we using on line 1449 and 1492 psa_hash_operation_init(); and PSA_HASH_OPERATION_INIT here?

Copy link
Collaborator

Choose a reason for hiding this comment

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

{0} and INIT (macro) can be used to initialize global variables, but init() (function) can't. {0} is generic but some compilers warn that this implicitly initializes other fields to 0. init() is the only one that's typed, so you'll get an error if you use it in the wrong context. memset to 0 is also defined as equivalent because it allows applications to use e.g. calloc, and in practice it produces the same value as {0} on virtually all platforms.

In most cases, the choice is indifferent.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

PSA_HASH_OPERATION_INIT is all static, so you can use it for static globals. The inline function can be used where functions can be used, which is a few less places, but it uses the static initializer under-the-hood. = {0} is usually ok, but some compilers will complain about missing field initializers.

I personally prefer using the macro everywhere, but previous authors inside library/ssl_tls.c liked the function. There is no functional difference in this case.

Copy link
Collaborator

@yanesca yanesca left a comment

Choose a reason for hiding this comment

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

Looks good to me!

@Patater
Copy link
Contributor Author

Patater commented Feb 21, 2019

CI failure is only FreeBSD timing test, a known-flaky test.

@Patater Patater merged commit bf61ca7 into ARMmbed:development Feb 21, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working compliance Discrepancy between the library and the PSA Crypto API specification needs: review The pull request is ready for review. This generally means that it has no known issues.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants