Commit Graph

1249 Commits

Author SHA1 Message Date
Manuel Pégourié-Gonnard
a3d831b9e6 Add test for session_load() from small buffers
This uncovered a bug that led to a double-free (in practice, in general could
be free() on any invalid value): initially the session structure is loaded
with `memcpy()` which copies the previous values of pointers peer_cert and
ticket to heap-allocated buffers (or any other value if the input is
attacker-controlled). Now if we exit before we got a chance to replace those
invalid values with valid ones (for example because the input buffer is too
small, or because the second malloc() failed), then the next call to
session_free() is going to call free() on invalid pointers.

This bug is fixed in this commit by always setting the pointers to NULL right
after they've been read from the serialised state, so that the invalid values
can never be used.

(An alternative would be to NULL-ify them when writing, which was rejected
mostly because we need to do it when reading anyway (as the consequences of
free(invalid) are too severe to take any risk), so doing it when writing as
well is redundant and a waste of code size.)

Also, while thinking about what happens in case of errors, it became apparent
to me that it was bad practice to leave the session structure in an
half-initialised state and rely on the caller to call session_free(), so this
commit also ensures we always clear the structure when loading failed.
2019-08-23 12:48:41 +03:00
Manuel Pégourié-Gonnard
26f982f50e Improve save API by always updating olen
This allows callers to discover what an appropriate size is. Otherwise they'd
have to either try repeatedly, or allocate an overly large buffer (or some
combination of those).

Adapt documentation an example usage in ssl_client2.
2019-08-23 12:48:41 +03:00
Manuel Pégourié-Gonnard
b5e4e0a395 Add mbedtls_ssl_get_session_pointer()
Avoid useless copy with mbedtls_ssl_get_session() before serialising.

Used in ssl_client2 for testing and demonstrating usage, but unfortunately
that means mbedtls_ssl_get_session() is no longer tested, which will be fixed
in the next commit.
2019-08-23 12:48:41 +03:00
Manuel Pégourié-Gonnard
35eb802103 Add support for serialisation session with ticket
On client side, this is required for the main use case where of serialising a
session for later resumption, in case tickets are used.

On server side, this doesn't change much as ticket_len will always be 0.

This unblocks testing the functions by using them in ssl_client2, which will
be done in the next commit.
2019-08-23 12:48:41 +03:00
Manuel Pégourié-Gonnard
a3e7c65101 Move session save/load function to ssl_tls.c
This finishes making these functions public. Next step is to get them tested,
but there's currently a blocker for that, see next commit (and the commit
after it for tests).
2019-08-23 12:48:41 +03:00
Manuel Pégourié-Gonnard
8faa70e810 Use more specific name in debug message for testing
While 'session hash' is currently unique, so suitable to prove that the
intended code path has been taken, it's a generic enough phrase that in the
future we might add other debug messages containing it in completely unrelated
code paths. In order to future-proof the accuracy of the test, let's use a
more specific string.
2019-08-23 12:45:33 +03:00
Manuel Pégourié-Gonnard
d91efa47c0 Fix alignment issues 2019-08-23 12:45:33 +03:00
Manuel Pégourié-Gonnard
47e33e11f7 Clarify comment about TLS versions
The previous comment used "TLS" as a shortcut for "TLS 1.0/1.1" which was
confusing. This partially reflected the names of the calc_verify/finished that
go ssl, tls (for 1.0/1.1) tls_shaxxx (for 1.2), but still it's clearer to be
explicit in the comment - and perhaps in the long term the function names
could be clarified instead.
2019-08-23 12:45:33 +03:00
Manuel Pégourié-Gonnard
7fa1407adb Remove redundant debug message.
Two consecutive messages (ie no branch between them) at the same level are not
needed, so only keep the one that has the most information.
2019-08-23 12:45:33 +03:00
Manuel Pégourié-Gonnard
6fa57bfae5 Remove 'session' input from populate_tranform()
When using this function to deserialize, it's not a problem to have a session
structure as input as we'll have one around anyway (most probably freshly
deserialised).

However for tests it's convenient to be able to build a transform without
having a session structure around.

Also, removing this structure from parameters makes the function signature
more uniform, the only exception left being the ssl param at the end that's
hard to avoid for now.
2019-08-23 12:45:33 +03:00
Manuel Pégourié-Gonnard
31d3ef11f5 Fix typo in comment 2019-08-23 12:45:33 +03:00
Manuel Pégourié-Gonnard
a7505d18eb Enforce promise to not use whole ssl context
Configs with no DEBUG_C are used for example in test-ref-configs.pl, which also
runs parts of compat.sh or ssl-opt.sh on them, so the added 'ssl = NULL'
statements will be exercised in those tests at least.
2019-08-23 12:45:33 +03:00
Manuel Pégourié-Gonnard
c864f6a209 Partially rm 'ssl' input from populate_transform() 2019-08-23 12:45:33 +03:00
Manuel Pégourié-Gonnard
9b108c242d Remove "handshake" input from populate_transform() 2019-08-23 12:45:33 +03:00
Manuel Pégourié-Gonnard
344460c913 Work around bug in key exporter API
https://github.com/ARMmbed/mbedtls/issues/2759
2019-08-23 12:45:33 +03:00
Manuel Pégourié-Gonnard
cba40d92bd Start refining parameters of populate_transform()
Parameters 'handshake' and 'ssl' will be replaced with more fine-grained
inputs in follow-up commits.
2019-08-23 12:45:33 +03:00
Manuel Pégourié-Gonnard
d73b47fe2e Move compress_buf allocation to derive_keys 2019-08-23 12:45:33 +03:00
Manuel Pégourié-Gonnard
040a9517b5 Move handling of randbytes to derive_keys() 2019-08-23 12:45:33 +03:00
Manuel Pégourié-Gonnard
de718b99b5 Make calc_verify() return the length as well
Simplifies ssl_compute_hash(), but unfortunately not so much the other uses.
2019-08-23 12:45:33 +03:00
Manuel Pégourié-Gonnard
0d56aaac7b Constify ssl_context param of calc_verify() 2019-08-23 12:45:33 +03:00
Manuel Pégourié-Gonnard
de047adfb4 Improve signature of ssl_compute_master()
Make it more explicit what's used. Unfortunately, we still need ssl as a
parameter for debugging, and because calc_verify wants it as a parameter (for
all TLS versions except SSL3 it would actually only need handshake, but SSL3
also accesses session_negotiate).

It's also because of calc_verify that we can't make it const yet, but see next
commit.
2019-08-23 12:45:33 +03:00
Manuel Pégourié-Gonnard
85680c49ef Reduce indentation in ssl_compute_master()
Exit earlier when there's noting to do.

