Commit Graph

74 Commits

Author SHA1 Message Date
Tomas Mraz
38b051a1fe SSL object refactoring using SSL_CONNECTION object
Make the SSL object polymorphic based on whether this is
a traditional SSL connection, QUIC connection, or later
to be implemented a QUIC stream.

It requires adding if after every SSL_CONNECTION_FROM_SSL() call
which itself has to be added to almost every public SSL_ API call.

Reviewed-by: Richard Levitte <levitte@openssl.org>
Reviewed-by: Hugo Landau <hlandau@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/18612)
2022-07-28 10:04:28 +01:00
Matt Caswell
fecb3aae22 Update copyright year
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Release: yes
2022-05-03 13:34:51 +01:00
Bernd Edlinger
e915c3f538 Fix an assertion in the DTLS server code
This fixes an internal error alert from the server and
an unexpected connection failure in the release version,
but a failed assertion and a server crash in the
debug version.

Reproduce this issue with a DTLS server/client like that:

./openssl s_server -dtls -mtu 1500
./openssl s_client -dtls -maxfraglen 512

In the debug version a crash happens in the Server now:

./openssl s_server -dtls -mtu 1500
Using default temp DH parameters
ACCEPT
ssl/statem/statem_dtls.c:269: OpenSSL internal error: Assertion failed: len == written
Aborted (core dumped)

While in the release version the handshake exceeds the
negotiated max fragment size, and fails because of this:

$ ./openssl s_server -dtls -mtu 1500
Using default temp DH parameters
ACCEPT
ERROR
4057152ADA7F0000:error:0A0000C2:SSL routines:do_dtls1_write:exceeds max fragment size:ssl/record/rec_layer_d1.c:826:
shutting down SSL
CONNECTION CLOSED

From the client's point of view the connection fails
with an Internal Error Alert:

$ ./openssl s_client -dtls -maxfraglen 512
Connecting to ::1
CONNECTED(00000003)
40B76343377F0000:error:0A000438:SSL routines:dtls1_read_bytes:tlsv1 alert internal error:ssl/record/rec_layer_d1.c:613:SSL alert number 80

and now the connection attempt fails unexpectedly.

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/18093)
2022-04-14 16:16:47 +02:00
Tomas Mraz
ed576acdf5 Rename all getters to use get/get0 in name
For functions that exist in 1.1.1 provide a simple aliases via #define.

Fixes #15236

Functions with OSSL_DECODER_, OSSL_ENCODER_, OSSL_STORE_LOADER_,
EVP_KEYEXCH_, EVP_KEM_, EVP_ASYM_CIPHER_, EVP_SIGNATURE_,
EVP_KEYMGMT_, EVP_RAND_, EVP_MAC_, EVP_KDF_, EVP_PKEY_,
EVP_MD_, and EVP_CIPHER_ prefixes are renamed.

Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15405)
2021-06-01 12:40:00 +02:00
Matt Caswell
f42e68dc47 Defer Finished MAC handling until after state transition
In TLS we process received messages like this:

1) Read Message Header
2) Validate and transition state based on received message type
3) Read Message Body
4) Process Message

In DTLS we read messages like this:

1) Read Message Header and Body
2) Validate and transition state based on received message type
3) Process Message

The difference is because of the stream vs datagram semantics of the
underlying transport.

In both TLS and DTLS we were doing finished MAC processing as part of
reading the message body. This means that in DTLS this was occurring
*before* the state transition has been validated. A crash was occurring
in DTLS if a Finished message was sent in an invalid state due to
assumptions in the code that certain variables would have been setup by
the time a Finished message arrives.

To avoid this problem we shift the finished MAC processing to be after
the state transition in DTLS.

Thanks to github user @bathooman for reporting this issue.

Fixes #14906

