In the PSA crypto library, the code for verification of ECDSA is the same for
both MBEDTLS_PSA_BUILTIN_ALG_ECDSA and
MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA. So, the guards should allow for
either one to enable the code blocks. The original implementation only had
the check for ECDSA. In order to make this work, config_psa.h was updated
to ensure when MBEDTLS_CRYPTO_CONFIG is disabled, the setting for DETERMINISTIC
is only updated if MBEDTLS_ECDSA_C is also enabled.
Signed-off-by: John Durkop <john.durkop@fermatsoftware.com>
Now that there's a validate_key entry point for drivers, it becomes
much more important to separate the import action (where a key needs
to be validated) from the load action (where a key has been
previously validated, and thus re-validating it would be a waste of
time).
This also exposes why not storing the 'bits' attribute persistently
was a bad idea. The only reason there's a rather large function to
detect bit size is because loading from persistent storage requires
it.
Signed-off-by: Steven Cooreman <steven.cooreman@silabs.com>
There's no need for calling export-and-import when the key is
guaranteed to have been stored in export representation.
Signed-off-by: Steven Cooreman <steven.cooreman@silabs.com>
The psa crypto library was generically using PSA_WANT_ALG_xxx, but
should have been using the correct MBEDTLS_PSA_BUILTIN_ALG_xxx
definition since that code is the builtin version. There were also
a couple of spots that needed to ensure the code block was enabled
for either ECDSA or DETERMINISTIC_ECDSA, not just one of them.
Fixed all the new ALG_ECDSA_DETERMINISTIC names to be
ALG_DETERMINISTIC_ECDSA instead.
Fixed test to use correct definitions.
Signed-off-by: John Durkop <john.durkop@fermatsoftware.com>
* Stores bits in psa_persistent_key_storage_format.
* psa_load_persistent_key_into_slot still imports plaintext keys which
ensures that the bits value gets set.
* Updates key specification to match new implementation.
* Expands persistent store and load tests with to check for bits
attribute.
* Removes bits storage from psa_se_key_data_storage_t.
Signed-off-by: Torstein Nesse <torstein.nesse@silabs.com>
* #3742 After input of a key as SECRET in the derivation, allow the
derivation result to be used as key.
Signed-off-by: Steven Cooreman <steven.cooreman@silabs.com>
* #3741 Allow key agreement inside derivation with a key that's allowed
for the relevant agreement.
Signed-off-by: Steven Cooreman <steven.cooreman@silabs.com>
In psa_generate_key_internal() for ECC keys, remove the check that the
bit-size according to Mbed TLS is equal to the requested bit-size.
This check was necessary back when the PSA API encoded curves and key
sizes independently, in order to reject combinations such as SECP256R1
with a 512-bit size. Since the curve encoding changed to specifying a
curve family and a size separately, the Mbed TLS curve id (grp_id) and
the curve data (curve_info) are now determined from the size, and
checking that (curve_info->bit_size == bits) is now only a redundant
sanity check.
This check is actually buggy, because PSA Crypto and Mbed TLS don't
have exactly the same notion of key size. PSA thinks Curve25519 is
255-bit and secp224k1 is 225-bit, but Mbed TLS thinks they're 256-bit
and 224-bit respectively. Removing the check allows key generation to
work for these curves.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
... as opposed to PSA_ERROR_BAD_STATE.
The spec on psa_cipher_finish() states that PSA_ERROR_INVALID_ARGUMENT
should be returned when:
"The total input size passed to this operation is not valid for this
particular algorithm. For example, the algorithm is a based on block
cipher and requires a whole number of blocks, but the total input size
is not a multiple of the block size."
Currently, there is a distinction between encryption and decryption
on whether INVALID_ARGUMENT or BAD_STATE is returned, but this is not
a part of the spec.
This fix ensures that PSA_ERROR_INVALID_ARGUMENT is returned
consistently on invalid cipher input sizes.
Signed-off-by: Fredrik Strupe <fredrik.strupe@silabs.com>
Initial changes to PSA crypto core to support configuration
of ECDSA algorithm using PSA crypto configuration mechanism.
Guards using MBEDTLS_ECDSA_C and MBEDTLS_ECDSA_DETERMINISTIC have
been changed to be based off PSA_WANT_ALG_ECDSA and
PSA_WANT_ALG_ECDSA_DETERMINISTIC. Added new tests to all.sh to
confirm new settings are working properly. Current code does not
pass the tests since built in signature verification is not in place.
Signed-off-by: John Durkop <john.durkop@fermatsoftware.com>
* Reworked the cipher context once again to be more robustly defined
* Removed redundant memset
* Unified behaviour on failure between driver and software in cipher_finish
* Cipher test driver setup function now also returns early when its status
is overridden, like the other test driver functions
* Removed redundant test cases
* Added bad-order checking to verify the driver doesn't get called where
the spec says it won't.
Signed-off-by: Steven Cooreman <steven.cooreman@silabs.com>
As pointed out by Ronald. The key slot is populated using
get_key_from_slot, and after calling the driver the slot is
validated to not contain an external key, so calling
get_transparent_key is superfluous.
Signed-off-by: Steven Cooreman <steven.cooreman@silabs.com>
Once an operation has been 'accepted' by a driver, the remainder is bound
to the same driver, since driver-specific context structs cannot be shared.
This provides a pretty good gate mechanism for the fallback logic, too.
Signed-off-by: Steven Cooreman <steven.cooreman@silabs.com>
This is a more natural place for handling the drivers belonging to the
'previous' SE driver spec. It makes for a cleaner psa_crypto.c, and
potentially an easier overview of how to migrate from the old SE driver
interface to the 'opaque accelerator' interface.
Signed-off-by: Steven Cooreman <steven.cooreman@silabs.com>
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>
Since it is being dereferenced by free on exit it should be inited to NULL.
Also added a small test that would trigger the issue.
Signed-off-by: Steven Cooreman <steven.cooreman@silabs.com>
* return is treated as a function call
* space between opening and closing parentheses
* remove whiteline between assignment and checking of same variable
Signed-off-by: Steven Cooreman <steven.cooreman@silabs.com>
* No need to check for NULL before free'ing
* No need to reset variables that weren't touched
* Set output buffer to zero if key output fails
* Document internal functions and rearrange order of input arguments to
better match other functions.
* Clean up Montgomery fix to be less verbose code
Signed-off-by: Steven Cooreman <steven.cooreman@silabs.com>
PSA Crypto was checking the byte length of a to-be-imported public ECP key
against the expected length for Weierstrass keys, forgetting that
Curve25519/Curve448 exists.
Signed-off-by: Steven Cooreman <steven.cooreman@silabs.com>
Avoids stack-allocating a key slot during ECDH, and mock-attaching a
key to a key slot during key import.
Signed-off-by: Steven Cooreman <steven.cooreman@silabs.com>
* No null-check before calling free
* Close memory leak
* No need for double check of privkey validity
Signed-off-by: Steven Cooreman <steven.cooreman@silabs.com>
* Allocate internal representation contexts on the heap (i.e. don't change
where they're being allocated)
* Unify load_xxx_representation in terms of allocation and init behaviour
Signed-off-by: Steven Cooreman <steven.cooreman@silabs.com>
* Updated wording
* Split out buffer allocation to a convenience function
* Moved variable declarations to beginning of their code block
Signed-off-by: Steven Cooreman <steven.cooreman@silabs.com>
Now that both ECP and RSA keys are represented in export representation,
they can be treated more uniformly.
Signed-off-by: Steven Cooreman <steven.cooreman@silabs.com>
Change to on-demand loading of the internal representation when required
in order to call an mbed TLS cryptography API.
Signed-off-by: Steven Cooreman <steven.cooreman@silabs.com>
Change to on-demand loading of the internal representation when required
in order to call an mbed TLS cryptography API.
Signed-off-by: Steven Cooreman <steven.cooreman@silabs.com>
In preparation for the implementation of the accelerator APIs. This is
ramping up to the goal of only storing the export representation in the
key slot, and not keeping the crypto implementation-specific representations
around.
Signed-off-by: Steven Cooreman <steven.cooreman@silabs.com>
PSA_ALG_ECB_NO_PADDING came in to the PSA Crypto API spec v1.0.0, but
was not implemented yet in the mbed TLS implementation.
Signed-off-by: Steven Cooreman <steven.cooreman@silabs.com>
Changed PSA core (and PKWrite) from reaching into MPI to using the proper
ecp function to fetch a private key.
Added changelog.
Signed-off-by: Steven Cooreman <steven.cooreman@silabs.com>
Rename PSA_ECC_CURVE_xxx to PSA_ECC_FAMILY_xxx, also rename
PSA_KEY_TYPE_GET_CURVE to PSA_KEY_TYPE_ECC_GET_FAMILY and rename
psa_ecc_curve_t to psa_ecc_family_t. Old defines are provided in
include/crypto_compat.h for backward compatibility.
Signed-off-by: Paul Elliott <paul.elliott@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>
Also normalize the first line of the copyright headers.
This commit was generated using the following script:
# ========================
#!/bin/sh
# Find scripts
find -path './.git' -prune -o '(' -name '*.c' -o -name '*.cpp' -o -name '*.fmt' -o -name '*.h' ')' -print | xargs sed -i '
# Normalize the first line of the copyright headers (no text on the first line of a block comment)
/^\/\*.*Copyright.*Arm/I {
i\
/*
s/^\// /
}
/Copyright.*Arm/I {
# Print copyright declaration
p
# Read the two lines immediately following the copyright declaration
N
N
# Insert Apache header if it is missing
/SPDX/! i\
* SPDX-License-Identifier: Apache-2.0\
*\
* Licensed under the Apache License, Version 2.0 (the "License"); you may\
* not use this file except in compliance with the License.\
* You may obtain a copy of the License at\
*\
* http://www.apache.org/licenses/LICENSE-2.0\
*\
* Unless required by applicable law or agreed to in writing, software\
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\
* See the License for the specific language governing permissions and\
* limitations under the License.
# Clear copyright declaration from buffer
D
}
'
# ========================
Signed-off-by: Bence Szépkúti <bence.szepkuti@arm.com>
On dual world platforms, we want to run the PK module (pk.c) on the NS
side so TLS can use PSA APIs via the PK interface. PK currently has a
hard dependency on mbedtls_ecc_group_to_psa() which is declared in
crypto_extra.h, but only defined in psa_crypto.c, which is only built
for the S side.
Without this change, dual world platforms get error messages like the
following.
[Error] @0,0: L6218E: Undefined symbol mbedtls_ecc_group_to_psa (referred from BUILD/LPC55S69_NS/ARM/mbed-os/features/mbedtls/mbed-crypto/src/pk.o)
Make mbedtls_ecc_group_to_psa() inline within crypto_extra.h so that it
is available to both NS and S world code.
Fixes#3300
Signed-off-by: Darryl Green <darryl.green@arm.com>
Signed-off-by: Jaeden Amero <jaeden.amero@arm.com>
Clear bits in mbedtls_ecc_group_to_psa() to avoid static analyzers and
possibly compilers from warning that bits may be used uninitialized in
certain code paths.
For example, if mbedtls_ecc_group_to_psa() were to be inlined in
crypto_extra.h, the following compiler warning is likely.
In file included from ../include/psa/crypto.h:3774:0,
from ../include/mbedtls/pk.h:49,
from pk.c:29:
pk.c: In function 'mbedtls_pk_wrap_as_opaque':
../include/psa/crypto_struct.h:460:33: error: 'bits' may be used uninitialized in this function [-Werror=maybe-uninitialized]
attributes->core.bits = (psa_key_bits_t) bits;
^~~~~~~~~~~~~~~~~~~~~
pk.c:608:12: note: 'bits' was declared here
size_t bits;
^~~~
Signed-off-by: Jaeden Amero <jaeden.amero@arm.com>
If psa_key_agreement_ecdh fails, there may be output that leaks
sensitive information in the output buffer. Zeroize it.
If this is due to an underlying failure in the ECDH implementation, it
is currently not an issue since both the traditional Mbed TLS/Crypto
implementation and Everest only write to the output buffer once every
intermediate step has succeeded, but zeroizing is more robust. If this
is because the recently added key size check fails, a leak could be a
serious issue.
All key types now have an encoding on 32 bits where the bottom 16 bits
are zero. Change to using 16 bits only.
Keep 32 bits for key types in storage, but move the significant
half-word from the top to the bottom.
Likewise, change EC curve and DH group families from 32 bits out of
which the top 8 and bottom 16 bits are zero, to 8 bits only.
Reorder psa_core_key_attributes_t to avoid padding.
Remove the values of curve encodings that are based on the TLS registry
and include the curve size, keeping only the new encoding that merely
encodes a curve family in 8 bits.
Keep the old constant names as aliases for the new values and
deprecate the old names.
Define constants for ECC curve families and DH group families. These
constants have 0x0000 in the lower 16 bits of the key type.
Support these constants in the implementation and in the PSA metadata
tests.
Switch the slot management and secure element driver HAL tests to the
new curve encodings. This requires SE driver code to become slightly
more clever when figuring out the bit-size of an imported EC key since
it now needs to take the data size into account.
Switch some documentation to the new encodings.
Remove the macro PSA_ECC_CURVE_BITS which can no longer be implemented.
Change the representation of psa_ecc_curve_t and psa_dh_group_t from
the IETF 16-bit encoding to a custom 24-bit encoding where the upper 8
bits represent a curve family and the lower 16 bits are the key size
in bits. Families are based on naming and mathematical similarity,
with sufficiently precise families that no two curves in a family have
the same bit size (for example SECP-R1 and SECP-R2 are two different
families).
As a consequence, the lower 16 bits of a key type value are always
either the key size or 0.
Don't rely on the bit size encoded in the PSA curve identifier, in
preparation for removing that.
For some inputs, the error code on EC key creation changes from
PSA_ERROR_INVALID_ARGUMENT to PSA_ERROR_NOT_SUPPORTED or vice versa.
There will be further such changes in subsequent commits.
If psa_mac_finish_internal fails (which can only happen due to bad
parameters or hardware problem), the error code was converted to
PSA_ERROR_INVALID_SIGNATURE if the uninitialized stack variable
actual_mac happened to contain the expected MAC. This is a minor bug
but it may be possible to leverage it as part of a longer attack path
in some scenarios.
Reported externally. Found by static analysis.
Rename some macros and functions related to signature which are
changing as part of the addition of psa_sign_message and
psa_verify_message.
perl -i -pe '%t = (
PSA_KEY_USAGE_SIGN => PSA_KEY_USAGE_SIGN_HASH,
PSA_KEY_USAGE_VERIFY => PSA_KEY_USAGE_VERIFY_HASH,
PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE => PSA_SIGNATURE_MAX_SIZE,
PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE => PSA_SIGN_OUTPUT_SIZE,
psa_asymmetric_sign => psa_sign_hash,
psa_asymmetric_verify => psa_verify_hash,
); s/\b(@{[join("|", keys %t)]})\b/$t{$1}/ge' $(git ls-files . ':!:**/crypto_compat.h')
When registering a key in a secure element, go through the transaction
mechanism. This makes the code simpler, at the expense of a few extra
storage operations. Given that registering a key is typically very
rare over the lifetime of a device, this is an acceptable loss.
Drivers must now have a p_validate_slot_number method, otherwise
registering a key is not possible. This reduces the risk that due to a
mistake during the integration of a device, an application might claim
a slot in a way that is not supported by the driver.
If none of the inputs to a key derivation is a
PSA_KEY_DERIVATION_INPUT_SECRET passed with
psa_key_derivation_input_key(), forbid
psa_key_derivation_output_key(). It usually doesn't make sense to
derive a key object if the secret isn't itself a proper key.
Allow a direct input as the SECRET input step in a key derivation, in
addition to allowing DERIVE keys. This makes it easier for
applications to run a key derivation where the "secret" input is
obtained from somewhere else. This makes it possible for the "secret"
input to be empty (keys cannot be empty), which some protocols do (for
example the IV derivation in EAP-TLS).
Conversely, allow a RAW_DATA key as the INFO/LABEL/SALT/SEED input to a key
derivation, in addition to allowing direct inputs. This doesn't
improve security, but removes a step when a personalization parameter
is stored in the key store, and allows this personalization parameter
to remain opaque.
Add test cases that explore step/key-type-and-keyhood combinations.
The signature must have exactly the same length as the key, it can't
be longer. Fix#258
If the signature doesn't have the correct size, that's an invalid
signature, not a problem with an output buffer size. Fix the error code.
Add test cases.
In psa_asymmetric_sign, immediately reject an empty signature buffer.
This can never be right.
Add test cases (one RSA and one ECDSA).
Change the SE HAL mock tests not to use an empty signature buffer.
Zero-length keys are rejected at creation time, so we don't need any
special handling internally.
When exporting a key, we do need to take care of the case where the
output buffer is empty, but this is easy: an empty output buffer is
never valid.
At the end of `psa_hmac_setup_internal()`, the ipad is cleared.
However, the size that was given to clear was `key_len` which is larger
than the size of `ipad`.
In psa_import_key, the key bits value was uninitialized before
calling the secure element driver import function. There is a
potential issue if the driver returns PSA_SUCCESS without setting
the key bits. This shouldn't happen, but shouldn't be discounted
either, so we initialize the key bits to an invalid issue.
Adopt a simple method for tracking whether there was a failure: each
fallible operation sets overall_status, unless overall_status is
already non-successful. Thus in case of multiple failures, the
function always reports whatever failed first. This may not always be
the right thing, but it's simple.
This revealed a bug whereby if the only failure was the call to
psa_destroy_se_key(), i.e. if the driver reported a failure or if the
driver lacked support for destroying keys, psa_destroy_key() would
ignore that failure.
For a key in a secure element, if creating a transaction file fails,
don't touch storage, but close the key in memory. This may not be
right, but it's no wronger than it was before. Tracked in
https://github.com/ARMmbed/mbed-crypto/issues/215
When a key slot is wiped, a copy of the key material may remain in
operations. This is undesirable, but does not violate the safety of
the code. Tracked in https://github.com/ARMmbed/mbed-crypto/issues/86
The methods to import and generate a key in a secure element drivers
were written for an earlier version of the application-side interface.
Now that there is a psa_key_attributes_t structure that combines all
key metadata including its lifetime (location), type, size, policy and
extra type-specific data (domain parameters), pass that to drivers
instead of separate arguments for each piece of metadata. This makes
the interface less cluttered.
Update parameter names and descriptions to follow general conventions.
Document the public-key output on key generation more precisely.
Explain that it is optional in a driver, and when a driver would
implement it. Declare that it is optional in the core, too (which
means that a crypto core might not support drivers for secure elements
that do need this feature).
Update the implementation and the tests accordingly.
Register an existing key in a secure element.
Minimal implementation that doesn't call any driver method and just
lets the application declare whatever it wants.
Pass the key creation method (import/generate/derive/copy) to the
driver methods to allocate or validate a slot number. This allows
drivers to enforce policies such as "this key slot can only be used
for keys generated inside the secure element".
Let psa_start_key_creation know what type of key creation this is. This
will be used at least for key registration in a secure element, which
is a peculiar kind of creation since it uses existing key material.
Allow the application to choose the slot number in a secure element,
rather than always letting the driver choose.
With this commit, any application may request any slot. In an
implementation with isolation, it's up to the service to filter key
creation requests and apply policies to limit which applications can
request which slot.
This function no longer modifies anything, so it doesn't actually
allocate the slot. Now, it just returns the empty key slot, and it's
up to the caller to cause the slot to be in use (or not).
Add a slot_number field to psa_key_attributes_t and getter/setter
functions. Since slot numbers can have the value 0, indicate the
presence of the field via a separate flag.
In psa_get_key_attributes(), report the slot number if the key is in a
secure element.
When creating a key, for now, applications cannot choose a slot
number. A subsequent commit will add this capability in the secure
element HAL.
Add infrastructure for internal, external and dual-use flags, with a
compile-time check (if static_assert is available) to ensure that the
same numerical value doesn't get declared for two different purposes
in crypto_struct.h (external or dual-use) and
psa_crypto_core.h (internal).
mbedtls_ctr_drbg_random can only return up to
MBEDTLS_CTR_DRBG_MAX_REQUEST (normally 1024) bytes at a time. So if
more than that is requested, call mbedtls_ctr_drbg_random in a loop.
When psa_generate_random fails, psa_generate_key_internal frees the
key buffer but a the pointer to the now-freed buffer in the slot. Then
psa_generate_key calls psa_fail_key_creation which sees the pointer
and calls free() again.
This bug was introduced by ff5f0e7221
"Implement atomic-creation psa_{generate,generator_import}_key" which
changed how psa_generate_key() cleans up on errors. I went through the
code and could not find a similar bug in cleanup on an error during
key creation.
Fix#207
Conflict resolution:
* `scripts/config.pl`:
Take the exclusion of `MBEDTLS_PSA_CRYPTO_SE_C` from the API branch.
Take the removal of `MBEDTLS_PSA_CRYPTO_STORAGE_ITS_C` (obsolete) from
the development branch.
* `tests/scripts/all.sh`:
Multiple instances of factoring a sequence of `config.pl` calls into
a mere `config.pl baremetal` in the development branch, and a change in
the composition of `baremetal` in the API branch. In each case, take the
version from development.
* `tests/suites/test_suite_psa_crypto_slot_management.function`:
A function became non-static in development and disappeared in the API
branch. Keep the version from the API branch. Functions need to be
non-static if they're defined but unused in some configurations,
which is not the case for any function in this file at the moment.
* `tests/suites/test_suite_psa_crypto.function`:
Consecutive changes in the two branches, reconciled.
The flag to mark key slots as allocated was introduced to mark slots
that are claimed and in use, but do not have key material yet, at a
time when creating a key used several API functions: allocate a slot,
then progressively set its metadata, and finally create the key
material. Now that all of these steps are combined into a single
API function call, the notion of allocated-but-not-filled slot is no
longer relevant. So remove the corresponding flag.
A slot is occupied iff there is a key in it. (For a key in a secure
element, the key material is not present, but the slot contains the
key metadata.) This key must have a type which is nonzero, so use this
as an indicator that a slot is in use.
There is now a field for the key size in the key slot in memory. Use
it.
This makes psa_get_key_attributes() marginally faster at the expense
of memory that is available anyway in the current memory layout (16
bits for the size, 16 bits for flags). That's not the goal, though:
the goal is to simplify the code, in particular to make it more
uniform between transparent keys (whose size can be recomputed) and
keys in secure elements (whose size cannot be recomputed).
For keys in a secure element, the bit size is now saved by serializing
the type psa_key_bits_t (which is an alias for uint16_t) rather than
size_t.
Change the type of key slots in memory to use
psa_core_key_attributes_t rather than separate fields. The goal is to
simplify some parts of the code. This commit only does the mechanical
replacement, not the substitution.
The bit-field `allocate` is now a flag `PSA_KEY_SLOT_FLAG_ALLOCATED`
in the `flags` field.
Write accessor functions for flags.
Key slots now contain a bit size field which is currently unused.
Subsequent commits will make use of it.