For a small diff, review with 'git show -w'.
2019-08-23 12:45:33 +03:00
Manuel Pégourié-Gonnard
9951b712bd Start extracting ssl_compute_master()
For now just moving code around, not changing indentation. Calling convention
and signature are going to be adjusted in upcoming commits.
2019-08-23 12:45:33 +03:00
Manuel Pégourié-Gonnard
8d2805c784 Fix signature of ssl_set_transform_prfs() 2019-08-23 12:45:33 +03:00
Manuel Pégourié-Gonnard
1b00c4f5b3 Start extraction ssl_set_handshake_prfs()
For now just moving code around, will improve signature in the next commit.
2019-08-23 12:45:33 +03:00
Manuel Pégourié-Gonnard
e59ae23868 Start splitting populate_transform() out of derive_keys()
This is currently a dummy, just introducing the new name.
2019-08-23 12:45:33 +03:00
Jaeden Amero
beec142010 Merge remote-tracking branch 'origin/pr/2790' into development
* origin/pr/2790: (40 commits)
  Fix possibly-lossy conversion warning from MSVC
  Reintroduce length 0 check for records
  Don't use memcpy() for 2-byte copy operation
  Remove integer parsing macro
  Fix alignment in record header parsing routine
  Don't disallow 'record from another epoch' log msg in proxy ref test
  Make sure 'record from another epoch' is displayed for next epoch
  Implement record checking API
  Mark ssl_parse_record_header() as `const` in SSL context
  Make mbedtls_ssl_in_hdr_len() CID-unaware
  Remove duplicate setting of ssl->in_msgtype and ssl->in_msglen
  Move update of in_xxx fields in ssl_get_next_record()
  Move update of in_xxx fields outside of ssl_prepare_record_content()
  Reduce dependency of ssl_prepare_record_content() on in_xxx fields
  Move ssl_update_in_pointers() to after record hdr parsing
  Mark DTLS replay check as `const` on the SSL context
  Move updating the internal rec ptrs to outside of rec hdr parsing
  Mark ssl_decrypt_buf() as `const in the input SSL context
  Adapt ssl_prepare_record_content() to use SSL record structure
  Use record length from record structure when fetching content in TLS
  ...
2019-08-22 11:09:15 +01:00
Jaeden Amero
9a09f511b5 Merge remote-tracking branch 'origin/pr/2781' into development
* origin/pr/2781:
  Documentation fixes according to review
  Remove unused label in ssl_client2/ssl_server2
  Add missing word in documentation of mbedtls_ssl_check_record()
  cli/srv ex: Add dbg msg if record checking gives inconsistent result
  Fix minor issues in documentation of mbedtls_ssl_check_record()
  State that record checking is DTLS only and doesn't check content type
  Update version_features.c
  Pass dgrams to mbedtls_ssl_check_record in ssl_client2/server2
  Add IO wrappers to ssl_server2 as interm's between NET and SSL layer
  Add IO wrappers to ssl_client2 as interm's between NET and SSL layer
  Introduce configuration option and API for SSL record checking
2019-08-22 11:08:52 +01:00
Janos Follath
da6ac01963 Rename local variables 2019-08-16 13:47:29 +01:00
Janos Follath
1239d70870 Remove calls to psa_allocate_key
In PSA 1.0 keys are allocated implicitly by other functions
(like psa_import_key) and psa_allocate_key is not needed and does not
exist anymore.
2019-08-16 13:37:32 +01:00
Janos Follath
53b8ec27a2 Make variable naming consistent 2019-08-16 13:37:32 +01:00
Janos Follath
ed73b04c6e Update psa_import_key to PSA 1.0 2019-08-16 13:36:15 +01:00
Janos Follath
bd096101b5 Update psa_generator_abort to PSA 1.0 2019-08-16 11:45:55 +01:00
Janos Follath
6de99db449 Update psa_generator_read to PSA 1.0 2019-08-16 11:45:55 +01:00
Janos Follath
8dee877e8a Update psa_crypto_generator_t to PSA 1.0 2019-08-16 11:45:55 +01:00
Janos Follath
7374ee6139 Update GENERATOR_INIT macro to PSA 1.0 2019-08-16 11:45:55 +01:00
Jaeden Amero
922013e46d tls: Remove duplicate psa_util.h include
Don't include psa_util.h twice. It's enough to include it once.
2019-08-15 15:44:50 +01:00
Manuel Pégourié-Gonnard
7e821b5bcd Fix possibly-lossy conversion warning from MSVC
ssl_tls.c(4876): warning C4267: '=': conversion from 'size_t' to 'uint8_t', possible loss of data
2019-08-14 15:08:09 +01:00
Hanno Becker
d417cc945c Reintroduce length 0 check for records 2019-08-14 15:08:08 +01:00
Hanno Becker
d0b66d08bb Don't use memcpy() for 2-byte copy operation
Manual copying is slightly shorter here.
2019-08-14 15:08:08 +01:00
Hanno Becker
9eca276768 Remove integer parsing macro
If this is introduced, it should be defined in a prominent place
and put to use throughout the library, but this is left for another
time.
2019-08-14 15:08:08 +01:00
Hanno Becker
f5466258b4 Fix alignment in record header parsing routine 2019-08-14 15:08:08 +01:00
Hanno Becker
552f747216 Make sure 'record from another epoch' is displayed for next epoch
The test 'DTLS proxy: delay ChangeCipherSpec' from ssl-opt.sh
relies on this.
2019-08-14 15:08:08 +01:00
Hanno Becker
5422981052 Implement record checking API
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.
2019-08-14 15:08:08 +01:00
Hanno Becker
331de3df9a Mark ssl_parse_record_header() as const in SSL context 2019-08-14 15:08:08 +01:00
Hanno Becker
b0fe0eedce Remove duplicate setting of ssl->in_msgtype and ssl->in_msglen 2019-08-14 15:06:44 +01:00
Hanno Becker
44d89b2d53 Move update of in_xxx fields in ssl_get_next_record()
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.
2019-08-14 15:06:44 +01:00
Hanno Becker
8685c822c1 Move update of in_xxx fields outside of ssl_prepare_record_content()
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.
2019-08-14 15:06:44 +01:00
Hanno Becker
58ef0bf19f Reduce dependency of ssl_prepare_record_content() on in_xxx fields 2019-08-14 15:06:44 +01:00
Hanno Becker
d8bf8ceeb4 Move ssl_update_in_pointers() to after record hdr parsing
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.
2019-08-14 15:06:06 +01:00
Hanno Becker
0183d699bf Mark DTLS replay check as const on the SSL context 2019-08-14 15:06:06 +01:00
Hanno Becker
7ae20e0f4c Move updating the internal rec ptrs to outside of rec hdr parsing
The stack maintains pointers mbedtls_ssl_context::in_xxx pointing to
various parts of the [D]TLS record header. Originally, these fields
were determined and set in ssl_parse_record_header(). By now,
ssl_parse_record_header() has been modularized to setup an instance
of the internal SSL record structure mbedtls_record, and to derive
the old in_xxx fields from that.

This commit takes a further step towards removing the in_xxx fields
by deriving them from the established record structure _outside_ of
ssl_parse_record_header() after the latter has succeeded.

One exception is the handling of possible client reconnects,
which happens in the case then ssl_parse_record_header() returns
MBEDTLS_ERR_SSL_UNEXPECTED_RECORD; since ssl_check_client_reconnect()
so far uses the in_xxx fields, they need to be derived from the
record structure beforehand.
2019-08-14 15:06:06 +01:00
Hanno Becker
605949f84c Mark ssl_decrypt_buf() as `const in the input SSL context
In fact, the SSL context is only used to access the debug callback.
2019-08-14 15:06:06 +01:00
Hanno Becker
fdf660426d Adapt ssl_prepare_record_content() to use SSL record structure 2019-08-14 15:06:06 +01:00
Hanno Becker
a31756619c Use record length from record structure when fetching content in TLS 2019-08-14 15:06:06 +01:00
Hanno Becker
f50da50c04 Use record structure when remembering offset of next record in dgram 2019-08-14 15:06:06 +01:00
Hanno Becker
4acada35f5 Use SSL record structure when skipping over unexpected record 2019-08-14 15:06:06 +01:00
Hanno Becker
519f15dbba Adapt ssl_buffer_future_record() to work with SSL record structure 2019-08-14 15:06:05 +01:00
Hanno Becker
e5e7e7833c Setup SSL record structure in ssl_parse_record_header()
This commit makes a first step towards modularizing the incoming record
processing by having it operate on instances of the structure mbedtls_record
representing SSL records.

So far, only record encryption/decryption operate in terms of record
instances, but the rest of the parsing doesn't. In particular,
ssl_parse_record_header() operates directly on the fixed input buffer,
setting the various ssl->in_xxx pointers and fields, and only directly
before/after calling ssl_decrypt_buf() these fields a converted to/from
mbedtls_record instances.

This commit does not yet remove the ssl->in_xxx fields, but makes a step
towards extending the lifetime of mbedtls_record structure representing
incoming records, by modifying ssl_parse_record_header() to setup an
instance of mbedtls_record, and setting the ssl->in_xxx fields from that
instance. The instance so-constructed isn't used further so far, and in
particular it is not yet consolidated with the instance set up for use
in ssl_decrypt_record(). That's for a later commit.
2019-08-14 15:06:04 +01:00
Hanno Becker
37cfe73c92 Minor documentation improvements in ssl_parse_record_header() 2019-08-14 14:45:20 +01:00
Hanno Becker
955a5c98df Check for sufficient datagram size in ssl_parse_record_header()
Previously, ssl_parse_record_header() did not check whether the current
datagram is large enough to hold a record of the advertised size. This
could lead to records being silently skipped over or backed up on the
basis of an invalid record length. Concretely, the following would happen:

1) In the case of a record from an old epoch, the record would be
   'skipped over' by setting next_record_offset according to the advertised
   but non-validated length, and only in the subsequent mbedtls_ssl_fetch_input()
   it would be noticed in an assertion failure if the record length is too
   large for the current incoming datagram.
   While not critical, this is fragile, and also contrary to the intend
   that MBEDTLS_ERR_SSL_INTERNAL_ERROR should never be trigger-able by
   external input.
2) In the case of a future record being buffered, it might be that we
   backup a record before we have validated its length, hence copying
   parts of the input buffer that don't belong to the current record.
   This is a bug, and it's by luck that it doesn't seem to have critical
   consequences.

