-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
Check mbedtls_platform_zeroize() calls #8143
Check mbedtls_platform_zeroize() calls #8143
Conversation
Great, this catches the expected failure:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test configuration is leaking into the library.
include/mbedtls/platform_util.h
Outdated
* It is only intended to be used in CFLAGS, with -Wsizeof-pointer-memaccess, | ||
* to check for those incorrect calls to mbedtls_platform_zeroize(). | ||
*/ | ||
//#define MBEDTLS_PLATFORM_ZEROIZE_CHECK_UNSAFE |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really don't like having test-only code that reduces security in the library. Our normal policy for this is a two-tier system: enable a compilation option that by itself doesn't change the runtime behavior, and provide or run additional code that has to be deliberately written.
Here, we can already achieve the effect by activating MBEDTLS_PLATFORM_ZEROIZE_ALT
and building with an implementation of mbedtls_platform_zeroize
, which lives in the tests/src
directory, that just calls memset
. (Similar example: we can build with a deterministic, non-cryptographic RNG by activating MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
and linking with the external RNG from tests/src/fake_external_rng_for_test.c
.) See tests/configs/user-config-for-test.h
and tests/configs/config-wrapper-malloc-0-null.h
for examples doing something similar.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We actually need the compiler to see the calls to mbedtls_platform_zeroize()
as memset()
, rather to have a call to mbedtls_platform_zeroize()
be implemented as memset()
, since it's at the mbedtls_platform_zeroize()
call site that the information is available about the types of parameters, which is what need to be checked.
This can only be done with a macro, so the choice is between having it in the header permanently, like this, or having the test use a perl
(or sed
, I suppose) script to make these changes when we run the test build. However, that would be fragile.
Also, I disagree that this is test-only code: rather, it is enabling static analysis. If there was an annotation comparable to the __attribute__ ((format (...)))
one for printf
-style function then we would apply it to this function definition at this point; this is very similar to that, so I think this is the right way to do this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comment below - we can add a check for MBEDTLS_TEST_HOOKS
to limit the risk?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's annoying that this can't be done with the existing option. (I checked, and indeed even compiling with -O3
and a static inline
wrapper with __attribute__((access(write_only, 1, 2)))
is not enough to get the warning.) Food for thought when we simplify the platform interface: this is a thing you can't do with a function replacement, only if you
can define a macro, the blocking thing being the function prototype. (If we manage to skip the function prototype then we can define a macro and all is good.)
So this does require a patch to platform_util.h
. But (unless we actually patch the file before building, which I'd rather avoid), this patch should still not, by itself, make an insecure build as easy as -D
. Gating by MBEDTLS_TEST_HOOKS
doesn't help: there's already a compile-time option to gate the insecurity (which should be called MBEDTLS_TEST_something
), but our policy is a two-tier system to make it a genuine hurdle to make an insecure build: an insecure build should need to either write your own insecure code or compile with something under tests
.
The minimum patch we need in platform_util.h
is to skip the prototype. So I propose to have a symbol (not referenced outside platform_util.h
and test code) that does just that. The #define mbedtls_platform_zeroize …
should be in a file under tests
.
include/mbedtls/platform_util.h
Outdated
@@ -167,7 +167,28 @@ MBEDTLS_DEPRECATED typedef int mbedtls_deprecated_numeric_constant_t; | |||
* \param len Length of the buffer in bytes | |||
* | |||
*/ | |||
#if defined(MBEDTLS_PLATFORM_ZEROIZE_CHECK_UNSAFE) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#if defined(MBEDTLS_PLATFORM_ZEROIZE_CHECK_UNSAFE) | |
#if defined(MBEDTLS_PLATFORM_ZEROIZE_CHECK_UNSAFE) && defined(MBEDTLS_TEST_HOOKS) |
Maybe this can help reduce the risk of this accidentally getting enabled?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, MBEDTLS_TEST_HOOKS
, is a documented config option in mbedtls_config.h
. It has to be manually enabled in all.sh
if wanted. The name has got "TEST" in the name, indicating that it might not necessarily be wanted in production.
MBEDTLS_PLATFORM_ZEROIZE_CHECK_UNSAFE
is only documented just under where it is used (to placate check-names, otherwise I would have not put it in). It needs to be manually enabled when wanted, which it is in the test in all.sh
, and to enable it in the configuration file requires typing it in, rather than removing comments. The name has got "UNSAFE" in it, indicating that it really shouldn't be used in production. It's not in mbedtls_config.h
, so someone running through enabling everything without careful reading is not going to get it.
So: this would seem to be the equivalent of needing to turn two keys before launching a missile, rather than just one.
I'm happy to add it if you think it really necessary, but I think MBEDTLS_TEST_HOOKS
is more likely to be accidentally enabled than MBEDTLS_PLATFORM_ZEROIZE_CHECK_UNSAFE
is, so I don't know if it's actually worth it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So: this would seem to be the equivalent of needing to turn two keys before launching a missile, rather than just one.
Yes, which is why our policy is that it takes more than doing some key turning to launch a missile. MBEDTLS_TEST_HOOKS
by itself must not enable any insecure behavior, only the possibility of injecting some code (not from the library) which itself may be insecure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The overall design looks good now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
#include <string.h> | ||
|
||
/* Define _ALT so we don't get the built-in implementation. The test code will | ||
* also need to define MBEDTLS_TEST_DEFINES_ZEROIZE so we don't get the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could define MBEDTLS_TEST_DEFINES_ZEROIZE
in this file. It's ok if defining MBEDTLS_USER_CONFIG_FILE
(factor 1) to point to a file under tests
(factor 2) results in an insecure build. But needing both definitions is ok too, this isn't a thing we need to do often.
@@ -5117,6 +5117,16 @@ support_build_cmake_custom_config_file () { | |||
} | |||
|
|||
|
|||
component_build_zeroize_checks () { | |||
msg "build: check for obviously wrong calls to mbedtls_platform_zeroize()" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A side note, we've considered running clang-tidy and its bugprone-sizeof-expression
looks for the same kind of problem. I don't know whether it would catch invalid calls in a normal build or if we'd need this memset replacement.
I thought we had an open issue for clang-tidy but turns out we don't, I'll file one (as part of the huge tech debt backlog, so don't hold your breath).
The The other build failure,
|
Editing the description seems to have re-triggered the CI, good |
Ah - except I need to rebase onto |
…eof-pointer-memaccess Signed-off-by: Tom Cosgrove <tom.cosgrove@arm.com>
Signed-off-by: Tom Cosgrove <tom.cosgrove@arm.com>
Signed-off-by: Tom Cosgrove <tom.cosgrove@arm.com>
Signed-off-by: Tom Cosgrove <tom.cosgrove@arm.com>
Signed-off-by: Tom Cosgrove <tom.cosgrove@arm.com>
…h and not include mbedtls_config.h Signed-off-by: Tom Cosgrove <tom.cosgrove@arm.com>
42a7e99
to
b2fafa5
Compare
Rebased on top of latest
|
Description
Add the ability to verify mbedtls_platform_zeroize() calls with -Wsizeof-pointer-memaccess, and fix a problem it finds in the tests.
PR checklist
Please tick as appropriate and edit the reasons (e.g.: "backport: not needed because this is a new feature")