In `psa_cipher_decrypt()` and in the corresponding function in our built-in
implementation `mbedtls_psa_cipher_decrypt()`, treat `status` and
`*output_length` as sensitive variables whose value must not leak through a
timing side channel. This is important when doing decryption with unpadding,
where leaking the validity or amount of padding can enable a padding oracle
attack.
With this change, `psa_cipher_decrypt()` should be constant-time if the
underlying legacy function (including the cipher implementation) is.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
In `psa_cipher_finish()` and in the corresponding function in our built-in
implementation `mbedtls_psa_cipher_finish()`, treat `status` and
`*output_length` as sensitive variables whose value must not leak through a
timing side channel. This is important when doing decryption with unpadding,
where leaking the validity or amount of padding can enable a padding oracle
attack.
With this change, `psa_cipher_finish()` should be constant-time if the
underlying legacy function (including the cipher implementation) is.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
Factor some common code for one-shot or multipart encryption/decryption into
auxiliary functions. No behavior change.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
The main goal is to validate that unpadding is constant-time, including
error reporting.
Use a separate test function, not annotations in the existing function, so
that the functional tests can run on any platform, and we know from test
outcomes where we have run the constant-time tests.
The tests can only be actually constant-time if AES is constant time, since
AES computations are part of what is checked. Thus this requires
hardware-accelerated AES. We can't run our AESNI (or AESCE?) code under
Msan (it doesn't detect when memory is written from assembly code), so these
tests can only be run with Valgrind.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
`SIZE_MAX` and `~(size_t) 0` are the same, but since the documentation says
"all-bits-one", write it that way in the test code.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
A function that was previously called in multiple places is now called
only once, hence more susceptible to being inlined, hence the test fix.
Signed-off-by: Manuel Pégourié-Gonnard <manuel.pegourie-gonnard@arm.com>
The overall function is still not constant-time, but it just got a lot
less leaky.
Signed-off-by: Manuel Pégourié-Gonnard <manuel.pegourie-gonnard@arm.com>
The path using builtin should be OK, as it should be using dedicated CPU
instructions which are constant time.
This fixes the no-builing path.
GCC gained support for __has_builtin in version 10. We're still testing
with older GCC on the CI, so the non-builtin path is tested on the CI.
https://gcc.gnu.org/gcc-10/changes.html
Signed-off-by: Manuel Pégourié-Gonnard <manuel.pegourie-gonnard@arm.com>
In the next refactoring we'll have:
- pretty different paths for N odd or even,
- possibly different paths for A <= 0, in [0, N) or above,
- possibly special cases when A % N is 0 or 1.
Pick two small moduli of different parities (3 and 4)
and go over the range [-(N+1), 2N-1] with A.
This should ensure we naturally run into all special cases.
Signed-off-by: Manuel Pégourié-Gonnard <manuel.pegourie-gonnard@arm.com>
Addresses https://github.com/Mbed-TLS/mbedtls/issues/9586 .
This is not a fully satisfactory resolution, because we don't run every
constant-flow test with Valgrind in PR jobs, only a small subset. We should
improve the coverage/resource balance.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
Some tests from `test_suite_cipher.constant_time.data` follow the same
pattern as `test_suite_cipher.aes.data` and so have the same coverage
discrepancy.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
The decrypted length reveals the amount of padding that was eliminated, and
thus reveals partial information about the last ciphertext block.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>