This commit fixes this by modifying ssl_parse_record_header() to check that
the current incoming datagram is large enough to hold a record of the
advertised length, returning MBEDTLS_ERR_SSL_INVALID_RECORD otherwise.
2019-08-14 14:44:55 +01:00
Hanno Becker
d5c0f826e6 Don't send an alert when receiving a record of unknown ContentType
We don't send alerts on other instances of ill-formed records,
so why should we do it here? If we want to keep it, the alerts
should rather be sent ssl_get_next_record().
2019-08-14 14:44:36 +01:00
Hanno Becker
a8814794e9 Don't call ssl_fetch_input for record content fetch in DTLS
As explained in the previous commit, if mbedtls_ssl_fetch_input()
is called multiple times, all but the first call are equivalent to
bounds checks in the incoming datagram.
2019-08-14 14:43:46 +01:00
Hanno Becker
59be60e98b Don't call ssl_fetch_input for record hdr size check in DTLS
In DTLS, if mbedtls_ssl_fetch_input() is called multiple times without
resetting the input buffer in between, the non-initial calls are functionally
equivalent to mere bounds checks ensuring that the incoming datagram is
large enough to hold the requested data. In the interest of code-size
and modularity (removing a call to a non-const function which is logically
const in this instance), this commit replaces such a call to
mbedtls_ssl_fetch_input() by an explicit bounds check in
ssl_parse_record_header().
2019-08-14 14:41:57 +01:00
Hanno Becker
e538d8287e Move size-check for DTLS record header with CID to DTLS-only branch 2019-08-14 14:41:37 +01:00
Hanno Becker
2fddd3765e Check same-port-reconnect from client outside of record hdr parsing
Previously, `ssl_handle_possible_reconnect()` was part of
`ssl_parse_record_header()`, which was required to return a non-zero error
code to indicate a record which should not be further processed because it
was invalid, unexpected, duplicate, .... In this case, some error codes
would lead to some actions to be taken, e.g. `MBEDTLS_ERR_SSL_EARLY_MESSAGE`
to potential buffering of the record, but eventually, the record would be
dropped regardless of the precise value of the error code. The error code
`MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED` returned from
`ssl_handle_possible_reconnect()` did not receive any special treatment and
lead to silent dopping of the record - in particular, it was never returned
to the user.

In the new logic this commit introduces, `ssl_handle_possible_reconnect()` is
part of `ssl_check_client_reconnect()` which is triggered _after_
`ssl_parse_record_header()` found an unexpected record, which is already in
the code-path eventually dropping the record; we want to leave this code-path
only if a valid cookie has been found and we want to reset, but do nothing
otherwise. That's why `ssl_handle_possible_reconnect()` now returns `0` unless
a valid cookie has been found or a fatal error occurred.
2019-08-14 14:41:06 +01:00
Hanno Becker
4894873b92 Remove redundant minimum length check
Availability of sufficient incoming data should be checked when
it is needed, which is in mbedtls_ssl_fetch_input(), and this
function has the necessary bounds checks in place.
2019-08-14 14:34:49 +01:00
Hanno Becker
20016654c3 Remove unnecessary backup of explicit IV in AEAD record decryption
There is no need to hold back the explicit IV for AEAD ciphers.
2019-08-14 14:34:26 +01:00
Hanno Becker
d96a652d80 Improve documentation of mbedtls_ssl_decrypt_buf() 2019-08-14 14:34:04 +01:00
Hanno Becker
c957e3b5f8 Remove redundant length check during record header parsing
The check is in terms of the internal input buffer length and is
hence likely to be originally intended to protect against overflow
of the input buffer when fetching data from the underlying
transport in mbedtls_ssl_fetch_input(). For locality of reasoning,
it's better to perform such a check close to where it's needed,
and in fact, mbedtls_ssl_fetch_input() _does_ contain an equivalent
bounds check, too, rendering the bounds check in question redundant.
2019-08-14 14:33:39 +01:00
Hanno Becker
e2b786d40f Remove misleading comment in mbedtls_ssl_decrypt_buf()
The comment doesn't seem to relate to the code that follows.
2019-08-14 14:33:09 +01:00
Hanno Becker
47ebaa2205 Remove assertion in mbedtls_ssl_decrypt_buf()
mbedtls_ssl_decrypt_buf() asserts that the passed transform is not NULL,
but the function is only invoked in a single place, and this invocation
is clearly visible to be within a branch ensuring that the incoming
transform isn't NULL. Remove the assertion for the benefit of code-size.
2019-08-14 14:32:39 +01:00
Hanno Becker
d96e10bf23 Check architectural bound for max record payload len in one place
The previous code performed architectural maximum record length checks
both before and after record decryption. Since MBEDTLS_SSL_IN_CONTENT_LEN
bounds the maximum length of the record plaintext, it suffices to check
only once after (potential) decryption.

This must not be confused with the internal check that the record
length is small enough to make the record fit into the internal input
buffer; this is done in mbedtls_ssl_fetch_input().
2019-08-14 14:31:58 +01:00
Hanno Becker
3be264e2c3 Remove redundant length-0 checks for incoming unprotected records 2019-08-14 14:30:51 +01:00
Hanno Becker
cfe457921a Introduce configuration option and API for SSL record checking 2019-08-06 10:09:08 +03:00
Jaeden Amero
d431104926 ssl_tls: Enable Suite B with subset of ECP curves
Make sure the code compiles even if some curves are not defined.

Fixes #1591
2019-06-20 10:59:05 +01:00
Jaeden Amero
2de07f1dd1 ssl: Don't access non-existent encrypt_then_mac field
When MBEDTLS_SSL_ENCRYPT_THEN_MAC is enabled, but not
MBEDTLS_SSL_SOME_MODES_USE_MAC, mbedtls_ssl_derive_keys() and
build_transforms() will attempt to use a non-existent `encrypt_then_mac`
field in the ssl_transform.

    Compile [ 93.7%]: ssl_tls.c
    [Error] ssl_tls.c@865,14: 'mbedtls_ssl_transform {aka struct mbedtls_ssl_transform}' ha
s no member named 'encrypt_then_mac'
    [ERROR] ./mbed-os/features/mbedtls/src/ssl_tls.c: In function 'mbedtls_ssl_derive_keys'
:
    ./mbed-os/features/mbedtls/src/ssl_tls.c:865:14: error: 'mbedtls_ssl_transform {aka str
uct mbedtls_ssl_transform}' has no member named 'encrypt_then_mac'
         transform->encrypt_then_mac = session->encrypt_then_mac;
                  ^~

Change mbedtls_ssl_derive_keys() and build_transforms() to only access
`encrypt_then_mac` if `encrypt_then_mac` is actually present.

Add a regression test to detect when we have regressions with
configurations that do not include any MAC ciphersuites.

Fixes d56ed2491b ("Reduce size of `ssl_transform` if no MAC ciphersuite is enabled")
2019-06-05 14:09:29 +01:00
Hanno Becker
e8d6afd627 Add debug line witnessing receipt of unexpected CID 2019-06-03 16:07:50 +01:00
Hanno Becker
92d30f5bcf Fix indentation in debug message in ssl_tls.c 2019-06-03 16:07:50 +01:00
Hanno Becker
8e55b0f852 Improve comment in ssl_parse_record_header() 2019-06-03 16:07:50 +01:00
Hanno Becker
615ef17b67 Allow passing NULL pointers to mbedtls_ssl_get_peer_cid()
This commit modifies mbedtls_ssl_get_peer_cid() to also allow passing
NULL pointers in the arguments for the peer's CID value and length, in
case this information is needed.

For example, some users might only be interested in whether the use of
the CID was negotiated, in which case both CID value and length pointers
can be set to NULL. Other users might only be interested in confirming
that the use of CID was negotiated and the peer chose the empty CID,
in which case the CID value pointer only would be set to NULL.
It doesn't make sense to pass a NULL pointer for the CID length but a
non-NULL pointer for the CID value, as the caller has no way of telling
the length of the returned CID - and this case is therefore forbidden.
2019-06-03 16:07:50 +01:00
Hanno Becker
a0e20d04b2 Rename MBEDTLS_SSL_CID to MBEDTLS_SSL_DTLS_CONNECTION_ID
Files modified via

