Context: This commit makes a change to mbedtls_pk_parse_key() which
is responsible for parsing of private keys. The function doesn't know
the key format in advance (PEM vs. DER, encrypted vs. unencrypted) and
tries them one by one, resetting the PK context in between.
Issue: The previous code resets the PK context through a call to
mbedtls_pk_free() along, lacking the accompanying mbedtls_pk_init()
call. Practically, this is not an issue because functionally
mbedtls_pk_free() + mbedtls_pk_init() is equivalent to mbedtls_pk_free()
with the current implementation of these functions, but strictly
speaking it's nonetheless a violation of the API semantics according
to which xxx_free() functions leave a context in uninitialized state.
(yet not entirely random, because xxx_free() functions must be idempotent,
so they cannot just fill the context they operate on with garbage).
Change: The commit adds calls to mbedtls_pk_init() after those calls
to mbedtls_pk_free() within mbedtls_pk_parse_key() after which the
PK context might still be used.
When a random number is generated for the Miller-Rabin primality test,
if the bit length of the random number is larger than the number being
tested, the random number is shifted right to have the same bit length.
This introduces bias, as the random number is now guaranteed to be
larger than 2^(bit length-1).
Changing this to instead zero all bits higher than the tested numbers
bit length will remove this bias and keep the random number being
uniformly generated.
Primality tests have to deal with different distribution when generating
primes and when validating primes.
These new tests are testing if mbedtls_mpi_is_prime() is working
properly in the latter setting.
The new tests involve pseudoprimes with maximum number of
non-witnesses. The non-witnesses were generated by printing them
from mpi_miller_rabin(). The pseudoprimes were generated by the
following function:
void gen_monier( mbedtls_mpi* res, int nbits )
{
mbedtls_mpi p_2x_plus_1, p_4x_plus_1, x, tmp;
mbedtls_mpi_init( &p_2x_plus_1 );
mbedtls_mpi_init( &p_4x_plus_1 );
mbedtls_mpi_init( &x ); mbedtls_mpi_init( &tmp );
do
{
mbedtls_mpi_gen_prime( &p_2x_plus_1, nbits >> 1, 0,
rnd_std_rand, NULL );
mbedtls_mpi_sub_int( &x, &p_2x_plus_1, 1 );
mbedtls_mpi_div_int( &x, &tmp, &x, 2 );
if( mbedtls_mpi_get_bit( &x, 0 ) == 0 )
continue;
mbedtls_mpi_mul_int( &p_4x_plus_1, &x, 4 );
mbedtls_mpi_add_int( &p_4x_plus_1, &p_4x_plus_1, 1 );
if( mbedtls_mpi_is_prime( &p_4x_plus_1, rnd_std_rand,
NULL ) == 0 )
break;
} while( 1 );
mbedtls_mpi_mul_mpi( res, &p_2x_plus_1, &p_4x_plus_1 );
}
When MBEDTLS_MEMORY_BUFFER_ALLOC_C was defined, the sample ssl_server2.c was
using its own memory buffer for memory allocated by the library. The memory
used wasn't obvious, so this adds a macro for the memory buffer allocated to
make the allocated memory size more obvious and hence easier to configure.
Newer features in the library have increased the overall RAM usage of the
library, when all features are enabled. ssl_server2.c, with all features enabled
was running out of memory for the ssl-opt.sh test 'Authentication: client
max_int chain, server required'.
This commit increases the memory buffer allocation for ssl_server2.c to allow
the test to work with all features enabled.
This commit changes the behavior of the record decryption routine
`ssl_decrypt_buf()` in the following situation:
1. A CBC ciphersuite with Encrypt-then-MAC is used.
2. A record with valid MAC but invalid CBC padding is received.
In this situation, the previous code would not raise and error but
instead forward the decrypted packet, including the wrong padding,
to the user.
This commit changes this behavior to return the error
MBEDTLS_ERR_SSL_INVALID_MAC instead.
While erroneous, the previous behavior does not constitute a
security flaw since it can only happen for properly authenticated
records, that is, if the peer makes a mistake while preparing the
padded plaintext.
This commit duplicates the public function mbedtls_asn1_find_named_data()
defined in library/asn1parse.c within library/asn1write.c in order to
avoid a dependency of the ASN.1 writing module on the ASN.1 parsing module.
The duplication is unproblematic from a semantic and an efficiency
perspective becasue it is just a short list traversal that doesn't
actually do any ASN.1 parsing.
Previously, mbedtls_pkcs5_pbes2() was unconditionally declared
in `pkcs5.h` but defined as a stub returning
`MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE` in case
MBEDTLS_ASN1_PARSE_C was not defined.
In line with the previous commits, this commit removes declaration
and definition from both `pkcs5.h` and `pkcs5.c` in case
MBEDTLS_ASN1_PARSE_C is not defined.
This commit ensures that buffers holding fragmented or
handshake messages get zeroized before they are freed
when the respective handshake message is no longer needed.
Previously, the handshake message content would leak on
the heap.
This commit replaces multiple `memset()` calls in the example
programs aes/aescrypt2.c and aes/crypt_and_hash.c by calls to
the reliable zeroization function `mbedtls_zeroize()`.
While not a security issue because the code is in the example
programs, it's bad practice and should be fixed.
The `id` parameter of the public `MBEDTLS_X509_ID_FLAG` macro was
used in a subtraction without being surrounded by parentheses.
Since some operators bind less strongly than subtraction, this
could lead to erroneous evaluation of `MBEDTLS_X509_ID_FLAG`.
For example, `MBEDTLS_X509_ID_FLAG( 1 << 2 )` would evaluate
evaluate to
`1 << ( 1 << 2 - 1 ) == 1 << ( 1 << 1 ) == 4`
instead of the intended
`1 << ( ( 1 << 2 ) - 1 ) == 1 << ( 4 - 1 ) == 8`.
This commit fixes this by adding parentheses about the `id`
parameter in the definition of `MBEDTLS_X509_ID_FLAG`.
The code assumed that `int x = - (unsigned) u` with 0 <= u < INT_MAX
sets `x` to the negative of u, but actually this calculates
(UINT_MAX - u) and then converts this value to int, which overflows.
Cast to int before applying the unary minus operator to guarantee the
desired behavior.
The code was making two unsequenced reads from volatile locations.
This is undefined behavior. It was probably harmless because we didn't
care in what order the reads happened and the reads were from ordinary
memory, but UB is UB and IAR8 complained.
The input distribution to primality testing functions is completely
different when used for generating primes and when for validating
primes. The constants used in the library are geared towards the prime
generation use case and are weak when used for validation. (Maliciously
constructed composite numbers can pass the test with high probability)
The mbedtls_mpi_is_prime() function is in the public API and although it
is not documented, it is reasonable to assume that the primary use case
is validating primes. The RSA module too uses it for validating key
material.
This commit removes the definition of the API function
`mbedtls_platform_set_calloc_free()`
from `library/platform.c` in case the macros
`MBEDTLS_PLATFORM_CALLOC_MACRO`
`MBEDTLS_PLATFORM_FREE_MACRO`
for compile time configuration of calloc/free are set.
This is in line with the corresponding header `mbedtls/platform.h`
which declares `mbedtls_platform_set_calloc_free()` only if
`MBEDTLS_PLATFORM_{CALLOC/FREE}_MACRO` are not defined.
Fixes#1642.
This commit adds a test to tests/scripts/all.sh exercising an
ASan build of the default configuration with
MBEDTLS_PLATFORM_MEMORY enabled,
MBEDTLS_PLATFORM_CALLOC_MACRO set to std calloc
MBEDTLS_PLATFORM_FREE_MACRO set to std free
(This should functionally be indistinguishable from a default build)
The previous code triggered a compiler warning because of a comparison
of a signed and an unsigned integer.
The conversion is safe because `len` is representable by 16-bits,
hence smaller than the maximum integer.
If `MBEDTLS_MEMORY_BUFFER_ALLOC_C` is configured and Mbed TLS'
custom buffer allocator is used for calloc() and free(), the
read buffer used by the server example application is allocated
from the buffer allocator, but freed after the buffer allocator
has been destroyed. If memory backtracing is enabled, this leaves
a memory leak in the backtracing structure allocated for the buffer,
as found by valgrind.
Fixes#2069.
In the previous bounds check `(*p) > end - len`, the computation
of `end - len` might underflow if `end` is within the first 64KB
of the address space (note that the length `len` is controlled by
the peer). In this case, the bounds check will be bypassed, leading
to `*p` exceed the message bounds by up to 64KB when leaving
`ssl_parse_server_psk_hint()`. In a pure PSK-based handshake,
this doesn't seem to have any consequences, as `*p*` is not accessed
afterwards. In a PSK-(EC)DHE handshake, however, `*p` is read from
in `ssl_parse_server_ecdh_params()` and `ssl_parse_server_dh_params()`
which might lead to an application crash of information leakage.
Functional tests for various payload sizes and output buffer sizes.
When the padding is bad or the plaintext is too large for the output
buffer, verify that function writes some outputs. This doesn't
validate that the implementation is time-constant, but it at least
validates that it doesn't just return early without outputting anything.
Get rid of the variable p. This makes it more apparent where the code
accesses the buffer at an offset whose value is sensitive.
No intended behavior change in this commit.
Rather than doing the quadratic-time constant-memory-trace on the
whole working buffer, do it on the section of the buffer where the
data to copy has to lie, which can be significantly smaller if the
output buffer is significantly smaller than the working buffer, e.g.
for TLS RSA ciphersuites (48 bytes vs MBEDTLS_MPI_MAX_SIZE).
In mbedtls_rsa_rsaes_pkcs1_v15_decrypt, use size_greater_than (which
is based on bitwise operations) instead of the < operator to compare
sizes when the values being compared must not leak. Some compilers
compile < to a branch at least under some circumstances (observed with
gcc 5.4 for arm-gnueabi -O9 on a toy program).
Replace memmove(to, to + offset, length) by a functionally equivalent
function that strives to make the same memory access patterns
regardless of the value of length. This fixes an information leak
through timing (especially timing of memory accesses via cache probes)
that leads to a Bleichenbacher-style attack on PKCS#1 v1.5 decryption
using the plaintext length as the observable.
mbedtls_rsa_rsaes_pkcs1_v15_decrypt takes care not to reveal whether
the padding is valid or not, even through timing or memory access
patterns. This is a defense against an attack published by
Bleichenbacher. The attacker can also obtain the same information by
observing the length of the plaintext. The current implementation
leaks the length of the plaintext through timing and memory access
patterns.
This commit is a first step towards fixing this leak. It reduces the
leak to a single memmove call inside the working buffer.
Make the function more robust by taking an arbitrary zero/nonzero
argument instead of insisting on zero/all-bits-one. Update and fix its
documentation.
mbedtls_rsa_rsaes_pkcs1_v15_decrypt took care of calculating the
padding length without leaking the amount of padding or the validity
of the padding. However it then skipped the copying of the data if the
padding was invalid, which could allow an adversary to find out
whether the padding was valid through precise timing measurements,
especially if for a local attacker who could observe memory access via
cache timings.
Avoid this leak by always copying from the decryption buffer to the
output buffer, even when the padding is invalid. With invalid padding,
copy the same amount of data as what is expected on valid padding: the
minimum valid padding size if this fits in the output buffer,
otherwise the output buffer size. To avoid leaking payload data from
an unsuccessful decryption, zero the decryption buffer before copying
if the padding was invalid.