Reviewed-by: Paul Dale <pauli@openssl.org>
Reviewed-by: Tim Hudson <tjh@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/14930)
2021-04-28 16:23:08 +01:00
Matt Caswell
f5afac4bda Update copyright year
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/14986)
2021-04-22 14:38:44 +01:00
Rich Salz
f6c95e46c0 Add "origin" field to EVP_CIPHER, EVP_MD
Add a "where did this EVP_{CIPHER,MD} come from" flag: global, via fetch,
or via EVP_{CIPHER,MD}_meth_new.  Update EVP_{CIPHER,MD}_free to handle all
three origins. The flag is deliberately right before some function pointers,
so that compile-time failures (int/pointer) will occur, as opposed to
taking a bit in the existing "flags" field.  The "global variable" flag
is non-zero, so the default case of using OPENSSL_zalloc (for provider
ciphers), will do the right thing. Ref-counting is a no-op for
Make up_ref no-op for global MD and CIPHER objects

Deprecate EVP_MD_CTX_md().  Added EVP_MD_CTX_get0_md() (same semantics as
the deprecated function) and EVP_MD_CTX_get1_md().  Likewise, deprecate
EVP_CIPHER_CTX_cipher() in favor of EVP_CIPHER_CTX_get0_cipher(), and add
EVP_CIPHER_CTX_get1_CIPHER().

Refactor EVP_MD_free() and EVP_MD_meth_free() to call new common
evp_md_free_int() function.
Refactor EVP_CIPHER_free() and EVP_CIPHER_meth_free() to call new common
evp_cipher_free_int() function.

Also change some flags tests to explicit test == or != zero. E.g.,
        if (flags & x) --> if ((flags & x) != 0)
        if (!(flags & x)) --> if ((flags & x) == 0)
Only done for those lines where "get0_cipher" calls were made.

Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/14193)
2021-04-18 10:03:07 +02:00
Richard Levitte
c48ffbcca1 SSL: refactor all SSLfatal() calls
Since SSLfatal() doesn't take a function code any more, we drop that
argument everywhere.  Also, we convert all combinations of SSLfatal()
and ERR_add_data() to an SSLfatal_data() call.

Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/13316)
2020-11-11 12:12:23 +01:00
Richard Levitte
6849b73ccc Convert all {NAME}err() in ssl/ to their corresponding ERR_raise() call
This was done using util/err-to-raise

Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/13316)
2020-11-11 12:12:11 +01:00
Matt Caswell
eec0ad10b9 Update copyright year
Reviewed-by: Nicola Tuveri <nic.tuv@gmail.com>
(Merged from https://github.com/openssl/openssl/pull/13144)
2020-10-15 14:10:06 +01:00
Pauli
48ff651ecc DTLS: free allocated memory on error paths
Reviewed-by: Richard Levitte <levitte@openssl.org>
Reviewed-by: Kurt Roeckx <kurt@roeckx.be>
(Merged from https://github.com/openssl/openssl/pull/12870)
2020-09-16 07:22:43 +10:00
Dr. Matthias St. Pierre
706457b7bd Reorganize local header files
Apart from public and internal header files, there is a third type called
local header files, which are located next to source files in the source
directory. Currently, they have different suffixes like

  '*_lcl.h', '*_local.h', or '*_int.h'

This commit changes the different suffixes to '*_local.h' uniformly.

Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/9333)
2019-09-28 20:26:35 +02:00
Todd Short
555cbb328e Collapse ssl3_state_st (s3) into ssl_st
With the removal of SSLv2, the s3 structure is always allocated, so
there is little point in having it be an allocated pointer. Collapse
the ssl3_state_st structure into ssl_st and fixup any references.

This should be faster than going through an indirection and due to
fewer allocations, but I'm not seeing any significant performance
improvement; it seems to be within the margin of error in timing.

Reviewed-by: Paul Yang <yang.yang@baishancloud.com>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/7888)
2019-04-29 17:26:09 +01:00
Richard Levitte
2c18d164f5 Following the license change, modify the boilerplates in ssl/
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/7768)
2018-12-06 14:20:59 +01:00
Matt Caswell
a925e7dbf4 Don't memcpy the contents of an empty fragment
In DTLS if we have buffered a fragment for a zero length message (e.g.
ServerHelloDone) then, when we unbuffered the fragment, we were attempting
to memcpy the contents of the fragment which is zero length and a NULL
pointer. This is undefined behaviour. We should check first whether we
have a zero length fragment.