sed -i 's/MBEDTLS_SSL_CID\([^_]\|$\)/MBEDTLS_SSL_DTLS_CONNECTION_ID\1/g' **/*.c **/*.h **/*.sh **/*.function
2019-06-03 16:07:50 +01:00
Hanno Becker
d1f203557f Slightly reorder CID debug messages during creation of transforms 2019-06-03 16:07:50 +01:00
Hanno Becker
611ac77127 Fix mbedtls_ssl_conf_cid() to not depend on macro constant values
The previous implementation of mbedtls_ssl_conf_cid() relied on
MBEDTLS_SSL_UNEXPECTED_CID_IGNORE being defined as 1.
2019-06-03 16:07:50 +01:00
Hanno Becker
5d12467fad Remove warnings about unfinished CID implementation
The implementation is complete now.
2019-06-03 16:07:50 +01:00
Hanno Becker
8367ccc03b Allow to configure the stack's behaviour on unexpected CIDs
This commit modifies the CID configuration API mbedtls_ssl_conf_cid_len()
to allow the configuration of the stack's behaviour when receiving an
encrypted DTLS record with unexpected CID.
2019-06-03 16:07:50 +01:00
Hanno Becker
b9ec44fcf6 Remove restriction on value of MBEDTLS_SSL_CID_PADDING_GRANULARITY 2019-06-03 16:07:50 +01:00
Hanno Becker
2cdc5c3cf9 Make signed to unsigned integer truncation cast explicit 2019-06-03 16:07:50 +01:00
Hanno Becker
b1aa1b3616 Allow the configuration of padding when using CID extension 2019-06-03 16:07:50 +01:00
Hanno Becker
4c3eb7c919 Set CID pointer to default value even for TLS
There are two options:
1. Don't set it, and don't use it during record protection,
   guarding the respective paths by a check whether TLS or
   DTLS is used.
2. Set it to the default value even for TLS, and avoid the
   protocol-dependent branch during record protection.

This commit picks option 2.
2019-06-03 16:07:50 +01:00
Hanno Becker
4a4af9fcbe Fix typo in comment 2019-06-03 16:07:50 +01:00
Hanno Becker
22a59fdca8 Remove indicators and warnings about unfinished CID implementation 2019-06-03 16:07:50 +01:00
Hanno Becker
05154c3897 Re-enable passing CIDs to record transforms 2019-06-03 16:07:50 +01:00
Hanno Becker
16ded98bef Don't fail on record with unexpected CID
This commit changes the stack's behaviour when facing a record
with a non-matching CID. Previously, the stack failed in this
case, while now we silently skip over the current record.
2019-06-03 16:07:50 +01:00
Hanno Becker
938489a1bc Re-enable CID comparison when decrypting CID-based records 2019-06-03 16:07:50 +01:00
Hanno Becker
ca59c2b486 Implement parsing of CID-based records
Previously, ssl_get_next_record() would fetch 13 Bytes for the
record header and hand over to ssl_parse_record_header() to parse
and validate these. With the introduction of CID-based records, the
record length is not known in advance, and parsing and validating
must happen at the same time. ssl_parse_record_header() is therefore
rewritten in the following way:
1. Fetch and validate record content type and version.
2. If the record content type indicates a record including a CID,
   adjust the record header pointers accordingly; here, we use the
   statically configured length of incoming CIDs, avoiding any
   elaborate CID parsing mechanism or dependency on the record
   epoch, as explained in the previous commit.
3. Fetch the rest of the record header (note: this doesn't actually
   fetch anything, but makes sure that the datagram fetched in the
   earlier call to ssl_fetch_input() contains enough data).
4. Parse and validate the rest of the record header as before.
2019-06-03 16:07:50 +01:00
Hanno Becker
6430faf098 Adapt record encryption/decryption routines to change of record type
This commit modifies the code surrounding the invocations of
ssl_decrypt_buf() and ssl_encrypt_buf() to deal with a change
of record content type during CID-based record encryption/decryption.
2019-06-03 16:07:50 +01:00
Hanno Becker
f9c6a4bea1 Add pointers to in/out CID fields to mbedtls_ssl_context
mbedtls_ssl_context contains pointers in_buf, in_hdr, in_len, ...
which point to various parts of the header of an incoming TLS or
DTLS record; similarly, there are pointers out_buf, ... for
outgoing records.

This commit adds fields in_cid and out_cid which point to where
the CID of incoming/outgoing records should reside, if present,
namely prior to where the record length resides.

Quoting https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-04:

   The DTLSInnerPlaintext value is then encrypted and the CID added to
   produce the final DTLSCiphertext.

        struct {
            ContentType special_type = tls12_cid; /* 25 */
            ProtocolVersion version;
            uint16 epoch;
            uint48 sequence_number;
            opaque cid[cid_length];               // New field
            uint16 length;
            opaque enc_content[DTLSCiphertext.length];
        } DTLSCiphertext;

For outgoing records, out_cid is set in ssl_update_out_pointers()
based on the settings in the current outgoing transform.

For incoming records, ssl_update_in_pointers() sets in_cid as if no
CID was present, and it is the responsibility of ssl_parse_record_header()
to update the field (as well as in_len, in_msg and in_iv) when parsing
records that do contain a CID. This will be done in a subsequent commit.

Finally, the code around the invocations of ssl_decrypt_buf()
and ssl_encrypt_buf() is adapted to transfer the CID from the
input/output buffer to the CID field in the internal record
structure (which is what ssl_{encrypt/decrypt}_buf() uses).

Note that mbedtls_ssl_in_hdr_len() doesn't need change because
it infers the header length as in_iv - in_hdr, which will account
for the CID for records using such.
2019-06-03 16:07:50 +01:00
Hanno Becker
6cbad5560d Account for additional record expansion when using CIDs
Using the Connection ID extension increases the maximum record expansion
because
- the real record content type is added to the plaintext
- the plaintext may be padded with an arbitrary number of
  zero bytes, in order to prevent leakage of information
  through package length analysis. Currently, we always
  pad the plaintext in a minimal way so that its length
  is a multiple of 16 Bytes.

This commit adapts the various parts of the library to account
for that additional source of record expansion.
2019-06-03 16:07:50 +01:00
Hanno Becker
ad4a137965 Add CID configuration API
Context:
The CID draft does not require that the length of CIDs used for incoming
records must not change in the course of a connection. Since the record
header does not contain a length field for the CID, this means that if
CIDs of varying lengths are used, the CID length must be inferred from
other aspects of the record header (such as the epoch) and/or by means
outside of the protocol, e.g. by coding its length in the CID itself.

Inferring the CID length from the record's epoch is theoretically possible
in DTLS 1.2, but it requires the information about the epoch to be present
even if the epoch is no longer used: That's because one should silently drop
records from old epochs, but not the entire datagrams to which they belong
(there might be entire flights in a single datagram, including a change of
epoch); however, in order to do so, one needs to parse the record's content
length, the position of which is only known once the CID length for the epoch
is known. In conclusion, it puts a significant burden on the implementation
to infer the CID length from the record epoch, which moreover mangles record
processing with the high-level logic of the protocol (determining which epochs
are in use in which flights, when they are changed, etc. -- this would normally
determine when we drop epochs).

Moreover, with DTLS 1.3, CIDs are no longer uniquely associated to epochs,
but every epoch may use a set of CIDs of varying lengths -- in that case,
it's even theoretically impossible to do record header parsing based on
the epoch configuration only.

We must therefore seek a way for standalone record header parsing, which
means that we must either (a) fix the CID lengths for incoming records,
or (b) allow the application-code to configure a callback to implement
an application-specific CID parsing which would somehow infer the length
of the CID from the CID itself.

Supporting multiple lengths for incoming CIDs significantly increases
complexity while, on the other hand, the restriction to a fixed CID length
for incoming CIDs (which the application controls - in contrast to the
lengths of the CIDs used when writing messages to the peer) doesn't
appear to severely limit the usefulness of the CID extension.

Therefore, the initial implementation of the CID feature will require
a fixed length for incoming CIDs, which is what this commit enforces,
in the following way:

In order to avoid a change of API in case support for variable lengths
CIDs shall be added at some point, we keep mbedtls_ssl_set_cid(), which
includes a CID length parameter, but add a new API mbedtls_ssl_conf_cid_len()
which applies to an SSL configuration, and which fixes the CID length that
any call to mbetls_ssl_set_cid() which applies to an SSL context that is bound
to the given SSL configuration must use.

While this creates a slight redundancy of parameters, it allows to
potentially add an API like mbedtls_ssl_conf_cid_len_cb() later which
could allow users to register a callback which dynamically infers the
length of a CID at record header parsing time, without changing the
rest of the API.
2019-06-03 16:07:50 +01:00
Hanno Becker
5903de45b6 Split mbedtls_ssl_hdr_len() in separate functions for in/out records
The function mbedtls_ssl_hdr_len() returns the length of the record
header (so far: always 13 Bytes for DTLS, and always 5 Bytes for TLS).

