A few style tweaks here and there. The main change is that curr and
packet_len are now offsets into the buffer to account for the fact that
the pointers can change if the buffer grows. Also dropped support for the
WPACKET_set_packet_len() function. I thought that was going to be needed
but so far it hasn't been. It doesn't really work any more due to the
offsets change.
Reviewed-by: Rich Salz <rsalz@openssl.org>
The function tls_construct_cert_status() is called by both TLS and DTLS
code. However it only ever constructed a TLS message header for the message
which obviously failed in DTLS.
Reviewed-by: Rich Salz <rsalz@openssl.org>
DTLS can handle out of order record delivery. Additionally since
handshake messages can be bigger than will fit into a single packet, the
messages can be fragmented across multiple records (as with normal TLS).
That means that the messages can arrive mixed up, and we have to
reassemble them. We keep a queue of buffered messages that are "from the
future", i.e. messages we're not ready to deal with yet but have arrived
early. The messages held there may not be full yet - they could be one
or more fragments that are still in the process of being reassembled.
The code assumes that we will eventually complete the reassembly and
when that occurs the complete message is removed from the queue at the
point that we need to use it.
However, DTLS is also tolerant of packet loss. To get around that DTLS
messages can be retransmitted. If we receive a full (non-fragmented)
message from the peer after previously having received a fragment of
that message, then we ignore the message in the queue and just use the
non-fragmented version. At that point the queued message will never get
removed.
Additionally the peer could send "future" messages that we never get to
in order to complete the handshake. Each message has a sequence number
(starting from 0). We will accept a message fragment for the current
message sequence number, or for any sequence up to 10 into the future.
However if the Finished message has a sequence number of 2, anything
greater than that in the queue is just left there.
So, in those two ways we can end up with "orphaned" data in the queue
that will never get removed - except when the connection is closed. At
that point all the queues are flushed.
An attacker could seek to exploit this by filling up the queues with
lots of large messages that are never going to be used in order to
attempt a DoS by memory exhaustion.
I will assume that we are only concerned with servers here. It does not
seem reasonable to be concerned about a memory exhaustion attack on a
client. They are unlikely to process enough connections for this to be
an issue.
A "long" handshake with many messages might be 5 messages long (in the
incoming direction), e.g. ClientHello, Certificate, ClientKeyExchange,
CertificateVerify, Finished. So this would be message sequence numbers 0
to 4. Additionally we can buffer up to 10 messages in the future.
Therefore the maximum number of messages that an attacker could send
that could get orphaned would typically be 15.
The maximum size that a DTLS message is allowed to be is defined by
max_cert_list, which by default is 100k. Therefore the maximum amount of
"orphaned" memory per connection is 1500k.
Message sequence numbers get reset after the Finished message, so
renegotiation will not extend the maximum number of messages that can be
orphaned per connection.
As noted above, the queues do get cleared when the connection is closed.
Therefore in order to mount an effective attack, an attacker would have
to open many simultaneous connections.
Issue reported by Quan Luo.
CVE-2016-2179
Reviewed-by: Richard Levitte <levitte@openssl.org>
Run util/openssl-format-source on ssl/
Some comments and hand-formatted tables were fixed up
manually by disabling auto-formatting.
Reviewed-by: Rich Salz <rsalz@openssl.org>
When handling ECDH check to see if the curve is "custom" (X25519 is
currently the only curve of this type) and instead of setting a curve
NID just allocate a key of appropriate type.
Reviewed-by: Rich Salz <rsalz@openssl.org>
DTLSv1_client_method() is deprecated, but it was the only way to obtain
DTLS1_BAD_VER support. The SSL_OP_CISCO_ANYCONNECT hack doesn't work with
DTLS_client_method(), and it's relatively non-trivial to make it work without
expanding the hack into lots of places.
So deprecate SSL_OP_CISCO_ANYCONNECT with DTLSv1_client_method(), and make
it work with SSL_CTX_set_{min,max}_proto_version(DTLS1_BAD_VER) instead.
Reviewed-by: Rich Salz <rsalz@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
The Change Cipher Spec message in this ancient pre-standard version of DTLS
that Cisco are unfortunately still using in their products, is 3 bytes.
Allow it.
Reviewed-by: Rich Salz <rsalz@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
This is adapted from BoringSSL commit 2f87112b963.
This fixes a number of bugs where the existence of bbio was leaked in the
public API and broke things.
- SSL_get_wbio returned the bbio during the handshake. It must always return
the BIO the consumer configured. In doing so, some internal accesses of
SSL_get_wbio should be switched to ssl->wbio since those want to see bbio.
- The logic in SSL_set_rfd, etc. (which I doubt is quite right since
SSL_set_bio's lifetime is unclear) would get confused once wbio got
wrapped. Those want to compare to SSL_get_wbio.
- If SSL_set_bio was called mid-handshake, bbio would get disconnected and
lose state. It forgets to reattach the bbio afterwards. Unfortunately,
Conscrypt does this a lot. It just never ended up calling it at a point
where the bbio would cause problems.
- Make more explicit the invariant that any bbio's which exist are always
attached. Simplify a few things as part of that.
RT#4572
Reviewed-by: Richard Levitte <levitte@openssl.org>
Fix some indentation at the same time
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/1292)
- Always process ALPN (previously there was an early return in the
certificate status handling)
- Don't send a duplicate alert. Previously, both
ssl_check_clienthello_tlsext_late and its caller would send an
alert. Consolidate alert sending code in the caller.
Reviewed-by: Rich Salz <rsalz@openssl.org>
Continuing from the previous commit. Refactor tls_process_key_exchange() to
split out into a separate function the ECDHE aspects.
Reviewed-by: Richard Levitte <levitte@openssl.org>
Continuing from the previous commit. Refactor tls_process_key_exchange() to
split out into a separate function the DHE aspects.
Reviewed-by: Richard Levitte <levitte@openssl.org>
Continuing from the previous commit. Refactor tls_process_key_exchange() to
split out into a separate function the SRP aspects.
Reviewed-by: Richard Levitte <levitte@openssl.org>
The tls_process_key_exchange() function is too long. This commit starts
the process of splitting it up by moving the PSK preamble code to a
separate function.
Reviewed-by: Richard Levitte <levitte@openssl.org>
The function tls_process_key_exchange() is too long. This commit moves
the PSK preamble processing out to a separate function.
Reviewed-by: Richard Levitte <levitte@openssl.org>
If the SSL_SESS_CACHE_NO_INTERNAL_STORE cache mode is used then we weren't
removing sessions from the external cache, e.g. if an alert occurs the
session is supposed to be automatically removed.
Reviewed-by: Richard Levitte <levitte@openssl.org>
Don't call strncpy with strlen of the source as the length. Don't call
strlen multiple times. Eventually we will want to replace this with a proper
PACKET style handling (but for construction of PACKETs instead of just
reading them as it is now). For now though this is safe because
PSK_MAX_IDENTITY_LEN will always fit into the destination buffer.
This addresses an OCAP Audit issue.
Reviewed-by: Richard Levitte <levitte@openssl.org>
Continuing previous commit to break up the
tls_construct_client_key_exchange() function. This splits out the SRP
code.
Reviewed-by: Richard Levitte <levitte@openssl.org>
Continuing previous commit to break up the
tls_construct_client_key_exchange() function. This splits out the GOST
code.
Reviewed-by: Richard Levitte <levitte@openssl.org>
Continuing previous commit to break up the
tls_construct_client_key_exchange() function. This splits out the ECDHE
code.
Reviewed-by: Richard Levitte <levitte@openssl.org>
Continuing previous commit to break up the
tls_construct_client_key_exchange() function. This splits out the DHE
code.
Reviewed-by: Richard Levitte <levitte@openssl.org>
The tls_construct_client_key_exchange() function is too long. This splits
out the construction of the PSK pre-amble into a separate function as well
as the RSA construction.
Reviewed-by: Richard Levitte <levitte@openssl.org>
Continuing from the previous commits, this splits out the GOST code into
a separate function from the process CKE code.
Reviewed-by: Richard Levitte <levitte@openssl.org>
Continuing from the previous commits, this splits out the ECDHE code into
a separate function from the process CKE code.
Reviewed-by: Richard Levitte <levitte@openssl.org>
Continuing from the previous commit, this splits out the DHE code into
a separate function from the process CKE code.
Reviewed-by: Richard Levitte <levitte@openssl.org>
The tls_process_client_key_exchange() function is far too long. This
splits out the PSK preamble processing, and the RSA processing into
separate functions.
Reviewed-by: Richard Levitte <levitte@openssl.org>