Fixes a travis issue.

[extended tests]

Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/6223)
2018-05-12 09:59:02 +01:00
Rich Salz
cdb10bae3f Set error code on alloc failures
Almost all *alloc failures now set an error code.

Reviewed-by: Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com>
(Merged from https://github.com/openssl/openssl/pull/5842)
2018-04-03 11:31:16 -04:00
Matt Caswell
2e92af5ea5 Check for alerts while waiting for a dry event
At a couple of points in a DTLS/SCTP handshake we need to wait for a dry
event before continuing. However if an alert has been sent by the peer
then we will never receive that dry event and an infinite loop results.

This commit changes things so that we attempt to read a message if we
are waiting for a dry event but haven't got one yet. This should never
succeed, but any alerts will be processed.

Fixes #4763

Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/5084)
2018-03-21 10:27:29 +00:00
Matt Caswell
6738bf1417 Update copyright year
Reviewed-by: Richard Levitte <levitte@openssl.org>
2018-02-13 13:59:25 +00:00
Matt Caswell
5d67110173 Don't calculate the Finished MAC twice
In <= TLSv1.2 a Finished message always comes immediately after a CCS
except in the case of NPN where there is an additional message between
the CCS and Finished. Historically we always calculated the Finished MAC
when we processed the CCS. However to deal with NPN we also calculated it
when we receive the Finished message. Really this should only have been
done if we hand negotiated NPN.

This simplifies the code to only calculate the MAC when we receive the
Finished. In 1.1.1 we need to do it this way anyway because there is no
CCS (except in middlebox compat mode) in TLSv1.3.

Coincidentally, this commit also fixes the fact that no-nextprotoneg does
not currently work in master.

Reviewed-by: Andy Polyakov <appro@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/5285)
2018-02-09 15:27:32 +00:00
Matt Caswell
c285338293 More record layer conversions to use SSLfatal()
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4841)
2017-12-08 16:42:02 +00:00
Matt Caswell
d273b60b41 Convert more functions in ssl/statem/statem_dtls.c to use SSLfatal()
Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4778)
2017-12-04 13:31:48 +00:00
Matt Caswell
a2c2e00050 Convert remaining functions in statem_clnt.c to use SSLfatal()
Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4778)
2017-12-04 13:31:48 +00:00
Matt Caswell
67dc995eaf Move ossl_assert
Move the definition of ossl_assert() out of e_os.h which is intended for OS
specific things. Instead it is moved into internal/cryptlib.h.

This also changes the definition to remove the (int) cast.

Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4073)
2017-08-03 10:48:00 +01:00
Matt Caswell
380a522f68 Replace instances of OPENSSL_assert() with soft asserts in libssl
Reviewed-by: Tim Hudson <tjh@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/3496)
2017-05-22 14:00:19 +01:00
Matt Caswell
fb34a0f4e0 Try to be more consistent about the alerts we send
We are quite inconsistent about which alerts get sent. Specifically, these
alerts should be used (normally) in the following circumstances:

SSL_AD_DECODE_ERROR = The peer sent a syntactically incorrect message
SSL_AD_ILLEGAL_PARAMETER = The peer sent a message which was syntactically
correct, but a parameter given is invalid for the context
SSL_AD_HANDSHAKE_FAILURE = The peer's messages were syntactically and
semantically correct, but the parameters provided were unacceptable to us
(e.g. because we do not support the requested parameters)
SSL_AD_INTERNAL_ERROR = We messed up (e.g. malloc failure)