With the introduction of the CID extension, the lengths of record
headers depends on whether the records are incoming or outgoing,
and also on the current transform.

Preparing for this, this commit splits mbedtls_ssl_hdr_len() in two
-- so far unmodified -- functions mbedtls_ssl_in_hdr_len() and
mbedtls_ssl_out_hdr_len() and replaces the uses of mbedtls_ssl_hdr_len()
according to whether they are about incoming or outgoing records.

There is no need to change the signature of mbedtls_ssl_{in/out}_hdr_len()
in preparation for its dependency on the currently active transform,
since the SSL context is passed as an argument, and the currently
active transform is referenced from that.
2019-06-03 16:07:50 +01:00
Hanno Becker
f661c9c39c Add helper function to check validity of record content type
With the introduction of the CID feature, the stack needs to be able
to handle a change of record content type during record protection,
which in particular means that the record content type check will
need to move or be duplicated.

This commit introduces a tiny static helper function which checks
the validity of record content types, which hopefully makes it
easier to subsequently move or duplicate this check.
2019-06-03 16:07:50 +01:00
Hanno Becker
37ae952923 Move dropping of unexpected AD records to after record decryption
With the introduction of the CID extension, the record content type
may change during decryption; we must therefore re-consider every
record content type check that happens before decryption, and either
move or duplicate it to ensure it also applies to records whose
real content type is only revealed during decryption.

This commit does this for the silent dropping of unexpected
ApplicationData records in DTLS. Previously, this was caught
in ssl_parse_record_header(), returning
MBEDTLS_ERR_SSL_UNEXPECTED_RECORD which in ssl_get_next_record()
would lead to silent skipping of the record.

When using CID, this check wouldn't trigger e.g. when delayed
encrypted ApplicationData records come on a CID-based connection
during a renegotiation.

This commit moves the check to mbedtls_ssl_handle_message_type()
and returns MBEDTLS_ERR_SSL_NON_FATAL if it triggers, which leads
so silent skipover in the caller mbedtls_ssl_read_record().
2019-06-03 16:07:50 +01:00
Hanno Becker
79594fd0d4 Set pointer to start of plaintext at record decryption time
The SSL context structure mbedtls_ssl_context contains several pointers
ssl->in_hdr, ssl->in_len, ssl->in_iv, ssl->in_msg pointing to various
parts of the record header in an incoming record, and they are setup
in the static function ssl_update_in_pointers() based on the _expected_
transform for the next incoming record.
In particular, the pointer ssl->in_msg is set to where the record plaintext
should reside after record decryption, and an assertion double-checks this
after each call to ssl_decrypt_buf().

This commit removes the dependency of ssl_update_in_pointers() on the
expected incoming transform by setting ssl->in_msg to ssl->in_iv --
the beginning of the record content (potentially including the IV) --
and adjusting ssl->in_msg after calling ssl_decrypt_buf() on a protected
record.

Care has to be taken to not load ssl->in_msg before calling
mbedtls_ssl_read_record(), then, which was previously the
case in ssl_parse_server_hello(); the commit fixes that.
2019-06-03 16:07:50 +01:00
Hanno Becker
82e2a3961c Treat an invalid record after decryption as fatal
If a record exhibits an invalid feature only after successful
authenticated decryption, this is a protocol violation by the
peer and should hence lead to connection failure. The previous
code, however, would silently ignore such records. This commit
fixes this.

So far, the only case to which this applies is the non-acceptance
of empty non-AD records in TLS 1.2. With the present commit, such
records lead to connection failure, while previously, they were
silently ignored.

With the introduction of the Connection ID extension (or TLS 1.3),
this will also apply to records whose real content type -- which
is only revealed during authenticated decryption -- is invalid.
2019-06-03 16:07:50 +01:00
Hanno Becker
6e7700df17 Expain rationale for handling of consecutive empty AD records 2019-06-03 16:07:50 +01:00
Hanno Becker
76a79ab4a2 Don't allow calling CID API outside of DTLS 2019-06-03 16:07:50 +01:00
Hanno Becker
95e4bbcf6c Fix additional data calculation if CID is disabled
In contrast to other aspects of the Connection ID extension,
the CID-based additional data for MAC computations differs from
the non-CID case even if the CID length is 0, because it
includes the CID length.
2019-06-03 14:47:36 +01:00
Hanno Becker
af05ac067b Remove unnecessary empty line in ssl_tls.c 2019-06-03 14:47:36 +01:00
Hanno Becker
07dc97db8c Don't quote DTLSInnerPlaintext structure multiple times 2019-06-03 14:47:36 +01:00
Hanno Becker
d3f8c79ea0 Improve wording in ssl_build_inner_plaintext() 2019-06-03 14:47:36 +01:00
Hanno Becker
edb24f8eec Remove unnecessary whitespace in ssl_extract_add_data_from_record() 2019-06-03 14:47:36 +01:00
Hanno Becker
92fb4fa802 Reduce stack usage for additional data buffers in record dec/enc 2019-06-03 14:47:36 +01:00
Hanno Becker
c4a190bb0f Add length of CID to additional data used for record protection
Quoting the CID draft 04:

   -  Block Ciphers:

       MAC(MAC_write_key, seq_num +
           tls12_cid +                     // New input
           DTLSPlaintext.version +
           cid +                           // New input
           cid_length +                    // New input
           length_of_DTLSInnerPlaintext +  // New input
           DTLSInnerPlaintext.content +    // New input
           DTLSInnerPlaintext.real_type +  // New input
           DTLSInnerPlaintext.zeros        // New input
       )

And similar for AEAD and Encrypt-then-MAC.
2019-06-03 14:47:36 +01:00
Hanno Becker
d5aeab1e8a Improve documentation of ssl_extract_add_data_from_record() 2019-06-03 14:47:36 +01:00
Hanno Becker
43c24b8da9 Fix missing compile-time guards around CID-only constants 2019-06-03 14:47:36 +01:00
Hanno Becker
f44e55de5e Remove TODO 2019-06-03 14:47:36 +01:00
Hanno Becker
75f080f4b6 Use MBEDTLS_ namespace for internal CID length constant 2019-06-03 14:47:36 +01:00
Hanno Becker
8a7f972202 Skip copying CIDs to SSL transforms until CID feature is complete
This commit temporarily comments the copying of the negotiated CIDs
into the established ::mbedtls_ssl_transform in mbedtls_ssl_derive_keys()
until the CID feature has been fully implemented.

While mbedtls_ssl_decrypt_buf() and mbedtls_ssl_encrypt_buf() do
support CID-based record protection by now and can be unit tested,
the following two changes in the rest of the stack are still missing
before CID-based record protection can be integrated:
- Parsing of CIDs in incoming records.
- Allowing the new CID record content type for incoming records.
- Dealing with a change of record content type during record
  decryption.

Further, since mbedtls_ssl_get_peer_cid() judges the use of CIDs by
the CID fields in the currently transforms, this change also requires
temporarily disabling some grepping for ssl_client2 / ssl_server2
debug output in ssl-opt.sh.
2019-06-03 14:47:36 +01:00
Hanno Becker
8b3eb5ab82 Implement inner plaintext parsing/writing for CID-based connections 2019-06-03 14:47:36 +01:00
Hanno Becker
cab87e68b6 Incorporate CID into MAC computations during record protection
This commit modifies ssl_decrypt_buf() and ssl_encrypt_buf()
to include the CID into authentication data during record
protection.

It does not yet implement the new DTLSInnerPlaintext format
from https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-04
2019-06-03 14:47:36 +01:00
Hanno Becker
1c1f046804 Replace 'ingoing' -> 'incoming' in CID debug messages 2019-06-03 14:43:16 +01:00
Hanno Becker
c5f2422116 Document behaviour of mbedtls_ssl_get_peer_cid() for empty CIDs 2019-06-03 14:43:16 +01:00
Hanno Becker
b7ee0cf3f9 Make integer truncation explicit in mbedtls_ssl_set_cid() 2019-06-03 14:43:16 +01:00
Hanno Becker
b1f89cd602 Implement mbedtls_ssl_get_peer_cid() 2019-06-03 14:43:16 +01:00
Hanno Becker
4bf7465840 Copy CIDs into SSL transform if use of CID has been negotiated 2019-06-03 14:43:16 +01:00
Hanno Becker
ca092246a7 Allow configuring own CID fields through mbedtls_ssl_get_peer_cid() 2019-06-03 14:43:16 +01:00
Hanno Becker
35c36a6760 Guard CID implementations by MBEDTLS_SSL_CID 2019-06-03 14:42:08 +01:00
Hanno Becker
f1f9a82320 Add warnings about status of implementation of CID API 2019-06-03 14:42:08 +01:00
Hanno Becker
f8542cf620 Add dummy implementations for CID API 2019-06-03 14:42:08 +01:00
Manuel Pégourié-Gonnard
45be3d8136 Fix compile guard for static function in ssl
The guard for the definition of the function was different from the guard on
its only use - make it the same.

