Fix a null pointer dereference when performing some operations on zero
represented with 0 limbs: mbedtls_mpi_mod_int() dividing by 2, or
mbedtls_mpi_write_string() in base 2.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
Compilers are likely to generate shorter assembly for loops of the
form `while( cnt-- ) { ... }` rather than
`for( ; count >= X; count -= X ) { ... }`. (E.g. the latter needs
a subtract+compare+branch after each loop, while the former only
needs decrement+branch).
Signed-off-by: Hanno Becker <hanno.becker@arm.com>
Removing the trimming has significant memory impact. While it is clearly what
we want to do eventually for constant-time'ness, it should be fixed alongside
a strategy to contain the ramifications on memory usage.
Signed-off-by: Hanno Becker <hanno.becker@arm.com>
A previous commit has changed the signature of mpi_mul_hlp, making the length
of the output explicit. This commit adjusts mpi_montmul() accordingly.
It also fixes a comment on the required size of the temporary value
passed to mpi_montmul() (but does not change the call-sites).
Signed-off-by: Hanno Becker <hanno.becker@arm.com>
A previous commit has changed the signature of mpi_mul_hlp(), making
the length of the output explicit.
This commit adjusts mbedtls_mpi_mul_int() to this change.
Along the way, we make the code simpler and more secure by not calculating
the minimal limb-size of A. A previous comment indicated that this was
functionally necessary because of the implementation of mpi_mul_hlp() --
if it ever was, it isn't anymore.
Signed-off-by: Hanno Becker <hanno.becker@arm.com>
The previous commit has changed the signature of mpi_mul_hlp(),
making the length of the output explicit.
This commit adjusts the call-site in mbedtls_mpi_mul_mpi() to
this new signature.
A notable change to the multiplication strategy had to be made:
mbedtls_mpi_mul_mpi() performs a simple row-wise schoolbook
multiplication, which however was so far computed iterating
rows from top to bottom. This leads to the undesirable consequence
that as lower rows are calculated and added to the temporary
result, carry chains can grow. It is simpler and faster to
iterate from bottom to top instead, as it is guaranteed that
there will be no carry when adding the next row to the previous
temporary result: The length of the output in each iteration
can be fixed to len(B)+1.
Signed-off-by: Hanno Becker <hanno.becker@arm.com>
The helper `mpi_mul_hlp()` performs a multiply-accumulate
operation `d += s * b`, where `d,b` are MPIs and `b` is a scalar.
Previously, only the length of `s` was specified, while `d` was
assumed to be 0-terminated of unspecified length.
This was leveraged at the end of the core multiplication steps
computingg the first `limb(s)` limbs of `d + s*b`: Namely, the
routine would keep on adding the current carry to `d` until none
was left. This can, in theory, run for an arbitrarily long time
if `d` has a tail of `0xFF`s, and hence the assumption of
`0`-termination.
This solution is both fragile and insecure -- the latter because
the carry-loop depends on the result of the multiplication.
This commit changes the signature of `mpi_mul_hlp()` to receive
the length of the output buffer, which must be greater or equal
to the length of the input buffer.
It is _not_ assumed that the output buffer is strictly larger
than the input buffer -- instead, the routine will simply return
any carry that's left. This will be useful in some applications
of this function. It is the responsibility of the caller to either
size the output appropriately so that no carry will be left, or
to handle the carry.
NOTE: The commit leaves the library in a state where it cannot
be compiled since the call-sites of mpi_mul_hlp() have
not yet been adjusted. This will be done in the subsequent
commits.
Signed-off-by: Hanno Becker <hanno.becker@arm.com>
This commit removes code from the Montgomery multiplication routine
`mpi_montmul()` which seems to serve no purpose.
Details: `mpi_montmul()` uses a temporary storage `T` for intermediate
results which is assumed to be of twice the size as the inputs to be
multiplied, and which is used as follows: After the i-th (i=0,1,...)
iteration, the n-limb word starting at `T->p + i + 1` contains the
Montgomery multiplication of B with the limbs 0,..,i of A, and the
variable `d` points to `T->p + i + 1`. In particular, after `n` iterations,
`T->p + n` holds the full multiplication
(subject to conditional subtraction).
As a consequence of this way of using the temporary `T`, the contents
of `{T->p, ..., T->p + i}` are irrelevant after the i-th iteration. Nonetheless,
the code copies `A[i]` to `T->p[i]` at the end of the i-th iterations, which is
redundant and can be removed.
Signed-off-by: Hanno Becker <hanno.becker@arm.com>
Elinimate macros defined by modules locally in the functions that are
moving to the new constant-time module.
Signed-off-by: gabor-mezei-arm <gabor.mezei@arm.com>
There were multiple functions called mbedtls_cf_size_bool_eq. They had exactly
the same behavior, so move the one in bignum.c and remove the other.
Signed-off-by: gabor-mezei-arm <gabor.mezei@arm.com>
The loop exits early iff there is a nonzero limb, so i==0 means that
all limbs are 0, whether the number of limbs is 0 or not.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
Fix a bug introduced in "Fix multiplication producing a negative zero" that
caused the sign to be forced to +1 when A > 0, B < 0 and B's low-order limb
is 0.
Add a non-regression test. More generally, systematically test combinations
of leading zeros, trailing zeros and signs.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
In mbedtls_mpi_read_string, if the string is empty, return an empty bignum
rather than a bignum with one limb with the value 0.
Both representations are correct, so this is not, in principle, a
user-visible change. The change does leak however through
mbedtls_mpi_write_string in base 16 (but not in other bases), as it writes a
bignum with 0 limbs as "" but a bignum with the value 0 and at least one
limb as "00".
This change makes it possible to construct an empty bignum through
mbedtls_mpi_read_string, which is especially useful to construct test
cases (a common use of mbedtls_mpi_read_string, as most formats use in
production encode numbers in binary, to be read with mbedtls_mpi_read_binary
or mbedtls_mpi_read_binary_le).
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
Fix mbedtls_mpi_mul_mpi() when one of the operands is zero and the
other is negative. The sign of the result must be 1, since some
library functions do not treat {-1, 0, NULL} or {-1, n, {0}} as
representing the value 0.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
Shifting TA and TB before the loop is not necessary. If A != 0, it will be
done at the start of the loop iteration. If A == 0, then lz==0 and G is
correctly set to B after 0 loop iterations.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
Fix a null pointer dereference in mbedtls_mpi_exp_mod(X, A, N, E, _RR) when
A is the value 0 represented with 0 limbs.
Make the code a little more robust against similar bugs.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
Unrelated to RSA (only used in ECP), but while improving one
mbedtls_safe_cond_xxx function, let's improve the other as well.
Signed-off-by: Manuel Pégourié-Gonnard <manuel.pegourie-gonnard@arm.com>
mbedtls_mpi_cf_bool_eq() is a verbatim copy of mbedtls_ssl_cf_bool_eq()
Deduplication will be part of a future task.
Signed-off-by: Manuel Pégourié-Gonnard <manuel.pegourie-gonnard@arm.com>
Calling mbedtls_mpi_cmp_int reveals the number of leading zero limbs
to an adversary who is capable of very fine-grained timing
measurements. This is very little information, but could be practical
with secp521r1 (1/512 chance of the leading limb being 0) if the
adversary can measure the precise timing of a large number of
signature operations.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
The idiom "resize an mpi to a given size" appeared 4 times. Unify it
in a single function. Guarantee that the value is set to 0, which is
required by some of the callers and not a significant expense where
not required.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
Since the internal function mpi_fill_random_internal() assumes that X
has the right size, there is no need to call grow().
To further simplify the function, set the sign outside, and zero out
the non-randomized part directly.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
In real life, min << N and the probability that mbedtls_mpi_random()
fails to find a suitable value after 30 iterations is less than one in
a billion. But at least for testing purposes, it's useful to not
outright reject "silly" small values of N, and for such values, 30
iterations is not enough to have a good probability of success.
Pick 250 iterations, which is enough for cases like (min=3, N=4), but
not for cases like (min=255, N=256).
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
This comment is no longer in the specific context of generating a
random point on an elliptic curve.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
mbedtls_mpi_random() uses mbedtls_mpi_cmp_mpi_ct(), which requires its
two arguments to have the same storage size. This was not the case
when the upper bound passed to mbedtls_mpi_random() had leading zero
limbs.
Fix this by forcing the result MPI to the desired size. Since this is
not what mbedtls_mpi_fill_random() does, don't call it from
mbedtls_mpi_random(), but instead call a new auxiliary function.
Add tests to cover this and other conditions with varying sizes for
the two arguments.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
Since mbedtls_mpi_random() is not specific to ECC code, move it from
the ECP module to the bignum module.
This increases the code size in builds without short Weierstrass
curves (including builds without ECC at all) that do not optimize out
unused functions.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
Move the handling of the sign out of the base-specific loops. This
both simplifies the code, and corrects an edge case: the code in the
non-hexadecimal case depended on mbedtls_mpi_mul_int() preserving the
sign bit when multiplying a "negative zero" MPI by an integer, which
used to be the case but stopped with PR #2512.
Fix#4295. Thanks to Guido Vranken for analyzing the cause of the bug.
Credit to OSS-Fuzz.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
Move `include/mbedtls/bn_mul.h` to `library/bn_mul.h`.
Update includes and references to `bn_mul.h` to new location.
Also remove internal headers from `cpp_dummy_build.cpp` as it should only
test public headers in the library.
Signed-off-by: Chris Jones <christopher.jones@arm.com>
Fix a buffer overflow in mbedtls_mpi_sub_abs() when calculating
|A| - |B| where |B| is larger than |A| and has more limbs (so the
function should return MBEDTLS_ERR_MPI_NEGATIVE_VALUE).
Fix#4042
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
T1 is set to a 2-limb value. The first operation that takes it as
input is mbedtls_mpi_mul_int, which makes it grow to 3 limbs. Later it
is shifted left, which causes it to grow again. Set its size to the
final size from the start. This saves two calls to calloc(), at the
expense of a slowdown in some operations involving T1 as input since
it now has more leading zeros.
Setting T1 to 3 limbs initially instead of 2 saves about 6% of the
calloc() calls in test_suite_ecp and does not incur a performance
penalty. Setting T1 to A->n + 2 limbs instead of 2 saves about 20% of
the calloc calls and does not cause a measurable performance
difference on my Linux PC.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
Note a possible microoptimization in mbedtls_mpi_mul_hlp that I tried
in the hope of reducing the number of allocations, but turned out to
be counterproductive.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
Rewrite mbedtls_mpi_mul_int to call mpi_mul_hlp directly rather than
create a temporary mpi object. This has the benefit of not performing
an allocation when the multiplication is in place (mpi operand aliased
with the result) and the result mpi is large enough.
This saves about 40% of the calloc() calls in test_suite_ecp. There is
no measurable performance difference on my Linux PC.
The cost is a few bytes in bignum.o.
When there is no aliasing, or when there is aliasing but the mpi
object needs to be enlarged, the performance difference is negligible.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
mbedtls_mpi_sub_abs systematically allocated a new mpi when the result
was aliased with the right operand (i.e. X = A - X). This aliasing
very commonly happens during ECP operations. Rewrite the function to
allocate only if the result might not fit otherwise.
This costs a few bytes of code size in bignum.o, and might make
mbedtls_mpi_sub_abs very very slightly slower when no reallocation is
done. However, there is a substantial performance gain in ECP
operations with Montgomery curves (10-20% on my PC).
test_suite_ecp drops from 1422794 to 1271506 calls to calloc().
This commit also fixes a bug whereby mbedtls_mpi_sub_abs would leak
memory when X == B (so TB was in use) and the result was negative.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
Fix a memory leak in mbedtls_mpi_sub_abs when the output parameter is
aliased to the second operand (X = A - X) and the result is negative.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
* development: (488 commits)
Fix removal of deprecated PSA constants
Use GitHub-compatible table formatting
Remove psa header files in uninstall part
Change function casting in `ssl_calc_finished_tls_sha384`
Fix GCC warning in `ssl_calc_finished_tls_sha384`
Add changelog entry file to `ChangeLog.d`
Fix GCC warning in `ssl_calc_finished_tls_sha384`
Fix GCC warning about `test_snprintf`
Fix mismatched function parameters (prototype/definition)
Fix build failure on gcc-11
Copyediting
Clarifications around key import
Fix copypasta
A variable is unused in some configurations
Rename test_driver_keygen to test_driver_key_management
Move "internal use" sentence attached to the wrong function
Added changelog
Plug in the entry point for public key export through driver
tests: psa: Reset key attributes where needed
Improve/fix documentation
...
Check that the exponent and modulus is below `MBEDTLS_MPI_MAX_BITS` before
performing a time expensive operation (modular exponentiation). This prevents
a potential DoS from Diffie-Hellman computations with extremely
large key sizes.
Signed-off-by: Chris Jones <christopher.jones@arm.com>
Probably the `W[2 << MBEDTLS_MPI_WINDOW_SIZE]` notation is based on a transcription of 2**MBEDTLS_MPI_WINDOW_SIZE.
Signed-off-by: Daniel Otte <d.otte@wut.de>
As a result, the copyright of contributors other than Arm is now
acknowledged, and the years of publishing are no longer tracked in the
source files.
Also remove the now-redundant lines declaring that the files are part of
MbedTLS.
This commit was generated using the following script:
# ========================
#!/bin/sh
# Find files
find '(' -path './.git' -o -path './3rdparty' ')' -prune -o -type f -print | xargs sed -bi '
# Replace copyright attribution line
s/Copyright.*Arm.*/Copyright The Mbed TLS Contributors/I
# Remove redundant declaration and the preceding line
$!N
/This file is part of Mbed TLS/Id
P
D
'
# ========================
Signed-off-by: Bence Szépkúti <bence.szepkuti@arm.com>
In library source files, include "common.h", which takes care of
including "mbedtls/config.h" (or the alternative MBEDTLS_CONFIG_FILE)
and other things that are used throughout the library.
FROM=$'#if !defined(MBEDTLS_CONFIG_FILE)\n#include "mbedtls/config.h"\n#else\n#include MBEDTLS_CONFIG_FILE\n#endif' perl -i -0777 -pe 's~\Q$ENV{FROM}~#include "common.h"~' library/*.c 3rdparty/*/library/*.c scripts/data_files/error.fmt scripts/data_files/version_features.fmt
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
The function mbedtls_mpi_sub_abs first checked that A >= B and then
performed the subtraction, relying on the fact that A >= B to
guarantee that the carry propagation would stop, and not taking
advantage of the fact that the carry when subtracting two numbers can
only be 0 or 1. This made the carry propagation code a little hard to
follow.
Write an ad hoc loop for the carry propagation, checking the size of
the result. This makes termination obvious.
The initial check that A >= B is no longer needed, since the function
now checks that the carry propagation terminates, which is equivalent.
This is a slight performance gain.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
There was some confusion during review about when A->p[n] could be
nonzero. In fact, there is no need to set A->p[n]: only the
intermediate result d might need to extend to n+1 limbs, not the final
result A. So never access A->p[n]. Rework the explanation of the
calculation in a way that should be easier to follow.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
The function mpi_sub_hlp had confusing semantics: although it took a
size parameter, it accessed the limb array d beyond this size, to
propagate the carry. This made the function difficult to understand
and analyze, with a potential buffer overflow if misused (not enough
room to propagate the carry).
Change the function so that it only performs the subtraction within
the specified number of limbs, and returns the carry.
Move the carry propagation out of mpi_sub_hlp and into its caller
mbedtls_mpi_sub_abs. This makes the code of subtraction very slightly
less neat, but not significantly different.
In the one other place where mpi_sub_hlp is used, namely mpi_montmul,
this is a net win because the carry is potentially sensitive data and
the function carefully arranges to not have to propagate it.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
mpi_sub_hlp performs a subtraction A - B, but took parameters in the
order (B, A). Swap the parameters so that they match the usual
mathematical syntax.
This has the additional benefit of putting the output parameter (A)
first, which is the normal convention in this module.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
Let code analyzers know that this is deliberate. For example MSVC
warns about the conversion if it's implicit.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
In mpi_montmul, an auxiliary function for modular
exponentiation (mbedtls_mpi_mod_exp) that performs Montgomery
multiplication, the last step is a conditional subtraction to force
the result into the correct range. The current implementation uses a
branch and therefore may leak information about secret data to an
adversary who can observe what branch is taken through a side channel.
Avoid this potential leak by always doing the same subtraction and
doing a contant-trace conditional assignment to set the result.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
Separate out a version of mpi_safe_cond_assign that works on
equal-sized limb arrays, without worrying about allocation sizes or
signs.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
This reverts commit 2cc69fffcf.
A check was added in mpi_montmul because clang-analyzer warned about a
possibly null pointer. However this was a false positive. Recent
versions of clang-analyzer no longer emit a warning (3.6 does, 6
doesn't).
Incidentally, the size check was wrong: mpi_montmul needs
T->n >= 2 * (N->n + 1), not just T->n >= N->n + 1.
Given that this is an internal function which is only used from one
public function and in a tightly controlled way, remove both the null
check (which is of low value to begin with) and the size check (which
would be slightly more valuable, but was wrong anyway). This allows
the function not to need to return an error, which makes the source
code a little easier to read and makes the object code a little
smaller.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
If Y was constructed through functions in this module, then Y->n == 0
iff Y->p == NULL. However we do not prevent filling mpi structures
manually, and zero may be represented with n=0 and p a valid pointer.
Most of the code can cope with such a representation, but for the
source of mbedtls_mpi_copy, this would cause an integer underflow.
Changing the test for zero from Y->p==NULL to Y->n==0 causes this case
to work at no extra cost.
In the case of *ret we might need to preserve a 0 value throughout the
loop and therefore we need an extra condition to protect it from being
overwritten.
The value of done is always 1 after *ret has been set and does not need
to be protected from overwriting. Therefore in this case the extra
condition can be removed.
The code relied on the assumptions that CHAR_BIT is 8 and that unsigned
does not have padding bits.
In the Bignum module we already assume that the sign of an MPI is either
-1 or 1. Using this, we eliminate the above mentioned dependency.
The signature of mbedtls_mpi_cmp_mpi_ct() meant to support using it in
place of mbedtls_mpi_cmp_mpi(). This meant full comparison functionality
and a signed result.
To make the function more universal and friendly to constant time
coding, we change the result type to unsigned. Theoretically, we could
encode the comparison result in an unsigned value, but it would be less
intuitive.
Therefore we won't be able to represent the result as unsigned anymore
and the functionality will be constrained to checking if the first
operand is less than the second. This is sufficient to support the
current use case and to check any relationship between MPIs.
The only drawback is that we need to call the function twice when
checking for equality, but this can be optimised later if an when it is
needed.
Multiplication is known to have measurable timing variations based on
the operands. For example it typically is much faster if one of the
operands is zero. Remove them from constant time code.
1. variable name accoriding to the Mbed TLS coding style;
2. add a comment explaining safety of the optimization;
3. safer T2 initialization and memory zeroing on the function exit;
* restricted/pr/551:
ECP: Clarify test descriptions
ECP: remove extra whitespaces
Fix ECDH secret export for Mongomery curves
Improve ECP test names
Make ecp_get_type public
Add more tests for ecp_read_key
ECP: Catch unsupported import/export
Improve documentation of mbedtls_ecp_read_key
Fix typo in ECP module
Remove unnecessary cast from ECP test
Improve mbedtls_ecp_point_read_binary tests
Add Montgomery points to ecp_point_write_binary
ECDH: Add test vectors for Curve25519
Add little endian export to Bignum
Add mbedtls_ecp_read_key
Add Montgomery points to ecp_point_read_binary
Add little endian import to Bignum
The function `mbedtls_mpi_write_binary()` writes big endian byte order,
but we need to be able to write little endian in some caseses. (For
example when handling keys corresponding to Montgomery curves.)
Used `echo xx | tac -rs ..` to transform the test data to little endian.
The private keys used in ECDH differ in the case of Weierstrass and
Montgomery curves. They have different constraints, the former is based
on big endian, the latter little endian byte order. The fundamental
approach is different too:
- Weierstrass keys have to be in the right interval, otherwise they are
rejected.
- Any byte array of the right size is a valid Montgomery key and it
needs to be masked before interpreting it as a number.
Historically it was sufficient to use mbedtls_mpi_read_binary() to read
private keys, but as a preparation to improve support for Montgomery
curves we add mbedtls_ecp_read_key() to enable uniform treatment of EC
keys.
For the masking the `mbedtls_mpi_set_bit()` function is used. This is
suboptimal but seems to provide the best trade-off at this time.
Alternatives considered:
- Making a copy of the input buffer (less efficient)
- removing the `const` constraint from the input buffer (breaks the api
and makes it less user friendly)
- applying the mask directly to the limbs (violates the api between the
modules and creates and unwanted dependency)
The function `mbedtls_mpi_read_binary()` expects big endian byte order,
but we need to be able to read from little endian in some caseses. (For
example when handling keys corresponding to Montgomery curves.)
Used `echo xx | tac -rs .. | tr [a-z] [A-Z]` to transform the test data
to little endian and `echo "ibase=16;xx" | bc` to convert to decimal.