The standards themselves aren't always consistent but I think the above
represents the best interpretation.

Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/3480)
2017-05-19 08:47:08 +01:00
Matt Caswell
aefb925647 Don't attempt to send fragments > max_send_fragment in DTLS
We were allocating the write buffer based on the size of max_send_fragment,
but ignoring it when writing data. We should fragment handshake messages
if they exceed max_send_fragment and reject application data writes that
are too large.

Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/3286)
2017-04-25 11:13:39 +01:00
Matt Caswell
1f5b44e943 Miscellaneous style tweaks based on feedback received
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/2259)
2017-01-30 10:18:23 +00:00
Matt Caswell
c7f47786a5 Move state machine knowledge out of the record layer
The record layer was making decisions that should really be left to the
state machine around unexpected handshake messages that are received after
the initial handshake (i.e. renegotiation related messages). This commit
removes that code from the record layer and updates the state machine
accordingly. This simplifies the state machine and paves the way for
handling other messages post-handshake such as the NewSessionTicket in
TLSv1.3.

Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/2259)
2017-01-30 10:17:00 +00:00
FdaSilvaYY
0fe2a0af89 Fix a few double ;
Reviewed-by: Rich Salz <rsalz@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/1618)
2017-01-25 09:06:34 +00:00
Richard Levitte
e72040c1dc Remove heartbeat support
Reviewed-by: Rich Salz <rsalz@openssl.org>
Reviewed-by: Tim Hudson <tjh@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/1669)
2016-11-13 16:24:02 -05:00
Matt Caswell
54105ddd23 Rename all "read" variables with "readbytes"
Travis is reporting one file at a time shadowed variable warnings where
"read" has been used. This attempts to go through all of libssl and replace
"read" with "readbytes" to fix all the problems in one go.

Reviewed-by: Rich Salz <rsalz@openssl.org>
2016-11-04 12:09:46 +00:00
Matt Caswell
348240c676 Fix misc size_t issues causing Windows warnings in 64 bit
Reviewed-by: Rich Salz <rsalz@openssl.org>
2016-11-04 12:09:46 +00:00
Matt Caswell
e3c9727fec Resolve some outstanding size_t related TODOs
Reviewed-by: Rich Salz <rsalz@openssl.org>
2016-11-04 12:09:45 +00:00
Matt Caswell
d736bc1a7d Update misc function params in libssl for size_t
Reviewed-by: Rich Salz <rsalz@openssl.org>
2016-11-04 12:09:45 +00:00
Matt Caswell
7ee8627f6e Convert libssl writing for size_t
Reviewed-by: Rich Salz <rsalz@openssl.org>
2016-11-04 12:09:45 +00:00
Matt Caswell
eda757514e Further libssl size_t-ify of reading
Writing still to be done

Reviewed-by: Rich Salz <rsalz@openssl.org>
2016-11-04 12:09:45 +00:00
Matt Caswell
4a01c59f36 Harmonise setting the header and closing construction
Ensure all message types work the same way including CCS so that the state
machine doesn't need to know about special cases. Put all the special logic
into ssl_set_handshake_header() and ssl_close_construct_packet().

Reviewed-by: Rich Salz <rsalz@openssl.org>
2016-10-03 16:25:48 +01:00
Matt Caswell
7cea05dcc7 Move init of the WPACKET into write_state_machine()
Instead of initialising, finishing and cleaning up the WPACKET in every
message construction function, we should do it once in
write_state_machine().

Reviewed-by: Rich Salz <rsalz@openssl.org>
2016-10-03 16:25:48 +01:00
Matt Caswell
a29fa98ceb Rename ssl_set_handshake_header2()
ssl_set_handshake_header2() was only ever a temporary name while we had
to have ssl_set_handshake_header() for code that hadn't been converted to
WPACKET yet. No code remains that needed that so we can rename it.

Reviewed-by: Rich Salz <rsalz@openssl.org>
2016-10-02 20:25:57 +01:00
Matt Caswell
48c054fec3 Excessive allocation of memory in dtls1_preprocess_fragment()
This issue is very similar to CVE-2016-6307 described in the previous
commit. The underlying defect is different but the security analysis and
impacts are the same except that it impacts DTLS.