This has been caught by tests/scripts/key-exchanges.pl. It had not been caught
by this script in earlier CI runs, because previously USE_PSA_CRYPTO was
disabled in the builds used by this script; enabling it uncovered the issue.
2019-05-23 03:01:35 -04:00
Ron Eldor
d2f25f7ea8 Fix missing tls version test failures
Add checks for tls_prf tests with the relevant tls version configuration.
2019-05-15 14:54:22 +03:00
Ron Eldor
0810f0babd Fix typo
Fix typo `returnn` -> `return`
2019-05-15 13:58:13 +03:00
Ron Eldor
cf28009839 Add function to retrieve the tls_prf type
Add `tls_prf_get_type()` static function that returns the
`mbedtls_tls_prf_types` according to the used `tls_prf` function.
2019-05-15 13:57:39 +03:00
Ron Eldor
51d3ab544f Add public API for tls_prf
Add a public API for key derivation, introducing an enum for `tls_prf`
type.
2019-05-15 13:53:02 +03:00
Ron Eldor
b7fd64ce2b Add eap-tls key derivation in the examples.
Add support for eap-tls key derivation functionality,
in `ssl_client2` and `ssl_server2` reference applications.
2019-05-15 13:41:42 +03:00
Ron Eldor
f5cc10d93b Add an extra key export function
Add an additional function `mbedtls_ssl_export_keys_ext_t()`
for exporting key, that adds additional information such as
the used `tls_prf` and the random bytes.
2019-05-15 13:38:39 +03:00
Ron Eldor
3b350856ff Have the temporary buffer allocated dynamically
Change `tmp` buffer to be dynamically allocated, as it is now
dependent on external label given as input, in `tls_prf_generic()`.
2019-05-15 13:38:39 +03:00
Ron Eldor
a9f9a73920 Zeroize secret data in the exit point
Zeroize the secret data in `mbedtls_ssl_derive_keys()`
in the single exit point.
2019-05-15 13:38:39 +03:00
Ron Eldor
e699270908 Add a single exit point in key derivation function
Add a single exit point in `mbedtls_ssl_derive_keys()`.
2019-05-15 13:38:39 +03:00
Hanno Becker
1f10d7643f Fix uninitialized variable access in debug output of record enc/dec 2019-04-26 13:34:37 +01:00
Hanno Becker
22bf145599 Adapt PSA code to ssl_transform changes 2019-04-25 12:58:21 +01:00
Hanno Becker
78f839df94 Adapt record length value after encryption 2019-04-25 12:58:21 +01:00
Hanno Becker
b2ca87d289 Rename ssl_decrypt_buf() to mbedtls_ssl_decrypt_buf() in comment 2019-04-25 12:58:21 +01:00
Hanno Becker
29800d2fd1 Double check that record expansion is as expected during decryption 2019-04-25 12:58:21 +01:00
Hanno Becker
1c0c37feed Move debugging output after record decryption
The debugging call printing the decrypted record payload happened
before updating ssl->in_msglen.
2019-04-25 12:58:21 +01:00
Hanno Becker
a18d1320da Add tests for record encryption/decryption
This commit adds tests exercising mutually inverse pairs of
record encryption and decryption transformations for the various
transformation types allowed in TLS: Stream, CBC, and AEAD.
2019-04-25 12:58:21 +01:00
Hanno Becker
d56ed2491b Reduce size of ssl_transform if no MAC ciphersuite is enabled
The hash contexts `ssl_transform->md_ctx_{enc/dec}` are not used if
only AEAD ciphersuites are enabled. This commit removes them from the
`ssl_transform` struct in this case, saving a few bytes.
2019-04-25 12:58:21 +01:00
Hanno Becker
8031d06cb2 Remove code from ssl_derive_keys if relevant modes are not enabled
This commit guards code specific to AEAD, CBC and stream cipher modes
in `ssl_derive_keys` by the respective configuration flags, analogous
to the guards that are already in place in the record decryption and
encryption functions `ssl_decrypt_buf` resp. `ssl_decrypt_buf`.
2019-04-25 12:58:21 +01:00
Hanno Becker
2e24c3b672 Provide standalone version of ssl_decrypt_buf
Analogous to the previous commit, but concerning the record decryption
routine `ssl_decrypt_buf`.

An important change regards the checking of CBC padding:
Prior to this commit, the CBC padding check always read 256 bytes at
the end of the internal record buffer, almost always going past the
boundaries of the record under consideration. In order to stay within
the bounds of the given record, this commit changes this behavior by
always reading the last min(256, plaintext_len) bytes of the record
plaintext buffer and taking into consideration the last `padlen` of
these for the padding check. With this change, the memory access
pattern and runtime of the padding check is entirely determined by
the size of the encrypted record, in particular not giving away
any information on the validity of the padding.

The following depicts the different behaviors:

1) Previous CBC padding check

1.a) Claimed padding length <= plaintext length

  +----------------------------------------+----+
  |   Record plaintext buffer   |          | PL |
  +----------------------------------------+----+
                                 \__ PL __/

                                +------------------------------------...
                                |  read for padding check            ...
                                +------------------------------------...
                                                |
                                                 contents discarded
                                                 from here

1.b) Claimed padding length > plaintext length

  +----------------------------------------+----+
  |   Record plaintext buffer              | PL |
  +----------------------------------------+----+
                                           +-------------------------...
                                           |  read for padding check ...
                                           +-------------------------...
                                                |
                                                 contents discarded
                                                 from here

2) New CBC padding check

  +----------------------------------------+----+
  |   Record plaintext buffer   |          | PL |
  +----------------------------------------+----+
                                 \__ PL __/

        +---------------------------------------+
        |        read for padding check         |
        +---------------------------------------+
                                |
                                 contents discarded
                                 until here
2019-04-25 12:58:21 +01:00
Hanno Becker
9eddaebda5 Provide standalone version of ssl_encrypt_buf
The previous version of the record encryption function
`ssl_encrypt_buf` takes the entire SSL context as an argument,
while intuitively, it should only depend on the current security
parameters and the record buffer.

Analyzing the exact dependencies, it turned out that in addition
to the currently active `ssl_transform` instance and the record
information, the encryption function needs access to
- the negotiated protocol version, and
- the status of the encrypt-then-MAC extension.

This commit moves these two fields into `ssl_transform` and
changes the signature of `ssl_encrypt_buf` to only use an instance
of `ssl_transform` and an instance of the new `ssl_record` type.
The `ssl_context` instance is *solely* kept for the debugging macros
which need an SSL context instance.

The benefit of the change is twofold:
1) It avoids the need of the MPS to deal with instances of
   `ssl_context`. The MPS should only work with records and
   opaque security parameters, which is what the change in
   this commit makes progress towards.
2) It significantly eases testing of the encryption function:
   independent of any SSL context, the encryption function can
   be passed some record buffer to encrypt alongside some arbitrary
   choice of parameters, and e.g. be checked to not overflow the
   provided memory.
2019-04-25 12:58:21 +01:00
Hanno Becker
52344c2972 Correct space needed for MAC in case of NULL cipher
The macro constant `MBEDTLS_SSL_MAC_ADD` defined in `ssl_internal.h`
defines an upper bound for the amount of space needed for the record
authentication tag. Its definition distinguishes between the
presence of an ARC4 or CBC ciphersuite suite, in which case the maximum
size of an enabled SHA digest is used; otherwise, `MBEDTLS_SSL_MAC_ADD`
is set to 16 to accomodate AEAD authentication tags.

This assignment has a flaw in the situation where confidentiality is
not needed and the NULL cipher is in use. In this case, the
authentication tag also uses a SHA digest, but the definition of
`MBEDTLS_SSL_MAC_ADD` doesn't guarantee enough space.

The present commit fixes this by distinguishing between the presence
of *some* ciphersuite using a MAC, including those using a NULL cipher.
For that, the previously internal macro `SSL_SOME_MODES_USE_MAC` from
`ssl_tls.c` is renamed and moved to the public macro
`MBEDTLS_SOME_MODES_USE_MAC` defined in `ssl_internal.h`.
2019-04-25 12:58:21 +01:00
Hanno Becker
e694c3ef3e Remove ciphersuite_info from ssl_transform
Prior to this commit, the security parameter struct `ssl_transform`
contained a `ciphersuite_info` field pointing to the information
structure for the negotiated ciphersuite. However, the only
information extracted from that structure that was used in the core
encryption and decryption functions `ssl_encrypt_buf`/`ssl_decrypt_buf`
was the authentication tag length in case of an AEAD cipher.

