Previously, this wasn't necessary because ecdh.h was included
through ssl.h, but now that this is no longer the case (because
ssl.h doesn't use ECDH), we have to include it explicitly.
Previously, ecp.h was included only if MBEDTLS_ECDH_C was set,
which broke the build in configurations using ECDSA, but not ECDH.
An example of such a config is configs/config-thread.h, which
uses ECJPAKE exclusively.
Moreover, the inclusion of ecdh.h isn't needed, because the header
only uses constants defined in the ECP module.
There is no apparent direct dependency, and the indirect dependency
through the RSA and legacy ECP modules is already encoded in the
chain
MBEDTLS_X509_USE_C
-> MBEDTLS_PK_PARSE_C
-> MBEDTLS_PK_C
-> MBEDTLS_RSA_C || MBEDTLS_ECP_C
-> MBEDTLS_BIGNUM_C
which will be modified to
MBEDTLS_X509_USE_C
-> MBEDTLS_PK_PARSE_C
-> MBEDTLS_PK_C
-> MBEDTLS_RSA_C || MBEDTLS_ECP_C || MBEDTLS_USE_TINYCRYPT
in which case MBEDTLS_BIGNUM_C is not needed for MBEDTLS_X509_USE_C
if only MBEDTLS_USE_TINYCRYPT is set, but not MBEDTLS_RSA_C or
MBEDTLS_ECP_C.
asn1.h uses uint8_t which is defined in stdint.h.
This wasn't caught earlier by the luck that whenever asn1.h
was included, another header was included earlier that did in
turn include stdint.h.
Remark: Including ecp.h is actually redundant because it's
also included from ecdh.h. However, it's good practice to
explicitly include header files that are being used directly,
and ssl.h does use MBEDTLS_ECP_MAX_BYTES which is defined in ecp.h.
ssl.h contains a dummy union of fields each large enough to
hold the PMS for a particular ciphersuite. In particular, for
pure-ECDH ciphersuites, it contains a field large enough to
hold the ECDH shared secret in any of the enabled curves.
So far, this upper bound was unconditionally chosen to be
MBEDTLS_ECP_MAX_BYTES from the ECP module.
With the introduction of TinyCrypt as an alternative implementation
for ECDH, we need to
- guard the use of MBEDTLS_ECP_MAX_BYTES because MBEDTLS_ECP_C
is no longer implied by the surrounding MBEDTLS_KEY_EXCHANGE_XXX
guards
- add another field which contains the maximum length of shared
ECDH secrets for curves supported by TinyCrypt.
mbedtls/ecp.h defines constants
MBEDTLS_ECP_PF_UNCOMPRESSED
MBEDTLS_ECP_PF_COMPRESSED
MBEDTLS_ECP_TLS_NAMED_CURVE
which regard the encoding of elliptic curves and curve point formats in TLS.
As such, they should be defined in the SSL namespace. Asides, this will help
replacing the legacy ECC crypto by alternative ECC implementations.
The PK-type MBEDTLS_PK_ECDSA isn't really used by the library.
Especially, when parsing a generic EC key, a PK context of type
MBEDTLS_PK_ECKEY will be requested. Hence, to drop in TinyCrypt
for the legacy-ECC implementation, the PK type that TinyCrypt
implements must be MBEDTLS_PK_ECKEY.
TinyCrypt should be used as a replacement of legacy ECC. In particular,
there shouldn't be any use of identifiers from the legacy ECC module.
So far, there's the configuration option
MBEDTLS_SSL_CONF_SINGLE_EC_GRP_ID
that's relevant if MBEDTLS_SSL_CONF_SINGLE_CURVE is set, and which in
this case must resolve to an identifier of type mbedtls_ecp_group_id
indicating which single curve to enable.
With the introduction of TinyCrypt, we must either change the type
of this option to mbedtls_uecc_group_id, or introduce a separate
compilation option.
In order to avoid type confusion, this commit follows tha latter
approach, introducing the configuration option
MBEDTLS_SSL_CONF_SINGLE_UECC_GRP_ID
that indicatesthe TinyCrypt group identifier of the single curve
to use (must be Secp256r1) if MBEDTLS_SSL_CONF_SINGLE_CURVE
and MBEDTLS_USE_TINYCRYPT are set.
* mbedtls-2.16: (21 commits)
Exclude DTLS 1.2 only with older OpenSSL
Document the rationale for the armel build
Switch armel build to -Os
Add a build on ARMv5TE in ARM mode
Add changelog entry for ARM assembly fix
bn_mul.h: require at least ARMv6 to enable the ARM DSP code
Changelog entry for test certificates update
Change worktree_rev to HEAD for rev-parse
Add ChangeLog entry for entropy_nv_seed test case fix
entropy_nv_seed: cope with SHA-256
entropy_nv_seed: clean up properly
Add ChangeLog entry for undefined behavior fix in test_suite_nist_kw
Don't call memset after calloc
Adapt ChangeLog
ECP restart: Don't calculate address of sub ctx if ctx is NULL
Update certificates to expire in 2029
Update soon to be expired crl
Test that a shared library build produces a dynamically linked executable
Test that the shared library build with CMake works
Add a test of MBEDTLS_CONFIG_FILE
...
Usually, compilers are clever enough to pick the best inlining
strategy, but in this instance, it appears that compiling on ARMC6,
the compilers inlines xxx_prf_yyy() and xxx_calc_finished_yyy()
even though it really shouldn't. Forbid inlining through the use
of __attribute__((noinline)).
This saves a few bytes in configurations where only one hash
is enabled, and configurations allowing multiple hashes probably
don't care about code-size anyway.
Now function mbedtls_ssl_set_hostname is compile-time configurable
in config.h with define MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION.
This affects to many x509 API's. See config.h for details.
tinyCrypt uses a global RNG without context parameter while Mbed TLS in its
default configuration uses RNG+CTX bound to the SSL configuration.
This commit restricts the use of tinyCrypt to configurations that use a
global RNG function with NULL context by setting MBEDTLS_SSL_CONF_RNG in
the configuration. This allows to define a wrapper RNG to be used by
tinyCrypt which maps to this global hardcoded RNG.
Previously, ssl_ecrs_ske_start_processing was used to indicate that
the ServerKeyExchange has been fetched from the record layer, but
that parsing its ECDHE parameter component has been preempted by the
restartable ECP feature. On re-entry of ssl_parse_server_key_exchange()
in this state, the code would directly jump into the parsing routine.
However, the only non-reentrant code that's jumped over this way is
the record fetching routine mbedtls_ssl_parse_record(), which is now
made re-entrant by setting `ssl->keep_current_message = 1` in case of
pre-emption due to restartable ECC.
The ssl_ecrs_ske_start_processing state is therefore redundant and
can be removed, which is what this commit does.
The postprocessing code for the server-side incoming client key
exchange and the client-side outgoing client key exchange both
contain the same code-paths for building the premaster secret
depending on the chosen ciphersuite (e.g., for ECDHE-PSK,
concatenating the ECDHE secret with the chosen PSK).
This commit moves this common code to ssl_tls.c, allowing
client- and server-side to share it.
After and performing key generation operations,
the client-side outgoing ClientKeyExchange handling includes
code-paths to assembly the PreMasterSecret (PMS) from the
available keying material, the exact assembly procedure
depending on which ciphersuite is in use. E.g., in an
(EC)DHE-PSK ciphersuite, the (EC)DHE secret would be concatenated
with the PSK to form the PMS.
This assembly of the PMS logically can be done after the ClientKeyExchange
has been written and the respective keying material has been generated,
and this commit moves it to the new postprocessing function
ssl_client_key_exchange_postprocess().
Ideally, the PMS assembly could be done prior to writing the
ClientKeyExchange message, but the (EC)DHE API does currently
not allow splitting secret-generation and secret-export; as
long as that's the case, we to generation and exporting in the
message writing function, forcing PMS assembly to be done in
the postprocessing.
This commit adds declarations and dummy implementations for
the restructured outgoing client key exchange handling that
will replace the previous ssl_write_client_key_exchange().
The entry point for the CliKeyExchange handling that is called
from the handshake state machine is
`ssl_process_client_key_exchange()`,
splitting the processing into the following steps:
- Preparation
Compute the keying material to be sent.
* For (EC)DH: Pick parameters and compute PMS.
* For ECJPAKE: Run round 2
* For RSA: Encrypt PMS
- Writing: Prepare the writing of a new messae.
- Postprocessing: Update handstate state machine.
The subsequent commits will scatter the code from the previous
monolithic function ssl_write_client_key_exchange() among those
dedicated functions, commenting out each part of
ssl_write_client_key_exchange() that has already been dealt with.
This gradual progression is meant to ease reviewing. Once all
code has been moved and all changes explained,
ssl_write_client_key_exchange() will be removed.
Commit 16b1bd8932 "bn_mul.h: add ARM DSP optimized MULADDC code"
added some ARM DSP instructions that was assumed to always be available
when __ARM_FEATURE_DSP is defined to 1. Unfortunately it appears that
the ARMv5TE architecture (GCC flag -march=armv5te) supports the DSP
instructions, but only in Thumb mode and not in ARM mode, despite
defining __ARM_FEATURE_DSP in both cases.
This patch fixes the build issue by requiring at least ARMv6 in addition
to the DSP feature.
After the rewrite of incoming record processing to use the internal
SSL record structure mbedtls_record (which contains the data_offset
field to indicate where the IV resides), this field is no longer
necessary.
Note: This is an API break.
The function mbedtls_ssl_in_hdr_len() is supposed to return the length
of the record header of the current incoming record. With the advent
of the DTLS Connection ID, this length is only known at runtime and
hence so far needed to be derived from the internal in_iv pointer
pointing to the beginning of the payload of the current incooing
record.
By now, however, those uses of mbedtls_ssl_in_hdr_len() where the
presence of a CID would need to be detected have been removed
(specifically, ssl_parse_record_header() doesn't use it anymore
when checking that the current datagram is large enough to hold
the record header, including the CID), and it's sufficient to
statically return the default record header sizes of 5 / 13 Bytes
for TLS / DTLS.
This function is often called when there's already an error code to handle,
and one of the reasons to introduce the pending of alerts was to _not_ have
another potential error code to take care of. Reflect this by making `void`
the return type of `mbedtls_ssl_pend_fatal_alert()`.
The code wants timer callbacks to be set (checked in fetch_input()), and can't
easily check whether we're using nbio, so it seems easier to require the
callbacks to be always set rather than only with nbio as was previously done.
The number of meaning of the flags will be determined later, when handling the
relevant struct members. For now three bytes are reserved as an example, but
this number may change later.
Enforce restrictions indicated in the documentation.
This allows to make some simplifying assumptions (no need to worry about
saving IVs for CBC in TLS < 1.1, nor about saving handshake data) and
guarantees that all values marked as "forced" in the design document have the
intended values and can be skipped when serialising.
Some of the "forced" values are not checked because their value is a
consequence of other checks (for example, session_negotiated == NULL outside
handshakes). We do however check that session and transform are not NULL (even
if that's also a consequence of the initial handshake being over) as we're
going to dereference them and static analyzers may appreciate the info.
This commit introduces the option MBEDTLS_SSL_CONF_SINGLE_HASH
which can be used to register a single supported signature hash
algorithm at compile time. It replaces the runtime configuration
API mbedtls_ssl_conf_sig_hashes() which allows to register a _list_
of supported signature hash algorithms.
In contrast to other options used to hardcode configuration options,
MBEDTLS_SSL_CONF_SINGLE_HASH isn't a numeric option, but instead it's
only relevant if it's defined or not. To actually set the single
supported hash algorithm that should be supported, numeric options
MBEDTLS_SSL_CONF_SINGLE_HASH_TLS_ID
MBEDTLS_SSL_CONF_SINGLE_HASH_MD_ID
must both be defined and provide the TLS ID and the Mbed TLS internal
ID and the chosen hash algorithm, respectively.
This commit introduces the option MBEDTLS_SSL_CONF_SINGLE_EC
which can be used to register a single supported elliptic curve
at compile time. It replaces the runtime configuration API
mbedtls_ssl_conf_curves() which allows to register a _list_
of supported elliptic curves.
In contrast to other options used to hardcode configuration options,
MBEDTLS_SSL_CONF_SINGLE_EC isn't a numeric option, but instead it's
only relevant if it's defined or not. To actually set the single
elliptic curve that should be supported, numeric options
MBEDTLS_SSL_CONF_SINGLE_EC_TLS_ID
MBEDTLS_SSL_CONF_SINGLE_EC_GRP_ID
must both be defined and provide the TLS ID and the Mbed TLS internal
ID and the chosen curve, respectively.
The fields
- mbedtls_ssl_handshake_params::max_major_ver,
- mbedtls_ssl_handshake_params::max_minor_ver
are used only for server-side RSA-based key exchanges
can be removed otherwise.
Reasons:
- If the transport type is fixed at compile-time,
mbedtls_ssl_read_version() and mbedtls_ssl_write_version()
are called with a compile-time determined `transport`
parameter, so the transport-type branch in their body
can be eliminated at compile-time.
- mbedtls_ssl_read_version() is called with addresses of
local variables, which so far need to be put on the stack
to be addressable. Inlining the call allows to read directly
into the registers holding these local variables.
This saves 60 bytes w.r.t. the measurement performed by
> ./scripts/baremetal.sh --rom --gcc
If the minor/major version is enforced at compile-time, the `major_ver`
and `minor_ver` fields in `mbedtls_ssl_context` are redundant and can
be removed.
This commit introduces the numeric compile-time constants
- MBEDTLS_SSL_CONF_MIN_MINOR_VER
- MBEDTLS_SSL_CONF_MAX_MINOR_VER
- MBEDTLS_SSL_CONF_MIN_MAJOR_VER
- MBEDTLS_SSL_CONF_MAX_MAJOR_VER
which, when defined, overwrite the runtime configurable fields
mbedtls_ssl_config::min_major_ver etc. in the SSL configuration.
As for the preceding case of the ExtendedMasterSecret configuration,
it also introduces and puts to use getter functions for these variables
which evaluate to either a field access or the macro value, maintaining
readability of the code.
The runtime configuration API mbedtls_ssl_conf_{min|max}_version()
is kept for now but has no effect if MBEDTLS_SSL_CONF_XXX are set.
This is likely to be changed in a later commit but deliberately omitted
for now, in order to be able to study code-size benefits earlier in the
process.
This commit restructures ssl_ciphersuites.h and ssl_ciphersuites.c to
define all ciphersuite helper functions static inline in ssl_ciphersuites.h
if MBEDTLS_SSL_CONF_SINGLE_CIPHERSUITE is set, and to otherwise put their
definitions in ssl_ciphersuites.c.
If MBEDTLS_SSL_SINGLE_CIPHERSUITE is enabled, the type
mbedtls_ssl_ciphersuite_handle_t
is logically a boolean (concretely realized as `unsigned char`),
containing the invalid handle and the unique valid handle, which
represents the single enabled ciphersuite.
The SSL session structure mbedtls_ssl_session contains an instance
of mbedtls_ssl_ciphersuite_handle_t which is guaranteed to be valid,
and which is hence redundant in any two-valued implementation of
mbedtls_ssl_ciphersuite_handle_t.
This commit replaces read-uses of
mbedtls_ssl_session::ciphersuite_info
by a getter functions which, and defines this getter function
either by just reading the field from the session structure
(in case MBEDTLS_SSL_SINGLE_CIPHERSUITE is disabled), or by
returning the single valid ciphersuite handle (in case
MBEDTLS_SSL_SINGLE_CIPHERSUITE is enabled) and removing the
field from mbedtls_ssl_session in this case.
If MBEDTLS_SSL_SINGLE_CIPHERSUITE is enabled, it overwrites
the runtime configuration of supported ciphersuites, which
includes both the configuration API and the fields which are
used to store the configuration. Both are therefore no longer
needed and should be removed for the benefit of code-size,
memory usage, and API clarity (no accidental hiccup of runtime
vs. compile-time configuration possible).
The configuration API mbedtls_ssl_conf_ciphersuites() has
already been removed in case MBEDTLS_SSL_SINGLE_CIPHERSUITE,
and this commit removes the field
mbedtls_ssl_config::ciphersuite_list
which it updates.
If MBEDTLS_SSL_SINGLE_CIPHERSUITE is enabled, the type
mbedtls_ssl_ciphersuite_handle_t
is logically a boolean (concretely realized as `unsigned char`),
containing the invalid handle and the unique valid handle, which
represents the single enabled ciphersuite.
The SSL handshake structure mbedtls_ssl_handshake_params contains
an instance of mbedtls_ssl_ciphersuite_handle_t which is guaranteed
to be valid, and which is hence redundant in any two-valued
implementation of mbedtls_ssl_ciphersuite_handle_t.
This commit replaces read-uses of
mbedtls_ssl_handshake_params::ciphersuite_info
by a getter functions which, and defines this getter function
either by just reading the field from the handshake structure
(in case MBEDTLS_SSL_SINGLE_CIPHERSUITE is disabled), or by
returning the single valid ciphersuite handle (in case
MBEDTLS_SSL_SINGLE_CIPHERSUITE is enabled) and removing the
field from mbedtls_ssl_handshake_params in this case.
This commit modifies the ClientHello writing routine ssl_write_client_hello
in ssl_cli.c to switch between
(a) listing all runtime configured ciphersuites
(in case MBEDTLS_SSL_SINGLE_CIPHERSUITE is not defined)
(b) listing just the single hardcoded ciphersuite
(in case MBEDTLS_SSL_SINGLE_CIPHERSUITE is defined)
The approach taken is to introduce a pair of helper macros
MBEDTLS_SSL_BEGIN_FOR_EACH_CIPHERSUITE( ssl, ver, info )
MBEDTLS_SSL_END_FOR_EACH_CIPHERSUITE
which when delimiting a block of code lead to that block of
code being run once for each ciphersuite that's enabled in the
context `ssl` and version `ver`, referenced through the (fresh)
`info` variable. Internally, this is implemented either through
a plain `for` loop traversing the runtime configured ciphersuite
list (if MBEDTLS_SSL_SINGLE_CIPHERSUITE is disabled) or by just
hardcoding `info` to the single enabled ciphersuite (if
MBEDTLS_SSL_SINGLE_CIPHERSUITE is enabled).
These helper macros will prove useful whereever previous code
traversed the runtime configured ciphersuite list, but adaptations
of those occasions outside ClientHello writing are left for later
commits.
This commit is a step towards the goal of allowing to hardcode the choice
of a single ciphersuite at compile-time. The hoped for benefit of this is
that whereever a ciphersuite attribute is queried and checked against a
compile-time constant, the check can be recognized as either true or false
at compile-time, hence leading to a code-size reduction.
For this to work, the ciphersuite attribute getter functions
mbedtls_ssl_suite_get_xxx() will be modified to return something
the compiler can recognize as a compile-time constant. In particular,
in order to avoid relying on constant propagation abilities of the
compiler, these functions should ideally return constant symbols
(instead of, say, fields in a globally const structure instance).
This puts us in the following situation: On the one hand, there's the
array of ciphersuite information structures defining the attribute of
those ciphersuites the stack knows about. On the other hand, we need
direct access to those fields through constant symbols in the getter
functions.
In order to avoid any duplication of information, this commit exemplifies
how ciphersuites can be conveniently defined on the basis of macro
definitions, and how the corresponding instances of the ciphersuite
information structure can be auto-generated from this.
In the approach, to add support for a ciphersuite with official name
NAME (such as TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8), the following macro
constants need to be defined in ssl_ciphersuites.h:
MBEDTLS_SUITE__ NAME __ID
MBEDTLS_SUITE__ NAME __NAME
MBEDTLS_SUITE__ NAME __CIPHER
MBEDTLS_SUITE__ NAME __MAC
...
To make check-names.sh happy, one also needs a dummy macro
MBEDTLS_SUITE__ NAME()
These ciphersuite attribute values can then be queried via
MBEDTLS_SSL_SUITE_ID( NAME_MACRO )
...
where NAME_MACRO can be any macro expanding to a defined NAME.
Further, a convenience macro
MBEDTLS_SSL_SUITE_INFO( NAME_MACRO )
is provided that again takes a macro NAME_MACRO expanding to a
defined NAME, and itself expands to an instance of
mbedtls_ssl_ciphersuite_info_t using the macro attributes
defined for NAME. This macro is then used in ssl_ciphersuites.c
when defining the array of known ciphersuite information structures,
(a) without duplicating the information, and (b) with increased
readability, because there's only one line for each ciphersuite.
This commit introduces an internal zero-cost abstraction layer for
SSL ciphersuites: Instead of addressing ciphersuites via pointers
to instances of mbedtls_ssl_ciphersuite_t and accessing their fields
directly, this commit introduces an opaque type
mbedtls_ssl_ciphersuite_handle_t,
and getter functions
mbedtls_ssl_suite_get_xxx()
operating on ciphersuite handles.
The role of NULL is played by a new macro constant
MBEDTLS_SSL_CIPHERSUITE_INVALID_HANDLE
which results of functions returning handles can be checked against.
(For example, when doing a lookup of a ciphersuite from a peer-provided
ciphersuite ID in the per's Hello message).
The getter functions have the validity of the handle as a precondition
and are undefined if the handle is invalid.
So far, there's only one implementation of this abstraction layer, namely
mbedtls_ssl_ciphersuite_handle_t being mbedtls_ssl_ciphersuite_t const *
and
getter functions being field accesses.
In subsequent commits, however, the abstraction layer will be useful
to save code in the situation where only a single ciphersuite is enabled.
Previously, ssl.h included ssl_ciphersuites.h to have access to the
helper macros MBEDTLS_KEY_EXCHANGE_XXX_ENABLED, and for no other
reason. This commit moves the definitions of these macros to ssl.h,
thereby removing the dependency of ssl.h on ssl_ciphersuites.h.
So far, the client-proposed list of elliptic curves was stored for the
duration of the entire handshake in a heap-allocated buffer referenced
from mbedtls_ssl_handshake_params::curves. It is used in the following
places:
1) When the server chooses a suitable ciphersuite, it checks that
it has a certificate matching the ciphersuite; in particular, if
the ciphersuite involves ECDHE, the server needs an EC certificate
with a curve suitable for the client.
2) When performing the ECDHE key exchange, the server choose one
curve among those proposed by the client which matches the server's
own supported curve configuration.
This commit removes the hold back the entire client-side curve list
during the handshake, by performing (1) and (2) on during ClientHello
parsing, and in case of (2) only remembering the curve chosen for ECDHE
within mbedtls_ssl_handshake_params.