Add more variation to the random delay function by xor:ing two
variables. It is not enough to increment just a counter to create a
delay as it will be visible as uniform delay that can be easily
removed from the trace by analysis.
The flag is used for tracking if the premaster has
been succesfully generated. Note that when resuming
a session, the flag should not be used when trying to
notice if all the key generation/derivation has been done.
Default flow assumes failure causes multiple issues with
compatibility tests when the return value is initialised
with error value in ssl_in_server_key_exchange_parse.
The function would need a significant change in structure for this.
The verification could be skipped in server, changed the default flow
so that the handshake status is ever updated if the verify
succeeds, and that is checked twice.
Check that the encryption has been done for the outbut buffer.
This is to ensure that glitching out the encryption doesn't
result as a unecrypted buffer to be sent.
This is to enable hardening the security when changing
states in state machine so that the state cannot be changed by bit flipping.
The later commit changes the enumerations so that the states have large
hamming distance in between them to prevent this kind of attack.
-Replace usage of rand() with mbedtls_platform_random_in_range()
-Prevent for-ever loop by hardcoding SCA countermeasure position in
case of used random function is always returning constant number.
-Use separate control bytes for start and final round to get them
randomized separately.
-Remove struct name.
-Fix comments and follow Mbed TLS coding style.
SCA CM implementation caused AES performance drop. For example
AES-CCM-128 calculation speed was dropped from 240 KB/s to 111 KB/s.
(-54%), Similarily AES-CBC-128 calculation speed was dropped from
536 KB/s to 237 KB/s (-56%).
Use functions instead of macros to reduce code indirections and
therefore increase performance. Now the performance is 163 KB/s for
AES-CCM-128 (-32%) and 348 KB/s for AES-CBC-128 (-35%).
When SCA countermeasures are activated the performance is as follows:
122 KB/s for AES-CCM-128 (-49%) and 258 KB/s for AES-CBC-128 (-52%)
compared to the original AES implementation.
Use control bytes to instruct AES calculation rounds. Each
calculation round has a control byte that indicates what data
(real/fake) is used and if any offset is required for AES data
positions.
First and last AES calculation round are calculated with SCA CM data
included. The calculation order is randomized by the control bytes.
Calculations between the first and last rounds contains 3 SCA CMs
in randomized positions.
- Add configuration for AES_SCA_COUNTERMEASURES to config.h. By
default the feature is disabled.
- Add AES_SCA_COUNTERMEASURES configuration check to check_config.h
- Add AES_SCA_COUNTERMEASURES test to all.sh
- 3 additional dummy AES rounds calculated with random data for each
AES encryption/decryption
- additional rounds can be occur in any point in sequence of rounds
- MSVC doesn't like -1u
- We need to include platform.h for MBEDTLS_ERR_PLATFORM_FAULT_DETECTED - in
some configurations it was already included indirectly, but not in all
configurations, so better include it directly.
This commit first changes the return convention of EccPoint_mult_safer() so
that it properly reports when faults are detected. Then all functions that
call it need to be changed to (1) follow the same return convention and (2)
properly propagate UECC_FAULT_DETECTED when it occurs.
Here's the reverse call graph from EccPoint_mult_safer() to the rest of the
library (where return values are translated to the MBEDTLS_ERR_ space) and test
functions (where expected return values are asserted explicitly).
EccPoint_mult_safer()
EccPoint_compute_public_key()
uECC_compute_public_key()
pkparse.c
tests/suites/test_suite_pkparse.function
uECC_make_key_with_d()
uECC_make_key()
ssl_cli.c
ssl_srv.c
tests/suites/test_suite_pk.function
tests/suites/test_suite_tinycrypt.function
uECC_shared_secret()
ssl_tls.c
tests/suites/test_suite_tinycrypt.function
uECC_sign_with_k()
uECC_sign()
pk.c
tests/suites/test_suite_tinycrypt.function
Note: in uECC_sign_with_k() a test for uECC_vli_isZero(p) is suppressed
because it is redundant with a more thorough test (point validity) done at the
end of EccPoint_mult_safer(). This redundancy was introduced in a previous
commit but not noticed earlier.
-Add flow monitor, loop integrity check and variable doubling to
harden mbedtls_hmac_drbg_update_ret.
-Use longer hamming distance for nonce usage in hmac_drbg_reseed_core
-Return actual value instead of success in mbedtls_hmac_drbg_seed and
mbedtls_hmac_drbg_seed_buf
-Check illegal condition in hmac_drbg_reseed_core.
-Double buf/buf_len variables in mbedtls_hmac_drbg_random_with_add
-Add more hamming distance to MBEDTLS_HMAC_DRBG_PR_ON/OFF
Added an additional Makefile option of 'TINYCRYPT_BUILD' to exclude the
TinyCrypt source files from the build. This allows some tests to exclude those
files as and when necessary.
Specifically this includes in all.sh the test
'component_build_arm_none_eabi_gcc_no_64bit_multiplication' which was failing as
64bit cannot be disabled in TinyCrypt, and check-names.sh as TinyCrypt obviously
does not conform to Mbed TLS naming conventions.
In the previous version, it was enough for the attacker to glitch the
top-level 'if' to skip the entire block. We want two independent blocks here,
so that an attacker can only succeed with two successive glitches.
Before this commit, if a certificate only had one issue (for example, if the
"untrusted" bit was the only set in flags), an attacker that could flip this
single bit between the moment it's set and the moment flags are checked before
returning from mbedtls_x509_crt_verify() could make the entire verification
routine appear to succeed (return 0 with no bit set in flags).
Avoid that by making sure that flags always has either 0 or at least 9 bits
set during the execution of the function. However, to preserve the API, clear
the 8 extra bits before returning. This doesn't open the door to other
attacks, as fortunately the API already had redundancy: either both flags and
the return value are 0, or flags has bits set and the return value is non-zero
with at least 16 bits set (assuming 32-bit 2-complement ints).
If signature_is_good is 0 (invalid) of 1 (valid), then it's all too easy for
an active physical attacker to turn invalid into valid by flipping a single
bit in RAM, on the bus or in a CPU register.
Use a special value to represent "valid" that can't easily be reached by
flipping a few bits.
x509_crt_check_signature() directly returns the return value of
pk_verify_xxx() without looking at it, so nothing to do here. But its caller
compares the value to 0, which ought to be double-checked.
Inspection of the generated assembly showed that before this commit, armcc 5
was optimizing away the successive reads to the volatile local variable that's
used for double-checks. Inspection also reveals that inserting a call to an
external function is enough to prevent it from doing that.
The tested versions of ARM-GCC, Clang and Armcc 6 (aka armclang) all keep the
double read, with our without a call to an external function in the middle.
The inserted function can also be changed to insert a random delay if
desired in the future, as it is appropriately places between the reads.
This can be used by Mbed TLS functions in any module to signal that a fault
attack is likely happening, so this can be appropriately handled by the
application (report, fall back to safer mode or even halt, etc.)
This is a first step in protecting against fault injection attacks: the
attacker can no longer change failure into success by flipping a single bit.
Additional steps are needed to prevent other attacks (instruction skip etc)
and will be the object of future commits.
The return value of uECC_vli_equal() should be protected as well, which will
be done in a future commit as well.
This is a temporary work-around for an integration issue.
A future task will re-integrate randomness into these functions are their
entire point is to be randomized; this is really just temporary.
Record checking fails if mbedtls_ssl_check_record() is called with
external buffer. Received record sequence number is available in the
incoming record but it is not available in the ssl contexts `in_ctr`-
variable that is used when decoding the sequence number.
To fix the problem, temporarily update ssl context `in_ctr` to
point to the received record header and restore value later.
-Add config option for AES encyption only to config.h. Feature is
disabled by default.
-Enable AES encrypt only feature in baremetal.h configuration
-Remove AES encypt only feature from full config
- out_ctr is public because it's transmited over the wire in DTLS (and in TLS
it can be inferred by a passive network attacker just by counting records).
- handshake mask is not a secret because it can be inferred by a passive
network attacker just logging record sequence number seen so far.
This commits reverts to plain memset() for cases like:
some_type foo;
memset( &foo, 0, sizeof( foo ) );
(Sometimes there is code between declaration in memset(), but it doesn't
matter as long as it doesn't touch foo.)
The reasoning is the same as in the previous commit: the stack shouldn't
contain sensitive data as we carefully wipe it after use.
We call xxx_init() on a structure when it has been freshly allocated (on the
stack or heap).
At this point it contains random-looking data none of which should be
sensitive, as all sensitive data is wiped using mbedtls_platform_zeroize()
when we're done using it and the memory area is going to be reclaimed (by
exiting the function or free()ing the buffer).
Add it in all files that use mbedtls_plaform_memset() but didn't already
include platfom_util.h.
In some configurations it just happened to work, either because it was
included indirectly or because the part of the code that used that function
was disabled, but it some configurations it broke, so let's fix it properly.
Steps:
1. sed -i 's/\bmemset(\([^)]\)/mbedtls_platform_memset(\1/g' library/*.c tinycrypt/*.c include/mbedtls/*.h scripts/data_files/*.fmt
2. Manually edit library/platform_util.c to revert to memset() in the
implementations of mbedtls_platform_memset() and mbedtls_platform_memcpy()
3. egrep -n '\<memset\>' library/*.c include/mbedtls/*.h tinycrypt/*.c
The remaining occurrences are in three categories:
a. From point 2 above.
b. In comments.
c. In the initialisation of memset_func, to be changed in a future commit.