The present commit removes the `ciphersuite_info` field from the
`ssl_transform` structure and adds an explicit `taglen` field
for AEAD authentication tag length.

This is in accordance with the principle that the `ssl_transform`
structure should contain the raw parameters needed for the record
encryption and decryption functions to work, but not the higher-level
information that gave rise to them. For example, the `ssl_transform`
structure implicitly contains the encryption/decryption keys within
their cipher contexts, but it doesn't contain the SSL master or
premaster secrets. Likewise, it contains an explicit `maclen`, while
the status of the 'Truncated HMAC' extension -- which  determines the
value of `maclen` when the `ssl_transform` structure is created in
`ssl_derive_keys` -- is not contained in `ssl_transform`.

The `ciphersuite_info` pointer was used in other places outside
the encryption/decryption functions during the handshake, and for
these functions to work, this commit adds a `ciphersuite_info` pointer
field to the handshake-local `ssl_handshake_params` structure.
2019-04-25 12:58:21 +01:00
Hanno Becker
88aaf652b1 Remove key length field from ssl_transform
The `ssl_transform` security parameter structure contains opaque
cipher contexts for use by the record encryption/decryption functions
`ssl_decrypt_buf`/`ssl_encrypt_buf`, while the underlying key material
is configured once in `ssl_derive_keys` and is not explicitly dealt with
anymore afterwards. In particular, the key length is not needed
explicitly by the encryption/decryption functions but is nonetheless
stored in an explicit yet superfluous `keylen` field in `ssl_transform`.
This commit removes this field.
2019-04-25 12:57:19 +01:00
Jaeden Amero
7a1c4eb826 Merge remote-tracking branch 'origin/pr/2567' into development
* origin/pr/2567:
  Don't use debug level 1 for informational messages
2019-04-16 15:08:39 +01:00
Jaeden Amero
fe7106755e Merge remote-tracking branch 'origin/pr/2539' into development
Resolve conflicts by performing the following:
  - Ensure calls to mbedtls_x509_crt_verify_* are made with callbacks

* origin/pr/2539:
  Make CRT callback tests more robust
  Rename constant in client2.c
  Fix typo
  Add test for configuration specific CRT callback
  Fix doxygen documentation of mbedtls_ssl_set_verify()
  Add test exercising context-specific CRT callback to ssl-opt.sh
  Add cmd to use context-specific CRT callback in ssl_client2
  Implement context-specific verification callbacks
  Add context-specific CRT verification callbacks
  Improve documentation of mbedtls_ssl_conf_verify()
2019-04-16 15:05:18 +01:00
Hanno Becker
4c8c7aa95e Don't use debug level 1 for informational messages 2019-04-10 09:26:53 +01:00
Hanno Becker
efb440afec Add test exercising context-specific CRT callback to ssl-opt.sh 2019-04-03 13:11:20 +01:00
Hanno Becker
8927c83312 Implement context-specific verification callbacks 2019-04-03 12:53:28 +01:00
Jarno Lamsa
9822c0d2f1 Fix name to function call 2019-04-01 16:59:48 +03:00
Hanno Becker
afd0b0a1a7 Make use of CA callback if present when verifying peer CRT chain 2019-03-28 16:13:43 +00:00
Hanno Becker
5adaad9846 Add X.509 CA callback to SSL configuration and implement setter API 2019-03-28 16:13:43 +00:00
Hanno Becker
84d9d2734f Fix unused variable warning in ssl_parse_certificate_coordinate()
This was triggered in client-only builds.
2019-03-01 08:10:46 +00:00
Hanno Becker
353a6f0d50 Fix typo in documentation of ssl_parse_certificate_chain() 2019-02-26 14:38:09 +00:00
Hanno Becker
accc5998ae Set peer CRT length only after successful allocation 2019-02-26 14:38:09 +00:00
Hanno Becker
3acc9b9042 Remove question in comment about verify flags on cli vs. server 2019-02-26 14:38:09 +00:00
Hanno Becker
6b8fbab290 Free peer CRT chain immediately after verifying it
If we don't need to store the peer's CRT chain permanently, we may
free it immediately after verifying it. Moreover, since we parse the
CRT chain in-place from the input buffer in this case, pointers from
the CRT structure remain valid after freeing the structure, and we
use that to extract the digest and pubkey from the CRT after freeing
the structure.
2019-02-26 14:38:09 +00:00
Hanno Becker
0056eab3cd Parse peer's CRT chain in-place from the input buffer 2019-02-26 14:38:09 +00:00
Hanno Becker
b9d4479080 Correct compile-time guards for ssl_clear_peer_cert()
It is used in `mbedtls_ssl_session_free()` under
`MBEDTLS_X509_CRT_PARSE_C`, but defined only if
`MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED`.

Issue #2422 tracks the use of
`MBEDTLS_KEY_EXCHANGE__WITH_CERT_ENABLED` instead of
`MBEDTLS_X509_CRT_PARSE_C` for code and fields
related to CRT-based ciphersuites.
2019-02-26 14:38:09 +00:00
Hanno Becker
e68245750a Guard mbedtls_ssl_get_peer_cert() by new compile-time option 2019-02-26 14:38:09 +00:00
Hanno Becker
b6c5eca2d5 Adapt mbedtls_ssl_parse_certificate() to removal of peer_cert field 2019-02-26 14:38:09 +00:00
Hanno Becker
13c327d500 Adapt ssl_clear_peer_cert() to removal of peer_cert field 2019-02-26 14:38:09 +00:00
Hanno Becker
6d1986e6f5 Adapt mbedtls_ssl_session_copy() to removal of peer_cert field 2019-02-26 14:38:09 +00:00
Hanno Becker
a27475335a Make a copy of peer's raw public key after verifying its CRT chain
This commit modifies `mbedtls_ssl_parse_certificate()` to store a
copy of the peer's public key after parsing and verifying the peer's
CRT chain.

So far, this leads to heavy memory duplication: We have the CRT chain
in the I/O buffer, then parse (and, thereby, copy) it to a
`mbedtls_x509_crt` structure, and then make another copy of the
peer's public key, plus the overhead from the MPI and ECP structures.

This inefficiency will soon go away to a significant extend, because:
- Another PR adds functionality to parse CRTs without taking
  ownership of the input buffers. Applying this here will allow
  parsing and verifying the peer's chain without making an additional
  raw copy. The overhead reduces to the size of `mbedtls_x509_crt`,
  the public key, and the DN structures referenced in the CRT.
- Once copyless parsing is in place and the removal of the peer CRT
  is fully implemented, we can extract the public key bounds from
  the parsed certificate and then free the entire chain before
  parsing the public key again. This means that we never store
  the parsed public key twice at the same time.
2019-02-26 14:38:09 +00:00
Hanno Becker
75173121fe Add field for peer's raw public key to TLS handshake param structure
When removing the (session-local) copy of the peer's CRT chain, we must
keep a handshake-local copy of the peer's public key, as (naturally) every
key exchange will make use of that public key at some point to verify that
the peer actually owns the corresponding private key (e.g., verify signatures
from ServerKeyExchange or CertificateVerify, or encrypt a PMS in a RSA-based
exchange, or extract static (EC)DH parameters).

This commit adds a PK context field `peer_pubkey` to the handshake parameter
structure `mbedtls_handshake_params_init()` and adapts the init and free
functions accordingly. It does not yet make actual use of the new field.
2019-02-26 14:38:09 +00:00
Hanno Becker
3dad311ef0 Parse and verify peer CRT chain in local variable
`mbedtls_ssl_parse_certificate()` parses the peer's certificate chain
directly into the `peer_cert` field of the `mbedtls_ssl_session`
structure being established. To allow to optionally remove this field
from the session structure, this commit changes this to parse the peer's
chain into a local variable instead first, which can then either be freed
after CRT verification - in case the chain should not be stored - or
mapped to the `peer_cert` if it should be kept. For now, only the latter
is implemented.
2019-02-26 14:38:09 +00:00
Hanno Becker
177475a3aa Mitigate triple handshake attack by comparing digests only
This paves the way for the removal of the peer CRT chain from
`mbedtls_ssl_session`.
2019-02-26 14:38:09 +00:00
Hanno Becker
6bbd94c4eb Compute digest of peer's end-CRT in mbedtls_ssl_parse_certificate() 2019-02-26 14:38:09 +00:00
Hanno Becker
9198ad1101 Extend mbedtls_ssl_session by buffer holding peer CRT digest 2019-02-26 14:38:09 +00:00
Hanno Becker
52055ae91f Give ssl_session_copy() external linkage
A subsequent commit will need this function in the session ticket
and session cache implementations. As the latter are server-side,
this commit also removes the MBEDTLS_SSL_CLI_C guard.

