xref: /optee_os/lib/libmbedtls/mbedtls/library/ssl_msg.c (revision 039e02df2716a0ed886b56e1e07b7ac1d8597228)
111fa71b9SJerome Forissier /*
211fa71b9SJerome Forissier  *  Generic SSL/TLS messaging layer functions
311fa71b9SJerome Forissier  *  (record layer + retransmission state machine)
411fa71b9SJerome Forissier  *
57901324dSJerome Forissier  *  Copyright The Mbed TLS Contributors
611fa71b9SJerome Forissier  *  SPDX-License-Identifier: Apache-2.0
711fa71b9SJerome Forissier  *
811fa71b9SJerome Forissier  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
911fa71b9SJerome Forissier  *  not use this file except in compliance with the License.
1011fa71b9SJerome Forissier  *  You may obtain a copy of the License at
1111fa71b9SJerome Forissier  *
1211fa71b9SJerome Forissier  *  http://www.apache.org/licenses/LICENSE-2.0
1311fa71b9SJerome Forissier  *
1411fa71b9SJerome Forissier  *  Unless required by applicable law or agreed to in writing, software
1511fa71b9SJerome Forissier  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
1611fa71b9SJerome Forissier  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1711fa71b9SJerome Forissier  *  See the License for the specific language governing permissions and
1811fa71b9SJerome Forissier  *  limitations under the License.
1911fa71b9SJerome Forissier  */
2011fa71b9SJerome Forissier /*
2111fa71b9SJerome Forissier  *  The SSL 3.0 specification was drafted by Netscape in 1996,
2211fa71b9SJerome Forissier  *  and became an IETF standard in 1999.
2311fa71b9SJerome Forissier  *
2411fa71b9SJerome Forissier  *  http://wp.netscape.com/eng/ssl3/
2511fa71b9SJerome Forissier  *  http://www.ietf.org/rfc/rfc2246.txt
2611fa71b9SJerome Forissier  *  http://www.ietf.org/rfc/rfc4346.txt
2711fa71b9SJerome Forissier  */
2811fa71b9SJerome Forissier 
297901324dSJerome Forissier #include "common.h"
3011fa71b9SJerome Forissier 
3111fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_TLS_C)
3211fa71b9SJerome Forissier 
3311fa71b9SJerome Forissier #if defined(MBEDTLS_PLATFORM_C)
3411fa71b9SJerome Forissier #include "mbedtls/platform.h"
3511fa71b9SJerome Forissier #else
3611fa71b9SJerome Forissier #include <stdlib.h>
3711fa71b9SJerome Forissier #define mbedtls_calloc    calloc
3811fa71b9SJerome Forissier #define mbedtls_free      free
3911fa71b9SJerome Forissier #endif
4011fa71b9SJerome Forissier 
4111fa71b9SJerome Forissier #include "mbedtls/ssl.h"
4211fa71b9SJerome Forissier #include "mbedtls/ssl_internal.h"
4311fa71b9SJerome Forissier #include "mbedtls/debug.h"
4411fa71b9SJerome Forissier #include "mbedtls/error.h"
4511fa71b9SJerome Forissier #include "mbedtls/platform_util.h"
4611fa71b9SJerome Forissier #include "mbedtls/version.h"
47*039e02dfSJerome Forissier #include "constant_time_internal.h"
48*039e02dfSJerome Forissier #include "mbedtls/constant_time.h"
497901324dSJerome Forissier 
5011fa71b9SJerome Forissier #include <string.h>
5111fa71b9SJerome Forissier 
5211fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO)
5311fa71b9SJerome Forissier #include "mbedtls/psa_util.h"
5411fa71b9SJerome Forissier #include "psa/crypto.h"
5511fa71b9SJerome Forissier #endif
5611fa71b9SJerome Forissier 
5711fa71b9SJerome Forissier #if defined(MBEDTLS_X509_CRT_PARSE_C)
5811fa71b9SJerome Forissier #include "mbedtls/oid.h"
5911fa71b9SJerome Forissier #endif
6011fa71b9SJerome Forissier 
6111fa71b9SJerome Forissier static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl );
6211fa71b9SJerome Forissier 
6311fa71b9SJerome Forissier /*
6411fa71b9SJerome Forissier  * Start a timer.
6511fa71b9SJerome Forissier  * Passing millisecs = 0 cancels a running timer.
6611fa71b9SJerome Forissier  */
6711fa71b9SJerome Forissier void mbedtls_ssl_set_timer( mbedtls_ssl_context *ssl, uint32_t millisecs )
6811fa71b9SJerome Forissier {
6911fa71b9SJerome Forissier     if( ssl->f_set_timer == NULL )
7011fa71b9SJerome Forissier         return;
7111fa71b9SJerome Forissier 
7211fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 3, ( "set_timer to %d ms", (int) millisecs ) );
7311fa71b9SJerome Forissier     ssl->f_set_timer( ssl->p_timer, millisecs / 4, millisecs );
7411fa71b9SJerome Forissier }
7511fa71b9SJerome Forissier 
7611fa71b9SJerome Forissier /*
7711fa71b9SJerome Forissier  * Return -1 is timer is expired, 0 if it isn't.
7811fa71b9SJerome Forissier  */
7911fa71b9SJerome Forissier int mbedtls_ssl_check_timer( mbedtls_ssl_context *ssl )
8011fa71b9SJerome Forissier {
8111fa71b9SJerome Forissier     if( ssl->f_get_timer == NULL )
8211fa71b9SJerome Forissier         return( 0 );
8311fa71b9SJerome Forissier 
8411fa71b9SJerome Forissier     if( ssl->f_get_timer( ssl->p_timer ) == 2 )
8511fa71b9SJerome Forissier     {
8611fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 3, ( "timer expired" ) );
8711fa71b9SJerome Forissier         return( -1 );
8811fa71b9SJerome Forissier     }
8911fa71b9SJerome Forissier 
9011fa71b9SJerome Forissier     return( 0 );
9111fa71b9SJerome Forissier }
9211fa71b9SJerome Forissier 
9311fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_RECORD_CHECKING)
94*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
9511fa71b9SJerome Forissier static int ssl_parse_record_header( mbedtls_ssl_context const *ssl,
9611fa71b9SJerome Forissier                                     unsigned char *buf,
9711fa71b9SJerome Forissier                                     size_t len,
9811fa71b9SJerome Forissier                                     mbedtls_record *rec );
9911fa71b9SJerome Forissier 
10011fa71b9SJerome Forissier int mbedtls_ssl_check_record( mbedtls_ssl_context const *ssl,
10111fa71b9SJerome Forissier                               unsigned char *buf,
10211fa71b9SJerome Forissier                               size_t buflen )
10311fa71b9SJerome Forissier {
10411fa71b9SJerome Forissier     int ret = 0;
10511fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 1, ( "=> mbedtls_ssl_check_record" ) );
10611fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_BUF( 3, "record buffer", buf, buflen );
10711fa71b9SJerome Forissier 
10811fa71b9SJerome Forissier     /* We don't support record checking in TLS because
10911fa71b9SJerome Forissier      * (a) there doesn't seem to be a usecase for it, and
11011fa71b9SJerome Forissier      * (b) In SSLv3 and TLS 1.0, CBC record decryption has state
11111fa71b9SJerome Forissier      *     and we'd need to backup the transform here.
11211fa71b9SJerome Forissier      */
11311fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM )
11411fa71b9SJerome Forissier     {
11511fa71b9SJerome Forissier         ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
11611fa71b9SJerome Forissier         goto exit;
11711fa71b9SJerome Forissier     }
11811fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
11911fa71b9SJerome Forissier     else
12011fa71b9SJerome Forissier     {
12111fa71b9SJerome Forissier         mbedtls_record rec;
12211fa71b9SJerome Forissier 
12311fa71b9SJerome Forissier         ret = ssl_parse_record_header( ssl, buf, buflen, &rec );
12411fa71b9SJerome Forissier         if( ret != 0 )
12511fa71b9SJerome Forissier         {
12611fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 3, "ssl_parse_record_header", ret );
12711fa71b9SJerome Forissier             goto exit;
12811fa71b9SJerome Forissier         }
12911fa71b9SJerome Forissier 
13011fa71b9SJerome Forissier         if( ssl->transform_in != NULL )
13111fa71b9SJerome Forissier         {
13211fa71b9SJerome Forissier             ret = mbedtls_ssl_decrypt_buf( ssl, ssl->transform_in, &rec );
13311fa71b9SJerome Forissier             if( ret != 0 )
13411fa71b9SJerome Forissier             {
13511fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_RET( 3, "mbedtls_ssl_decrypt_buf", ret );
13611fa71b9SJerome Forissier                 goto exit;
13711fa71b9SJerome Forissier             }
13811fa71b9SJerome Forissier         }
13911fa71b9SJerome Forissier     }
14011fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
14111fa71b9SJerome Forissier 
14211fa71b9SJerome Forissier exit:
14311fa71b9SJerome Forissier     /* On success, we have decrypted the buffer in-place, so make
14411fa71b9SJerome Forissier      * sure we don't leak any plaintext data. */
14511fa71b9SJerome Forissier     mbedtls_platform_zeroize( buf, buflen );
14611fa71b9SJerome Forissier 
14711fa71b9SJerome Forissier     /* For the purpose of this API, treat messages with unexpected CID
14811fa71b9SJerome Forissier      * as well as such from future epochs as unexpected. */
14911fa71b9SJerome Forissier     if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_CID ||
15011fa71b9SJerome Forissier         ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE )
15111fa71b9SJerome Forissier     {
15211fa71b9SJerome Forissier         ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD;
15311fa71b9SJerome Forissier     }
15411fa71b9SJerome Forissier 
15511fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 1, ( "<= mbedtls_ssl_check_record" ) );
15611fa71b9SJerome Forissier     return( ret );
15711fa71b9SJerome Forissier }
15811fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_RECORD_CHECKING */
15911fa71b9SJerome Forissier 
16011fa71b9SJerome Forissier #define SSL_DONT_FORCE_FLUSH 0
16111fa71b9SJerome Forissier #define SSL_FORCE_FLUSH      1
16211fa71b9SJerome Forissier 
16311fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
16411fa71b9SJerome Forissier 
16511fa71b9SJerome Forissier /* Forward declarations for functions related to message buffering. */
16611fa71b9SJerome Forissier static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl,
16711fa71b9SJerome Forissier                                      uint8_t slot );
16811fa71b9SJerome Forissier static void ssl_free_buffered_record( mbedtls_ssl_context *ssl );
169*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
17011fa71b9SJerome Forissier static int ssl_load_buffered_message( mbedtls_ssl_context *ssl );
171*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
17211fa71b9SJerome Forissier static int ssl_load_buffered_record( mbedtls_ssl_context *ssl );
173*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
17411fa71b9SJerome Forissier static int ssl_buffer_message( mbedtls_ssl_context *ssl );
175*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
17611fa71b9SJerome Forissier static int ssl_buffer_future_record( mbedtls_ssl_context *ssl,
17711fa71b9SJerome Forissier                                      mbedtls_record const *rec );
178*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
17911fa71b9SJerome Forissier static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl );
18011fa71b9SJerome Forissier 
18111fa71b9SJerome Forissier static size_t ssl_get_maximum_datagram_size( mbedtls_ssl_context const *ssl )
18211fa71b9SJerome Forissier {
18311fa71b9SJerome Forissier     size_t mtu = mbedtls_ssl_get_current_mtu( ssl );
18411fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
18511fa71b9SJerome Forissier     size_t out_buf_len = ssl->out_buf_len;
18611fa71b9SJerome Forissier #else
18711fa71b9SJerome Forissier     size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN;
18811fa71b9SJerome Forissier #endif
18911fa71b9SJerome Forissier 
19011fa71b9SJerome Forissier     if( mtu != 0 && mtu < out_buf_len )
19111fa71b9SJerome Forissier         return( mtu );
19211fa71b9SJerome Forissier 
19311fa71b9SJerome Forissier     return( out_buf_len );
19411fa71b9SJerome Forissier }
19511fa71b9SJerome Forissier 
196*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
19711fa71b9SJerome Forissier static int ssl_get_remaining_space_in_datagram( mbedtls_ssl_context const *ssl )
19811fa71b9SJerome Forissier {
19911fa71b9SJerome Forissier     size_t const bytes_written = ssl->out_left;
20011fa71b9SJerome Forissier     size_t const mtu           = ssl_get_maximum_datagram_size( ssl );
20111fa71b9SJerome Forissier 
20211fa71b9SJerome Forissier     /* Double-check that the write-index hasn't gone
20311fa71b9SJerome Forissier      * past what we can transmit in a single datagram. */
20411fa71b9SJerome Forissier     if( bytes_written > mtu )
20511fa71b9SJerome Forissier     {
20611fa71b9SJerome Forissier         /* Should never happen... */
20711fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
20811fa71b9SJerome Forissier     }
20911fa71b9SJerome Forissier 
21011fa71b9SJerome Forissier     return( (int) ( mtu - bytes_written ) );
21111fa71b9SJerome Forissier }
21211fa71b9SJerome Forissier 
213*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
21411fa71b9SJerome Forissier static int ssl_get_remaining_payload_in_datagram( mbedtls_ssl_context const *ssl )
21511fa71b9SJerome Forissier {
21611fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
21711fa71b9SJerome Forissier     size_t remaining, expansion;
21811fa71b9SJerome Forissier     size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN;
21911fa71b9SJerome Forissier 
22011fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
22111fa71b9SJerome Forissier     const size_t mfl = mbedtls_ssl_get_output_max_frag_len( ssl );
22211fa71b9SJerome Forissier 
22311fa71b9SJerome Forissier     if( max_len > mfl )
22411fa71b9SJerome Forissier         max_len = mfl;
22511fa71b9SJerome Forissier 
22611fa71b9SJerome Forissier     /* By the standard (RFC 6066 Sect. 4), the MFL extension
22711fa71b9SJerome Forissier      * only limits the maximum record payload size, so in theory
22811fa71b9SJerome Forissier      * we would be allowed to pack multiple records of payload size
22911fa71b9SJerome Forissier      * MFL into a single datagram. However, this would mean that there's
23011fa71b9SJerome Forissier      * no way to explicitly communicate MTU restrictions to the peer.
23111fa71b9SJerome Forissier      *
23211fa71b9SJerome Forissier      * The following reduction of max_len makes sure that we never
23311fa71b9SJerome Forissier      * write datagrams larger than MFL + Record Expansion Overhead.
23411fa71b9SJerome Forissier      */
23511fa71b9SJerome Forissier     if( max_len <= ssl->out_left )
23611fa71b9SJerome Forissier         return( 0 );
23711fa71b9SJerome Forissier 
23811fa71b9SJerome Forissier     max_len -= ssl->out_left;
23911fa71b9SJerome Forissier #endif
24011fa71b9SJerome Forissier 
24111fa71b9SJerome Forissier     ret = ssl_get_remaining_space_in_datagram( ssl );
24211fa71b9SJerome Forissier     if( ret < 0 )
24311fa71b9SJerome Forissier         return( ret );
24411fa71b9SJerome Forissier     remaining = (size_t) ret;
24511fa71b9SJerome Forissier 
24611fa71b9SJerome Forissier     ret = mbedtls_ssl_get_record_expansion( ssl );
24711fa71b9SJerome Forissier     if( ret < 0 )
24811fa71b9SJerome Forissier         return( ret );
24911fa71b9SJerome Forissier     expansion = (size_t) ret;
25011fa71b9SJerome Forissier 
25111fa71b9SJerome Forissier     if( remaining <= expansion )
25211fa71b9SJerome Forissier         return( 0 );
25311fa71b9SJerome Forissier 
25411fa71b9SJerome Forissier     remaining -= expansion;
25511fa71b9SJerome Forissier     if( remaining >= max_len )
25611fa71b9SJerome Forissier         remaining = max_len;
25711fa71b9SJerome Forissier 
25811fa71b9SJerome Forissier     return( (int) remaining );
25911fa71b9SJerome Forissier }
26011fa71b9SJerome Forissier 
26111fa71b9SJerome Forissier /*
26211fa71b9SJerome Forissier  * Double the retransmit timeout value, within the allowed range,
26311fa71b9SJerome Forissier  * returning -1 if the maximum value has already been reached.
26411fa71b9SJerome Forissier  */
265*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
26611fa71b9SJerome Forissier static int ssl_double_retransmit_timeout( mbedtls_ssl_context *ssl )
26711fa71b9SJerome Forissier {
26811fa71b9SJerome Forissier     uint32_t new_timeout;
26911fa71b9SJerome Forissier 
27011fa71b9SJerome Forissier     if( ssl->handshake->retransmit_timeout >= ssl->conf->hs_timeout_max )
27111fa71b9SJerome Forissier         return( -1 );
27211fa71b9SJerome Forissier 
27311fa71b9SJerome Forissier     /* Implement the final paragraph of RFC 6347 section 4.1.1.1
27411fa71b9SJerome Forissier      * in the following way: after the initial transmission and a first
27511fa71b9SJerome Forissier      * retransmission, back off to a temporary estimated MTU of 508 bytes.
27611fa71b9SJerome Forissier      * This value is guaranteed to be deliverable (if not guaranteed to be
27711fa71b9SJerome Forissier      * delivered) of any compliant IPv4 (and IPv6) network, and should work
27811fa71b9SJerome Forissier      * on most non-IP stacks too. */
27911fa71b9SJerome Forissier     if( ssl->handshake->retransmit_timeout != ssl->conf->hs_timeout_min )
28011fa71b9SJerome Forissier     {
28111fa71b9SJerome Forissier         ssl->handshake->mtu = 508;
28211fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 2, ( "mtu autoreduction to %d bytes", ssl->handshake->mtu ) );
28311fa71b9SJerome Forissier     }
28411fa71b9SJerome Forissier 
28511fa71b9SJerome Forissier     new_timeout = 2 * ssl->handshake->retransmit_timeout;
28611fa71b9SJerome Forissier 
28711fa71b9SJerome Forissier     /* Avoid arithmetic overflow and range overflow */
28811fa71b9SJerome Forissier     if( new_timeout < ssl->handshake->retransmit_timeout ||
28911fa71b9SJerome Forissier         new_timeout > ssl->conf->hs_timeout_max )
29011fa71b9SJerome Forissier     {
29111fa71b9SJerome Forissier         new_timeout = ssl->conf->hs_timeout_max;
29211fa71b9SJerome Forissier     }
29311fa71b9SJerome Forissier 
29411fa71b9SJerome Forissier     ssl->handshake->retransmit_timeout = new_timeout;
2957901324dSJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %lu millisecs",
2967901324dSJerome Forissier                         (unsigned long) ssl->handshake->retransmit_timeout ) );
29711fa71b9SJerome Forissier 
29811fa71b9SJerome Forissier     return( 0 );
29911fa71b9SJerome Forissier }
30011fa71b9SJerome Forissier 
30111fa71b9SJerome Forissier static void ssl_reset_retransmit_timeout( mbedtls_ssl_context *ssl )
30211fa71b9SJerome Forissier {
30311fa71b9SJerome Forissier     ssl->handshake->retransmit_timeout = ssl->conf->hs_timeout_min;
3047901324dSJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %lu millisecs",
3057901324dSJerome Forissier                         (unsigned long) ssl->handshake->retransmit_timeout ) );
30611fa71b9SJerome Forissier }
30711fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
30811fa71b9SJerome Forissier 
30911fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
31011fa71b9SJerome Forissier int (*mbedtls_ssl_hw_record_init)( mbedtls_ssl_context *ssl,
31111fa71b9SJerome Forissier                      const unsigned char *key_enc, const unsigned char *key_dec,
31211fa71b9SJerome Forissier                      size_t keylen,
31311fa71b9SJerome Forissier                      const unsigned char *iv_enc,  const unsigned char *iv_dec,
31411fa71b9SJerome Forissier                      size_t ivlen,
31511fa71b9SJerome Forissier                      const unsigned char *mac_enc, const unsigned char *mac_dec,
31611fa71b9SJerome Forissier                      size_t maclen ) = NULL;
31711fa71b9SJerome Forissier int (*mbedtls_ssl_hw_record_activate)( mbedtls_ssl_context *ssl, int direction) = NULL;
31811fa71b9SJerome Forissier int (*mbedtls_ssl_hw_record_reset)( mbedtls_ssl_context *ssl ) = NULL;
31911fa71b9SJerome Forissier int (*mbedtls_ssl_hw_record_write)( mbedtls_ssl_context *ssl ) = NULL;
32011fa71b9SJerome Forissier int (*mbedtls_ssl_hw_record_read)( mbedtls_ssl_context *ssl ) = NULL;
32111fa71b9SJerome Forissier int (*mbedtls_ssl_hw_record_finish)( mbedtls_ssl_context *ssl ) = NULL;
32211fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */
32311fa71b9SJerome Forissier 
32411fa71b9SJerome Forissier /*
32511fa71b9SJerome Forissier  * Encryption/decryption functions
32611fa71b9SJerome Forissier  */
32711fa71b9SJerome Forissier 
3287901324dSJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) ||  \
3297901324dSJerome Forissier     defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
3307901324dSJerome Forissier 
3317901324dSJerome Forissier static size_t ssl_compute_padding_length( size_t len,
3327901324dSJerome Forissier                                           size_t granularity )
3337901324dSJerome Forissier {
3347901324dSJerome Forissier     return( ( granularity - ( len + 1 ) % granularity ) % granularity );
3357901324dSJerome Forissier }
3367901324dSJerome Forissier 
3377901324dSJerome Forissier /* This functions transforms a (D)TLS plaintext fragment and a record content
3387901324dSJerome Forissier  * type into an instance of the (D)TLSInnerPlaintext structure. This is used
3397901324dSJerome Forissier  * in DTLS 1.2 + CID and within TLS 1.3 to allow flexible padding and to protect
3407901324dSJerome Forissier  * a record's content type.
34111fa71b9SJerome Forissier  *
34211fa71b9SJerome Forissier  *        struct {
34311fa71b9SJerome Forissier  *            opaque content[DTLSPlaintext.length];
34411fa71b9SJerome Forissier  *            ContentType real_type;
34511fa71b9SJerome Forissier  *            uint8 zeros[length_of_padding];
3467901324dSJerome Forissier  *        } (D)TLSInnerPlaintext;
34711fa71b9SJerome Forissier  *
34811fa71b9SJerome Forissier  *  Input:
34911fa71b9SJerome Forissier  *  - `content`: The beginning of the buffer holding the
35011fa71b9SJerome Forissier  *               plaintext to be wrapped.
35111fa71b9SJerome Forissier  *  - `*content_size`: The length of the plaintext in Bytes.
35211fa71b9SJerome Forissier  *  - `max_len`: The number of Bytes available starting from
35311fa71b9SJerome Forissier  *               `content`. This must be `>= *content_size`.
35411fa71b9SJerome Forissier  *  - `rec_type`: The desired record content type.
35511fa71b9SJerome Forissier  *
35611fa71b9SJerome Forissier  *  Output:
3577901324dSJerome Forissier  *  - `content`: The beginning of the resulting (D)TLSInnerPlaintext structure.
3587901324dSJerome Forissier  *  - `*content_size`: The length of the resulting (D)TLSInnerPlaintext structure.
35911fa71b9SJerome Forissier  *
36011fa71b9SJerome Forissier  *  Returns:
36111fa71b9SJerome Forissier  *  - `0` on success.
36211fa71b9SJerome Forissier  *  - A negative error code if `max_len` didn't offer enough space
36311fa71b9SJerome Forissier  *    for the expansion.
36411fa71b9SJerome Forissier  */
365*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
3667901324dSJerome Forissier static int ssl_build_inner_plaintext( unsigned char *content,
36711fa71b9SJerome Forissier                                       size_t *content_size,
36811fa71b9SJerome Forissier                                       size_t remaining,
3697901324dSJerome Forissier                                       uint8_t rec_type,
3707901324dSJerome Forissier                                       size_t pad )
37111fa71b9SJerome Forissier {
37211fa71b9SJerome Forissier     size_t len = *content_size;
37311fa71b9SJerome Forissier 
37411fa71b9SJerome Forissier     /* Write real content type */
37511fa71b9SJerome Forissier     if( remaining == 0 )
37611fa71b9SJerome Forissier         return( -1 );
37711fa71b9SJerome Forissier     content[ len ] = rec_type;
37811fa71b9SJerome Forissier     len++;
37911fa71b9SJerome Forissier     remaining--;
38011fa71b9SJerome Forissier 
38111fa71b9SJerome Forissier     if( remaining < pad )
38211fa71b9SJerome Forissier         return( -1 );
38311fa71b9SJerome Forissier     memset( content + len, 0, pad );
38411fa71b9SJerome Forissier     len += pad;
38511fa71b9SJerome Forissier     remaining -= pad;
38611fa71b9SJerome Forissier 
38711fa71b9SJerome Forissier     *content_size = len;
38811fa71b9SJerome Forissier     return( 0 );
38911fa71b9SJerome Forissier }
39011fa71b9SJerome Forissier 
3917901324dSJerome Forissier /* This function parses a (D)TLSInnerPlaintext structure.
3927901324dSJerome Forissier  * See ssl_build_inner_plaintext() for details. */
393*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
3947901324dSJerome Forissier static int ssl_parse_inner_plaintext( unsigned char const *content,
39511fa71b9SJerome Forissier                                           size_t *content_size,
39611fa71b9SJerome Forissier                                           uint8_t *rec_type )
39711fa71b9SJerome Forissier {
39811fa71b9SJerome Forissier     size_t remaining = *content_size;
39911fa71b9SJerome Forissier 
40011fa71b9SJerome Forissier     /* Determine length of padding by skipping zeroes from the back. */
40111fa71b9SJerome Forissier     do
40211fa71b9SJerome Forissier     {
40311fa71b9SJerome Forissier         if( remaining == 0 )
40411fa71b9SJerome Forissier             return( -1 );
40511fa71b9SJerome Forissier         remaining--;
40611fa71b9SJerome Forissier     } while( content[ remaining ] == 0 );
40711fa71b9SJerome Forissier 
40811fa71b9SJerome Forissier     *content_size = remaining;
40911fa71b9SJerome Forissier     *rec_type = content[ remaining ];
41011fa71b9SJerome Forissier 
41111fa71b9SJerome Forissier     return( 0 );
41211fa71b9SJerome Forissier }
4137901324dSJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID ||
4147901324dSJerome Forissier           MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
41511fa71b9SJerome Forissier 
41611fa71b9SJerome Forissier /* `add_data` must have size 13 Bytes if the CID extension is disabled,
41711fa71b9SJerome Forissier  * and 13 + 1 + CID-length Bytes if the CID extension is enabled. */
41811fa71b9SJerome Forissier static void ssl_extract_add_data_from_record( unsigned char* add_data,
41911fa71b9SJerome Forissier                                               size_t *add_data_len,
4207901324dSJerome Forissier                                               mbedtls_record *rec,
4217901324dSJerome Forissier                                               unsigned minor_ver )
42211fa71b9SJerome Forissier {
42311fa71b9SJerome Forissier     /* Quoting RFC 5246 (TLS 1.2):
42411fa71b9SJerome Forissier      *
42511fa71b9SJerome Forissier      *    additional_data = seq_num + TLSCompressed.type +
42611fa71b9SJerome Forissier      *                      TLSCompressed.version + TLSCompressed.length;
42711fa71b9SJerome Forissier      *
42811fa71b9SJerome Forissier      * For the CID extension, this is extended as follows
42911fa71b9SJerome Forissier      * (quoting draft-ietf-tls-dtls-connection-id-05,
43011fa71b9SJerome Forissier      *  https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05):
43111fa71b9SJerome Forissier      *
43211fa71b9SJerome Forissier      *       additional_data = seq_num + DTLSPlaintext.type +
43311fa71b9SJerome Forissier      *                         DTLSPlaintext.version +
43411fa71b9SJerome Forissier      *                         cid +
43511fa71b9SJerome Forissier      *                         cid_length +
43611fa71b9SJerome Forissier      *                         length_of_DTLSInnerPlaintext;
4377901324dSJerome Forissier      *
4387901324dSJerome Forissier      * For TLS 1.3, the record sequence number is dropped from the AAD
4397901324dSJerome Forissier      * and encoded within the nonce of the AEAD operation instead.
44011fa71b9SJerome Forissier      */
44111fa71b9SJerome Forissier 
4427901324dSJerome Forissier     unsigned char *cur = add_data;
4437901324dSJerome Forissier 
4447901324dSJerome Forissier #if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
4457901324dSJerome Forissier     if( minor_ver != MBEDTLS_SSL_MINOR_VERSION_4 )
4467901324dSJerome Forissier #endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
4477901324dSJerome Forissier     {
4487901324dSJerome Forissier         ((void) minor_ver);
4497901324dSJerome Forissier         memcpy( cur, rec->ctr, sizeof( rec->ctr ) );
4507901324dSJerome Forissier         cur += sizeof( rec->ctr );
4517901324dSJerome Forissier     }
4527901324dSJerome Forissier 
4537901324dSJerome Forissier     *cur = rec->type;
4547901324dSJerome Forissier     cur++;
4557901324dSJerome Forissier 
4567901324dSJerome Forissier     memcpy( cur, rec->ver, sizeof( rec->ver ) );
4577901324dSJerome Forissier     cur += sizeof( rec->ver );
45811fa71b9SJerome Forissier 
45911fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
46011fa71b9SJerome Forissier     if( rec->cid_len != 0 )
46111fa71b9SJerome Forissier     {
4627901324dSJerome Forissier         memcpy( cur, rec->cid, rec->cid_len );
4637901324dSJerome Forissier         cur += rec->cid_len;
4647901324dSJerome Forissier 
4657901324dSJerome Forissier         *cur = rec->cid_len;
4667901324dSJerome Forissier         cur++;
4677901324dSJerome Forissier 
468*039e02dfSJerome Forissier         MBEDTLS_PUT_UINT16_BE( rec->data_len, cur, 0 );
4697901324dSJerome Forissier         cur += 2;
47011fa71b9SJerome Forissier     }
47111fa71b9SJerome Forissier     else
47211fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
47311fa71b9SJerome Forissier     {
474*039e02dfSJerome Forissier         MBEDTLS_PUT_UINT16_BE( rec->data_len, cur, 0 );
4757901324dSJerome Forissier         cur += 2;
47611fa71b9SJerome Forissier     }
4777901324dSJerome Forissier 
4787901324dSJerome Forissier     *add_data_len = cur - add_data;
47911fa71b9SJerome Forissier }
48011fa71b9SJerome Forissier 
48111fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_SSL3)
48211fa71b9SJerome Forissier 
48311fa71b9SJerome Forissier #define SSL3_MAC_MAX_BYTES   20  /* MD-5 or SHA-1 */
48411fa71b9SJerome Forissier 
48511fa71b9SJerome Forissier /*
48611fa71b9SJerome Forissier  * SSLv3.0 MAC functions
48711fa71b9SJerome Forissier  */
488*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
489*039e02dfSJerome Forissier static int ssl_mac( mbedtls_md_context_t *md_ctx,
49011fa71b9SJerome Forissier                     const unsigned char *secret,
49111fa71b9SJerome Forissier                     const unsigned char *buf, size_t len,
49211fa71b9SJerome Forissier                     const unsigned char *ctr, int type,
49311fa71b9SJerome Forissier                     unsigned char out[SSL3_MAC_MAX_BYTES] )
49411fa71b9SJerome Forissier {
49511fa71b9SJerome Forissier     unsigned char header[11];
49611fa71b9SJerome Forissier     unsigned char padding[48];
49711fa71b9SJerome Forissier     int padlen;
49811fa71b9SJerome Forissier     int md_size = mbedtls_md_get_size( md_ctx->md_info );
49911fa71b9SJerome Forissier     int md_type = mbedtls_md_get_type( md_ctx->md_info );
500*039e02dfSJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
50111fa71b9SJerome Forissier 
50211fa71b9SJerome Forissier     /* Only MD5 and SHA-1 supported */
50311fa71b9SJerome Forissier     if( md_type == MBEDTLS_MD_MD5 )
50411fa71b9SJerome Forissier         padlen = 48;
50511fa71b9SJerome Forissier     else
50611fa71b9SJerome Forissier         padlen = 40;
50711fa71b9SJerome Forissier 
50811fa71b9SJerome Forissier     memcpy( header, ctr, 8 );
50911fa71b9SJerome Forissier     header[8] = (unsigned char)  type;
510*039e02dfSJerome Forissier     MBEDTLS_PUT_UINT16_BE( len, header, 9);
51111fa71b9SJerome Forissier 
51211fa71b9SJerome Forissier     memset( padding, 0x36, padlen );
513*039e02dfSJerome Forissier     ret = mbedtls_md_starts( md_ctx );
514*039e02dfSJerome Forissier     if( ret != 0 )
515*039e02dfSJerome Forissier         return( ret );
516*039e02dfSJerome Forissier     ret = mbedtls_md_update( md_ctx, secret,  md_size );
517*039e02dfSJerome Forissier     if( ret != 0 )
518*039e02dfSJerome Forissier         return( ret );
519*039e02dfSJerome Forissier     ret = mbedtls_md_update( md_ctx, padding, padlen  );
520*039e02dfSJerome Forissier     if( ret != 0 )
521*039e02dfSJerome Forissier         return( ret );
522*039e02dfSJerome Forissier     ret = mbedtls_md_update( md_ctx, header,  11      );
523*039e02dfSJerome Forissier     if( ret != 0 )
524*039e02dfSJerome Forissier         return( ret );
525*039e02dfSJerome Forissier     ret = mbedtls_md_update( md_ctx, buf,     len     );
526*039e02dfSJerome Forissier     if( ret != 0 )
527*039e02dfSJerome Forissier         return( ret );
528*039e02dfSJerome Forissier     ret = mbedtls_md_finish( md_ctx, out              );
529*039e02dfSJerome Forissier     if( ret != 0 )
530*039e02dfSJerome Forissier         return( ret );
53111fa71b9SJerome Forissier 
53211fa71b9SJerome Forissier     memset( padding, 0x5C, padlen );
533*039e02dfSJerome Forissier     ret = mbedtls_md_starts( md_ctx );
534*039e02dfSJerome Forissier     if( ret != 0 )
535*039e02dfSJerome Forissier         return( ret );
536*039e02dfSJerome Forissier     ret = mbedtls_md_update( md_ctx, secret,    md_size );
537*039e02dfSJerome Forissier     if( ret != 0 )
538*039e02dfSJerome Forissier         return( ret );
539*039e02dfSJerome Forissier     ret = mbedtls_md_update( md_ctx, padding,   padlen  );
540*039e02dfSJerome Forissier     if( ret != 0 )
541*039e02dfSJerome Forissier         return( ret );
542*039e02dfSJerome Forissier     ret = mbedtls_md_update( md_ctx, out,       md_size );
543*039e02dfSJerome Forissier     if( ret != 0 )
544*039e02dfSJerome Forissier         return( ret );
545*039e02dfSJerome Forissier     ret = mbedtls_md_finish( md_ctx, out                );
546*039e02dfSJerome Forissier     if( ret != 0 )
547*039e02dfSJerome Forissier         return( ret );
548*039e02dfSJerome Forissier 
549*039e02dfSJerome Forissier     return( 0 );
55011fa71b9SJerome Forissier }
55111fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_SSL3 */
55211fa71b9SJerome Forissier 
5537901324dSJerome Forissier #if defined(MBEDTLS_GCM_C) || \
5547901324dSJerome Forissier     defined(MBEDTLS_CCM_C) || \
5557901324dSJerome Forissier     defined(MBEDTLS_CHACHAPOLY_C)
556*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
5577901324dSJerome Forissier static int ssl_transform_aead_dynamic_iv_is_explicit(
5587901324dSJerome Forissier                                 mbedtls_ssl_transform const *transform )
5597901324dSJerome Forissier {
5607901324dSJerome Forissier     return( transform->ivlen != transform->fixed_ivlen );
5617901324dSJerome Forissier }
5627901324dSJerome Forissier 
5637901324dSJerome Forissier /* Compute IV := ( fixed_iv || 0 ) XOR ( 0 || dynamic_IV )
5647901324dSJerome Forissier  *
5657901324dSJerome Forissier  * Concretely, this occurs in two variants:
5667901324dSJerome Forissier  *
5677901324dSJerome Forissier  * a) Fixed and dynamic IV lengths add up to total IV length, giving
5687901324dSJerome Forissier  *       IV = fixed_iv || dynamic_iv
5697901324dSJerome Forissier  *
5707901324dSJerome Forissier  *    This variant is used in TLS 1.2 when used with GCM or CCM.
5717901324dSJerome Forissier  *
5727901324dSJerome Forissier  * b) Fixed IV lengths matches total IV length, giving
5737901324dSJerome Forissier  *       IV = fixed_iv XOR ( 0 || dynamic_iv )
5747901324dSJerome Forissier  *
5757901324dSJerome Forissier  *    This variant occurs in TLS 1.3 and for TLS 1.2 when using ChaChaPoly.
5767901324dSJerome Forissier  *
5777901324dSJerome Forissier  * See also the documentation of mbedtls_ssl_transform.
5787901324dSJerome Forissier  *
5797901324dSJerome Forissier  * This function has the precondition that
5807901324dSJerome Forissier  *
5817901324dSJerome Forissier  *     dst_iv_len >= max( fixed_iv_len, dynamic_iv_len )
5827901324dSJerome Forissier  *
5837901324dSJerome Forissier  * which has to be ensured by the caller. If this precondition
5847901324dSJerome Forissier  * violated, the behavior of this function is undefined.
5857901324dSJerome Forissier  */
5867901324dSJerome Forissier static void ssl_build_record_nonce( unsigned char *dst_iv,
5877901324dSJerome Forissier                                     size_t dst_iv_len,
5887901324dSJerome Forissier                                     unsigned char const *fixed_iv,
5897901324dSJerome Forissier                                     size_t fixed_iv_len,
5907901324dSJerome Forissier                                     unsigned char const *dynamic_iv,
5917901324dSJerome Forissier                                     size_t dynamic_iv_len )
5927901324dSJerome Forissier {
5937901324dSJerome Forissier     size_t i;
5947901324dSJerome Forissier 
5957901324dSJerome Forissier     /* Start with Fixed IV || 0 */
5967901324dSJerome Forissier     memset( dst_iv, 0, dst_iv_len );
5977901324dSJerome Forissier     memcpy( dst_iv, fixed_iv, fixed_iv_len );
5987901324dSJerome Forissier 
5997901324dSJerome Forissier     dst_iv += dst_iv_len - dynamic_iv_len;
6007901324dSJerome Forissier     for( i = 0; i < dynamic_iv_len; i++ )
6017901324dSJerome Forissier         dst_iv[i] ^= dynamic_iv[i];
6027901324dSJerome Forissier }
6037901324dSJerome Forissier #endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */
6047901324dSJerome Forissier 
60511fa71b9SJerome Forissier int mbedtls_ssl_encrypt_buf( mbedtls_ssl_context *ssl,
60611fa71b9SJerome Forissier                              mbedtls_ssl_transform *transform,
60711fa71b9SJerome Forissier                              mbedtls_record *rec,
60811fa71b9SJerome Forissier                              int (*f_rng)(void *, unsigned char *, size_t),
60911fa71b9SJerome Forissier                              void *p_rng )
61011fa71b9SJerome Forissier {
61111fa71b9SJerome Forissier     mbedtls_cipher_mode_t mode;
61211fa71b9SJerome Forissier     int auth_done = 0;
61311fa71b9SJerome Forissier     unsigned char * data;
61411fa71b9SJerome Forissier     unsigned char add_data[13 + 1 + MBEDTLS_SSL_CID_OUT_LEN_MAX ];
61511fa71b9SJerome Forissier     size_t add_data_len;
61611fa71b9SJerome Forissier     size_t post_avail;
61711fa71b9SJerome Forissier 
61811fa71b9SJerome Forissier     /* The SSL context is only used for debugging purposes! */
61911fa71b9SJerome Forissier #if !defined(MBEDTLS_DEBUG_C)
62011fa71b9SJerome Forissier     ssl = NULL; /* make sure we don't use it except for debug */
62111fa71b9SJerome Forissier     ((void) ssl);
62211fa71b9SJerome Forissier #endif
62311fa71b9SJerome Forissier 
62411fa71b9SJerome Forissier     /* The PRNG is used for dynamic IV generation that's used
62511fa71b9SJerome Forissier      * for CBC transformations in TLS 1.1 and TLS 1.2. */
6267901324dSJerome Forissier #if !( defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) && \
62711fa71b9SJerome Forissier        ( defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) ) )
62811fa71b9SJerome Forissier     ((void) f_rng);
62911fa71b9SJerome Forissier     ((void) p_rng);
63011fa71b9SJerome Forissier #endif
63111fa71b9SJerome Forissier 
63211fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> encrypt buf" ) );
63311fa71b9SJerome Forissier 
63411fa71b9SJerome Forissier     if( transform == NULL )
63511fa71b9SJerome Forissier     {
63611fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "no transform provided to encrypt_buf" ) );
63711fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
63811fa71b9SJerome Forissier     }
63911fa71b9SJerome Forissier     if( rec == NULL
64011fa71b9SJerome Forissier         || rec->buf == NULL
64111fa71b9SJerome Forissier         || rec->buf_len < rec->data_offset
64211fa71b9SJerome Forissier         || rec->buf_len - rec->data_offset < rec->data_len
64311fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
64411fa71b9SJerome Forissier         || rec->cid_len != 0
64511fa71b9SJerome Forissier #endif
64611fa71b9SJerome Forissier         )
64711fa71b9SJerome Forissier     {
64811fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad record structure provided to encrypt_buf" ) );
64911fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
65011fa71b9SJerome Forissier     }
65111fa71b9SJerome Forissier 
65211fa71b9SJerome Forissier     data = rec->buf + rec->data_offset;
65311fa71b9SJerome Forissier     post_avail = rec->buf_len - ( rec->data_len + rec->data_offset );
65411fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_BUF( 4, "before encrypt: output payload",
65511fa71b9SJerome Forissier                            data, rec->data_len );
65611fa71b9SJerome Forissier 
65711fa71b9SJerome Forissier     mode = mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc );
65811fa71b9SJerome Forissier 
65911fa71b9SJerome Forissier     if( rec->data_len > MBEDTLS_SSL_OUT_CONTENT_LEN )
66011fa71b9SJerome Forissier     {
6617901324dSJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record content %" MBEDTLS_PRINTF_SIZET
6627901324dSJerome Forissier                                     " too large, maximum %" MBEDTLS_PRINTF_SIZET,
6637901324dSJerome Forissier                                     rec->data_len,
6647901324dSJerome Forissier                                     (size_t) MBEDTLS_SSL_OUT_CONTENT_LEN ) );
66511fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
66611fa71b9SJerome Forissier     }
66711fa71b9SJerome Forissier 
6687901324dSJerome Forissier     /* The following two code paths implement the (D)TLSInnerPlaintext
6697901324dSJerome Forissier      * structure present in TLS 1.3 and DTLS 1.2 + CID.
6707901324dSJerome Forissier      *
6717901324dSJerome Forissier      * See ssl_build_inner_plaintext() for more information.
6727901324dSJerome Forissier      *
6737901324dSJerome Forissier      * Note that this changes `rec->data_len`, and hence
6747901324dSJerome Forissier      * `post_avail` needs to be recalculated afterwards.
6757901324dSJerome Forissier      *
6767901324dSJerome Forissier      * Note also that the two code paths cannot occur simultaneously
6777901324dSJerome Forissier      * since they apply to different versions of the protocol. There
6787901324dSJerome Forissier      * is hence no risk of double-addition of the inner plaintext.
6797901324dSJerome Forissier      */
6807901324dSJerome Forissier #if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
6817901324dSJerome Forissier     if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_4 )
6827901324dSJerome Forissier     {
6837901324dSJerome Forissier         size_t padding =
6847901324dSJerome Forissier             ssl_compute_padding_length( rec->data_len,
6857901324dSJerome Forissier                                         MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY );
6867901324dSJerome Forissier         if( ssl_build_inner_plaintext( data,
6877901324dSJerome Forissier                                        &rec->data_len,
6887901324dSJerome Forissier                                        post_avail,
6897901324dSJerome Forissier                                        rec->type,
6907901324dSJerome Forissier                                        padding ) != 0 )
6917901324dSJerome Forissier         {
6927901324dSJerome Forissier             return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
6937901324dSJerome Forissier         }
6947901324dSJerome Forissier 
6957901324dSJerome Forissier         rec->type = MBEDTLS_SSL_MSG_APPLICATION_DATA;
6967901324dSJerome Forissier     }
6977901324dSJerome Forissier #endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
6987901324dSJerome Forissier 
69911fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
70011fa71b9SJerome Forissier     /*
70111fa71b9SJerome Forissier      * Add CID information
70211fa71b9SJerome Forissier      */
70311fa71b9SJerome Forissier     rec->cid_len = transform->out_cid_len;
70411fa71b9SJerome Forissier     memcpy( rec->cid, transform->out_cid, transform->out_cid_len );
70511fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_BUF( 3, "CID", rec->cid, rec->cid_len );
70611fa71b9SJerome Forissier 
70711fa71b9SJerome Forissier     if( rec->cid_len != 0 )
70811fa71b9SJerome Forissier     {
7097901324dSJerome Forissier         size_t padding =
7107901324dSJerome Forissier             ssl_compute_padding_length( rec->data_len,
7117901324dSJerome Forissier                                         MBEDTLS_SSL_CID_PADDING_GRANULARITY );
71211fa71b9SJerome Forissier         /*
71311fa71b9SJerome Forissier          * Wrap plaintext into DTLSInnerPlaintext structure.
7147901324dSJerome Forissier          * See ssl_build_inner_plaintext() for more information.
71511fa71b9SJerome Forissier          *
71611fa71b9SJerome Forissier          * Note that this changes `rec->data_len`, and hence
71711fa71b9SJerome Forissier          * `post_avail` needs to be recalculated afterwards.
71811fa71b9SJerome Forissier          */
7197901324dSJerome Forissier         if( ssl_build_inner_plaintext( data,
72011fa71b9SJerome Forissier                         &rec->data_len,
72111fa71b9SJerome Forissier                         post_avail,
7227901324dSJerome Forissier                         rec->type,
7237901324dSJerome Forissier                         padding ) != 0 )
72411fa71b9SJerome Forissier         {
72511fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
72611fa71b9SJerome Forissier         }
72711fa71b9SJerome Forissier 
72811fa71b9SJerome Forissier         rec->type = MBEDTLS_SSL_MSG_CID;
72911fa71b9SJerome Forissier     }
73011fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
73111fa71b9SJerome Forissier 
73211fa71b9SJerome Forissier     post_avail = rec->buf_len - ( rec->data_len + rec->data_offset );
73311fa71b9SJerome Forissier 
73411fa71b9SJerome Forissier     /*
73511fa71b9SJerome Forissier      * Add MAC before if needed
73611fa71b9SJerome Forissier      */
73711fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
73811fa71b9SJerome Forissier     if( mode == MBEDTLS_MODE_STREAM ||
73911fa71b9SJerome Forissier         ( mode == MBEDTLS_MODE_CBC
74011fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
74111fa71b9SJerome Forissier           && transform->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED
74211fa71b9SJerome Forissier #endif
74311fa71b9SJerome Forissier         ) )
74411fa71b9SJerome Forissier     {
74511fa71b9SJerome Forissier         if( post_avail < transform->maclen )
74611fa71b9SJerome Forissier         {
74711fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) );
74811fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
74911fa71b9SJerome Forissier         }
75011fa71b9SJerome Forissier 
75111fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_SSL3)
75211fa71b9SJerome Forissier         if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
75311fa71b9SJerome Forissier         {
75411fa71b9SJerome Forissier             unsigned char mac[SSL3_MAC_MAX_BYTES];
755*039e02dfSJerome Forissier             int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
756*039e02dfSJerome Forissier             ret = ssl_mac( &transform->md_ctx_enc, transform->mac_enc,
75711fa71b9SJerome Forissier                            data, rec->data_len, rec->ctr, rec->type, mac );
758*039e02dfSJerome Forissier             if( ret == 0 )
75911fa71b9SJerome Forissier                 memcpy( data + rec->data_len, mac, transform->maclen );
760*039e02dfSJerome Forissier             mbedtls_platform_zeroize( mac, transform->maclen );
761*039e02dfSJerome Forissier             if( ret != 0 )
762*039e02dfSJerome Forissier             {
763*039e02dfSJerome Forissier                 MBEDTLS_SSL_DEBUG_RET( 1, "ssl_mac", ret );
764*039e02dfSJerome Forissier                 return( ret );
765*039e02dfSJerome Forissier             }
76611fa71b9SJerome Forissier         }
76711fa71b9SJerome Forissier         else
76811fa71b9SJerome Forissier #endif
76911fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
77011fa71b9SJerome Forissier         defined(MBEDTLS_SSL_PROTO_TLS1_2)
77111fa71b9SJerome Forissier         if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 )
77211fa71b9SJerome Forissier         {
77311fa71b9SJerome Forissier             unsigned char mac[MBEDTLS_SSL_MAC_ADD];
774*039e02dfSJerome Forissier             int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
77511fa71b9SJerome Forissier 
7767901324dSJerome Forissier             ssl_extract_add_data_from_record( add_data, &add_data_len, rec,
7777901324dSJerome Forissier                                               transform->minor_ver );
77811fa71b9SJerome Forissier 
779*039e02dfSJerome Forissier             ret = mbedtls_md_hmac_update( &transform->md_ctx_enc,
780*039e02dfSJerome Forissier                                           add_data, add_data_len );
781*039e02dfSJerome Forissier             if( ret != 0 )
782*039e02dfSJerome Forissier                 goto hmac_failed_etm_disabled;
783*039e02dfSJerome Forissier             ret = mbedtls_md_hmac_update( &transform->md_ctx_enc,
78411fa71b9SJerome Forissier                                           data, rec->data_len );
785*039e02dfSJerome Forissier             if( ret != 0 )
786*039e02dfSJerome Forissier                 goto hmac_failed_etm_disabled;
787*039e02dfSJerome Forissier             ret = mbedtls_md_hmac_finish( &transform->md_ctx_enc, mac );
788*039e02dfSJerome Forissier             if( ret != 0 )
789*039e02dfSJerome Forissier                 goto hmac_failed_etm_disabled;
790*039e02dfSJerome Forissier             ret = mbedtls_md_hmac_reset( &transform->md_ctx_enc );
791*039e02dfSJerome Forissier             if( ret != 0 )
792*039e02dfSJerome Forissier                 goto hmac_failed_etm_disabled;
79311fa71b9SJerome Forissier 
79411fa71b9SJerome Forissier             memcpy( data + rec->data_len, mac, transform->maclen );
795*039e02dfSJerome Forissier 
796*039e02dfSJerome Forissier         hmac_failed_etm_disabled:
797*039e02dfSJerome Forissier             mbedtls_platform_zeroize( mac, transform->maclen );
798*039e02dfSJerome Forissier             if( ret != 0 )
799*039e02dfSJerome Forissier             {
800*039e02dfSJerome Forissier                 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_hmac_xxx", ret );
801*039e02dfSJerome Forissier                 return( ret );
802*039e02dfSJerome Forissier             }
80311fa71b9SJerome Forissier         }
80411fa71b9SJerome Forissier         else
80511fa71b9SJerome Forissier #endif
80611fa71b9SJerome Forissier         {
80711fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
80811fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
80911fa71b9SJerome Forissier         }
81011fa71b9SJerome Forissier 
81111fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_BUF( 4, "computed mac", data + rec->data_len,
81211fa71b9SJerome Forissier                                transform->maclen );
81311fa71b9SJerome Forissier 
81411fa71b9SJerome Forissier         rec->data_len += transform->maclen;
81511fa71b9SJerome Forissier         post_avail -= transform->maclen;
81611fa71b9SJerome Forissier         auth_done++;
81711fa71b9SJerome Forissier     }
81811fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */
81911fa71b9SJerome Forissier 
82011fa71b9SJerome Forissier     /*
82111fa71b9SJerome Forissier      * Encrypt
82211fa71b9SJerome Forissier      */
82311fa71b9SJerome Forissier #if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER)
82411fa71b9SJerome Forissier     if( mode == MBEDTLS_MODE_STREAM )
82511fa71b9SJerome Forissier     {
82611fa71b9SJerome Forissier         int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
82711fa71b9SJerome Forissier         size_t olen;
8287901324dSJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %" MBEDTLS_PRINTF_SIZET ", "
82911fa71b9SJerome Forissier                                     "including %d bytes of padding",
83011fa71b9SJerome Forissier                                     rec->data_len, 0 ) );
83111fa71b9SJerome Forissier 
83211fa71b9SJerome Forissier         if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_enc,
83311fa71b9SJerome Forissier                                    transform->iv_enc, transform->ivlen,
83411fa71b9SJerome Forissier                                    data, rec->data_len,
83511fa71b9SJerome Forissier                                    data, &olen ) ) != 0 )
83611fa71b9SJerome Forissier         {
83711fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret );
83811fa71b9SJerome Forissier             return( ret );
83911fa71b9SJerome Forissier         }
84011fa71b9SJerome Forissier 
84111fa71b9SJerome Forissier         if( rec->data_len != olen )
84211fa71b9SJerome Forissier         {
84311fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
84411fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
84511fa71b9SJerome Forissier         }
84611fa71b9SJerome Forissier     }
84711fa71b9SJerome Forissier     else
84811fa71b9SJerome Forissier #endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */
84911fa71b9SJerome Forissier 
85011fa71b9SJerome Forissier #if defined(MBEDTLS_GCM_C) || \
85111fa71b9SJerome Forissier     defined(MBEDTLS_CCM_C) || \
85211fa71b9SJerome Forissier     defined(MBEDTLS_CHACHAPOLY_C)
85311fa71b9SJerome Forissier     if( mode == MBEDTLS_MODE_GCM ||
85411fa71b9SJerome Forissier         mode == MBEDTLS_MODE_CCM ||
85511fa71b9SJerome Forissier         mode == MBEDTLS_MODE_CHACHAPOLY )
85611fa71b9SJerome Forissier     {
85711fa71b9SJerome Forissier         int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
85811fa71b9SJerome Forissier         unsigned char iv[12];
8597901324dSJerome Forissier         unsigned char *dynamic_iv;
8607901324dSJerome Forissier         size_t dynamic_iv_len;
8617901324dSJerome Forissier         int dynamic_iv_is_explicit =
8627901324dSJerome Forissier             ssl_transform_aead_dynamic_iv_is_explicit( transform );
86311fa71b9SJerome Forissier 
8647901324dSJerome Forissier         /* Check that there's space for the authentication tag. */
8657901324dSJerome Forissier         if( post_avail < transform->taglen )
86611fa71b9SJerome Forissier         {
86711fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) );
86811fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
86911fa71b9SJerome Forissier         }
87011fa71b9SJerome Forissier 
87111fa71b9SJerome Forissier         /*
8727901324dSJerome Forissier          * Build nonce for AEAD encryption.
8737901324dSJerome Forissier          *
8747901324dSJerome Forissier          * Note: In the case of CCM and GCM in TLS 1.2, the dynamic
8757901324dSJerome Forissier          *       part of the IV is prepended to the ciphertext and
8767901324dSJerome Forissier          *       can be chosen freely - in particular, it need not
8777901324dSJerome Forissier          *       agree with the record sequence number.
8787901324dSJerome Forissier          *       However, since ChaChaPoly as well as all AEAD modes
8797901324dSJerome Forissier          *       in TLS 1.3 use the record sequence number as the
8807901324dSJerome Forissier          *       dynamic part of the nonce, we uniformly use the
8817901324dSJerome Forissier          *       record sequence number here in all cases.
88211fa71b9SJerome Forissier          */
8837901324dSJerome Forissier         dynamic_iv     = rec->ctr;
8847901324dSJerome Forissier         dynamic_iv_len = sizeof( rec->ctr );
88511fa71b9SJerome Forissier 
8867901324dSJerome Forissier         ssl_build_record_nonce( iv, sizeof( iv ),
8877901324dSJerome Forissier                                 transform->iv_enc,
8887901324dSJerome Forissier                                 transform->fixed_ivlen,
8897901324dSJerome Forissier                                 dynamic_iv,
8907901324dSJerome Forissier                                 dynamic_iv_len );
89111fa71b9SJerome Forissier 
8927901324dSJerome Forissier         /*
8937901324dSJerome Forissier          * Build additional data for AEAD encryption.
8947901324dSJerome Forissier          * This depends on the TLS version.
8957901324dSJerome Forissier          */
8967901324dSJerome Forissier         ssl_extract_add_data_from_record( add_data, &add_data_len, rec,
8977901324dSJerome Forissier                                           transform->minor_ver );
89811fa71b9SJerome Forissier 
89911fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (internal)",
90011fa71b9SJerome Forissier                                iv, transform->ivlen );
90111fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (transmitted)",
9027901324dSJerome Forissier                                dynamic_iv,
9037901324dSJerome Forissier                                dynamic_iv_is_explicit ? dynamic_iv_len : 0 );
90411fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD",
90511fa71b9SJerome Forissier                                add_data, add_data_len );
9067901324dSJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %" MBEDTLS_PRINTF_SIZET ", "
90711fa71b9SJerome Forissier                                     "including 0 bytes of padding",
90811fa71b9SJerome Forissier                                     rec->data_len ) );
90911fa71b9SJerome Forissier 
91011fa71b9SJerome Forissier         /*
91111fa71b9SJerome Forissier          * Encrypt and authenticate
91211fa71b9SJerome Forissier          */
91311fa71b9SJerome Forissier 
9147901324dSJerome Forissier         if( ( ret = mbedtls_cipher_auth_encrypt_ext( &transform->cipher_ctx_enc,
91511fa71b9SJerome Forissier                    iv, transform->ivlen,
9167901324dSJerome Forissier                    add_data, add_data_len,
9177901324dSJerome Forissier                    data, rec->data_len,                     /* src */
9187901324dSJerome Forissier                    data, rec->buf_len - (data - rec->buf),  /* dst */
9197901324dSJerome Forissier                    &rec->data_len,
9207901324dSJerome Forissier                    transform->taglen ) ) != 0 )
92111fa71b9SJerome Forissier         {
92211fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_encrypt", ret );
92311fa71b9SJerome Forissier             return( ret );
92411fa71b9SJerome Forissier         }
92511fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_BUF( 4, "after encrypt: tag",
9267901324dSJerome Forissier                                data + rec->data_len - transform->taglen,
9277901324dSJerome Forissier                                transform->taglen );
9287901324dSJerome Forissier         /* Account for authentication tag. */
92911fa71b9SJerome Forissier         post_avail -= transform->taglen;
9307901324dSJerome Forissier 
9317901324dSJerome Forissier         /*
9327901324dSJerome Forissier          * Prefix record content with dynamic IV in case it is explicit.
9337901324dSJerome Forissier          */
9347901324dSJerome Forissier         if( dynamic_iv_is_explicit != 0 )
9357901324dSJerome Forissier         {
9367901324dSJerome Forissier             if( rec->data_offset < dynamic_iv_len )
9377901324dSJerome Forissier             {
9387901324dSJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) );
9397901324dSJerome Forissier                 return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
9407901324dSJerome Forissier             }
9417901324dSJerome Forissier 
9427901324dSJerome Forissier             memcpy( data - dynamic_iv_len, dynamic_iv, dynamic_iv_len );
9437901324dSJerome Forissier             rec->data_offset -= dynamic_iv_len;
9447901324dSJerome Forissier             rec->data_len    += dynamic_iv_len;
9457901324dSJerome Forissier         }
9467901324dSJerome Forissier 
94711fa71b9SJerome Forissier         auth_done++;
94811fa71b9SJerome Forissier     }
94911fa71b9SJerome Forissier     else
9507901324dSJerome Forissier #endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */
9517901324dSJerome Forissier #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC)
95211fa71b9SJerome Forissier     if( mode == MBEDTLS_MODE_CBC )
95311fa71b9SJerome Forissier     {
95411fa71b9SJerome Forissier         int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
95511fa71b9SJerome Forissier         size_t padlen, i;
95611fa71b9SJerome Forissier         size_t olen;
95711fa71b9SJerome Forissier 
95811fa71b9SJerome Forissier         /* Currently we're always using minimal padding
95911fa71b9SJerome Forissier          * (up to 255 bytes would be allowed). */
96011fa71b9SJerome Forissier         padlen = transform->ivlen - ( rec->data_len + 1 ) % transform->ivlen;
96111fa71b9SJerome Forissier         if( padlen == transform->ivlen )
96211fa71b9SJerome Forissier             padlen = 0;
96311fa71b9SJerome Forissier 
96411fa71b9SJerome Forissier         /* Check there's enough space in the buffer for the padding. */
96511fa71b9SJerome Forissier         if( post_avail < padlen + 1 )
96611fa71b9SJerome Forissier         {
96711fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) );
96811fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
96911fa71b9SJerome Forissier         }
97011fa71b9SJerome Forissier 
97111fa71b9SJerome Forissier         for( i = 0; i <= padlen; i++ )
97211fa71b9SJerome Forissier             data[rec->data_len + i] = (unsigned char) padlen;
97311fa71b9SJerome Forissier 
97411fa71b9SJerome Forissier         rec->data_len += padlen + 1;
97511fa71b9SJerome Forissier         post_avail -= padlen + 1;
97611fa71b9SJerome Forissier 
97711fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)
97811fa71b9SJerome Forissier         /*
97911fa71b9SJerome Forissier          * Prepend per-record IV for block cipher in TLS v1.1 and up as per
98011fa71b9SJerome Forissier          * Method 1 (6.2.3.2. in RFC4346 and RFC5246)
98111fa71b9SJerome Forissier          */
98211fa71b9SJerome Forissier         if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
98311fa71b9SJerome Forissier         {
98411fa71b9SJerome Forissier             if( f_rng == NULL )
98511fa71b9SJerome Forissier             {
98611fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "No PRNG provided to encrypt_record routine" ) );
98711fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
98811fa71b9SJerome Forissier             }
98911fa71b9SJerome Forissier 
99011fa71b9SJerome Forissier             if( rec->data_offset < transform->ivlen )
99111fa71b9SJerome Forissier             {
99211fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) );
99311fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
99411fa71b9SJerome Forissier             }
99511fa71b9SJerome Forissier 
99611fa71b9SJerome Forissier             /*
99711fa71b9SJerome Forissier              * Generate IV
99811fa71b9SJerome Forissier              */
99911fa71b9SJerome Forissier             ret = f_rng( p_rng, transform->iv_enc, transform->ivlen );
100011fa71b9SJerome Forissier             if( ret != 0 )
100111fa71b9SJerome Forissier                 return( ret );
100211fa71b9SJerome Forissier 
100311fa71b9SJerome Forissier             memcpy( data - transform->ivlen, transform->iv_enc,
100411fa71b9SJerome Forissier                     transform->ivlen );
100511fa71b9SJerome Forissier 
100611fa71b9SJerome Forissier         }
100711fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */
100811fa71b9SJerome Forissier 
10097901324dSJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %" MBEDTLS_PRINTF_SIZET ", "
10107901324dSJerome Forissier                             "including %" MBEDTLS_PRINTF_SIZET
10117901324dSJerome Forissier                             " bytes of IV and %" MBEDTLS_PRINTF_SIZET " bytes of padding",
101211fa71b9SJerome Forissier                             rec->data_len, transform->ivlen,
101311fa71b9SJerome Forissier                             padlen + 1 ) );
101411fa71b9SJerome Forissier 
101511fa71b9SJerome Forissier         if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_enc,
101611fa71b9SJerome Forissier                                    transform->iv_enc,
101711fa71b9SJerome Forissier                                    transform->ivlen,
101811fa71b9SJerome Forissier                                    data, rec->data_len,
101911fa71b9SJerome Forissier                                    data, &olen ) ) != 0 )
102011fa71b9SJerome Forissier         {
102111fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret );
102211fa71b9SJerome Forissier             return( ret );
102311fa71b9SJerome Forissier         }
102411fa71b9SJerome Forissier 
102511fa71b9SJerome Forissier         if( rec->data_len != olen )
102611fa71b9SJerome Forissier         {
102711fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
102811fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
102911fa71b9SJerome Forissier         }
103011fa71b9SJerome Forissier 
103111fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1)
103211fa71b9SJerome Forissier         if( transform->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 )
103311fa71b9SJerome Forissier         {
103411fa71b9SJerome Forissier             /*
103511fa71b9SJerome Forissier              * Save IV in SSL3 and TLS1
103611fa71b9SJerome Forissier              */
103711fa71b9SJerome Forissier             memcpy( transform->iv_enc, transform->cipher_ctx_enc.iv,
103811fa71b9SJerome Forissier                     transform->ivlen );
103911fa71b9SJerome Forissier         }
104011fa71b9SJerome Forissier         else
104111fa71b9SJerome Forissier #endif
104211fa71b9SJerome Forissier         {
104311fa71b9SJerome Forissier             data             -= transform->ivlen;
104411fa71b9SJerome Forissier             rec->data_offset -= transform->ivlen;
104511fa71b9SJerome Forissier             rec->data_len    += transform->ivlen;
104611fa71b9SJerome Forissier         }
104711fa71b9SJerome Forissier 
104811fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
104911fa71b9SJerome Forissier         if( auth_done == 0 )
105011fa71b9SJerome Forissier         {
105111fa71b9SJerome Forissier             unsigned char mac[MBEDTLS_SSL_MAC_ADD];
105211fa71b9SJerome Forissier 
105311fa71b9SJerome Forissier             /*
105411fa71b9SJerome Forissier              * MAC(MAC_write_key, seq_num +
105511fa71b9SJerome Forissier              *     TLSCipherText.type +
105611fa71b9SJerome Forissier              *     TLSCipherText.version +
105711fa71b9SJerome Forissier              *     length_of( (IV +) ENC(...) ) +
105811fa71b9SJerome Forissier              *     IV + // except for TLS 1.0
105911fa71b9SJerome Forissier              *     ENC(content + padding + padding_length));
106011fa71b9SJerome Forissier              */
106111fa71b9SJerome Forissier 
106211fa71b9SJerome Forissier             if( post_avail < transform->maclen)
106311fa71b9SJerome Forissier             {
106411fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) );
106511fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
106611fa71b9SJerome Forissier             }
106711fa71b9SJerome Forissier 
10687901324dSJerome Forissier             ssl_extract_add_data_from_record( add_data, &add_data_len,
10697901324dSJerome Forissier                                               rec, transform->minor_ver );
107011fa71b9SJerome Forissier 
107111fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) );
107211fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", add_data,
107311fa71b9SJerome Forissier                                    add_data_len );
107411fa71b9SJerome Forissier 
1075*039e02dfSJerome Forissier             ret = mbedtls_md_hmac_update( &transform->md_ctx_enc, add_data,
107611fa71b9SJerome Forissier                                           add_data_len );
1077*039e02dfSJerome Forissier             if( ret != 0 )
1078*039e02dfSJerome Forissier                 goto hmac_failed_etm_enabled;
1079*039e02dfSJerome Forissier             ret = mbedtls_md_hmac_update( &transform->md_ctx_enc,
108011fa71b9SJerome Forissier                                           data, rec->data_len );
1081*039e02dfSJerome Forissier             if( ret != 0 )
1082*039e02dfSJerome Forissier                 goto hmac_failed_etm_enabled;
1083*039e02dfSJerome Forissier             ret = mbedtls_md_hmac_finish( &transform->md_ctx_enc, mac );
1084*039e02dfSJerome Forissier             if( ret != 0 )
1085*039e02dfSJerome Forissier                 goto hmac_failed_etm_enabled;
1086*039e02dfSJerome Forissier             ret = mbedtls_md_hmac_reset( &transform->md_ctx_enc );
1087*039e02dfSJerome Forissier             if( ret != 0 )
1088*039e02dfSJerome Forissier                 goto hmac_failed_etm_enabled;
108911fa71b9SJerome Forissier 
109011fa71b9SJerome Forissier             memcpy( data + rec->data_len, mac, transform->maclen );
109111fa71b9SJerome Forissier 
109211fa71b9SJerome Forissier             rec->data_len += transform->maclen;
109311fa71b9SJerome Forissier             post_avail -= transform->maclen;
109411fa71b9SJerome Forissier             auth_done++;
1095*039e02dfSJerome Forissier 
1096*039e02dfSJerome Forissier         hmac_failed_etm_enabled:
1097*039e02dfSJerome Forissier             mbedtls_platform_zeroize( mac, transform->maclen );
1098*039e02dfSJerome Forissier             if( ret != 0 )
1099*039e02dfSJerome Forissier             {
1100*039e02dfSJerome Forissier                 MBEDTLS_SSL_DEBUG_RET( 1, "HMAC calculation failed", ret );
1101*039e02dfSJerome Forissier                 return( ret );
1102*039e02dfSJerome Forissier             }
110311fa71b9SJerome Forissier         }
110411fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
110511fa71b9SJerome Forissier     }
110611fa71b9SJerome Forissier     else
11077901324dSJerome Forissier #endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC) */
110811fa71b9SJerome Forissier     {
110911fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
111011fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
111111fa71b9SJerome Forissier     }
111211fa71b9SJerome Forissier 
111311fa71b9SJerome Forissier     /* Make extra sure authentication was performed, exactly once */
111411fa71b9SJerome Forissier     if( auth_done != 1 )
111511fa71b9SJerome Forissier     {
111611fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
111711fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
111811fa71b9SJerome Forissier     }
111911fa71b9SJerome Forissier 
112011fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= encrypt buf" ) );
112111fa71b9SJerome Forissier 
112211fa71b9SJerome Forissier     return( 0 );
112311fa71b9SJerome Forissier }
112411fa71b9SJerome Forissier 
112511fa71b9SJerome Forissier int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl,
112611fa71b9SJerome Forissier                              mbedtls_ssl_transform *transform,
112711fa71b9SJerome Forissier                              mbedtls_record *rec )
112811fa71b9SJerome Forissier {
112911fa71b9SJerome Forissier     size_t olen;
113011fa71b9SJerome Forissier     mbedtls_cipher_mode_t mode;
113111fa71b9SJerome Forissier     int ret, auth_done = 0;
113211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
113311fa71b9SJerome Forissier     size_t padlen = 0, correct = 1;
113411fa71b9SJerome Forissier #endif
113511fa71b9SJerome Forissier     unsigned char* data;
113611fa71b9SJerome Forissier     unsigned char add_data[13 + 1 + MBEDTLS_SSL_CID_IN_LEN_MAX ];
113711fa71b9SJerome Forissier     size_t add_data_len;
113811fa71b9SJerome Forissier 
113911fa71b9SJerome Forissier #if !defined(MBEDTLS_DEBUG_C)
114011fa71b9SJerome Forissier     ssl = NULL; /* make sure we don't use it except for debug */
114111fa71b9SJerome Forissier     ((void) ssl);
114211fa71b9SJerome Forissier #endif
114311fa71b9SJerome Forissier 
114411fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decrypt buf" ) );
114511fa71b9SJerome Forissier     if( rec == NULL                     ||
114611fa71b9SJerome Forissier         rec->buf == NULL                ||
114711fa71b9SJerome Forissier         rec->buf_len < rec->data_offset ||
114811fa71b9SJerome Forissier         rec->buf_len - rec->data_offset < rec->data_len )
114911fa71b9SJerome Forissier     {
115011fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad record structure provided to decrypt_buf" ) );
115111fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
115211fa71b9SJerome Forissier     }
115311fa71b9SJerome Forissier 
115411fa71b9SJerome Forissier     data = rec->buf + rec->data_offset;
115511fa71b9SJerome Forissier     mode = mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_dec );
115611fa71b9SJerome Forissier 
115711fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
115811fa71b9SJerome Forissier     /*
115911fa71b9SJerome Forissier      * Match record's CID with incoming CID.
116011fa71b9SJerome Forissier      */
116111fa71b9SJerome Forissier     if( rec->cid_len != transform->in_cid_len ||
116211fa71b9SJerome Forissier         memcmp( rec->cid, transform->in_cid, rec->cid_len ) != 0 )
116311fa71b9SJerome Forissier     {
116411fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_UNEXPECTED_CID );
116511fa71b9SJerome Forissier     }
116611fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
116711fa71b9SJerome Forissier 
116811fa71b9SJerome Forissier #if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER)
116911fa71b9SJerome Forissier     if( mode == MBEDTLS_MODE_STREAM )
117011fa71b9SJerome Forissier     {
117111fa71b9SJerome Forissier         padlen = 0;
117211fa71b9SJerome Forissier         if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_dec,
117311fa71b9SJerome Forissier                                    transform->iv_dec,
117411fa71b9SJerome Forissier                                    transform->ivlen,
117511fa71b9SJerome Forissier                                    data, rec->data_len,
117611fa71b9SJerome Forissier                                    data, &olen ) ) != 0 )
117711fa71b9SJerome Forissier         {
117811fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret );
117911fa71b9SJerome Forissier             return( ret );
118011fa71b9SJerome Forissier         }
118111fa71b9SJerome Forissier 
118211fa71b9SJerome Forissier         if( rec->data_len != olen )
118311fa71b9SJerome Forissier         {
118411fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
118511fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
118611fa71b9SJerome Forissier         }
118711fa71b9SJerome Forissier     }
118811fa71b9SJerome Forissier     else
118911fa71b9SJerome Forissier #endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */
119011fa71b9SJerome Forissier #if defined(MBEDTLS_GCM_C) || \
119111fa71b9SJerome Forissier     defined(MBEDTLS_CCM_C) || \
119211fa71b9SJerome Forissier     defined(MBEDTLS_CHACHAPOLY_C)
119311fa71b9SJerome Forissier     if( mode == MBEDTLS_MODE_GCM ||
119411fa71b9SJerome Forissier         mode == MBEDTLS_MODE_CCM ||
119511fa71b9SJerome Forissier         mode == MBEDTLS_MODE_CHACHAPOLY )
119611fa71b9SJerome Forissier     {
119711fa71b9SJerome Forissier         unsigned char iv[12];
11987901324dSJerome Forissier         unsigned char *dynamic_iv;
11997901324dSJerome Forissier         size_t dynamic_iv_len;
120011fa71b9SJerome Forissier 
120111fa71b9SJerome Forissier         /*
12027901324dSJerome Forissier          * Extract dynamic part of nonce for AEAD decryption.
12037901324dSJerome Forissier          *
12047901324dSJerome Forissier          * Note: In the case of CCM and GCM in TLS 1.2, the dynamic
12057901324dSJerome Forissier          *       part of the IV is prepended to the ciphertext and
12067901324dSJerome Forissier          *       can be chosen freely - in particular, it need not
12077901324dSJerome Forissier          *       agree with the record sequence number.
120811fa71b9SJerome Forissier          */
12097901324dSJerome Forissier         dynamic_iv_len = sizeof( rec->ctr );
12107901324dSJerome Forissier         if( ssl_transform_aead_dynamic_iv_is_explicit( transform ) == 1 )
121111fa71b9SJerome Forissier         {
12127901324dSJerome Forissier             if( rec->data_len < dynamic_iv_len )
12137901324dSJerome Forissier             {
12147901324dSJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%" MBEDTLS_PRINTF_SIZET
12157901324dSJerome Forissier                                             " ) < explicit_iv_len (%" MBEDTLS_PRINTF_SIZET ") ",
12167901324dSJerome Forissier                                             rec->data_len,
12177901324dSJerome Forissier                                             dynamic_iv_len ) );
121811fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_INVALID_MAC );
121911fa71b9SJerome Forissier             }
12207901324dSJerome Forissier             dynamic_iv = data;
122111fa71b9SJerome Forissier 
12227901324dSJerome Forissier             data += dynamic_iv_len;
12237901324dSJerome Forissier             rec->data_offset += dynamic_iv_len;
12247901324dSJerome Forissier             rec->data_len    -= dynamic_iv_len;
122511fa71b9SJerome Forissier         }
122611fa71b9SJerome Forissier         else
122711fa71b9SJerome Forissier         {
12287901324dSJerome Forissier             dynamic_iv = rec->ctr;
122911fa71b9SJerome Forissier         }
123011fa71b9SJerome Forissier 
12317901324dSJerome Forissier         /* Check that there's space for the authentication tag. */
12327901324dSJerome Forissier         if( rec->data_len < transform->taglen )
12337901324dSJerome Forissier         {
12347901324dSJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%" MBEDTLS_PRINTF_SIZET
12357901324dSJerome Forissier                                         ") < taglen (%" MBEDTLS_PRINTF_SIZET ") ",
12367901324dSJerome Forissier                                         rec->data_len,
12377901324dSJerome Forissier                                         transform->taglen ) );
12387901324dSJerome Forissier             return( MBEDTLS_ERR_SSL_INVALID_MAC );
12397901324dSJerome Forissier         }
12407901324dSJerome Forissier         rec->data_len -= transform->taglen;
124111fa71b9SJerome Forissier 
12427901324dSJerome Forissier         /*
12437901324dSJerome Forissier          * Prepare nonce from dynamic and static parts.
12447901324dSJerome Forissier          */
12457901324dSJerome Forissier         ssl_build_record_nonce( iv, sizeof( iv ),
12467901324dSJerome Forissier                                 transform->iv_dec,
12477901324dSJerome Forissier                                 transform->fixed_ivlen,
12487901324dSJerome Forissier                                 dynamic_iv,
12497901324dSJerome Forissier                                 dynamic_iv_len );
12507901324dSJerome Forissier 
12517901324dSJerome Forissier         /*
12527901324dSJerome Forissier          * Build additional data for AEAD encryption.
12537901324dSJerome Forissier          * This depends on the TLS version.
12547901324dSJerome Forissier          */
12557901324dSJerome Forissier         ssl_extract_add_data_from_record( add_data, &add_data_len, rec,
12567901324dSJerome Forissier                                           transform->minor_ver );
125711fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD",
125811fa71b9SJerome Forissier                                add_data, add_data_len );
125911fa71b9SJerome Forissier 
126011fa71b9SJerome Forissier         /* Because of the check above, we know that there are
1261*039e02dfSJerome Forissier          * explicit_iv_len Bytes preceding data, and taglen
126211fa71b9SJerome Forissier          * bytes following data + data_len. This justifies
126311fa71b9SJerome Forissier          * the debug message and the invocation of
126411fa71b9SJerome Forissier          * mbedtls_cipher_auth_decrypt() below. */
126511fa71b9SJerome Forissier 
126611fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", iv, transform->ivlen );
126711fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_BUF( 4, "TAG used", data + rec->data_len,
126811fa71b9SJerome Forissier                                transform->taglen );
126911fa71b9SJerome Forissier 
127011fa71b9SJerome Forissier         /*
127111fa71b9SJerome Forissier          * Decrypt and authenticate
127211fa71b9SJerome Forissier          */
12737901324dSJerome Forissier         if( ( ret = mbedtls_cipher_auth_decrypt_ext( &transform->cipher_ctx_dec,
127411fa71b9SJerome Forissier                   iv, transform->ivlen,
127511fa71b9SJerome Forissier                   add_data, add_data_len,
12767901324dSJerome Forissier                   data, rec->data_len + transform->taglen,          /* src */
12777901324dSJerome Forissier                   data, rec->buf_len - (data - rec->buf), &olen,    /* dst */
127811fa71b9SJerome Forissier                   transform->taglen ) ) != 0 )
127911fa71b9SJerome Forissier         {
128011fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_decrypt", ret );
128111fa71b9SJerome Forissier 
128211fa71b9SJerome Forissier             if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED )
128311fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_INVALID_MAC );
128411fa71b9SJerome Forissier 
128511fa71b9SJerome Forissier             return( ret );
128611fa71b9SJerome Forissier         }
128711fa71b9SJerome Forissier         auth_done++;
128811fa71b9SJerome Forissier 
128911fa71b9SJerome Forissier         /* Double-check that AEAD decryption doesn't change content length. */
129011fa71b9SJerome Forissier         if( olen != rec->data_len )
129111fa71b9SJerome Forissier         {
129211fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
129311fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
129411fa71b9SJerome Forissier         }
129511fa71b9SJerome Forissier     }
129611fa71b9SJerome Forissier     else
129711fa71b9SJerome Forissier #endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */
12987901324dSJerome Forissier #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC)
129911fa71b9SJerome Forissier     if( mode == MBEDTLS_MODE_CBC )
130011fa71b9SJerome Forissier     {
130111fa71b9SJerome Forissier         size_t minlen = 0;
130211fa71b9SJerome Forissier 
130311fa71b9SJerome Forissier         /*
130411fa71b9SJerome Forissier          * Check immediate ciphertext sanity
130511fa71b9SJerome Forissier          */
130611fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)
130711fa71b9SJerome Forissier         if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
130811fa71b9SJerome Forissier         {
130911fa71b9SJerome Forissier             /* The ciphertext is prefixed with the CBC IV. */
131011fa71b9SJerome Forissier             minlen += transform->ivlen;
131111fa71b9SJerome Forissier         }
131211fa71b9SJerome Forissier #endif
131311fa71b9SJerome Forissier 
131411fa71b9SJerome Forissier         /* Size considerations:
131511fa71b9SJerome Forissier          *
131611fa71b9SJerome Forissier          * - The CBC cipher text must not be empty and hence
131711fa71b9SJerome Forissier          *   at least of size transform->ivlen.
131811fa71b9SJerome Forissier          *
131911fa71b9SJerome Forissier          * Together with the potential IV-prefix, this explains
132011fa71b9SJerome Forissier          * the first of the two checks below.
132111fa71b9SJerome Forissier          *
132211fa71b9SJerome Forissier          * - The record must contain a MAC, either in plain or
132311fa71b9SJerome Forissier          *   encrypted, depending on whether Encrypt-then-MAC
132411fa71b9SJerome Forissier          *   is used or not.
132511fa71b9SJerome Forissier          *   - If it is, the message contains the IV-prefix,
132611fa71b9SJerome Forissier          *     the CBC ciphertext, and the MAC.
132711fa71b9SJerome Forissier          *   - If it is not, the padded plaintext, and hence
132811fa71b9SJerome Forissier          *     the CBC ciphertext, has at least length maclen + 1
132911fa71b9SJerome Forissier          *     because there is at least the padding length byte.
133011fa71b9SJerome Forissier          *
133111fa71b9SJerome Forissier          * As the CBC ciphertext is not empty, both cases give the
133211fa71b9SJerome Forissier          * lower bound minlen + maclen + 1 on the record size, which
133311fa71b9SJerome Forissier          * we test for in the second check below.
133411fa71b9SJerome Forissier          */
133511fa71b9SJerome Forissier         if( rec->data_len < minlen + transform->ivlen ||
133611fa71b9SJerome Forissier             rec->data_len < minlen + transform->maclen + 1 )
133711fa71b9SJerome Forissier         {
13387901324dSJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%" MBEDTLS_PRINTF_SIZET
13397901324dSJerome Forissier                                         ") < max( ivlen(%" MBEDTLS_PRINTF_SIZET
13407901324dSJerome Forissier                                         "), maclen (%" MBEDTLS_PRINTF_SIZET ") "
134111fa71b9SJerome Forissier                                 "+ 1 ) ( + expl IV )", rec->data_len,
134211fa71b9SJerome Forissier                                 transform->ivlen,
134311fa71b9SJerome Forissier                                 transform->maclen ) );
134411fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INVALID_MAC );
134511fa71b9SJerome Forissier         }
134611fa71b9SJerome Forissier 
134711fa71b9SJerome Forissier         /*
134811fa71b9SJerome Forissier          * Authenticate before decrypt if enabled
134911fa71b9SJerome Forissier          */
135011fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
135111fa71b9SJerome Forissier         if( transform->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED )
135211fa71b9SJerome Forissier         {
135311fa71b9SJerome Forissier             unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD];
135411fa71b9SJerome Forissier 
135511fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) );
135611fa71b9SJerome Forissier 
135711fa71b9SJerome Forissier             /* Update data_len in tandem with add_data.
135811fa71b9SJerome Forissier              *
135911fa71b9SJerome Forissier              * The subtraction is safe because of the previous check
136011fa71b9SJerome Forissier              * data_len >= minlen + maclen + 1.
136111fa71b9SJerome Forissier              *
136211fa71b9SJerome Forissier              * Afterwards, we know that data + data_len is followed by at
136311fa71b9SJerome Forissier              * least maclen Bytes, which justifies the call to
1364*039e02dfSJerome Forissier              * mbedtls_ct_memcmp() below.
136511fa71b9SJerome Forissier              *
136611fa71b9SJerome Forissier              * Further, we still know that data_len > minlen */
136711fa71b9SJerome Forissier             rec->data_len -= transform->maclen;
13687901324dSJerome Forissier             ssl_extract_add_data_from_record( add_data, &add_data_len, rec,
13697901324dSJerome Forissier                                               transform->minor_ver );
137011fa71b9SJerome Forissier 
137111fa71b9SJerome Forissier             /* Calculate expected MAC. */
137211fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", add_data,
137311fa71b9SJerome Forissier                                    add_data_len );
1374*039e02dfSJerome Forissier             ret = mbedtls_md_hmac_update( &transform->md_ctx_dec, add_data,
137511fa71b9SJerome Forissier                                           add_data_len );
1376*039e02dfSJerome Forissier             if( ret != 0 )
1377*039e02dfSJerome Forissier                 goto hmac_failed_etm_enabled;
1378*039e02dfSJerome Forissier             ret = mbedtls_md_hmac_update( &transform->md_ctx_dec,
137911fa71b9SJerome Forissier                                     data, rec->data_len );
1380*039e02dfSJerome Forissier             if( ret != 0 )
1381*039e02dfSJerome Forissier                 goto hmac_failed_etm_enabled;
1382*039e02dfSJerome Forissier             ret = mbedtls_md_hmac_finish( &transform->md_ctx_dec, mac_expect );
1383*039e02dfSJerome Forissier             if( ret != 0 )
1384*039e02dfSJerome Forissier                 goto hmac_failed_etm_enabled;
1385*039e02dfSJerome Forissier             ret = mbedtls_md_hmac_reset( &transform->md_ctx_dec );
1386*039e02dfSJerome Forissier             if( ret != 0 )
1387*039e02dfSJerome Forissier                 goto hmac_failed_etm_enabled;
138811fa71b9SJerome Forissier 
138911fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_BUF( 4, "message  mac", data + rec->data_len,
139011fa71b9SJerome Forissier                                    transform->maclen );
139111fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect,
139211fa71b9SJerome Forissier                                    transform->maclen );
139311fa71b9SJerome Forissier 
139411fa71b9SJerome Forissier             /* Compare expected MAC with MAC at the end of the record. */
1395*039e02dfSJerome Forissier             if( mbedtls_ct_memcmp( data + rec->data_len, mac_expect,
139611fa71b9SJerome Forissier                                               transform->maclen ) != 0 )
139711fa71b9SJerome Forissier             {
139811fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) );
1399*039e02dfSJerome Forissier                 ret = MBEDTLS_ERR_SSL_INVALID_MAC;
1400*039e02dfSJerome Forissier                 goto hmac_failed_etm_enabled;
140111fa71b9SJerome Forissier             }
140211fa71b9SJerome Forissier             auth_done++;
1403*039e02dfSJerome Forissier 
1404*039e02dfSJerome Forissier         hmac_failed_etm_enabled:
1405*039e02dfSJerome Forissier             mbedtls_platform_zeroize( mac_expect, transform->maclen );
1406*039e02dfSJerome Forissier             if( ret != 0 )
1407*039e02dfSJerome Forissier             {
1408*039e02dfSJerome Forissier                 if( ret != MBEDTLS_ERR_SSL_INVALID_MAC )
1409*039e02dfSJerome Forissier                     MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_hmac_xxx", ret );
1410*039e02dfSJerome Forissier                 return( ret );
1411*039e02dfSJerome Forissier             }
141211fa71b9SJerome Forissier         }
141311fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
141411fa71b9SJerome Forissier 
141511fa71b9SJerome Forissier         /*
141611fa71b9SJerome Forissier          * Check length sanity
141711fa71b9SJerome Forissier          */
141811fa71b9SJerome Forissier 
141911fa71b9SJerome Forissier         /* We know from above that data_len > minlen >= 0,
142011fa71b9SJerome Forissier          * so the following check in particular implies that
142111fa71b9SJerome Forissier          * data_len >= minlen + ivlen ( = minlen or 2 * minlen ). */
142211fa71b9SJerome Forissier         if( rec->data_len % transform->ivlen != 0 )
142311fa71b9SJerome Forissier         {
14247901324dSJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%" MBEDTLS_PRINTF_SIZET
14257901324dSJerome Forissier                                         ") %% ivlen (%" MBEDTLS_PRINTF_SIZET ") != 0",
142611fa71b9SJerome Forissier                                         rec->data_len, transform->ivlen ) );
142711fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INVALID_MAC );
142811fa71b9SJerome Forissier         }
142911fa71b9SJerome Forissier 
143011fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)
143111fa71b9SJerome Forissier         /*
143211fa71b9SJerome Forissier          * Initialize for prepended IV for block cipher in TLS v1.1 and up
143311fa71b9SJerome Forissier          */
143411fa71b9SJerome Forissier         if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
143511fa71b9SJerome Forissier         {
143611fa71b9SJerome Forissier             /* Safe because data_len >= minlen + ivlen = 2 * ivlen. */
143711fa71b9SJerome Forissier             memcpy( transform->iv_dec, data, transform->ivlen );
143811fa71b9SJerome Forissier 
143911fa71b9SJerome Forissier             data += transform->ivlen;
144011fa71b9SJerome Forissier             rec->data_offset += transform->ivlen;
144111fa71b9SJerome Forissier             rec->data_len -= transform->ivlen;
144211fa71b9SJerome Forissier         }
144311fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */
144411fa71b9SJerome Forissier 
144511fa71b9SJerome Forissier         /* We still have data_len % ivlen == 0 and data_len >= ivlen here. */
144611fa71b9SJerome Forissier 
144711fa71b9SJerome Forissier         if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_dec,
144811fa71b9SJerome Forissier                                    transform->iv_dec, transform->ivlen,
144911fa71b9SJerome Forissier                                    data, rec->data_len, data, &olen ) ) != 0 )
145011fa71b9SJerome Forissier         {
145111fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret );
145211fa71b9SJerome Forissier             return( ret );
145311fa71b9SJerome Forissier         }
145411fa71b9SJerome Forissier 
145511fa71b9SJerome Forissier         /* Double-check that length hasn't changed during decryption. */
145611fa71b9SJerome Forissier         if( rec->data_len != olen )
145711fa71b9SJerome Forissier         {
145811fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
145911fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
146011fa71b9SJerome Forissier         }
146111fa71b9SJerome Forissier 
146211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1)
146311fa71b9SJerome Forissier         if( transform->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 )
146411fa71b9SJerome Forissier         {
146511fa71b9SJerome Forissier             /*
146611fa71b9SJerome Forissier              * Save IV in SSL3 and TLS1, where CBC decryption of consecutive
146711fa71b9SJerome Forissier              * records is equivalent to CBC decryption of the concatenation
146811fa71b9SJerome Forissier              * of the records; in other words, IVs are maintained across
146911fa71b9SJerome Forissier              * record decryptions.
147011fa71b9SJerome Forissier              */
147111fa71b9SJerome Forissier             memcpy( transform->iv_dec, transform->cipher_ctx_dec.iv,
147211fa71b9SJerome Forissier                     transform->ivlen );
147311fa71b9SJerome Forissier         }
147411fa71b9SJerome Forissier #endif
147511fa71b9SJerome Forissier 
147611fa71b9SJerome Forissier         /* Safe since data_len >= minlen + maclen + 1, so after having
147711fa71b9SJerome Forissier          * subtracted at most minlen and maclen up to this point,
147811fa71b9SJerome Forissier          * data_len > 0 (because of data_len % ivlen == 0, it's actually
147911fa71b9SJerome Forissier          * >= ivlen ). */
148011fa71b9SJerome Forissier         padlen = data[rec->data_len - 1];
148111fa71b9SJerome Forissier 
148211fa71b9SJerome Forissier         if( auth_done == 1 )
148311fa71b9SJerome Forissier         {
1484*039e02dfSJerome Forissier             const size_t mask = mbedtls_ct_size_mask_ge(
14857901324dSJerome Forissier                                 rec->data_len,
14867901324dSJerome Forissier                                 padlen + 1 );
14877901324dSJerome Forissier             correct &= mask;
14887901324dSJerome Forissier             padlen  &= mask;
148911fa71b9SJerome Forissier         }
149011fa71b9SJerome Forissier         else
149111fa71b9SJerome Forissier         {
149211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DEBUG_ALL)
149311fa71b9SJerome Forissier             if( rec->data_len < transform->maclen + padlen + 1 )
149411fa71b9SJerome Forissier             {
14957901324dSJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%" MBEDTLS_PRINTF_SIZET
14967901324dSJerome Forissier                                             ") < maclen (%" MBEDTLS_PRINTF_SIZET
14977901324dSJerome Forissier                                             ") + padlen (%" MBEDTLS_PRINTF_SIZET ")",
149811fa71b9SJerome Forissier                                             rec->data_len,
149911fa71b9SJerome Forissier                                             transform->maclen,
150011fa71b9SJerome Forissier                                             padlen + 1 ) );
150111fa71b9SJerome Forissier             }
150211fa71b9SJerome Forissier #endif
150311fa71b9SJerome Forissier 
1504*039e02dfSJerome Forissier             const size_t mask = mbedtls_ct_size_mask_ge(
15057901324dSJerome Forissier                                 rec->data_len,
15067901324dSJerome Forissier                                 transform->maclen + padlen + 1 );
15077901324dSJerome Forissier             correct &= mask;
15087901324dSJerome Forissier             padlen  &= mask;
150911fa71b9SJerome Forissier         }
151011fa71b9SJerome Forissier 
151111fa71b9SJerome Forissier         padlen++;
151211fa71b9SJerome Forissier 
151311fa71b9SJerome Forissier         /* Regardless of the validity of the padding,
151411fa71b9SJerome Forissier          * we have data_len >= padlen here. */
151511fa71b9SJerome Forissier 
151611fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_SSL3)
151711fa71b9SJerome Forissier         if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
151811fa71b9SJerome Forissier         {
15197901324dSJerome Forissier             /* This is the SSL 3.0 path, we don't have to worry about Lucky
15207901324dSJerome Forissier              * 13, because there's a strictly worse padding attack built in
15217901324dSJerome Forissier              * the protocol (known as part of POODLE), so we don't care if the
15227901324dSJerome Forissier              * code is not constant-time, in particular branches are OK. */
152311fa71b9SJerome Forissier             if( padlen > transform->ivlen )
152411fa71b9SJerome Forissier             {
152511fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DEBUG_ALL)
15267901324dSJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding length: is %" MBEDTLS_PRINTF_SIZET ", "
15277901324dSJerome Forissier                                             "should be no more than %" MBEDTLS_PRINTF_SIZET,
152811fa71b9SJerome Forissier                                             padlen, transform->ivlen ) );
152911fa71b9SJerome Forissier #endif
153011fa71b9SJerome Forissier                 correct = 0;
153111fa71b9SJerome Forissier             }
153211fa71b9SJerome Forissier         }
153311fa71b9SJerome Forissier         else
153411fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_SSL3 */
153511fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
153611fa71b9SJerome Forissier     defined(MBEDTLS_SSL_PROTO_TLS1_2)
153711fa71b9SJerome Forissier         if( transform->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0 )
153811fa71b9SJerome Forissier         {
153911fa71b9SJerome Forissier             /* The padding check involves a series of up to 256
154011fa71b9SJerome Forissier              * consecutive memory reads at the end of the record
154111fa71b9SJerome Forissier              * plaintext buffer. In order to hide the length and
154211fa71b9SJerome Forissier              * validity of the padding, always perform exactly
154311fa71b9SJerome Forissier              * `min(256,plaintext_len)` reads (but take into account
154411fa71b9SJerome Forissier              * only the last `padlen` bytes for the padding check). */
154511fa71b9SJerome Forissier             size_t pad_count = 0;
154611fa71b9SJerome Forissier             volatile unsigned char* const check = data;
154711fa71b9SJerome Forissier 
154811fa71b9SJerome Forissier             /* Index of first padding byte; it has been ensured above
154911fa71b9SJerome Forissier              * that the subtraction is safe. */
155011fa71b9SJerome Forissier             size_t const padding_idx = rec->data_len - padlen;
155111fa71b9SJerome Forissier             size_t const num_checks = rec->data_len <= 256 ? rec->data_len : 256;
155211fa71b9SJerome Forissier             size_t const start_idx = rec->data_len - num_checks;
155311fa71b9SJerome Forissier             size_t idx;
155411fa71b9SJerome Forissier 
155511fa71b9SJerome Forissier             for( idx = start_idx; idx < rec->data_len; idx++ )
155611fa71b9SJerome Forissier             {
15577901324dSJerome Forissier                 /* pad_count += (idx >= padding_idx) &&
15587901324dSJerome Forissier                  *              (check[idx] == padlen - 1);
15597901324dSJerome Forissier                  */
1560*039e02dfSJerome Forissier                 const size_t mask = mbedtls_ct_size_mask_ge( idx, padding_idx );
1561*039e02dfSJerome Forissier                 const size_t equal = mbedtls_ct_size_bool_eq( check[idx],
15627901324dSJerome Forissier                                                               padlen - 1 );
15637901324dSJerome Forissier                 pad_count += mask & equal;
156411fa71b9SJerome Forissier             }
1565*039e02dfSJerome Forissier             correct &= mbedtls_ct_size_bool_eq( pad_count, padlen );
156611fa71b9SJerome Forissier 
156711fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DEBUG_ALL)
156811fa71b9SJerome Forissier             if( padlen > 0 && correct == 0 )
156911fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding byte detected" ) );
157011fa71b9SJerome Forissier #endif
1571*039e02dfSJerome Forissier             padlen &= mbedtls_ct_size_mask( correct );
157211fa71b9SJerome Forissier         }
157311fa71b9SJerome Forissier         else
157411fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
157511fa71b9SJerome Forissier           MBEDTLS_SSL_PROTO_TLS1_2 */
157611fa71b9SJerome Forissier         {
157711fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
157811fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
157911fa71b9SJerome Forissier         }
158011fa71b9SJerome Forissier 
158111fa71b9SJerome Forissier         /* If the padding was found to be invalid, padlen == 0
158211fa71b9SJerome Forissier          * and the subtraction is safe. If the padding was found valid,
158311fa71b9SJerome Forissier          * padlen hasn't been changed and the previous assertion
158411fa71b9SJerome Forissier          * data_len >= padlen still holds. */
158511fa71b9SJerome Forissier         rec->data_len -= padlen;
158611fa71b9SJerome Forissier     }
158711fa71b9SJerome Forissier     else
15887901324dSJerome Forissier #endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC */
158911fa71b9SJerome Forissier     {
159011fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
159111fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
159211fa71b9SJerome Forissier     }
159311fa71b9SJerome Forissier 
159411fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DEBUG_ALL)
159511fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_BUF( 4, "raw buffer after decryption",
159611fa71b9SJerome Forissier                            data, rec->data_len );
159711fa71b9SJerome Forissier #endif
159811fa71b9SJerome Forissier 
159911fa71b9SJerome Forissier     /*
160011fa71b9SJerome Forissier      * Authenticate if not done yet.
160111fa71b9SJerome Forissier      * Compute the MAC regardless of the padding result (RFC4346, CBCTIME).
160211fa71b9SJerome Forissier      */
160311fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
160411fa71b9SJerome Forissier     if( auth_done == 0 )
160511fa71b9SJerome Forissier     {
1606*039e02dfSJerome Forissier         unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD] = { 0 };
1607*039e02dfSJerome Forissier         unsigned char mac_peer[MBEDTLS_SSL_MAC_ADD] = { 0 };
160811fa71b9SJerome Forissier 
160911fa71b9SJerome Forissier         /* If the initial value of padlen was such that
161011fa71b9SJerome Forissier          * data_len < maclen + padlen + 1, then padlen
161111fa71b9SJerome Forissier          * got reset to 1, and the initial check
161211fa71b9SJerome Forissier          * data_len >= minlen + maclen + 1
161311fa71b9SJerome Forissier          * guarantees that at this point we still
161411fa71b9SJerome Forissier          * have at least data_len >= maclen.
161511fa71b9SJerome Forissier          *
161611fa71b9SJerome Forissier          * If the initial value of padlen was such that
161711fa71b9SJerome Forissier          * data_len >= maclen + padlen + 1, then we have
161811fa71b9SJerome Forissier          * subtracted either padlen + 1 (if the padding was correct)
161911fa71b9SJerome Forissier          * or 0 (if the padding was incorrect) since then,
162011fa71b9SJerome Forissier          * hence data_len >= maclen in any case.
162111fa71b9SJerome Forissier          */
162211fa71b9SJerome Forissier         rec->data_len -= transform->maclen;
16237901324dSJerome Forissier         ssl_extract_add_data_from_record( add_data, &add_data_len, rec,
16247901324dSJerome Forissier                                           transform->minor_ver );
162511fa71b9SJerome Forissier 
162611fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_SSL3)
162711fa71b9SJerome Forissier         if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
162811fa71b9SJerome Forissier         {
1629*039e02dfSJerome Forissier             ret = ssl_mac( &transform->md_ctx_dec,
163011fa71b9SJerome Forissier                            transform->mac_dec,
163111fa71b9SJerome Forissier                            data, rec->data_len,
163211fa71b9SJerome Forissier                            rec->ctr, rec->type,
163311fa71b9SJerome Forissier                            mac_expect );
1634*039e02dfSJerome Forissier             if( ret != 0 )
1635*039e02dfSJerome Forissier             {
1636*039e02dfSJerome Forissier                 MBEDTLS_SSL_DEBUG_RET( 1, "ssl_mac", ret );
1637*039e02dfSJerome Forissier                 goto hmac_failed_etm_disabled;
1638*039e02dfSJerome Forissier             }
16397901324dSJerome Forissier             memcpy( mac_peer, data + rec->data_len, transform->maclen );
164011fa71b9SJerome Forissier         }
164111fa71b9SJerome Forissier         else
164211fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_SSL3 */
164311fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
164411fa71b9SJerome Forissier         defined(MBEDTLS_SSL_PROTO_TLS1_2)
164511fa71b9SJerome Forissier         if( transform->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0 )
164611fa71b9SJerome Forissier         {
164711fa71b9SJerome Forissier             /*
164811fa71b9SJerome Forissier              * The next two sizes are the minimum and maximum values of
16497901324dSJerome Forissier              * data_len over all padlen values.
165011fa71b9SJerome Forissier              *
165111fa71b9SJerome Forissier              * They're independent of padlen, since we previously did
165211fa71b9SJerome Forissier              * data_len -= padlen.
165311fa71b9SJerome Forissier              *
165411fa71b9SJerome Forissier              * Note that max_len + maclen is never more than the buffer
165511fa71b9SJerome Forissier              * length, as we previously did in_msglen -= maclen too.
165611fa71b9SJerome Forissier              */
165711fa71b9SJerome Forissier             const size_t max_len = rec->data_len + padlen;
165811fa71b9SJerome Forissier             const size_t min_len = ( max_len > 256 ) ? max_len - 256 : 0;
165911fa71b9SJerome Forissier 
1660*039e02dfSJerome Forissier             ret = mbedtls_ct_hmac( &transform->md_ctx_dec,
16617901324dSJerome Forissier                                    add_data, add_data_len,
16627901324dSJerome Forissier                                    data, rec->data_len, min_len, max_len,
16637901324dSJerome Forissier                                    mac_expect );
16647901324dSJerome Forissier             if( ret != 0 )
166511fa71b9SJerome Forissier             {
1666*039e02dfSJerome Forissier                 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ct_hmac", ret );
1667*039e02dfSJerome Forissier                 goto hmac_failed_etm_disabled;
166811fa71b9SJerome Forissier             }
166911fa71b9SJerome Forissier 
1670*039e02dfSJerome Forissier             mbedtls_ct_memcpy_offset( mac_peer, data,
16717901324dSJerome Forissier                                       rec->data_len,
16727901324dSJerome Forissier                                       min_len, max_len,
16737901324dSJerome Forissier                                       transform->maclen );
167411fa71b9SJerome Forissier         }
167511fa71b9SJerome Forissier         else
167611fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
167711fa71b9SJerome Forissier               MBEDTLS_SSL_PROTO_TLS1_2 */
167811fa71b9SJerome Forissier         {
167911fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
168011fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
168111fa71b9SJerome Forissier         }
168211fa71b9SJerome Forissier 
168311fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DEBUG_ALL)
168411fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect, transform->maclen );
16857901324dSJerome Forissier         MBEDTLS_SSL_DEBUG_BUF( 4, "message  mac", mac_peer, transform->maclen );
168611fa71b9SJerome Forissier #endif
168711fa71b9SJerome Forissier 
1688*039e02dfSJerome Forissier         if( mbedtls_ct_memcmp( mac_peer, mac_expect,
168911fa71b9SJerome Forissier                                           transform->maclen ) != 0 )
169011fa71b9SJerome Forissier         {
169111fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DEBUG_ALL)
169211fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) );
169311fa71b9SJerome Forissier #endif
169411fa71b9SJerome Forissier             correct = 0;
169511fa71b9SJerome Forissier         }
169611fa71b9SJerome Forissier         auth_done++;
1697*039e02dfSJerome Forissier 
1698*039e02dfSJerome Forissier     hmac_failed_etm_disabled:
1699*039e02dfSJerome Forissier         mbedtls_platform_zeroize( mac_peer, transform->maclen );
1700*039e02dfSJerome Forissier         mbedtls_platform_zeroize( mac_expect, transform->maclen );
1701*039e02dfSJerome Forissier         if( ret != 0 )
1702*039e02dfSJerome Forissier             return( ret );
170311fa71b9SJerome Forissier     }
170411fa71b9SJerome Forissier 
170511fa71b9SJerome Forissier     /*
170611fa71b9SJerome Forissier      * Finally check the correct flag
170711fa71b9SJerome Forissier      */
170811fa71b9SJerome Forissier     if( correct == 0 )
170911fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INVALID_MAC );
171011fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */
171111fa71b9SJerome Forissier 
171211fa71b9SJerome Forissier     /* Make extra sure authentication was performed, exactly once */
171311fa71b9SJerome Forissier     if( auth_done != 1 )
171411fa71b9SJerome Forissier     {
171511fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
171611fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
171711fa71b9SJerome Forissier     }
171811fa71b9SJerome Forissier 
17197901324dSJerome Forissier #if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
17207901324dSJerome Forissier     if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_4 )
17217901324dSJerome Forissier     {
17227901324dSJerome Forissier         /* Remove inner padding and infer true content type. */
17237901324dSJerome Forissier         ret = ssl_parse_inner_plaintext( data, &rec->data_len,
17247901324dSJerome Forissier                                          &rec->type );
17257901324dSJerome Forissier 
17267901324dSJerome Forissier         if( ret != 0 )
17277901324dSJerome Forissier             return( MBEDTLS_ERR_SSL_INVALID_RECORD );
17287901324dSJerome Forissier     }
17297901324dSJerome Forissier #endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
17307901324dSJerome Forissier 
173111fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
173211fa71b9SJerome Forissier     if( rec->cid_len != 0 )
173311fa71b9SJerome Forissier     {
17347901324dSJerome Forissier         ret = ssl_parse_inner_plaintext( data, &rec->data_len,
173511fa71b9SJerome Forissier                                          &rec->type );
173611fa71b9SJerome Forissier         if( ret != 0 )
173711fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INVALID_RECORD );
173811fa71b9SJerome Forissier     }
173911fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
174011fa71b9SJerome Forissier 
174111fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= decrypt buf" ) );
174211fa71b9SJerome Forissier 
174311fa71b9SJerome Forissier     return( 0 );
174411fa71b9SJerome Forissier }
174511fa71b9SJerome Forissier 
174611fa71b9SJerome Forissier #undef MAC_NONE
174711fa71b9SJerome Forissier #undef MAC_PLAINTEXT
174811fa71b9SJerome Forissier #undef MAC_CIPHERTEXT
174911fa71b9SJerome Forissier 
175011fa71b9SJerome Forissier #if defined(MBEDTLS_ZLIB_SUPPORT)
175111fa71b9SJerome Forissier /*
175211fa71b9SJerome Forissier  * Compression/decompression functions
175311fa71b9SJerome Forissier  */
1754*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
175511fa71b9SJerome Forissier static int ssl_compress_buf( mbedtls_ssl_context *ssl )
175611fa71b9SJerome Forissier {
175711fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
175811fa71b9SJerome Forissier     unsigned char *msg_post = ssl->out_msg;
175911fa71b9SJerome Forissier     ptrdiff_t bytes_written = ssl->out_msg - ssl->out_buf;
176011fa71b9SJerome Forissier     size_t len_pre = ssl->out_msglen;
176111fa71b9SJerome Forissier     unsigned char *msg_pre = ssl->compress_buf;
176211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
176311fa71b9SJerome Forissier     size_t out_buf_len = ssl->out_buf_len;
176411fa71b9SJerome Forissier #else
176511fa71b9SJerome Forissier     size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN;
176611fa71b9SJerome Forissier #endif
176711fa71b9SJerome Forissier 
176811fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> compress buf" ) );
176911fa71b9SJerome Forissier 
177011fa71b9SJerome Forissier     if( len_pre == 0 )
177111fa71b9SJerome Forissier         return( 0 );
177211fa71b9SJerome Forissier 
177311fa71b9SJerome Forissier     memcpy( msg_pre, ssl->out_msg, len_pre );
177411fa71b9SJerome Forissier 
17757901324dSJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 3, ( "before compression: msglen = %" MBEDTLS_PRINTF_SIZET ", ",
177611fa71b9SJerome Forissier                    ssl->out_msglen ) );
177711fa71b9SJerome Forissier 
177811fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_BUF( 4, "before compression: output payload",
177911fa71b9SJerome Forissier                    ssl->out_msg, ssl->out_msglen );
178011fa71b9SJerome Forissier 
178111fa71b9SJerome Forissier     ssl->transform_out->ctx_deflate.next_in = msg_pre;
178211fa71b9SJerome Forissier     ssl->transform_out->ctx_deflate.avail_in = len_pre;
178311fa71b9SJerome Forissier     ssl->transform_out->ctx_deflate.next_out = msg_post;
178411fa71b9SJerome Forissier     ssl->transform_out->ctx_deflate.avail_out = out_buf_len - bytes_written;
178511fa71b9SJerome Forissier 
178611fa71b9SJerome Forissier     ret = deflate( &ssl->transform_out->ctx_deflate, Z_SYNC_FLUSH );
178711fa71b9SJerome Forissier     if( ret != Z_OK )
178811fa71b9SJerome Forissier     {
178911fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "failed to perform compression (%d)", ret ) );
179011fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED );
179111fa71b9SJerome Forissier     }
179211fa71b9SJerome Forissier 
179311fa71b9SJerome Forissier     ssl->out_msglen = out_buf_len -
179411fa71b9SJerome Forissier                       ssl->transform_out->ctx_deflate.avail_out - bytes_written;
179511fa71b9SJerome Forissier 
17967901324dSJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 3, ( "after compression: msglen = %" MBEDTLS_PRINTF_SIZET ", ",
179711fa71b9SJerome Forissier                    ssl->out_msglen ) );
179811fa71b9SJerome Forissier 
179911fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_BUF( 4, "after compression: output payload",
180011fa71b9SJerome Forissier                    ssl->out_msg, ssl->out_msglen );
180111fa71b9SJerome Forissier 
180211fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= compress buf" ) );
180311fa71b9SJerome Forissier 
180411fa71b9SJerome Forissier     return( 0 );
180511fa71b9SJerome Forissier }
180611fa71b9SJerome Forissier 
1807*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
180811fa71b9SJerome Forissier static int ssl_decompress_buf( mbedtls_ssl_context *ssl )
180911fa71b9SJerome Forissier {
181011fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
181111fa71b9SJerome Forissier     unsigned char *msg_post = ssl->in_msg;
181211fa71b9SJerome Forissier     ptrdiff_t header_bytes = ssl->in_msg - ssl->in_buf;
181311fa71b9SJerome Forissier     size_t len_pre = ssl->in_msglen;
181411fa71b9SJerome Forissier     unsigned char *msg_pre = ssl->compress_buf;
181511fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
181611fa71b9SJerome Forissier     size_t in_buf_len = ssl->in_buf_len;
181711fa71b9SJerome Forissier #else
181811fa71b9SJerome Forissier     size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN;
181911fa71b9SJerome Forissier #endif
182011fa71b9SJerome Forissier 
182111fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decompress buf" ) );
182211fa71b9SJerome Forissier 
182311fa71b9SJerome Forissier     if( len_pre == 0 )
182411fa71b9SJerome Forissier         return( 0 );
182511fa71b9SJerome Forissier 
182611fa71b9SJerome Forissier     memcpy( msg_pre, ssl->in_msg, len_pre );
182711fa71b9SJerome Forissier 
18287901324dSJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 3, ( "before decompression: msglen = %" MBEDTLS_PRINTF_SIZET ", ",
182911fa71b9SJerome Forissier                    ssl->in_msglen ) );
183011fa71b9SJerome Forissier 
183111fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_BUF( 4, "before decompression: input payload",
183211fa71b9SJerome Forissier                    ssl->in_msg, ssl->in_msglen );
183311fa71b9SJerome Forissier 
183411fa71b9SJerome Forissier     ssl->transform_in->ctx_inflate.next_in = msg_pre;
183511fa71b9SJerome Forissier     ssl->transform_in->ctx_inflate.avail_in = len_pre;
183611fa71b9SJerome Forissier     ssl->transform_in->ctx_inflate.next_out = msg_post;
183711fa71b9SJerome Forissier     ssl->transform_in->ctx_inflate.avail_out = in_buf_len - header_bytes;
183811fa71b9SJerome Forissier 
183911fa71b9SJerome Forissier     ret = inflate( &ssl->transform_in->ctx_inflate, Z_SYNC_FLUSH );
184011fa71b9SJerome Forissier     if( ret != Z_OK )
184111fa71b9SJerome Forissier     {
184211fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "failed to perform decompression (%d)", ret ) );
184311fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED );
184411fa71b9SJerome Forissier     }
184511fa71b9SJerome Forissier 
184611fa71b9SJerome Forissier     ssl->in_msglen = in_buf_len -
184711fa71b9SJerome Forissier                      ssl->transform_in->ctx_inflate.avail_out - header_bytes;
184811fa71b9SJerome Forissier 
18497901324dSJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 3, ( "after decompression: msglen = %" MBEDTLS_PRINTF_SIZET ", ",
185011fa71b9SJerome Forissier                    ssl->in_msglen ) );
185111fa71b9SJerome Forissier 
185211fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_BUF( 4, "after decompression: input payload",
185311fa71b9SJerome Forissier                    ssl->in_msg, ssl->in_msglen );
185411fa71b9SJerome Forissier 
185511fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= decompress buf" ) );
185611fa71b9SJerome Forissier 
185711fa71b9SJerome Forissier     return( 0 );
185811fa71b9SJerome Forissier }
185911fa71b9SJerome Forissier #endif /* MBEDTLS_ZLIB_SUPPORT */
186011fa71b9SJerome Forissier 
186111fa71b9SJerome Forissier /*
186211fa71b9SJerome Forissier  * Fill the input message buffer by appending data to it.
186311fa71b9SJerome Forissier  * The amount of data already fetched is in ssl->in_left.
186411fa71b9SJerome Forissier  *
186511fa71b9SJerome Forissier  * If we return 0, is it guaranteed that (at least) nb_want bytes are
186611fa71b9SJerome Forissier  * available (from this read and/or a previous one). Otherwise, an error code
186711fa71b9SJerome Forissier  * is returned (possibly EOF or WANT_READ).
186811fa71b9SJerome Forissier  *
186911fa71b9SJerome Forissier  * With stream transport (TLS) on success ssl->in_left == nb_want, but
187011fa71b9SJerome Forissier  * with datagram transport (DTLS) on success ssl->in_left >= nb_want,
187111fa71b9SJerome Forissier  * since we always read a whole datagram at once.
187211fa71b9SJerome Forissier  *
187311fa71b9SJerome Forissier  * For DTLS, it is up to the caller to set ssl->next_record_offset when
187411fa71b9SJerome Forissier  * they're done reading a record.
187511fa71b9SJerome Forissier  */
187611fa71b9SJerome Forissier int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want )
187711fa71b9SJerome Forissier {
187811fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
187911fa71b9SJerome Forissier     size_t len;
188011fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
188111fa71b9SJerome Forissier     size_t in_buf_len = ssl->in_buf_len;
188211fa71b9SJerome Forissier #else
188311fa71b9SJerome Forissier     size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN;
188411fa71b9SJerome Forissier #endif
188511fa71b9SJerome Forissier 
188611fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> fetch input" ) );
188711fa71b9SJerome Forissier 
188811fa71b9SJerome Forissier     if( ssl->f_recv == NULL && ssl->f_recv_timeout == NULL )
188911fa71b9SJerome Forissier     {
189011fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() "
189111fa71b9SJerome Forissier                             "or mbedtls_ssl_set_bio()" ) );
189211fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
189311fa71b9SJerome Forissier     }
189411fa71b9SJerome Forissier 
189511fa71b9SJerome Forissier     if( nb_want > in_buf_len - (size_t)( ssl->in_hdr - ssl->in_buf ) )
189611fa71b9SJerome Forissier     {
189711fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "requesting more data than fits" ) );
189811fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
189911fa71b9SJerome Forissier     }
190011fa71b9SJerome Forissier 
190111fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
190211fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
190311fa71b9SJerome Forissier     {
190411fa71b9SJerome Forissier         uint32_t timeout;
190511fa71b9SJerome Forissier 
190611fa71b9SJerome Forissier         /*
190711fa71b9SJerome Forissier          * The point is, we need to always read a full datagram at once, so we
190811fa71b9SJerome Forissier          * sometimes read more then requested, and handle the additional data.
190911fa71b9SJerome Forissier          * It could be the rest of the current record (while fetching the
191011fa71b9SJerome Forissier          * header) and/or some other records in the same datagram.
191111fa71b9SJerome Forissier          */
191211fa71b9SJerome Forissier 
191311fa71b9SJerome Forissier         /*
191411fa71b9SJerome Forissier          * Move to the next record in the already read datagram if applicable
191511fa71b9SJerome Forissier          */
191611fa71b9SJerome Forissier         if( ssl->next_record_offset != 0 )
191711fa71b9SJerome Forissier         {
191811fa71b9SJerome Forissier             if( ssl->in_left < ssl->next_record_offset )
191911fa71b9SJerome Forissier             {
192011fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
192111fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
192211fa71b9SJerome Forissier             }
192311fa71b9SJerome Forissier 
192411fa71b9SJerome Forissier             ssl->in_left -= ssl->next_record_offset;
192511fa71b9SJerome Forissier 
192611fa71b9SJerome Forissier             if( ssl->in_left != 0 )
192711fa71b9SJerome Forissier             {
19287901324dSJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 2, ( "next record in same datagram, offset: %"
19297901324dSJerome Forissier                                             MBEDTLS_PRINTF_SIZET,
193011fa71b9SJerome Forissier                                     ssl->next_record_offset ) );
193111fa71b9SJerome Forissier                 memmove( ssl->in_hdr,
193211fa71b9SJerome Forissier                          ssl->in_hdr + ssl->next_record_offset,
193311fa71b9SJerome Forissier                          ssl->in_left );
193411fa71b9SJerome Forissier             }
193511fa71b9SJerome Forissier 
193611fa71b9SJerome Forissier             ssl->next_record_offset = 0;
193711fa71b9SJerome Forissier         }
193811fa71b9SJerome Forissier 
19397901324dSJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %" MBEDTLS_PRINTF_SIZET
19407901324dSJerome Forissier                                     ", nb_want: %" MBEDTLS_PRINTF_SIZET,
194111fa71b9SJerome Forissier                        ssl->in_left, nb_want ) );
194211fa71b9SJerome Forissier 
194311fa71b9SJerome Forissier         /*
194411fa71b9SJerome Forissier          * Done if we already have enough data.
194511fa71b9SJerome Forissier          */
194611fa71b9SJerome Forissier         if( nb_want <= ssl->in_left)
194711fa71b9SJerome Forissier         {
194811fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) );
194911fa71b9SJerome Forissier             return( 0 );
195011fa71b9SJerome Forissier         }
195111fa71b9SJerome Forissier 
195211fa71b9SJerome Forissier         /*
195311fa71b9SJerome Forissier          * A record can't be split across datagrams. If we need to read but
195411fa71b9SJerome Forissier          * are not at the beginning of a new record, the caller did something
195511fa71b9SJerome Forissier          * wrong.
195611fa71b9SJerome Forissier          */
195711fa71b9SJerome Forissier         if( ssl->in_left != 0 )
195811fa71b9SJerome Forissier         {
195911fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
196011fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
196111fa71b9SJerome Forissier         }
196211fa71b9SJerome Forissier 
196311fa71b9SJerome Forissier         /*
196411fa71b9SJerome Forissier          * Don't even try to read if time's out already.
196511fa71b9SJerome Forissier          * This avoids by-passing the timer when repeatedly receiving messages
196611fa71b9SJerome Forissier          * that will end up being dropped.
196711fa71b9SJerome Forissier          */
196811fa71b9SJerome Forissier         if( mbedtls_ssl_check_timer( ssl ) != 0 )
196911fa71b9SJerome Forissier         {
197011fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 2, ( "timer has expired" ) );
197111fa71b9SJerome Forissier             ret = MBEDTLS_ERR_SSL_TIMEOUT;
197211fa71b9SJerome Forissier         }
197311fa71b9SJerome Forissier         else
197411fa71b9SJerome Forissier         {
197511fa71b9SJerome Forissier             len = in_buf_len - ( ssl->in_hdr - ssl->in_buf );
197611fa71b9SJerome Forissier 
197711fa71b9SJerome Forissier             if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
197811fa71b9SJerome Forissier                 timeout = ssl->handshake->retransmit_timeout;
197911fa71b9SJerome Forissier             else
198011fa71b9SJerome Forissier                 timeout = ssl->conf->read_timeout;
198111fa71b9SJerome Forissier 
19827901324dSJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 3, ( "f_recv_timeout: %lu ms", (unsigned long) timeout ) );
198311fa71b9SJerome Forissier 
198411fa71b9SJerome Forissier             if( ssl->f_recv_timeout != NULL )
198511fa71b9SJerome Forissier                 ret = ssl->f_recv_timeout( ssl->p_bio, ssl->in_hdr, len,
198611fa71b9SJerome Forissier                                                                     timeout );
198711fa71b9SJerome Forissier             else
198811fa71b9SJerome Forissier                 ret = ssl->f_recv( ssl->p_bio, ssl->in_hdr, len );
198911fa71b9SJerome Forissier 
199011fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret );
199111fa71b9SJerome Forissier 
199211fa71b9SJerome Forissier             if( ret == 0 )
199311fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_CONN_EOF );
199411fa71b9SJerome Forissier         }
199511fa71b9SJerome Forissier 
199611fa71b9SJerome Forissier         if( ret == MBEDTLS_ERR_SSL_TIMEOUT )
199711fa71b9SJerome Forissier         {
199811fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 2, ( "timeout" ) );
199911fa71b9SJerome Forissier             mbedtls_ssl_set_timer( ssl, 0 );
200011fa71b9SJerome Forissier 
200111fa71b9SJerome Forissier             if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
200211fa71b9SJerome Forissier             {
200311fa71b9SJerome Forissier                 if( ssl_double_retransmit_timeout( ssl ) != 0 )
200411fa71b9SJerome Forissier                 {
200511fa71b9SJerome Forissier                     MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake timeout" ) );
200611fa71b9SJerome Forissier                     return( MBEDTLS_ERR_SSL_TIMEOUT );
200711fa71b9SJerome Forissier                 }
200811fa71b9SJerome Forissier 
200911fa71b9SJerome Forissier                 if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 )
201011fa71b9SJerome Forissier                 {
201111fa71b9SJerome Forissier                     MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret );
201211fa71b9SJerome Forissier                     return( ret );
201311fa71b9SJerome Forissier                 }
201411fa71b9SJerome Forissier 
201511fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_WANT_READ );
201611fa71b9SJerome Forissier             }
201711fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION)
201811fa71b9SJerome Forissier             else if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
201911fa71b9SJerome Forissier                      ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING )
202011fa71b9SJerome Forissier             {
202111fa71b9SJerome Forissier                 if( ( ret = mbedtls_ssl_resend_hello_request( ssl ) ) != 0 )
202211fa71b9SJerome Forissier                 {
202311fa71b9SJerome Forissier                     MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend_hello_request",
202411fa71b9SJerome Forissier                                            ret );
202511fa71b9SJerome Forissier                     return( ret );
202611fa71b9SJerome Forissier                 }
202711fa71b9SJerome Forissier 
202811fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_WANT_READ );
202911fa71b9SJerome Forissier             }
203011fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */
203111fa71b9SJerome Forissier         }
203211fa71b9SJerome Forissier 
203311fa71b9SJerome Forissier         if( ret < 0 )
203411fa71b9SJerome Forissier             return( ret );
203511fa71b9SJerome Forissier 
203611fa71b9SJerome Forissier         ssl->in_left = ret;
203711fa71b9SJerome Forissier     }
203811fa71b9SJerome Forissier     else
203911fa71b9SJerome Forissier #endif
204011fa71b9SJerome Forissier     {
20417901324dSJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %" MBEDTLS_PRINTF_SIZET
20427901324dSJerome Forissier                                     ", nb_want: %" MBEDTLS_PRINTF_SIZET,
204311fa71b9SJerome Forissier                        ssl->in_left, nb_want ) );
204411fa71b9SJerome Forissier 
204511fa71b9SJerome Forissier         while( ssl->in_left < nb_want )
204611fa71b9SJerome Forissier         {
204711fa71b9SJerome Forissier             len = nb_want - ssl->in_left;
204811fa71b9SJerome Forissier 
204911fa71b9SJerome Forissier             if( mbedtls_ssl_check_timer( ssl ) != 0 )
205011fa71b9SJerome Forissier                 ret = MBEDTLS_ERR_SSL_TIMEOUT;
205111fa71b9SJerome Forissier             else
205211fa71b9SJerome Forissier             {
205311fa71b9SJerome Forissier                 if( ssl->f_recv_timeout != NULL )
205411fa71b9SJerome Forissier                 {
205511fa71b9SJerome Forissier                     ret = ssl->f_recv_timeout( ssl->p_bio,
205611fa71b9SJerome Forissier                                                ssl->in_hdr + ssl->in_left, len,
205711fa71b9SJerome Forissier                                                ssl->conf->read_timeout );
205811fa71b9SJerome Forissier                 }
205911fa71b9SJerome Forissier                 else
206011fa71b9SJerome Forissier                 {
206111fa71b9SJerome Forissier                     ret = ssl->f_recv( ssl->p_bio,
206211fa71b9SJerome Forissier                                        ssl->in_hdr + ssl->in_left, len );
206311fa71b9SJerome Forissier                 }
206411fa71b9SJerome Forissier             }
206511fa71b9SJerome Forissier 
20667901324dSJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %" MBEDTLS_PRINTF_SIZET
20677901324dSJerome Forissier                                         ", nb_want: %" MBEDTLS_PRINTF_SIZET,
206811fa71b9SJerome Forissier                                         ssl->in_left, nb_want ) );
206911fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret );
207011fa71b9SJerome Forissier 
207111fa71b9SJerome Forissier             if( ret == 0 )
207211fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_CONN_EOF );
207311fa71b9SJerome Forissier 
207411fa71b9SJerome Forissier             if( ret < 0 )
207511fa71b9SJerome Forissier                 return( ret );
207611fa71b9SJerome Forissier 
20777901324dSJerome Forissier             if ( (size_t)ret > len || ( INT_MAX > SIZE_MAX && ret > (int)SIZE_MAX ) )
207811fa71b9SJerome Forissier             {
207911fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1,
20807901324dSJerome Forissier                     ( "f_recv returned %d bytes but only %" MBEDTLS_PRINTF_SIZET " were requested",
20817901324dSJerome Forissier                     ret, len ) );
208211fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
208311fa71b9SJerome Forissier             }
208411fa71b9SJerome Forissier 
208511fa71b9SJerome Forissier             ssl->in_left += ret;
208611fa71b9SJerome Forissier         }
208711fa71b9SJerome Forissier     }
208811fa71b9SJerome Forissier 
208911fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) );
209011fa71b9SJerome Forissier 
209111fa71b9SJerome Forissier     return( 0 );
209211fa71b9SJerome Forissier }
209311fa71b9SJerome Forissier 
209411fa71b9SJerome Forissier /*
209511fa71b9SJerome Forissier  * Flush any data not yet written
209611fa71b9SJerome Forissier  */
209711fa71b9SJerome Forissier int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl )
209811fa71b9SJerome Forissier {
209911fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
210011fa71b9SJerome Forissier     unsigned char *buf;
210111fa71b9SJerome Forissier 
210211fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> flush output" ) );
210311fa71b9SJerome Forissier 
210411fa71b9SJerome Forissier     if( ssl->f_send == NULL )
210511fa71b9SJerome Forissier     {
210611fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() "
210711fa71b9SJerome Forissier                             "or mbedtls_ssl_set_bio()" ) );
210811fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
210911fa71b9SJerome Forissier     }
211011fa71b9SJerome Forissier 
211111fa71b9SJerome Forissier     /* Avoid incrementing counter if data is flushed */
211211fa71b9SJerome Forissier     if( ssl->out_left == 0 )
211311fa71b9SJerome Forissier     {
211411fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) );
211511fa71b9SJerome Forissier         return( 0 );
211611fa71b9SJerome Forissier     }
211711fa71b9SJerome Forissier 
211811fa71b9SJerome Forissier     while( ssl->out_left > 0 )
211911fa71b9SJerome Forissier     {
21207901324dSJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 2, ( "message length: %" MBEDTLS_PRINTF_SIZET
21217901324dSJerome Forissier                                     ", out_left: %" MBEDTLS_PRINTF_SIZET,
212211fa71b9SJerome Forissier                        mbedtls_ssl_out_hdr_len( ssl ) + ssl->out_msglen, ssl->out_left ) );
212311fa71b9SJerome Forissier 
212411fa71b9SJerome Forissier         buf = ssl->out_hdr - ssl->out_left;
212511fa71b9SJerome Forissier         ret = ssl->f_send( ssl->p_bio, buf, ssl->out_left );
212611fa71b9SJerome Forissier 
212711fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_send", ret );
212811fa71b9SJerome Forissier 
212911fa71b9SJerome Forissier         if( ret <= 0 )
213011fa71b9SJerome Forissier             return( ret );
213111fa71b9SJerome Forissier 
21327901324dSJerome Forissier         if( (size_t)ret > ssl->out_left || ( INT_MAX > SIZE_MAX && ret > (int)SIZE_MAX ) )
213311fa71b9SJerome Forissier         {
213411fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1,
21357901324dSJerome Forissier                 ( "f_send returned %d bytes but only %" MBEDTLS_PRINTF_SIZET " bytes were sent",
21367901324dSJerome Forissier                 ret, ssl->out_left ) );
213711fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
213811fa71b9SJerome Forissier         }
213911fa71b9SJerome Forissier 
214011fa71b9SJerome Forissier         ssl->out_left -= ret;
214111fa71b9SJerome Forissier     }
214211fa71b9SJerome Forissier 
214311fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
214411fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
214511fa71b9SJerome Forissier     {
214611fa71b9SJerome Forissier         ssl->out_hdr = ssl->out_buf;
214711fa71b9SJerome Forissier     }
214811fa71b9SJerome Forissier     else
214911fa71b9SJerome Forissier #endif
215011fa71b9SJerome Forissier     {
215111fa71b9SJerome Forissier         ssl->out_hdr = ssl->out_buf + 8;
215211fa71b9SJerome Forissier     }
215311fa71b9SJerome Forissier     mbedtls_ssl_update_out_pointers( ssl, ssl->transform_out );
215411fa71b9SJerome Forissier 
215511fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) );
215611fa71b9SJerome Forissier 
215711fa71b9SJerome Forissier     return( 0 );
215811fa71b9SJerome Forissier }
215911fa71b9SJerome Forissier 
216011fa71b9SJerome Forissier /*
216111fa71b9SJerome Forissier  * Functions to handle the DTLS retransmission state machine
216211fa71b9SJerome Forissier  */
216311fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
216411fa71b9SJerome Forissier /*
216511fa71b9SJerome Forissier  * Append current handshake message to current outgoing flight
216611fa71b9SJerome Forissier  */
2167*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
216811fa71b9SJerome Forissier static int ssl_flight_append( mbedtls_ssl_context *ssl )
216911fa71b9SJerome Forissier {
217011fa71b9SJerome Forissier     mbedtls_ssl_flight_item *msg;
217111fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_flight_append" ) );
217211fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_BUF( 4, "message appended to flight",
217311fa71b9SJerome Forissier                            ssl->out_msg, ssl->out_msglen );
217411fa71b9SJerome Forissier 
217511fa71b9SJerome Forissier     /* Allocate space for current message */
217611fa71b9SJerome Forissier     if( ( msg = mbedtls_calloc( 1, sizeof(  mbedtls_ssl_flight_item ) ) ) == NULL )
217711fa71b9SJerome Forissier     {
21787901324dSJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %" MBEDTLS_PRINTF_SIZET " bytes failed",
217911fa71b9SJerome Forissier                             sizeof( mbedtls_ssl_flight_item ) ) );
218011fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
218111fa71b9SJerome Forissier     }
218211fa71b9SJerome Forissier 
218311fa71b9SJerome Forissier     if( ( msg->p = mbedtls_calloc( 1, ssl->out_msglen ) ) == NULL )
218411fa71b9SJerome Forissier     {
21857901324dSJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %" MBEDTLS_PRINTF_SIZET " bytes failed",
21867901324dSJerome Forissier                                     ssl->out_msglen ) );
218711fa71b9SJerome Forissier         mbedtls_free( msg );
218811fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
218911fa71b9SJerome Forissier     }
219011fa71b9SJerome Forissier 
219111fa71b9SJerome Forissier     /* Copy current handshake message with headers */
219211fa71b9SJerome Forissier     memcpy( msg->p, ssl->out_msg, ssl->out_msglen );
219311fa71b9SJerome Forissier     msg->len = ssl->out_msglen;
219411fa71b9SJerome Forissier     msg->type = ssl->out_msgtype;
219511fa71b9SJerome Forissier     msg->next = NULL;
219611fa71b9SJerome Forissier 
219711fa71b9SJerome Forissier     /* Append to the current flight */
219811fa71b9SJerome Forissier     if( ssl->handshake->flight == NULL )
219911fa71b9SJerome Forissier         ssl->handshake->flight = msg;
220011fa71b9SJerome Forissier     else
220111fa71b9SJerome Forissier     {
220211fa71b9SJerome Forissier         mbedtls_ssl_flight_item *cur = ssl->handshake->flight;
220311fa71b9SJerome Forissier         while( cur->next != NULL )
220411fa71b9SJerome Forissier             cur = cur->next;
220511fa71b9SJerome Forissier         cur->next = msg;
220611fa71b9SJerome Forissier     }
220711fa71b9SJerome Forissier 
220811fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_flight_append" ) );
220911fa71b9SJerome Forissier     return( 0 );
221011fa71b9SJerome Forissier }
221111fa71b9SJerome Forissier 
221211fa71b9SJerome Forissier /*
221311fa71b9SJerome Forissier  * Free the current flight of handshake messages
221411fa71b9SJerome Forissier  */
221511fa71b9SJerome Forissier void mbedtls_ssl_flight_free( mbedtls_ssl_flight_item *flight )
221611fa71b9SJerome Forissier {
221711fa71b9SJerome Forissier     mbedtls_ssl_flight_item *cur = flight;
221811fa71b9SJerome Forissier     mbedtls_ssl_flight_item *next;
221911fa71b9SJerome Forissier 
222011fa71b9SJerome Forissier     while( cur != NULL )
222111fa71b9SJerome Forissier     {
222211fa71b9SJerome Forissier         next = cur->next;
222311fa71b9SJerome Forissier 
222411fa71b9SJerome Forissier         mbedtls_free( cur->p );
222511fa71b9SJerome Forissier         mbedtls_free( cur );
222611fa71b9SJerome Forissier 
222711fa71b9SJerome Forissier         cur = next;
222811fa71b9SJerome Forissier     }
222911fa71b9SJerome Forissier }
223011fa71b9SJerome Forissier 
223111fa71b9SJerome Forissier /*
223211fa71b9SJerome Forissier  * Swap transform_out and out_ctr with the alternative ones
223311fa71b9SJerome Forissier  */
2234*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
223511fa71b9SJerome Forissier static int ssl_swap_epochs( mbedtls_ssl_context *ssl )
223611fa71b9SJerome Forissier {
223711fa71b9SJerome Forissier     mbedtls_ssl_transform *tmp_transform;
223811fa71b9SJerome Forissier     unsigned char tmp_out_ctr[8];
223911fa71b9SJerome Forissier 
224011fa71b9SJerome Forissier     if( ssl->transform_out == ssl->handshake->alt_transform_out )
224111fa71b9SJerome Forissier     {
224211fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip swap epochs" ) );
224311fa71b9SJerome Forissier         return( 0 );
224411fa71b9SJerome Forissier     }
224511fa71b9SJerome Forissier 
224611fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 3, ( "swap epochs" ) );
224711fa71b9SJerome Forissier 
224811fa71b9SJerome Forissier     /* Swap transforms */
224911fa71b9SJerome Forissier     tmp_transform                     = ssl->transform_out;
225011fa71b9SJerome Forissier     ssl->transform_out                = ssl->handshake->alt_transform_out;
225111fa71b9SJerome Forissier     ssl->handshake->alt_transform_out = tmp_transform;
225211fa71b9SJerome Forissier 
225311fa71b9SJerome Forissier     /* Swap epoch + sequence_number */
225411fa71b9SJerome Forissier     memcpy( tmp_out_ctr,                 ssl->cur_out_ctr,            8 );
225511fa71b9SJerome Forissier     memcpy( ssl->cur_out_ctr,            ssl->handshake->alt_out_ctr, 8 );
225611fa71b9SJerome Forissier     memcpy( ssl->handshake->alt_out_ctr, tmp_out_ctr,                 8 );
225711fa71b9SJerome Forissier 
225811fa71b9SJerome Forissier     /* Adjust to the newly activated transform */
225911fa71b9SJerome Forissier     mbedtls_ssl_update_out_pointers( ssl, ssl->transform_out );
226011fa71b9SJerome Forissier 
226111fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
226211fa71b9SJerome Forissier     if( mbedtls_ssl_hw_record_activate != NULL )
226311fa71b9SJerome Forissier     {
226411fa71b9SJerome Forissier         int ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_OUTBOUND );
226511fa71b9SJerome Forissier         if( ret != 0 )
226611fa71b9SJerome Forissier         {
226711fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret );
226811fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
226911fa71b9SJerome Forissier         }
227011fa71b9SJerome Forissier     }
227111fa71b9SJerome Forissier #endif
227211fa71b9SJerome Forissier 
227311fa71b9SJerome Forissier     return( 0 );
227411fa71b9SJerome Forissier }
227511fa71b9SJerome Forissier 
227611fa71b9SJerome Forissier /*
227711fa71b9SJerome Forissier  * Retransmit the current flight of messages.
227811fa71b9SJerome Forissier  */
227911fa71b9SJerome Forissier int mbedtls_ssl_resend( mbedtls_ssl_context *ssl )
228011fa71b9SJerome Forissier {
228111fa71b9SJerome Forissier     int ret = 0;
228211fa71b9SJerome Forissier 
228311fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_resend" ) );
228411fa71b9SJerome Forissier 
228511fa71b9SJerome Forissier     ret = mbedtls_ssl_flight_transmit( ssl );
228611fa71b9SJerome Forissier 
228711fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_resend" ) );
228811fa71b9SJerome Forissier 
228911fa71b9SJerome Forissier     return( ret );
229011fa71b9SJerome Forissier }
229111fa71b9SJerome Forissier 
229211fa71b9SJerome Forissier /*
229311fa71b9SJerome Forissier  * Transmit or retransmit the current flight of messages.
229411fa71b9SJerome Forissier  *
229511fa71b9SJerome Forissier  * Need to remember the current message in case flush_output returns
229611fa71b9SJerome Forissier  * WANT_WRITE, causing us to exit this function and come back later.
229711fa71b9SJerome Forissier  * This function must be called until state is no longer SENDING.
229811fa71b9SJerome Forissier  */
229911fa71b9SJerome Forissier int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl )
230011fa71b9SJerome Forissier {
230111fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
230211fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_flight_transmit" ) );
230311fa71b9SJerome Forissier 
230411fa71b9SJerome Forissier     if( ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING )
230511fa71b9SJerome Forissier     {
230611fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialise flight transmission" ) );
230711fa71b9SJerome Forissier 
230811fa71b9SJerome Forissier         ssl->handshake->cur_msg = ssl->handshake->flight;
230911fa71b9SJerome Forissier         ssl->handshake->cur_msg_p = ssl->handshake->flight->p + 12;
231011fa71b9SJerome Forissier         ret = ssl_swap_epochs( ssl );
231111fa71b9SJerome Forissier         if( ret != 0 )
231211fa71b9SJerome Forissier             return( ret );
231311fa71b9SJerome Forissier 
231411fa71b9SJerome Forissier         ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_SENDING;
231511fa71b9SJerome Forissier     }
231611fa71b9SJerome Forissier 
231711fa71b9SJerome Forissier     while( ssl->handshake->cur_msg != NULL )
231811fa71b9SJerome Forissier     {
231911fa71b9SJerome Forissier         size_t max_frag_len;
232011fa71b9SJerome Forissier         const mbedtls_ssl_flight_item * const cur = ssl->handshake->cur_msg;
232111fa71b9SJerome Forissier 
232211fa71b9SJerome Forissier         int const is_finished =
232311fa71b9SJerome Forissier             ( cur->type == MBEDTLS_SSL_MSG_HANDSHAKE &&
232411fa71b9SJerome Forissier               cur->p[0] == MBEDTLS_SSL_HS_FINISHED );
232511fa71b9SJerome Forissier 
232611fa71b9SJerome Forissier         uint8_t const force_flush = ssl->disable_datagram_packing == 1 ?
232711fa71b9SJerome Forissier             SSL_FORCE_FLUSH : SSL_DONT_FORCE_FLUSH;
232811fa71b9SJerome Forissier 
232911fa71b9SJerome Forissier         /* Swap epochs before sending Finished: we can't do it after
233011fa71b9SJerome Forissier          * sending ChangeCipherSpec, in case write returns WANT_READ.
233111fa71b9SJerome Forissier          * Must be done before copying, may change out_msg pointer */
233211fa71b9SJerome Forissier         if( is_finished && ssl->handshake->cur_msg_p == ( cur->p + 12 ) )
233311fa71b9SJerome Forissier         {
233411fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 2, ( "swap epochs to send finished message" ) );
233511fa71b9SJerome Forissier             ret = ssl_swap_epochs( ssl );
233611fa71b9SJerome Forissier             if( ret != 0 )
233711fa71b9SJerome Forissier                 return( ret );
233811fa71b9SJerome Forissier         }
233911fa71b9SJerome Forissier 
234011fa71b9SJerome Forissier         ret = ssl_get_remaining_payload_in_datagram( ssl );
234111fa71b9SJerome Forissier         if( ret < 0 )
234211fa71b9SJerome Forissier             return( ret );
234311fa71b9SJerome Forissier         max_frag_len = (size_t) ret;
234411fa71b9SJerome Forissier 
234511fa71b9SJerome Forissier         /* CCS is copied as is, while HS messages may need fragmentation */
234611fa71b9SJerome Forissier         if( cur->type == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC )
234711fa71b9SJerome Forissier         {
234811fa71b9SJerome Forissier             if( max_frag_len == 0 )
234911fa71b9SJerome Forissier             {
235011fa71b9SJerome Forissier                 if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
235111fa71b9SJerome Forissier                     return( ret );
235211fa71b9SJerome Forissier 
235311fa71b9SJerome Forissier                 continue;
235411fa71b9SJerome Forissier             }
235511fa71b9SJerome Forissier 
235611fa71b9SJerome Forissier             memcpy( ssl->out_msg, cur->p, cur->len );
235711fa71b9SJerome Forissier             ssl->out_msglen  = cur->len;
235811fa71b9SJerome Forissier             ssl->out_msgtype = cur->type;
235911fa71b9SJerome Forissier 
236011fa71b9SJerome Forissier             /* Update position inside current message */
236111fa71b9SJerome Forissier             ssl->handshake->cur_msg_p += cur->len;
236211fa71b9SJerome Forissier         }
236311fa71b9SJerome Forissier         else
236411fa71b9SJerome Forissier         {
236511fa71b9SJerome Forissier             const unsigned char * const p = ssl->handshake->cur_msg_p;
236611fa71b9SJerome Forissier             const size_t hs_len = cur->len - 12;
236711fa71b9SJerome Forissier             const size_t frag_off = p - ( cur->p + 12 );
236811fa71b9SJerome Forissier             const size_t rem_len = hs_len - frag_off;
236911fa71b9SJerome Forissier             size_t cur_hs_frag_len, max_hs_frag_len;
237011fa71b9SJerome Forissier 
237111fa71b9SJerome Forissier             if( ( max_frag_len < 12 ) || ( max_frag_len == 12 && hs_len != 0 ) )
237211fa71b9SJerome Forissier             {
237311fa71b9SJerome Forissier                 if( is_finished )
237411fa71b9SJerome Forissier                 {
237511fa71b9SJerome Forissier                     ret = ssl_swap_epochs( ssl );
237611fa71b9SJerome Forissier                     if( ret != 0 )
237711fa71b9SJerome Forissier                         return( ret );
237811fa71b9SJerome Forissier                 }
237911fa71b9SJerome Forissier 
238011fa71b9SJerome Forissier                 if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
238111fa71b9SJerome Forissier                     return( ret );
238211fa71b9SJerome Forissier 
238311fa71b9SJerome Forissier                 continue;
238411fa71b9SJerome Forissier             }
238511fa71b9SJerome Forissier             max_hs_frag_len = max_frag_len - 12;
238611fa71b9SJerome Forissier 
238711fa71b9SJerome Forissier             cur_hs_frag_len = rem_len > max_hs_frag_len ?
238811fa71b9SJerome Forissier                 max_hs_frag_len : rem_len;
238911fa71b9SJerome Forissier 
239011fa71b9SJerome Forissier             if( frag_off == 0 && cur_hs_frag_len != hs_len )
239111fa71b9SJerome Forissier             {
239211fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 2, ( "fragmenting handshake message (%u > %u)",
239311fa71b9SJerome Forissier                                             (unsigned) cur_hs_frag_len,
239411fa71b9SJerome Forissier                                             (unsigned) max_hs_frag_len ) );
239511fa71b9SJerome Forissier             }
239611fa71b9SJerome Forissier 
239711fa71b9SJerome Forissier             /* Messages are stored with handshake headers as if not fragmented,
239811fa71b9SJerome Forissier              * copy beginning of headers then fill fragmentation fields.
239911fa71b9SJerome Forissier              * Handshake headers: type(1) len(3) seq(2) f_off(3) f_len(3) */
240011fa71b9SJerome Forissier             memcpy( ssl->out_msg, cur->p, 6 );
240111fa71b9SJerome Forissier 
2402*039e02dfSJerome Forissier             ssl->out_msg[6] = MBEDTLS_BYTE_2( frag_off );
2403*039e02dfSJerome Forissier             ssl->out_msg[7] = MBEDTLS_BYTE_1( frag_off );
2404*039e02dfSJerome Forissier             ssl->out_msg[8] = MBEDTLS_BYTE_0( frag_off );
240511fa71b9SJerome Forissier 
2406*039e02dfSJerome Forissier             ssl->out_msg[ 9] = MBEDTLS_BYTE_2( cur_hs_frag_len );
2407*039e02dfSJerome Forissier             ssl->out_msg[10] = MBEDTLS_BYTE_1( cur_hs_frag_len );
2408*039e02dfSJerome Forissier             ssl->out_msg[11] = MBEDTLS_BYTE_0( cur_hs_frag_len );
240911fa71b9SJerome Forissier 
241011fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_BUF( 3, "handshake header", ssl->out_msg, 12 );
241111fa71b9SJerome Forissier 
241211fa71b9SJerome Forissier             /* Copy the handshake message content and set records fields */
241311fa71b9SJerome Forissier             memcpy( ssl->out_msg + 12, p, cur_hs_frag_len );
241411fa71b9SJerome Forissier             ssl->out_msglen = cur_hs_frag_len + 12;
241511fa71b9SJerome Forissier             ssl->out_msgtype = cur->type;
241611fa71b9SJerome Forissier 
241711fa71b9SJerome Forissier             /* Update position inside current message */
241811fa71b9SJerome Forissier             ssl->handshake->cur_msg_p += cur_hs_frag_len;
241911fa71b9SJerome Forissier         }
242011fa71b9SJerome Forissier 
242111fa71b9SJerome Forissier         /* If done with the current message move to the next one if any */
242211fa71b9SJerome Forissier         if( ssl->handshake->cur_msg_p >= cur->p + cur->len )
242311fa71b9SJerome Forissier         {
242411fa71b9SJerome Forissier             if( cur->next != NULL )
242511fa71b9SJerome Forissier             {
242611fa71b9SJerome Forissier                 ssl->handshake->cur_msg = cur->next;
242711fa71b9SJerome Forissier                 ssl->handshake->cur_msg_p = cur->next->p + 12;
242811fa71b9SJerome Forissier             }
242911fa71b9SJerome Forissier             else
243011fa71b9SJerome Forissier             {
243111fa71b9SJerome Forissier                 ssl->handshake->cur_msg = NULL;
243211fa71b9SJerome Forissier                 ssl->handshake->cur_msg_p = NULL;
243311fa71b9SJerome Forissier             }
243411fa71b9SJerome Forissier         }
243511fa71b9SJerome Forissier 
243611fa71b9SJerome Forissier         /* Actually send the message out */
243711fa71b9SJerome Forissier         if( ( ret = mbedtls_ssl_write_record( ssl, force_flush ) ) != 0 )
243811fa71b9SJerome Forissier         {
243911fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
244011fa71b9SJerome Forissier             return( ret );
244111fa71b9SJerome Forissier         }
244211fa71b9SJerome Forissier     }
244311fa71b9SJerome Forissier 
244411fa71b9SJerome Forissier     if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
244511fa71b9SJerome Forissier         return( ret );
244611fa71b9SJerome Forissier 
244711fa71b9SJerome Forissier     /* Update state and set timer */
244811fa71b9SJerome Forissier     if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
244911fa71b9SJerome Forissier         ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED;
245011fa71b9SJerome Forissier     else
245111fa71b9SJerome Forissier     {
245211fa71b9SJerome Forissier         ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING;
245311fa71b9SJerome Forissier         mbedtls_ssl_set_timer( ssl, ssl->handshake->retransmit_timeout );
245411fa71b9SJerome Forissier     }
245511fa71b9SJerome Forissier 
245611fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_flight_transmit" ) );
245711fa71b9SJerome Forissier 
245811fa71b9SJerome Forissier     return( 0 );
245911fa71b9SJerome Forissier }
246011fa71b9SJerome Forissier 
246111fa71b9SJerome Forissier /*
246211fa71b9SJerome Forissier  * To be called when the last message of an incoming flight is received.
246311fa71b9SJerome Forissier  */
246411fa71b9SJerome Forissier void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl )
246511fa71b9SJerome Forissier {
246611fa71b9SJerome Forissier     /* We won't need to resend that one any more */
246711fa71b9SJerome Forissier     mbedtls_ssl_flight_free( ssl->handshake->flight );
246811fa71b9SJerome Forissier     ssl->handshake->flight = NULL;
246911fa71b9SJerome Forissier     ssl->handshake->cur_msg = NULL;
247011fa71b9SJerome Forissier 
247111fa71b9SJerome Forissier     /* The next incoming flight will start with this msg_seq */
247211fa71b9SJerome Forissier     ssl->handshake->in_flight_start_seq = ssl->handshake->in_msg_seq;
247311fa71b9SJerome Forissier 
247411fa71b9SJerome Forissier     /* We don't want to remember CCS's across flight boundaries. */
247511fa71b9SJerome Forissier     ssl->handshake->buffering.seen_ccs = 0;
247611fa71b9SJerome Forissier 
247711fa71b9SJerome Forissier     /* Clear future message buffering structure. */
247811fa71b9SJerome Forissier     mbedtls_ssl_buffering_free( ssl );
247911fa71b9SJerome Forissier 
248011fa71b9SJerome Forissier     /* Cancel timer */
248111fa71b9SJerome Forissier     mbedtls_ssl_set_timer( ssl, 0 );
248211fa71b9SJerome Forissier 
248311fa71b9SJerome Forissier     if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
248411fa71b9SJerome Forissier         ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED )
248511fa71b9SJerome Forissier     {
248611fa71b9SJerome Forissier         ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED;
248711fa71b9SJerome Forissier     }
248811fa71b9SJerome Forissier     else
248911fa71b9SJerome Forissier         ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING;
249011fa71b9SJerome Forissier }
249111fa71b9SJerome Forissier 
249211fa71b9SJerome Forissier /*
249311fa71b9SJerome Forissier  * To be called when the last message of an outgoing flight is send.
249411fa71b9SJerome Forissier  */
249511fa71b9SJerome Forissier void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl )
249611fa71b9SJerome Forissier {
249711fa71b9SJerome Forissier     ssl_reset_retransmit_timeout( ssl );
249811fa71b9SJerome Forissier     mbedtls_ssl_set_timer( ssl, ssl->handshake->retransmit_timeout );
249911fa71b9SJerome Forissier 
250011fa71b9SJerome Forissier     if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
250111fa71b9SJerome Forissier         ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED )
250211fa71b9SJerome Forissier     {
250311fa71b9SJerome Forissier         ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED;
250411fa71b9SJerome Forissier     }
250511fa71b9SJerome Forissier     else
250611fa71b9SJerome Forissier         ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING;
250711fa71b9SJerome Forissier }
250811fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
250911fa71b9SJerome Forissier 
251011fa71b9SJerome Forissier /*
251111fa71b9SJerome Forissier  * Handshake layer functions
251211fa71b9SJerome Forissier  */
251311fa71b9SJerome Forissier 
251411fa71b9SJerome Forissier /*
251511fa71b9SJerome Forissier  * Write (DTLS: or queue) current handshake (including CCS) message.
251611fa71b9SJerome Forissier  *
251711fa71b9SJerome Forissier  *  - fill in handshake headers
251811fa71b9SJerome Forissier  *  - update handshake checksum
251911fa71b9SJerome Forissier  *  - DTLS: save message for resending
252011fa71b9SJerome Forissier  *  - then pass to the record layer
252111fa71b9SJerome Forissier  *
252211fa71b9SJerome Forissier  * DTLS: except for HelloRequest, messages are only queued, and will only be
252311fa71b9SJerome Forissier  * actually sent when calling flight_transmit() or resend().
252411fa71b9SJerome Forissier  *
252511fa71b9SJerome Forissier  * Inputs:
252611fa71b9SJerome Forissier  *  - ssl->out_msglen: 4 + actual handshake message len
252711fa71b9SJerome Forissier  *      (4 is the size of handshake headers for TLS)
252811fa71b9SJerome Forissier  *  - ssl->out_msg[0]: the handshake type (ClientHello, ServerHello, etc)
252911fa71b9SJerome Forissier  *  - ssl->out_msg + 4: the handshake message body
253011fa71b9SJerome Forissier  *
253111fa71b9SJerome Forissier  * Outputs, ie state before passing to flight_append() or write_record():
253211fa71b9SJerome Forissier  *   - ssl->out_msglen: the length of the record contents
253311fa71b9SJerome Forissier  *      (including handshake headers but excluding record headers)
253411fa71b9SJerome Forissier  *   - ssl->out_msg: the record contents (handshake headers + content)
253511fa71b9SJerome Forissier  */
253611fa71b9SJerome Forissier int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl )
253711fa71b9SJerome Forissier {
253811fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
253911fa71b9SJerome Forissier     const size_t hs_len = ssl->out_msglen - 4;
254011fa71b9SJerome Forissier     const unsigned char hs_type = ssl->out_msg[0];
254111fa71b9SJerome Forissier 
254211fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write handshake message" ) );
254311fa71b9SJerome Forissier 
254411fa71b9SJerome Forissier     /*
254511fa71b9SJerome Forissier      * Sanity checks
254611fa71b9SJerome Forissier      */
254711fa71b9SJerome Forissier     if( ssl->out_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE          &&
254811fa71b9SJerome Forissier         ssl->out_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC )
254911fa71b9SJerome Forissier     {
255011fa71b9SJerome Forissier         /* In SSLv3, the client might send a NoCertificate alert. */
255111fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_CLI_C)
255211fa71b9SJerome Forissier         if( ! ( ssl->minor_ver      == MBEDTLS_SSL_MINOR_VERSION_0 &&
255311fa71b9SJerome Forissier                 ssl->out_msgtype    == MBEDTLS_SSL_MSG_ALERT       &&
255411fa71b9SJerome Forissier                 ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) )
255511fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */
255611fa71b9SJerome Forissier         {
255711fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
255811fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
255911fa71b9SJerome Forissier         }
256011fa71b9SJerome Forissier     }
256111fa71b9SJerome Forissier 
256211fa71b9SJerome Forissier     /* Whenever we send anything different from a
256311fa71b9SJerome Forissier      * HelloRequest we should be in a handshake - double check. */
256411fa71b9SJerome Forissier     if( ! ( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
256511fa71b9SJerome Forissier             hs_type          == MBEDTLS_SSL_HS_HELLO_REQUEST ) &&
256611fa71b9SJerome Forissier         ssl->handshake == NULL )
256711fa71b9SJerome Forissier     {
256811fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
256911fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
257011fa71b9SJerome Forissier     }
257111fa71b9SJerome Forissier 
257211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
257311fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
257411fa71b9SJerome Forissier         ssl->handshake != NULL &&
257511fa71b9SJerome Forissier         ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING )
257611fa71b9SJerome Forissier     {
257711fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
257811fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
257911fa71b9SJerome Forissier     }
258011fa71b9SJerome Forissier #endif
258111fa71b9SJerome Forissier 
258211fa71b9SJerome Forissier     /* Double-check that we did not exceed the bounds
258311fa71b9SJerome Forissier      * of the outgoing record buffer.
258411fa71b9SJerome Forissier      * This should never fail as the various message
258511fa71b9SJerome Forissier      * writing functions must obey the bounds of the
258611fa71b9SJerome Forissier      * outgoing record buffer, but better be safe.
258711fa71b9SJerome Forissier      *
258811fa71b9SJerome Forissier      * Note: We deliberately do not check for the MTU or MFL here.
258911fa71b9SJerome Forissier      */
259011fa71b9SJerome Forissier     if( ssl->out_msglen > MBEDTLS_SSL_OUT_CONTENT_LEN )
259111fa71b9SJerome Forissier     {
259211fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record too large: "
25937901324dSJerome Forissier                                     "size %" MBEDTLS_PRINTF_SIZET
25947901324dSJerome Forissier                                     ", maximum %" MBEDTLS_PRINTF_SIZET,
25957901324dSJerome Forissier                                     ssl->out_msglen,
25967901324dSJerome Forissier                                     (size_t) MBEDTLS_SSL_OUT_CONTENT_LEN ) );
259711fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
259811fa71b9SJerome Forissier     }
259911fa71b9SJerome Forissier 
260011fa71b9SJerome Forissier     /*
260111fa71b9SJerome Forissier      * Fill handshake headers
260211fa71b9SJerome Forissier      */
260311fa71b9SJerome Forissier     if( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE )
260411fa71b9SJerome Forissier     {
2605*039e02dfSJerome Forissier         ssl->out_msg[1] = MBEDTLS_BYTE_2( hs_len );
2606*039e02dfSJerome Forissier         ssl->out_msg[2] = MBEDTLS_BYTE_1( hs_len );
2607*039e02dfSJerome Forissier         ssl->out_msg[3] = MBEDTLS_BYTE_0( hs_len );
260811fa71b9SJerome Forissier 
260911fa71b9SJerome Forissier         /*
261011fa71b9SJerome Forissier          * DTLS has additional fields in the Handshake layer,
261111fa71b9SJerome Forissier          * between the length field and the actual payload:
261211fa71b9SJerome Forissier          *      uint16 message_seq;
261311fa71b9SJerome Forissier          *      uint24 fragment_offset;
261411fa71b9SJerome Forissier          *      uint24 fragment_length;
261511fa71b9SJerome Forissier          */
261611fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
261711fa71b9SJerome Forissier         if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
261811fa71b9SJerome Forissier         {
261911fa71b9SJerome Forissier             /* Make room for the additional DTLS fields */
262011fa71b9SJerome Forissier             if( MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen < 8 )
262111fa71b9SJerome Forissier             {
262211fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS handshake message too large: "
26237901324dSJerome Forissier                               "size %" MBEDTLS_PRINTF_SIZET ", maximum %" MBEDTLS_PRINTF_SIZET,
26247901324dSJerome Forissier                                hs_len,
26257901324dSJerome Forissier                                (size_t) ( MBEDTLS_SSL_OUT_CONTENT_LEN - 12 ) ) );
262611fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
262711fa71b9SJerome Forissier             }
262811fa71b9SJerome Forissier 
262911fa71b9SJerome Forissier             memmove( ssl->out_msg + 12, ssl->out_msg + 4, hs_len );
263011fa71b9SJerome Forissier             ssl->out_msglen += 8;
263111fa71b9SJerome Forissier 
263211fa71b9SJerome Forissier             /* Write message_seq and update it, except for HelloRequest */
263311fa71b9SJerome Forissier             if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST )
263411fa71b9SJerome Forissier             {
2635*039e02dfSJerome Forissier                 MBEDTLS_PUT_UINT16_BE( ssl->handshake->out_msg_seq, ssl->out_msg, 4 );
263611fa71b9SJerome Forissier                 ++( ssl->handshake->out_msg_seq );
263711fa71b9SJerome Forissier             }
263811fa71b9SJerome Forissier             else
263911fa71b9SJerome Forissier             {
264011fa71b9SJerome Forissier                 ssl->out_msg[4] = 0;
264111fa71b9SJerome Forissier                 ssl->out_msg[5] = 0;
264211fa71b9SJerome Forissier             }
264311fa71b9SJerome Forissier 
264411fa71b9SJerome Forissier             /* Handshake hashes are computed without fragmentation,
264511fa71b9SJerome Forissier              * so set frag_offset = 0 and frag_len = hs_len for now */
264611fa71b9SJerome Forissier             memset( ssl->out_msg + 6, 0x00, 3 );
264711fa71b9SJerome Forissier             memcpy( ssl->out_msg + 9, ssl->out_msg + 1, 3 );
264811fa71b9SJerome Forissier         }
264911fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
265011fa71b9SJerome Forissier 
265111fa71b9SJerome Forissier         /* Update running hashes of handshake messages seen */
265211fa71b9SJerome Forissier         if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST )
265311fa71b9SJerome Forissier             ssl->handshake->update_checksum( ssl, ssl->out_msg, ssl->out_msglen );
265411fa71b9SJerome Forissier     }
265511fa71b9SJerome Forissier 
265611fa71b9SJerome Forissier     /* Either send now, or just save to be sent (and resent) later */
265711fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
265811fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
265911fa71b9SJerome Forissier         ! ( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
266011fa71b9SJerome Forissier             hs_type          == MBEDTLS_SSL_HS_HELLO_REQUEST ) )
266111fa71b9SJerome Forissier     {
266211fa71b9SJerome Forissier         if( ( ret = ssl_flight_append( ssl ) ) != 0 )
266311fa71b9SJerome Forissier         {
266411fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "ssl_flight_append", ret );
266511fa71b9SJerome Forissier             return( ret );
266611fa71b9SJerome Forissier         }
266711fa71b9SJerome Forissier     }
266811fa71b9SJerome Forissier     else
266911fa71b9SJerome Forissier #endif
267011fa71b9SJerome Forissier     {
267111fa71b9SJerome Forissier         if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 )
267211fa71b9SJerome Forissier         {
267311fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_record", ret );
267411fa71b9SJerome Forissier             return( ret );
267511fa71b9SJerome Forissier         }
267611fa71b9SJerome Forissier     }
267711fa71b9SJerome Forissier 
267811fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write handshake message" ) );
267911fa71b9SJerome Forissier 
268011fa71b9SJerome Forissier     return( 0 );
268111fa71b9SJerome Forissier }
268211fa71b9SJerome Forissier 
268311fa71b9SJerome Forissier /*
268411fa71b9SJerome Forissier  * Record layer functions
268511fa71b9SJerome Forissier  */
268611fa71b9SJerome Forissier 
268711fa71b9SJerome Forissier /*
268811fa71b9SJerome Forissier  * Write current record.
268911fa71b9SJerome Forissier  *
269011fa71b9SJerome Forissier  * Uses:
269111fa71b9SJerome Forissier  *  - ssl->out_msgtype: type of the message (AppData, Handshake, Alert, CCS)
269211fa71b9SJerome Forissier  *  - ssl->out_msglen: length of the record content (excl headers)
269311fa71b9SJerome Forissier  *  - ssl->out_msg: record content
269411fa71b9SJerome Forissier  */
269511fa71b9SJerome Forissier int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush )
269611fa71b9SJerome Forissier {
269711fa71b9SJerome Forissier     int ret, done = 0;
269811fa71b9SJerome Forissier     size_t len = ssl->out_msglen;
269911fa71b9SJerome Forissier     uint8_t flush = force_flush;
270011fa71b9SJerome Forissier 
270111fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write record" ) );
270211fa71b9SJerome Forissier 
270311fa71b9SJerome Forissier #if defined(MBEDTLS_ZLIB_SUPPORT)
270411fa71b9SJerome Forissier     if( ssl->transform_out != NULL &&
270511fa71b9SJerome Forissier         ssl->session_out->compression == MBEDTLS_SSL_COMPRESS_DEFLATE )
270611fa71b9SJerome Forissier     {
270711fa71b9SJerome Forissier         if( ( ret = ssl_compress_buf( ssl ) ) != 0 )
270811fa71b9SJerome Forissier         {
270911fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "ssl_compress_buf", ret );
271011fa71b9SJerome Forissier             return( ret );
271111fa71b9SJerome Forissier         }
271211fa71b9SJerome Forissier 
271311fa71b9SJerome Forissier         len = ssl->out_msglen;
271411fa71b9SJerome Forissier     }
271511fa71b9SJerome Forissier #endif /*MBEDTLS_ZLIB_SUPPORT */
271611fa71b9SJerome Forissier 
271711fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
271811fa71b9SJerome Forissier     if( mbedtls_ssl_hw_record_write != NULL )
271911fa71b9SJerome Forissier     {
272011fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_write()" ) );
272111fa71b9SJerome Forissier 
272211fa71b9SJerome Forissier         ret = mbedtls_ssl_hw_record_write( ssl );
272311fa71b9SJerome Forissier         if( ret != 0 && ret != MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH )
272411fa71b9SJerome Forissier         {
272511fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_write", ret );
272611fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
272711fa71b9SJerome Forissier         }
272811fa71b9SJerome Forissier 
272911fa71b9SJerome Forissier         if( ret == 0 )
273011fa71b9SJerome Forissier             done = 1;
273111fa71b9SJerome Forissier     }
273211fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */
273311fa71b9SJerome Forissier     if( !done )
273411fa71b9SJerome Forissier     {
273511fa71b9SJerome Forissier         unsigned i;
273611fa71b9SJerome Forissier         size_t protected_record_size;
273711fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
273811fa71b9SJerome Forissier         size_t out_buf_len = ssl->out_buf_len;
273911fa71b9SJerome Forissier #else
274011fa71b9SJerome Forissier         size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN;
274111fa71b9SJerome Forissier #endif
274211fa71b9SJerome Forissier         /* Skip writing the record content type to after the encryption,
274311fa71b9SJerome Forissier          * as it may change when using the CID extension. */
274411fa71b9SJerome Forissier 
274511fa71b9SJerome Forissier         mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver,
274611fa71b9SJerome Forissier                            ssl->conf->transport, ssl->out_hdr + 1 );
274711fa71b9SJerome Forissier 
274811fa71b9SJerome Forissier         memcpy( ssl->out_ctr, ssl->cur_out_ctr, 8 );
2749*039e02dfSJerome Forissier         MBEDTLS_PUT_UINT16_BE( len, ssl->out_len, 0);
275011fa71b9SJerome Forissier 
275111fa71b9SJerome Forissier         if( ssl->transform_out != NULL )
275211fa71b9SJerome Forissier         {
275311fa71b9SJerome Forissier             mbedtls_record rec;
275411fa71b9SJerome Forissier 
275511fa71b9SJerome Forissier             rec.buf         = ssl->out_iv;
275611fa71b9SJerome Forissier             rec.buf_len     = out_buf_len - ( ssl->out_iv - ssl->out_buf );
275711fa71b9SJerome Forissier             rec.data_len    = ssl->out_msglen;
275811fa71b9SJerome Forissier             rec.data_offset = ssl->out_msg - rec.buf;
275911fa71b9SJerome Forissier 
276011fa71b9SJerome Forissier             memcpy( &rec.ctr[0], ssl->out_ctr, 8 );
276111fa71b9SJerome Forissier             mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver,
276211fa71b9SJerome Forissier                                        ssl->conf->transport, rec.ver );
276311fa71b9SJerome Forissier             rec.type = ssl->out_msgtype;
276411fa71b9SJerome Forissier 
276511fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
276611fa71b9SJerome Forissier             /* The CID is set by mbedtls_ssl_encrypt_buf(). */
276711fa71b9SJerome Forissier             rec.cid_len = 0;
276811fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
276911fa71b9SJerome Forissier 
277011fa71b9SJerome Forissier             if( ( ret = mbedtls_ssl_encrypt_buf( ssl, ssl->transform_out, &rec,
277111fa71b9SJerome Forissier                                          ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
277211fa71b9SJerome Forissier             {
277311fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_RET( 1, "ssl_encrypt_buf", ret );
277411fa71b9SJerome Forissier                 return( ret );
277511fa71b9SJerome Forissier             }
277611fa71b9SJerome Forissier 
277711fa71b9SJerome Forissier             if( rec.data_offset != 0 )
277811fa71b9SJerome Forissier             {
277911fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
278011fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
278111fa71b9SJerome Forissier             }
278211fa71b9SJerome Forissier 
278311fa71b9SJerome Forissier             /* Update the record content type and CID. */
278411fa71b9SJerome Forissier             ssl->out_msgtype = rec.type;
278511fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID )
278611fa71b9SJerome Forissier             memcpy( ssl->out_cid, rec.cid, rec.cid_len );
278711fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
278811fa71b9SJerome Forissier             ssl->out_msglen = len = rec.data_len;
2789*039e02dfSJerome Forissier             MBEDTLS_PUT_UINT16_BE( rec.data_len, ssl->out_len, 0 );
279011fa71b9SJerome Forissier         }
279111fa71b9SJerome Forissier 
279211fa71b9SJerome Forissier         protected_record_size = len + mbedtls_ssl_out_hdr_len( ssl );
279311fa71b9SJerome Forissier 
279411fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
279511fa71b9SJerome Forissier         /* In case of DTLS, double-check that we don't exceed
279611fa71b9SJerome Forissier          * the remaining space in the datagram. */
279711fa71b9SJerome Forissier         if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
279811fa71b9SJerome Forissier         {
279911fa71b9SJerome Forissier             ret = ssl_get_remaining_space_in_datagram( ssl );
280011fa71b9SJerome Forissier             if( ret < 0 )
280111fa71b9SJerome Forissier                 return( ret );
280211fa71b9SJerome Forissier 
280311fa71b9SJerome Forissier             if( protected_record_size > (size_t) ret )
280411fa71b9SJerome Forissier             {
280511fa71b9SJerome Forissier                 /* Should never happen */
280611fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
280711fa71b9SJerome Forissier             }
280811fa71b9SJerome Forissier         }
280911fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
281011fa71b9SJerome Forissier 
281111fa71b9SJerome Forissier         /* Now write the potentially updated record content type. */
281211fa71b9SJerome Forissier         ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype;
281311fa71b9SJerome Forissier 
28147901324dSJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 3, ( "output record: msgtype = %u, "
28157901324dSJerome Forissier                                     "version = [%u:%u], msglen = %" MBEDTLS_PRINTF_SIZET,
281611fa71b9SJerome Forissier                                     ssl->out_hdr[0], ssl->out_hdr[1],
281711fa71b9SJerome Forissier                                     ssl->out_hdr[2], len ) );
281811fa71b9SJerome Forissier 
281911fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network",
282011fa71b9SJerome Forissier                                ssl->out_hdr, protected_record_size );
282111fa71b9SJerome Forissier 
282211fa71b9SJerome Forissier         ssl->out_left += protected_record_size;
282311fa71b9SJerome Forissier         ssl->out_hdr  += protected_record_size;
282411fa71b9SJerome Forissier         mbedtls_ssl_update_out_pointers( ssl, ssl->transform_out );
282511fa71b9SJerome Forissier 
282611fa71b9SJerome Forissier         for( i = 8; i > mbedtls_ssl_ep_len( ssl ); i-- )
282711fa71b9SJerome Forissier             if( ++ssl->cur_out_ctr[i - 1] != 0 )
282811fa71b9SJerome Forissier                 break;
282911fa71b9SJerome Forissier 
283011fa71b9SJerome Forissier         /* The loop goes to its end iff the counter is wrapping */
283111fa71b9SJerome Forissier         if( i == mbedtls_ssl_ep_len( ssl ) )
283211fa71b9SJerome Forissier         {
283311fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "outgoing message counter would wrap" ) );
283411fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING );
283511fa71b9SJerome Forissier         }
283611fa71b9SJerome Forissier     }
283711fa71b9SJerome Forissier 
283811fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
283911fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
284011fa71b9SJerome Forissier         flush == SSL_DONT_FORCE_FLUSH )
284111fa71b9SJerome Forissier     {
284211fa71b9SJerome Forissier         size_t remaining;
284311fa71b9SJerome Forissier         ret = ssl_get_remaining_payload_in_datagram( ssl );
284411fa71b9SJerome Forissier         if( ret < 0 )
284511fa71b9SJerome Forissier         {
284611fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_remaining_payload_in_datagram",
284711fa71b9SJerome Forissier                                    ret );
284811fa71b9SJerome Forissier             return( ret );
284911fa71b9SJerome Forissier         }
285011fa71b9SJerome Forissier 
285111fa71b9SJerome Forissier         remaining = (size_t) ret;
285211fa71b9SJerome Forissier         if( remaining == 0 )
285311fa71b9SJerome Forissier         {
285411fa71b9SJerome Forissier             flush = SSL_FORCE_FLUSH;
285511fa71b9SJerome Forissier         }
285611fa71b9SJerome Forissier         else
285711fa71b9SJerome Forissier         {
285811fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 2, ( "Still %u bytes available in current datagram", (unsigned) remaining ) );
285911fa71b9SJerome Forissier         }
286011fa71b9SJerome Forissier     }
286111fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
286211fa71b9SJerome Forissier 
286311fa71b9SJerome Forissier     if( ( flush == SSL_FORCE_FLUSH ) &&
286411fa71b9SJerome Forissier         ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
286511fa71b9SJerome Forissier     {
286611fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret );
286711fa71b9SJerome Forissier         return( ret );
286811fa71b9SJerome Forissier     }
286911fa71b9SJerome Forissier 
287011fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write record" ) );
287111fa71b9SJerome Forissier 
287211fa71b9SJerome Forissier     return( 0 );
287311fa71b9SJerome Forissier }
287411fa71b9SJerome Forissier 
287511fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
287611fa71b9SJerome Forissier 
2877*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
287811fa71b9SJerome Forissier static int ssl_hs_is_proper_fragment( mbedtls_ssl_context *ssl )
287911fa71b9SJerome Forissier {
288011fa71b9SJerome Forissier     if( ssl->in_msglen < ssl->in_hslen ||
288111fa71b9SJerome Forissier         memcmp( ssl->in_msg + 6, "\0\0\0",        3 ) != 0 ||
288211fa71b9SJerome Forissier         memcmp( ssl->in_msg + 9, ssl->in_msg + 1, 3 ) != 0 )
288311fa71b9SJerome Forissier     {
288411fa71b9SJerome Forissier         return( 1 );
288511fa71b9SJerome Forissier     }
288611fa71b9SJerome Forissier     return( 0 );
288711fa71b9SJerome Forissier }
288811fa71b9SJerome Forissier 
288911fa71b9SJerome Forissier static uint32_t ssl_get_hs_frag_len( mbedtls_ssl_context const *ssl )
289011fa71b9SJerome Forissier {
289111fa71b9SJerome Forissier     return( ( ssl->in_msg[9] << 16  ) |
289211fa71b9SJerome Forissier             ( ssl->in_msg[10] << 8  ) |
289311fa71b9SJerome Forissier               ssl->in_msg[11] );
289411fa71b9SJerome Forissier }
289511fa71b9SJerome Forissier 
289611fa71b9SJerome Forissier static uint32_t ssl_get_hs_frag_off( mbedtls_ssl_context const *ssl )
289711fa71b9SJerome Forissier {
289811fa71b9SJerome Forissier     return( ( ssl->in_msg[6] << 16 ) |
289911fa71b9SJerome Forissier             ( ssl->in_msg[7] << 8  ) |
290011fa71b9SJerome Forissier               ssl->in_msg[8] );
290111fa71b9SJerome Forissier }
290211fa71b9SJerome Forissier 
2903*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
290411fa71b9SJerome Forissier static int ssl_check_hs_header( mbedtls_ssl_context const *ssl )
290511fa71b9SJerome Forissier {
290611fa71b9SJerome Forissier     uint32_t msg_len, frag_off, frag_len;
290711fa71b9SJerome Forissier 
290811fa71b9SJerome Forissier     msg_len  = ssl_get_hs_total_len( ssl );
290911fa71b9SJerome Forissier     frag_off = ssl_get_hs_frag_off( ssl );
291011fa71b9SJerome Forissier     frag_len = ssl_get_hs_frag_len( ssl );
291111fa71b9SJerome Forissier 
291211fa71b9SJerome Forissier     if( frag_off > msg_len )
291311fa71b9SJerome Forissier         return( -1 );
291411fa71b9SJerome Forissier 
291511fa71b9SJerome Forissier     if( frag_len > msg_len - frag_off )
291611fa71b9SJerome Forissier         return( -1 );
291711fa71b9SJerome Forissier 
291811fa71b9SJerome Forissier     if( frag_len + 12 > ssl->in_msglen )
291911fa71b9SJerome Forissier         return( -1 );
292011fa71b9SJerome Forissier 
292111fa71b9SJerome Forissier     return( 0 );
292211fa71b9SJerome Forissier }
292311fa71b9SJerome Forissier 
292411fa71b9SJerome Forissier /*
292511fa71b9SJerome Forissier  * Mark bits in bitmask (used for DTLS HS reassembly)
292611fa71b9SJerome Forissier  */
292711fa71b9SJerome Forissier static void ssl_bitmask_set( unsigned char *mask, size_t offset, size_t len )
292811fa71b9SJerome Forissier {
292911fa71b9SJerome Forissier     unsigned int start_bits, end_bits;
293011fa71b9SJerome Forissier 
293111fa71b9SJerome Forissier     start_bits = 8 - ( offset % 8 );
293211fa71b9SJerome Forissier     if( start_bits != 8 )
293311fa71b9SJerome Forissier     {
293411fa71b9SJerome Forissier         size_t first_byte_idx = offset / 8;
293511fa71b9SJerome Forissier 
293611fa71b9SJerome Forissier         /* Special case */
293711fa71b9SJerome Forissier         if( len <= start_bits )
293811fa71b9SJerome Forissier         {
293911fa71b9SJerome Forissier             for( ; len != 0; len-- )
294011fa71b9SJerome Forissier                 mask[first_byte_idx] |= 1 << ( start_bits - len );
294111fa71b9SJerome Forissier 
294211fa71b9SJerome Forissier             /* Avoid potential issues with offset or len becoming invalid */
294311fa71b9SJerome Forissier             return;
294411fa71b9SJerome Forissier         }
294511fa71b9SJerome Forissier 
294611fa71b9SJerome Forissier         offset += start_bits; /* Now offset % 8 == 0 */
294711fa71b9SJerome Forissier         len -= start_bits;
294811fa71b9SJerome Forissier 
294911fa71b9SJerome Forissier         for( ; start_bits != 0; start_bits-- )
295011fa71b9SJerome Forissier             mask[first_byte_idx] |= 1 << ( start_bits - 1 );
295111fa71b9SJerome Forissier     }
295211fa71b9SJerome Forissier 
295311fa71b9SJerome Forissier     end_bits = len % 8;
295411fa71b9SJerome Forissier     if( end_bits != 0 )
295511fa71b9SJerome Forissier     {
295611fa71b9SJerome Forissier         size_t last_byte_idx = ( offset + len ) / 8;
295711fa71b9SJerome Forissier 
295811fa71b9SJerome Forissier         len -= end_bits; /* Now len % 8 == 0 */
295911fa71b9SJerome Forissier 
296011fa71b9SJerome Forissier         for( ; end_bits != 0; end_bits-- )
296111fa71b9SJerome Forissier             mask[last_byte_idx] |= 1 << ( 8 - end_bits );
296211fa71b9SJerome Forissier     }
296311fa71b9SJerome Forissier 
296411fa71b9SJerome Forissier     memset( mask + offset / 8, 0xFF, len / 8 );
296511fa71b9SJerome Forissier }
296611fa71b9SJerome Forissier 
296711fa71b9SJerome Forissier /*
296811fa71b9SJerome Forissier  * Check that bitmask is full
296911fa71b9SJerome Forissier  */
2970*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
297111fa71b9SJerome Forissier static int ssl_bitmask_check( unsigned char *mask, size_t len )
297211fa71b9SJerome Forissier {
297311fa71b9SJerome Forissier     size_t i;
297411fa71b9SJerome Forissier 
297511fa71b9SJerome Forissier     for( i = 0; i < len / 8; i++ )
297611fa71b9SJerome Forissier         if( mask[i] != 0xFF )
297711fa71b9SJerome Forissier             return( -1 );
297811fa71b9SJerome Forissier 
297911fa71b9SJerome Forissier     for( i = 0; i < len % 8; i++ )
298011fa71b9SJerome Forissier         if( ( mask[len / 8] & ( 1 << ( 7 - i ) ) ) == 0 )
298111fa71b9SJerome Forissier             return( -1 );
298211fa71b9SJerome Forissier 
298311fa71b9SJerome Forissier     return( 0 );
298411fa71b9SJerome Forissier }
298511fa71b9SJerome Forissier 
298611fa71b9SJerome Forissier /* msg_len does not include the handshake header */
298711fa71b9SJerome Forissier static size_t ssl_get_reassembly_buffer_size( size_t msg_len,
298811fa71b9SJerome Forissier                                               unsigned add_bitmap )
298911fa71b9SJerome Forissier {
299011fa71b9SJerome Forissier     size_t alloc_len;
299111fa71b9SJerome Forissier 
299211fa71b9SJerome Forissier     alloc_len  = 12;                                 /* Handshake header */
299311fa71b9SJerome Forissier     alloc_len += msg_len;                            /* Content buffer   */
299411fa71b9SJerome Forissier 
299511fa71b9SJerome Forissier     if( add_bitmap )
299611fa71b9SJerome Forissier         alloc_len += msg_len / 8 + ( msg_len % 8 != 0 ); /* Bitmap       */
299711fa71b9SJerome Forissier 
299811fa71b9SJerome Forissier     return( alloc_len );
299911fa71b9SJerome Forissier }
300011fa71b9SJerome Forissier 
300111fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
300211fa71b9SJerome Forissier 
300311fa71b9SJerome Forissier static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl )
300411fa71b9SJerome Forissier {
300511fa71b9SJerome Forissier     return( ( ssl->in_msg[1] << 16 ) |
300611fa71b9SJerome Forissier             ( ssl->in_msg[2] << 8  ) |
300711fa71b9SJerome Forissier               ssl->in_msg[3] );
300811fa71b9SJerome Forissier }
300911fa71b9SJerome Forissier 
301011fa71b9SJerome Forissier int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl )
301111fa71b9SJerome Forissier {
301211fa71b9SJerome Forissier     if( ssl->in_msglen < mbedtls_ssl_hs_hdr_len( ssl ) )
301311fa71b9SJerome Forissier     {
30147901324dSJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too short: %" MBEDTLS_PRINTF_SIZET,
301511fa71b9SJerome Forissier                             ssl->in_msglen ) );
301611fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INVALID_RECORD );
301711fa71b9SJerome Forissier     }
301811fa71b9SJerome Forissier 
301911fa71b9SJerome Forissier     ssl->in_hslen = mbedtls_ssl_hs_hdr_len( ssl ) + ssl_get_hs_total_len( ssl );
302011fa71b9SJerome Forissier 
302111fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 3, ( "handshake message: msglen ="
30227901324dSJerome Forissier                         " %" MBEDTLS_PRINTF_SIZET ", type = %u, hslen = %" MBEDTLS_PRINTF_SIZET,
302311fa71b9SJerome Forissier                         ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) );
302411fa71b9SJerome Forissier 
302511fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
302611fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
302711fa71b9SJerome Forissier     {
302811fa71b9SJerome Forissier         int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
302911fa71b9SJerome Forissier         unsigned int recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5];
303011fa71b9SJerome Forissier 
303111fa71b9SJerome Forissier         if( ssl_check_hs_header( ssl ) != 0 )
303211fa71b9SJerome Forissier         {
303311fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid handshake header" ) );
303411fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INVALID_RECORD );
303511fa71b9SJerome Forissier         }
303611fa71b9SJerome Forissier 
303711fa71b9SJerome Forissier         if( ssl->handshake != NULL &&
303811fa71b9SJerome Forissier             ( ( ssl->state   != MBEDTLS_SSL_HANDSHAKE_OVER &&
303911fa71b9SJerome Forissier                 recv_msg_seq != ssl->handshake->in_msg_seq ) ||
304011fa71b9SJerome Forissier               ( ssl->state  == MBEDTLS_SSL_HANDSHAKE_OVER &&
304111fa71b9SJerome Forissier                 ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) ) )
304211fa71b9SJerome Forissier         {
304311fa71b9SJerome Forissier             if( recv_msg_seq > ssl->handshake->in_msg_seq )
304411fa71b9SJerome Forissier             {
304511fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 2, ( "received future handshake message of sequence number %u (next %u)",
304611fa71b9SJerome Forissier                                             recv_msg_seq,
304711fa71b9SJerome Forissier                                             ssl->handshake->in_msg_seq ) );
304811fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_EARLY_MESSAGE );
304911fa71b9SJerome Forissier             }
305011fa71b9SJerome Forissier 
305111fa71b9SJerome Forissier             /* Retransmit only on last message from previous flight, to avoid
305211fa71b9SJerome Forissier              * too many retransmissions.
305311fa71b9SJerome Forissier              * Besides, No sane server ever retransmits HelloVerifyRequest */
305411fa71b9SJerome Forissier             if( recv_msg_seq == ssl->handshake->in_flight_start_seq - 1 &&
305511fa71b9SJerome Forissier                 ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST )
305611fa71b9SJerome Forissier             {
305711fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 2, ( "received message from last flight, "
30587901324dSJerome Forissier                                     "message_seq = %u, start_of_flight = %u",
305911fa71b9SJerome Forissier                                     recv_msg_seq,
306011fa71b9SJerome Forissier                                     ssl->handshake->in_flight_start_seq ) );
306111fa71b9SJerome Forissier 
306211fa71b9SJerome Forissier                 if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 )
306311fa71b9SJerome Forissier                 {
306411fa71b9SJerome Forissier                     MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret );
306511fa71b9SJerome Forissier                     return( ret );
306611fa71b9SJerome Forissier                 }
306711fa71b9SJerome Forissier             }
306811fa71b9SJerome Forissier             else
306911fa71b9SJerome Forissier             {
307011fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 2, ( "dropping out-of-sequence message: "
30717901324dSJerome Forissier                                     "message_seq = %u, expected = %u",
307211fa71b9SJerome Forissier                                     recv_msg_seq,
307311fa71b9SJerome Forissier                                     ssl->handshake->in_msg_seq ) );
307411fa71b9SJerome Forissier             }
307511fa71b9SJerome Forissier 
307611fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
307711fa71b9SJerome Forissier         }
307811fa71b9SJerome Forissier         /* Wait until message completion to increment in_msg_seq */
307911fa71b9SJerome Forissier 
308011fa71b9SJerome Forissier         /* Message reassembly is handled alongside buffering of future
308111fa71b9SJerome Forissier          * messages; the commonality is that both handshake fragments and
308211fa71b9SJerome Forissier          * future messages cannot be forwarded immediately to the
308311fa71b9SJerome Forissier          * handshake logic layer. */
308411fa71b9SJerome Forissier         if( ssl_hs_is_proper_fragment( ssl ) == 1 )
308511fa71b9SJerome Forissier         {
308611fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 2, ( "found fragmented DTLS handshake message" ) );
308711fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_EARLY_MESSAGE );
308811fa71b9SJerome Forissier         }
308911fa71b9SJerome Forissier     }
309011fa71b9SJerome Forissier     else
309111fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
309211fa71b9SJerome Forissier     /* With TLS we don't handle fragmentation (for now) */
309311fa71b9SJerome Forissier     if( ssl->in_msglen < ssl->in_hslen )
309411fa71b9SJerome Forissier     {
309511fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLS handshake fragmentation not supported" ) );
309611fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
309711fa71b9SJerome Forissier     }
309811fa71b9SJerome Forissier 
309911fa71b9SJerome Forissier     return( 0 );
310011fa71b9SJerome Forissier }
310111fa71b9SJerome Forissier 
310211fa71b9SJerome Forissier void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl )
310311fa71b9SJerome Forissier {
310411fa71b9SJerome Forissier     mbedtls_ssl_handshake_params * const hs = ssl->handshake;
310511fa71b9SJerome Forissier 
310611fa71b9SJerome Forissier     if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && hs != NULL )
310711fa71b9SJerome Forissier     {
310811fa71b9SJerome Forissier         ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen );
310911fa71b9SJerome Forissier     }
311011fa71b9SJerome Forissier 
311111fa71b9SJerome Forissier     /* Handshake message is complete, increment counter */
311211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
311311fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
311411fa71b9SJerome Forissier         ssl->handshake != NULL )
311511fa71b9SJerome Forissier     {
311611fa71b9SJerome Forissier         unsigned offset;
311711fa71b9SJerome Forissier         mbedtls_ssl_hs_buffer *hs_buf;
311811fa71b9SJerome Forissier 
311911fa71b9SJerome Forissier         /* Increment handshake sequence number */
312011fa71b9SJerome Forissier         hs->in_msg_seq++;
312111fa71b9SJerome Forissier 
312211fa71b9SJerome Forissier         /*
312311fa71b9SJerome Forissier          * Clear up handshake buffering and reassembly structure.
312411fa71b9SJerome Forissier          */
312511fa71b9SJerome Forissier 
312611fa71b9SJerome Forissier         /* Free first entry */
312711fa71b9SJerome Forissier         ssl_buffering_free_slot( ssl, 0 );
312811fa71b9SJerome Forissier 
312911fa71b9SJerome Forissier         /* Shift all other entries */
313011fa71b9SJerome Forissier         for( offset = 0, hs_buf = &hs->buffering.hs[0];
313111fa71b9SJerome Forissier              offset + 1 < MBEDTLS_SSL_MAX_BUFFERED_HS;
313211fa71b9SJerome Forissier              offset++, hs_buf++ )
313311fa71b9SJerome Forissier         {
313411fa71b9SJerome Forissier             *hs_buf = *(hs_buf + 1);
313511fa71b9SJerome Forissier         }
313611fa71b9SJerome Forissier 
313711fa71b9SJerome Forissier         /* Create a fresh last entry */
313811fa71b9SJerome Forissier         memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) );
313911fa71b9SJerome Forissier     }
314011fa71b9SJerome Forissier #endif
314111fa71b9SJerome Forissier }
314211fa71b9SJerome Forissier 
314311fa71b9SJerome Forissier /*
314411fa71b9SJerome Forissier  * DTLS anti-replay: RFC 6347 4.1.2.6
314511fa71b9SJerome Forissier  *
314611fa71b9SJerome Forissier  * in_window is a field of bits numbered from 0 (lsb) to 63 (msb).
314711fa71b9SJerome Forissier  * Bit n is set iff record number in_window_top - n has been seen.
314811fa71b9SJerome Forissier  *
314911fa71b9SJerome Forissier  * Usually, in_window_top is the last record number seen and the lsb of
315011fa71b9SJerome Forissier  * in_window is set. The only exception is the initial state (record number 0
315111fa71b9SJerome Forissier  * not seen yet).
315211fa71b9SJerome Forissier  */
315311fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
315411fa71b9SJerome Forissier void mbedtls_ssl_dtls_replay_reset( mbedtls_ssl_context *ssl )
315511fa71b9SJerome Forissier {
315611fa71b9SJerome Forissier     ssl->in_window_top = 0;
315711fa71b9SJerome Forissier     ssl->in_window = 0;
315811fa71b9SJerome Forissier }
315911fa71b9SJerome Forissier 
316011fa71b9SJerome Forissier static inline uint64_t ssl_load_six_bytes( unsigned char *buf )
316111fa71b9SJerome Forissier {
316211fa71b9SJerome Forissier     return( ( (uint64_t) buf[0] << 40 ) |
316311fa71b9SJerome Forissier             ( (uint64_t) buf[1] << 32 ) |
316411fa71b9SJerome Forissier             ( (uint64_t) buf[2] << 24 ) |
316511fa71b9SJerome Forissier             ( (uint64_t) buf[3] << 16 ) |
316611fa71b9SJerome Forissier             ( (uint64_t) buf[4] <<  8 ) |
316711fa71b9SJerome Forissier             ( (uint64_t) buf[5]       ) );
316811fa71b9SJerome Forissier }
316911fa71b9SJerome Forissier 
3170*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
317111fa71b9SJerome Forissier static int mbedtls_ssl_dtls_record_replay_check( mbedtls_ssl_context *ssl, uint8_t *record_in_ctr )
317211fa71b9SJerome Forissier {
317311fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
317411fa71b9SJerome Forissier     unsigned char *original_in_ctr;
317511fa71b9SJerome Forissier 
317611fa71b9SJerome Forissier     // save original in_ctr
317711fa71b9SJerome Forissier     original_in_ctr = ssl->in_ctr;
317811fa71b9SJerome Forissier 
317911fa71b9SJerome Forissier     // use counter from record
318011fa71b9SJerome Forissier     ssl->in_ctr = record_in_ctr;
318111fa71b9SJerome Forissier 
318211fa71b9SJerome Forissier     ret = mbedtls_ssl_dtls_replay_check( (mbedtls_ssl_context const *) ssl );
318311fa71b9SJerome Forissier 
318411fa71b9SJerome Forissier     // restore the counter
318511fa71b9SJerome Forissier     ssl->in_ctr = original_in_ctr;
318611fa71b9SJerome Forissier 
318711fa71b9SJerome Forissier     return ret;
318811fa71b9SJerome Forissier }
318911fa71b9SJerome Forissier 
319011fa71b9SJerome Forissier /*
319111fa71b9SJerome Forissier  * Return 0 if sequence number is acceptable, -1 otherwise
319211fa71b9SJerome Forissier  */
319311fa71b9SJerome Forissier int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context const *ssl )
319411fa71b9SJerome Forissier {
319511fa71b9SJerome Forissier     uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 );
319611fa71b9SJerome Forissier     uint64_t bit;
319711fa71b9SJerome Forissier 
319811fa71b9SJerome Forissier     if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED )
319911fa71b9SJerome Forissier         return( 0 );
320011fa71b9SJerome Forissier 
320111fa71b9SJerome Forissier     if( rec_seqnum > ssl->in_window_top )
320211fa71b9SJerome Forissier         return( 0 );
320311fa71b9SJerome Forissier 
320411fa71b9SJerome Forissier     bit = ssl->in_window_top - rec_seqnum;
320511fa71b9SJerome Forissier 
320611fa71b9SJerome Forissier     if( bit >= 64 )
320711fa71b9SJerome Forissier         return( -1 );
320811fa71b9SJerome Forissier 
320911fa71b9SJerome Forissier     if( ( ssl->in_window & ( (uint64_t) 1 << bit ) ) != 0 )
321011fa71b9SJerome Forissier         return( -1 );
321111fa71b9SJerome Forissier 
321211fa71b9SJerome Forissier     return( 0 );
321311fa71b9SJerome Forissier }
321411fa71b9SJerome Forissier 
321511fa71b9SJerome Forissier /*
321611fa71b9SJerome Forissier  * Update replay window on new validated record
321711fa71b9SJerome Forissier  */
321811fa71b9SJerome Forissier void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl )
321911fa71b9SJerome Forissier {
322011fa71b9SJerome Forissier     uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 );
322111fa71b9SJerome Forissier 
322211fa71b9SJerome Forissier     if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED )
322311fa71b9SJerome Forissier         return;
322411fa71b9SJerome Forissier 
322511fa71b9SJerome Forissier     if( rec_seqnum > ssl->in_window_top )
322611fa71b9SJerome Forissier     {
322711fa71b9SJerome Forissier         /* Update window_top and the contents of the window */
322811fa71b9SJerome Forissier         uint64_t shift = rec_seqnum - ssl->in_window_top;
322911fa71b9SJerome Forissier 
323011fa71b9SJerome Forissier         if( shift >= 64 )
323111fa71b9SJerome Forissier             ssl->in_window = 1;
323211fa71b9SJerome Forissier         else
323311fa71b9SJerome Forissier         {
323411fa71b9SJerome Forissier             ssl->in_window <<= shift;
323511fa71b9SJerome Forissier             ssl->in_window |= 1;
323611fa71b9SJerome Forissier         }
323711fa71b9SJerome Forissier 
323811fa71b9SJerome Forissier         ssl->in_window_top = rec_seqnum;
323911fa71b9SJerome Forissier     }
324011fa71b9SJerome Forissier     else
324111fa71b9SJerome Forissier     {
324211fa71b9SJerome Forissier         /* Mark that number as seen in the current window */
324311fa71b9SJerome Forissier         uint64_t bit = ssl->in_window_top - rec_seqnum;
324411fa71b9SJerome Forissier 
324511fa71b9SJerome Forissier         if( bit < 64 ) /* Always true, but be extra sure */
324611fa71b9SJerome Forissier             ssl->in_window |= (uint64_t) 1 << bit;
324711fa71b9SJerome Forissier     }
324811fa71b9SJerome Forissier }
324911fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */
325011fa71b9SJerome Forissier 
325111fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
325211fa71b9SJerome Forissier /*
3253*039e02dfSJerome Forissier  * Check if a datagram looks like a ClientHello with a valid cookie,
3254*039e02dfSJerome Forissier  * and if it doesn't, generate a HelloVerifyRequest message.
325511fa71b9SJerome Forissier  * Both input and output include full DTLS headers.
325611fa71b9SJerome Forissier  *
325711fa71b9SJerome Forissier  * - if cookie is valid, return 0
325811fa71b9SJerome Forissier  * - if ClientHello looks superficially valid but cookie is not,
325911fa71b9SJerome Forissier  *   fill obuf and set olen, then
326011fa71b9SJerome Forissier  *   return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED
326111fa71b9SJerome Forissier  * - otherwise return a specific error code
326211fa71b9SJerome Forissier  */
3263*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
3264*039e02dfSJerome Forissier MBEDTLS_STATIC_TESTABLE
3265*039e02dfSJerome Forissier int mbedtls_ssl_check_dtls_clihlo_cookie(
3266*039e02dfSJerome Forissier                            mbedtls_ssl_context *ssl,
326711fa71b9SJerome Forissier                            const unsigned char *cli_id, size_t cli_id_len,
326811fa71b9SJerome Forissier                            const unsigned char *in, size_t in_len,
326911fa71b9SJerome Forissier                            unsigned char *obuf, size_t buf_len, size_t *olen )
327011fa71b9SJerome Forissier {
327111fa71b9SJerome Forissier     size_t sid_len, cookie_len;
327211fa71b9SJerome Forissier     unsigned char *p;
327311fa71b9SJerome Forissier 
327411fa71b9SJerome Forissier     /*
327511fa71b9SJerome Forissier      * Structure of ClientHello with record and handshake headers,
327611fa71b9SJerome Forissier      * and expected values. We don't need to check a lot, more checks will be
327711fa71b9SJerome Forissier      * done when actually parsing the ClientHello - skipping those checks
327811fa71b9SJerome Forissier      * avoids code duplication and does not make cookie forging any easier.
327911fa71b9SJerome Forissier      *
328011fa71b9SJerome Forissier      *  0-0  ContentType type;                  copied, must be handshake
328111fa71b9SJerome Forissier      *  1-2  ProtocolVersion version;           copied
328211fa71b9SJerome Forissier      *  3-4  uint16 epoch;                      copied, must be 0
328311fa71b9SJerome Forissier      *  5-10 uint48 sequence_number;            copied
328411fa71b9SJerome Forissier      * 11-12 uint16 length;                     (ignored)
328511fa71b9SJerome Forissier      *
328611fa71b9SJerome Forissier      * 13-13 HandshakeType msg_type;            (ignored)
328711fa71b9SJerome Forissier      * 14-16 uint24 length;                     (ignored)
328811fa71b9SJerome Forissier      * 17-18 uint16 message_seq;                copied
328911fa71b9SJerome Forissier      * 19-21 uint24 fragment_offset;            copied, must be 0
329011fa71b9SJerome Forissier      * 22-24 uint24 fragment_length;            (ignored)
329111fa71b9SJerome Forissier      *
329211fa71b9SJerome Forissier      * 25-26 ProtocolVersion client_version;    (ignored)
329311fa71b9SJerome Forissier      * 27-58 Random random;                     (ignored)
329411fa71b9SJerome Forissier      * 59-xx SessionID session_id;              1 byte len + sid_len content
329511fa71b9SJerome Forissier      * 60+   opaque cookie<0..2^8-1>;           1 byte len + content
329611fa71b9SJerome Forissier      *       ...
329711fa71b9SJerome Forissier      *
329811fa71b9SJerome Forissier      * Minimum length is 61 bytes.
329911fa71b9SJerome Forissier      */
3300*039e02dfSJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: in_len=%u",
3301*039e02dfSJerome Forissier                                 (unsigned) in_len ) );
3302*039e02dfSJerome Forissier     MBEDTLS_SSL_DEBUG_BUF( 4, "cli_id", cli_id, cli_id_len );
3303*039e02dfSJerome Forissier     if( in_len < 61 )
3304*039e02dfSJerome Forissier     {
3305*039e02dfSJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: record too short" ) );
3306*039e02dfSJerome Forissier         return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
3307*039e02dfSJerome Forissier     }
3308*039e02dfSJerome Forissier     if( in[0] != MBEDTLS_SSL_MSG_HANDSHAKE ||
330911fa71b9SJerome Forissier         in[3] != 0 || in[4] != 0 ||
331011fa71b9SJerome Forissier         in[19] != 0 || in[20] != 0 || in[21] != 0 )
331111fa71b9SJerome Forissier     {
3312*039e02dfSJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: not a good ClientHello" ) );
3313*039e02dfSJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 4, ( "    type=%u epoch=%u fragment_offset=%u",
3314*039e02dfSJerome Forissier                                     in[0],
3315*039e02dfSJerome Forissier                                     (unsigned) in[3] << 8 | in[4],
3316*039e02dfSJerome Forissier                                     (unsigned) in[19] << 16 | in[20] << 8 | in[21] ) );
331711fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
331811fa71b9SJerome Forissier     }
331911fa71b9SJerome Forissier 
332011fa71b9SJerome Forissier     sid_len = in[59];
3321*039e02dfSJerome Forissier     if( 59 + 1 + sid_len + 1 > in_len )
3322*039e02dfSJerome Forissier     {
3323*039e02dfSJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: sid_len=%u > %u",
3324*039e02dfSJerome Forissier                                     (unsigned) sid_len,
3325*039e02dfSJerome Forissier                                     (unsigned) in_len - 61 ) );
332611fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
3327*039e02dfSJerome Forissier     }
3328*039e02dfSJerome Forissier     MBEDTLS_SSL_DEBUG_BUF( 4, "sid received from network",
3329*039e02dfSJerome Forissier                            in + 60, sid_len );
333011fa71b9SJerome Forissier 
333111fa71b9SJerome Forissier     cookie_len = in[60 + sid_len];
3332*039e02dfSJerome Forissier     if( 59 + 1 + sid_len + 1 + cookie_len > in_len )
3333*039e02dfSJerome Forissier     {
3334*039e02dfSJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: cookie_len=%u > %u",
3335*039e02dfSJerome Forissier                                     (unsigned) cookie_len,
3336*039e02dfSJerome Forissier                                     (unsigned) ( in_len - sid_len - 61 ) ) );
333711fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
3338*039e02dfSJerome Forissier     }
333911fa71b9SJerome Forissier 
3340*039e02dfSJerome Forissier     MBEDTLS_SSL_DEBUG_BUF( 4, "cookie received from network",
3341*039e02dfSJerome Forissier                            in + sid_len + 61, cookie_len );
3342*039e02dfSJerome Forissier     if( ssl->conf->f_cookie_check( ssl->conf->p_cookie,
3343*039e02dfSJerome Forissier                                    in + sid_len + 61, cookie_len,
334411fa71b9SJerome Forissier                                    cli_id, cli_id_len ) == 0 )
334511fa71b9SJerome Forissier     {
3346*039e02dfSJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: valid" ) );
334711fa71b9SJerome Forissier         return( 0 );
334811fa71b9SJerome Forissier     }
334911fa71b9SJerome Forissier 
335011fa71b9SJerome Forissier     /*
335111fa71b9SJerome Forissier      * If we get here, we've got an invalid cookie, let's prepare HVR.
335211fa71b9SJerome Forissier      *
335311fa71b9SJerome Forissier      *  0-0  ContentType type;                  copied
335411fa71b9SJerome Forissier      *  1-2  ProtocolVersion version;           copied
335511fa71b9SJerome Forissier      *  3-4  uint16 epoch;                      copied
335611fa71b9SJerome Forissier      *  5-10 uint48 sequence_number;            copied
335711fa71b9SJerome Forissier      * 11-12 uint16 length;                     olen - 13
335811fa71b9SJerome Forissier      *
335911fa71b9SJerome Forissier      * 13-13 HandshakeType msg_type;            hello_verify_request
336011fa71b9SJerome Forissier      * 14-16 uint24 length;                     olen - 25
336111fa71b9SJerome Forissier      * 17-18 uint16 message_seq;                copied
336211fa71b9SJerome Forissier      * 19-21 uint24 fragment_offset;            copied
336311fa71b9SJerome Forissier      * 22-24 uint24 fragment_length;            olen - 25
336411fa71b9SJerome Forissier      *
336511fa71b9SJerome Forissier      * 25-26 ProtocolVersion server_version;    0xfe 0xff
336611fa71b9SJerome Forissier      * 27-27 opaque cookie<0..2^8-1>;           cookie_len = olen - 27, cookie
336711fa71b9SJerome Forissier      *
336811fa71b9SJerome Forissier      * Minimum length is 28.
336911fa71b9SJerome Forissier      */
337011fa71b9SJerome Forissier     if( buf_len < 28 )
337111fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
337211fa71b9SJerome Forissier 
337311fa71b9SJerome Forissier     /* Copy most fields and adapt others */
337411fa71b9SJerome Forissier     memcpy( obuf, in, 25 );
337511fa71b9SJerome Forissier     obuf[13] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST;
337611fa71b9SJerome Forissier     obuf[25] = 0xfe;
337711fa71b9SJerome Forissier     obuf[26] = 0xff;
337811fa71b9SJerome Forissier 
337911fa71b9SJerome Forissier     /* Generate and write actual cookie */
338011fa71b9SJerome Forissier     p = obuf + 28;
3381*039e02dfSJerome Forissier     if( ssl->conf->f_cookie_write( ssl->conf->p_cookie,
3382*039e02dfSJerome Forissier                                    &p, obuf + buf_len,
3383*039e02dfSJerome Forissier                                    cli_id, cli_id_len ) != 0 )
338411fa71b9SJerome Forissier     {
338511fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
338611fa71b9SJerome Forissier     }
338711fa71b9SJerome Forissier 
338811fa71b9SJerome Forissier     *olen = p - obuf;
338911fa71b9SJerome Forissier 
339011fa71b9SJerome Forissier     /* Go back and fill length fields */
339111fa71b9SJerome Forissier     obuf[27] = (unsigned char)( *olen - 28 );
339211fa71b9SJerome Forissier 
3393*039e02dfSJerome Forissier     obuf[14] = obuf[22] = MBEDTLS_BYTE_2( *olen - 25 );
3394*039e02dfSJerome Forissier     obuf[15] = obuf[23] = MBEDTLS_BYTE_1( *olen - 25 );
3395*039e02dfSJerome Forissier     obuf[16] = obuf[24] = MBEDTLS_BYTE_0( *olen - 25 );
339611fa71b9SJerome Forissier 
3397*039e02dfSJerome Forissier     MBEDTLS_PUT_UINT16_BE( *olen - 13, obuf, 11 );
339811fa71b9SJerome Forissier 
339911fa71b9SJerome Forissier     return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED );
340011fa71b9SJerome Forissier }
340111fa71b9SJerome Forissier 
340211fa71b9SJerome Forissier /*
340311fa71b9SJerome Forissier  * Handle possible client reconnect with the same UDP quadruplet
340411fa71b9SJerome Forissier  * (RFC 6347 Section 4.2.8).
340511fa71b9SJerome Forissier  *
340611fa71b9SJerome Forissier  * Called by ssl_parse_record_header() in case we receive an epoch 0 record
340711fa71b9SJerome Forissier  * that looks like a ClientHello.
340811fa71b9SJerome Forissier  *
340911fa71b9SJerome Forissier  * - if the input looks like a ClientHello without cookies,
341011fa71b9SJerome Forissier  *   send back HelloVerifyRequest, then return 0
341111fa71b9SJerome Forissier  * - if the input looks like a ClientHello with a valid cookie,
341211fa71b9SJerome Forissier  *   reset the session of the current context, and
341311fa71b9SJerome Forissier  *   return MBEDTLS_ERR_SSL_CLIENT_RECONNECT
341411fa71b9SJerome Forissier  * - if anything goes wrong, return a specific error code
341511fa71b9SJerome Forissier  *
341611fa71b9SJerome Forissier  * This function is called (through ssl_check_client_reconnect()) when an
341711fa71b9SJerome Forissier  * unexpected record is found in ssl_get_next_record(), which will discard the
341811fa71b9SJerome Forissier  * record if we return 0, and bubble up the return value otherwise (this
341911fa71b9SJerome Forissier  * includes the case of MBEDTLS_ERR_SSL_CLIENT_RECONNECT and of unexpected
342011fa71b9SJerome Forissier  * errors, and is the right thing to do in both cases).
342111fa71b9SJerome Forissier  */
3422*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
342311fa71b9SJerome Forissier static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl )
342411fa71b9SJerome Forissier {
342511fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
342611fa71b9SJerome Forissier     size_t len;
342711fa71b9SJerome Forissier 
342811fa71b9SJerome Forissier     if( ssl->conf->f_cookie_write == NULL ||
342911fa71b9SJerome Forissier         ssl->conf->f_cookie_check == NULL )
343011fa71b9SJerome Forissier     {
343111fa71b9SJerome Forissier         /* If we can't use cookies to verify reachability of the peer,
343211fa71b9SJerome Forissier          * drop the record. */
343311fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "no cookie callbacks, "
343411fa71b9SJerome Forissier                                     "can't check reconnect validity" ) );
343511fa71b9SJerome Forissier         return( 0 );
343611fa71b9SJerome Forissier     }
343711fa71b9SJerome Forissier 
3438*039e02dfSJerome Forissier     ret = mbedtls_ssl_check_dtls_clihlo_cookie(
3439*039e02dfSJerome Forissier             ssl,
344011fa71b9SJerome Forissier             ssl->cli_id, ssl->cli_id_len,
344111fa71b9SJerome Forissier             ssl->in_buf, ssl->in_left,
344211fa71b9SJerome Forissier             ssl->out_buf, MBEDTLS_SSL_OUT_CONTENT_LEN, &len );
344311fa71b9SJerome Forissier 
3444*039e02dfSJerome Forissier     MBEDTLS_SSL_DEBUG_RET( 2, "mbedtls_ssl_check_dtls_clihlo_cookie", ret );
344511fa71b9SJerome Forissier 
344611fa71b9SJerome Forissier     if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED )
344711fa71b9SJerome Forissier     {
344811fa71b9SJerome Forissier         int send_ret;
344911fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "sending HelloVerifyRequest" ) );
345011fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network",
345111fa71b9SJerome Forissier                                   ssl->out_buf, len );
345211fa71b9SJerome Forissier         /* Don't check write errors as we can't do anything here.
345311fa71b9SJerome Forissier          * If the error is permanent we'll catch it later,
345411fa71b9SJerome Forissier          * if it's not, then hopefully it'll work next time. */
345511fa71b9SJerome Forissier         send_ret = ssl->f_send( ssl->p_bio, ssl->out_buf, len );
345611fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_send", send_ret );
345711fa71b9SJerome Forissier         (void) send_ret;
345811fa71b9SJerome Forissier 
345911fa71b9SJerome Forissier         return( 0 );
346011fa71b9SJerome Forissier     }
346111fa71b9SJerome Forissier 
346211fa71b9SJerome Forissier     if( ret == 0 )
346311fa71b9SJerome Forissier     {
346411fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "cookie is valid, resetting context" ) );
346511fa71b9SJerome Forissier         if( ( ret = mbedtls_ssl_session_reset_int( ssl, 1 ) ) != 0 )
346611fa71b9SJerome Forissier         {
346711fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "reset", ret );
346811fa71b9SJerome Forissier             return( ret );
346911fa71b9SJerome Forissier         }
347011fa71b9SJerome Forissier 
347111fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_CLIENT_RECONNECT );
347211fa71b9SJerome Forissier     }
347311fa71b9SJerome Forissier 
347411fa71b9SJerome Forissier     return( ret );
347511fa71b9SJerome Forissier }
347611fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */
347711fa71b9SJerome Forissier 
3478*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
347911fa71b9SJerome Forissier static int ssl_check_record_type( uint8_t record_type )
348011fa71b9SJerome Forissier {
348111fa71b9SJerome Forissier     if( record_type != MBEDTLS_SSL_MSG_HANDSHAKE &&
348211fa71b9SJerome Forissier         record_type != MBEDTLS_SSL_MSG_ALERT &&
348311fa71b9SJerome Forissier         record_type != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC &&
348411fa71b9SJerome Forissier         record_type != MBEDTLS_SSL_MSG_APPLICATION_DATA )
348511fa71b9SJerome Forissier     {
348611fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INVALID_RECORD );
348711fa71b9SJerome Forissier     }
348811fa71b9SJerome Forissier 
348911fa71b9SJerome Forissier     return( 0 );
349011fa71b9SJerome Forissier }
349111fa71b9SJerome Forissier 
349211fa71b9SJerome Forissier /*
349311fa71b9SJerome Forissier  * ContentType type;
349411fa71b9SJerome Forissier  * ProtocolVersion version;
349511fa71b9SJerome Forissier  * uint16 epoch;            // DTLS only
349611fa71b9SJerome Forissier  * uint48 sequence_number;  // DTLS only
349711fa71b9SJerome Forissier  * uint16 length;
349811fa71b9SJerome Forissier  *
349911fa71b9SJerome Forissier  * Return 0 if header looks sane (and, for DTLS, the record is expected)
350011fa71b9SJerome Forissier  * MBEDTLS_ERR_SSL_INVALID_RECORD if the header looks bad,
350111fa71b9SJerome Forissier  * MBEDTLS_ERR_SSL_UNEXPECTED_RECORD (DTLS only) if sane but unexpected.
350211fa71b9SJerome Forissier  *
350311fa71b9SJerome Forissier  * With DTLS, mbedtls_ssl_read_record() will:
350411fa71b9SJerome Forissier  * 1. proceed with the record if this function returns 0
350511fa71b9SJerome Forissier  * 2. drop only the current record if this function returns UNEXPECTED_RECORD
350611fa71b9SJerome Forissier  * 3. return CLIENT_RECONNECT if this function return that value
350711fa71b9SJerome Forissier  * 4. drop the whole datagram if this function returns anything else.
350811fa71b9SJerome Forissier  * Point 2 is needed when the peer is resending, and we have already received
350911fa71b9SJerome Forissier  * the first record from a datagram but are still waiting for the others.
351011fa71b9SJerome Forissier  */
3511*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
351211fa71b9SJerome Forissier static int ssl_parse_record_header( mbedtls_ssl_context const *ssl,
351311fa71b9SJerome Forissier                                     unsigned char *buf,
351411fa71b9SJerome Forissier                                     size_t len,
351511fa71b9SJerome Forissier                                     mbedtls_record *rec )
351611fa71b9SJerome Forissier {
351711fa71b9SJerome Forissier     int major_ver, minor_ver;
351811fa71b9SJerome Forissier 
351911fa71b9SJerome Forissier     size_t const rec_hdr_type_offset    = 0;
352011fa71b9SJerome Forissier     size_t const rec_hdr_type_len       = 1;
352111fa71b9SJerome Forissier 
352211fa71b9SJerome Forissier     size_t const rec_hdr_version_offset = rec_hdr_type_offset +
352311fa71b9SJerome Forissier                                           rec_hdr_type_len;
352411fa71b9SJerome Forissier     size_t const rec_hdr_version_len    = 2;
352511fa71b9SJerome Forissier 
352611fa71b9SJerome Forissier     size_t const rec_hdr_ctr_len        = 8;
352711fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
352811fa71b9SJerome Forissier     uint32_t     rec_epoch;
352911fa71b9SJerome Forissier     size_t const rec_hdr_ctr_offset     = rec_hdr_version_offset +
353011fa71b9SJerome Forissier                                           rec_hdr_version_len;
353111fa71b9SJerome Forissier 
353211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
353311fa71b9SJerome Forissier     size_t const rec_hdr_cid_offset     = rec_hdr_ctr_offset +
353411fa71b9SJerome Forissier                                           rec_hdr_ctr_len;
353511fa71b9SJerome Forissier     size_t       rec_hdr_cid_len        = 0;
353611fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
353711fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
353811fa71b9SJerome Forissier 
353911fa71b9SJerome Forissier     size_t       rec_hdr_len_offset; /* To be determined */
354011fa71b9SJerome Forissier     size_t const rec_hdr_len_len    = 2;
354111fa71b9SJerome Forissier 
354211fa71b9SJerome Forissier     /*
354311fa71b9SJerome Forissier      * Check minimum lengths for record header.
354411fa71b9SJerome Forissier      */
354511fa71b9SJerome Forissier 
354611fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
354711fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
354811fa71b9SJerome Forissier     {
354911fa71b9SJerome Forissier         rec_hdr_len_offset = rec_hdr_ctr_offset + rec_hdr_ctr_len;
355011fa71b9SJerome Forissier     }
355111fa71b9SJerome Forissier     else
355211fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
355311fa71b9SJerome Forissier     {
355411fa71b9SJerome Forissier         rec_hdr_len_offset = rec_hdr_version_offset + rec_hdr_version_len;
355511fa71b9SJerome Forissier     }
355611fa71b9SJerome Forissier 
355711fa71b9SJerome Forissier     if( len < rec_hdr_len_offset + rec_hdr_len_len )
355811fa71b9SJerome Forissier     {
355911fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "datagram of length %u too small to hold DTLS record header of length %u",
356011fa71b9SJerome Forissier                  (unsigned) len,
356111fa71b9SJerome Forissier                  (unsigned)( rec_hdr_len_len + rec_hdr_len_len ) ) );
356211fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INVALID_RECORD );
356311fa71b9SJerome Forissier     }
356411fa71b9SJerome Forissier 
356511fa71b9SJerome Forissier     /*
356611fa71b9SJerome Forissier      * Parse and validate record content type
356711fa71b9SJerome Forissier      */
356811fa71b9SJerome Forissier 
356911fa71b9SJerome Forissier     rec->type = buf[ rec_hdr_type_offset ];
357011fa71b9SJerome Forissier 
357111fa71b9SJerome Forissier     /* Check record content type */
357211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
357311fa71b9SJerome Forissier     rec->cid_len = 0;
357411fa71b9SJerome Forissier 
357511fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
357611fa71b9SJerome Forissier         ssl->conf->cid_len != 0                                &&
357711fa71b9SJerome Forissier         rec->type == MBEDTLS_SSL_MSG_CID )
357811fa71b9SJerome Forissier     {
357911fa71b9SJerome Forissier         /* Shift pointers to account for record header including CID
358011fa71b9SJerome Forissier          * struct {
358111fa71b9SJerome Forissier          *   ContentType special_type = tls12_cid;
358211fa71b9SJerome Forissier          *   ProtocolVersion version;
358311fa71b9SJerome Forissier          *   uint16 epoch;
358411fa71b9SJerome Forissier          *   uint48 sequence_number;
358511fa71b9SJerome Forissier          *   opaque cid[cid_length]; // Additional field compared to
358611fa71b9SJerome Forissier          *                           // default DTLS record format
358711fa71b9SJerome Forissier          *   uint16 length;
358811fa71b9SJerome Forissier          *   opaque enc_content[DTLSCiphertext.length];
358911fa71b9SJerome Forissier          * } DTLSCiphertext;
359011fa71b9SJerome Forissier          */
359111fa71b9SJerome Forissier 
359211fa71b9SJerome Forissier         /* So far, we only support static CID lengths
359311fa71b9SJerome Forissier          * fixed in the configuration. */
359411fa71b9SJerome Forissier         rec_hdr_cid_len = ssl->conf->cid_len;
359511fa71b9SJerome Forissier         rec_hdr_len_offset += rec_hdr_cid_len;
359611fa71b9SJerome Forissier 
359711fa71b9SJerome Forissier         if( len < rec_hdr_len_offset + rec_hdr_len_len )
359811fa71b9SJerome Forissier         {
359911fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "datagram of length %u too small to hold DTLS record header including CID, length %u",
360011fa71b9SJerome Forissier                 (unsigned) len,
360111fa71b9SJerome Forissier                 (unsigned)( rec_hdr_len_offset + rec_hdr_len_len ) ) );
360211fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INVALID_RECORD );
360311fa71b9SJerome Forissier         }
360411fa71b9SJerome Forissier 
360511fa71b9SJerome Forissier         /* configured CID len is guaranteed at most 255, see
360611fa71b9SJerome Forissier          * MBEDTLS_SSL_CID_OUT_LEN_MAX in check_config.h */
360711fa71b9SJerome Forissier         rec->cid_len = (uint8_t) rec_hdr_cid_len;
360811fa71b9SJerome Forissier         memcpy( rec->cid, buf + rec_hdr_cid_offset, rec_hdr_cid_len );
360911fa71b9SJerome Forissier     }
361011fa71b9SJerome Forissier     else
361111fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
361211fa71b9SJerome Forissier     {
361311fa71b9SJerome Forissier         if( ssl_check_record_type( rec->type ) )
361411fa71b9SJerome Forissier         {
361511fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type %u",
361611fa71b9SJerome Forissier                                         (unsigned) rec->type ) );
361711fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INVALID_RECORD );
361811fa71b9SJerome Forissier         }
361911fa71b9SJerome Forissier     }
362011fa71b9SJerome Forissier 
362111fa71b9SJerome Forissier     /*
362211fa71b9SJerome Forissier      * Parse and validate record version
362311fa71b9SJerome Forissier      */
362411fa71b9SJerome Forissier     rec->ver[0] = buf[ rec_hdr_version_offset + 0 ];
362511fa71b9SJerome Forissier     rec->ver[1] = buf[ rec_hdr_version_offset + 1 ];
362611fa71b9SJerome Forissier     mbedtls_ssl_read_version( &major_ver, &minor_ver,
362711fa71b9SJerome Forissier                               ssl->conf->transport,
362811fa71b9SJerome Forissier                               &rec->ver[0] );
362911fa71b9SJerome Forissier 
363011fa71b9SJerome Forissier     if( major_ver != ssl->major_ver )
363111fa71b9SJerome Forissier     {
3632*039e02dfSJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "major version mismatch: got %u, expected %u",
3633*039e02dfSJerome Forissier                                     (unsigned) major_ver,
3634*039e02dfSJerome Forissier                                     (unsigned) ssl->major_ver ) );
363511fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INVALID_RECORD );
363611fa71b9SJerome Forissier     }
363711fa71b9SJerome Forissier 
363811fa71b9SJerome Forissier     if( minor_ver > ssl->conf->max_minor_ver )
363911fa71b9SJerome Forissier     {
3640*039e02dfSJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "minor version mismatch: got %u, expected max %u",
3641*039e02dfSJerome Forissier                                     (unsigned) minor_ver,
3642*039e02dfSJerome Forissier                                     (unsigned) ssl->conf->max_minor_ver ) );
364311fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INVALID_RECORD );
364411fa71b9SJerome Forissier     }
364511fa71b9SJerome Forissier     /*
364611fa71b9SJerome Forissier      * Parse/Copy record sequence number.
364711fa71b9SJerome Forissier      */
364811fa71b9SJerome Forissier 
364911fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
365011fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
365111fa71b9SJerome Forissier     {
365211fa71b9SJerome Forissier         /* Copy explicit record sequence number from input buffer. */
365311fa71b9SJerome Forissier         memcpy( &rec->ctr[0], buf + rec_hdr_ctr_offset,
365411fa71b9SJerome Forissier                 rec_hdr_ctr_len );
365511fa71b9SJerome Forissier     }
365611fa71b9SJerome Forissier     else
365711fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
365811fa71b9SJerome Forissier     {
365911fa71b9SJerome Forissier         /* Copy implicit record sequence number from SSL context structure. */
366011fa71b9SJerome Forissier         memcpy( &rec->ctr[0], ssl->in_ctr, rec_hdr_ctr_len );
366111fa71b9SJerome Forissier     }
366211fa71b9SJerome Forissier 
366311fa71b9SJerome Forissier     /*
366411fa71b9SJerome Forissier      * Parse record length.
366511fa71b9SJerome Forissier      */
366611fa71b9SJerome Forissier 
366711fa71b9SJerome Forissier     rec->data_offset = rec_hdr_len_offset + rec_hdr_len_len;
366811fa71b9SJerome Forissier     rec->data_len    = ( (size_t) buf[ rec_hdr_len_offset + 0 ] << 8 ) |
366911fa71b9SJerome Forissier                        ( (size_t) buf[ rec_hdr_len_offset + 1 ] << 0 );
367011fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_BUF( 4, "input record header", buf, rec->data_offset );
367111fa71b9SJerome Forissier 
36727901324dSJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 3, ( "input record: msgtype = %u, "
36737901324dSJerome Forissier                                 "version = [%d:%d], msglen = %" MBEDTLS_PRINTF_SIZET,
367411fa71b9SJerome Forissier                                 rec->type,
367511fa71b9SJerome Forissier                                 major_ver, minor_ver, rec->data_len ) );
367611fa71b9SJerome Forissier 
367711fa71b9SJerome Forissier     rec->buf     = buf;
367811fa71b9SJerome Forissier     rec->buf_len = rec->data_offset + rec->data_len;
367911fa71b9SJerome Forissier 
368011fa71b9SJerome Forissier     if( rec->data_len == 0 )
368111fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INVALID_RECORD );
368211fa71b9SJerome Forissier 
368311fa71b9SJerome Forissier     /*
368411fa71b9SJerome Forissier      * DTLS-related tests.
368511fa71b9SJerome Forissier      * Check epoch before checking length constraint because
368611fa71b9SJerome Forissier      * the latter varies with the epoch. E.g., if a ChangeCipherSpec
368711fa71b9SJerome Forissier      * message gets duplicated before the corresponding Finished message,
368811fa71b9SJerome Forissier      * the second ChangeCipherSpec should be discarded because it belongs
368911fa71b9SJerome Forissier      * to an old epoch, but not because its length is shorter than
369011fa71b9SJerome Forissier      * the minimum record length for packets using the new record transform.
369111fa71b9SJerome Forissier      * Note that these two kinds of failures are handled differently,
369211fa71b9SJerome Forissier      * as an unexpected record is silently skipped but an invalid
369311fa71b9SJerome Forissier      * record leads to the entire datagram being dropped.
369411fa71b9SJerome Forissier      */
369511fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
369611fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
369711fa71b9SJerome Forissier     {
369811fa71b9SJerome Forissier         rec_epoch = ( rec->ctr[0] << 8 ) | rec->ctr[1];
369911fa71b9SJerome Forissier 
370011fa71b9SJerome Forissier         /* Check that the datagram is large enough to contain a record
370111fa71b9SJerome Forissier          * of the advertised length. */
370211fa71b9SJerome Forissier         if( len < rec->data_offset + rec->data_len )
370311fa71b9SJerome Forissier         {
370411fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "Datagram of length %u too small to contain record of advertised length %u.",
370511fa71b9SJerome Forissier                              (unsigned) len,
370611fa71b9SJerome Forissier                              (unsigned)( rec->data_offset + rec->data_len ) ) );
370711fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INVALID_RECORD );
370811fa71b9SJerome Forissier         }
370911fa71b9SJerome Forissier 
371011fa71b9SJerome Forissier         /* Records from other, non-matching epochs are silently discarded.
371111fa71b9SJerome Forissier          * (The case of same-port Client reconnects must be considered in
371211fa71b9SJerome Forissier          *  the caller). */
371311fa71b9SJerome Forissier         if( rec_epoch != ssl->in_epoch )
371411fa71b9SJerome Forissier         {
371511fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "record from another epoch: "
37167901324dSJerome Forissier                                         "expected %u, received %lu",
37177901324dSJerome Forissier                                         ssl->in_epoch, (unsigned long) rec_epoch ) );
371811fa71b9SJerome Forissier 
371911fa71b9SJerome Forissier             /* Records from the next epoch are considered for buffering
372011fa71b9SJerome Forissier              * (concretely: early Finished messages). */
372111fa71b9SJerome Forissier             if( rec_epoch == (unsigned) ssl->in_epoch + 1 )
372211fa71b9SJerome Forissier             {
372311fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 2, ( "Consider record for buffering" ) );
372411fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_EARLY_MESSAGE );
372511fa71b9SJerome Forissier             }
372611fa71b9SJerome Forissier 
372711fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
372811fa71b9SJerome Forissier         }
372911fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
373011fa71b9SJerome Forissier         /* For records from the correct epoch, check whether their
373111fa71b9SJerome Forissier          * sequence number has been seen before. */
373211fa71b9SJerome Forissier         else if( mbedtls_ssl_dtls_record_replay_check( (mbedtls_ssl_context *) ssl,
373311fa71b9SJerome Forissier             &rec->ctr[0] ) != 0 )
373411fa71b9SJerome Forissier         {
373511fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "replayed record" ) );
373611fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
373711fa71b9SJerome Forissier         }
373811fa71b9SJerome Forissier #endif
373911fa71b9SJerome Forissier     }
374011fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
374111fa71b9SJerome Forissier 
374211fa71b9SJerome Forissier     return( 0 );
374311fa71b9SJerome Forissier }
374411fa71b9SJerome Forissier 
374511fa71b9SJerome Forissier 
374611fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
3747*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
374811fa71b9SJerome Forissier static int ssl_check_client_reconnect( mbedtls_ssl_context *ssl )
374911fa71b9SJerome Forissier {
375011fa71b9SJerome Forissier     unsigned int rec_epoch = ( ssl->in_ctr[0] << 8 ) | ssl->in_ctr[1];
375111fa71b9SJerome Forissier 
375211fa71b9SJerome Forissier     /*
375311fa71b9SJerome Forissier      * Check for an epoch 0 ClientHello. We can't use in_msg here to
375411fa71b9SJerome Forissier      * access the first byte of record content (handshake type), as we
375511fa71b9SJerome Forissier      * have an active transform (possibly iv_len != 0), so use the
375611fa71b9SJerome Forissier      * fact that the record header len is 13 instead.
375711fa71b9SJerome Forissier      */
375811fa71b9SJerome Forissier     if( rec_epoch == 0 &&
375911fa71b9SJerome Forissier         ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
376011fa71b9SJerome Forissier         ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER &&
376111fa71b9SJerome Forissier         ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
376211fa71b9SJerome Forissier         ssl->in_left > 13 &&
376311fa71b9SJerome Forissier         ssl->in_buf[13] == MBEDTLS_SSL_HS_CLIENT_HELLO )
376411fa71b9SJerome Forissier     {
376511fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "possible client reconnect "
376611fa71b9SJerome Forissier                                     "from the same port" ) );
376711fa71b9SJerome Forissier         return( ssl_handle_possible_reconnect( ssl ) );
376811fa71b9SJerome Forissier     }
376911fa71b9SJerome Forissier 
377011fa71b9SJerome Forissier     return( 0 );
377111fa71b9SJerome Forissier }
377211fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */
377311fa71b9SJerome Forissier 
377411fa71b9SJerome Forissier /*
377511fa71b9SJerome Forissier  * If applicable, decrypt record content
377611fa71b9SJerome Forissier  */
3777*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
377811fa71b9SJerome Forissier static int ssl_prepare_record_content( mbedtls_ssl_context *ssl,
377911fa71b9SJerome Forissier                                        mbedtls_record *rec )
378011fa71b9SJerome Forissier {
378111fa71b9SJerome Forissier     int ret, done = 0;
378211fa71b9SJerome Forissier 
378311fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_BUF( 4, "input record from network",
378411fa71b9SJerome Forissier                            rec->buf, rec->buf_len );
378511fa71b9SJerome Forissier 
378611fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
378711fa71b9SJerome Forissier     if( mbedtls_ssl_hw_record_read != NULL )
378811fa71b9SJerome Forissier     {
378911fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_read()" ) );
379011fa71b9SJerome Forissier 
379111fa71b9SJerome Forissier         ret = mbedtls_ssl_hw_record_read( ssl );
379211fa71b9SJerome Forissier         if( ret != 0 && ret != MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH )
379311fa71b9SJerome Forissier         {
379411fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_read", ret );
379511fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
379611fa71b9SJerome Forissier         }
379711fa71b9SJerome Forissier 
379811fa71b9SJerome Forissier         if( ret == 0 )
379911fa71b9SJerome Forissier             done = 1;
380011fa71b9SJerome Forissier     }
380111fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */
380211fa71b9SJerome Forissier     if( !done && ssl->transform_in != NULL )
380311fa71b9SJerome Forissier     {
380411fa71b9SJerome Forissier         unsigned char const old_msg_type = rec->type;
380511fa71b9SJerome Forissier 
380611fa71b9SJerome Forissier         if( ( ret = mbedtls_ssl_decrypt_buf( ssl, ssl->transform_in,
380711fa71b9SJerome Forissier                                              rec ) ) != 0 )
380811fa71b9SJerome Forissier         {
380911fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decrypt_buf", ret );
381011fa71b9SJerome Forissier 
381111fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
381211fa71b9SJerome Forissier             if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_CID &&
381311fa71b9SJerome Forissier                 ssl->conf->ignore_unexpected_cid
381411fa71b9SJerome Forissier                     == MBEDTLS_SSL_UNEXPECTED_CID_IGNORE )
381511fa71b9SJerome Forissier             {
381611fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 3, ( "ignoring unexpected CID" ) );
381711fa71b9SJerome Forissier                 ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING;
381811fa71b9SJerome Forissier             }
381911fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
382011fa71b9SJerome Forissier 
382111fa71b9SJerome Forissier             return( ret );
382211fa71b9SJerome Forissier         }
382311fa71b9SJerome Forissier 
382411fa71b9SJerome Forissier         if( old_msg_type != rec->type )
382511fa71b9SJerome Forissier         {
382611fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 4, ( "record type after decrypt (before %d): %d",
382711fa71b9SJerome Forissier                                         old_msg_type, rec->type ) );
382811fa71b9SJerome Forissier         }
382911fa71b9SJerome Forissier 
383011fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_BUF( 4, "input payload after decrypt",
383111fa71b9SJerome Forissier                                rec->buf + rec->data_offset, rec->data_len );
383211fa71b9SJerome Forissier 
383311fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
383411fa71b9SJerome Forissier         /* We have already checked the record content type
383511fa71b9SJerome Forissier          * in ssl_parse_record_header(), failing or silently
383611fa71b9SJerome Forissier          * dropping the record in the case of an unknown type.
383711fa71b9SJerome Forissier          *
383811fa71b9SJerome Forissier          * Since with the use of CIDs, the record content type
383911fa71b9SJerome Forissier          * might change during decryption, re-check the record
384011fa71b9SJerome Forissier          * content type, but treat a failure as fatal this time. */
384111fa71b9SJerome Forissier         if( ssl_check_record_type( rec->type ) )
384211fa71b9SJerome Forissier         {
384311fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type" ) );
384411fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INVALID_RECORD );
384511fa71b9SJerome Forissier         }
384611fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
384711fa71b9SJerome Forissier 
384811fa71b9SJerome Forissier         if( rec->data_len == 0 )
384911fa71b9SJerome Forissier         {
385011fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
385111fa71b9SJerome Forissier             if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3
385211fa71b9SJerome Forissier                 && rec->type != MBEDTLS_SSL_MSG_APPLICATION_DATA )
385311fa71b9SJerome Forissier             {
385411fa71b9SJerome Forissier                 /* TLS v1.2 explicitly disallows zero-length messages which are not application data */
385511fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid zero-length message type: %d", ssl->in_msgtype ) );
385611fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_INVALID_RECORD );
385711fa71b9SJerome Forissier             }
385811fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
385911fa71b9SJerome Forissier 
386011fa71b9SJerome Forissier             ssl->nb_zero++;
386111fa71b9SJerome Forissier 
386211fa71b9SJerome Forissier             /*
386311fa71b9SJerome Forissier              * Three or more empty messages may be a DoS attack
386411fa71b9SJerome Forissier              * (excessive CPU consumption).
386511fa71b9SJerome Forissier              */
386611fa71b9SJerome Forissier             if( ssl->nb_zero > 3 )
386711fa71b9SJerome Forissier             {
386811fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "received four consecutive empty "
386911fa71b9SJerome Forissier                                             "messages, possible DoS attack" ) );
387011fa71b9SJerome Forissier                 /* Treat the records as if they were not properly authenticated,
387111fa71b9SJerome Forissier                  * thereby failing the connection if we see more than allowed
387211fa71b9SJerome Forissier                  * by the configured bad MAC threshold. */
387311fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_INVALID_MAC );
387411fa71b9SJerome Forissier             }
387511fa71b9SJerome Forissier         }
387611fa71b9SJerome Forissier         else
387711fa71b9SJerome Forissier             ssl->nb_zero = 0;
387811fa71b9SJerome Forissier 
387911fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
388011fa71b9SJerome Forissier         if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
388111fa71b9SJerome Forissier         {
388211fa71b9SJerome Forissier             ; /* in_ctr read from peer, not maintained internally */
388311fa71b9SJerome Forissier         }
388411fa71b9SJerome Forissier         else
388511fa71b9SJerome Forissier #endif
388611fa71b9SJerome Forissier         {
388711fa71b9SJerome Forissier             unsigned i;
388811fa71b9SJerome Forissier             for( i = 8; i > mbedtls_ssl_ep_len( ssl ); i-- )
388911fa71b9SJerome Forissier                 if( ++ssl->in_ctr[i - 1] != 0 )
389011fa71b9SJerome Forissier                     break;
389111fa71b9SJerome Forissier 
389211fa71b9SJerome Forissier             /* The loop goes to its end iff the counter is wrapping */
389311fa71b9SJerome Forissier             if( i == mbedtls_ssl_ep_len( ssl ) )
389411fa71b9SJerome Forissier             {
389511fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "incoming message counter would wrap" ) );
389611fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING );
389711fa71b9SJerome Forissier             }
389811fa71b9SJerome Forissier         }
389911fa71b9SJerome Forissier 
390011fa71b9SJerome Forissier     }
390111fa71b9SJerome Forissier 
390211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
390311fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
390411fa71b9SJerome Forissier     {
390511fa71b9SJerome Forissier         mbedtls_ssl_dtls_replay_update( ssl );
390611fa71b9SJerome Forissier     }
390711fa71b9SJerome Forissier #endif
390811fa71b9SJerome Forissier 
390911fa71b9SJerome Forissier     /* Check actual (decrypted) record content length against
391011fa71b9SJerome Forissier      * configured maximum. */
3911*039e02dfSJerome Forissier     if( rec->data_len > MBEDTLS_SSL_IN_CONTENT_LEN )
391211fa71b9SJerome Forissier     {
391311fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
391411fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INVALID_RECORD );
391511fa71b9SJerome Forissier     }
391611fa71b9SJerome Forissier 
391711fa71b9SJerome Forissier     return( 0 );
391811fa71b9SJerome Forissier }
391911fa71b9SJerome Forissier 
392011fa71b9SJerome Forissier /*
392111fa71b9SJerome Forissier  * Read a record.
392211fa71b9SJerome Forissier  *
392311fa71b9SJerome Forissier  * Silently ignore non-fatal alert (and for DTLS, invalid records as well,
392411fa71b9SJerome Forissier  * RFC 6347 4.1.2.7) and continue reading until a valid record is found.
392511fa71b9SJerome Forissier  *
392611fa71b9SJerome Forissier  */
392711fa71b9SJerome Forissier 
392811fa71b9SJerome Forissier /* Helper functions for mbedtls_ssl_read_record(). */
3929*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
393011fa71b9SJerome Forissier static int ssl_consume_current_message( mbedtls_ssl_context *ssl );
3931*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
393211fa71b9SJerome Forissier static int ssl_get_next_record( mbedtls_ssl_context *ssl );
3933*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
393411fa71b9SJerome Forissier static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl );
393511fa71b9SJerome Forissier 
393611fa71b9SJerome Forissier int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl,
393711fa71b9SJerome Forissier                              unsigned update_hs_digest )
393811fa71b9SJerome Forissier {
393911fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
394011fa71b9SJerome Forissier 
394111fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read record" ) );
394211fa71b9SJerome Forissier 
394311fa71b9SJerome Forissier     if( ssl->keep_current_message == 0 )
394411fa71b9SJerome Forissier     {
394511fa71b9SJerome Forissier         do {
394611fa71b9SJerome Forissier 
394711fa71b9SJerome Forissier             ret = ssl_consume_current_message( ssl );
394811fa71b9SJerome Forissier             if( ret != 0 )
394911fa71b9SJerome Forissier                 return( ret );
395011fa71b9SJerome Forissier 
395111fa71b9SJerome Forissier             if( ssl_record_is_in_progress( ssl ) == 0 )
395211fa71b9SJerome Forissier             {
395311fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
395411fa71b9SJerome Forissier                 int have_buffered = 0;
395511fa71b9SJerome Forissier 
395611fa71b9SJerome Forissier                 /* We only check for buffered messages if the
395711fa71b9SJerome Forissier                  * current datagram is fully consumed. */
395811fa71b9SJerome Forissier                 if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
395911fa71b9SJerome Forissier                     ssl_next_record_is_in_datagram( ssl ) == 0 )
396011fa71b9SJerome Forissier                 {
396111fa71b9SJerome Forissier                     if( ssl_load_buffered_message( ssl ) == 0 )
396211fa71b9SJerome Forissier                         have_buffered = 1;
396311fa71b9SJerome Forissier                 }
396411fa71b9SJerome Forissier 
396511fa71b9SJerome Forissier                 if( have_buffered == 0 )
396611fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
396711fa71b9SJerome Forissier                 {
396811fa71b9SJerome Forissier                     ret = ssl_get_next_record( ssl );
396911fa71b9SJerome Forissier                     if( ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING )
397011fa71b9SJerome Forissier                         continue;
397111fa71b9SJerome Forissier 
397211fa71b9SJerome Forissier                     if( ret != 0 )
397311fa71b9SJerome Forissier                     {
397411fa71b9SJerome Forissier                         MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_get_next_record" ), ret );
397511fa71b9SJerome Forissier                         return( ret );
397611fa71b9SJerome Forissier                     }
397711fa71b9SJerome Forissier                 }
397811fa71b9SJerome Forissier             }
397911fa71b9SJerome Forissier 
398011fa71b9SJerome Forissier             ret = mbedtls_ssl_handle_message_type( ssl );
398111fa71b9SJerome Forissier 
398211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
398311fa71b9SJerome Forissier             if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE )
398411fa71b9SJerome Forissier             {
398511fa71b9SJerome Forissier                 /* Buffer future message */
398611fa71b9SJerome Forissier                 ret = ssl_buffer_message( ssl );
398711fa71b9SJerome Forissier                 if( ret != 0 )
398811fa71b9SJerome Forissier                     return( ret );
398911fa71b9SJerome Forissier 
399011fa71b9SJerome Forissier                 ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING;
399111fa71b9SJerome Forissier             }
399211fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
399311fa71b9SJerome Forissier 
399411fa71b9SJerome Forissier         } while( MBEDTLS_ERR_SSL_NON_FATAL           == ret  ||
399511fa71b9SJerome Forissier                  MBEDTLS_ERR_SSL_CONTINUE_PROCESSING == ret );
399611fa71b9SJerome Forissier 
399711fa71b9SJerome Forissier         if( 0 != ret )
399811fa71b9SJerome Forissier         {
399911fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_handle_message_type" ), ret );
400011fa71b9SJerome Forissier             return( ret );
400111fa71b9SJerome Forissier         }
400211fa71b9SJerome Forissier 
400311fa71b9SJerome Forissier         if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
400411fa71b9SJerome Forissier             update_hs_digest == 1 )
400511fa71b9SJerome Forissier         {
400611fa71b9SJerome Forissier             mbedtls_ssl_update_handshake_status( ssl );
400711fa71b9SJerome Forissier         }
400811fa71b9SJerome Forissier     }
400911fa71b9SJerome Forissier     else
401011fa71b9SJerome Forissier     {
401111fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 2, ( "reuse previously read message" ) );
401211fa71b9SJerome Forissier         ssl->keep_current_message = 0;
401311fa71b9SJerome Forissier     }
401411fa71b9SJerome Forissier 
401511fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read record" ) );
401611fa71b9SJerome Forissier 
401711fa71b9SJerome Forissier     return( 0 );
401811fa71b9SJerome Forissier }
401911fa71b9SJerome Forissier 
402011fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
4021*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
402211fa71b9SJerome Forissier static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl )
402311fa71b9SJerome Forissier {
402411fa71b9SJerome Forissier     if( ssl->in_left > ssl->next_record_offset )
402511fa71b9SJerome Forissier         return( 1 );
402611fa71b9SJerome Forissier 
402711fa71b9SJerome Forissier     return( 0 );
402811fa71b9SJerome Forissier }
402911fa71b9SJerome Forissier 
4030*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
403111fa71b9SJerome Forissier static int ssl_load_buffered_message( mbedtls_ssl_context *ssl )
403211fa71b9SJerome Forissier {
403311fa71b9SJerome Forissier     mbedtls_ssl_handshake_params * const hs = ssl->handshake;
403411fa71b9SJerome Forissier     mbedtls_ssl_hs_buffer * hs_buf;
403511fa71b9SJerome Forissier     int ret = 0;
403611fa71b9SJerome Forissier 
403711fa71b9SJerome Forissier     if( hs == NULL )
403811fa71b9SJerome Forissier         return( -1 );
403911fa71b9SJerome Forissier 
404011fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_messsage" ) );
404111fa71b9SJerome Forissier 
404211fa71b9SJerome Forissier     if( ssl->state == MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC ||
404311fa71b9SJerome Forissier         ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC )
404411fa71b9SJerome Forissier     {
404511fa71b9SJerome Forissier         /* Check if we have seen a ChangeCipherSpec before.
404611fa71b9SJerome Forissier          * If yes, synthesize a CCS record. */
404711fa71b9SJerome Forissier         if( !hs->buffering.seen_ccs )
404811fa71b9SJerome Forissier         {
404911fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 2, ( "CCS not seen in the current flight" ) );
405011fa71b9SJerome Forissier             ret = -1;
405111fa71b9SJerome Forissier             goto exit;
405211fa71b9SJerome Forissier         }
405311fa71b9SJerome Forissier 
405411fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 2, ( "Injecting buffered CCS message" ) );
405511fa71b9SJerome Forissier         ssl->in_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC;
405611fa71b9SJerome Forissier         ssl->in_msglen = 1;
405711fa71b9SJerome Forissier         ssl->in_msg[0] = 1;
405811fa71b9SJerome Forissier 
405911fa71b9SJerome Forissier         /* As long as they are equal, the exact value doesn't matter. */
406011fa71b9SJerome Forissier         ssl->in_left            = 0;
406111fa71b9SJerome Forissier         ssl->next_record_offset = 0;
406211fa71b9SJerome Forissier 
406311fa71b9SJerome Forissier         hs->buffering.seen_ccs = 0;
406411fa71b9SJerome Forissier         goto exit;
406511fa71b9SJerome Forissier     }
406611fa71b9SJerome Forissier 
406711fa71b9SJerome Forissier #if defined(MBEDTLS_DEBUG_C)
406811fa71b9SJerome Forissier     /* Debug only */
406911fa71b9SJerome Forissier     {
407011fa71b9SJerome Forissier         unsigned offset;
407111fa71b9SJerome Forissier         for( offset = 1; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++ )
407211fa71b9SJerome Forissier         {
407311fa71b9SJerome Forissier             hs_buf = &hs->buffering.hs[offset];
407411fa71b9SJerome Forissier             if( hs_buf->is_valid == 1 )
407511fa71b9SJerome Forissier             {
407611fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 2, ( "Future message with sequence number %u %s buffered.",
407711fa71b9SJerome Forissier                             hs->in_msg_seq + offset,
407811fa71b9SJerome Forissier                             hs_buf->is_complete ? "fully" : "partially" ) );
407911fa71b9SJerome Forissier             }
408011fa71b9SJerome Forissier         }
408111fa71b9SJerome Forissier     }
408211fa71b9SJerome Forissier #endif /* MBEDTLS_DEBUG_C */
408311fa71b9SJerome Forissier 
408411fa71b9SJerome Forissier     /* Check if we have buffered and/or fully reassembled the
408511fa71b9SJerome Forissier      * next handshake message. */
408611fa71b9SJerome Forissier     hs_buf = &hs->buffering.hs[0];
408711fa71b9SJerome Forissier     if( ( hs_buf->is_valid == 1 ) && ( hs_buf->is_complete == 1 ) )
408811fa71b9SJerome Forissier     {
408911fa71b9SJerome Forissier         /* Synthesize a record containing the buffered HS message. */
409011fa71b9SJerome Forissier         size_t msg_len = ( hs_buf->data[1] << 16 ) |
409111fa71b9SJerome Forissier                          ( hs_buf->data[2] << 8  ) |
409211fa71b9SJerome Forissier                            hs_buf->data[3];
409311fa71b9SJerome Forissier 
409411fa71b9SJerome Forissier         /* Double-check that we haven't accidentally buffered
409511fa71b9SJerome Forissier          * a message that doesn't fit into the input buffer. */
409611fa71b9SJerome Forissier         if( msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN )
409711fa71b9SJerome Forissier         {
409811fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
409911fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
410011fa71b9SJerome Forissier         }
410111fa71b9SJerome Forissier 
410211fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 2, ( "Next handshake message has been buffered - load" ) );
410311fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered handshake message (incl. header)",
410411fa71b9SJerome Forissier                                hs_buf->data, msg_len + 12 );
410511fa71b9SJerome Forissier 
410611fa71b9SJerome Forissier         ssl->in_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
410711fa71b9SJerome Forissier         ssl->in_hslen   = msg_len + 12;
410811fa71b9SJerome Forissier         ssl->in_msglen  = msg_len + 12;
410911fa71b9SJerome Forissier         memcpy( ssl->in_msg, hs_buf->data, ssl->in_hslen );
411011fa71b9SJerome Forissier 
411111fa71b9SJerome Forissier         ret = 0;
411211fa71b9SJerome Forissier         goto exit;
411311fa71b9SJerome Forissier     }
411411fa71b9SJerome Forissier     else
411511fa71b9SJerome Forissier     {
411611fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 2, ( "Next handshake message %u not or only partially bufffered",
411711fa71b9SJerome Forissier                                     hs->in_msg_seq ) );
411811fa71b9SJerome Forissier     }
411911fa71b9SJerome Forissier 
412011fa71b9SJerome Forissier     ret = -1;
412111fa71b9SJerome Forissier 
412211fa71b9SJerome Forissier exit:
412311fa71b9SJerome Forissier 
412411fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_load_buffered_message" ) );
412511fa71b9SJerome Forissier     return( ret );
412611fa71b9SJerome Forissier }
412711fa71b9SJerome Forissier 
4128*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
412911fa71b9SJerome Forissier static int ssl_buffer_make_space( mbedtls_ssl_context *ssl,
413011fa71b9SJerome Forissier                                   size_t desired )
413111fa71b9SJerome Forissier {
413211fa71b9SJerome Forissier     int offset;
413311fa71b9SJerome Forissier     mbedtls_ssl_handshake_params * const hs = ssl->handshake;
413411fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "Attempt to free buffered messages to have %u bytes available",
413511fa71b9SJerome Forissier                                 (unsigned) desired ) );
413611fa71b9SJerome Forissier 
413711fa71b9SJerome Forissier     /* Get rid of future records epoch first, if such exist. */
413811fa71b9SJerome Forissier     ssl_free_buffered_record( ssl );
413911fa71b9SJerome Forissier 
414011fa71b9SJerome Forissier     /* Check if we have enough space available now. */
414111fa71b9SJerome Forissier     if( desired <= ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
414211fa71b9SJerome Forissier                      hs->buffering.total_bytes_buffered ) )
414311fa71b9SJerome Forissier     {
414411fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 2, ( "Enough space available after freeing future epoch record" ) );
414511fa71b9SJerome Forissier         return( 0 );
414611fa71b9SJerome Forissier     }
414711fa71b9SJerome Forissier 
414811fa71b9SJerome Forissier     /* We don't have enough space to buffer the next expected handshake
414911fa71b9SJerome Forissier      * message. Remove buffers used for future messages to gain space,
415011fa71b9SJerome Forissier      * starting with the most distant one. */
415111fa71b9SJerome Forissier     for( offset = MBEDTLS_SSL_MAX_BUFFERED_HS - 1;
415211fa71b9SJerome Forissier          offset >= 0; offset-- )
415311fa71b9SJerome Forissier     {
415411fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 2, ( "Free buffering slot %d to make space for reassembly of next handshake message",
415511fa71b9SJerome Forissier                                     offset ) );
415611fa71b9SJerome Forissier 
415711fa71b9SJerome Forissier         ssl_buffering_free_slot( ssl, (uint8_t) offset );
415811fa71b9SJerome Forissier 
415911fa71b9SJerome Forissier         /* Check if we have enough space available now. */
416011fa71b9SJerome Forissier         if( desired <= ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
416111fa71b9SJerome Forissier                          hs->buffering.total_bytes_buffered ) )
416211fa71b9SJerome Forissier         {
416311fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 2, ( "Enough space available after freeing buffered HS messages" ) );
416411fa71b9SJerome Forissier             return( 0 );
416511fa71b9SJerome Forissier         }
416611fa71b9SJerome Forissier     }
416711fa71b9SJerome Forissier 
416811fa71b9SJerome Forissier     return( -1 );
416911fa71b9SJerome Forissier }
417011fa71b9SJerome Forissier 
4171*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
417211fa71b9SJerome Forissier static int ssl_buffer_message( mbedtls_ssl_context *ssl )
417311fa71b9SJerome Forissier {
417411fa71b9SJerome Forissier     int ret = 0;
417511fa71b9SJerome Forissier     mbedtls_ssl_handshake_params * const hs = ssl->handshake;
417611fa71b9SJerome Forissier 
417711fa71b9SJerome Forissier     if( hs == NULL )
417811fa71b9SJerome Forissier         return( 0 );
417911fa71b9SJerome Forissier 
418011fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_buffer_message" ) );
418111fa71b9SJerome Forissier 
418211fa71b9SJerome Forissier     switch( ssl->in_msgtype )
418311fa71b9SJerome Forissier     {
418411fa71b9SJerome Forissier         case MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC:
418511fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 2, ( "Remember CCS message" ) );
418611fa71b9SJerome Forissier 
418711fa71b9SJerome Forissier             hs->buffering.seen_ccs = 1;
418811fa71b9SJerome Forissier             break;
418911fa71b9SJerome Forissier 
419011fa71b9SJerome Forissier         case MBEDTLS_SSL_MSG_HANDSHAKE:
419111fa71b9SJerome Forissier         {
419211fa71b9SJerome Forissier             unsigned recv_msg_seq_offset;
419311fa71b9SJerome Forissier             unsigned recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5];
419411fa71b9SJerome Forissier             mbedtls_ssl_hs_buffer *hs_buf;
419511fa71b9SJerome Forissier             size_t msg_len = ssl->in_hslen - 12;
419611fa71b9SJerome Forissier 
419711fa71b9SJerome Forissier             /* We should never receive an old handshake
419811fa71b9SJerome Forissier              * message - double-check nonetheless. */
419911fa71b9SJerome Forissier             if( recv_msg_seq < ssl->handshake->in_msg_seq )
420011fa71b9SJerome Forissier             {
420111fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
420211fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
420311fa71b9SJerome Forissier             }
420411fa71b9SJerome Forissier 
420511fa71b9SJerome Forissier             recv_msg_seq_offset = recv_msg_seq - ssl->handshake->in_msg_seq;
420611fa71b9SJerome Forissier             if( recv_msg_seq_offset >= MBEDTLS_SSL_MAX_BUFFERED_HS )
420711fa71b9SJerome Forissier             {
420811fa71b9SJerome Forissier                 /* Silently ignore -- message too far in the future */
420911fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 2,
421011fa71b9SJerome Forissier                  ( "Ignore future HS message with sequence number %u, "
421111fa71b9SJerome Forissier                    "buffering window %u - %u",
421211fa71b9SJerome Forissier                    recv_msg_seq, ssl->handshake->in_msg_seq,
421311fa71b9SJerome Forissier                    ssl->handshake->in_msg_seq + MBEDTLS_SSL_MAX_BUFFERED_HS - 1 ) );
421411fa71b9SJerome Forissier 
421511fa71b9SJerome Forissier                 goto exit;
421611fa71b9SJerome Forissier             }
421711fa71b9SJerome Forissier 
421811fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering HS message with sequence number %u, offset %u ",
421911fa71b9SJerome Forissier                                         recv_msg_seq, recv_msg_seq_offset ) );
422011fa71b9SJerome Forissier 
422111fa71b9SJerome Forissier             hs_buf = &hs->buffering.hs[ recv_msg_seq_offset ];
422211fa71b9SJerome Forissier 
422311fa71b9SJerome Forissier             /* Check if the buffering for this seq nr has already commenced. */
422411fa71b9SJerome Forissier             if( !hs_buf->is_valid )
422511fa71b9SJerome Forissier             {
422611fa71b9SJerome Forissier                 size_t reassembly_buf_sz;
422711fa71b9SJerome Forissier 
422811fa71b9SJerome Forissier                 hs_buf->is_fragmented =
422911fa71b9SJerome Forissier                     ( ssl_hs_is_proper_fragment( ssl ) == 1 );
423011fa71b9SJerome Forissier 
423111fa71b9SJerome Forissier                 /* We copy the message back into the input buffer
423211fa71b9SJerome Forissier                  * after reassembly, so check that it's not too large.
423311fa71b9SJerome Forissier                  * This is an implementation-specific limitation
423411fa71b9SJerome Forissier                  * and not one from the standard, hence it is not
423511fa71b9SJerome Forissier                  * checked in ssl_check_hs_header(). */
423611fa71b9SJerome Forissier                 if( msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN )
423711fa71b9SJerome Forissier                 {
423811fa71b9SJerome Forissier                     /* Ignore message */
423911fa71b9SJerome Forissier                     goto exit;
424011fa71b9SJerome Forissier                 }
424111fa71b9SJerome Forissier 
424211fa71b9SJerome Forissier                 /* Check if we have enough space to buffer the message. */
424311fa71b9SJerome Forissier                 if( hs->buffering.total_bytes_buffered >
424411fa71b9SJerome Forissier                     MBEDTLS_SSL_DTLS_MAX_BUFFERING )
424511fa71b9SJerome Forissier                 {
424611fa71b9SJerome Forissier                     MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
424711fa71b9SJerome Forissier                     return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
424811fa71b9SJerome Forissier                 }
424911fa71b9SJerome Forissier 
425011fa71b9SJerome Forissier                 reassembly_buf_sz = ssl_get_reassembly_buffer_size( msg_len,
425111fa71b9SJerome Forissier                                                        hs_buf->is_fragmented );
425211fa71b9SJerome Forissier 
425311fa71b9SJerome Forissier                 if( reassembly_buf_sz > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
425411fa71b9SJerome Forissier                                           hs->buffering.total_bytes_buffered ) )
425511fa71b9SJerome Forissier                 {
425611fa71b9SJerome Forissier                     if( recv_msg_seq_offset > 0 )
425711fa71b9SJerome Forissier                     {
425811fa71b9SJerome Forissier                         /* If we can't buffer a future message because
425911fa71b9SJerome Forissier                          * of space limitations -- ignore. */
42607901324dSJerome Forissier                         MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %" MBEDTLS_PRINTF_SIZET
42617901324dSJerome Forissier                                                     " would exceed the compile-time limit %" MBEDTLS_PRINTF_SIZET
42627901324dSJerome Forissier                                                     " (already %" MBEDTLS_PRINTF_SIZET
42637901324dSJerome Forissier                                                     " bytes buffered) -- ignore\n",
42647901324dSJerome Forissier                              msg_len, (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING,
42657901324dSJerome Forissier                              hs->buffering.total_bytes_buffered ) );
426611fa71b9SJerome Forissier                         goto exit;
426711fa71b9SJerome Forissier                     }
426811fa71b9SJerome Forissier                     else
426911fa71b9SJerome Forissier                     {
42707901324dSJerome Forissier                         MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %" MBEDTLS_PRINTF_SIZET
42717901324dSJerome Forissier                                                     " would exceed the compile-time limit %" MBEDTLS_PRINTF_SIZET
42727901324dSJerome Forissier                                                     " (already %" MBEDTLS_PRINTF_SIZET
42737901324dSJerome Forissier                                                     " bytes buffered) -- attempt to make space by freeing buffered future messages\n",
42747901324dSJerome Forissier                              msg_len, (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING,
42757901324dSJerome Forissier                              hs->buffering.total_bytes_buffered ) );
427611fa71b9SJerome Forissier                     }
427711fa71b9SJerome Forissier 
427811fa71b9SJerome Forissier                     if( ssl_buffer_make_space( ssl, reassembly_buf_sz ) != 0 )
427911fa71b9SJerome Forissier                     {
42807901324dSJerome Forissier                         MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reassembly of next message of size %" MBEDTLS_PRINTF_SIZET
42817901324dSJerome Forissier                                                     " (%" MBEDTLS_PRINTF_SIZET " with bitmap) would exceed"
42827901324dSJerome Forissier                                                     " the compile-time limit %" MBEDTLS_PRINTF_SIZET
42837901324dSJerome Forissier                                                     " (already %" MBEDTLS_PRINTF_SIZET
42847901324dSJerome Forissier                                                     " bytes buffered) -- fail\n",
42857901324dSJerome Forissier                              msg_len,
42867901324dSJerome Forissier                              reassembly_buf_sz,
42877901324dSJerome Forissier                              (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING,
42887901324dSJerome Forissier                              hs->buffering.total_bytes_buffered ) );
428911fa71b9SJerome Forissier                         ret = MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
429011fa71b9SJerome Forissier                         goto exit;
429111fa71b9SJerome Forissier                     }
429211fa71b9SJerome Forissier                 }
429311fa71b9SJerome Forissier 
42947901324dSJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %" MBEDTLS_PRINTF_SIZET,
429511fa71b9SJerome Forissier                                             msg_len ) );
429611fa71b9SJerome Forissier 
429711fa71b9SJerome Forissier                 hs_buf->data = mbedtls_calloc( 1, reassembly_buf_sz );
429811fa71b9SJerome Forissier                 if( hs_buf->data == NULL )
429911fa71b9SJerome Forissier                 {
430011fa71b9SJerome Forissier                     ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
430111fa71b9SJerome Forissier                     goto exit;
430211fa71b9SJerome Forissier                 }
430311fa71b9SJerome Forissier                 hs_buf->data_len = reassembly_buf_sz;
430411fa71b9SJerome Forissier 
430511fa71b9SJerome Forissier                 /* Prepare final header: copy msg_type, length and message_seq,
430611fa71b9SJerome Forissier                  * then add standardised fragment_offset and fragment_length */
430711fa71b9SJerome Forissier                 memcpy( hs_buf->data, ssl->in_msg, 6 );
430811fa71b9SJerome Forissier                 memset( hs_buf->data + 6, 0, 3 );
430911fa71b9SJerome Forissier                 memcpy( hs_buf->data + 9, hs_buf->data + 1, 3 );
431011fa71b9SJerome Forissier 
431111fa71b9SJerome Forissier                 hs_buf->is_valid = 1;
431211fa71b9SJerome Forissier 
431311fa71b9SJerome Forissier                 hs->buffering.total_bytes_buffered += reassembly_buf_sz;
431411fa71b9SJerome Forissier             }
431511fa71b9SJerome Forissier             else
431611fa71b9SJerome Forissier             {
431711fa71b9SJerome Forissier                 /* Make sure msg_type and length are consistent */
431811fa71b9SJerome Forissier                 if( memcmp( hs_buf->data, ssl->in_msg, 4 ) != 0 )
431911fa71b9SJerome Forissier                 {
432011fa71b9SJerome Forissier                     MBEDTLS_SSL_DEBUG_MSG( 1, ( "Fragment header mismatch - ignore" ) );
432111fa71b9SJerome Forissier                     /* Ignore */
432211fa71b9SJerome Forissier                     goto exit;
432311fa71b9SJerome Forissier                 }
432411fa71b9SJerome Forissier             }
432511fa71b9SJerome Forissier 
432611fa71b9SJerome Forissier             if( !hs_buf->is_complete )
432711fa71b9SJerome Forissier             {
432811fa71b9SJerome Forissier                 size_t frag_len, frag_off;
432911fa71b9SJerome Forissier                 unsigned char * const msg = hs_buf->data + 12;
433011fa71b9SJerome Forissier 
433111fa71b9SJerome Forissier                 /*
433211fa71b9SJerome Forissier                  * Check and copy current fragment
433311fa71b9SJerome Forissier                  */
433411fa71b9SJerome Forissier 
433511fa71b9SJerome Forissier                 /* Validation of header fields already done in
433611fa71b9SJerome Forissier                  * mbedtls_ssl_prepare_handshake_record(). */
433711fa71b9SJerome Forissier                 frag_off = ssl_get_hs_frag_off( ssl );
433811fa71b9SJerome Forissier                 frag_len = ssl_get_hs_frag_len( ssl );
433911fa71b9SJerome Forissier 
43407901324dSJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 2, ( "adding fragment, offset = %" MBEDTLS_PRINTF_SIZET
43417901324dSJerome Forissier                                             ", length = %" MBEDTLS_PRINTF_SIZET,
434211fa71b9SJerome Forissier                                             frag_off, frag_len ) );
434311fa71b9SJerome Forissier                 memcpy( msg + frag_off, ssl->in_msg + 12, frag_len );
434411fa71b9SJerome Forissier 
434511fa71b9SJerome Forissier                 if( hs_buf->is_fragmented )
434611fa71b9SJerome Forissier                 {
434711fa71b9SJerome Forissier                     unsigned char * const bitmask = msg + msg_len;
434811fa71b9SJerome Forissier                     ssl_bitmask_set( bitmask, frag_off, frag_len );
434911fa71b9SJerome Forissier                     hs_buf->is_complete = ( ssl_bitmask_check( bitmask,
435011fa71b9SJerome Forissier                                                                msg_len ) == 0 );
435111fa71b9SJerome Forissier                 }
435211fa71b9SJerome Forissier                 else
435311fa71b9SJerome Forissier                 {
435411fa71b9SJerome Forissier                     hs_buf->is_complete = 1;
435511fa71b9SJerome Forissier                 }
435611fa71b9SJerome Forissier 
435711fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 2, ( "message %scomplete",
435811fa71b9SJerome Forissier                                    hs_buf->is_complete ? "" : "not yet " ) );
435911fa71b9SJerome Forissier             }
436011fa71b9SJerome Forissier 
436111fa71b9SJerome Forissier             break;
436211fa71b9SJerome Forissier         }
436311fa71b9SJerome Forissier 
436411fa71b9SJerome Forissier         default:
436511fa71b9SJerome Forissier             /* We don't buffer other types of messages. */
436611fa71b9SJerome Forissier             break;
436711fa71b9SJerome Forissier     }
436811fa71b9SJerome Forissier 
436911fa71b9SJerome Forissier exit:
437011fa71b9SJerome Forissier 
437111fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_buffer_message" ) );
437211fa71b9SJerome Forissier     return( ret );
437311fa71b9SJerome Forissier }
437411fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
437511fa71b9SJerome Forissier 
4376*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
437711fa71b9SJerome Forissier static int ssl_consume_current_message( mbedtls_ssl_context *ssl )
437811fa71b9SJerome Forissier {
437911fa71b9SJerome Forissier     /*
438011fa71b9SJerome Forissier      * Consume last content-layer message and potentially
438111fa71b9SJerome Forissier      * update in_msglen which keeps track of the contents'
438211fa71b9SJerome Forissier      * consumption state.
438311fa71b9SJerome Forissier      *
438411fa71b9SJerome Forissier      * (1) Handshake messages:
438511fa71b9SJerome Forissier      *     Remove last handshake message, move content
438611fa71b9SJerome Forissier      *     and adapt in_msglen.
438711fa71b9SJerome Forissier      *
438811fa71b9SJerome Forissier      * (2) Alert messages:
438911fa71b9SJerome Forissier      *     Consume whole record content, in_msglen = 0.
439011fa71b9SJerome Forissier      *
439111fa71b9SJerome Forissier      * (3) Change cipher spec:
439211fa71b9SJerome Forissier      *     Consume whole record content, in_msglen = 0.
439311fa71b9SJerome Forissier      *
439411fa71b9SJerome Forissier      * (4) Application data:
439511fa71b9SJerome Forissier      *     Don't do anything - the record layer provides
439611fa71b9SJerome Forissier      *     the application data as a stream transport
439711fa71b9SJerome Forissier      *     and consumes through mbedtls_ssl_read only.
439811fa71b9SJerome Forissier      *
439911fa71b9SJerome Forissier      */
440011fa71b9SJerome Forissier 
440111fa71b9SJerome Forissier     /* Case (1): Handshake messages */
440211fa71b9SJerome Forissier     if( ssl->in_hslen != 0 )
440311fa71b9SJerome Forissier     {
440411fa71b9SJerome Forissier         /* Hard assertion to be sure that no application data
440511fa71b9SJerome Forissier          * is in flight, as corrupting ssl->in_msglen during
440611fa71b9SJerome Forissier          * ssl->in_offt != NULL is fatal. */
440711fa71b9SJerome Forissier         if( ssl->in_offt != NULL )
440811fa71b9SJerome Forissier         {
440911fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
441011fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
441111fa71b9SJerome Forissier         }
441211fa71b9SJerome Forissier 
441311fa71b9SJerome Forissier         /*
441411fa71b9SJerome Forissier          * Get next Handshake message in the current record
441511fa71b9SJerome Forissier          */
441611fa71b9SJerome Forissier 
441711fa71b9SJerome Forissier         /* Notes:
441811fa71b9SJerome Forissier          * (1) in_hslen is not necessarily the size of the
441911fa71b9SJerome Forissier          *     current handshake content: If DTLS handshake
442011fa71b9SJerome Forissier          *     fragmentation is used, that's the fragment
442111fa71b9SJerome Forissier          *     size instead. Using the total handshake message
442211fa71b9SJerome Forissier          *     size here is faulty and should be changed at
442311fa71b9SJerome Forissier          *     some point.
442411fa71b9SJerome Forissier          * (2) While it doesn't seem to cause problems, one
442511fa71b9SJerome Forissier          *     has to be very careful not to assume that in_hslen
442611fa71b9SJerome Forissier          *     is always <= in_msglen in a sensible communication.
442711fa71b9SJerome Forissier          *     Again, it's wrong for DTLS handshake fragmentation.
442811fa71b9SJerome Forissier          *     The following check is therefore mandatory, and
442911fa71b9SJerome Forissier          *     should not be treated as a silently corrected assertion.
443011fa71b9SJerome Forissier          *     Additionally, ssl->in_hslen might be arbitrarily out of
443111fa71b9SJerome Forissier          *     bounds after handling a DTLS message with an unexpected
443211fa71b9SJerome Forissier          *     sequence number, see mbedtls_ssl_prepare_handshake_record.
443311fa71b9SJerome Forissier          */
443411fa71b9SJerome Forissier         if( ssl->in_hslen < ssl->in_msglen )
443511fa71b9SJerome Forissier         {
443611fa71b9SJerome Forissier             ssl->in_msglen -= ssl->in_hslen;
443711fa71b9SJerome Forissier             memmove( ssl->in_msg, ssl->in_msg + ssl->in_hslen,
443811fa71b9SJerome Forissier                      ssl->in_msglen );
443911fa71b9SJerome Forissier 
444011fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_BUF( 4, "remaining content in record",
444111fa71b9SJerome Forissier                                    ssl->in_msg, ssl->in_msglen );
444211fa71b9SJerome Forissier         }
444311fa71b9SJerome Forissier         else
444411fa71b9SJerome Forissier         {
444511fa71b9SJerome Forissier             ssl->in_msglen = 0;
444611fa71b9SJerome Forissier         }
444711fa71b9SJerome Forissier 
444811fa71b9SJerome Forissier         ssl->in_hslen   = 0;
444911fa71b9SJerome Forissier     }
445011fa71b9SJerome Forissier     /* Case (4): Application data */
445111fa71b9SJerome Forissier     else if( ssl->in_offt != NULL )
445211fa71b9SJerome Forissier     {
445311fa71b9SJerome Forissier         return( 0 );
445411fa71b9SJerome Forissier     }
445511fa71b9SJerome Forissier     /* Everything else (CCS & Alerts) */
445611fa71b9SJerome Forissier     else
445711fa71b9SJerome Forissier     {
445811fa71b9SJerome Forissier         ssl->in_msglen = 0;
445911fa71b9SJerome Forissier     }
446011fa71b9SJerome Forissier 
446111fa71b9SJerome Forissier     return( 0 );
446211fa71b9SJerome Forissier }
446311fa71b9SJerome Forissier 
4464*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
446511fa71b9SJerome Forissier static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl )
446611fa71b9SJerome Forissier {
446711fa71b9SJerome Forissier     if( ssl->in_msglen > 0 )
446811fa71b9SJerome Forissier         return( 1 );
446911fa71b9SJerome Forissier 
447011fa71b9SJerome Forissier     return( 0 );
447111fa71b9SJerome Forissier }
447211fa71b9SJerome Forissier 
447311fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
447411fa71b9SJerome Forissier 
447511fa71b9SJerome Forissier static void ssl_free_buffered_record( mbedtls_ssl_context *ssl )
447611fa71b9SJerome Forissier {
447711fa71b9SJerome Forissier     mbedtls_ssl_handshake_params * const hs = ssl->handshake;
447811fa71b9SJerome Forissier     if( hs == NULL )
447911fa71b9SJerome Forissier         return;
448011fa71b9SJerome Forissier 
448111fa71b9SJerome Forissier     if( hs->buffering.future_record.data != NULL )
448211fa71b9SJerome Forissier     {
448311fa71b9SJerome Forissier         hs->buffering.total_bytes_buffered -=
448411fa71b9SJerome Forissier             hs->buffering.future_record.len;
448511fa71b9SJerome Forissier 
448611fa71b9SJerome Forissier         mbedtls_free( hs->buffering.future_record.data );
448711fa71b9SJerome Forissier         hs->buffering.future_record.data = NULL;
448811fa71b9SJerome Forissier     }
448911fa71b9SJerome Forissier }
449011fa71b9SJerome Forissier 
4491*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
449211fa71b9SJerome Forissier static int ssl_load_buffered_record( mbedtls_ssl_context *ssl )
449311fa71b9SJerome Forissier {
449411fa71b9SJerome Forissier     mbedtls_ssl_handshake_params * const hs = ssl->handshake;
449511fa71b9SJerome Forissier     unsigned char * rec;
449611fa71b9SJerome Forissier     size_t rec_len;
449711fa71b9SJerome Forissier     unsigned rec_epoch;
449811fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
449911fa71b9SJerome Forissier     size_t in_buf_len = ssl->in_buf_len;
450011fa71b9SJerome Forissier #else
450111fa71b9SJerome Forissier     size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN;
450211fa71b9SJerome Forissier #endif
450311fa71b9SJerome Forissier     if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM )
450411fa71b9SJerome Forissier         return( 0 );
450511fa71b9SJerome Forissier 
450611fa71b9SJerome Forissier     if( hs == NULL )
450711fa71b9SJerome Forissier         return( 0 );
450811fa71b9SJerome Forissier 
450911fa71b9SJerome Forissier     rec       = hs->buffering.future_record.data;
451011fa71b9SJerome Forissier     rec_len   = hs->buffering.future_record.len;
451111fa71b9SJerome Forissier     rec_epoch = hs->buffering.future_record.epoch;
451211fa71b9SJerome Forissier 
451311fa71b9SJerome Forissier     if( rec == NULL )
451411fa71b9SJerome Forissier         return( 0 );
451511fa71b9SJerome Forissier 
451611fa71b9SJerome Forissier     /* Only consider loading future records if the
451711fa71b9SJerome Forissier      * input buffer is empty. */
451811fa71b9SJerome Forissier     if( ssl_next_record_is_in_datagram( ssl ) == 1 )
451911fa71b9SJerome Forissier         return( 0 );
452011fa71b9SJerome Forissier 
452111fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_record" ) );
452211fa71b9SJerome Forissier 
452311fa71b9SJerome Forissier     if( rec_epoch != ssl->in_epoch )
452411fa71b9SJerome Forissier     {
452511fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffered record not from current epoch." ) );
452611fa71b9SJerome Forissier         goto exit;
452711fa71b9SJerome Forissier     }
452811fa71b9SJerome Forissier 
452911fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "Found buffered record from current epoch - load" ) );
453011fa71b9SJerome Forissier 
453111fa71b9SJerome Forissier     /* Double-check that the record is not too large */
453211fa71b9SJerome Forissier     if( rec_len > in_buf_len - (size_t)( ssl->in_hdr - ssl->in_buf ) )
453311fa71b9SJerome Forissier     {
453411fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
453511fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
453611fa71b9SJerome Forissier     }
453711fa71b9SJerome Forissier 
453811fa71b9SJerome Forissier     memcpy( ssl->in_hdr, rec, rec_len );
453911fa71b9SJerome Forissier     ssl->in_left = rec_len;
454011fa71b9SJerome Forissier     ssl->next_record_offset = 0;
454111fa71b9SJerome Forissier 
454211fa71b9SJerome Forissier     ssl_free_buffered_record( ssl );
454311fa71b9SJerome Forissier 
454411fa71b9SJerome Forissier exit:
454511fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_load_buffered_record" ) );
454611fa71b9SJerome Forissier     return( 0 );
454711fa71b9SJerome Forissier }
454811fa71b9SJerome Forissier 
4549*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
455011fa71b9SJerome Forissier static int ssl_buffer_future_record( mbedtls_ssl_context *ssl,
455111fa71b9SJerome Forissier                                      mbedtls_record const *rec )
455211fa71b9SJerome Forissier {
455311fa71b9SJerome Forissier     mbedtls_ssl_handshake_params * const hs = ssl->handshake;
455411fa71b9SJerome Forissier 
455511fa71b9SJerome Forissier     /* Don't buffer future records outside handshakes. */
455611fa71b9SJerome Forissier     if( hs == NULL )
455711fa71b9SJerome Forissier         return( 0 );
455811fa71b9SJerome Forissier 
455911fa71b9SJerome Forissier     /* Only buffer handshake records (we are only interested
456011fa71b9SJerome Forissier      * in Finished messages). */
456111fa71b9SJerome Forissier     if( rec->type != MBEDTLS_SSL_MSG_HANDSHAKE )
456211fa71b9SJerome Forissier         return( 0 );
456311fa71b9SJerome Forissier 
456411fa71b9SJerome Forissier     /* Don't buffer more than one future epoch record. */
456511fa71b9SJerome Forissier     if( hs->buffering.future_record.data != NULL )
456611fa71b9SJerome Forissier         return( 0 );
456711fa71b9SJerome Forissier 
456811fa71b9SJerome Forissier     /* Don't buffer record if there's not enough buffering space remaining. */
456911fa71b9SJerome Forissier     if( rec->buf_len > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
457011fa71b9SJerome Forissier                          hs->buffering.total_bytes_buffered ) )
457111fa71b9SJerome Forissier     {
45727901324dSJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future epoch record of size %" MBEDTLS_PRINTF_SIZET
45737901324dSJerome Forissier                                     " would exceed the compile-time limit %" MBEDTLS_PRINTF_SIZET
45747901324dSJerome Forissier                                     " (already %" MBEDTLS_PRINTF_SIZET
45757901324dSJerome Forissier                                     " bytes buffered) -- ignore\n",
45767901324dSJerome Forissier                         rec->buf_len, (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING,
45777901324dSJerome Forissier                         hs->buffering.total_bytes_buffered ) );
457811fa71b9SJerome Forissier         return( 0 );
457911fa71b9SJerome Forissier     }
458011fa71b9SJerome Forissier 
458111fa71b9SJerome Forissier     /* Buffer record */
458211fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffer record from epoch %u",
45837901324dSJerome Forissier                                 ssl->in_epoch + 1U ) );
458411fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered record", rec->buf, rec->buf_len );
458511fa71b9SJerome Forissier 
458611fa71b9SJerome Forissier     /* ssl_parse_record_header() only considers records
458711fa71b9SJerome Forissier      * of the next epoch as candidates for buffering. */
458811fa71b9SJerome Forissier     hs->buffering.future_record.epoch = ssl->in_epoch + 1;
458911fa71b9SJerome Forissier     hs->buffering.future_record.len   = rec->buf_len;
459011fa71b9SJerome Forissier 
459111fa71b9SJerome Forissier     hs->buffering.future_record.data =
459211fa71b9SJerome Forissier         mbedtls_calloc( 1, hs->buffering.future_record.len );
459311fa71b9SJerome Forissier     if( hs->buffering.future_record.data == NULL )
459411fa71b9SJerome Forissier     {
459511fa71b9SJerome Forissier         /* If we run out of RAM trying to buffer a
459611fa71b9SJerome Forissier          * record from the next epoch, just ignore. */
459711fa71b9SJerome Forissier         return( 0 );
459811fa71b9SJerome Forissier     }
459911fa71b9SJerome Forissier 
460011fa71b9SJerome Forissier     memcpy( hs->buffering.future_record.data, rec->buf, rec->buf_len );
460111fa71b9SJerome Forissier 
460211fa71b9SJerome Forissier     hs->buffering.total_bytes_buffered += rec->buf_len;
460311fa71b9SJerome Forissier     return( 0 );
460411fa71b9SJerome Forissier }
460511fa71b9SJerome Forissier 
460611fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
460711fa71b9SJerome Forissier 
4608*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
460911fa71b9SJerome Forissier static int ssl_get_next_record( mbedtls_ssl_context *ssl )
461011fa71b9SJerome Forissier {
461111fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
461211fa71b9SJerome Forissier     mbedtls_record rec;
461311fa71b9SJerome Forissier 
461411fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
461511fa71b9SJerome Forissier     /* We might have buffered a future record; if so,
461611fa71b9SJerome Forissier      * and if the epoch matches now, load it.
461711fa71b9SJerome Forissier      * On success, this call will set ssl->in_left to
461811fa71b9SJerome Forissier      * the length of the buffered record, so that
461911fa71b9SJerome Forissier      * the calls to ssl_fetch_input() below will
462011fa71b9SJerome Forissier      * essentially be no-ops. */
462111fa71b9SJerome Forissier     ret = ssl_load_buffered_record( ssl );
462211fa71b9SJerome Forissier     if( ret != 0 )
462311fa71b9SJerome Forissier         return( ret );
462411fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
462511fa71b9SJerome Forissier 
462611fa71b9SJerome Forissier     /* Ensure that we have enough space available for the default form
462711fa71b9SJerome Forissier      * of TLS / DTLS record headers (5 Bytes for TLS, 13 Bytes for DTLS,
462811fa71b9SJerome Forissier      * with no space for CIDs counted in). */
462911fa71b9SJerome Forissier     ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_in_hdr_len( ssl ) );
463011fa71b9SJerome Forissier     if( ret != 0 )
463111fa71b9SJerome Forissier     {
463211fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret );
463311fa71b9SJerome Forissier         return( ret );
463411fa71b9SJerome Forissier     }
463511fa71b9SJerome Forissier 
463611fa71b9SJerome Forissier     ret = ssl_parse_record_header( ssl, ssl->in_hdr, ssl->in_left, &rec );
463711fa71b9SJerome Forissier     if( ret != 0 )
463811fa71b9SJerome Forissier     {
463911fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
464011fa71b9SJerome Forissier         if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
464111fa71b9SJerome Forissier         {
464211fa71b9SJerome Forissier             if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE )
464311fa71b9SJerome Forissier             {
464411fa71b9SJerome Forissier                 ret = ssl_buffer_future_record( ssl, &rec );
464511fa71b9SJerome Forissier                 if( ret != 0 )
464611fa71b9SJerome Forissier                     return( ret );
464711fa71b9SJerome Forissier 
464811fa71b9SJerome Forissier                 /* Fall through to handling of unexpected records */
464911fa71b9SJerome Forissier                 ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD;
465011fa71b9SJerome Forissier             }
465111fa71b9SJerome Forissier 
465211fa71b9SJerome Forissier             if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD )
465311fa71b9SJerome Forissier             {
465411fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
465511fa71b9SJerome Forissier                 /* Reset in pointers to default state for TLS/DTLS records,
465611fa71b9SJerome Forissier                  * assuming no CID and no offset between record content and
465711fa71b9SJerome Forissier                  * record plaintext. */
465811fa71b9SJerome Forissier                 mbedtls_ssl_update_in_pointers( ssl );
465911fa71b9SJerome Forissier 
466011fa71b9SJerome Forissier                 /* Setup internal message pointers from record structure. */
466111fa71b9SJerome Forissier                 ssl->in_msgtype = rec.type;
466211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
466311fa71b9SJerome Forissier                 ssl->in_len = ssl->in_cid + rec.cid_len;
466411fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
466511fa71b9SJerome Forissier                 ssl->in_iv  = ssl->in_msg = ssl->in_len + 2;
466611fa71b9SJerome Forissier                 ssl->in_msglen = rec.data_len;
466711fa71b9SJerome Forissier 
466811fa71b9SJerome Forissier                 ret = ssl_check_client_reconnect( ssl );
466911fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_RET( 2, "ssl_check_client_reconnect", ret );
467011fa71b9SJerome Forissier                 if( ret != 0 )
467111fa71b9SJerome Forissier                     return( ret );
467211fa71b9SJerome Forissier #endif
467311fa71b9SJerome Forissier 
467411fa71b9SJerome Forissier                 /* Skip unexpected record (but not whole datagram) */
467511fa71b9SJerome Forissier                 ssl->next_record_offset = rec.buf_len;
467611fa71b9SJerome Forissier 
467711fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding unexpected record "
467811fa71b9SJerome Forissier                                             "(header)" ) );
467911fa71b9SJerome Forissier             }
468011fa71b9SJerome Forissier             else
468111fa71b9SJerome Forissier             {
468211fa71b9SJerome Forissier                 /* Skip invalid record and the rest of the datagram */
468311fa71b9SJerome Forissier                 ssl->next_record_offset = 0;
468411fa71b9SJerome Forissier                 ssl->in_left = 0;
468511fa71b9SJerome Forissier 
468611fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record "
468711fa71b9SJerome Forissier                                             "(header)" ) );
468811fa71b9SJerome Forissier             }
468911fa71b9SJerome Forissier 
469011fa71b9SJerome Forissier             /* Get next record */
469111fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
469211fa71b9SJerome Forissier         }
469311fa71b9SJerome Forissier         else
469411fa71b9SJerome Forissier #endif
469511fa71b9SJerome Forissier         {
469611fa71b9SJerome Forissier             return( ret );
469711fa71b9SJerome Forissier         }
469811fa71b9SJerome Forissier     }
469911fa71b9SJerome Forissier 
470011fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
470111fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
470211fa71b9SJerome Forissier     {
470311fa71b9SJerome Forissier         /* Remember offset of next record within datagram. */
470411fa71b9SJerome Forissier         ssl->next_record_offset = rec.buf_len;
470511fa71b9SJerome Forissier         if( ssl->next_record_offset < ssl->in_left )
470611fa71b9SJerome Forissier         {
470711fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 3, ( "more than one record within datagram" ) );
470811fa71b9SJerome Forissier         }
470911fa71b9SJerome Forissier     }
471011fa71b9SJerome Forissier     else
471111fa71b9SJerome Forissier #endif
471211fa71b9SJerome Forissier     {
471311fa71b9SJerome Forissier         /*
471411fa71b9SJerome Forissier          * Fetch record contents from underlying transport.
471511fa71b9SJerome Forissier          */
471611fa71b9SJerome Forissier         ret = mbedtls_ssl_fetch_input( ssl, rec.buf_len );
471711fa71b9SJerome Forissier         if( ret != 0 )
471811fa71b9SJerome Forissier         {
471911fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret );
472011fa71b9SJerome Forissier             return( ret );
472111fa71b9SJerome Forissier         }
472211fa71b9SJerome Forissier 
472311fa71b9SJerome Forissier         ssl->in_left = 0;
472411fa71b9SJerome Forissier     }
472511fa71b9SJerome Forissier 
472611fa71b9SJerome Forissier     /*
472711fa71b9SJerome Forissier      * Decrypt record contents.
472811fa71b9SJerome Forissier      */
472911fa71b9SJerome Forissier 
473011fa71b9SJerome Forissier     if( ( ret = ssl_prepare_record_content( ssl, &rec ) ) != 0 )
473111fa71b9SJerome Forissier     {
473211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
473311fa71b9SJerome Forissier         if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
473411fa71b9SJerome Forissier         {
473511fa71b9SJerome Forissier             /* Silently discard invalid records */
473611fa71b9SJerome Forissier             if( ret == MBEDTLS_ERR_SSL_INVALID_MAC )
473711fa71b9SJerome Forissier             {
473811fa71b9SJerome Forissier                 /* Except when waiting for Finished as a bad mac here
473911fa71b9SJerome Forissier                  * probably means something went wrong in the handshake
474011fa71b9SJerome Forissier                  * (eg wrong psk used, mitm downgrade attempt, etc.) */
474111fa71b9SJerome Forissier                 if( ssl->state == MBEDTLS_SSL_CLIENT_FINISHED ||
474211fa71b9SJerome Forissier                     ssl->state == MBEDTLS_SSL_SERVER_FINISHED )
474311fa71b9SJerome Forissier                 {
474411fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES)
474511fa71b9SJerome Forissier                     if( ret == MBEDTLS_ERR_SSL_INVALID_MAC )
474611fa71b9SJerome Forissier                     {
474711fa71b9SJerome Forissier                         mbedtls_ssl_send_alert_message( ssl,
474811fa71b9SJerome Forissier                                 MBEDTLS_SSL_ALERT_LEVEL_FATAL,
474911fa71b9SJerome Forissier                                 MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC );
475011fa71b9SJerome Forissier                     }
475111fa71b9SJerome Forissier #endif
475211fa71b9SJerome Forissier                     return( ret );
475311fa71b9SJerome Forissier                 }
475411fa71b9SJerome Forissier 
475511fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT)
475611fa71b9SJerome Forissier                 if( ssl->conf->badmac_limit != 0 &&
475711fa71b9SJerome Forissier                     ++ssl->badmac_seen >= ssl->conf->badmac_limit )
475811fa71b9SJerome Forissier                 {
475911fa71b9SJerome Forissier                     MBEDTLS_SSL_DEBUG_MSG( 1, ( "too many records with bad MAC" ) );
476011fa71b9SJerome Forissier                     return( MBEDTLS_ERR_SSL_INVALID_MAC );
476111fa71b9SJerome Forissier                 }
476211fa71b9SJerome Forissier #endif
476311fa71b9SJerome Forissier 
476411fa71b9SJerome Forissier                 /* As above, invalid records cause
476511fa71b9SJerome Forissier                  * dismissal of the whole datagram. */
476611fa71b9SJerome Forissier 
476711fa71b9SJerome Forissier                 ssl->next_record_offset = 0;
476811fa71b9SJerome Forissier                 ssl->in_left = 0;
476911fa71b9SJerome Forissier 
477011fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record (mac)" ) );
477111fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
477211fa71b9SJerome Forissier             }
477311fa71b9SJerome Forissier 
477411fa71b9SJerome Forissier             return( ret );
477511fa71b9SJerome Forissier         }
477611fa71b9SJerome Forissier         else
477711fa71b9SJerome Forissier #endif
477811fa71b9SJerome Forissier         {
477911fa71b9SJerome Forissier             /* Error out (and send alert) on invalid records */
478011fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES)
478111fa71b9SJerome Forissier             if( ret == MBEDTLS_ERR_SSL_INVALID_MAC )
478211fa71b9SJerome Forissier             {
478311fa71b9SJerome Forissier                 mbedtls_ssl_send_alert_message( ssl,
478411fa71b9SJerome Forissier                         MBEDTLS_SSL_ALERT_LEVEL_FATAL,
478511fa71b9SJerome Forissier                         MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC );
478611fa71b9SJerome Forissier             }
478711fa71b9SJerome Forissier #endif
478811fa71b9SJerome Forissier             return( ret );
478911fa71b9SJerome Forissier         }
479011fa71b9SJerome Forissier     }
479111fa71b9SJerome Forissier 
479211fa71b9SJerome Forissier 
479311fa71b9SJerome Forissier     /* Reset in pointers to default state for TLS/DTLS records,
479411fa71b9SJerome Forissier      * assuming no CID and no offset between record content and
479511fa71b9SJerome Forissier      * record plaintext. */
479611fa71b9SJerome Forissier     mbedtls_ssl_update_in_pointers( ssl );
479711fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
479811fa71b9SJerome Forissier     ssl->in_len = ssl->in_cid + rec.cid_len;
479911fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
480011fa71b9SJerome Forissier     ssl->in_iv  = ssl->in_len + 2;
480111fa71b9SJerome Forissier 
480211fa71b9SJerome Forissier     /* The record content type may change during decryption,
480311fa71b9SJerome Forissier      * so re-read it. */
480411fa71b9SJerome Forissier     ssl->in_msgtype = rec.type;
480511fa71b9SJerome Forissier     /* Also update the input buffer, because unfortunately
480611fa71b9SJerome Forissier      * the server-side ssl_parse_client_hello() reparses the
480711fa71b9SJerome Forissier      * record header when receiving a ClientHello initiating
480811fa71b9SJerome Forissier      * a renegotiation. */
480911fa71b9SJerome Forissier     ssl->in_hdr[0] = rec.type;
481011fa71b9SJerome Forissier     ssl->in_msg    = rec.buf + rec.data_offset;
481111fa71b9SJerome Forissier     ssl->in_msglen = rec.data_len;
4812*039e02dfSJerome Forissier     MBEDTLS_PUT_UINT16_BE( rec.data_len, ssl->in_len, 0 );
481311fa71b9SJerome Forissier 
481411fa71b9SJerome Forissier #if defined(MBEDTLS_ZLIB_SUPPORT)
481511fa71b9SJerome Forissier     if( ssl->transform_in != NULL &&
481611fa71b9SJerome Forissier         ssl->session_in->compression == MBEDTLS_SSL_COMPRESS_DEFLATE )
481711fa71b9SJerome Forissier     {
481811fa71b9SJerome Forissier         if( ( ret = ssl_decompress_buf( ssl ) ) != 0 )
481911fa71b9SJerome Forissier         {
482011fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decompress_buf", ret );
482111fa71b9SJerome Forissier             return( ret );
482211fa71b9SJerome Forissier         }
482311fa71b9SJerome Forissier 
482411fa71b9SJerome Forissier         /* Check actual (decompress) record content length against
482511fa71b9SJerome Forissier          * configured maximum. */
482611fa71b9SJerome Forissier         if( ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN )
482711fa71b9SJerome Forissier         {
482811fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
482911fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INVALID_RECORD );
483011fa71b9SJerome Forissier         }
483111fa71b9SJerome Forissier     }
483211fa71b9SJerome Forissier #endif /* MBEDTLS_ZLIB_SUPPORT */
483311fa71b9SJerome Forissier 
483411fa71b9SJerome Forissier     return( 0 );
483511fa71b9SJerome Forissier }
483611fa71b9SJerome Forissier 
483711fa71b9SJerome Forissier int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl )
483811fa71b9SJerome Forissier {
483911fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
484011fa71b9SJerome Forissier 
484111fa71b9SJerome Forissier     /*
484211fa71b9SJerome Forissier      * Handle particular types of records
484311fa71b9SJerome Forissier      */
484411fa71b9SJerome Forissier     if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE )
484511fa71b9SJerome Forissier     {
484611fa71b9SJerome Forissier         if( ( ret = mbedtls_ssl_prepare_handshake_record( ssl ) ) != 0 )
484711fa71b9SJerome Forissier         {
484811fa71b9SJerome Forissier             return( ret );
484911fa71b9SJerome Forissier         }
485011fa71b9SJerome Forissier     }
485111fa71b9SJerome Forissier 
485211fa71b9SJerome Forissier     if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC )
485311fa71b9SJerome Forissier     {
485411fa71b9SJerome Forissier         if( ssl->in_msglen != 1 )
485511fa71b9SJerome Forissier         {
48567901324dSJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, len: %" MBEDTLS_PRINTF_SIZET,
485711fa71b9SJerome Forissier                            ssl->in_msglen ) );
485811fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INVALID_RECORD );
485911fa71b9SJerome Forissier         }
486011fa71b9SJerome Forissier 
486111fa71b9SJerome Forissier         if( ssl->in_msg[0] != 1 )
486211fa71b9SJerome Forissier         {
486311fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, content: %02x",
486411fa71b9SJerome Forissier                                         ssl->in_msg[0] ) );
486511fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INVALID_RECORD );
486611fa71b9SJerome Forissier         }
486711fa71b9SJerome Forissier 
486811fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
486911fa71b9SJerome Forissier         if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
487011fa71b9SJerome Forissier             ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC    &&
487111fa71b9SJerome Forissier             ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC )
487211fa71b9SJerome Forissier         {
487311fa71b9SJerome Forissier             if( ssl->handshake == NULL )
487411fa71b9SJerome Forissier             {
487511fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping ChangeCipherSpec outside handshake" ) );
487611fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
487711fa71b9SJerome Forissier             }
487811fa71b9SJerome Forissier 
487911fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "received out-of-order ChangeCipherSpec - remember" ) );
488011fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_EARLY_MESSAGE );
488111fa71b9SJerome Forissier         }
488211fa71b9SJerome Forissier #endif
488311fa71b9SJerome Forissier     }
488411fa71b9SJerome Forissier 
488511fa71b9SJerome Forissier     if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT )
488611fa71b9SJerome Forissier     {
488711fa71b9SJerome Forissier         if( ssl->in_msglen != 2 )
488811fa71b9SJerome Forissier         {
488911fa71b9SJerome Forissier             /* Note: Standard allows for more than one 2 byte alert
489011fa71b9SJerome Forissier                to be packed in a single message, but Mbed TLS doesn't
489111fa71b9SJerome Forissier                currently support this. */
48927901324dSJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid alert message, len: %" MBEDTLS_PRINTF_SIZET,
489311fa71b9SJerome Forissier                            ssl->in_msglen ) );
489411fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INVALID_RECORD );
489511fa71b9SJerome Forissier         }
489611fa71b9SJerome Forissier 
48977901324dSJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 2, ( "got an alert message, type: [%u:%u]",
489811fa71b9SJerome Forissier                        ssl->in_msg[0], ssl->in_msg[1] ) );
489911fa71b9SJerome Forissier 
490011fa71b9SJerome Forissier         /*
490111fa71b9SJerome Forissier          * Ignore non-fatal alerts, except close_notify and no_renegotiation
490211fa71b9SJerome Forissier          */
490311fa71b9SJerome Forissier         if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_FATAL )
490411fa71b9SJerome Forissier         {
490511fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "is a fatal alert message (msg %d)",
490611fa71b9SJerome Forissier                            ssl->in_msg[1] ) );
490711fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE );
490811fa71b9SJerome Forissier         }
490911fa71b9SJerome Forissier 
491011fa71b9SJerome Forissier         if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING &&
491111fa71b9SJerome Forissier             ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY )
491211fa71b9SJerome Forissier         {
491311fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a close notify message" ) );
491411fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY );
491511fa71b9SJerome Forissier         }
491611fa71b9SJerome Forissier 
491711fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_RENEGOTIATION_ENABLED)
491811fa71b9SJerome Forissier         if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING &&
491911fa71b9SJerome Forissier             ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION )
492011fa71b9SJerome Forissier         {
492111fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no renegotiation alert" ) );
492211fa71b9SJerome Forissier             /* Will be handled when trying to parse ServerHello */
492311fa71b9SJerome Forissier             return( 0 );
492411fa71b9SJerome Forissier         }
492511fa71b9SJerome Forissier #endif
492611fa71b9SJerome Forissier 
492711fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_SRV_C)
492811fa71b9SJerome Forissier         if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 &&
492911fa71b9SJerome Forissier             ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
493011fa71b9SJerome Forissier             ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING &&
493111fa71b9SJerome Forissier             ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_CERT )
493211fa71b9SJerome Forissier         {
493311fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no_cert" ) );
493411fa71b9SJerome Forissier             /* Will be handled in mbedtls_ssl_parse_certificate() */
493511fa71b9SJerome Forissier             return( 0 );
493611fa71b9SJerome Forissier         }
493711fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */
493811fa71b9SJerome Forissier 
493911fa71b9SJerome Forissier         /* Silently ignore: fetch new message */
494011fa71b9SJerome Forissier         return MBEDTLS_ERR_SSL_NON_FATAL;
494111fa71b9SJerome Forissier     }
494211fa71b9SJerome Forissier 
494311fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
494411fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
494511fa71b9SJerome Forissier     {
494611fa71b9SJerome Forissier         /* Drop unexpected ApplicationData records,
494711fa71b9SJerome Forissier          * except at the beginning of renegotiations */
494811fa71b9SJerome Forissier         if( ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA &&
494911fa71b9SJerome Forissier             ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER
495011fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_RENEGOTIATION)
495111fa71b9SJerome Forissier             && ! ( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
495211fa71b9SJerome Forissier                    ssl->state == MBEDTLS_SSL_SERVER_HELLO )
495311fa71b9SJerome Forissier #endif
495411fa71b9SJerome Forissier             )
495511fa71b9SJerome Forissier         {
495611fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ApplicationData" ) );
495711fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_NON_FATAL );
495811fa71b9SJerome Forissier         }
495911fa71b9SJerome Forissier 
496011fa71b9SJerome Forissier         if( ssl->handshake != NULL &&
496111fa71b9SJerome Forissier             ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER  )
496211fa71b9SJerome Forissier         {
496311fa71b9SJerome Forissier             mbedtls_ssl_handshake_wrapup_free_hs_transform( ssl );
496411fa71b9SJerome Forissier         }
496511fa71b9SJerome Forissier     }
496611fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
496711fa71b9SJerome Forissier 
496811fa71b9SJerome Forissier     return( 0 );
496911fa71b9SJerome Forissier }
497011fa71b9SJerome Forissier 
497111fa71b9SJerome Forissier int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl )
497211fa71b9SJerome Forissier {
497311fa71b9SJerome Forissier     return( mbedtls_ssl_send_alert_message( ssl,
497411fa71b9SJerome Forissier                   MBEDTLS_SSL_ALERT_LEVEL_FATAL,
497511fa71b9SJerome Forissier                   MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ) );
497611fa71b9SJerome Forissier }
497711fa71b9SJerome Forissier 
497811fa71b9SJerome Forissier int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl,
497911fa71b9SJerome Forissier                             unsigned char level,
498011fa71b9SJerome Forissier                             unsigned char message )
498111fa71b9SJerome Forissier {
498211fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
498311fa71b9SJerome Forissier 
498411fa71b9SJerome Forissier     if( ssl == NULL || ssl->conf == NULL )
498511fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
498611fa71b9SJerome Forissier 
4987*039e02dfSJerome Forissier     if( ssl->out_left != 0 )
4988*039e02dfSJerome Forissier         return( mbedtls_ssl_flush_output( ssl ) );
4989*039e02dfSJerome Forissier 
499011fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> send alert message" ) );
499111fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 3, ( "send alert level=%u message=%u", level, message ));
499211fa71b9SJerome Forissier 
499311fa71b9SJerome Forissier     ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT;
499411fa71b9SJerome Forissier     ssl->out_msglen = 2;
499511fa71b9SJerome Forissier     ssl->out_msg[0] = level;
499611fa71b9SJerome Forissier     ssl->out_msg[1] = message;
499711fa71b9SJerome Forissier 
499811fa71b9SJerome Forissier     if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 )
499911fa71b9SJerome Forissier     {
500011fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
500111fa71b9SJerome Forissier         return( ret );
500211fa71b9SJerome Forissier     }
500311fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= send alert message" ) );
500411fa71b9SJerome Forissier 
500511fa71b9SJerome Forissier     return( 0 );
500611fa71b9SJerome Forissier }
500711fa71b9SJerome Forissier 
500811fa71b9SJerome Forissier int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl )
500911fa71b9SJerome Forissier {
501011fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
501111fa71b9SJerome Forissier 
501211fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write change cipher spec" ) );
501311fa71b9SJerome Forissier 
501411fa71b9SJerome Forissier     ssl->out_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC;
501511fa71b9SJerome Forissier     ssl->out_msglen  = 1;
501611fa71b9SJerome Forissier     ssl->out_msg[0]  = 1;
501711fa71b9SJerome Forissier 
501811fa71b9SJerome Forissier     ssl->state++;
501911fa71b9SJerome Forissier 
502011fa71b9SJerome Forissier     if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
502111fa71b9SJerome Forissier     {
502211fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
502311fa71b9SJerome Forissier         return( ret );
502411fa71b9SJerome Forissier     }
502511fa71b9SJerome Forissier 
502611fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write change cipher spec" ) );
502711fa71b9SJerome Forissier 
502811fa71b9SJerome Forissier     return( 0 );
502911fa71b9SJerome Forissier }
503011fa71b9SJerome Forissier 
503111fa71b9SJerome Forissier int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl )
503211fa71b9SJerome Forissier {
503311fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
503411fa71b9SJerome Forissier 
503511fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse change cipher spec" ) );
503611fa71b9SJerome Forissier 
503711fa71b9SJerome Forissier     if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
503811fa71b9SJerome Forissier     {
503911fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
504011fa71b9SJerome Forissier         return( ret );
504111fa71b9SJerome Forissier     }
504211fa71b9SJerome Forissier 
504311fa71b9SJerome Forissier     if( ssl->in_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC )
504411fa71b9SJerome Forissier     {
504511fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) );
504611fa71b9SJerome Forissier         mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
504711fa71b9SJerome Forissier                                         MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
504811fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
504911fa71b9SJerome Forissier     }
505011fa71b9SJerome Forissier 
505111fa71b9SJerome Forissier     /* CCS records are only accepted if they have length 1 and content '1',
505211fa71b9SJerome Forissier      * so we don't need to check this here. */
505311fa71b9SJerome Forissier 
505411fa71b9SJerome Forissier     /*
505511fa71b9SJerome Forissier      * Switch to our negotiated transform and session parameters for inbound
505611fa71b9SJerome Forissier      * data.
505711fa71b9SJerome Forissier      */
505811fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 3, ( "switching to new transform spec for inbound data" ) );
505911fa71b9SJerome Forissier     ssl->transform_in = ssl->transform_negotiate;
506011fa71b9SJerome Forissier     ssl->session_in = ssl->session_negotiate;
506111fa71b9SJerome Forissier 
506211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
506311fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
506411fa71b9SJerome Forissier     {
506511fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
506611fa71b9SJerome Forissier         mbedtls_ssl_dtls_replay_reset( ssl );
506711fa71b9SJerome Forissier #endif
506811fa71b9SJerome Forissier 
506911fa71b9SJerome Forissier         /* Increment epoch */
507011fa71b9SJerome Forissier         if( ++ssl->in_epoch == 0 )
507111fa71b9SJerome Forissier         {
507211fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS epoch would wrap" ) );
507311fa71b9SJerome Forissier             /* This is highly unlikely to happen for legitimate reasons, so
507411fa71b9SJerome Forissier                treat it as an attack and don't send an alert. */
507511fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING );
507611fa71b9SJerome Forissier         }
507711fa71b9SJerome Forissier     }
507811fa71b9SJerome Forissier     else
507911fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
508011fa71b9SJerome Forissier     memset( ssl->in_ctr, 0, 8 );
508111fa71b9SJerome Forissier 
508211fa71b9SJerome Forissier     mbedtls_ssl_update_in_pointers( ssl );
508311fa71b9SJerome Forissier 
508411fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
508511fa71b9SJerome Forissier     if( mbedtls_ssl_hw_record_activate != NULL )
508611fa71b9SJerome Forissier     {
508711fa71b9SJerome Forissier         if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_INBOUND ) ) != 0 )
508811fa71b9SJerome Forissier         {
508911fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret );
509011fa71b9SJerome Forissier             mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
509111fa71b9SJerome Forissier                                             MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
509211fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
509311fa71b9SJerome Forissier         }
509411fa71b9SJerome Forissier     }
509511fa71b9SJerome Forissier #endif
509611fa71b9SJerome Forissier 
509711fa71b9SJerome Forissier     ssl->state++;
509811fa71b9SJerome Forissier 
509911fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse change cipher spec" ) );
510011fa71b9SJerome Forissier 
510111fa71b9SJerome Forissier     return( 0 );
510211fa71b9SJerome Forissier }
510311fa71b9SJerome Forissier 
510411fa71b9SJerome Forissier /* Once ssl->out_hdr as the address of the beginning of the
510511fa71b9SJerome Forissier  * next outgoing record is set, deduce the other pointers.
510611fa71b9SJerome Forissier  *
510711fa71b9SJerome Forissier  * Note: For TLS, we save the implicit record sequence number
510811fa71b9SJerome Forissier  *       (entering MAC computation) in the 8 bytes before ssl->out_hdr,
510911fa71b9SJerome Forissier  *       and the caller has to make sure there's space for this.
511011fa71b9SJerome Forissier  */
511111fa71b9SJerome Forissier 
51127901324dSJerome Forissier static size_t ssl_transform_get_explicit_iv_len(
51137901324dSJerome Forissier                         mbedtls_ssl_transform const *transform )
51147901324dSJerome Forissier {
51157901324dSJerome Forissier     if( transform->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 )
51167901324dSJerome Forissier         return( 0 );
51177901324dSJerome Forissier 
51187901324dSJerome Forissier     return( transform->ivlen - transform->fixed_ivlen );
51197901324dSJerome Forissier }
51207901324dSJerome Forissier 
512111fa71b9SJerome Forissier void mbedtls_ssl_update_out_pointers( mbedtls_ssl_context *ssl,
512211fa71b9SJerome Forissier                                       mbedtls_ssl_transform *transform )
512311fa71b9SJerome Forissier {
512411fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
512511fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
512611fa71b9SJerome Forissier     {
512711fa71b9SJerome Forissier         ssl->out_ctr = ssl->out_hdr +  3;
512811fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
512911fa71b9SJerome Forissier         ssl->out_cid = ssl->out_ctr +  8;
513011fa71b9SJerome Forissier         ssl->out_len = ssl->out_cid;
513111fa71b9SJerome Forissier         if( transform != NULL )
513211fa71b9SJerome Forissier             ssl->out_len += transform->out_cid_len;
513311fa71b9SJerome Forissier #else /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
513411fa71b9SJerome Forissier         ssl->out_len = ssl->out_ctr + 8;
513511fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
513611fa71b9SJerome Forissier         ssl->out_iv  = ssl->out_len + 2;
513711fa71b9SJerome Forissier     }
513811fa71b9SJerome Forissier     else
513911fa71b9SJerome Forissier #endif
514011fa71b9SJerome Forissier     {
514111fa71b9SJerome Forissier         ssl->out_ctr = ssl->out_hdr - 8;
514211fa71b9SJerome Forissier         ssl->out_len = ssl->out_hdr + 3;
514311fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
514411fa71b9SJerome Forissier         ssl->out_cid = ssl->out_len;
514511fa71b9SJerome Forissier #endif
514611fa71b9SJerome Forissier         ssl->out_iv  = ssl->out_hdr + 5;
514711fa71b9SJerome Forissier     }
514811fa71b9SJerome Forissier 
514911fa71b9SJerome Forissier     ssl->out_msg = ssl->out_iv;
51507901324dSJerome Forissier     /* Adjust out_msg to make space for explicit IV, if used. */
51517901324dSJerome Forissier     if( transform != NULL )
51527901324dSJerome Forissier         ssl->out_msg += ssl_transform_get_explicit_iv_len( transform );
515311fa71b9SJerome Forissier }
515411fa71b9SJerome Forissier 
515511fa71b9SJerome Forissier /* Once ssl->in_hdr as the address of the beginning of the
515611fa71b9SJerome Forissier  * next incoming record is set, deduce the other pointers.
515711fa71b9SJerome Forissier  *
515811fa71b9SJerome Forissier  * Note: For TLS, we save the implicit record sequence number
515911fa71b9SJerome Forissier  *       (entering MAC computation) in the 8 bytes before ssl->in_hdr,
516011fa71b9SJerome Forissier  *       and the caller has to make sure there's space for this.
516111fa71b9SJerome Forissier  */
516211fa71b9SJerome Forissier 
516311fa71b9SJerome Forissier void mbedtls_ssl_update_in_pointers( mbedtls_ssl_context *ssl )
516411fa71b9SJerome Forissier {
516511fa71b9SJerome Forissier     /* This function sets the pointers to match the case
516611fa71b9SJerome Forissier      * of unprotected TLS/DTLS records, with both  ssl->in_iv
516711fa71b9SJerome Forissier      * and ssl->in_msg pointing to the beginning of the record
516811fa71b9SJerome Forissier      * content.
516911fa71b9SJerome Forissier      *
517011fa71b9SJerome Forissier      * When decrypting a protected record, ssl->in_msg
517111fa71b9SJerome Forissier      * will be shifted to point to the beginning of the
517211fa71b9SJerome Forissier      * record plaintext.
517311fa71b9SJerome Forissier      */
517411fa71b9SJerome Forissier 
517511fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
517611fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
517711fa71b9SJerome Forissier     {
517811fa71b9SJerome Forissier         /* This sets the header pointers to match records
517911fa71b9SJerome Forissier          * without CID. When we receive a record containing
518011fa71b9SJerome Forissier          * a CID, the fields are shifted accordingly in
518111fa71b9SJerome Forissier          * ssl_parse_record_header(). */
518211fa71b9SJerome Forissier         ssl->in_ctr = ssl->in_hdr +  3;
518311fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
518411fa71b9SJerome Forissier         ssl->in_cid = ssl->in_ctr +  8;
518511fa71b9SJerome Forissier         ssl->in_len = ssl->in_cid; /* Default: no CID */
518611fa71b9SJerome Forissier #else /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
518711fa71b9SJerome Forissier         ssl->in_len = ssl->in_ctr + 8;
518811fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
518911fa71b9SJerome Forissier         ssl->in_iv  = ssl->in_len + 2;
519011fa71b9SJerome Forissier     }
519111fa71b9SJerome Forissier     else
519211fa71b9SJerome Forissier #endif
519311fa71b9SJerome Forissier     {
519411fa71b9SJerome Forissier         ssl->in_ctr = ssl->in_hdr - 8;
519511fa71b9SJerome Forissier         ssl->in_len = ssl->in_hdr + 3;
519611fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
519711fa71b9SJerome Forissier         ssl->in_cid = ssl->in_len;
519811fa71b9SJerome Forissier #endif
519911fa71b9SJerome Forissier         ssl->in_iv  = ssl->in_hdr + 5;
520011fa71b9SJerome Forissier     }
520111fa71b9SJerome Forissier 
520211fa71b9SJerome Forissier     /* This will be adjusted at record decryption time. */
520311fa71b9SJerome Forissier     ssl->in_msg = ssl->in_iv;
520411fa71b9SJerome Forissier }
520511fa71b9SJerome Forissier 
520611fa71b9SJerome Forissier /*
520711fa71b9SJerome Forissier  * Setup an SSL context
520811fa71b9SJerome Forissier  */
520911fa71b9SJerome Forissier 
521011fa71b9SJerome Forissier void mbedtls_ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl )
521111fa71b9SJerome Forissier {
521211fa71b9SJerome Forissier     /* Set the incoming and outgoing record pointers. */
521311fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
521411fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
521511fa71b9SJerome Forissier     {
521611fa71b9SJerome Forissier         ssl->out_hdr = ssl->out_buf;
521711fa71b9SJerome Forissier         ssl->in_hdr  = ssl->in_buf;
521811fa71b9SJerome Forissier     }
521911fa71b9SJerome Forissier     else
522011fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
522111fa71b9SJerome Forissier     {
522211fa71b9SJerome Forissier         ssl->out_hdr = ssl->out_buf + 8;
522311fa71b9SJerome Forissier         ssl->in_hdr  = ssl->in_buf  + 8;
522411fa71b9SJerome Forissier     }
522511fa71b9SJerome Forissier 
522611fa71b9SJerome Forissier     /* Derive other internal pointers. */
522711fa71b9SJerome Forissier     mbedtls_ssl_update_out_pointers( ssl, NULL /* no transform enabled */ );
522811fa71b9SJerome Forissier     mbedtls_ssl_update_in_pointers ( ssl );
522911fa71b9SJerome Forissier }
523011fa71b9SJerome Forissier 
523111fa71b9SJerome Forissier /*
523211fa71b9SJerome Forissier  * SSL get accessors
523311fa71b9SJerome Forissier  */
523411fa71b9SJerome Forissier size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl )
523511fa71b9SJerome Forissier {
523611fa71b9SJerome Forissier     return( ssl->in_offt == NULL ? 0 : ssl->in_msglen );
523711fa71b9SJerome Forissier }
523811fa71b9SJerome Forissier 
523911fa71b9SJerome Forissier int mbedtls_ssl_check_pending( const mbedtls_ssl_context *ssl )
524011fa71b9SJerome Forissier {
524111fa71b9SJerome Forissier     /*
524211fa71b9SJerome Forissier      * Case A: We're currently holding back
524311fa71b9SJerome Forissier      * a message for further processing.
524411fa71b9SJerome Forissier      */
524511fa71b9SJerome Forissier 
524611fa71b9SJerome Forissier     if( ssl->keep_current_message == 1 )
524711fa71b9SJerome Forissier     {
524811fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: record held back for processing" ) );
524911fa71b9SJerome Forissier         return( 1 );
525011fa71b9SJerome Forissier     }
525111fa71b9SJerome Forissier 
525211fa71b9SJerome Forissier     /*
525311fa71b9SJerome Forissier      * Case B: Further records are pending in the current datagram.
525411fa71b9SJerome Forissier      */
525511fa71b9SJerome Forissier 
525611fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
525711fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
525811fa71b9SJerome Forissier         ssl->in_left > ssl->next_record_offset )
525911fa71b9SJerome Forissier     {
526011fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: more records within current datagram" ) );
526111fa71b9SJerome Forissier         return( 1 );
526211fa71b9SJerome Forissier     }
526311fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
526411fa71b9SJerome Forissier 
526511fa71b9SJerome Forissier     /*
526611fa71b9SJerome Forissier      * Case C: A handshake message is being processed.
526711fa71b9SJerome Forissier      */
526811fa71b9SJerome Forissier 
526911fa71b9SJerome Forissier     if( ssl->in_hslen > 0 && ssl->in_hslen < ssl->in_msglen )
527011fa71b9SJerome Forissier     {
527111fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: more handshake messages within current record" ) );
527211fa71b9SJerome Forissier         return( 1 );
527311fa71b9SJerome Forissier     }
527411fa71b9SJerome Forissier 
527511fa71b9SJerome Forissier     /*
527611fa71b9SJerome Forissier      * Case D: An application data message is being processed
527711fa71b9SJerome Forissier      */
527811fa71b9SJerome Forissier     if( ssl->in_offt != NULL )
527911fa71b9SJerome Forissier     {
528011fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: application data record is being processed" ) );
528111fa71b9SJerome Forissier         return( 1 );
528211fa71b9SJerome Forissier     }
528311fa71b9SJerome Forissier 
528411fa71b9SJerome Forissier     /*
528511fa71b9SJerome Forissier      * In all other cases, the rest of the message can be dropped.
528611fa71b9SJerome Forissier      * As in ssl_get_next_record, this needs to be adapted if
528711fa71b9SJerome Forissier      * we implement support for multiple alerts in single records.
528811fa71b9SJerome Forissier      */
528911fa71b9SJerome Forissier 
529011fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: nothing pending" ) );
529111fa71b9SJerome Forissier     return( 0 );
529211fa71b9SJerome Forissier }
529311fa71b9SJerome Forissier 
529411fa71b9SJerome Forissier 
529511fa71b9SJerome Forissier int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl )
529611fa71b9SJerome Forissier {
529711fa71b9SJerome Forissier     size_t transform_expansion = 0;
529811fa71b9SJerome Forissier     const mbedtls_ssl_transform *transform = ssl->transform_out;
529911fa71b9SJerome Forissier     unsigned block_size;
530011fa71b9SJerome Forissier 
530111fa71b9SJerome Forissier     size_t out_hdr_len = mbedtls_ssl_out_hdr_len( ssl );
530211fa71b9SJerome Forissier 
530311fa71b9SJerome Forissier     if( transform == NULL )
530411fa71b9SJerome Forissier         return( (int) out_hdr_len );
530511fa71b9SJerome Forissier 
530611fa71b9SJerome Forissier #if defined(MBEDTLS_ZLIB_SUPPORT)
530711fa71b9SJerome Forissier     if( ssl->session_out->compression != MBEDTLS_SSL_COMPRESS_NULL )
530811fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
530911fa71b9SJerome Forissier #endif
531011fa71b9SJerome Forissier 
531111fa71b9SJerome Forissier     switch( mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc ) )
531211fa71b9SJerome Forissier     {
531311fa71b9SJerome Forissier         case MBEDTLS_MODE_GCM:
531411fa71b9SJerome Forissier         case MBEDTLS_MODE_CCM:
531511fa71b9SJerome Forissier         case MBEDTLS_MODE_CHACHAPOLY:
531611fa71b9SJerome Forissier         case MBEDTLS_MODE_STREAM:
531711fa71b9SJerome Forissier             transform_expansion = transform->minlen;
531811fa71b9SJerome Forissier             break;
531911fa71b9SJerome Forissier 
532011fa71b9SJerome Forissier         case MBEDTLS_MODE_CBC:
532111fa71b9SJerome Forissier 
532211fa71b9SJerome Forissier             block_size = mbedtls_cipher_get_block_size(
532311fa71b9SJerome Forissier                 &transform->cipher_ctx_enc );
532411fa71b9SJerome Forissier 
532511fa71b9SJerome Forissier             /* Expansion due to the addition of the MAC. */
532611fa71b9SJerome Forissier             transform_expansion += transform->maclen;
532711fa71b9SJerome Forissier 
532811fa71b9SJerome Forissier             /* Expansion due to the addition of CBC padding;
532911fa71b9SJerome Forissier              * Theoretically up to 256 bytes, but we never use
533011fa71b9SJerome Forissier              * more than the block size of the underlying cipher. */
533111fa71b9SJerome Forissier             transform_expansion += block_size;
533211fa71b9SJerome Forissier 
533311fa71b9SJerome Forissier             /* For TLS 1.1 or higher, an explicit IV is added
533411fa71b9SJerome Forissier              * after the record header. */
533511fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)
533611fa71b9SJerome Forissier             if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
533711fa71b9SJerome Forissier                 transform_expansion += block_size;
533811fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */
533911fa71b9SJerome Forissier 
534011fa71b9SJerome Forissier             break;
534111fa71b9SJerome Forissier 
534211fa71b9SJerome Forissier         default:
534311fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
534411fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
534511fa71b9SJerome Forissier     }
534611fa71b9SJerome Forissier 
534711fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
534811fa71b9SJerome Forissier     if( transform->out_cid_len != 0 )
534911fa71b9SJerome Forissier         transform_expansion += MBEDTLS_SSL_MAX_CID_EXPANSION;
535011fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
535111fa71b9SJerome Forissier 
535211fa71b9SJerome Forissier     return( (int)( out_hdr_len + transform_expansion ) );
535311fa71b9SJerome Forissier }
535411fa71b9SJerome Forissier 
535511fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_RENEGOTIATION)
535611fa71b9SJerome Forissier /*
535711fa71b9SJerome Forissier  * Check record counters and renegotiate if they're above the limit.
535811fa71b9SJerome Forissier  */
5359*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
536011fa71b9SJerome Forissier static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl )
536111fa71b9SJerome Forissier {
536211fa71b9SJerome Forissier     size_t ep_len = mbedtls_ssl_ep_len( ssl );
536311fa71b9SJerome Forissier     int in_ctr_cmp;
536411fa71b9SJerome Forissier     int out_ctr_cmp;
536511fa71b9SJerome Forissier 
536611fa71b9SJerome Forissier     if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ||
536711fa71b9SJerome Forissier         ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ||
536811fa71b9SJerome Forissier         ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED )
536911fa71b9SJerome Forissier     {
537011fa71b9SJerome Forissier         return( 0 );
537111fa71b9SJerome Forissier     }
537211fa71b9SJerome Forissier 
537311fa71b9SJerome Forissier     in_ctr_cmp = memcmp( ssl->in_ctr + ep_len,
537411fa71b9SJerome Forissier                         ssl->conf->renego_period + ep_len, 8 - ep_len );
537511fa71b9SJerome Forissier     out_ctr_cmp = memcmp( ssl->cur_out_ctr + ep_len,
537611fa71b9SJerome Forissier                           ssl->conf->renego_period + ep_len, 8 - ep_len );
537711fa71b9SJerome Forissier 
537811fa71b9SJerome Forissier     if( in_ctr_cmp <= 0 && out_ctr_cmp <= 0 )
537911fa71b9SJerome Forissier     {
538011fa71b9SJerome Forissier         return( 0 );
538111fa71b9SJerome Forissier     }
538211fa71b9SJerome Forissier 
538311fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 1, ( "record counter limit reached: renegotiate" ) );
538411fa71b9SJerome Forissier     return( mbedtls_ssl_renegotiate( ssl ) );
538511fa71b9SJerome Forissier }
538611fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_RENEGOTIATION */
538711fa71b9SJerome Forissier 
538811fa71b9SJerome Forissier /*
538911fa71b9SJerome Forissier  * Receive application data decrypted from the SSL layer
539011fa71b9SJerome Forissier  */
539111fa71b9SJerome Forissier int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
539211fa71b9SJerome Forissier {
539311fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
539411fa71b9SJerome Forissier     size_t n;
539511fa71b9SJerome Forissier 
539611fa71b9SJerome Forissier     if( ssl == NULL || ssl->conf == NULL )
539711fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
539811fa71b9SJerome Forissier 
539911fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read" ) );
540011fa71b9SJerome Forissier 
540111fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
540211fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
540311fa71b9SJerome Forissier     {
540411fa71b9SJerome Forissier         if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
540511fa71b9SJerome Forissier             return( ret );
540611fa71b9SJerome Forissier 
540711fa71b9SJerome Forissier         if( ssl->handshake != NULL &&
540811fa71b9SJerome Forissier             ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING )
540911fa71b9SJerome Forissier         {
541011fa71b9SJerome Forissier             if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
541111fa71b9SJerome Forissier                 return( ret );
541211fa71b9SJerome Forissier         }
541311fa71b9SJerome Forissier     }
541411fa71b9SJerome Forissier #endif
541511fa71b9SJerome Forissier 
541611fa71b9SJerome Forissier     /*
541711fa71b9SJerome Forissier      * Check if renegotiation is necessary and/or handshake is
541811fa71b9SJerome Forissier      * in process. If yes, perform/continue, and fall through
541911fa71b9SJerome Forissier      * if an unexpected packet is received while the client
542011fa71b9SJerome Forissier      * is waiting for the ServerHello.
542111fa71b9SJerome Forissier      *
542211fa71b9SJerome Forissier      * (There is no equivalent to the last condition on
542311fa71b9SJerome Forissier      *  the server-side as it is not treated as within
542411fa71b9SJerome Forissier      *  a handshake while waiting for the ClientHello
542511fa71b9SJerome Forissier      *  after a renegotiation request.)
542611fa71b9SJerome Forissier      */
542711fa71b9SJerome Forissier 
542811fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_RENEGOTIATION)
542911fa71b9SJerome Forissier     ret = ssl_check_ctr_renegotiate( ssl );
543011fa71b9SJerome Forissier     if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO &&
543111fa71b9SJerome Forissier         ret != 0 )
543211fa71b9SJerome Forissier     {
543311fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret );
543411fa71b9SJerome Forissier         return( ret );
543511fa71b9SJerome Forissier     }
543611fa71b9SJerome Forissier #endif
543711fa71b9SJerome Forissier 
543811fa71b9SJerome Forissier     if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
543911fa71b9SJerome Forissier     {
544011fa71b9SJerome Forissier         ret = mbedtls_ssl_handshake( ssl );
544111fa71b9SJerome Forissier         if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO &&
544211fa71b9SJerome Forissier             ret != 0 )
544311fa71b9SJerome Forissier         {
544411fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret );
544511fa71b9SJerome Forissier             return( ret );
544611fa71b9SJerome Forissier         }
544711fa71b9SJerome Forissier     }
544811fa71b9SJerome Forissier 
544911fa71b9SJerome Forissier     /* Loop as long as no application data record is available */
545011fa71b9SJerome Forissier     while( ssl->in_offt == NULL )
545111fa71b9SJerome Forissier     {
545211fa71b9SJerome Forissier         /* Start timer if not already running */
545311fa71b9SJerome Forissier         if( ssl->f_get_timer != NULL &&
545411fa71b9SJerome Forissier             ssl->f_get_timer( ssl->p_timer ) == -1 )
545511fa71b9SJerome Forissier         {
545611fa71b9SJerome Forissier             mbedtls_ssl_set_timer( ssl, ssl->conf->read_timeout );
545711fa71b9SJerome Forissier         }
545811fa71b9SJerome Forissier 
545911fa71b9SJerome Forissier         if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
546011fa71b9SJerome Forissier         {
546111fa71b9SJerome Forissier             if( ret == MBEDTLS_ERR_SSL_CONN_EOF )
546211fa71b9SJerome Forissier                 return( 0 );
546311fa71b9SJerome Forissier 
546411fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
546511fa71b9SJerome Forissier             return( ret );
546611fa71b9SJerome Forissier         }
546711fa71b9SJerome Forissier 
546811fa71b9SJerome Forissier         if( ssl->in_msglen  == 0 &&
546911fa71b9SJerome Forissier             ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA )
547011fa71b9SJerome Forissier         {
547111fa71b9SJerome Forissier             /*
547211fa71b9SJerome Forissier              * OpenSSL sends empty messages to randomize the IV
547311fa71b9SJerome Forissier              */
547411fa71b9SJerome Forissier             if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
547511fa71b9SJerome Forissier             {
547611fa71b9SJerome Forissier                 if( ret == MBEDTLS_ERR_SSL_CONN_EOF )
547711fa71b9SJerome Forissier                     return( 0 );
547811fa71b9SJerome Forissier 
547911fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
548011fa71b9SJerome Forissier                 return( ret );
548111fa71b9SJerome Forissier             }
548211fa71b9SJerome Forissier         }
548311fa71b9SJerome Forissier 
548411fa71b9SJerome Forissier         if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE )
548511fa71b9SJerome Forissier         {
548611fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "received handshake message" ) );
548711fa71b9SJerome Forissier 
548811fa71b9SJerome Forissier             /*
548911fa71b9SJerome Forissier              * - For client-side, expect SERVER_HELLO_REQUEST.
549011fa71b9SJerome Forissier              * - For server-side, expect CLIENT_HELLO.
549111fa71b9SJerome Forissier              * - Fail (TLS) or silently drop record (DTLS) in other cases.
549211fa71b9SJerome Forissier              */
549311fa71b9SJerome Forissier 
549411fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_CLI_C)
549511fa71b9SJerome Forissier             if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
549611fa71b9SJerome Forissier                 ( ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_REQUEST ||
549711fa71b9SJerome Forissier                   ssl->in_hslen  != mbedtls_ssl_hs_hdr_len( ssl ) ) )
549811fa71b9SJerome Forissier             {
549911fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not HelloRequest)" ) );
550011fa71b9SJerome Forissier 
550111fa71b9SJerome Forissier                 /* With DTLS, drop the packet (probably from last handshake) */
550211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
550311fa71b9SJerome Forissier                 if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
550411fa71b9SJerome Forissier                 {
550511fa71b9SJerome Forissier                     continue;
550611fa71b9SJerome Forissier                 }
550711fa71b9SJerome Forissier #endif
550811fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
550911fa71b9SJerome Forissier             }
551011fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_CLI_C */
551111fa71b9SJerome Forissier 
551211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_SRV_C)
551311fa71b9SJerome Forissier             if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
551411fa71b9SJerome Forissier                 ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO )
551511fa71b9SJerome Forissier             {
551611fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not ClientHello)" ) );
551711fa71b9SJerome Forissier 
551811fa71b9SJerome Forissier                 /* With DTLS, drop the packet (probably from last handshake) */
551911fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
552011fa71b9SJerome Forissier                 if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
552111fa71b9SJerome Forissier                 {
552211fa71b9SJerome Forissier                     continue;
552311fa71b9SJerome Forissier                 }
552411fa71b9SJerome Forissier #endif
552511fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
552611fa71b9SJerome Forissier             }
552711fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_SRV_C */
552811fa71b9SJerome Forissier 
552911fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_RENEGOTIATION)
553011fa71b9SJerome Forissier             /* Determine whether renegotiation attempt should be accepted */
553111fa71b9SJerome Forissier             if( ! ( ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED ||
553211fa71b9SJerome Forissier                     ( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
553311fa71b9SJerome Forissier                       ssl->conf->allow_legacy_renegotiation ==
553411fa71b9SJerome Forissier                                                    MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) ) )
553511fa71b9SJerome Forissier             {
553611fa71b9SJerome Forissier                 /*
553711fa71b9SJerome Forissier                  * Accept renegotiation request
553811fa71b9SJerome Forissier                  */
553911fa71b9SJerome Forissier 
554011fa71b9SJerome Forissier                 /* DTLS clients need to know renego is server-initiated */
554111fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
554211fa71b9SJerome Forissier                 if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
554311fa71b9SJerome Forissier                     ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
554411fa71b9SJerome Forissier                 {
554511fa71b9SJerome Forissier                     ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING;
554611fa71b9SJerome Forissier                 }
554711fa71b9SJerome Forissier #endif
554811fa71b9SJerome Forissier                 ret = mbedtls_ssl_start_renegotiation( ssl );
554911fa71b9SJerome Forissier                 if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO &&
555011fa71b9SJerome Forissier                     ret != 0 )
555111fa71b9SJerome Forissier                 {
555211fa71b9SJerome Forissier                     MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_start_renegotiation",
555311fa71b9SJerome Forissier                                            ret );
555411fa71b9SJerome Forissier                     return( ret );
555511fa71b9SJerome Forissier                 }
555611fa71b9SJerome Forissier             }
555711fa71b9SJerome Forissier             else
555811fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_RENEGOTIATION */
555911fa71b9SJerome Forissier             {
556011fa71b9SJerome Forissier                 /*
556111fa71b9SJerome Forissier                  * Refuse renegotiation
556211fa71b9SJerome Forissier                  */
556311fa71b9SJerome Forissier 
556411fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 3, ( "refusing renegotiation, sending alert" ) );
556511fa71b9SJerome Forissier 
556611fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_SSL3)
556711fa71b9SJerome Forissier                 if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
556811fa71b9SJerome Forissier                 {
556911fa71b9SJerome Forissier                     /* SSLv3 does not have a "no_renegotiation" warning, so
557011fa71b9SJerome Forissier                        we send a fatal alert and abort the connection. */
557111fa71b9SJerome Forissier                     mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
557211fa71b9SJerome Forissier                                                     MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
557311fa71b9SJerome Forissier                     return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
557411fa71b9SJerome Forissier                 }
557511fa71b9SJerome Forissier                 else
557611fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_SSL3 */
557711fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
557811fa71b9SJerome Forissier     defined(MBEDTLS_SSL_PROTO_TLS1_2)
557911fa71b9SJerome Forissier                 if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 )
558011fa71b9SJerome Forissier                 {
558111fa71b9SJerome Forissier                     if( ( ret = mbedtls_ssl_send_alert_message( ssl,
558211fa71b9SJerome Forissier                                     MBEDTLS_SSL_ALERT_LEVEL_WARNING,
558311fa71b9SJerome Forissier                                     MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION ) ) != 0 )
558411fa71b9SJerome Forissier                     {
558511fa71b9SJerome Forissier                         return( ret );
558611fa71b9SJerome Forissier                     }
558711fa71b9SJerome Forissier                 }
558811fa71b9SJerome Forissier                 else
558911fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 ||
559011fa71b9SJerome Forissier           MBEDTLS_SSL_PROTO_TLS1_2 */
559111fa71b9SJerome Forissier                 {
559211fa71b9SJerome Forissier                     MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
559311fa71b9SJerome Forissier                     return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
559411fa71b9SJerome Forissier                 }
559511fa71b9SJerome Forissier             }
559611fa71b9SJerome Forissier 
559711fa71b9SJerome Forissier             /* At this point, we don't know whether the renegotiation has been
559811fa71b9SJerome Forissier              * completed or not. The cases to consider are the following:
559911fa71b9SJerome Forissier              * 1) The renegotiation is complete. In this case, no new record
560011fa71b9SJerome Forissier              *    has been read yet.
560111fa71b9SJerome Forissier              * 2) The renegotiation is incomplete because the client received
560211fa71b9SJerome Forissier              *    an application data record while awaiting the ServerHello.
560311fa71b9SJerome Forissier              * 3) The renegotiation is incomplete because the client received
560411fa71b9SJerome Forissier              *    a non-handshake, non-application data message while awaiting
560511fa71b9SJerome Forissier              *    the ServerHello.
560611fa71b9SJerome Forissier              * In each of these case, looping will be the proper action:
560711fa71b9SJerome Forissier              * - For 1), the next iteration will read a new record and check
560811fa71b9SJerome Forissier              *   if it's application data.
560911fa71b9SJerome Forissier              * - For 2), the loop condition isn't satisfied as application data
561011fa71b9SJerome Forissier              *   is present, hence continue is the same as break
561111fa71b9SJerome Forissier              * - For 3), the loop condition is satisfied and read_record
561211fa71b9SJerome Forissier              *   will re-deliver the message that was held back by the client
561311fa71b9SJerome Forissier              *   when expecting the ServerHello.
561411fa71b9SJerome Forissier              */
561511fa71b9SJerome Forissier             continue;
561611fa71b9SJerome Forissier         }
561711fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_RENEGOTIATION)
561811fa71b9SJerome Forissier         else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING )
561911fa71b9SJerome Forissier         {
562011fa71b9SJerome Forissier             if( ssl->conf->renego_max_records >= 0 )
562111fa71b9SJerome Forissier             {
562211fa71b9SJerome Forissier                 if( ++ssl->renego_records_seen > ssl->conf->renego_max_records )
562311fa71b9SJerome Forissier                 {
562411fa71b9SJerome Forissier                     MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation requested, "
562511fa71b9SJerome Forissier                                         "but not honored by client" ) );
562611fa71b9SJerome Forissier                     return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
562711fa71b9SJerome Forissier                 }
562811fa71b9SJerome Forissier             }
562911fa71b9SJerome Forissier         }
563011fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_RENEGOTIATION */
563111fa71b9SJerome Forissier 
563211fa71b9SJerome Forissier         /* Fatal and closure alerts handled by mbedtls_ssl_read_record() */
563311fa71b9SJerome Forissier         if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT )
563411fa71b9SJerome Forissier         {
563511fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 2, ( "ignoring non-fatal non-closure alert" ) );
563611fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_WANT_READ );
563711fa71b9SJerome Forissier         }
563811fa71b9SJerome Forissier 
563911fa71b9SJerome Forissier         if( ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA )
564011fa71b9SJerome Forissier         {
564111fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad application data message" ) );
564211fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
564311fa71b9SJerome Forissier         }
564411fa71b9SJerome Forissier 
564511fa71b9SJerome Forissier         ssl->in_offt = ssl->in_msg;
564611fa71b9SJerome Forissier 
564711fa71b9SJerome Forissier         /* We're going to return something now, cancel timer,
564811fa71b9SJerome Forissier          * except if handshake (renegotiation) is in progress */
564911fa71b9SJerome Forissier         if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
565011fa71b9SJerome Forissier             mbedtls_ssl_set_timer( ssl, 0 );
565111fa71b9SJerome Forissier 
565211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
565311fa71b9SJerome Forissier         /* If we requested renego but received AppData, resend HelloRequest.
565411fa71b9SJerome Forissier          * Do it now, after setting in_offt, to avoid taking this branch
565511fa71b9SJerome Forissier          * again if ssl_write_hello_request() returns WANT_WRITE */
565611fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION)
565711fa71b9SJerome Forissier         if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
565811fa71b9SJerome Forissier             ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING )
565911fa71b9SJerome Forissier         {
566011fa71b9SJerome Forissier             if( ( ret = mbedtls_ssl_resend_hello_request( ssl ) ) != 0 )
566111fa71b9SJerome Forissier             {
566211fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend_hello_request",
566311fa71b9SJerome Forissier                                        ret );
566411fa71b9SJerome Forissier                 return( ret );
566511fa71b9SJerome Forissier             }
566611fa71b9SJerome Forissier         }
566711fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */
566811fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
566911fa71b9SJerome Forissier     }
567011fa71b9SJerome Forissier 
567111fa71b9SJerome Forissier     n = ( len < ssl->in_msglen )
567211fa71b9SJerome Forissier         ? len : ssl->in_msglen;
567311fa71b9SJerome Forissier 
567411fa71b9SJerome Forissier     memcpy( buf, ssl->in_offt, n );
567511fa71b9SJerome Forissier     ssl->in_msglen -= n;
567611fa71b9SJerome Forissier 
56777901324dSJerome Forissier     /* Zeroising the plaintext buffer to erase unused application data
56787901324dSJerome Forissier        from the memory. */
56797901324dSJerome Forissier     mbedtls_platform_zeroize( ssl->in_offt, n );
56807901324dSJerome Forissier 
568111fa71b9SJerome Forissier     if( ssl->in_msglen == 0 )
568211fa71b9SJerome Forissier     {
568311fa71b9SJerome Forissier         /* all bytes consumed */
568411fa71b9SJerome Forissier         ssl->in_offt = NULL;
568511fa71b9SJerome Forissier         ssl->keep_current_message = 0;
568611fa71b9SJerome Forissier     }
568711fa71b9SJerome Forissier     else
568811fa71b9SJerome Forissier     {
568911fa71b9SJerome Forissier         /* more data available */
569011fa71b9SJerome Forissier         ssl->in_offt += n;
569111fa71b9SJerome Forissier     }
569211fa71b9SJerome Forissier 
569311fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read" ) );
569411fa71b9SJerome Forissier 
569511fa71b9SJerome Forissier     return( (int) n );
569611fa71b9SJerome Forissier }
569711fa71b9SJerome Forissier 
569811fa71b9SJerome Forissier /*
569911fa71b9SJerome Forissier  * Send application data to be encrypted by the SSL layer, taking care of max
570011fa71b9SJerome Forissier  * fragment length and buffer size.
570111fa71b9SJerome Forissier  *
570211fa71b9SJerome Forissier  * According to RFC 5246 Section 6.2.1:
570311fa71b9SJerome Forissier  *
570411fa71b9SJerome Forissier  *      Zero-length fragments of Application data MAY be sent as they are
570511fa71b9SJerome Forissier  *      potentially useful as a traffic analysis countermeasure.
570611fa71b9SJerome Forissier  *
570711fa71b9SJerome Forissier  * Therefore, it is possible that the input message length is 0 and the
570811fa71b9SJerome Forissier  * corresponding return code is 0 on success.
570911fa71b9SJerome Forissier  */
5710*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
571111fa71b9SJerome Forissier static int ssl_write_real( mbedtls_ssl_context *ssl,
571211fa71b9SJerome Forissier                            const unsigned char *buf, size_t len )
571311fa71b9SJerome Forissier {
571411fa71b9SJerome Forissier     int ret = mbedtls_ssl_get_max_out_record_payload( ssl );
571511fa71b9SJerome Forissier     const size_t max_len = (size_t) ret;
571611fa71b9SJerome Forissier 
571711fa71b9SJerome Forissier     if( ret < 0 )
571811fa71b9SJerome Forissier     {
571911fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_get_max_out_record_payload", ret );
572011fa71b9SJerome Forissier         return( ret );
572111fa71b9SJerome Forissier     }
572211fa71b9SJerome Forissier 
572311fa71b9SJerome Forissier     if( len > max_len )
572411fa71b9SJerome Forissier     {
572511fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
572611fa71b9SJerome Forissier         if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
572711fa71b9SJerome Forissier         {
572811fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "fragment larger than the (negotiated) "
57297901324dSJerome Forissier                                 "maximum fragment length: %" MBEDTLS_PRINTF_SIZET
57307901324dSJerome Forissier                                 " > %" MBEDTLS_PRINTF_SIZET,
573111fa71b9SJerome Forissier                                 len, max_len ) );
573211fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
573311fa71b9SJerome Forissier         }
573411fa71b9SJerome Forissier         else
573511fa71b9SJerome Forissier #endif
573611fa71b9SJerome Forissier             len = max_len;
573711fa71b9SJerome Forissier     }
573811fa71b9SJerome Forissier 
573911fa71b9SJerome Forissier     if( ssl->out_left != 0 )
574011fa71b9SJerome Forissier     {
574111fa71b9SJerome Forissier         /*
574211fa71b9SJerome Forissier          * The user has previously tried to send the data and
574311fa71b9SJerome Forissier          * MBEDTLS_ERR_SSL_WANT_WRITE or the message was only partially
574411fa71b9SJerome Forissier          * written. In this case, we expect the high-level write function
574511fa71b9SJerome Forissier          * (e.g. mbedtls_ssl_write()) to be called with the same parameters
574611fa71b9SJerome Forissier          */
574711fa71b9SJerome Forissier         if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
574811fa71b9SJerome Forissier         {
574911fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret );
575011fa71b9SJerome Forissier             return( ret );
575111fa71b9SJerome Forissier         }
575211fa71b9SJerome Forissier     }
575311fa71b9SJerome Forissier     else
575411fa71b9SJerome Forissier     {
575511fa71b9SJerome Forissier         /*
575611fa71b9SJerome Forissier          * The user is trying to send a message the first time, so we need to
575711fa71b9SJerome Forissier          * copy the data into the internal buffers and setup the data structure
575811fa71b9SJerome Forissier          * to keep track of partial writes
575911fa71b9SJerome Forissier          */
576011fa71b9SJerome Forissier         ssl->out_msglen  = len;
576111fa71b9SJerome Forissier         ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA;
576211fa71b9SJerome Forissier         memcpy( ssl->out_msg, buf, len );
576311fa71b9SJerome Forissier 
576411fa71b9SJerome Forissier         if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 )
576511fa71b9SJerome Forissier         {
576611fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
576711fa71b9SJerome Forissier             return( ret );
576811fa71b9SJerome Forissier         }
576911fa71b9SJerome Forissier     }
577011fa71b9SJerome Forissier 
577111fa71b9SJerome Forissier     return( (int) len );
577211fa71b9SJerome Forissier }
577311fa71b9SJerome Forissier 
577411fa71b9SJerome Forissier /*
577511fa71b9SJerome Forissier  * Write application data, doing 1/n-1 splitting if necessary.
577611fa71b9SJerome Forissier  *
577711fa71b9SJerome Forissier  * With non-blocking I/O, ssl_write_real() may return WANT_WRITE,
577811fa71b9SJerome Forissier  * then the caller will call us again with the same arguments, so
577911fa71b9SJerome Forissier  * remember whether we already did the split or not.
578011fa71b9SJerome Forissier  */
578111fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING)
5782*039e02dfSJerome Forissier MBEDTLS_CHECK_RETURN_CRITICAL
578311fa71b9SJerome Forissier static int ssl_write_split( mbedtls_ssl_context *ssl,
578411fa71b9SJerome Forissier                             const unsigned char *buf, size_t len )
578511fa71b9SJerome Forissier {
578611fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
578711fa71b9SJerome Forissier 
578811fa71b9SJerome Forissier     if( ssl->conf->cbc_record_splitting ==
578911fa71b9SJerome Forissier             MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED ||
579011fa71b9SJerome Forissier         len <= 1 ||
579111fa71b9SJerome Forissier         ssl->minor_ver > MBEDTLS_SSL_MINOR_VERSION_1 ||
579211fa71b9SJerome Forissier         mbedtls_cipher_get_cipher_mode( &ssl->transform_out->cipher_ctx_enc )
579311fa71b9SJerome Forissier                                 != MBEDTLS_MODE_CBC )
579411fa71b9SJerome Forissier     {
579511fa71b9SJerome Forissier         return( ssl_write_real( ssl, buf, len ) );
579611fa71b9SJerome Forissier     }
579711fa71b9SJerome Forissier 
579811fa71b9SJerome Forissier     if( ssl->split_done == 0 )
579911fa71b9SJerome Forissier     {
580011fa71b9SJerome Forissier         if( ( ret = ssl_write_real( ssl, buf, 1 ) ) <= 0 )
580111fa71b9SJerome Forissier             return( ret );
580211fa71b9SJerome Forissier         ssl->split_done = 1;
580311fa71b9SJerome Forissier     }
580411fa71b9SJerome Forissier 
580511fa71b9SJerome Forissier     if( ( ret = ssl_write_real( ssl, buf + 1, len - 1 ) ) <= 0 )
580611fa71b9SJerome Forissier         return( ret );
580711fa71b9SJerome Forissier     ssl->split_done = 0;
580811fa71b9SJerome Forissier 
580911fa71b9SJerome Forissier     return( ret + 1 );
581011fa71b9SJerome Forissier }
581111fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */
581211fa71b9SJerome Forissier 
581311fa71b9SJerome Forissier /*
581411fa71b9SJerome Forissier  * Write application data (public-facing wrapper)
581511fa71b9SJerome Forissier  */
581611fa71b9SJerome Forissier int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len )
581711fa71b9SJerome Forissier {
581811fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
581911fa71b9SJerome Forissier 
582011fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write" ) );
582111fa71b9SJerome Forissier 
582211fa71b9SJerome Forissier     if( ssl == NULL || ssl->conf == NULL )
582311fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
582411fa71b9SJerome Forissier 
582511fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_RENEGOTIATION)
582611fa71b9SJerome Forissier     if( ( ret = ssl_check_ctr_renegotiate( ssl ) ) != 0 )
582711fa71b9SJerome Forissier     {
582811fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret );
582911fa71b9SJerome Forissier         return( ret );
583011fa71b9SJerome Forissier     }
583111fa71b9SJerome Forissier #endif
583211fa71b9SJerome Forissier 
583311fa71b9SJerome Forissier     if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
583411fa71b9SJerome Forissier     {
583511fa71b9SJerome Forissier         if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 )
583611fa71b9SJerome Forissier         {
583711fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret );
583811fa71b9SJerome Forissier             return( ret );
583911fa71b9SJerome Forissier         }
584011fa71b9SJerome Forissier     }
584111fa71b9SJerome Forissier 
584211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING)
584311fa71b9SJerome Forissier     ret = ssl_write_split( ssl, buf, len );
584411fa71b9SJerome Forissier #else
584511fa71b9SJerome Forissier     ret = ssl_write_real( ssl, buf, len );
584611fa71b9SJerome Forissier #endif
584711fa71b9SJerome Forissier 
584811fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write" ) );
584911fa71b9SJerome Forissier 
585011fa71b9SJerome Forissier     return( ret );
585111fa71b9SJerome Forissier }
585211fa71b9SJerome Forissier 
585311fa71b9SJerome Forissier /*
585411fa71b9SJerome Forissier  * Notify the peer that the connection is being closed
585511fa71b9SJerome Forissier  */
585611fa71b9SJerome Forissier int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl )
585711fa71b9SJerome Forissier {
585811fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
585911fa71b9SJerome Forissier 
586011fa71b9SJerome Forissier     if( ssl == NULL || ssl->conf == NULL )
586111fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
586211fa71b9SJerome Forissier 
586311fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write close notify" ) );
586411fa71b9SJerome Forissier 
586511fa71b9SJerome Forissier     if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
586611fa71b9SJerome Forissier     {
586711fa71b9SJerome Forissier         if( ( ret = mbedtls_ssl_send_alert_message( ssl,
586811fa71b9SJerome Forissier                         MBEDTLS_SSL_ALERT_LEVEL_WARNING,
586911fa71b9SJerome Forissier                         MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY ) ) != 0 )
587011fa71b9SJerome Forissier         {
587111fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_send_alert_message", ret );
587211fa71b9SJerome Forissier             return( ret );
587311fa71b9SJerome Forissier         }
587411fa71b9SJerome Forissier     }
587511fa71b9SJerome Forissier 
587611fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write close notify" ) );
587711fa71b9SJerome Forissier 
587811fa71b9SJerome Forissier     return( 0 );
587911fa71b9SJerome Forissier }
588011fa71b9SJerome Forissier 
588111fa71b9SJerome Forissier void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform )
588211fa71b9SJerome Forissier {
588311fa71b9SJerome Forissier     if( transform == NULL )
588411fa71b9SJerome Forissier         return;
588511fa71b9SJerome Forissier 
588611fa71b9SJerome Forissier #if defined(MBEDTLS_ZLIB_SUPPORT)
588711fa71b9SJerome Forissier     deflateEnd( &transform->ctx_deflate );
588811fa71b9SJerome Forissier     inflateEnd( &transform->ctx_inflate );
588911fa71b9SJerome Forissier #endif
589011fa71b9SJerome Forissier 
589111fa71b9SJerome Forissier     mbedtls_cipher_free( &transform->cipher_ctx_enc );
589211fa71b9SJerome Forissier     mbedtls_cipher_free( &transform->cipher_ctx_dec );
589311fa71b9SJerome Forissier 
589411fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
589511fa71b9SJerome Forissier     mbedtls_md_free( &transform->md_ctx_enc );
589611fa71b9SJerome Forissier     mbedtls_md_free( &transform->md_ctx_dec );
589711fa71b9SJerome Forissier #endif
589811fa71b9SJerome Forissier 
589911fa71b9SJerome Forissier     mbedtls_platform_zeroize( transform, sizeof( mbedtls_ssl_transform ) );
590011fa71b9SJerome Forissier }
590111fa71b9SJerome Forissier 
590211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
590311fa71b9SJerome Forissier 
590411fa71b9SJerome Forissier void mbedtls_ssl_buffering_free( mbedtls_ssl_context *ssl )
590511fa71b9SJerome Forissier {
590611fa71b9SJerome Forissier     unsigned offset;
590711fa71b9SJerome Forissier     mbedtls_ssl_handshake_params * const hs = ssl->handshake;
590811fa71b9SJerome Forissier 
590911fa71b9SJerome Forissier     if( hs == NULL )
591011fa71b9SJerome Forissier         return;
591111fa71b9SJerome Forissier 
591211fa71b9SJerome Forissier     ssl_free_buffered_record( ssl );
591311fa71b9SJerome Forissier 
591411fa71b9SJerome Forissier     for( offset = 0; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++ )
591511fa71b9SJerome Forissier         ssl_buffering_free_slot( ssl, offset );
591611fa71b9SJerome Forissier }
591711fa71b9SJerome Forissier 
591811fa71b9SJerome Forissier static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl,
591911fa71b9SJerome Forissier                                      uint8_t slot )
592011fa71b9SJerome Forissier {
592111fa71b9SJerome Forissier     mbedtls_ssl_handshake_params * const hs = ssl->handshake;
592211fa71b9SJerome Forissier     mbedtls_ssl_hs_buffer * const hs_buf = &hs->buffering.hs[slot];
592311fa71b9SJerome Forissier 
592411fa71b9SJerome Forissier     if( slot >= MBEDTLS_SSL_MAX_BUFFERED_HS )
592511fa71b9SJerome Forissier         return;
592611fa71b9SJerome Forissier 
592711fa71b9SJerome Forissier     if( hs_buf->is_valid == 1 )
592811fa71b9SJerome Forissier     {
592911fa71b9SJerome Forissier         hs->buffering.total_bytes_buffered -= hs_buf->data_len;
593011fa71b9SJerome Forissier         mbedtls_platform_zeroize( hs_buf->data, hs_buf->data_len );
593111fa71b9SJerome Forissier         mbedtls_free( hs_buf->data );
593211fa71b9SJerome Forissier         memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) );
593311fa71b9SJerome Forissier     }
593411fa71b9SJerome Forissier }
593511fa71b9SJerome Forissier 
593611fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
593711fa71b9SJerome Forissier 
593811fa71b9SJerome Forissier /*
593911fa71b9SJerome Forissier  * Convert version numbers to/from wire format
594011fa71b9SJerome Forissier  * and, for DTLS, to/from TLS equivalent.
594111fa71b9SJerome Forissier  *
594211fa71b9SJerome Forissier  * For TLS this is the identity.
594311fa71b9SJerome Forissier  * For DTLS, use 1's complement (v -> 255 - v, and then map as follows:
594411fa71b9SJerome Forissier  * 1.0 <-> 3.2      (DTLS 1.0 is based on TLS 1.1)
594511fa71b9SJerome Forissier  * 1.x <-> 3.x+1    for x != 0 (DTLS 1.2 based on TLS 1.2)
594611fa71b9SJerome Forissier  */
594711fa71b9SJerome Forissier void mbedtls_ssl_write_version( int major, int minor, int transport,
594811fa71b9SJerome Forissier                         unsigned char ver[2] )
594911fa71b9SJerome Forissier {
595011fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
595111fa71b9SJerome Forissier     if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
595211fa71b9SJerome Forissier     {
595311fa71b9SJerome Forissier         if( minor == MBEDTLS_SSL_MINOR_VERSION_2 )
595411fa71b9SJerome Forissier             --minor; /* DTLS 1.0 stored as TLS 1.1 internally */
595511fa71b9SJerome Forissier 
595611fa71b9SJerome Forissier         ver[0] = (unsigned char)( 255 - ( major - 2 ) );
595711fa71b9SJerome Forissier         ver[1] = (unsigned char)( 255 - ( minor - 1 ) );
595811fa71b9SJerome Forissier     }
595911fa71b9SJerome Forissier     else
596011fa71b9SJerome Forissier #else
596111fa71b9SJerome Forissier     ((void) transport);
596211fa71b9SJerome Forissier #endif
596311fa71b9SJerome Forissier     {
596411fa71b9SJerome Forissier         ver[0] = (unsigned char) major;
596511fa71b9SJerome Forissier         ver[1] = (unsigned char) minor;
596611fa71b9SJerome Forissier     }
596711fa71b9SJerome Forissier }
596811fa71b9SJerome Forissier 
596911fa71b9SJerome Forissier void mbedtls_ssl_read_version( int *major, int *minor, int transport,
597011fa71b9SJerome Forissier                        const unsigned char ver[2] )
597111fa71b9SJerome Forissier {
597211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
597311fa71b9SJerome Forissier     if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
597411fa71b9SJerome Forissier     {
597511fa71b9SJerome Forissier         *major = 255 - ver[0] + 2;
597611fa71b9SJerome Forissier         *minor = 255 - ver[1] + 1;
597711fa71b9SJerome Forissier 
597811fa71b9SJerome Forissier         if( *minor == MBEDTLS_SSL_MINOR_VERSION_1 )
597911fa71b9SJerome Forissier             ++*minor; /* DTLS 1.0 stored as TLS 1.1 internally */
598011fa71b9SJerome Forissier     }
598111fa71b9SJerome Forissier     else
598211fa71b9SJerome Forissier #else
598311fa71b9SJerome Forissier     ((void) transport);
598411fa71b9SJerome Forissier #endif
598511fa71b9SJerome Forissier     {
598611fa71b9SJerome Forissier         *major = ver[0];
598711fa71b9SJerome Forissier         *minor = ver[1];
598811fa71b9SJerome Forissier     }
598911fa71b9SJerome Forissier }
599011fa71b9SJerome Forissier 
599111fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_TLS_C */
5992