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.
IAR doesn't like `((void) var);` as a means to indicate an unused
variable if that variable hasn't been initialized before. Make it
happy by initializing the variable before.
ssl_server_key_exchange_parse() is compiled even if there's no ciphersuite
enabled which uses it (for example, that's the case in RSA-only builds).
The rationale for that is to avoid cluttering the code with numerous
compile-time guards. A consequence, however, is the top of
ssl_server_key_exchange_parse() contains declarations for variables
which are never put to use, and rightfully leading to compiler warnings.
This commit silences these warnings by putting `((void) VAR);` statements
in the branch which detects if we ever happen to call the function in an
unexpected ciphersuite.
In the PSK and RSA-PSK ciphersuites, the ServerKeyExchange message
MAY be skipped. This commit moves the code-path peeking at the
incoming message to decide whether it's probably a ServerKeyExchange
to the new coordination function ssl_server_key_exchange_coordinate().
This commit moves the code checking whether a SrvKeyExchange message
is expected or not to the new function ssl_srv_key_exchange_coordinate().
Note that the potential static DH extraction is done prior to the
coordination step.
This code moves the code-path that extracts static DH parameters
from the server's CRT (if applicable) to the new function
ssl_server_key_exchange_prepare().
This commit adds declarations and dummy implementations for
the restructured incoming server key exchange handling that
will replace the previous ssl_parse_server_key_exchange().
The entry point for the SrvKeyExchange handling that is called
from the handshake state machine is
`ssl_process_server_key_exchange()`,
splitting the processing into the following steps:
- Preparation: For a static DH key exchange, extract
DH parameters from the server's CRT.
- Coordination: Check if a SrvKeyExchange message is expected
(e.g., it isn't for a RSA-based key exchange)
- Reading: Fetch and check content and handshake type
of incoming message.
- Parsing: Parse and store the ServerKeyExchange message.
- Postprocessing: Update handstate state machine.
The subsequent commits will scatter the code from the previous
monolithic function ssl_parse_server_key_exchange() among those
dedicated functions, commenting out each part of
ssl_parse_server_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_parse_server_key_exchange() will be removed.
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.
The code from the previous function ssl_parse_client_key_exchange()
has been entirely moved to one of the newly introduced subroutines
and is no longer needed. This commit removes it.
After parsing and performing key generation operations,
the server-side incoming 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 comes done after the ClientKeyExchange
has been parsed and the respective keying material has been generated,
and this commit moves it to the new postprocessing function
ssl_client_key_exchange_postprocess().
This commit moves the generation of the master secret and session keys
from the premaster secret (done in mbedtlsssl_derive_keys()) from the
previous ClientKeyExchange parsing function ssl_parse_client_key_exchange()
to the new postprocessing function ssl_client_key_exchange_postprocess().
This commit adds declarations and dummy implementations for
the restructured incoming client key exchange handling that
will replace the previous ssl_parse_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:
- Fetching: Read next message from the messaging layer
and check that it has the correct type.
The ClientKeyExchange message is never
omitted, so there is no ambiguity in what
to expect, and hence no dedicated preparation
step as for other handshake states.
- Parsing: Parse the ClientKeyExchange message and
use the information in it to derive keying
material such as the shared (EC)DHE secret.
- Postprocessing:
Compute the session keys from the available
keying material. This splits in two steps:
(1) Build the PreMasterSecret (PMS) from the
available keying material, e.g. concatenate
the (EC)DHE secret with a PSK, if used.
(2) Extract the MasterSecret and Session Keys
from the PreMasterSecret.
The subsequent commits will scatter the code from the previous
monolithic function ssl_parse_client_key_exchange() among those
dedicated functions, commenting out each part of
ssl_parse_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_parse_client_key_exchange() will be removed.
The code from the previous function ssl_write_client_key_exchange()
has been entirely moved to one of the newly introduced subroutines
and is no longer needed. This commit removes it.
This commit moves the code responsible for
(a) generating the client's private and public (EC)DHE keys
(b) writing it to the message buffer
to the new writing function ssl_client_key_exchange_write().
As mentioned in the previous commit message, (a) and (b) are
currently inseparable at the (EC)DHE API level, which is why
(a) can't be moved to the preparation step.
For RSA or RSA-PSK exchanges, the PMS contains 46 random bytes
picked by the client. These bytes are generated prior to the
writing of the ClientKeyExchange message.
This commit splits the previous function ssl_write_encrypted_pms() into
PPMS-GEN: ssl_rsa_generate_partial_pms()
PPMS-ENC: ssl_rsa_encrypt_partial_pms().
The prefix 'partial' is meant to emphasize that the generation of the PMS
is not always entirely done by these functions: For RSA-PSK e.g., the
PSK still needs to be added.
The two calls of ssl_write_encrypted_pms() in
ssl_write_client_key_exchange() will split in calls of the functions
PPMS-GEN and PPMS-ENC each, with PPMS-GEN being moved to the new
preparation function ssl_client_key_exchange_prepare() in this commit,
and PPMS-ENC being moved to ssl_client_key_exchange_write() in the
next commit.
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.
* mbedtls-2.16:
Fix parsing issue when int parameter is in base 16
Refactor receive_uint32()
Refactor get_byte function
Make the script portable to both pythons
Update the test encoding to support python3
update the test script
tests: Limit each log to 10 GiB
It happens regularly in test runs that the server example application
shuts down a connection, goes into waiting mode for a new connection,
and then receives the encrypted ClosureAlert from the client. The only
reason why this does currently not trigger the 'record from another epoch'
message is that we handle ClientHello parsing outside of the main record
stack because we want to be able to detect SSLv2 ClientHellos. However,
this is likely to go away, and once it happens, we'll see the log message.
Further, when record checking is used, every record, including the mentioned
closure alert, is passed to the record checking API before being passed to
the rest of the stack, which leads to the log message being printed.
In summary, grepping for 'record from another epoch' is a fragile way
of checking whether a reordered message has arrived. A more reliable
way is to grep for 'Buffer record from epoch' which is printed when
a record from a future epoch is actually buffered, and 'ssl_buffer_message'
which is the function buffering a future handshake message.
This commit implements the record checking API
mbedtls_ssl_check_record()
on top of the restructured incoming record stack.
Specifically, it makes use of the fact that the core processing routines
ssl_parse_record_header()
mbedtls_ssl_decrypt_buf()
now operate on instances of the SSL record structure mbedtls_record
instead of the previous mbedtls_ssl_context::in_xxx fields.
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.
ssl_get_next_record() updates the legacy in_xxx fields in two places,
once before record decryption and once after. Now that record decryption
doesn't use or affect the in_xxx fields anymore, setting up the these
legacy fields can entirely be moved to the end of ssl_get_next_record(),
which is what this comit does.
This commit solely moves existing code, but doesn't yet simplify the
now partially redundant settings of the in_xxx fields. This will be
done in a separate commit.
Multiple record attributes such as content type and payload length
may change during record decryption, and the legacy in_xxx fields
in the SSL context therefore need to be updated after the record
decryption routine ssl_decrypt_buf() has been called.
After the previous commit has made ssl_prepare_record_content()
independent of the in_xxx fields, setting them can be moved
outside of ssl_prepare_record_content(), which is what this
commit does.
Previously, ssl_update_in_pointers() ensured that the in_xxx pointers
in the SSL context are set to their default state so that the record
header parsing function ssl_parse_record_header() could make use of them.
By now, the latter is independent of these pointers, so they don't need
to be setup before calling ssl_parse_record_header() anymore.
However, other parts of the messaging stack might still depend on it
(to be studied), and hence this commit does not yet reomve
ssl_update_in_pointers() entirely.