For now, the function is declared in ssl_internal.h and hence not
part of the public API.
2019-02-26 14:38:09 +00:00
Hanno Becker
c7bd780e02 Allow passing any X.509 CRT chain to ssl_parse_certificate_chain()
This commit modifies the helper `ssl_parse_certificate_chain()` to
accep any target X.509 CRT chain instead of hardcoding it to
`session_negotiate->peer_cert`. This increases modularity and paves
the way towards removing `mbedtls_ssl_session::peer_cert`.
2019-02-26 14:38:09 +00:00
Hanno Becker
6863619a2f Introduce helper function for peer CRT chain verification 2019-02-26 14:38:09 +00:00
Hanno Becker
fcd9e71cdf Don't progress TLS state machine on peer CRT chain parsing error 2019-02-26 14:38:09 +00:00
Hanno Becker
28f2fcd08d Add helper function to check whether a CRT msg is expected
This commit adds a helper function `ssl_parse_certificate_coordinate()`
which checks whether a `Certificate` message is expected from the peer.

The logic is the following:
- For ciphersuites which don't use server-side CRTs, no Certificate
  message is expected (neither for the server, nor the client).
- On the server, no client certificate is expected in the following cases:
  * The server server didn't request a Certificate, which is controlled
    by the `authmode` setting.
  * A RSA-PSK suite is used; this is the only suite using server CRTs
    but not allowing client-side authentication.
2019-02-26 14:38:09 +00:00
Hanno Becker
7177a88a36 Introduce helper function to determine whether suite uses server CRT
This commit introduces a static helper function

   `mbedtls_ssl_ciphersuite_uses_srv_cert()`

which determines whether a ciphersuite may make use of server-side CRTs.

This function is in turn uses in `mbedtls_ssl_parse_certificate()` to
skip certificate parsing for ciphersuites which don't involve CRTs.

Note: Ciphersuites not using server-side CRTs don't allow client-side CRTs
either, so it is safe to guard `mbedtls_ssl_{parse/write}_certificate()`
this way.

Note: Previously, the code uses a positive check over the suites

- MBEDTLS_KEY_EXCHANGE_PSK
- MBEDTLS_KEY_EXCHANGE_DHE_PSK
- MBEDTLS_KEY_EXCHANGE_ECDHE_PSK
- MBEDTLS_KEY_EXCHANGE_ECJPAKE,

while now, it uses a negative check over `mbedtls_ssl_ciphersuite_uses_srv_cert()`,
which checks for the suites

- MBEDTLS_KEY_EXCHANGE_RSA
- MBEDTLS_KEY_EXCHANGE_RSA_PSK
- MBEDTLS_KEY_EXCHANGE_DHE_RSA
- MBEDTLS_KEY_EXCHANGE_ECDH_RSA
- MBEDTLS_KEY_EXCHANGE_ECDHE_RSA
- MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA
- MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA

This is equivalent since, together, those are all ciphersuites.
Quoting ssl_ciphersuites.h:

```
typedef enum {
    MBEDTLS_KEY_EXCHANGE_NONE = 0,
    MBEDTLS_KEY_EXCHANGE_RSA,
    MBEDTLS_KEY_EXCHANGE_DHE_RSA,
    MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
    MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
    MBEDTLS_KEY_EXCHANGE_PSK,
    MBEDTLS_KEY_EXCHANGE_DHE_PSK,
    MBEDTLS_KEY_EXCHANGE_RSA_PSK,
    MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
    MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
    MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
    MBEDTLS_KEY_EXCHANGE_ECJPAKE,
} mbedtls_key_exchange_type_t;
```
2019-02-26 14:38:09 +00:00
Hanno Becker
2148993900 Use helper macro to detect whether some ciphersuite uses CRTs 2019-02-26 14:38:09 +00:00
Hanno Becker
6bdfab2ccc Unify state machine update in mbedtls_ssl_parse_certificate()
The handler `mbedtls_ssl_parse_certificate()` for incoming `Certificate`
messages contains many branches updating the handshake state. For easier
reasoning about state evolution, this commit introduces a single code-path
updating the state machine at the end of `mbedtls_ssl_parse_certificate()`.
2019-02-26 14:38:09 +00:00
Hanno Becker
7a955a043e Clear peer's CRT chain outside before parsing new one
If an attempt for session resumption fails, the `session_negotiate` structure
might be partially filled, and in particular already contain a peer certificate
structure. This certificate structure needs to be freed before parsing the
certificate sent in the `Certificate` message.

This commit moves the code-path taking care of this from the helper
function `ssl_parse_certificate_chain()`, whose purpose should be parsing
only, to the top-level handler `mbedtls_ssl_parse_certificate()`.

The fact that we don't know the state of `ssl->session_negotiate` after
a failed attempt for session resumption is undesirable, and a separate
issue #2414 has been opened to improve on this.
2019-02-26 14:38:09 +00:00
Hanno Becker
4a55f638e2 Introduce helper to check for no-CRT notification from client
This commit introduces a server-side static helper function
`ssl_srv_check_client_no_crt_notification()`, which checks if
the message we received during the incoming certificate state
notifies the server of the lack of certificate on the client.

For SSLv3, such a notification comes as a specific alert,
while for all other TLS versions, it comes as a `Certificate`
handshake message with an empty CRT list.
2019-02-26 14:38:09 +00:00
Hanno Becker
a028c5bbd8 Introduce CRT counter to CRT chain parsing function
So far, we've used the `peer_cert` pointer to detect whether
we're parsing the first CRT, but that will soon be removed
if `MBEDTLS_SSL_KEEP_PEER_CERTIFICATE` is unset.
2019-02-26 14:38:09 +00:00
Hanno Becker
1294a0b260 Introduce helper function to clear peer CRT from session structure
This commit introduces a helper function `ssl_clear_peer_cert()`
which frees all data related to the peer's certificate from an
`mbedtls_ssl_session` structure. Currently, this is the peer's
certificate itself, while eventually, it'll be its digest only.
2019-02-26 14:38:09 +00:00
Hanno Becker
f852b1c035 Break overly long line in definition of mbedtls_ssl_get_session() 2019-02-26 14:38:09 +00:00
Hanno Becker
60848e6574 Don't reuse CRT from initial handshake during renegotiation
After mitigating the 'triple handshake attack' by checking that
the peer's end-CRT didn't change during renegotation, the current
code avoids re-parsing the CRT by moving the CRT-pointer from the
old session to the new one. While efficient, this will no longer
work once only the hash of the peer's CRT is stored beyond the
handshake.

This commit removes the code-path moving the old CRT, and instead
frees the entire peer CRT chain from the initial handshake as soon
as the 'triple handshake attack' protection has completed.
2019-02-26 14:38:09 +00:00
Jaeden Amero
86016a03a1 Merge remote-tracking branch 'origin/pr/2338' into development 2019-02-22 12:55:30 +00:00
Jaeden Amero
461bd3dcca Merge remote-tracking branch 'origin/pr/2454' into development 2019-02-22 10:32:44 +00:00
Jaeden Amero
9f47f82218 Merge remote-tracking branch 'origin/pr/2391' into development 2019-02-22 10:32:44 +00:00
Jaeden Amero
3497323f79 Initialize PSA Crypto operation contexts
It is now required to initialize PSA Crypto operation contexts before
calling psa_*_setup(). Otherwise, one gets a PSA_ERROR_BAD_STATE error.
2019-02-20 10:58:55 +00:00
Hanno Becker
4a63ed421c Implement ClientKeyExchange writing in PSA-based ECDHE suites
- Populate the ECDH private key slot with a fresh private EC key
  designated for the correct algorithm.
- Export the public part of the ECDH private key from PSA and
  reformat it to suite the format of the ClientKeyExchange message.
- Perform the PSA-based ECDH key agreement and store the result
  as the premaster secret for the connection.
2019-02-18 16:42:01 +00:00
Hanno Becker
46f34d0ac0 Fix style issue and wording 2019-02-08 14:26:41 +00:00
Hanno Becker
c1e18bdf06 Fix memory leak 2019-02-08 14:26:41 +00:00