A DTLS message includes 3 bytes for its length in the header for the
message.
This would allow for messages up to 16Mb in length. Messages of this length
are excessive and OpenSSL includes a check to ensure that a peer is sending
reasonably sized messages in order to avoid too much memory being consumed
to service a connection. A flaw in the logic of version 1.1.0 means that
memory for the message is allocated too early, prior to the excessive
message length check. Due to way memory is allocated in OpenSSL this could
mean an attacker could force up to 21Mb to be allocated to service a
connection. This could lead to a Denial of Service through memory
exhaustion. However, the excessive message length check still takes place,
and this would cause the connection to immediately fail. Assuming that the
application calls SSL_free() on the failed conneciton in a timely manner
then the 21Mb of allocated memory will then be immediately freed again.
Therefore the excessive memory allocation will be transitory in nature.
This then means that there is only a security impact if:

1) The application does not call SSL_free() in a timely manner in the
event that the connection fails
or
2) The application is working in a constrained environment where there
is very little free memory
or
3) The attacker initiates multiple connection attempts such that there
are multiple connections in a state where memory has been allocated for
the connection; SSL_free() has not yet been called; and there is
insufficient memory to service the multiple requests.

Except in the instance of (1) above any Denial Of Service is likely to
be transitory because as soon as the connection fails the memory is
subsequently freed again in the SSL_free() call. However there is an
increased risk during this period of application crashes due to the lack
of memory - which would then mean a more serious Denial of Service.

This issue does not affect TLS users.

Issue was reported by Shi Lei (Gear Team, Qihoo 360 Inc.).

CVE-2016-6308

Reviewed-by: Richard Levitte <levitte@openssl.org>
2016-09-21 20:37:53 +01:00
Matt Caswell
3c10632529 make update and fix some associated mis-matched error codes
Reviewed-by: Richard Levitte <levitte@openssl.org>
2016-09-21 14:31:30 +01:00
Matt Caswell
08029dfa03 Convert WPACKET_put_bytes to use convenience macros
All the other functions that take an argument for the number of bytes
use convenience macros for this purpose. We should do the same with
WPACKET_put_bytes().

Reviewed-by: Rich Salz <rsalz@openssl.org>
2016-09-20 14:47:44 +01:00
Matt Caswell
85a7a5e6ef Convert CCS construction to WPACKET
Reviewed-by: Rich Salz <rsalz@openssl.org>
2016-09-20 14:17:50 +01:00
Matt Caswell
f1ec23c0bc Convert CKE construction to use the WPACKET API
Reviewed-by: Rich Salz <rsalz@openssl.org>
2016-09-14 00:02:34 +01:00
Matt Caswell
c0f9e23c6b Fix a few style nits in the wpacket code
Addressing more feedback comments.

Reviewed-by: Rich Salz <rsalz@openssl.org>
2016-09-13 09:41:21 +01:00
Matt Caswell
de451856f0 Address WPACKET review comments
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>
2016-09-13 09:41:21 +01:00
Matt Caswell
0217dd19c0 Move from explicit sub-packets to implicit ones
No need to declare an explicit sub-packet. Just start one.

Reviewed-by: Rich Salz <rsalz@openssl.org>
2016-09-13 09:41:21 +01:00
Matt Caswell
ae2f7b37da Rename PACKETW to WPACKET
To avoid confusion with the read PACKET structure.

Reviewed-by: Rich Salz <rsalz@openssl.org>
2016-09-13 09:41:21 +01:00
Matt Caswell
2c7b4dbc1a Convert tls_construct_client_hello() to use PACKETW
Reviewed-by: Rich Salz <rsalz@openssl.org>
2016-09-13 09:41:21 +01:00
Matt Caswell
f5c7f5dfba Fix DTLS buffered message DoS attack
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>
2016-08-22 10:53:55 +01:00