xref: /optee_os/lib/libmbedtls/mbedtls/library/ssl_msg.c (revision 7901324d9530594155991c8b283023d567741cc7)
111fa71b9SJerome Forissier /*
211fa71b9SJerome Forissier  *  Generic SSL/TLS messaging layer functions
311fa71b9SJerome Forissier  *  (record layer + retransmission state machine)
411fa71b9SJerome Forissier  *
5*7901324dSJerome 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 
29*7901324dSJerome 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"
4711fa71b9SJerome Forissier 
48*7901324dSJerome Forissier #include "ssl_invasive.h"
49*7901324dSJerome 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)
9411fa71b9SJerome Forissier static int ssl_parse_record_header( mbedtls_ssl_context const *ssl,
9511fa71b9SJerome Forissier                                     unsigned char *buf,
9611fa71b9SJerome Forissier                                     size_t len,
9711fa71b9SJerome Forissier                                     mbedtls_record *rec );
9811fa71b9SJerome Forissier 
9911fa71b9SJerome Forissier int mbedtls_ssl_check_record( mbedtls_ssl_context const *ssl,
10011fa71b9SJerome Forissier                               unsigned char *buf,
10111fa71b9SJerome Forissier                               size_t buflen )
10211fa71b9SJerome Forissier {
10311fa71b9SJerome Forissier     int ret = 0;
10411fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 1, ( "=> mbedtls_ssl_check_record" ) );
10511fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_BUF( 3, "record buffer", buf, buflen );
10611fa71b9SJerome Forissier 
10711fa71b9SJerome Forissier     /* We don't support record checking in TLS because
10811fa71b9SJerome Forissier      * (a) there doesn't seem to be a usecase for it, and
10911fa71b9SJerome Forissier      * (b) In SSLv3 and TLS 1.0, CBC record decryption has state
11011fa71b9SJerome Forissier      *     and we'd need to backup the transform here.
11111fa71b9SJerome Forissier      */
11211fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM )
11311fa71b9SJerome Forissier     {
11411fa71b9SJerome Forissier         ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
11511fa71b9SJerome Forissier         goto exit;
11611fa71b9SJerome Forissier     }
11711fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
11811fa71b9SJerome Forissier     else
11911fa71b9SJerome Forissier     {
12011fa71b9SJerome Forissier         mbedtls_record rec;
12111fa71b9SJerome Forissier 
12211fa71b9SJerome Forissier         ret = ssl_parse_record_header( ssl, buf, buflen, &rec );
12311fa71b9SJerome Forissier         if( ret != 0 )
12411fa71b9SJerome Forissier         {
12511fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 3, "ssl_parse_record_header", ret );
12611fa71b9SJerome Forissier             goto exit;
12711fa71b9SJerome Forissier         }
12811fa71b9SJerome Forissier 
12911fa71b9SJerome Forissier         if( ssl->transform_in != NULL )
13011fa71b9SJerome Forissier         {
13111fa71b9SJerome Forissier             ret = mbedtls_ssl_decrypt_buf( ssl, ssl->transform_in, &rec );
13211fa71b9SJerome Forissier             if( ret != 0 )
13311fa71b9SJerome Forissier             {
13411fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_RET( 3, "mbedtls_ssl_decrypt_buf", ret );
13511fa71b9SJerome Forissier                 goto exit;
13611fa71b9SJerome Forissier             }
13711fa71b9SJerome Forissier         }
13811fa71b9SJerome Forissier     }
13911fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
14011fa71b9SJerome Forissier 
14111fa71b9SJerome Forissier exit:
14211fa71b9SJerome Forissier     /* On success, we have decrypted the buffer in-place, so make
14311fa71b9SJerome Forissier      * sure we don't leak any plaintext data. */
14411fa71b9SJerome Forissier     mbedtls_platform_zeroize( buf, buflen );
14511fa71b9SJerome Forissier 
14611fa71b9SJerome Forissier     /* For the purpose of this API, treat messages with unexpected CID
14711fa71b9SJerome Forissier      * as well as such from future epochs as unexpected. */
14811fa71b9SJerome Forissier     if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_CID ||
14911fa71b9SJerome Forissier         ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE )
15011fa71b9SJerome Forissier     {
15111fa71b9SJerome Forissier         ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD;
15211fa71b9SJerome Forissier     }
15311fa71b9SJerome Forissier 
15411fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 1, ( "<= mbedtls_ssl_check_record" ) );
15511fa71b9SJerome Forissier     return( ret );
15611fa71b9SJerome Forissier }
15711fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_RECORD_CHECKING */
15811fa71b9SJerome Forissier 
15911fa71b9SJerome Forissier #define SSL_DONT_FORCE_FLUSH 0
16011fa71b9SJerome Forissier #define SSL_FORCE_FLUSH      1
16111fa71b9SJerome Forissier 
16211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
16311fa71b9SJerome Forissier 
16411fa71b9SJerome Forissier /* Forward declarations for functions related to message buffering. */
16511fa71b9SJerome Forissier static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl,
16611fa71b9SJerome Forissier                                      uint8_t slot );
16711fa71b9SJerome Forissier static void ssl_free_buffered_record( mbedtls_ssl_context *ssl );
16811fa71b9SJerome Forissier static int ssl_load_buffered_message( mbedtls_ssl_context *ssl );
16911fa71b9SJerome Forissier static int ssl_load_buffered_record( mbedtls_ssl_context *ssl );
17011fa71b9SJerome Forissier static int ssl_buffer_message( mbedtls_ssl_context *ssl );
17111fa71b9SJerome Forissier static int ssl_buffer_future_record( mbedtls_ssl_context *ssl,
17211fa71b9SJerome Forissier                                      mbedtls_record const *rec );
17311fa71b9SJerome Forissier static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl );
17411fa71b9SJerome Forissier 
17511fa71b9SJerome Forissier static size_t ssl_get_maximum_datagram_size( mbedtls_ssl_context const *ssl )
17611fa71b9SJerome Forissier {
17711fa71b9SJerome Forissier     size_t mtu = mbedtls_ssl_get_current_mtu( ssl );
17811fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
17911fa71b9SJerome Forissier     size_t out_buf_len = ssl->out_buf_len;
18011fa71b9SJerome Forissier #else
18111fa71b9SJerome Forissier     size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN;
18211fa71b9SJerome Forissier #endif
18311fa71b9SJerome Forissier 
18411fa71b9SJerome Forissier     if( mtu != 0 && mtu < out_buf_len )
18511fa71b9SJerome Forissier         return( mtu );
18611fa71b9SJerome Forissier 
18711fa71b9SJerome Forissier     return( out_buf_len );
18811fa71b9SJerome Forissier }
18911fa71b9SJerome Forissier 
19011fa71b9SJerome Forissier static int ssl_get_remaining_space_in_datagram( mbedtls_ssl_context const *ssl )
19111fa71b9SJerome Forissier {
19211fa71b9SJerome Forissier     size_t const bytes_written = ssl->out_left;
19311fa71b9SJerome Forissier     size_t const mtu           = ssl_get_maximum_datagram_size( ssl );
19411fa71b9SJerome Forissier 
19511fa71b9SJerome Forissier     /* Double-check that the write-index hasn't gone
19611fa71b9SJerome Forissier      * past what we can transmit in a single datagram. */
19711fa71b9SJerome Forissier     if( bytes_written > mtu )
19811fa71b9SJerome Forissier     {
19911fa71b9SJerome Forissier         /* Should never happen... */
20011fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
20111fa71b9SJerome Forissier     }
20211fa71b9SJerome Forissier 
20311fa71b9SJerome Forissier     return( (int) ( mtu - bytes_written ) );
20411fa71b9SJerome Forissier }
20511fa71b9SJerome Forissier 
20611fa71b9SJerome Forissier static int ssl_get_remaining_payload_in_datagram( mbedtls_ssl_context const *ssl )
20711fa71b9SJerome Forissier {
20811fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
20911fa71b9SJerome Forissier     size_t remaining, expansion;
21011fa71b9SJerome Forissier     size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN;
21111fa71b9SJerome Forissier 
21211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
21311fa71b9SJerome Forissier     const size_t mfl = mbedtls_ssl_get_output_max_frag_len( ssl );
21411fa71b9SJerome Forissier 
21511fa71b9SJerome Forissier     if( max_len > mfl )
21611fa71b9SJerome Forissier         max_len = mfl;
21711fa71b9SJerome Forissier 
21811fa71b9SJerome Forissier     /* By the standard (RFC 6066 Sect. 4), the MFL extension
21911fa71b9SJerome Forissier      * only limits the maximum record payload size, so in theory
22011fa71b9SJerome Forissier      * we would be allowed to pack multiple records of payload size
22111fa71b9SJerome Forissier      * MFL into a single datagram. However, this would mean that there's
22211fa71b9SJerome Forissier      * no way to explicitly communicate MTU restrictions to the peer.
22311fa71b9SJerome Forissier      *
22411fa71b9SJerome Forissier      * The following reduction of max_len makes sure that we never
22511fa71b9SJerome Forissier      * write datagrams larger than MFL + Record Expansion Overhead.
22611fa71b9SJerome Forissier      */
22711fa71b9SJerome Forissier     if( max_len <= ssl->out_left )
22811fa71b9SJerome Forissier         return( 0 );
22911fa71b9SJerome Forissier 
23011fa71b9SJerome Forissier     max_len -= ssl->out_left;
23111fa71b9SJerome Forissier #endif
23211fa71b9SJerome Forissier 
23311fa71b9SJerome Forissier     ret = ssl_get_remaining_space_in_datagram( ssl );
23411fa71b9SJerome Forissier     if( ret < 0 )
23511fa71b9SJerome Forissier         return( ret );
23611fa71b9SJerome Forissier     remaining = (size_t) ret;
23711fa71b9SJerome Forissier 
23811fa71b9SJerome Forissier     ret = mbedtls_ssl_get_record_expansion( ssl );
23911fa71b9SJerome Forissier     if( ret < 0 )
24011fa71b9SJerome Forissier         return( ret );
24111fa71b9SJerome Forissier     expansion = (size_t) ret;
24211fa71b9SJerome Forissier 
24311fa71b9SJerome Forissier     if( remaining <= expansion )
24411fa71b9SJerome Forissier         return( 0 );
24511fa71b9SJerome Forissier 
24611fa71b9SJerome Forissier     remaining -= expansion;
24711fa71b9SJerome Forissier     if( remaining >= max_len )
24811fa71b9SJerome Forissier         remaining = max_len;
24911fa71b9SJerome Forissier 
25011fa71b9SJerome Forissier     return( (int) remaining );
25111fa71b9SJerome Forissier }
25211fa71b9SJerome Forissier 
25311fa71b9SJerome Forissier /*
25411fa71b9SJerome Forissier  * Double the retransmit timeout value, within the allowed range,
25511fa71b9SJerome Forissier  * returning -1 if the maximum value has already been reached.
25611fa71b9SJerome Forissier  */
25711fa71b9SJerome Forissier static int ssl_double_retransmit_timeout( mbedtls_ssl_context *ssl )
25811fa71b9SJerome Forissier {
25911fa71b9SJerome Forissier     uint32_t new_timeout;
26011fa71b9SJerome Forissier 
26111fa71b9SJerome Forissier     if( ssl->handshake->retransmit_timeout >= ssl->conf->hs_timeout_max )
26211fa71b9SJerome Forissier         return( -1 );
26311fa71b9SJerome Forissier 
26411fa71b9SJerome Forissier     /* Implement the final paragraph of RFC 6347 section 4.1.1.1
26511fa71b9SJerome Forissier      * in the following way: after the initial transmission and a first
26611fa71b9SJerome Forissier      * retransmission, back off to a temporary estimated MTU of 508 bytes.
26711fa71b9SJerome Forissier      * This value is guaranteed to be deliverable (if not guaranteed to be
26811fa71b9SJerome Forissier      * delivered) of any compliant IPv4 (and IPv6) network, and should work
26911fa71b9SJerome Forissier      * on most non-IP stacks too. */
27011fa71b9SJerome Forissier     if( ssl->handshake->retransmit_timeout != ssl->conf->hs_timeout_min )
27111fa71b9SJerome Forissier     {
27211fa71b9SJerome Forissier         ssl->handshake->mtu = 508;
27311fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 2, ( "mtu autoreduction to %d bytes", ssl->handshake->mtu ) );
27411fa71b9SJerome Forissier     }
27511fa71b9SJerome Forissier 
27611fa71b9SJerome Forissier     new_timeout = 2 * ssl->handshake->retransmit_timeout;
27711fa71b9SJerome Forissier 
27811fa71b9SJerome Forissier     /* Avoid arithmetic overflow and range overflow */
27911fa71b9SJerome Forissier     if( new_timeout < ssl->handshake->retransmit_timeout ||
28011fa71b9SJerome Forissier         new_timeout > ssl->conf->hs_timeout_max )
28111fa71b9SJerome Forissier     {
28211fa71b9SJerome Forissier         new_timeout = ssl->conf->hs_timeout_max;
28311fa71b9SJerome Forissier     }
28411fa71b9SJerome Forissier 
28511fa71b9SJerome Forissier     ssl->handshake->retransmit_timeout = new_timeout;
286*7901324dSJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %lu millisecs",
287*7901324dSJerome Forissier                         (unsigned long) ssl->handshake->retransmit_timeout ) );
28811fa71b9SJerome Forissier 
28911fa71b9SJerome Forissier     return( 0 );
29011fa71b9SJerome Forissier }
29111fa71b9SJerome Forissier 
29211fa71b9SJerome Forissier static void ssl_reset_retransmit_timeout( mbedtls_ssl_context *ssl )
29311fa71b9SJerome Forissier {
29411fa71b9SJerome Forissier     ssl->handshake->retransmit_timeout = ssl->conf->hs_timeout_min;
295*7901324dSJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %lu millisecs",
296*7901324dSJerome Forissier                         (unsigned long) ssl->handshake->retransmit_timeout ) );
29711fa71b9SJerome Forissier }
29811fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
29911fa71b9SJerome Forissier 
30011fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
30111fa71b9SJerome Forissier int (*mbedtls_ssl_hw_record_init)( mbedtls_ssl_context *ssl,
30211fa71b9SJerome Forissier                      const unsigned char *key_enc, const unsigned char *key_dec,
30311fa71b9SJerome Forissier                      size_t keylen,
30411fa71b9SJerome Forissier                      const unsigned char *iv_enc,  const unsigned char *iv_dec,
30511fa71b9SJerome Forissier                      size_t ivlen,
30611fa71b9SJerome Forissier                      const unsigned char *mac_enc, const unsigned char *mac_dec,
30711fa71b9SJerome Forissier                      size_t maclen ) = NULL;
30811fa71b9SJerome Forissier int (*mbedtls_ssl_hw_record_activate)( mbedtls_ssl_context *ssl, int direction) = NULL;
30911fa71b9SJerome Forissier int (*mbedtls_ssl_hw_record_reset)( mbedtls_ssl_context *ssl ) = NULL;
31011fa71b9SJerome Forissier int (*mbedtls_ssl_hw_record_write)( mbedtls_ssl_context *ssl ) = NULL;
31111fa71b9SJerome Forissier int (*mbedtls_ssl_hw_record_read)( mbedtls_ssl_context *ssl ) = NULL;
31211fa71b9SJerome Forissier int (*mbedtls_ssl_hw_record_finish)( mbedtls_ssl_context *ssl ) = NULL;
31311fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */
31411fa71b9SJerome Forissier 
31511fa71b9SJerome Forissier /*
31611fa71b9SJerome Forissier  * Encryption/decryption functions
31711fa71b9SJerome Forissier  */
31811fa71b9SJerome Forissier 
319*7901324dSJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) ||  \
320*7901324dSJerome Forissier     defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
321*7901324dSJerome Forissier 
322*7901324dSJerome Forissier static size_t ssl_compute_padding_length( size_t len,
323*7901324dSJerome Forissier                                           size_t granularity )
324*7901324dSJerome Forissier {
325*7901324dSJerome Forissier     return( ( granularity - ( len + 1 ) % granularity ) % granularity );
326*7901324dSJerome Forissier }
327*7901324dSJerome Forissier 
328*7901324dSJerome Forissier /* This functions transforms a (D)TLS plaintext fragment and a record content
329*7901324dSJerome Forissier  * type into an instance of the (D)TLSInnerPlaintext structure. This is used
330*7901324dSJerome Forissier  * in DTLS 1.2 + CID and within TLS 1.3 to allow flexible padding and to protect
331*7901324dSJerome Forissier  * a record's content type.
33211fa71b9SJerome Forissier  *
33311fa71b9SJerome Forissier  *        struct {
33411fa71b9SJerome Forissier  *            opaque content[DTLSPlaintext.length];
33511fa71b9SJerome Forissier  *            ContentType real_type;
33611fa71b9SJerome Forissier  *            uint8 zeros[length_of_padding];
337*7901324dSJerome Forissier  *        } (D)TLSInnerPlaintext;
33811fa71b9SJerome Forissier  *
33911fa71b9SJerome Forissier  *  Input:
34011fa71b9SJerome Forissier  *  - `content`: The beginning of the buffer holding the
34111fa71b9SJerome Forissier  *               plaintext to be wrapped.
34211fa71b9SJerome Forissier  *  - `*content_size`: The length of the plaintext in Bytes.
34311fa71b9SJerome Forissier  *  - `max_len`: The number of Bytes available starting from
34411fa71b9SJerome Forissier  *               `content`. This must be `>= *content_size`.
34511fa71b9SJerome Forissier  *  - `rec_type`: The desired record content type.
34611fa71b9SJerome Forissier  *
34711fa71b9SJerome Forissier  *  Output:
348*7901324dSJerome Forissier  *  - `content`: The beginning of the resulting (D)TLSInnerPlaintext structure.
349*7901324dSJerome Forissier  *  - `*content_size`: The length of the resulting (D)TLSInnerPlaintext structure.
35011fa71b9SJerome Forissier  *
35111fa71b9SJerome Forissier  *  Returns:
35211fa71b9SJerome Forissier  *  - `0` on success.
35311fa71b9SJerome Forissier  *  - A negative error code if `max_len` didn't offer enough space
35411fa71b9SJerome Forissier  *    for the expansion.
35511fa71b9SJerome Forissier  */
356*7901324dSJerome Forissier static int ssl_build_inner_plaintext( unsigned char *content,
35711fa71b9SJerome Forissier                                       size_t *content_size,
35811fa71b9SJerome Forissier                                       size_t remaining,
359*7901324dSJerome Forissier                                       uint8_t rec_type,
360*7901324dSJerome Forissier                                       size_t pad )
36111fa71b9SJerome Forissier {
36211fa71b9SJerome Forissier     size_t len = *content_size;
36311fa71b9SJerome Forissier 
36411fa71b9SJerome Forissier     /* Write real content type */
36511fa71b9SJerome Forissier     if( remaining == 0 )
36611fa71b9SJerome Forissier         return( -1 );
36711fa71b9SJerome Forissier     content[ len ] = rec_type;
36811fa71b9SJerome Forissier     len++;
36911fa71b9SJerome Forissier     remaining--;
37011fa71b9SJerome Forissier 
37111fa71b9SJerome Forissier     if( remaining < pad )
37211fa71b9SJerome Forissier         return( -1 );
37311fa71b9SJerome Forissier     memset( content + len, 0, pad );
37411fa71b9SJerome Forissier     len += pad;
37511fa71b9SJerome Forissier     remaining -= pad;
37611fa71b9SJerome Forissier 
37711fa71b9SJerome Forissier     *content_size = len;
37811fa71b9SJerome Forissier     return( 0 );
37911fa71b9SJerome Forissier }
38011fa71b9SJerome Forissier 
381*7901324dSJerome Forissier /* This function parses a (D)TLSInnerPlaintext structure.
382*7901324dSJerome Forissier  * See ssl_build_inner_plaintext() for details. */
383*7901324dSJerome Forissier static int ssl_parse_inner_plaintext( unsigned char const *content,
38411fa71b9SJerome Forissier                                           size_t *content_size,
38511fa71b9SJerome Forissier                                           uint8_t *rec_type )
38611fa71b9SJerome Forissier {
38711fa71b9SJerome Forissier     size_t remaining = *content_size;
38811fa71b9SJerome Forissier 
38911fa71b9SJerome Forissier     /* Determine length of padding by skipping zeroes from the back. */
39011fa71b9SJerome Forissier     do
39111fa71b9SJerome Forissier     {
39211fa71b9SJerome Forissier         if( remaining == 0 )
39311fa71b9SJerome Forissier             return( -1 );
39411fa71b9SJerome Forissier         remaining--;
39511fa71b9SJerome Forissier     } while( content[ remaining ] == 0 );
39611fa71b9SJerome Forissier 
39711fa71b9SJerome Forissier     *content_size = remaining;
39811fa71b9SJerome Forissier     *rec_type = content[ remaining ];
39911fa71b9SJerome Forissier 
40011fa71b9SJerome Forissier     return( 0 );
40111fa71b9SJerome Forissier }
402*7901324dSJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID ||
403*7901324dSJerome Forissier           MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
40411fa71b9SJerome Forissier 
40511fa71b9SJerome Forissier /* `add_data` must have size 13 Bytes if the CID extension is disabled,
40611fa71b9SJerome Forissier  * and 13 + 1 + CID-length Bytes if the CID extension is enabled. */
40711fa71b9SJerome Forissier static void ssl_extract_add_data_from_record( unsigned char* add_data,
40811fa71b9SJerome Forissier                                               size_t *add_data_len,
409*7901324dSJerome Forissier                                               mbedtls_record *rec,
410*7901324dSJerome Forissier                                               unsigned minor_ver )
41111fa71b9SJerome Forissier {
41211fa71b9SJerome Forissier     /* Quoting RFC 5246 (TLS 1.2):
41311fa71b9SJerome Forissier      *
41411fa71b9SJerome Forissier      *    additional_data = seq_num + TLSCompressed.type +
41511fa71b9SJerome Forissier      *                      TLSCompressed.version + TLSCompressed.length;
41611fa71b9SJerome Forissier      *
41711fa71b9SJerome Forissier      * For the CID extension, this is extended as follows
41811fa71b9SJerome Forissier      * (quoting draft-ietf-tls-dtls-connection-id-05,
41911fa71b9SJerome Forissier      *  https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05):
42011fa71b9SJerome Forissier      *
42111fa71b9SJerome Forissier      *       additional_data = seq_num + DTLSPlaintext.type +
42211fa71b9SJerome Forissier      *                         DTLSPlaintext.version +
42311fa71b9SJerome Forissier      *                         cid +
42411fa71b9SJerome Forissier      *                         cid_length +
42511fa71b9SJerome Forissier      *                         length_of_DTLSInnerPlaintext;
426*7901324dSJerome Forissier      *
427*7901324dSJerome Forissier      * For TLS 1.3, the record sequence number is dropped from the AAD
428*7901324dSJerome Forissier      * and encoded within the nonce of the AEAD operation instead.
42911fa71b9SJerome Forissier      */
43011fa71b9SJerome Forissier 
431*7901324dSJerome Forissier     unsigned char *cur = add_data;
432*7901324dSJerome Forissier 
433*7901324dSJerome Forissier #if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
434*7901324dSJerome Forissier     if( minor_ver != MBEDTLS_SSL_MINOR_VERSION_4 )
435*7901324dSJerome Forissier #endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
436*7901324dSJerome Forissier     {
437*7901324dSJerome Forissier         ((void) minor_ver);
438*7901324dSJerome Forissier         memcpy( cur, rec->ctr, sizeof( rec->ctr ) );
439*7901324dSJerome Forissier         cur += sizeof( rec->ctr );
440*7901324dSJerome Forissier     }
441*7901324dSJerome Forissier 
442*7901324dSJerome Forissier     *cur = rec->type;
443*7901324dSJerome Forissier     cur++;
444*7901324dSJerome Forissier 
445*7901324dSJerome Forissier     memcpy( cur, rec->ver, sizeof( rec->ver ) );
446*7901324dSJerome Forissier     cur += sizeof( rec->ver );
44711fa71b9SJerome Forissier 
44811fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
44911fa71b9SJerome Forissier     if( rec->cid_len != 0 )
45011fa71b9SJerome Forissier     {
451*7901324dSJerome Forissier         memcpy( cur, rec->cid, rec->cid_len );
452*7901324dSJerome Forissier         cur += rec->cid_len;
453*7901324dSJerome Forissier 
454*7901324dSJerome Forissier         *cur = rec->cid_len;
455*7901324dSJerome Forissier         cur++;
456*7901324dSJerome Forissier 
457*7901324dSJerome Forissier         cur[0] = ( rec->data_len >> 8 ) & 0xFF;
458*7901324dSJerome Forissier         cur[1] = ( rec->data_len >> 0 ) & 0xFF;
459*7901324dSJerome Forissier         cur += 2;
46011fa71b9SJerome Forissier     }
46111fa71b9SJerome Forissier     else
46211fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
46311fa71b9SJerome Forissier     {
464*7901324dSJerome Forissier         cur[0] = ( rec->data_len >> 8 ) & 0xFF;
465*7901324dSJerome Forissier         cur[1] = ( rec->data_len >> 0 ) & 0xFF;
466*7901324dSJerome Forissier         cur += 2;
46711fa71b9SJerome Forissier     }
468*7901324dSJerome Forissier 
469*7901324dSJerome Forissier     *add_data_len = cur - add_data;
47011fa71b9SJerome Forissier }
47111fa71b9SJerome Forissier 
47211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_SSL3)
47311fa71b9SJerome Forissier 
47411fa71b9SJerome Forissier #define SSL3_MAC_MAX_BYTES   20  /* MD-5 or SHA-1 */
47511fa71b9SJerome Forissier 
47611fa71b9SJerome Forissier /*
47711fa71b9SJerome Forissier  * SSLv3.0 MAC functions
47811fa71b9SJerome Forissier  */
47911fa71b9SJerome Forissier static void ssl_mac( mbedtls_md_context_t *md_ctx,
48011fa71b9SJerome Forissier                      const unsigned char *secret,
48111fa71b9SJerome Forissier                      const unsigned char *buf, size_t len,
48211fa71b9SJerome Forissier                      const unsigned char *ctr, int type,
48311fa71b9SJerome Forissier                      unsigned char out[SSL3_MAC_MAX_BYTES] )
48411fa71b9SJerome Forissier {
48511fa71b9SJerome Forissier     unsigned char header[11];
48611fa71b9SJerome Forissier     unsigned char padding[48];
48711fa71b9SJerome Forissier     int padlen;
48811fa71b9SJerome Forissier     int md_size = mbedtls_md_get_size( md_ctx->md_info );
48911fa71b9SJerome Forissier     int md_type = mbedtls_md_get_type( md_ctx->md_info );
49011fa71b9SJerome Forissier 
49111fa71b9SJerome Forissier     /* Only MD5 and SHA-1 supported */
49211fa71b9SJerome Forissier     if( md_type == MBEDTLS_MD_MD5 )
49311fa71b9SJerome Forissier         padlen = 48;
49411fa71b9SJerome Forissier     else
49511fa71b9SJerome Forissier         padlen = 40;
49611fa71b9SJerome Forissier 
49711fa71b9SJerome Forissier     memcpy( header, ctr, 8 );
49811fa71b9SJerome Forissier     header[ 8] = (unsigned char)  type;
49911fa71b9SJerome Forissier     header[ 9] = (unsigned char)( len >> 8 );
50011fa71b9SJerome Forissier     header[10] = (unsigned char)( len      );
50111fa71b9SJerome Forissier 
50211fa71b9SJerome Forissier     memset( padding, 0x36, padlen );
50311fa71b9SJerome Forissier     mbedtls_md_starts( md_ctx );
50411fa71b9SJerome Forissier     mbedtls_md_update( md_ctx, secret,  md_size );
50511fa71b9SJerome Forissier     mbedtls_md_update( md_ctx, padding, padlen  );
50611fa71b9SJerome Forissier     mbedtls_md_update( md_ctx, header,  11      );
50711fa71b9SJerome Forissier     mbedtls_md_update( md_ctx, buf,     len     );
50811fa71b9SJerome Forissier     mbedtls_md_finish( md_ctx, out              );
50911fa71b9SJerome Forissier 
51011fa71b9SJerome Forissier     memset( padding, 0x5C, padlen );
51111fa71b9SJerome Forissier     mbedtls_md_starts( md_ctx );
51211fa71b9SJerome Forissier     mbedtls_md_update( md_ctx, secret,    md_size );
51311fa71b9SJerome Forissier     mbedtls_md_update( md_ctx, padding,   padlen  );
51411fa71b9SJerome Forissier     mbedtls_md_update( md_ctx, out,       md_size );
51511fa71b9SJerome Forissier     mbedtls_md_finish( md_ctx, out                );
51611fa71b9SJerome Forissier }
51711fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_SSL3 */
51811fa71b9SJerome Forissier 
519*7901324dSJerome Forissier #if defined(MBEDTLS_GCM_C) || \
520*7901324dSJerome Forissier     defined(MBEDTLS_CCM_C) || \
521*7901324dSJerome Forissier     defined(MBEDTLS_CHACHAPOLY_C)
522*7901324dSJerome Forissier static int ssl_transform_aead_dynamic_iv_is_explicit(
523*7901324dSJerome Forissier                                 mbedtls_ssl_transform const *transform )
524*7901324dSJerome Forissier {
525*7901324dSJerome Forissier     return( transform->ivlen != transform->fixed_ivlen );
526*7901324dSJerome Forissier }
527*7901324dSJerome Forissier 
528*7901324dSJerome Forissier /* Compute IV := ( fixed_iv || 0 ) XOR ( 0 || dynamic_IV )
529*7901324dSJerome Forissier  *
530*7901324dSJerome Forissier  * Concretely, this occurs in two variants:
531*7901324dSJerome Forissier  *
532*7901324dSJerome Forissier  * a) Fixed and dynamic IV lengths add up to total IV length, giving
533*7901324dSJerome Forissier  *       IV = fixed_iv || dynamic_iv
534*7901324dSJerome Forissier  *
535*7901324dSJerome Forissier  *    This variant is used in TLS 1.2 when used with GCM or CCM.
536*7901324dSJerome Forissier  *
537*7901324dSJerome Forissier  * b) Fixed IV lengths matches total IV length, giving
538*7901324dSJerome Forissier  *       IV = fixed_iv XOR ( 0 || dynamic_iv )
539*7901324dSJerome Forissier  *
540*7901324dSJerome Forissier  *    This variant occurs in TLS 1.3 and for TLS 1.2 when using ChaChaPoly.
541*7901324dSJerome Forissier  *
542*7901324dSJerome Forissier  * See also the documentation of mbedtls_ssl_transform.
543*7901324dSJerome Forissier  *
544*7901324dSJerome Forissier  * This function has the precondition that
545*7901324dSJerome Forissier  *
546*7901324dSJerome Forissier  *     dst_iv_len >= max( fixed_iv_len, dynamic_iv_len )
547*7901324dSJerome Forissier  *
548*7901324dSJerome Forissier  * which has to be ensured by the caller. If this precondition
549*7901324dSJerome Forissier  * violated, the behavior of this function is undefined.
550*7901324dSJerome Forissier  */
551*7901324dSJerome Forissier static void ssl_build_record_nonce( unsigned char *dst_iv,
552*7901324dSJerome Forissier                                     size_t dst_iv_len,
553*7901324dSJerome Forissier                                     unsigned char const *fixed_iv,
554*7901324dSJerome Forissier                                     size_t fixed_iv_len,
555*7901324dSJerome Forissier                                     unsigned char const *dynamic_iv,
556*7901324dSJerome Forissier                                     size_t dynamic_iv_len )
557*7901324dSJerome Forissier {
558*7901324dSJerome Forissier     size_t i;
559*7901324dSJerome Forissier 
560*7901324dSJerome Forissier     /* Start with Fixed IV || 0 */
561*7901324dSJerome Forissier     memset( dst_iv, 0, dst_iv_len );
562*7901324dSJerome Forissier     memcpy( dst_iv, fixed_iv, fixed_iv_len );
563*7901324dSJerome Forissier 
564*7901324dSJerome Forissier     dst_iv += dst_iv_len - dynamic_iv_len;
565*7901324dSJerome Forissier     for( i = 0; i < dynamic_iv_len; i++ )
566*7901324dSJerome Forissier         dst_iv[i] ^= dynamic_iv[i];
567*7901324dSJerome Forissier }
568*7901324dSJerome Forissier #endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */
569*7901324dSJerome Forissier 
57011fa71b9SJerome Forissier int mbedtls_ssl_encrypt_buf( mbedtls_ssl_context *ssl,
57111fa71b9SJerome Forissier                              mbedtls_ssl_transform *transform,
57211fa71b9SJerome Forissier                              mbedtls_record *rec,
57311fa71b9SJerome Forissier                              int (*f_rng)(void *, unsigned char *, size_t),
57411fa71b9SJerome Forissier                              void *p_rng )
57511fa71b9SJerome Forissier {
57611fa71b9SJerome Forissier     mbedtls_cipher_mode_t mode;
57711fa71b9SJerome Forissier     int auth_done = 0;
57811fa71b9SJerome Forissier     unsigned char * data;
57911fa71b9SJerome Forissier     unsigned char add_data[13 + 1 + MBEDTLS_SSL_CID_OUT_LEN_MAX ];
58011fa71b9SJerome Forissier     size_t add_data_len;
58111fa71b9SJerome Forissier     size_t post_avail;
58211fa71b9SJerome Forissier 
58311fa71b9SJerome Forissier     /* The SSL context is only used for debugging purposes! */
58411fa71b9SJerome Forissier #if !defined(MBEDTLS_DEBUG_C)
58511fa71b9SJerome Forissier     ssl = NULL; /* make sure we don't use it except for debug */
58611fa71b9SJerome Forissier     ((void) ssl);
58711fa71b9SJerome Forissier #endif
58811fa71b9SJerome Forissier 
58911fa71b9SJerome Forissier     /* The PRNG is used for dynamic IV generation that's used
59011fa71b9SJerome Forissier      * for CBC transformations in TLS 1.1 and TLS 1.2. */
591*7901324dSJerome Forissier #if !( defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) && \
59211fa71b9SJerome Forissier        ( defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) ) )
59311fa71b9SJerome Forissier     ((void) f_rng);
59411fa71b9SJerome Forissier     ((void) p_rng);
59511fa71b9SJerome Forissier #endif
59611fa71b9SJerome Forissier 
59711fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> encrypt buf" ) );
59811fa71b9SJerome Forissier 
59911fa71b9SJerome Forissier     if( transform == NULL )
60011fa71b9SJerome Forissier     {
60111fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "no transform provided to encrypt_buf" ) );
60211fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
60311fa71b9SJerome Forissier     }
60411fa71b9SJerome Forissier     if( rec == NULL
60511fa71b9SJerome Forissier         || rec->buf == NULL
60611fa71b9SJerome Forissier         || rec->buf_len < rec->data_offset
60711fa71b9SJerome Forissier         || rec->buf_len - rec->data_offset < rec->data_len
60811fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
60911fa71b9SJerome Forissier         || rec->cid_len != 0
61011fa71b9SJerome Forissier #endif
61111fa71b9SJerome Forissier         )
61211fa71b9SJerome Forissier     {
61311fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad record structure provided to encrypt_buf" ) );
61411fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
61511fa71b9SJerome Forissier     }
61611fa71b9SJerome Forissier 
61711fa71b9SJerome Forissier     data = rec->buf + rec->data_offset;
61811fa71b9SJerome Forissier     post_avail = rec->buf_len - ( rec->data_len + rec->data_offset );
61911fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_BUF( 4, "before encrypt: output payload",
62011fa71b9SJerome Forissier                            data, rec->data_len );
62111fa71b9SJerome Forissier 
62211fa71b9SJerome Forissier     mode = mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc );
62311fa71b9SJerome Forissier 
62411fa71b9SJerome Forissier     if( rec->data_len > MBEDTLS_SSL_OUT_CONTENT_LEN )
62511fa71b9SJerome Forissier     {
626*7901324dSJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record content %" MBEDTLS_PRINTF_SIZET
627*7901324dSJerome Forissier                                     " too large, maximum %" MBEDTLS_PRINTF_SIZET,
628*7901324dSJerome Forissier                                     rec->data_len,
629*7901324dSJerome Forissier                                     (size_t) MBEDTLS_SSL_OUT_CONTENT_LEN ) );
63011fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
63111fa71b9SJerome Forissier     }
63211fa71b9SJerome Forissier 
633*7901324dSJerome Forissier     /* The following two code paths implement the (D)TLSInnerPlaintext
634*7901324dSJerome Forissier      * structure present in TLS 1.3 and DTLS 1.2 + CID.
635*7901324dSJerome Forissier      *
636*7901324dSJerome Forissier      * See ssl_build_inner_plaintext() for more information.
637*7901324dSJerome Forissier      *
638*7901324dSJerome Forissier      * Note that this changes `rec->data_len`, and hence
639*7901324dSJerome Forissier      * `post_avail` needs to be recalculated afterwards.
640*7901324dSJerome Forissier      *
641*7901324dSJerome Forissier      * Note also that the two code paths cannot occur simultaneously
642*7901324dSJerome Forissier      * since they apply to different versions of the protocol. There
643*7901324dSJerome Forissier      * is hence no risk of double-addition of the inner plaintext.
644*7901324dSJerome Forissier      */
645*7901324dSJerome Forissier #if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
646*7901324dSJerome Forissier     if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_4 )
647*7901324dSJerome Forissier     {
648*7901324dSJerome Forissier         size_t padding =
649*7901324dSJerome Forissier             ssl_compute_padding_length( rec->data_len,
650*7901324dSJerome Forissier                                         MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY );
651*7901324dSJerome Forissier         if( ssl_build_inner_plaintext( data,
652*7901324dSJerome Forissier                                        &rec->data_len,
653*7901324dSJerome Forissier                                        post_avail,
654*7901324dSJerome Forissier                                        rec->type,
655*7901324dSJerome Forissier                                        padding ) != 0 )
656*7901324dSJerome Forissier         {
657*7901324dSJerome Forissier             return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
658*7901324dSJerome Forissier         }
659*7901324dSJerome Forissier 
660*7901324dSJerome Forissier         rec->type = MBEDTLS_SSL_MSG_APPLICATION_DATA;
661*7901324dSJerome Forissier     }
662*7901324dSJerome Forissier #endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
663*7901324dSJerome Forissier 
66411fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
66511fa71b9SJerome Forissier     /*
66611fa71b9SJerome Forissier      * Add CID information
66711fa71b9SJerome Forissier      */
66811fa71b9SJerome Forissier     rec->cid_len = transform->out_cid_len;
66911fa71b9SJerome Forissier     memcpy( rec->cid, transform->out_cid, transform->out_cid_len );
67011fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_BUF( 3, "CID", rec->cid, rec->cid_len );
67111fa71b9SJerome Forissier 
67211fa71b9SJerome Forissier     if( rec->cid_len != 0 )
67311fa71b9SJerome Forissier     {
674*7901324dSJerome Forissier         size_t padding =
675*7901324dSJerome Forissier             ssl_compute_padding_length( rec->data_len,
676*7901324dSJerome Forissier                                         MBEDTLS_SSL_CID_PADDING_GRANULARITY );
67711fa71b9SJerome Forissier         /*
67811fa71b9SJerome Forissier          * Wrap plaintext into DTLSInnerPlaintext structure.
679*7901324dSJerome Forissier          * See ssl_build_inner_plaintext() for more information.
68011fa71b9SJerome Forissier          *
68111fa71b9SJerome Forissier          * Note that this changes `rec->data_len`, and hence
68211fa71b9SJerome Forissier          * `post_avail` needs to be recalculated afterwards.
68311fa71b9SJerome Forissier          */
684*7901324dSJerome Forissier         if( ssl_build_inner_plaintext( data,
68511fa71b9SJerome Forissier                         &rec->data_len,
68611fa71b9SJerome Forissier                         post_avail,
687*7901324dSJerome Forissier                         rec->type,
688*7901324dSJerome Forissier                         padding ) != 0 )
68911fa71b9SJerome Forissier         {
69011fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
69111fa71b9SJerome Forissier         }
69211fa71b9SJerome Forissier 
69311fa71b9SJerome Forissier         rec->type = MBEDTLS_SSL_MSG_CID;
69411fa71b9SJerome Forissier     }
69511fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
69611fa71b9SJerome Forissier 
69711fa71b9SJerome Forissier     post_avail = rec->buf_len - ( rec->data_len + rec->data_offset );
69811fa71b9SJerome Forissier 
69911fa71b9SJerome Forissier     /*
70011fa71b9SJerome Forissier      * Add MAC before if needed
70111fa71b9SJerome Forissier      */
70211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
70311fa71b9SJerome Forissier     if( mode == MBEDTLS_MODE_STREAM ||
70411fa71b9SJerome Forissier         ( mode == MBEDTLS_MODE_CBC
70511fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
70611fa71b9SJerome Forissier           && transform->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED
70711fa71b9SJerome Forissier #endif
70811fa71b9SJerome Forissier         ) )
70911fa71b9SJerome Forissier     {
71011fa71b9SJerome Forissier         if( post_avail < transform->maclen )
71111fa71b9SJerome Forissier         {
71211fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) );
71311fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
71411fa71b9SJerome Forissier         }
71511fa71b9SJerome Forissier 
71611fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_SSL3)
71711fa71b9SJerome Forissier         if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
71811fa71b9SJerome Forissier         {
71911fa71b9SJerome Forissier             unsigned char mac[SSL3_MAC_MAX_BYTES];
72011fa71b9SJerome Forissier             ssl_mac( &transform->md_ctx_enc, transform->mac_enc,
72111fa71b9SJerome Forissier                      data, rec->data_len, rec->ctr, rec->type, mac );
72211fa71b9SJerome Forissier             memcpy( data + rec->data_len, mac, transform->maclen );
72311fa71b9SJerome Forissier         }
72411fa71b9SJerome Forissier         else
72511fa71b9SJerome Forissier #endif
72611fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
72711fa71b9SJerome Forissier         defined(MBEDTLS_SSL_PROTO_TLS1_2)
72811fa71b9SJerome Forissier         if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 )
72911fa71b9SJerome Forissier         {
73011fa71b9SJerome Forissier             unsigned char mac[MBEDTLS_SSL_MAC_ADD];
73111fa71b9SJerome Forissier 
732*7901324dSJerome Forissier             ssl_extract_add_data_from_record( add_data, &add_data_len, rec,
733*7901324dSJerome Forissier                                               transform->minor_ver );
73411fa71b9SJerome Forissier 
73511fa71b9SJerome Forissier             mbedtls_md_hmac_update( &transform->md_ctx_enc, add_data,
73611fa71b9SJerome Forissier                                     add_data_len );
73711fa71b9SJerome Forissier             mbedtls_md_hmac_update( &transform->md_ctx_enc,
73811fa71b9SJerome Forissier                                     data, rec->data_len );
73911fa71b9SJerome Forissier             mbedtls_md_hmac_finish( &transform->md_ctx_enc, mac );
74011fa71b9SJerome Forissier             mbedtls_md_hmac_reset( &transform->md_ctx_enc );
74111fa71b9SJerome Forissier 
74211fa71b9SJerome Forissier             memcpy( data + rec->data_len, mac, transform->maclen );
74311fa71b9SJerome Forissier         }
74411fa71b9SJerome Forissier         else
74511fa71b9SJerome Forissier #endif
74611fa71b9SJerome Forissier         {
74711fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
74811fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
74911fa71b9SJerome Forissier         }
75011fa71b9SJerome Forissier 
75111fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_BUF( 4, "computed mac", data + rec->data_len,
75211fa71b9SJerome Forissier                                transform->maclen );
75311fa71b9SJerome Forissier 
75411fa71b9SJerome Forissier         rec->data_len += transform->maclen;
75511fa71b9SJerome Forissier         post_avail -= transform->maclen;
75611fa71b9SJerome Forissier         auth_done++;
75711fa71b9SJerome Forissier     }
75811fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */
75911fa71b9SJerome Forissier 
76011fa71b9SJerome Forissier     /*
76111fa71b9SJerome Forissier      * Encrypt
76211fa71b9SJerome Forissier      */
76311fa71b9SJerome Forissier #if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER)
76411fa71b9SJerome Forissier     if( mode == MBEDTLS_MODE_STREAM )
76511fa71b9SJerome Forissier     {
76611fa71b9SJerome Forissier         int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
76711fa71b9SJerome Forissier         size_t olen;
768*7901324dSJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %" MBEDTLS_PRINTF_SIZET ", "
76911fa71b9SJerome Forissier                                     "including %d bytes of padding",
77011fa71b9SJerome Forissier                                     rec->data_len, 0 ) );
77111fa71b9SJerome Forissier 
77211fa71b9SJerome Forissier         if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_enc,
77311fa71b9SJerome Forissier                                    transform->iv_enc, transform->ivlen,
77411fa71b9SJerome Forissier                                    data, rec->data_len,
77511fa71b9SJerome Forissier                                    data, &olen ) ) != 0 )
77611fa71b9SJerome Forissier         {
77711fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret );
77811fa71b9SJerome Forissier             return( ret );
77911fa71b9SJerome Forissier         }
78011fa71b9SJerome Forissier 
78111fa71b9SJerome Forissier         if( rec->data_len != olen )
78211fa71b9SJerome Forissier         {
78311fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
78411fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
78511fa71b9SJerome Forissier         }
78611fa71b9SJerome Forissier     }
78711fa71b9SJerome Forissier     else
78811fa71b9SJerome Forissier #endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */
78911fa71b9SJerome Forissier 
79011fa71b9SJerome Forissier #if defined(MBEDTLS_GCM_C) || \
79111fa71b9SJerome Forissier     defined(MBEDTLS_CCM_C) || \
79211fa71b9SJerome Forissier     defined(MBEDTLS_CHACHAPOLY_C)
79311fa71b9SJerome Forissier     if( mode == MBEDTLS_MODE_GCM ||
79411fa71b9SJerome Forissier         mode == MBEDTLS_MODE_CCM ||
79511fa71b9SJerome Forissier         mode == MBEDTLS_MODE_CHACHAPOLY )
79611fa71b9SJerome Forissier     {
79711fa71b9SJerome Forissier         int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
79811fa71b9SJerome Forissier         unsigned char iv[12];
799*7901324dSJerome Forissier         unsigned char *dynamic_iv;
800*7901324dSJerome Forissier         size_t dynamic_iv_len;
801*7901324dSJerome Forissier         int dynamic_iv_is_explicit =
802*7901324dSJerome Forissier             ssl_transform_aead_dynamic_iv_is_explicit( transform );
80311fa71b9SJerome Forissier 
804*7901324dSJerome Forissier         /* Check that there's space for the authentication tag. */
805*7901324dSJerome Forissier         if( post_avail < transform->taglen )
80611fa71b9SJerome Forissier         {
80711fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) );
80811fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
80911fa71b9SJerome Forissier         }
81011fa71b9SJerome Forissier 
81111fa71b9SJerome Forissier         /*
812*7901324dSJerome Forissier          * Build nonce for AEAD encryption.
813*7901324dSJerome Forissier          *
814*7901324dSJerome Forissier          * Note: In the case of CCM and GCM in TLS 1.2, the dynamic
815*7901324dSJerome Forissier          *       part of the IV is prepended to the ciphertext and
816*7901324dSJerome Forissier          *       can be chosen freely - in particular, it need not
817*7901324dSJerome Forissier          *       agree with the record sequence number.
818*7901324dSJerome Forissier          *       However, since ChaChaPoly as well as all AEAD modes
819*7901324dSJerome Forissier          *       in TLS 1.3 use the record sequence number as the
820*7901324dSJerome Forissier          *       dynamic part of the nonce, we uniformly use the
821*7901324dSJerome Forissier          *       record sequence number here in all cases.
82211fa71b9SJerome Forissier          */
823*7901324dSJerome Forissier         dynamic_iv     = rec->ctr;
824*7901324dSJerome Forissier         dynamic_iv_len = sizeof( rec->ctr );
82511fa71b9SJerome Forissier 
826*7901324dSJerome Forissier         ssl_build_record_nonce( iv, sizeof( iv ),
827*7901324dSJerome Forissier                                 transform->iv_enc,
828*7901324dSJerome Forissier                                 transform->fixed_ivlen,
829*7901324dSJerome Forissier                                 dynamic_iv,
830*7901324dSJerome Forissier                                 dynamic_iv_len );
83111fa71b9SJerome Forissier 
832*7901324dSJerome Forissier         /*
833*7901324dSJerome Forissier          * Build additional data for AEAD encryption.
834*7901324dSJerome Forissier          * This depends on the TLS version.
835*7901324dSJerome Forissier          */
836*7901324dSJerome Forissier         ssl_extract_add_data_from_record( add_data, &add_data_len, rec,
837*7901324dSJerome Forissier                                           transform->minor_ver );
83811fa71b9SJerome Forissier 
83911fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (internal)",
84011fa71b9SJerome Forissier                                iv, transform->ivlen );
84111fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (transmitted)",
842*7901324dSJerome Forissier                                dynamic_iv,
843*7901324dSJerome Forissier                                dynamic_iv_is_explicit ? dynamic_iv_len : 0 );
84411fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD",
84511fa71b9SJerome Forissier                                add_data, add_data_len );
846*7901324dSJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %" MBEDTLS_PRINTF_SIZET ", "
84711fa71b9SJerome Forissier                                     "including 0 bytes of padding",
84811fa71b9SJerome Forissier                                     rec->data_len ) );
84911fa71b9SJerome Forissier 
85011fa71b9SJerome Forissier         /*
85111fa71b9SJerome Forissier          * Encrypt and authenticate
85211fa71b9SJerome Forissier          */
85311fa71b9SJerome Forissier 
854*7901324dSJerome Forissier         if( ( ret = mbedtls_cipher_auth_encrypt_ext( &transform->cipher_ctx_enc,
85511fa71b9SJerome Forissier                    iv, transform->ivlen,
856*7901324dSJerome Forissier                    add_data, add_data_len,
857*7901324dSJerome Forissier                    data, rec->data_len,                     /* src */
858*7901324dSJerome Forissier                    data, rec->buf_len - (data - rec->buf),  /* dst */
859*7901324dSJerome Forissier                    &rec->data_len,
860*7901324dSJerome Forissier                    transform->taglen ) ) != 0 )
86111fa71b9SJerome Forissier         {
86211fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_encrypt", ret );
86311fa71b9SJerome Forissier             return( ret );
86411fa71b9SJerome Forissier         }
86511fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_BUF( 4, "after encrypt: tag",
866*7901324dSJerome Forissier                                data + rec->data_len - transform->taglen,
867*7901324dSJerome Forissier                                transform->taglen );
868*7901324dSJerome Forissier         /* Account for authentication tag. */
86911fa71b9SJerome Forissier         post_avail -= transform->taglen;
870*7901324dSJerome Forissier 
871*7901324dSJerome Forissier         /*
872*7901324dSJerome Forissier          * Prefix record content with dynamic IV in case it is explicit.
873*7901324dSJerome Forissier          */
874*7901324dSJerome Forissier         if( dynamic_iv_is_explicit != 0 )
875*7901324dSJerome Forissier         {
876*7901324dSJerome Forissier             if( rec->data_offset < dynamic_iv_len )
877*7901324dSJerome Forissier             {
878*7901324dSJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) );
879*7901324dSJerome Forissier                 return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
880*7901324dSJerome Forissier             }
881*7901324dSJerome Forissier 
882*7901324dSJerome Forissier             memcpy( data - dynamic_iv_len, dynamic_iv, dynamic_iv_len );
883*7901324dSJerome Forissier             rec->data_offset -= dynamic_iv_len;
884*7901324dSJerome Forissier             rec->data_len    += dynamic_iv_len;
885*7901324dSJerome Forissier         }
886*7901324dSJerome Forissier 
88711fa71b9SJerome Forissier         auth_done++;
88811fa71b9SJerome Forissier     }
88911fa71b9SJerome Forissier     else
890*7901324dSJerome Forissier #endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */
891*7901324dSJerome Forissier #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC)
89211fa71b9SJerome Forissier     if( mode == MBEDTLS_MODE_CBC )
89311fa71b9SJerome Forissier     {
89411fa71b9SJerome Forissier         int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
89511fa71b9SJerome Forissier         size_t padlen, i;
89611fa71b9SJerome Forissier         size_t olen;
89711fa71b9SJerome Forissier 
89811fa71b9SJerome Forissier         /* Currently we're always using minimal padding
89911fa71b9SJerome Forissier          * (up to 255 bytes would be allowed). */
90011fa71b9SJerome Forissier         padlen = transform->ivlen - ( rec->data_len + 1 ) % transform->ivlen;
90111fa71b9SJerome Forissier         if( padlen == transform->ivlen )
90211fa71b9SJerome Forissier             padlen = 0;
90311fa71b9SJerome Forissier 
90411fa71b9SJerome Forissier         /* Check there's enough space in the buffer for the padding. */
90511fa71b9SJerome Forissier         if( post_avail < padlen + 1 )
90611fa71b9SJerome Forissier         {
90711fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) );
90811fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
90911fa71b9SJerome Forissier         }
91011fa71b9SJerome Forissier 
91111fa71b9SJerome Forissier         for( i = 0; i <= padlen; i++ )
91211fa71b9SJerome Forissier             data[rec->data_len + i] = (unsigned char) padlen;
91311fa71b9SJerome Forissier 
91411fa71b9SJerome Forissier         rec->data_len += padlen + 1;
91511fa71b9SJerome Forissier         post_avail -= padlen + 1;
91611fa71b9SJerome Forissier 
91711fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)
91811fa71b9SJerome Forissier         /*
91911fa71b9SJerome Forissier          * Prepend per-record IV for block cipher in TLS v1.1 and up as per
92011fa71b9SJerome Forissier          * Method 1 (6.2.3.2. in RFC4346 and RFC5246)
92111fa71b9SJerome Forissier          */
92211fa71b9SJerome Forissier         if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
92311fa71b9SJerome Forissier         {
92411fa71b9SJerome Forissier             if( f_rng == NULL )
92511fa71b9SJerome Forissier             {
92611fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "No PRNG provided to encrypt_record routine" ) );
92711fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
92811fa71b9SJerome Forissier             }
92911fa71b9SJerome Forissier 
93011fa71b9SJerome Forissier             if( rec->data_offset < transform->ivlen )
93111fa71b9SJerome Forissier             {
93211fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) );
93311fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
93411fa71b9SJerome Forissier             }
93511fa71b9SJerome Forissier 
93611fa71b9SJerome Forissier             /*
93711fa71b9SJerome Forissier              * Generate IV
93811fa71b9SJerome Forissier              */
93911fa71b9SJerome Forissier             ret = f_rng( p_rng, transform->iv_enc, transform->ivlen );
94011fa71b9SJerome Forissier             if( ret != 0 )
94111fa71b9SJerome Forissier                 return( ret );
94211fa71b9SJerome Forissier 
94311fa71b9SJerome Forissier             memcpy( data - transform->ivlen, transform->iv_enc,
94411fa71b9SJerome Forissier                     transform->ivlen );
94511fa71b9SJerome Forissier 
94611fa71b9SJerome Forissier         }
94711fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */
94811fa71b9SJerome Forissier 
949*7901324dSJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %" MBEDTLS_PRINTF_SIZET ", "
950*7901324dSJerome Forissier                             "including %" MBEDTLS_PRINTF_SIZET
951*7901324dSJerome Forissier                             " bytes of IV and %" MBEDTLS_PRINTF_SIZET " bytes of padding",
95211fa71b9SJerome Forissier                             rec->data_len, transform->ivlen,
95311fa71b9SJerome Forissier                             padlen + 1 ) );
95411fa71b9SJerome Forissier 
95511fa71b9SJerome Forissier         if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_enc,
95611fa71b9SJerome Forissier                                    transform->iv_enc,
95711fa71b9SJerome Forissier                                    transform->ivlen,
95811fa71b9SJerome Forissier                                    data, rec->data_len,
95911fa71b9SJerome Forissier                                    data, &olen ) ) != 0 )
96011fa71b9SJerome Forissier         {
96111fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret );
96211fa71b9SJerome Forissier             return( ret );
96311fa71b9SJerome Forissier         }
96411fa71b9SJerome Forissier 
96511fa71b9SJerome Forissier         if( rec->data_len != olen )
96611fa71b9SJerome Forissier         {
96711fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
96811fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
96911fa71b9SJerome Forissier         }
97011fa71b9SJerome Forissier 
97111fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1)
97211fa71b9SJerome Forissier         if( transform->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 )
97311fa71b9SJerome Forissier         {
97411fa71b9SJerome Forissier             /*
97511fa71b9SJerome Forissier              * Save IV in SSL3 and TLS1
97611fa71b9SJerome Forissier              */
97711fa71b9SJerome Forissier             memcpy( transform->iv_enc, transform->cipher_ctx_enc.iv,
97811fa71b9SJerome Forissier                     transform->ivlen );
97911fa71b9SJerome Forissier         }
98011fa71b9SJerome Forissier         else
98111fa71b9SJerome Forissier #endif
98211fa71b9SJerome Forissier         {
98311fa71b9SJerome Forissier             data             -= transform->ivlen;
98411fa71b9SJerome Forissier             rec->data_offset -= transform->ivlen;
98511fa71b9SJerome Forissier             rec->data_len    += transform->ivlen;
98611fa71b9SJerome Forissier         }
98711fa71b9SJerome Forissier 
98811fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
98911fa71b9SJerome Forissier         if( auth_done == 0 )
99011fa71b9SJerome Forissier         {
99111fa71b9SJerome Forissier             unsigned char mac[MBEDTLS_SSL_MAC_ADD];
99211fa71b9SJerome Forissier 
99311fa71b9SJerome Forissier             /*
99411fa71b9SJerome Forissier              * MAC(MAC_write_key, seq_num +
99511fa71b9SJerome Forissier              *     TLSCipherText.type +
99611fa71b9SJerome Forissier              *     TLSCipherText.version +
99711fa71b9SJerome Forissier              *     length_of( (IV +) ENC(...) ) +
99811fa71b9SJerome Forissier              *     IV + // except for TLS 1.0
99911fa71b9SJerome Forissier              *     ENC(content + padding + padding_length));
100011fa71b9SJerome Forissier              */
100111fa71b9SJerome Forissier 
100211fa71b9SJerome Forissier             if( post_avail < transform->maclen)
100311fa71b9SJerome Forissier             {
100411fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) );
100511fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
100611fa71b9SJerome Forissier             }
100711fa71b9SJerome Forissier 
1008*7901324dSJerome Forissier             ssl_extract_add_data_from_record( add_data, &add_data_len,
1009*7901324dSJerome Forissier                                               rec, transform->minor_ver );
101011fa71b9SJerome Forissier 
101111fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) );
101211fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", add_data,
101311fa71b9SJerome Forissier                                    add_data_len );
101411fa71b9SJerome Forissier 
101511fa71b9SJerome Forissier             mbedtls_md_hmac_update( &transform->md_ctx_enc, add_data,
101611fa71b9SJerome Forissier                                     add_data_len );
101711fa71b9SJerome Forissier             mbedtls_md_hmac_update( &transform->md_ctx_enc,
101811fa71b9SJerome Forissier                                     data, rec->data_len );
101911fa71b9SJerome Forissier             mbedtls_md_hmac_finish( &transform->md_ctx_enc, mac );
102011fa71b9SJerome Forissier             mbedtls_md_hmac_reset( &transform->md_ctx_enc );
102111fa71b9SJerome Forissier 
102211fa71b9SJerome Forissier             memcpy( data + rec->data_len, mac, transform->maclen );
102311fa71b9SJerome Forissier 
102411fa71b9SJerome Forissier             rec->data_len += transform->maclen;
102511fa71b9SJerome Forissier             post_avail -= transform->maclen;
102611fa71b9SJerome Forissier             auth_done++;
102711fa71b9SJerome Forissier         }
102811fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
102911fa71b9SJerome Forissier     }
103011fa71b9SJerome Forissier     else
1031*7901324dSJerome Forissier #endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC) */
103211fa71b9SJerome Forissier     {
103311fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
103411fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
103511fa71b9SJerome Forissier     }
103611fa71b9SJerome Forissier 
103711fa71b9SJerome Forissier     /* Make extra sure authentication was performed, exactly once */
103811fa71b9SJerome Forissier     if( auth_done != 1 )
103911fa71b9SJerome Forissier     {
104011fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
104111fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
104211fa71b9SJerome Forissier     }
104311fa71b9SJerome Forissier 
104411fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= encrypt buf" ) );
104511fa71b9SJerome Forissier 
104611fa71b9SJerome Forissier     return( 0 );
104711fa71b9SJerome Forissier }
104811fa71b9SJerome Forissier 
1049*7901324dSJerome Forissier #if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC)
1050*7901324dSJerome Forissier /*
1051*7901324dSJerome Forissier  * Turn a bit into a mask:
1052*7901324dSJerome Forissier  * - if bit == 1, return the all-bits 1 mask, aka (size_t) -1
1053*7901324dSJerome Forissier  * - if bit == 0, return the all-bits 0 mask, aka 0
1054*7901324dSJerome Forissier  *
1055*7901324dSJerome Forissier  * This function can be used to write constant-time code by replacing branches
1056*7901324dSJerome Forissier  * with bit operations using masks.
1057*7901324dSJerome Forissier  *
1058*7901324dSJerome Forissier  * This function is implemented without using comparison operators, as those
1059*7901324dSJerome Forissier  * might be translated to branches by some compilers on some platforms.
1060*7901324dSJerome Forissier  */
1061*7901324dSJerome Forissier static size_t mbedtls_ssl_cf_mask_from_bit( size_t bit )
1062*7901324dSJerome Forissier {
1063*7901324dSJerome Forissier     /* MSVC has a warning about unary minus on unsigned integer types,
1064*7901324dSJerome Forissier      * but this is well-defined and precisely what we want to do here. */
1065*7901324dSJerome Forissier #if defined(_MSC_VER)
1066*7901324dSJerome Forissier #pragma warning( push )
1067*7901324dSJerome Forissier #pragma warning( disable : 4146 )
1068*7901324dSJerome Forissier #endif
1069*7901324dSJerome Forissier     return -bit;
1070*7901324dSJerome Forissier #if defined(_MSC_VER)
1071*7901324dSJerome Forissier #pragma warning( pop )
1072*7901324dSJerome Forissier #endif
1073*7901324dSJerome Forissier }
1074*7901324dSJerome Forissier 
1075*7901324dSJerome Forissier /*
1076*7901324dSJerome Forissier  * Constant-flow mask generation for "less than" comparison:
1077*7901324dSJerome Forissier  * - if x < y,  return all bits 1, that is (size_t) -1
1078*7901324dSJerome Forissier  * - otherwise, return all bits 0, that is 0
1079*7901324dSJerome Forissier  *
1080*7901324dSJerome Forissier  * This function can be used to write constant-time code by replacing branches
1081*7901324dSJerome Forissier  * with bit operations using masks.
1082*7901324dSJerome Forissier  *
1083*7901324dSJerome Forissier  * This function is implemented without using comparison operators, as those
1084*7901324dSJerome Forissier  * might be translated to branches by some compilers on some platforms.
1085*7901324dSJerome Forissier  */
1086*7901324dSJerome Forissier static size_t mbedtls_ssl_cf_mask_lt( size_t x, size_t y )
1087*7901324dSJerome Forissier {
1088*7901324dSJerome Forissier     /* This has the most significant bit set if and only if x < y */
1089*7901324dSJerome Forissier     const size_t sub = x - y;
1090*7901324dSJerome Forissier 
1091*7901324dSJerome Forissier     /* sub1 = (x < y) ? 1 : 0 */
1092*7901324dSJerome Forissier     const size_t sub1 = sub >> ( sizeof( sub ) * 8 - 1 );
1093*7901324dSJerome Forissier 
1094*7901324dSJerome Forissier     /* mask = (x < y) ? 0xff... : 0x00... */
1095*7901324dSJerome Forissier     const size_t mask = mbedtls_ssl_cf_mask_from_bit( sub1 );
1096*7901324dSJerome Forissier 
1097*7901324dSJerome Forissier     return( mask );
1098*7901324dSJerome Forissier }
1099*7901324dSJerome Forissier 
1100*7901324dSJerome Forissier /*
1101*7901324dSJerome Forissier  * Constant-flow mask generation for "greater or equal" comparison:
1102*7901324dSJerome Forissier  * - if x >= y, return all bits 1, that is (size_t) -1
1103*7901324dSJerome Forissier  * - otherwise, return all bits 0, that is 0
1104*7901324dSJerome Forissier  *
1105*7901324dSJerome Forissier  * This function can be used to write constant-time code by replacing branches
1106*7901324dSJerome Forissier  * with bit operations using masks.
1107*7901324dSJerome Forissier  *
1108*7901324dSJerome Forissier  * This function is implemented without using comparison operators, as those
1109*7901324dSJerome Forissier  * might be translated to branches by some compilers on some platforms.
1110*7901324dSJerome Forissier  */
1111*7901324dSJerome Forissier static size_t mbedtls_ssl_cf_mask_ge( size_t x, size_t y )
1112*7901324dSJerome Forissier {
1113*7901324dSJerome Forissier     return( ~mbedtls_ssl_cf_mask_lt( x, y ) );
1114*7901324dSJerome Forissier }
1115*7901324dSJerome Forissier 
1116*7901324dSJerome Forissier /*
1117*7901324dSJerome Forissier  * Constant-flow boolean "equal" comparison:
1118*7901324dSJerome Forissier  * return x == y
1119*7901324dSJerome Forissier  *
1120*7901324dSJerome Forissier  * This function can be used to write constant-time code by replacing branches
1121*7901324dSJerome Forissier  * with bit operations - it can be used in conjunction with
1122*7901324dSJerome Forissier  * mbedtls_ssl_cf_mask_from_bit().
1123*7901324dSJerome Forissier  *
1124*7901324dSJerome Forissier  * This function is implemented without using comparison operators, as those
1125*7901324dSJerome Forissier  * might be translated to branches by some compilers on some platforms.
1126*7901324dSJerome Forissier  */
1127*7901324dSJerome Forissier static size_t mbedtls_ssl_cf_bool_eq( size_t x, size_t y )
1128*7901324dSJerome Forissier {
1129*7901324dSJerome Forissier     /* diff = 0 if x == y, non-zero otherwise */
1130*7901324dSJerome Forissier     const size_t diff = x ^ y;
1131*7901324dSJerome Forissier 
1132*7901324dSJerome Forissier     /* MSVC has a warning about unary minus on unsigned integer types,
1133*7901324dSJerome Forissier      * but this is well-defined and precisely what we want to do here. */
1134*7901324dSJerome Forissier #if defined(_MSC_VER)
1135*7901324dSJerome Forissier #pragma warning( push )
1136*7901324dSJerome Forissier #pragma warning( disable : 4146 )
1137*7901324dSJerome Forissier #endif
1138*7901324dSJerome Forissier 
1139*7901324dSJerome Forissier     /* diff_msb's most significant bit is equal to x != y */
1140*7901324dSJerome Forissier     const size_t diff_msb = ( diff | -diff );
1141*7901324dSJerome Forissier 
1142*7901324dSJerome Forissier #if defined(_MSC_VER)
1143*7901324dSJerome Forissier #pragma warning( pop )
1144*7901324dSJerome Forissier #endif
1145*7901324dSJerome Forissier 
1146*7901324dSJerome Forissier     /* diff1 = (x != y) ? 1 : 0 */
1147*7901324dSJerome Forissier     const size_t diff1 = diff_msb >> ( sizeof( diff_msb ) * 8 - 1 );
1148*7901324dSJerome Forissier 
1149*7901324dSJerome Forissier     return( 1 ^ diff1 );
1150*7901324dSJerome Forissier }
1151*7901324dSJerome Forissier 
1152*7901324dSJerome Forissier /*
1153*7901324dSJerome Forissier  * Constant-flow conditional memcpy:
1154*7901324dSJerome Forissier  *  - if c1 == c2, equivalent to memcpy(dst, src, len),
1155*7901324dSJerome Forissier  *  - otherwise, a no-op,
1156*7901324dSJerome Forissier  * but with execution flow independent of the values of c1 and c2.
1157*7901324dSJerome Forissier  *
1158*7901324dSJerome Forissier  * This function is implemented without using comparison operators, as those
1159*7901324dSJerome Forissier  * might be translated to branches by some compilers on some platforms.
1160*7901324dSJerome Forissier  */
1161*7901324dSJerome Forissier static void mbedtls_ssl_cf_memcpy_if_eq( unsigned char *dst,
1162*7901324dSJerome Forissier                                          const unsigned char *src,
1163*7901324dSJerome Forissier                                          size_t len,
1164*7901324dSJerome Forissier                                          size_t c1, size_t c2 )
1165*7901324dSJerome Forissier {
1166*7901324dSJerome Forissier     /* mask = c1 == c2 ? 0xff : 0x00 */
1167*7901324dSJerome Forissier     const size_t equal = mbedtls_ssl_cf_bool_eq( c1, c2 );
1168*7901324dSJerome Forissier     const unsigned char mask = (unsigned char) mbedtls_ssl_cf_mask_from_bit( equal );
1169*7901324dSJerome Forissier 
1170*7901324dSJerome Forissier     /* dst[i] = c1 == c2 ? src[i] : dst[i] */
1171*7901324dSJerome Forissier     for( size_t i = 0; i < len; i++ )
1172*7901324dSJerome Forissier         dst[i] = ( src[i] & mask ) | ( dst[i] & ~mask );
1173*7901324dSJerome Forissier }
1174*7901324dSJerome Forissier 
1175*7901324dSJerome Forissier /*
1176*7901324dSJerome Forissier  * Compute HMAC of variable-length data with constant flow.
1177*7901324dSJerome Forissier  *
1178*7901324dSJerome Forissier  * Only works with MD-5, SHA-1, SHA-256 and SHA-384.
1179*7901324dSJerome Forissier  * (Otherwise, computation of block_size needs to be adapted.)
1180*7901324dSJerome Forissier  */
1181*7901324dSJerome Forissier MBEDTLS_STATIC_TESTABLE int mbedtls_ssl_cf_hmac(
1182*7901324dSJerome Forissier         mbedtls_md_context_t *ctx,
1183*7901324dSJerome Forissier         const unsigned char *add_data, size_t add_data_len,
1184*7901324dSJerome Forissier         const unsigned char *data, size_t data_len_secret,
1185*7901324dSJerome Forissier         size_t min_data_len, size_t max_data_len,
1186*7901324dSJerome Forissier         unsigned char *output )
1187*7901324dSJerome Forissier {
1188*7901324dSJerome Forissier     /*
1189*7901324dSJerome Forissier      * This function breaks the HMAC abstraction and uses the md_clone()
1190*7901324dSJerome Forissier      * extension to the MD API in order to get constant-flow behaviour.
1191*7901324dSJerome Forissier      *
1192*7901324dSJerome Forissier      * HMAC(msg) is defined as HASH(okey + HASH(ikey + msg)) where + means
1193*7901324dSJerome Forissier      * concatenation, and okey/ikey are the XOR of the key with some fixed bit
1194*7901324dSJerome Forissier      * patterns (see RFC 2104, sec. 2), which are stored in ctx->hmac_ctx.
1195*7901324dSJerome Forissier      *
1196*7901324dSJerome Forissier      * We'll first compute inner_hash = HASH(ikey + msg) by hashing up to
1197*7901324dSJerome Forissier      * minlen, then cloning the context, and for each byte up to maxlen
1198*7901324dSJerome Forissier      * finishing up the hash computation, keeping only the correct result.
1199*7901324dSJerome Forissier      *
1200*7901324dSJerome Forissier      * Then we only need to compute HASH(okey + inner_hash) and we're done.
1201*7901324dSJerome Forissier      */
1202*7901324dSJerome Forissier     const mbedtls_md_type_t md_alg = mbedtls_md_get_type( ctx->md_info );
1203*7901324dSJerome Forissier     /* TLS 1.0-1.2 only support SHA-384, SHA-256, SHA-1, MD-5,
1204*7901324dSJerome Forissier      * all of which have the same block size except SHA-384. */
1205*7901324dSJerome Forissier     const size_t block_size = md_alg == MBEDTLS_MD_SHA384 ? 128 : 64;
1206*7901324dSJerome Forissier     const unsigned char * const ikey = ctx->hmac_ctx;
1207*7901324dSJerome Forissier     const unsigned char * const okey = ikey + block_size;
1208*7901324dSJerome Forissier     const size_t hash_size = mbedtls_md_get_size( ctx->md_info );
1209*7901324dSJerome Forissier 
1210*7901324dSJerome Forissier     unsigned char aux_out[MBEDTLS_MD_MAX_SIZE];
1211*7901324dSJerome Forissier     mbedtls_md_context_t aux;
1212*7901324dSJerome Forissier     size_t offset;
1213*7901324dSJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1214*7901324dSJerome Forissier 
1215*7901324dSJerome Forissier     mbedtls_md_init( &aux );
1216*7901324dSJerome Forissier 
1217*7901324dSJerome Forissier #define MD_CHK( func_call ) \
1218*7901324dSJerome Forissier     do {                    \
1219*7901324dSJerome Forissier         ret = (func_call);  \
1220*7901324dSJerome Forissier         if( ret != 0 )      \
1221*7901324dSJerome Forissier             goto cleanup;   \
1222*7901324dSJerome Forissier     } while( 0 )
1223*7901324dSJerome Forissier 
1224*7901324dSJerome Forissier     MD_CHK( mbedtls_md_setup( &aux, ctx->md_info, 0 ) );
1225*7901324dSJerome Forissier 
1226*7901324dSJerome Forissier     /* After hmac_start() of hmac_reset(), ikey has already been hashed,
1227*7901324dSJerome Forissier      * so we can start directly with the message */
1228*7901324dSJerome Forissier     MD_CHK( mbedtls_md_update( ctx, add_data, add_data_len ) );
1229*7901324dSJerome Forissier     MD_CHK( mbedtls_md_update( ctx, data, min_data_len ) );
1230*7901324dSJerome Forissier 
1231*7901324dSJerome Forissier     /* For each possible length, compute the hash up to that point */
1232*7901324dSJerome Forissier     for( offset = min_data_len; offset <= max_data_len; offset++ )
1233*7901324dSJerome Forissier     {
1234*7901324dSJerome Forissier         MD_CHK( mbedtls_md_clone( &aux, ctx ) );
1235*7901324dSJerome Forissier         MD_CHK( mbedtls_md_finish( &aux, aux_out ) );
1236*7901324dSJerome Forissier         /* Keep only the correct inner_hash in the output buffer */
1237*7901324dSJerome Forissier         mbedtls_ssl_cf_memcpy_if_eq( output, aux_out, hash_size,
1238*7901324dSJerome Forissier                                      offset, data_len_secret );
1239*7901324dSJerome Forissier 
1240*7901324dSJerome Forissier         if( offset < max_data_len )
1241*7901324dSJerome Forissier             MD_CHK( mbedtls_md_update( ctx, data + offset, 1 ) );
1242*7901324dSJerome Forissier     }
1243*7901324dSJerome Forissier 
1244*7901324dSJerome Forissier     /* The context needs to finish() before it starts() again */
1245*7901324dSJerome Forissier     MD_CHK( mbedtls_md_finish( ctx, aux_out ) );
1246*7901324dSJerome Forissier 
1247*7901324dSJerome Forissier     /* Now compute HASH(okey + inner_hash) */
1248*7901324dSJerome Forissier     MD_CHK( mbedtls_md_starts( ctx ) );
1249*7901324dSJerome Forissier     MD_CHK( mbedtls_md_update( ctx, okey, block_size ) );
1250*7901324dSJerome Forissier     MD_CHK( mbedtls_md_update( ctx, output, hash_size ) );
1251*7901324dSJerome Forissier     MD_CHK( mbedtls_md_finish( ctx, output ) );
1252*7901324dSJerome Forissier 
1253*7901324dSJerome Forissier     /* Done, get ready for next time */
1254*7901324dSJerome Forissier     MD_CHK( mbedtls_md_hmac_reset( ctx ) );
1255*7901324dSJerome Forissier 
1256*7901324dSJerome Forissier #undef MD_CHK
1257*7901324dSJerome Forissier 
1258*7901324dSJerome Forissier cleanup:
1259*7901324dSJerome Forissier     mbedtls_md_free( &aux );
1260*7901324dSJerome Forissier     return( ret );
1261*7901324dSJerome Forissier }
1262*7901324dSJerome Forissier 
1263*7901324dSJerome Forissier /*
1264*7901324dSJerome Forissier  * Constant-flow memcpy from variable position in buffer.
1265*7901324dSJerome Forissier  * - functionally equivalent to memcpy(dst, src + offset_secret, len)
1266*7901324dSJerome Forissier  * - but with execution flow independent from the value of offset_secret.
1267*7901324dSJerome Forissier  */
1268*7901324dSJerome Forissier MBEDTLS_STATIC_TESTABLE void mbedtls_ssl_cf_memcpy_offset(
1269*7901324dSJerome Forissier                                    unsigned char *dst,
1270*7901324dSJerome Forissier                                    const unsigned char *src_base,
1271*7901324dSJerome Forissier                                    size_t offset_secret,
1272*7901324dSJerome Forissier                                    size_t offset_min, size_t offset_max,
1273*7901324dSJerome Forissier                                    size_t len )
1274*7901324dSJerome Forissier {
1275*7901324dSJerome Forissier     size_t offset;
1276*7901324dSJerome Forissier 
1277*7901324dSJerome Forissier     for( offset = offset_min; offset <= offset_max; offset++ )
1278*7901324dSJerome Forissier     {
1279*7901324dSJerome Forissier         mbedtls_ssl_cf_memcpy_if_eq( dst, src_base + offset, len,
1280*7901324dSJerome Forissier                                      offset, offset_secret );
1281*7901324dSJerome Forissier     }
1282*7901324dSJerome Forissier }
1283*7901324dSJerome Forissier #endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */
1284*7901324dSJerome Forissier 
128511fa71b9SJerome Forissier int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl,
128611fa71b9SJerome Forissier                              mbedtls_ssl_transform *transform,
128711fa71b9SJerome Forissier                              mbedtls_record *rec )
128811fa71b9SJerome Forissier {
128911fa71b9SJerome Forissier     size_t olen;
129011fa71b9SJerome Forissier     mbedtls_cipher_mode_t mode;
129111fa71b9SJerome Forissier     int ret, auth_done = 0;
129211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
129311fa71b9SJerome Forissier     size_t padlen = 0, correct = 1;
129411fa71b9SJerome Forissier #endif
129511fa71b9SJerome Forissier     unsigned char* data;
129611fa71b9SJerome Forissier     unsigned char add_data[13 + 1 + MBEDTLS_SSL_CID_IN_LEN_MAX ];
129711fa71b9SJerome Forissier     size_t add_data_len;
129811fa71b9SJerome Forissier 
129911fa71b9SJerome Forissier #if !defined(MBEDTLS_DEBUG_C)
130011fa71b9SJerome Forissier     ssl = NULL; /* make sure we don't use it except for debug */
130111fa71b9SJerome Forissier     ((void) ssl);
130211fa71b9SJerome Forissier #endif
130311fa71b9SJerome Forissier 
130411fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decrypt buf" ) );
130511fa71b9SJerome Forissier     if( rec == NULL                     ||
130611fa71b9SJerome Forissier         rec->buf == NULL                ||
130711fa71b9SJerome Forissier         rec->buf_len < rec->data_offset ||
130811fa71b9SJerome Forissier         rec->buf_len - rec->data_offset < rec->data_len )
130911fa71b9SJerome Forissier     {
131011fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad record structure provided to decrypt_buf" ) );
131111fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
131211fa71b9SJerome Forissier     }
131311fa71b9SJerome Forissier 
131411fa71b9SJerome Forissier     data = rec->buf + rec->data_offset;
131511fa71b9SJerome Forissier     mode = mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_dec );
131611fa71b9SJerome Forissier 
131711fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
131811fa71b9SJerome Forissier     /*
131911fa71b9SJerome Forissier      * Match record's CID with incoming CID.
132011fa71b9SJerome Forissier      */
132111fa71b9SJerome Forissier     if( rec->cid_len != transform->in_cid_len ||
132211fa71b9SJerome Forissier         memcmp( rec->cid, transform->in_cid, rec->cid_len ) != 0 )
132311fa71b9SJerome Forissier     {
132411fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_UNEXPECTED_CID );
132511fa71b9SJerome Forissier     }
132611fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
132711fa71b9SJerome Forissier 
132811fa71b9SJerome Forissier #if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER)
132911fa71b9SJerome Forissier     if( mode == MBEDTLS_MODE_STREAM )
133011fa71b9SJerome Forissier     {
133111fa71b9SJerome Forissier         padlen = 0;
133211fa71b9SJerome Forissier         if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_dec,
133311fa71b9SJerome Forissier                                    transform->iv_dec,
133411fa71b9SJerome Forissier                                    transform->ivlen,
133511fa71b9SJerome Forissier                                    data, rec->data_len,
133611fa71b9SJerome Forissier                                    data, &olen ) ) != 0 )
133711fa71b9SJerome Forissier         {
133811fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret );
133911fa71b9SJerome Forissier             return( ret );
134011fa71b9SJerome Forissier         }
134111fa71b9SJerome Forissier 
134211fa71b9SJerome Forissier         if( rec->data_len != olen )
134311fa71b9SJerome Forissier         {
134411fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
134511fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
134611fa71b9SJerome Forissier         }
134711fa71b9SJerome Forissier     }
134811fa71b9SJerome Forissier     else
134911fa71b9SJerome Forissier #endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */
135011fa71b9SJerome Forissier #if defined(MBEDTLS_GCM_C) || \
135111fa71b9SJerome Forissier     defined(MBEDTLS_CCM_C) || \
135211fa71b9SJerome Forissier     defined(MBEDTLS_CHACHAPOLY_C)
135311fa71b9SJerome Forissier     if( mode == MBEDTLS_MODE_GCM ||
135411fa71b9SJerome Forissier         mode == MBEDTLS_MODE_CCM ||
135511fa71b9SJerome Forissier         mode == MBEDTLS_MODE_CHACHAPOLY )
135611fa71b9SJerome Forissier     {
135711fa71b9SJerome Forissier         unsigned char iv[12];
1358*7901324dSJerome Forissier         unsigned char *dynamic_iv;
1359*7901324dSJerome Forissier         size_t dynamic_iv_len;
136011fa71b9SJerome Forissier 
136111fa71b9SJerome Forissier         /*
1362*7901324dSJerome Forissier          * Extract dynamic part of nonce for AEAD decryption.
1363*7901324dSJerome Forissier          *
1364*7901324dSJerome Forissier          * Note: In the case of CCM and GCM in TLS 1.2, the dynamic
1365*7901324dSJerome Forissier          *       part of the IV is prepended to the ciphertext and
1366*7901324dSJerome Forissier          *       can be chosen freely - in particular, it need not
1367*7901324dSJerome Forissier          *       agree with the record sequence number.
136811fa71b9SJerome Forissier          */
1369*7901324dSJerome Forissier         dynamic_iv_len = sizeof( rec->ctr );
1370*7901324dSJerome Forissier         if( ssl_transform_aead_dynamic_iv_is_explicit( transform ) == 1 )
137111fa71b9SJerome Forissier         {
1372*7901324dSJerome Forissier             if( rec->data_len < dynamic_iv_len )
1373*7901324dSJerome Forissier             {
1374*7901324dSJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%" MBEDTLS_PRINTF_SIZET
1375*7901324dSJerome Forissier                                             " ) < explicit_iv_len (%" MBEDTLS_PRINTF_SIZET ") ",
1376*7901324dSJerome Forissier                                             rec->data_len,
1377*7901324dSJerome Forissier                                             dynamic_iv_len ) );
137811fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_INVALID_MAC );
137911fa71b9SJerome Forissier             }
1380*7901324dSJerome Forissier             dynamic_iv = data;
138111fa71b9SJerome Forissier 
1382*7901324dSJerome Forissier             data += dynamic_iv_len;
1383*7901324dSJerome Forissier             rec->data_offset += dynamic_iv_len;
1384*7901324dSJerome Forissier             rec->data_len    -= dynamic_iv_len;
138511fa71b9SJerome Forissier         }
138611fa71b9SJerome Forissier         else
138711fa71b9SJerome Forissier         {
1388*7901324dSJerome Forissier             dynamic_iv = rec->ctr;
138911fa71b9SJerome Forissier         }
139011fa71b9SJerome Forissier 
1391*7901324dSJerome Forissier         /* Check that there's space for the authentication tag. */
1392*7901324dSJerome Forissier         if( rec->data_len < transform->taglen )
1393*7901324dSJerome Forissier         {
1394*7901324dSJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%" MBEDTLS_PRINTF_SIZET
1395*7901324dSJerome Forissier                                         ") < taglen (%" MBEDTLS_PRINTF_SIZET ") ",
1396*7901324dSJerome Forissier                                         rec->data_len,
1397*7901324dSJerome Forissier                                         transform->taglen ) );
1398*7901324dSJerome Forissier             return( MBEDTLS_ERR_SSL_INVALID_MAC );
1399*7901324dSJerome Forissier         }
1400*7901324dSJerome Forissier         rec->data_len -= transform->taglen;
140111fa71b9SJerome Forissier 
1402*7901324dSJerome Forissier         /*
1403*7901324dSJerome Forissier          * Prepare nonce from dynamic and static parts.
1404*7901324dSJerome Forissier          */
1405*7901324dSJerome Forissier         ssl_build_record_nonce( iv, sizeof( iv ),
1406*7901324dSJerome Forissier                                 transform->iv_dec,
1407*7901324dSJerome Forissier                                 transform->fixed_ivlen,
1408*7901324dSJerome Forissier                                 dynamic_iv,
1409*7901324dSJerome Forissier                                 dynamic_iv_len );
1410*7901324dSJerome Forissier 
1411*7901324dSJerome Forissier         /*
1412*7901324dSJerome Forissier          * Build additional data for AEAD encryption.
1413*7901324dSJerome Forissier          * This depends on the TLS version.
1414*7901324dSJerome Forissier          */
1415*7901324dSJerome Forissier         ssl_extract_add_data_from_record( add_data, &add_data_len, rec,
1416*7901324dSJerome Forissier                                           transform->minor_ver );
141711fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD",
141811fa71b9SJerome Forissier                                add_data, add_data_len );
141911fa71b9SJerome Forissier 
142011fa71b9SJerome Forissier         /* Because of the check above, we know that there are
142111fa71b9SJerome Forissier          * explicit_iv_len Bytes preceeding data, and taglen
142211fa71b9SJerome Forissier          * bytes following data + data_len. This justifies
142311fa71b9SJerome Forissier          * the debug message and the invocation of
142411fa71b9SJerome Forissier          * mbedtls_cipher_auth_decrypt() below. */
142511fa71b9SJerome Forissier 
142611fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", iv, transform->ivlen );
142711fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_BUF( 4, "TAG used", data + rec->data_len,
142811fa71b9SJerome Forissier                                transform->taglen );
142911fa71b9SJerome Forissier 
143011fa71b9SJerome Forissier         /*
143111fa71b9SJerome Forissier          * Decrypt and authenticate
143211fa71b9SJerome Forissier          */
1433*7901324dSJerome Forissier         if( ( ret = mbedtls_cipher_auth_decrypt_ext( &transform->cipher_ctx_dec,
143411fa71b9SJerome Forissier                   iv, transform->ivlen,
143511fa71b9SJerome Forissier                   add_data, add_data_len,
1436*7901324dSJerome Forissier                   data, rec->data_len + transform->taglen,          /* src */
1437*7901324dSJerome Forissier                   data, rec->buf_len - (data - rec->buf), &olen,    /* dst */
143811fa71b9SJerome Forissier                   transform->taglen ) ) != 0 )
143911fa71b9SJerome Forissier         {
144011fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_decrypt", ret );
144111fa71b9SJerome Forissier 
144211fa71b9SJerome Forissier             if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED )
144311fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_INVALID_MAC );
144411fa71b9SJerome Forissier 
144511fa71b9SJerome Forissier             return( ret );
144611fa71b9SJerome Forissier         }
144711fa71b9SJerome Forissier         auth_done++;
144811fa71b9SJerome Forissier 
144911fa71b9SJerome Forissier         /* Double-check that AEAD decryption doesn't change content length. */
145011fa71b9SJerome Forissier         if( olen != rec->data_len )
145111fa71b9SJerome Forissier         {
145211fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
145311fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
145411fa71b9SJerome Forissier         }
145511fa71b9SJerome Forissier     }
145611fa71b9SJerome Forissier     else
145711fa71b9SJerome Forissier #endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */
1458*7901324dSJerome Forissier #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC)
145911fa71b9SJerome Forissier     if( mode == MBEDTLS_MODE_CBC )
146011fa71b9SJerome Forissier     {
146111fa71b9SJerome Forissier         size_t minlen = 0;
146211fa71b9SJerome Forissier 
146311fa71b9SJerome Forissier         /*
146411fa71b9SJerome Forissier          * Check immediate ciphertext sanity
146511fa71b9SJerome Forissier          */
146611fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)
146711fa71b9SJerome Forissier         if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
146811fa71b9SJerome Forissier         {
146911fa71b9SJerome Forissier             /* The ciphertext is prefixed with the CBC IV. */
147011fa71b9SJerome Forissier             minlen += transform->ivlen;
147111fa71b9SJerome Forissier         }
147211fa71b9SJerome Forissier #endif
147311fa71b9SJerome Forissier 
147411fa71b9SJerome Forissier         /* Size considerations:
147511fa71b9SJerome Forissier          *
147611fa71b9SJerome Forissier          * - The CBC cipher text must not be empty and hence
147711fa71b9SJerome Forissier          *   at least of size transform->ivlen.
147811fa71b9SJerome Forissier          *
147911fa71b9SJerome Forissier          * Together with the potential IV-prefix, this explains
148011fa71b9SJerome Forissier          * the first of the two checks below.
148111fa71b9SJerome Forissier          *
148211fa71b9SJerome Forissier          * - The record must contain a MAC, either in plain or
148311fa71b9SJerome Forissier          *   encrypted, depending on whether Encrypt-then-MAC
148411fa71b9SJerome Forissier          *   is used or not.
148511fa71b9SJerome Forissier          *   - If it is, the message contains the IV-prefix,
148611fa71b9SJerome Forissier          *     the CBC ciphertext, and the MAC.
148711fa71b9SJerome Forissier          *   - If it is not, the padded plaintext, and hence
148811fa71b9SJerome Forissier          *     the CBC ciphertext, has at least length maclen + 1
148911fa71b9SJerome Forissier          *     because there is at least the padding length byte.
149011fa71b9SJerome Forissier          *
149111fa71b9SJerome Forissier          * As the CBC ciphertext is not empty, both cases give the
149211fa71b9SJerome Forissier          * lower bound minlen + maclen + 1 on the record size, which
149311fa71b9SJerome Forissier          * we test for in the second check below.
149411fa71b9SJerome Forissier          */
149511fa71b9SJerome Forissier         if( rec->data_len < minlen + transform->ivlen ||
149611fa71b9SJerome Forissier             rec->data_len < minlen + transform->maclen + 1 )
149711fa71b9SJerome Forissier         {
1498*7901324dSJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%" MBEDTLS_PRINTF_SIZET
1499*7901324dSJerome Forissier                                         ") < max( ivlen(%" MBEDTLS_PRINTF_SIZET
1500*7901324dSJerome Forissier                                         "), maclen (%" MBEDTLS_PRINTF_SIZET ") "
150111fa71b9SJerome Forissier                                 "+ 1 ) ( + expl IV )", rec->data_len,
150211fa71b9SJerome Forissier                                 transform->ivlen,
150311fa71b9SJerome Forissier                                 transform->maclen ) );
150411fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INVALID_MAC );
150511fa71b9SJerome Forissier         }
150611fa71b9SJerome Forissier 
150711fa71b9SJerome Forissier         /*
150811fa71b9SJerome Forissier          * Authenticate before decrypt if enabled
150911fa71b9SJerome Forissier          */
151011fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
151111fa71b9SJerome Forissier         if( transform->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED )
151211fa71b9SJerome Forissier         {
151311fa71b9SJerome Forissier             unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD];
151411fa71b9SJerome Forissier 
151511fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) );
151611fa71b9SJerome Forissier 
151711fa71b9SJerome Forissier             /* Update data_len in tandem with add_data.
151811fa71b9SJerome Forissier              *
151911fa71b9SJerome Forissier              * The subtraction is safe because of the previous check
152011fa71b9SJerome Forissier              * data_len >= minlen + maclen + 1.
152111fa71b9SJerome Forissier              *
152211fa71b9SJerome Forissier              * Afterwards, we know that data + data_len is followed by at
152311fa71b9SJerome Forissier              * least maclen Bytes, which justifies the call to
152411fa71b9SJerome Forissier              * mbedtls_ssl_safer_memcmp() below.
152511fa71b9SJerome Forissier              *
152611fa71b9SJerome Forissier              * Further, we still know that data_len > minlen */
152711fa71b9SJerome Forissier             rec->data_len -= transform->maclen;
1528*7901324dSJerome Forissier             ssl_extract_add_data_from_record( add_data, &add_data_len, rec,
1529*7901324dSJerome Forissier                                               transform->minor_ver );
153011fa71b9SJerome Forissier 
153111fa71b9SJerome Forissier             /* Calculate expected MAC. */
153211fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", add_data,
153311fa71b9SJerome Forissier                                    add_data_len );
153411fa71b9SJerome Forissier             mbedtls_md_hmac_update( &transform->md_ctx_dec, add_data,
153511fa71b9SJerome Forissier                                     add_data_len );
153611fa71b9SJerome Forissier             mbedtls_md_hmac_update( &transform->md_ctx_dec,
153711fa71b9SJerome Forissier                                     data, rec->data_len );
153811fa71b9SJerome Forissier             mbedtls_md_hmac_finish( &transform->md_ctx_dec, mac_expect );
153911fa71b9SJerome Forissier             mbedtls_md_hmac_reset( &transform->md_ctx_dec );
154011fa71b9SJerome Forissier 
154111fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_BUF( 4, "message  mac", data + rec->data_len,
154211fa71b9SJerome Forissier                                    transform->maclen );
154311fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect,
154411fa71b9SJerome Forissier                                    transform->maclen );
154511fa71b9SJerome Forissier 
154611fa71b9SJerome Forissier             /* Compare expected MAC with MAC at the end of the record. */
154711fa71b9SJerome Forissier             if( mbedtls_ssl_safer_memcmp( data + rec->data_len, mac_expect,
154811fa71b9SJerome Forissier                                           transform->maclen ) != 0 )
154911fa71b9SJerome Forissier             {
155011fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) );
155111fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_INVALID_MAC );
155211fa71b9SJerome Forissier             }
155311fa71b9SJerome Forissier             auth_done++;
155411fa71b9SJerome Forissier         }
155511fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
155611fa71b9SJerome Forissier 
155711fa71b9SJerome Forissier         /*
155811fa71b9SJerome Forissier          * Check length sanity
155911fa71b9SJerome Forissier          */
156011fa71b9SJerome Forissier 
156111fa71b9SJerome Forissier         /* We know from above that data_len > minlen >= 0,
156211fa71b9SJerome Forissier          * so the following check in particular implies that
156311fa71b9SJerome Forissier          * data_len >= minlen + ivlen ( = minlen or 2 * minlen ). */
156411fa71b9SJerome Forissier         if( rec->data_len % transform->ivlen != 0 )
156511fa71b9SJerome Forissier         {
1566*7901324dSJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%" MBEDTLS_PRINTF_SIZET
1567*7901324dSJerome Forissier                                         ") %% ivlen (%" MBEDTLS_PRINTF_SIZET ") != 0",
156811fa71b9SJerome Forissier                                         rec->data_len, transform->ivlen ) );
156911fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INVALID_MAC );
157011fa71b9SJerome Forissier         }
157111fa71b9SJerome Forissier 
157211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)
157311fa71b9SJerome Forissier         /*
157411fa71b9SJerome Forissier          * Initialize for prepended IV for block cipher in TLS v1.1 and up
157511fa71b9SJerome Forissier          */
157611fa71b9SJerome Forissier         if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
157711fa71b9SJerome Forissier         {
157811fa71b9SJerome Forissier             /* Safe because data_len >= minlen + ivlen = 2 * ivlen. */
157911fa71b9SJerome Forissier             memcpy( transform->iv_dec, data, transform->ivlen );
158011fa71b9SJerome Forissier 
158111fa71b9SJerome Forissier             data += transform->ivlen;
158211fa71b9SJerome Forissier             rec->data_offset += transform->ivlen;
158311fa71b9SJerome Forissier             rec->data_len -= transform->ivlen;
158411fa71b9SJerome Forissier         }
158511fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */
158611fa71b9SJerome Forissier 
158711fa71b9SJerome Forissier         /* We still have data_len % ivlen == 0 and data_len >= ivlen here. */
158811fa71b9SJerome Forissier 
158911fa71b9SJerome Forissier         if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_dec,
159011fa71b9SJerome Forissier                                    transform->iv_dec, transform->ivlen,
159111fa71b9SJerome Forissier                                    data, rec->data_len, data, &olen ) ) != 0 )
159211fa71b9SJerome Forissier         {
159311fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret );
159411fa71b9SJerome Forissier             return( ret );
159511fa71b9SJerome Forissier         }
159611fa71b9SJerome Forissier 
159711fa71b9SJerome Forissier         /* Double-check that length hasn't changed during decryption. */
159811fa71b9SJerome Forissier         if( rec->data_len != olen )
159911fa71b9SJerome Forissier         {
160011fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
160111fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
160211fa71b9SJerome Forissier         }
160311fa71b9SJerome Forissier 
160411fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1)
160511fa71b9SJerome Forissier         if( transform->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 )
160611fa71b9SJerome Forissier         {
160711fa71b9SJerome Forissier             /*
160811fa71b9SJerome Forissier              * Save IV in SSL3 and TLS1, where CBC decryption of consecutive
160911fa71b9SJerome Forissier              * records is equivalent to CBC decryption of the concatenation
161011fa71b9SJerome Forissier              * of the records; in other words, IVs are maintained across
161111fa71b9SJerome Forissier              * record decryptions.
161211fa71b9SJerome Forissier              */
161311fa71b9SJerome Forissier             memcpy( transform->iv_dec, transform->cipher_ctx_dec.iv,
161411fa71b9SJerome Forissier                     transform->ivlen );
161511fa71b9SJerome Forissier         }
161611fa71b9SJerome Forissier #endif
161711fa71b9SJerome Forissier 
161811fa71b9SJerome Forissier         /* Safe since data_len >= minlen + maclen + 1, so after having
161911fa71b9SJerome Forissier          * subtracted at most minlen and maclen up to this point,
162011fa71b9SJerome Forissier          * data_len > 0 (because of data_len % ivlen == 0, it's actually
162111fa71b9SJerome Forissier          * >= ivlen ). */
162211fa71b9SJerome Forissier         padlen = data[rec->data_len - 1];
162311fa71b9SJerome Forissier 
162411fa71b9SJerome Forissier         if( auth_done == 1 )
162511fa71b9SJerome Forissier         {
1626*7901324dSJerome Forissier             const size_t mask = mbedtls_ssl_cf_mask_ge(
1627*7901324dSJerome Forissier                                 rec->data_len,
1628*7901324dSJerome Forissier                                 padlen + 1 );
1629*7901324dSJerome Forissier             correct &= mask;
1630*7901324dSJerome Forissier             padlen  &= mask;
163111fa71b9SJerome Forissier         }
163211fa71b9SJerome Forissier         else
163311fa71b9SJerome Forissier         {
163411fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DEBUG_ALL)
163511fa71b9SJerome Forissier             if( rec->data_len < transform->maclen + padlen + 1 )
163611fa71b9SJerome Forissier             {
1637*7901324dSJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%" MBEDTLS_PRINTF_SIZET
1638*7901324dSJerome Forissier                                             ") < maclen (%" MBEDTLS_PRINTF_SIZET
1639*7901324dSJerome Forissier                                             ") + padlen (%" MBEDTLS_PRINTF_SIZET ")",
164011fa71b9SJerome Forissier                                             rec->data_len,
164111fa71b9SJerome Forissier                                             transform->maclen,
164211fa71b9SJerome Forissier                                             padlen + 1 ) );
164311fa71b9SJerome Forissier             }
164411fa71b9SJerome Forissier #endif
164511fa71b9SJerome Forissier 
1646*7901324dSJerome Forissier             const size_t mask = mbedtls_ssl_cf_mask_ge(
1647*7901324dSJerome Forissier                                 rec->data_len,
1648*7901324dSJerome Forissier                                 transform->maclen + padlen + 1 );
1649*7901324dSJerome Forissier             correct &= mask;
1650*7901324dSJerome Forissier             padlen  &= mask;
165111fa71b9SJerome Forissier         }
165211fa71b9SJerome Forissier 
165311fa71b9SJerome Forissier         padlen++;
165411fa71b9SJerome Forissier 
165511fa71b9SJerome Forissier         /* Regardless of the validity of the padding,
165611fa71b9SJerome Forissier          * we have data_len >= padlen here. */
165711fa71b9SJerome Forissier 
165811fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_SSL3)
165911fa71b9SJerome Forissier         if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
166011fa71b9SJerome Forissier         {
1661*7901324dSJerome Forissier             /* This is the SSL 3.0 path, we don't have to worry about Lucky
1662*7901324dSJerome Forissier              * 13, because there's a strictly worse padding attack built in
1663*7901324dSJerome Forissier              * the protocol (known as part of POODLE), so we don't care if the
1664*7901324dSJerome Forissier              * code is not constant-time, in particular branches are OK. */
166511fa71b9SJerome Forissier             if( padlen > transform->ivlen )
166611fa71b9SJerome Forissier             {
166711fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DEBUG_ALL)
1668*7901324dSJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding length: is %" MBEDTLS_PRINTF_SIZET ", "
1669*7901324dSJerome Forissier                                             "should be no more than %" MBEDTLS_PRINTF_SIZET,
167011fa71b9SJerome Forissier                                             padlen, transform->ivlen ) );
167111fa71b9SJerome Forissier #endif
167211fa71b9SJerome Forissier                 correct = 0;
167311fa71b9SJerome Forissier             }
167411fa71b9SJerome Forissier         }
167511fa71b9SJerome Forissier         else
167611fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_SSL3 */
167711fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
167811fa71b9SJerome Forissier     defined(MBEDTLS_SSL_PROTO_TLS1_2)
167911fa71b9SJerome Forissier         if( transform->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0 )
168011fa71b9SJerome Forissier         {
168111fa71b9SJerome Forissier             /* The padding check involves a series of up to 256
168211fa71b9SJerome Forissier              * consecutive memory reads at the end of the record
168311fa71b9SJerome Forissier              * plaintext buffer. In order to hide the length and
168411fa71b9SJerome Forissier              * validity of the padding, always perform exactly
168511fa71b9SJerome Forissier              * `min(256,plaintext_len)` reads (but take into account
168611fa71b9SJerome Forissier              * only the last `padlen` bytes for the padding check). */
168711fa71b9SJerome Forissier             size_t pad_count = 0;
168811fa71b9SJerome Forissier             volatile unsigned char* const check = data;
168911fa71b9SJerome Forissier 
169011fa71b9SJerome Forissier             /* Index of first padding byte; it has been ensured above
169111fa71b9SJerome Forissier              * that the subtraction is safe. */
169211fa71b9SJerome Forissier             size_t const padding_idx = rec->data_len - padlen;
169311fa71b9SJerome Forissier             size_t const num_checks = rec->data_len <= 256 ? rec->data_len : 256;
169411fa71b9SJerome Forissier             size_t const start_idx = rec->data_len - num_checks;
169511fa71b9SJerome Forissier             size_t idx;
169611fa71b9SJerome Forissier 
169711fa71b9SJerome Forissier             for( idx = start_idx; idx < rec->data_len; idx++ )
169811fa71b9SJerome Forissier             {
1699*7901324dSJerome Forissier                 /* pad_count += (idx >= padding_idx) &&
1700*7901324dSJerome Forissier                  *              (check[idx] == padlen - 1);
1701*7901324dSJerome Forissier                  */
1702*7901324dSJerome Forissier                 const size_t mask = mbedtls_ssl_cf_mask_ge( idx, padding_idx );
1703*7901324dSJerome Forissier                 const size_t equal = mbedtls_ssl_cf_bool_eq( check[idx],
1704*7901324dSJerome Forissier                                                              padlen - 1 );
1705*7901324dSJerome Forissier                 pad_count += mask & equal;
170611fa71b9SJerome Forissier             }
1707*7901324dSJerome Forissier             correct &= mbedtls_ssl_cf_bool_eq( pad_count, padlen );
170811fa71b9SJerome Forissier 
170911fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DEBUG_ALL)
171011fa71b9SJerome Forissier             if( padlen > 0 && correct == 0 )
171111fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding byte detected" ) );
171211fa71b9SJerome Forissier #endif
1713*7901324dSJerome Forissier             padlen &= mbedtls_ssl_cf_mask_from_bit( correct );
171411fa71b9SJerome Forissier         }
171511fa71b9SJerome Forissier         else
171611fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
171711fa71b9SJerome Forissier           MBEDTLS_SSL_PROTO_TLS1_2 */
171811fa71b9SJerome Forissier         {
171911fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
172011fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
172111fa71b9SJerome Forissier         }
172211fa71b9SJerome Forissier 
172311fa71b9SJerome Forissier         /* If the padding was found to be invalid, padlen == 0
172411fa71b9SJerome Forissier          * and the subtraction is safe. If the padding was found valid,
172511fa71b9SJerome Forissier          * padlen hasn't been changed and the previous assertion
172611fa71b9SJerome Forissier          * data_len >= padlen still holds. */
172711fa71b9SJerome Forissier         rec->data_len -= padlen;
172811fa71b9SJerome Forissier     }
172911fa71b9SJerome Forissier     else
1730*7901324dSJerome Forissier #endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC */
173111fa71b9SJerome Forissier     {
173211fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
173311fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
173411fa71b9SJerome Forissier     }
173511fa71b9SJerome Forissier 
173611fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DEBUG_ALL)
173711fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_BUF( 4, "raw buffer after decryption",
173811fa71b9SJerome Forissier                            data, rec->data_len );
173911fa71b9SJerome Forissier #endif
174011fa71b9SJerome Forissier 
174111fa71b9SJerome Forissier     /*
174211fa71b9SJerome Forissier      * Authenticate if not done yet.
174311fa71b9SJerome Forissier      * Compute the MAC regardless of the padding result (RFC4346, CBCTIME).
174411fa71b9SJerome Forissier      */
174511fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
174611fa71b9SJerome Forissier     if( auth_done == 0 )
174711fa71b9SJerome Forissier     {
174811fa71b9SJerome Forissier         unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD];
1749*7901324dSJerome Forissier         unsigned char mac_peer[MBEDTLS_SSL_MAC_ADD];
175011fa71b9SJerome Forissier 
175111fa71b9SJerome Forissier         /* If the initial value of padlen was such that
175211fa71b9SJerome Forissier          * data_len < maclen + padlen + 1, then padlen
175311fa71b9SJerome Forissier          * got reset to 1, and the initial check
175411fa71b9SJerome Forissier          * data_len >= minlen + maclen + 1
175511fa71b9SJerome Forissier          * guarantees that at this point we still
175611fa71b9SJerome Forissier          * have at least data_len >= maclen.
175711fa71b9SJerome Forissier          *
175811fa71b9SJerome Forissier          * If the initial value of padlen was such that
175911fa71b9SJerome Forissier          * data_len >= maclen + padlen + 1, then we have
176011fa71b9SJerome Forissier          * subtracted either padlen + 1 (if the padding was correct)
176111fa71b9SJerome Forissier          * or 0 (if the padding was incorrect) since then,
176211fa71b9SJerome Forissier          * hence data_len >= maclen in any case.
176311fa71b9SJerome Forissier          */
176411fa71b9SJerome Forissier         rec->data_len -= transform->maclen;
1765*7901324dSJerome Forissier         ssl_extract_add_data_from_record( add_data, &add_data_len, rec,
1766*7901324dSJerome Forissier                                           transform->minor_ver );
176711fa71b9SJerome Forissier 
176811fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_SSL3)
176911fa71b9SJerome Forissier         if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
177011fa71b9SJerome Forissier         {
177111fa71b9SJerome Forissier             ssl_mac( &transform->md_ctx_dec,
177211fa71b9SJerome Forissier                      transform->mac_dec,
177311fa71b9SJerome Forissier                      data, rec->data_len,
177411fa71b9SJerome Forissier                      rec->ctr, rec->type,
177511fa71b9SJerome Forissier                      mac_expect );
1776*7901324dSJerome Forissier             memcpy( mac_peer, data + rec->data_len, transform->maclen );
177711fa71b9SJerome Forissier         }
177811fa71b9SJerome Forissier         else
177911fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_SSL3 */
178011fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
178111fa71b9SJerome Forissier         defined(MBEDTLS_SSL_PROTO_TLS1_2)
178211fa71b9SJerome Forissier         if( transform->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0 )
178311fa71b9SJerome Forissier         {
178411fa71b9SJerome Forissier             /*
178511fa71b9SJerome Forissier              * The next two sizes are the minimum and maximum values of
1786*7901324dSJerome Forissier              * data_len over all padlen values.
178711fa71b9SJerome Forissier              *
178811fa71b9SJerome Forissier              * They're independent of padlen, since we previously did
178911fa71b9SJerome Forissier              * data_len -= padlen.
179011fa71b9SJerome Forissier              *
179111fa71b9SJerome Forissier              * Note that max_len + maclen is never more than the buffer
179211fa71b9SJerome Forissier              * length, as we previously did in_msglen -= maclen too.
179311fa71b9SJerome Forissier              */
179411fa71b9SJerome Forissier             const size_t max_len = rec->data_len + padlen;
179511fa71b9SJerome Forissier             const size_t min_len = ( max_len > 256 ) ? max_len - 256 : 0;
179611fa71b9SJerome Forissier 
1797*7901324dSJerome Forissier             ret = mbedtls_ssl_cf_hmac( &transform->md_ctx_dec,
1798*7901324dSJerome Forissier                                        add_data, add_data_len,
1799*7901324dSJerome Forissier                                        data, rec->data_len, min_len, max_len,
1800*7901324dSJerome Forissier                                        mac_expect );
1801*7901324dSJerome Forissier             if( ret != 0 )
180211fa71b9SJerome Forissier             {
1803*7901324dSJerome Forissier                 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_cf_hmac", ret );
1804*7901324dSJerome Forissier                 return( ret );
180511fa71b9SJerome Forissier             }
180611fa71b9SJerome Forissier 
1807*7901324dSJerome Forissier             mbedtls_ssl_cf_memcpy_offset( mac_peer, data,
1808*7901324dSJerome Forissier                                           rec->data_len,
1809*7901324dSJerome Forissier                                           min_len, max_len,
1810*7901324dSJerome Forissier                                           transform->maclen );
181111fa71b9SJerome Forissier         }
181211fa71b9SJerome Forissier         else
181311fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
181411fa71b9SJerome Forissier               MBEDTLS_SSL_PROTO_TLS1_2 */
181511fa71b9SJerome Forissier         {
181611fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
181711fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
181811fa71b9SJerome Forissier         }
181911fa71b9SJerome Forissier 
182011fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DEBUG_ALL)
182111fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect, transform->maclen );
1822*7901324dSJerome Forissier         MBEDTLS_SSL_DEBUG_BUF( 4, "message  mac", mac_peer, transform->maclen );
182311fa71b9SJerome Forissier #endif
182411fa71b9SJerome Forissier 
1825*7901324dSJerome Forissier         if( mbedtls_ssl_safer_memcmp( mac_peer, mac_expect,
182611fa71b9SJerome Forissier                                       transform->maclen ) != 0 )
182711fa71b9SJerome Forissier         {
182811fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DEBUG_ALL)
182911fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) );
183011fa71b9SJerome Forissier #endif
183111fa71b9SJerome Forissier             correct = 0;
183211fa71b9SJerome Forissier         }
183311fa71b9SJerome Forissier         auth_done++;
183411fa71b9SJerome Forissier     }
183511fa71b9SJerome Forissier 
183611fa71b9SJerome Forissier     /*
183711fa71b9SJerome Forissier      * Finally check the correct flag
183811fa71b9SJerome Forissier      */
183911fa71b9SJerome Forissier     if( correct == 0 )
184011fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INVALID_MAC );
184111fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */
184211fa71b9SJerome Forissier 
184311fa71b9SJerome Forissier     /* Make extra sure authentication was performed, exactly once */
184411fa71b9SJerome Forissier     if( auth_done != 1 )
184511fa71b9SJerome Forissier     {
184611fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
184711fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
184811fa71b9SJerome Forissier     }
184911fa71b9SJerome Forissier 
1850*7901324dSJerome Forissier #if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
1851*7901324dSJerome Forissier     if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_4 )
1852*7901324dSJerome Forissier     {
1853*7901324dSJerome Forissier         /* Remove inner padding and infer true content type. */
1854*7901324dSJerome Forissier         ret = ssl_parse_inner_plaintext( data, &rec->data_len,
1855*7901324dSJerome Forissier                                          &rec->type );
1856*7901324dSJerome Forissier 
1857*7901324dSJerome Forissier         if( ret != 0 )
1858*7901324dSJerome Forissier             return( MBEDTLS_ERR_SSL_INVALID_RECORD );
1859*7901324dSJerome Forissier     }
1860*7901324dSJerome Forissier #endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
1861*7901324dSJerome Forissier 
186211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
186311fa71b9SJerome Forissier     if( rec->cid_len != 0 )
186411fa71b9SJerome Forissier     {
1865*7901324dSJerome Forissier         ret = ssl_parse_inner_plaintext( data, &rec->data_len,
186611fa71b9SJerome Forissier                                          &rec->type );
186711fa71b9SJerome Forissier         if( ret != 0 )
186811fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INVALID_RECORD );
186911fa71b9SJerome Forissier     }
187011fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
187111fa71b9SJerome Forissier 
187211fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= decrypt buf" ) );
187311fa71b9SJerome Forissier 
187411fa71b9SJerome Forissier     return( 0 );
187511fa71b9SJerome Forissier }
187611fa71b9SJerome Forissier 
187711fa71b9SJerome Forissier #undef MAC_NONE
187811fa71b9SJerome Forissier #undef MAC_PLAINTEXT
187911fa71b9SJerome Forissier #undef MAC_CIPHERTEXT
188011fa71b9SJerome Forissier 
188111fa71b9SJerome Forissier #if defined(MBEDTLS_ZLIB_SUPPORT)
188211fa71b9SJerome Forissier /*
188311fa71b9SJerome Forissier  * Compression/decompression functions
188411fa71b9SJerome Forissier  */
188511fa71b9SJerome Forissier static int ssl_compress_buf( mbedtls_ssl_context *ssl )
188611fa71b9SJerome Forissier {
188711fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
188811fa71b9SJerome Forissier     unsigned char *msg_post = ssl->out_msg;
188911fa71b9SJerome Forissier     ptrdiff_t bytes_written = ssl->out_msg - ssl->out_buf;
189011fa71b9SJerome Forissier     size_t len_pre = ssl->out_msglen;
189111fa71b9SJerome Forissier     unsigned char *msg_pre = ssl->compress_buf;
189211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
189311fa71b9SJerome Forissier     size_t out_buf_len = ssl->out_buf_len;
189411fa71b9SJerome Forissier #else
189511fa71b9SJerome Forissier     size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN;
189611fa71b9SJerome Forissier #endif
189711fa71b9SJerome Forissier 
189811fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> compress buf" ) );
189911fa71b9SJerome Forissier 
190011fa71b9SJerome Forissier     if( len_pre == 0 )
190111fa71b9SJerome Forissier         return( 0 );
190211fa71b9SJerome Forissier 
190311fa71b9SJerome Forissier     memcpy( msg_pre, ssl->out_msg, len_pre );
190411fa71b9SJerome Forissier 
1905*7901324dSJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 3, ( "before compression: msglen = %" MBEDTLS_PRINTF_SIZET ", ",
190611fa71b9SJerome Forissier                    ssl->out_msglen ) );
190711fa71b9SJerome Forissier 
190811fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_BUF( 4, "before compression: output payload",
190911fa71b9SJerome Forissier                    ssl->out_msg, ssl->out_msglen );
191011fa71b9SJerome Forissier 
191111fa71b9SJerome Forissier     ssl->transform_out->ctx_deflate.next_in = msg_pre;
191211fa71b9SJerome Forissier     ssl->transform_out->ctx_deflate.avail_in = len_pre;
191311fa71b9SJerome Forissier     ssl->transform_out->ctx_deflate.next_out = msg_post;
191411fa71b9SJerome Forissier     ssl->transform_out->ctx_deflate.avail_out = out_buf_len - bytes_written;
191511fa71b9SJerome Forissier 
191611fa71b9SJerome Forissier     ret = deflate( &ssl->transform_out->ctx_deflate, Z_SYNC_FLUSH );
191711fa71b9SJerome Forissier     if( ret != Z_OK )
191811fa71b9SJerome Forissier     {
191911fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "failed to perform compression (%d)", ret ) );
192011fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED );
192111fa71b9SJerome Forissier     }
192211fa71b9SJerome Forissier 
192311fa71b9SJerome Forissier     ssl->out_msglen = out_buf_len -
192411fa71b9SJerome Forissier                       ssl->transform_out->ctx_deflate.avail_out - bytes_written;
192511fa71b9SJerome Forissier 
1926*7901324dSJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 3, ( "after compression: msglen = %" MBEDTLS_PRINTF_SIZET ", ",
192711fa71b9SJerome Forissier                    ssl->out_msglen ) );
192811fa71b9SJerome Forissier 
192911fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_BUF( 4, "after compression: output payload",
193011fa71b9SJerome Forissier                    ssl->out_msg, ssl->out_msglen );
193111fa71b9SJerome Forissier 
193211fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= compress buf" ) );
193311fa71b9SJerome Forissier 
193411fa71b9SJerome Forissier     return( 0 );
193511fa71b9SJerome Forissier }
193611fa71b9SJerome Forissier 
193711fa71b9SJerome Forissier static int ssl_decompress_buf( mbedtls_ssl_context *ssl )
193811fa71b9SJerome Forissier {
193911fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
194011fa71b9SJerome Forissier     unsigned char *msg_post = ssl->in_msg;
194111fa71b9SJerome Forissier     ptrdiff_t header_bytes = ssl->in_msg - ssl->in_buf;
194211fa71b9SJerome Forissier     size_t len_pre = ssl->in_msglen;
194311fa71b9SJerome Forissier     unsigned char *msg_pre = ssl->compress_buf;
194411fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
194511fa71b9SJerome Forissier     size_t in_buf_len = ssl->in_buf_len;
194611fa71b9SJerome Forissier #else
194711fa71b9SJerome Forissier     size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN;
194811fa71b9SJerome Forissier #endif
194911fa71b9SJerome Forissier 
195011fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decompress buf" ) );
195111fa71b9SJerome Forissier 
195211fa71b9SJerome Forissier     if( len_pre == 0 )
195311fa71b9SJerome Forissier         return( 0 );
195411fa71b9SJerome Forissier 
195511fa71b9SJerome Forissier     memcpy( msg_pre, ssl->in_msg, len_pre );
195611fa71b9SJerome Forissier 
1957*7901324dSJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 3, ( "before decompression: msglen = %" MBEDTLS_PRINTF_SIZET ", ",
195811fa71b9SJerome Forissier                    ssl->in_msglen ) );
195911fa71b9SJerome Forissier 
196011fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_BUF( 4, "before decompression: input payload",
196111fa71b9SJerome Forissier                    ssl->in_msg, ssl->in_msglen );
196211fa71b9SJerome Forissier 
196311fa71b9SJerome Forissier     ssl->transform_in->ctx_inflate.next_in = msg_pre;
196411fa71b9SJerome Forissier     ssl->transform_in->ctx_inflate.avail_in = len_pre;
196511fa71b9SJerome Forissier     ssl->transform_in->ctx_inflate.next_out = msg_post;
196611fa71b9SJerome Forissier     ssl->transform_in->ctx_inflate.avail_out = in_buf_len - header_bytes;
196711fa71b9SJerome Forissier 
196811fa71b9SJerome Forissier     ret = inflate( &ssl->transform_in->ctx_inflate, Z_SYNC_FLUSH );
196911fa71b9SJerome Forissier     if( ret != Z_OK )
197011fa71b9SJerome Forissier     {
197111fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "failed to perform decompression (%d)", ret ) );
197211fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED );
197311fa71b9SJerome Forissier     }
197411fa71b9SJerome Forissier 
197511fa71b9SJerome Forissier     ssl->in_msglen = in_buf_len -
197611fa71b9SJerome Forissier                      ssl->transform_in->ctx_inflate.avail_out - header_bytes;
197711fa71b9SJerome Forissier 
1978*7901324dSJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 3, ( "after decompression: msglen = %" MBEDTLS_PRINTF_SIZET ", ",
197911fa71b9SJerome Forissier                    ssl->in_msglen ) );
198011fa71b9SJerome Forissier 
198111fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_BUF( 4, "after decompression: input payload",
198211fa71b9SJerome Forissier                    ssl->in_msg, ssl->in_msglen );
198311fa71b9SJerome Forissier 
198411fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= decompress buf" ) );
198511fa71b9SJerome Forissier 
198611fa71b9SJerome Forissier     return( 0 );
198711fa71b9SJerome Forissier }
198811fa71b9SJerome Forissier #endif /* MBEDTLS_ZLIB_SUPPORT */
198911fa71b9SJerome Forissier 
199011fa71b9SJerome Forissier /*
199111fa71b9SJerome Forissier  * Fill the input message buffer by appending data to it.
199211fa71b9SJerome Forissier  * The amount of data already fetched is in ssl->in_left.
199311fa71b9SJerome Forissier  *
199411fa71b9SJerome Forissier  * If we return 0, is it guaranteed that (at least) nb_want bytes are
199511fa71b9SJerome Forissier  * available (from this read and/or a previous one). Otherwise, an error code
199611fa71b9SJerome Forissier  * is returned (possibly EOF or WANT_READ).
199711fa71b9SJerome Forissier  *
199811fa71b9SJerome Forissier  * With stream transport (TLS) on success ssl->in_left == nb_want, but
199911fa71b9SJerome Forissier  * with datagram transport (DTLS) on success ssl->in_left >= nb_want,
200011fa71b9SJerome Forissier  * since we always read a whole datagram at once.
200111fa71b9SJerome Forissier  *
200211fa71b9SJerome Forissier  * For DTLS, it is up to the caller to set ssl->next_record_offset when
200311fa71b9SJerome Forissier  * they're done reading a record.
200411fa71b9SJerome Forissier  */
200511fa71b9SJerome Forissier int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want )
200611fa71b9SJerome Forissier {
200711fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
200811fa71b9SJerome Forissier     size_t len;
200911fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
201011fa71b9SJerome Forissier     size_t in_buf_len = ssl->in_buf_len;
201111fa71b9SJerome Forissier #else
201211fa71b9SJerome Forissier     size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN;
201311fa71b9SJerome Forissier #endif
201411fa71b9SJerome Forissier 
201511fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> fetch input" ) );
201611fa71b9SJerome Forissier 
201711fa71b9SJerome Forissier     if( ssl->f_recv == NULL && ssl->f_recv_timeout == NULL )
201811fa71b9SJerome Forissier     {
201911fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() "
202011fa71b9SJerome Forissier                             "or mbedtls_ssl_set_bio()" ) );
202111fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
202211fa71b9SJerome Forissier     }
202311fa71b9SJerome Forissier 
202411fa71b9SJerome Forissier     if( nb_want > in_buf_len - (size_t)( ssl->in_hdr - ssl->in_buf ) )
202511fa71b9SJerome Forissier     {
202611fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "requesting more data than fits" ) );
202711fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
202811fa71b9SJerome Forissier     }
202911fa71b9SJerome Forissier 
203011fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
203111fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
203211fa71b9SJerome Forissier     {
203311fa71b9SJerome Forissier         uint32_t timeout;
203411fa71b9SJerome Forissier 
203511fa71b9SJerome Forissier         /*
203611fa71b9SJerome Forissier          * The point is, we need to always read a full datagram at once, so we
203711fa71b9SJerome Forissier          * sometimes read more then requested, and handle the additional data.
203811fa71b9SJerome Forissier          * It could be the rest of the current record (while fetching the
203911fa71b9SJerome Forissier          * header) and/or some other records in the same datagram.
204011fa71b9SJerome Forissier          */
204111fa71b9SJerome Forissier 
204211fa71b9SJerome Forissier         /*
204311fa71b9SJerome Forissier          * Move to the next record in the already read datagram if applicable
204411fa71b9SJerome Forissier          */
204511fa71b9SJerome Forissier         if( ssl->next_record_offset != 0 )
204611fa71b9SJerome Forissier         {
204711fa71b9SJerome Forissier             if( ssl->in_left < ssl->next_record_offset )
204811fa71b9SJerome Forissier             {
204911fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
205011fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
205111fa71b9SJerome Forissier             }
205211fa71b9SJerome Forissier 
205311fa71b9SJerome Forissier             ssl->in_left -= ssl->next_record_offset;
205411fa71b9SJerome Forissier 
205511fa71b9SJerome Forissier             if( ssl->in_left != 0 )
205611fa71b9SJerome Forissier             {
2057*7901324dSJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 2, ( "next record in same datagram, offset: %"
2058*7901324dSJerome Forissier                                             MBEDTLS_PRINTF_SIZET,
205911fa71b9SJerome Forissier                                     ssl->next_record_offset ) );
206011fa71b9SJerome Forissier                 memmove( ssl->in_hdr,
206111fa71b9SJerome Forissier                          ssl->in_hdr + ssl->next_record_offset,
206211fa71b9SJerome Forissier                          ssl->in_left );
206311fa71b9SJerome Forissier             }
206411fa71b9SJerome Forissier 
206511fa71b9SJerome Forissier             ssl->next_record_offset = 0;
206611fa71b9SJerome Forissier         }
206711fa71b9SJerome Forissier 
2068*7901324dSJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %" MBEDTLS_PRINTF_SIZET
2069*7901324dSJerome Forissier                                     ", nb_want: %" MBEDTLS_PRINTF_SIZET,
207011fa71b9SJerome Forissier                        ssl->in_left, nb_want ) );
207111fa71b9SJerome Forissier 
207211fa71b9SJerome Forissier         /*
207311fa71b9SJerome Forissier          * Done if we already have enough data.
207411fa71b9SJerome Forissier          */
207511fa71b9SJerome Forissier         if( nb_want <= ssl->in_left)
207611fa71b9SJerome Forissier         {
207711fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) );
207811fa71b9SJerome Forissier             return( 0 );
207911fa71b9SJerome Forissier         }
208011fa71b9SJerome Forissier 
208111fa71b9SJerome Forissier         /*
208211fa71b9SJerome Forissier          * A record can't be split across datagrams. If we need to read but
208311fa71b9SJerome Forissier          * are not at the beginning of a new record, the caller did something
208411fa71b9SJerome Forissier          * wrong.
208511fa71b9SJerome Forissier          */
208611fa71b9SJerome Forissier         if( ssl->in_left != 0 )
208711fa71b9SJerome Forissier         {
208811fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
208911fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
209011fa71b9SJerome Forissier         }
209111fa71b9SJerome Forissier 
209211fa71b9SJerome Forissier         /*
209311fa71b9SJerome Forissier          * Don't even try to read if time's out already.
209411fa71b9SJerome Forissier          * This avoids by-passing the timer when repeatedly receiving messages
209511fa71b9SJerome Forissier          * that will end up being dropped.
209611fa71b9SJerome Forissier          */
209711fa71b9SJerome Forissier         if( mbedtls_ssl_check_timer( ssl ) != 0 )
209811fa71b9SJerome Forissier         {
209911fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 2, ( "timer has expired" ) );
210011fa71b9SJerome Forissier             ret = MBEDTLS_ERR_SSL_TIMEOUT;
210111fa71b9SJerome Forissier         }
210211fa71b9SJerome Forissier         else
210311fa71b9SJerome Forissier         {
210411fa71b9SJerome Forissier             len = in_buf_len - ( ssl->in_hdr - ssl->in_buf );
210511fa71b9SJerome Forissier 
210611fa71b9SJerome Forissier             if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
210711fa71b9SJerome Forissier                 timeout = ssl->handshake->retransmit_timeout;
210811fa71b9SJerome Forissier             else
210911fa71b9SJerome Forissier                 timeout = ssl->conf->read_timeout;
211011fa71b9SJerome Forissier 
2111*7901324dSJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 3, ( "f_recv_timeout: %lu ms", (unsigned long) timeout ) );
211211fa71b9SJerome Forissier 
211311fa71b9SJerome Forissier             if( ssl->f_recv_timeout != NULL )
211411fa71b9SJerome Forissier                 ret = ssl->f_recv_timeout( ssl->p_bio, ssl->in_hdr, len,
211511fa71b9SJerome Forissier                                                                     timeout );
211611fa71b9SJerome Forissier             else
211711fa71b9SJerome Forissier                 ret = ssl->f_recv( ssl->p_bio, ssl->in_hdr, len );
211811fa71b9SJerome Forissier 
211911fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret );
212011fa71b9SJerome Forissier 
212111fa71b9SJerome Forissier             if( ret == 0 )
212211fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_CONN_EOF );
212311fa71b9SJerome Forissier         }
212411fa71b9SJerome Forissier 
212511fa71b9SJerome Forissier         if( ret == MBEDTLS_ERR_SSL_TIMEOUT )
212611fa71b9SJerome Forissier         {
212711fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 2, ( "timeout" ) );
212811fa71b9SJerome Forissier             mbedtls_ssl_set_timer( ssl, 0 );
212911fa71b9SJerome Forissier 
213011fa71b9SJerome Forissier             if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
213111fa71b9SJerome Forissier             {
213211fa71b9SJerome Forissier                 if( ssl_double_retransmit_timeout( ssl ) != 0 )
213311fa71b9SJerome Forissier                 {
213411fa71b9SJerome Forissier                     MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake timeout" ) );
213511fa71b9SJerome Forissier                     return( MBEDTLS_ERR_SSL_TIMEOUT );
213611fa71b9SJerome Forissier                 }
213711fa71b9SJerome Forissier 
213811fa71b9SJerome Forissier                 if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 )
213911fa71b9SJerome Forissier                 {
214011fa71b9SJerome Forissier                     MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret );
214111fa71b9SJerome Forissier                     return( ret );
214211fa71b9SJerome Forissier                 }
214311fa71b9SJerome Forissier 
214411fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_WANT_READ );
214511fa71b9SJerome Forissier             }
214611fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION)
214711fa71b9SJerome Forissier             else if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
214811fa71b9SJerome Forissier                      ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING )
214911fa71b9SJerome Forissier             {
215011fa71b9SJerome Forissier                 if( ( ret = mbedtls_ssl_resend_hello_request( ssl ) ) != 0 )
215111fa71b9SJerome Forissier                 {
215211fa71b9SJerome Forissier                     MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend_hello_request",
215311fa71b9SJerome Forissier                                            ret );
215411fa71b9SJerome Forissier                     return( ret );
215511fa71b9SJerome Forissier                 }
215611fa71b9SJerome Forissier 
215711fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_WANT_READ );
215811fa71b9SJerome Forissier             }
215911fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */
216011fa71b9SJerome Forissier         }
216111fa71b9SJerome Forissier 
216211fa71b9SJerome Forissier         if( ret < 0 )
216311fa71b9SJerome Forissier             return( ret );
216411fa71b9SJerome Forissier 
216511fa71b9SJerome Forissier         ssl->in_left = ret;
216611fa71b9SJerome Forissier     }
216711fa71b9SJerome Forissier     else
216811fa71b9SJerome Forissier #endif
216911fa71b9SJerome Forissier     {
2170*7901324dSJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %" MBEDTLS_PRINTF_SIZET
2171*7901324dSJerome Forissier                                     ", nb_want: %" MBEDTLS_PRINTF_SIZET,
217211fa71b9SJerome Forissier                        ssl->in_left, nb_want ) );
217311fa71b9SJerome Forissier 
217411fa71b9SJerome Forissier         while( ssl->in_left < nb_want )
217511fa71b9SJerome Forissier         {
217611fa71b9SJerome Forissier             len = nb_want - ssl->in_left;
217711fa71b9SJerome Forissier 
217811fa71b9SJerome Forissier             if( mbedtls_ssl_check_timer( ssl ) != 0 )
217911fa71b9SJerome Forissier                 ret = MBEDTLS_ERR_SSL_TIMEOUT;
218011fa71b9SJerome Forissier             else
218111fa71b9SJerome Forissier             {
218211fa71b9SJerome Forissier                 if( ssl->f_recv_timeout != NULL )
218311fa71b9SJerome Forissier                 {
218411fa71b9SJerome Forissier                     ret = ssl->f_recv_timeout( ssl->p_bio,
218511fa71b9SJerome Forissier                                                ssl->in_hdr + ssl->in_left, len,
218611fa71b9SJerome Forissier                                                ssl->conf->read_timeout );
218711fa71b9SJerome Forissier                 }
218811fa71b9SJerome Forissier                 else
218911fa71b9SJerome Forissier                 {
219011fa71b9SJerome Forissier                     ret = ssl->f_recv( ssl->p_bio,
219111fa71b9SJerome Forissier                                        ssl->in_hdr + ssl->in_left, len );
219211fa71b9SJerome Forissier                 }
219311fa71b9SJerome Forissier             }
219411fa71b9SJerome Forissier 
2195*7901324dSJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %" MBEDTLS_PRINTF_SIZET
2196*7901324dSJerome Forissier                                         ", nb_want: %" MBEDTLS_PRINTF_SIZET,
219711fa71b9SJerome Forissier                                         ssl->in_left, nb_want ) );
219811fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret );
219911fa71b9SJerome Forissier 
220011fa71b9SJerome Forissier             if( ret == 0 )
220111fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_CONN_EOF );
220211fa71b9SJerome Forissier 
220311fa71b9SJerome Forissier             if( ret < 0 )
220411fa71b9SJerome Forissier                 return( ret );
220511fa71b9SJerome Forissier 
2206*7901324dSJerome Forissier             if ( (size_t)ret > len || ( INT_MAX > SIZE_MAX && ret > (int)SIZE_MAX ) )
220711fa71b9SJerome Forissier             {
220811fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1,
2209*7901324dSJerome Forissier                     ( "f_recv returned %d bytes but only %" MBEDTLS_PRINTF_SIZET " were requested",
2210*7901324dSJerome Forissier                     ret, len ) );
221111fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
221211fa71b9SJerome Forissier             }
221311fa71b9SJerome Forissier 
221411fa71b9SJerome Forissier             ssl->in_left += ret;
221511fa71b9SJerome Forissier         }
221611fa71b9SJerome Forissier     }
221711fa71b9SJerome Forissier 
221811fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) );
221911fa71b9SJerome Forissier 
222011fa71b9SJerome Forissier     return( 0 );
222111fa71b9SJerome Forissier }
222211fa71b9SJerome Forissier 
222311fa71b9SJerome Forissier /*
222411fa71b9SJerome Forissier  * Flush any data not yet written
222511fa71b9SJerome Forissier  */
222611fa71b9SJerome Forissier int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl )
222711fa71b9SJerome Forissier {
222811fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
222911fa71b9SJerome Forissier     unsigned char *buf;
223011fa71b9SJerome Forissier 
223111fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> flush output" ) );
223211fa71b9SJerome Forissier 
223311fa71b9SJerome Forissier     if( ssl->f_send == NULL )
223411fa71b9SJerome Forissier     {
223511fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() "
223611fa71b9SJerome Forissier                             "or mbedtls_ssl_set_bio()" ) );
223711fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
223811fa71b9SJerome Forissier     }
223911fa71b9SJerome Forissier 
224011fa71b9SJerome Forissier     /* Avoid incrementing counter if data is flushed */
224111fa71b9SJerome Forissier     if( ssl->out_left == 0 )
224211fa71b9SJerome Forissier     {
224311fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) );
224411fa71b9SJerome Forissier         return( 0 );
224511fa71b9SJerome Forissier     }
224611fa71b9SJerome Forissier 
224711fa71b9SJerome Forissier     while( ssl->out_left > 0 )
224811fa71b9SJerome Forissier     {
2249*7901324dSJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 2, ( "message length: %" MBEDTLS_PRINTF_SIZET
2250*7901324dSJerome Forissier                                     ", out_left: %" MBEDTLS_PRINTF_SIZET,
225111fa71b9SJerome Forissier                        mbedtls_ssl_out_hdr_len( ssl ) + ssl->out_msglen, ssl->out_left ) );
225211fa71b9SJerome Forissier 
225311fa71b9SJerome Forissier         buf = ssl->out_hdr - ssl->out_left;
225411fa71b9SJerome Forissier         ret = ssl->f_send( ssl->p_bio, buf, ssl->out_left );
225511fa71b9SJerome Forissier 
225611fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_send", ret );
225711fa71b9SJerome Forissier 
225811fa71b9SJerome Forissier         if( ret <= 0 )
225911fa71b9SJerome Forissier             return( ret );
226011fa71b9SJerome Forissier 
2261*7901324dSJerome Forissier         if( (size_t)ret > ssl->out_left || ( INT_MAX > SIZE_MAX && ret > (int)SIZE_MAX ) )
226211fa71b9SJerome Forissier         {
226311fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1,
2264*7901324dSJerome Forissier                 ( "f_send returned %d bytes but only %" MBEDTLS_PRINTF_SIZET " bytes were sent",
2265*7901324dSJerome Forissier                 ret, ssl->out_left ) );
226611fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
226711fa71b9SJerome Forissier         }
226811fa71b9SJerome Forissier 
226911fa71b9SJerome Forissier         ssl->out_left -= ret;
227011fa71b9SJerome Forissier     }
227111fa71b9SJerome Forissier 
227211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
227311fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
227411fa71b9SJerome Forissier     {
227511fa71b9SJerome Forissier         ssl->out_hdr = ssl->out_buf;
227611fa71b9SJerome Forissier     }
227711fa71b9SJerome Forissier     else
227811fa71b9SJerome Forissier #endif
227911fa71b9SJerome Forissier     {
228011fa71b9SJerome Forissier         ssl->out_hdr = ssl->out_buf + 8;
228111fa71b9SJerome Forissier     }
228211fa71b9SJerome Forissier     mbedtls_ssl_update_out_pointers( ssl, ssl->transform_out );
228311fa71b9SJerome Forissier 
228411fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) );
228511fa71b9SJerome Forissier 
228611fa71b9SJerome Forissier     return( 0 );
228711fa71b9SJerome Forissier }
228811fa71b9SJerome Forissier 
228911fa71b9SJerome Forissier /*
229011fa71b9SJerome Forissier  * Functions to handle the DTLS retransmission state machine
229111fa71b9SJerome Forissier  */
229211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
229311fa71b9SJerome Forissier /*
229411fa71b9SJerome Forissier  * Append current handshake message to current outgoing flight
229511fa71b9SJerome Forissier  */
229611fa71b9SJerome Forissier static int ssl_flight_append( mbedtls_ssl_context *ssl )
229711fa71b9SJerome Forissier {
229811fa71b9SJerome Forissier     mbedtls_ssl_flight_item *msg;
229911fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_flight_append" ) );
230011fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_BUF( 4, "message appended to flight",
230111fa71b9SJerome Forissier                            ssl->out_msg, ssl->out_msglen );
230211fa71b9SJerome Forissier 
230311fa71b9SJerome Forissier     /* Allocate space for current message */
230411fa71b9SJerome Forissier     if( ( msg = mbedtls_calloc( 1, sizeof(  mbedtls_ssl_flight_item ) ) ) == NULL )
230511fa71b9SJerome Forissier     {
2306*7901324dSJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %" MBEDTLS_PRINTF_SIZET " bytes failed",
230711fa71b9SJerome Forissier                             sizeof( mbedtls_ssl_flight_item ) ) );
230811fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
230911fa71b9SJerome Forissier     }
231011fa71b9SJerome Forissier 
231111fa71b9SJerome Forissier     if( ( msg->p = mbedtls_calloc( 1, ssl->out_msglen ) ) == NULL )
231211fa71b9SJerome Forissier     {
2313*7901324dSJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %" MBEDTLS_PRINTF_SIZET " bytes failed",
2314*7901324dSJerome Forissier                                     ssl->out_msglen ) );
231511fa71b9SJerome Forissier         mbedtls_free( msg );
231611fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
231711fa71b9SJerome Forissier     }
231811fa71b9SJerome Forissier 
231911fa71b9SJerome Forissier     /* Copy current handshake message with headers */
232011fa71b9SJerome Forissier     memcpy( msg->p, ssl->out_msg, ssl->out_msglen );
232111fa71b9SJerome Forissier     msg->len = ssl->out_msglen;
232211fa71b9SJerome Forissier     msg->type = ssl->out_msgtype;
232311fa71b9SJerome Forissier     msg->next = NULL;
232411fa71b9SJerome Forissier 
232511fa71b9SJerome Forissier     /* Append to the current flight */
232611fa71b9SJerome Forissier     if( ssl->handshake->flight == NULL )
232711fa71b9SJerome Forissier         ssl->handshake->flight = msg;
232811fa71b9SJerome Forissier     else
232911fa71b9SJerome Forissier     {
233011fa71b9SJerome Forissier         mbedtls_ssl_flight_item *cur = ssl->handshake->flight;
233111fa71b9SJerome Forissier         while( cur->next != NULL )
233211fa71b9SJerome Forissier             cur = cur->next;
233311fa71b9SJerome Forissier         cur->next = msg;
233411fa71b9SJerome Forissier     }
233511fa71b9SJerome Forissier 
233611fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_flight_append" ) );
233711fa71b9SJerome Forissier     return( 0 );
233811fa71b9SJerome Forissier }
233911fa71b9SJerome Forissier 
234011fa71b9SJerome Forissier /*
234111fa71b9SJerome Forissier  * Free the current flight of handshake messages
234211fa71b9SJerome Forissier  */
234311fa71b9SJerome Forissier void mbedtls_ssl_flight_free( mbedtls_ssl_flight_item *flight )
234411fa71b9SJerome Forissier {
234511fa71b9SJerome Forissier     mbedtls_ssl_flight_item *cur = flight;
234611fa71b9SJerome Forissier     mbedtls_ssl_flight_item *next;
234711fa71b9SJerome Forissier 
234811fa71b9SJerome Forissier     while( cur != NULL )
234911fa71b9SJerome Forissier     {
235011fa71b9SJerome Forissier         next = cur->next;
235111fa71b9SJerome Forissier 
235211fa71b9SJerome Forissier         mbedtls_free( cur->p );
235311fa71b9SJerome Forissier         mbedtls_free( cur );
235411fa71b9SJerome Forissier 
235511fa71b9SJerome Forissier         cur = next;
235611fa71b9SJerome Forissier     }
235711fa71b9SJerome Forissier }
235811fa71b9SJerome Forissier 
235911fa71b9SJerome Forissier /*
236011fa71b9SJerome Forissier  * Swap transform_out and out_ctr with the alternative ones
236111fa71b9SJerome Forissier  */
236211fa71b9SJerome Forissier static int ssl_swap_epochs( mbedtls_ssl_context *ssl )
236311fa71b9SJerome Forissier {
236411fa71b9SJerome Forissier     mbedtls_ssl_transform *tmp_transform;
236511fa71b9SJerome Forissier     unsigned char tmp_out_ctr[8];
236611fa71b9SJerome Forissier 
236711fa71b9SJerome Forissier     if( ssl->transform_out == ssl->handshake->alt_transform_out )
236811fa71b9SJerome Forissier     {
236911fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip swap epochs" ) );
237011fa71b9SJerome Forissier         return( 0 );
237111fa71b9SJerome Forissier     }
237211fa71b9SJerome Forissier 
237311fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 3, ( "swap epochs" ) );
237411fa71b9SJerome Forissier 
237511fa71b9SJerome Forissier     /* Swap transforms */
237611fa71b9SJerome Forissier     tmp_transform                     = ssl->transform_out;
237711fa71b9SJerome Forissier     ssl->transform_out                = ssl->handshake->alt_transform_out;
237811fa71b9SJerome Forissier     ssl->handshake->alt_transform_out = tmp_transform;
237911fa71b9SJerome Forissier 
238011fa71b9SJerome Forissier     /* Swap epoch + sequence_number */
238111fa71b9SJerome Forissier     memcpy( tmp_out_ctr,                 ssl->cur_out_ctr,            8 );
238211fa71b9SJerome Forissier     memcpy( ssl->cur_out_ctr,            ssl->handshake->alt_out_ctr, 8 );
238311fa71b9SJerome Forissier     memcpy( ssl->handshake->alt_out_ctr, tmp_out_ctr,                 8 );
238411fa71b9SJerome Forissier 
238511fa71b9SJerome Forissier     /* Adjust to the newly activated transform */
238611fa71b9SJerome Forissier     mbedtls_ssl_update_out_pointers( ssl, ssl->transform_out );
238711fa71b9SJerome Forissier 
238811fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
238911fa71b9SJerome Forissier     if( mbedtls_ssl_hw_record_activate != NULL )
239011fa71b9SJerome Forissier     {
239111fa71b9SJerome Forissier         int ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_OUTBOUND );
239211fa71b9SJerome Forissier         if( ret != 0 )
239311fa71b9SJerome Forissier         {
239411fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret );
239511fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
239611fa71b9SJerome Forissier         }
239711fa71b9SJerome Forissier     }
239811fa71b9SJerome Forissier #endif
239911fa71b9SJerome Forissier 
240011fa71b9SJerome Forissier     return( 0 );
240111fa71b9SJerome Forissier }
240211fa71b9SJerome Forissier 
240311fa71b9SJerome Forissier /*
240411fa71b9SJerome Forissier  * Retransmit the current flight of messages.
240511fa71b9SJerome Forissier  */
240611fa71b9SJerome Forissier int mbedtls_ssl_resend( mbedtls_ssl_context *ssl )
240711fa71b9SJerome Forissier {
240811fa71b9SJerome Forissier     int ret = 0;
240911fa71b9SJerome Forissier 
241011fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_resend" ) );
241111fa71b9SJerome Forissier 
241211fa71b9SJerome Forissier     ret = mbedtls_ssl_flight_transmit( ssl );
241311fa71b9SJerome Forissier 
241411fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_resend" ) );
241511fa71b9SJerome Forissier 
241611fa71b9SJerome Forissier     return( ret );
241711fa71b9SJerome Forissier }
241811fa71b9SJerome Forissier 
241911fa71b9SJerome Forissier /*
242011fa71b9SJerome Forissier  * Transmit or retransmit the current flight of messages.
242111fa71b9SJerome Forissier  *
242211fa71b9SJerome Forissier  * Need to remember the current message in case flush_output returns
242311fa71b9SJerome Forissier  * WANT_WRITE, causing us to exit this function and come back later.
242411fa71b9SJerome Forissier  * This function must be called until state is no longer SENDING.
242511fa71b9SJerome Forissier  */
242611fa71b9SJerome Forissier int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl )
242711fa71b9SJerome Forissier {
242811fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
242911fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_flight_transmit" ) );
243011fa71b9SJerome Forissier 
243111fa71b9SJerome Forissier     if( ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING )
243211fa71b9SJerome Forissier     {
243311fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialise flight transmission" ) );
243411fa71b9SJerome Forissier 
243511fa71b9SJerome Forissier         ssl->handshake->cur_msg = ssl->handshake->flight;
243611fa71b9SJerome Forissier         ssl->handshake->cur_msg_p = ssl->handshake->flight->p + 12;
243711fa71b9SJerome Forissier         ret = ssl_swap_epochs( ssl );
243811fa71b9SJerome Forissier         if( ret != 0 )
243911fa71b9SJerome Forissier             return( ret );
244011fa71b9SJerome Forissier 
244111fa71b9SJerome Forissier         ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_SENDING;
244211fa71b9SJerome Forissier     }
244311fa71b9SJerome Forissier 
244411fa71b9SJerome Forissier     while( ssl->handshake->cur_msg != NULL )
244511fa71b9SJerome Forissier     {
244611fa71b9SJerome Forissier         size_t max_frag_len;
244711fa71b9SJerome Forissier         const mbedtls_ssl_flight_item * const cur = ssl->handshake->cur_msg;
244811fa71b9SJerome Forissier 
244911fa71b9SJerome Forissier         int const is_finished =
245011fa71b9SJerome Forissier             ( cur->type == MBEDTLS_SSL_MSG_HANDSHAKE &&
245111fa71b9SJerome Forissier               cur->p[0] == MBEDTLS_SSL_HS_FINISHED );
245211fa71b9SJerome Forissier 
245311fa71b9SJerome Forissier         uint8_t const force_flush = ssl->disable_datagram_packing == 1 ?
245411fa71b9SJerome Forissier             SSL_FORCE_FLUSH : SSL_DONT_FORCE_FLUSH;
245511fa71b9SJerome Forissier 
245611fa71b9SJerome Forissier         /* Swap epochs before sending Finished: we can't do it after
245711fa71b9SJerome Forissier          * sending ChangeCipherSpec, in case write returns WANT_READ.
245811fa71b9SJerome Forissier          * Must be done before copying, may change out_msg pointer */
245911fa71b9SJerome Forissier         if( is_finished && ssl->handshake->cur_msg_p == ( cur->p + 12 ) )
246011fa71b9SJerome Forissier         {
246111fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 2, ( "swap epochs to send finished message" ) );
246211fa71b9SJerome Forissier             ret = ssl_swap_epochs( ssl );
246311fa71b9SJerome Forissier             if( ret != 0 )
246411fa71b9SJerome Forissier                 return( ret );
246511fa71b9SJerome Forissier         }
246611fa71b9SJerome Forissier 
246711fa71b9SJerome Forissier         ret = ssl_get_remaining_payload_in_datagram( ssl );
246811fa71b9SJerome Forissier         if( ret < 0 )
246911fa71b9SJerome Forissier             return( ret );
247011fa71b9SJerome Forissier         max_frag_len = (size_t) ret;
247111fa71b9SJerome Forissier 
247211fa71b9SJerome Forissier         /* CCS is copied as is, while HS messages may need fragmentation */
247311fa71b9SJerome Forissier         if( cur->type == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC )
247411fa71b9SJerome Forissier         {
247511fa71b9SJerome Forissier             if( max_frag_len == 0 )
247611fa71b9SJerome Forissier             {
247711fa71b9SJerome Forissier                 if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
247811fa71b9SJerome Forissier                     return( ret );
247911fa71b9SJerome Forissier 
248011fa71b9SJerome Forissier                 continue;
248111fa71b9SJerome Forissier             }
248211fa71b9SJerome Forissier 
248311fa71b9SJerome Forissier             memcpy( ssl->out_msg, cur->p, cur->len );
248411fa71b9SJerome Forissier             ssl->out_msglen  = cur->len;
248511fa71b9SJerome Forissier             ssl->out_msgtype = cur->type;
248611fa71b9SJerome Forissier 
248711fa71b9SJerome Forissier             /* Update position inside current message */
248811fa71b9SJerome Forissier             ssl->handshake->cur_msg_p += cur->len;
248911fa71b9SJerome Forissier         }
249011fa71b9SJerome Forissier         else
249111fa71b9SJerome Forissier         {
249211fa71b9SJerome Forissier             const unsigned char * const p = ssl->handshake->cur_msg_p;
249311fa71b9SJerome Forissier             const size_t hs_len = cur->len - 12;
249411fa71b9SJerome Forissier             const size_t frag_off = p - ( cur->p + 12 );
249511fa71b9SJerome Forissier             const size_t rem_len = hs_len - frag_off;
249611fa71b9SJerome Forissier             size_t cur_hs_frag_len, max_hs_frag_len;
249711fa71b9SJerome Forissier 
249811fa71b9SJerome Forissier             if( ( max_frag_len < 12 ) || ( max_frag_len == 12 && hs_len != 0 ) )
249911fa71b9SJerome Forissier             {
250011fa71b9SJerome Forissier                 if( is_finished )
250111fa71b9SJerome Forissier                 {
250211fa71b9SJerome Forissier                     ret = ssl_swap_epochs( ssl );
250311fa71b9SJerome Forissier                     if( ret != 0 )
250411fa71b9SJerome Forissier                         return( ret );
250511fa71b9SJerome Forissier                 }
250611fa71b9SJerome Forissier 
250711fa71b9SJerome Forissier                 if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
250811fa71b9SJerome Forissier                     return( ret );
250911fa71b9SJerome Forissier 
251011fa71b9SJerome Forissier                 continue;
251111fa71b9SJerome Forissier             }
251211fa71b9SJerome Forissier             max_hs_frag_len = max_frag_len - 12;
251311fa71b9SJerome Forissier 
251411fa71b9SJerome Forissier             cur_hs_frag_len = rem_len > max_hs_frag_len ?
251511fa71b9SJerome Forissier                 max_hs_frag_len : rem_len;
251611fa71b9SJerome Forissier 
251711fa71b9SJerome Forissier             if( frag_off == 0 && cur_hs_frag_len != hs_len )
251811fa71b9SJerome Forissier             {
251911fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 2, ( "fragmenting handshake message (%u > %u)",
252011fa71b9SJerome Forissier                                             (unsigned) cur_hs_frag_len,
252111fa71b9SJerome Forissier                                             (unsigned) max_hs_frag_len ) );
252211fa71b9SJerome Forissier             }
252311fa71b9SJerome Forissier 
252411fa71b9SJerome Forissier             /* Messages are stored with handshake headers as if not fragmented,
252511fa71b9SJerome Forissier              * copy beginning of headers then fill fragmentation fields.
252611fa71b9SJerome Forissier              * Handshake headers: type(1) len(3) seq(2) f_off(3) f_len(3) */
252711fa71b9SJerome Forissier             memcpy( ssl->out_msg, cur->p, 6 );
252811fa71b9SJerome Forissier 
252911fa71b9SJerome Forissier             ssl->out_msg[6] = ( ( frag_off >> 16 ) & 0xff );
253011fa71b9SJerome Forissier             ssl->out_msg[7] = ( ( frag_off >>  8 ) & 0xff );
253111fa71b9SJerome Forissier             ssl->out_msg[8] = ( ( frag_off       ) & 0xff );
253211fa71b9SJerome Forissier 
253311fa71b9SJerome Forissier             ssl->out_msg[ 9] = ( ( cur_hs_frag_len >> 16 ) & 0xff );
253411fa71b9SJerome Forissier             ssl->out_msg[10] = ( ( cur_hs_frag_len >>  8 ) & 0xff );
253511fa71b9SJerome Forissier             ssl->out_msg[11] = ( ( cur_hs_frag_len       ) & 0xff );
253611fa71b9SJerome Forissier 
253711fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_BUF( 3, "handshake header", ssl->out_msg, 12 );
253811fa71b9SJerome Forissier 
253911fa71b9SJerome Forissier             /* Copy the handshake message content and set records fields */
254011fa71b9SJerome Forissier             memcpy( ssl->out_msg + 12, p, cur_hs_frag_len );
254111fa71b9SJerome Forissier             ssl->out_msglen = cur_hs_frag_len + 12;
254211fa71b9SJerome Forissier             ssl->out_msgtype = cur->type;
254311fa71b9SJerome Forissier 
254411fa71b9SJerome Forissier             /* Update position inside current message */
254511fa71b9SJerome Forissier             ssl->handshake->cur_msg_p += cur_hs_frag_len;
254611fa71b9SJerome Forissier         }
254711fa71b9SJerome Forissier 
254811fa71b9SJerome Forissier         /* If done with the current message move to the next one if any */
254911fa71b9SJerome Forissier         if( ssl->handshake->cur_msg_p >= cur->p + cur->len )
255011fa71b9SJerome Forissier         {
255111fa71b9SJerome Forissier             if( cur->next != NULL )
255211fa71b9SJerome Forissier             {
255311fa71b9SJerome Forissier                 ssl->handshake->cur_msg = cur->next;
255411fa71b9SJerome Forissier                 ssl->handshake->cur_msg_p = cur->next->p + 12;
255511fa71b9SJerome Forissier             }
255611fa71b9SJerome Forissier             else
255711fa71b9SJerome Forissier             {
255811fa71b9SJerome Forissier                 ssl->handshake->cur_msg = NULL;
255911fa71b9SJerome Forissier                 ssl->handshake->cur_msg_p = NULL;
256011fa71b9SJerome Forissier             }
256111fa71b9SJerome Forissier         }
256211fa71b9SJerome Forissier 
256311fa71b9SJerome Forissier         /* Actually send the message out */
256411fa71b9SJerome Forissier         if( ( ret = mbedtls_ssl_write_record( ssl, force_flush ) ) != 0 )
256511fa71b9SJerome Forissier         {
256611fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
256711fa71b9SJerome Forissier             return( ret );
256811fa71b9SJerome Forissier         }
256911fa71b9SJerome Forissier     }
257011fa71b9SJerome Forissier 
257111fa71b9SJerome Forissier     if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
257211fa71b9SJerome Forissier         return( ret );
257311fa71b9SJerome Forissier 
257411fa71b9SJerome Forissier     /* Update state and set timer */
257511fa71b9SJerome Forissier     if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
257611fa71b9SJerome Forissier         ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED;
257711fa71b9SJerome Forissier     else
257811fa71b9SJerome Forissier     {
257911fa71b9SJerome Forissier         ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING;
258011fa71b9SJerome Forissier         mbedtls_ssl_set_timer( ssl, ssl->handshake->retransmit_timeout );
258111fa71b9SJerome Forissier     }
258211fa71b9SJerome Forissier 
258311fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_flight_transmit" ) );
258411fa71b9SJerome Forissier 
258511fa71b9SJerome Forissier     return( 0 );
258611fa71b9SJerome Forissier }
258711fa71b9SJerome Forissier 
258811fa71b9SJerome Forissier /*
258911fa71b9SJerome Forissier  * To be called when the last message of an incoming flight is received.
259011fa71b9SJerome Forissier  */
259111fa71b9SJerome Forissier void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl )
259211fa71b9SJerome Forissier {
259311fa71b9SJerome Forissier     /* We won't need to resend that one any more */
259411fa71b9SJerome Forissier     mbedtls_ssl_flight_free( ssl->handshake->flight );
259511fa71b9SJerome Forissier     ssl->handshake->flight = NULL;
259611fa71b9SJerome Forissier     ssl->handshake->cur_msg = NULL;
259711fa71b9SJerome Forissier 
259811fa71b9SJerome Forissier     /* The next incoming flight will start with this msg_seq */
259911fa71b9SJerome Forissier     ssl->handshake->in_flight_start_seq = ssl->handshake->in_msg_seq;
260011fa71b9SJerome Forissier 
260111fa71b9SJerome Forissier     /* We don't want to remember CCS's across flight boundaries. */
260211fa71b9SJerome Forissier     ssl->handshake->buffering.seen_ccs = 0;
260311fa71b9SJerome Forissier 
260411fa71b9SJerome Forissier     /* Clear future message buffering structure. */
260511fa71b9SJerome Forissier     mbedtls_ssl_buffering_free( ssl );
260611fa71b9SJerome Forissier 
260711fa71b9SJerome Forissier     /* Cancel timer */
260811fa71b9SJerome Forissier     mbedtls_ssl_set_timer( ssl, 0 );
260911fa71b9SJerome Forissier 
261011fa71b9SJerome Forissier     if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
261111fa71b9SJerome Forissier         ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED )
261211fa71b9SJerome Forissier     {
261311fa71b9SJerome Forissier         ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED;
261411fa71b9SJerome Forissier     }
261511fa71b9SJerome Forissier     else
261611fa71b9SJerome Forissier         ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING;
261711fa71b9SJerome Forissier }
261811fa71b9SJerome Forissier 
261911fa71b9SJerome Forissier /*
262011fa71b9SJerome Forissier  * To be called when the last message of an outgoing flight is send.
262111fa71b9SJerome Forissier  */
262211fa71b9SJerome Forissier void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl )
262311fa71b9SJerome Forissier {
262411fa71b9SJerome Forissier     ssl_reset_retransmit_timeout( ssl );
262511fa71b9SJerome Forissier     mbedtls_ssl_set_timer( ssl, ssl->handshake->retransmit_timeout );
262611fa71b9SJerome Forissier 
262711fa71b9SJerome Forissier     if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
262811fa71b9SJerome Forissier         ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED )
262911fa71b9SJerome Forissier     {
263011fa71b9SJerome Forissier         ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED;
263111fa71b9SJerome Forissier     }
263211fa71b9SJerome Forissier     else
263311fa71b9SJerome Forissier         ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING;
263411fa71b9SJerome Forissier }
263511fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
263611fa71b9SJerome Forissier 
263711fa71b9SJerome Forissier /*
263811fa71b9SJerome Forissier  * Handshake layer functions
263911fa71b9SJerome Forissier  */
264011fa71b9SJerome Forissier 
264111fa71b9SJerome Forissier /*
264211fa71b9SJerome Forissier  * Write (DTLS: or queue) current handshake (including CCS) message.
264311fa71b9SJerome Forissier  *
264411fa71b9SJerome Forissier  *  - fill in handshake headers
264511fa71b9SJerome Forissier  *  - update handshake checksum
264611fa71b9SJerome Forissier  *  - DTLS: save message for resending
264711fa71b9SJerome Forissier  *  - then pass to the record layer
264811fa71b9SJerome Forissier  *
264911fa71b9SJerome Forissier  * DTLS: except for HelloRequest, messages are only queued, and will only be
265011fa71b9SJerome Forissier  * actually sent when calling flight_transmit() or resend().
265111fa71b9SJerome Forissier  *
265211fa71b9SJerome Forissier  * Inputs:
265311fa71b9SJerome Forissier  *  - ssl->out_msglen: 4 + actual handshake message len
265411fa71b9SJerome Forissier  *      (4 is the size of handshake headers for TLS)
265511fa71b9SJerome Forissier  *  - ssl->out_msg[0]: the handshake type (ClientHello, ServerHello, etc)
265611fa71b9SJerome Forissier  *  - ssl->out_msg + 4: the handshake message body
265711fa71b9SJerome Forissier  *
265811fa71b9SJerome Forissier  * Outputs, ie state before passing to flight_append() or write_record():
265911fa71b9SJerome Forissier  *   - ssl->out_msglen: the length of the record contents
266011fa71b9SJerome Forissier  *      (including handshake headers but excluding record headers)
266111fa71b9SJerome Forissier  *   - ssl->out_msg: the record contents (handshake headers + content)
266211fa71b9SJerome Forissier  */
266311fa71b9SJerome Forissier int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl )
266411fa71b9SJerome Forissier {
266511fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
266611fa71b9SJerome Forissier     const size_t hs_len = ssl->out_msglen - 4;
266711fa71b9SJerome Forissier     const unsigned char hs_type = ssl->out_msg[0];
266811fa71b9SJerome Forissier 
266911fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write handshake message" ) );
267011fa71b9SJerome Forissier 
267111fa71b9SJerome Forissier     /*
267211fa71b9SJerome Forissier      * Sanity checks
267311fa71b9SJerome Forissier      */
267411fa71b9SJerome Forissier     if( ssl->out_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE          &&
267511fa71b9SJerome Forissier         ssl->out_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC )
267611fa71b9SJerome Forissier     {
267711fa71b9SJerome Forissier         /* In SSLv3, the client might send a NoCertificate alert. */
267811fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_CLI_C)
267911fa71b9SJerome Forissier         if( ! ( ssl->minor_ver      == MBEDTLS_SSL_MINOR_VERSION_0 &&
268011fa71b9SJerome Forissier                 ssl->out_msgtype    == MBEDTLS_SSL_MSG_ALERT       &&
268111fa71b9SJerome Forissier                 ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) )
268211fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */
268311fa71b9SJerome Forissier         {
268411fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
268511fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
268611fa71b9SJerome Forissier         }
268711fa71b9SJerome Forissier     }
268811fa71b9SJerome Forissier 
268911fa71b9SJerome Forissier     /* Whenever we send anything different from a
269011fa71b9SJerome Forissier      * HelloRequest we should be in a handshake - double check. */
269111fa71b9SJerome Forissier     if( ! ( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
269211fa71b9SJerome Forissier             hs_type          == MBEDTLS_SSL_HS_HELLO_REQUEST ) &&
269311fa71b9SJerome Forissier         ssl->handshake == NULL )
269411fa71b9SJerome Forissier     {
269511fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
269611fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
269711fa71b9SJerome Forissier     }
269811fa71b9SJerome Forissier 
269911fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
270011fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
270111fa71b9SJerome Forissier         ssl->handshake != NULL &&
270211fa71b9SJerome Forissier         ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING )
270311fa71b9SJerome Forissier     {
270411fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
270511fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
270611fa71b9SJerome Forissier     }
270711fa71b9SJerome Forissier #endif
270811fa71b9SJerome Forissier 
270911fa71b9SJerome Forissier     /* Double-check that we did not exceed the bounds
271011fa71b9SJerome Forissier      * of the outgoing record buffer.
271111fa71b9SJerome Forissier      * This should never fail as the various message
271211fa71b9SJerome Forissier      * writing functions must obey the bounds of the
271311fa71b9SJerome Forissier      * outgoing record buffer, but better be safe.
271411fa71b9SJerome Forissier      *
271511fa71b9SJerome Forissier      * Note: We deliberately do not check for the MTU or MFL here.
271611fa71b9SJerome Forissier      */
271711fa71b9SJerome Forissier     if( ssl->out_msglen > MBEDTLS_SSL_OUT_CONTENT_LEN )
271811fa71b9SJerome Forissier     {
271911fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record too large: "
2720*7901324dSJerome Forissier                                     "size %" MBEDTLS_PRINTF_SIZET
2721*7901324dSJerome Forissier                                     ", maximum %" MBEDTLS_PRINTF_SIZET,
2722*7901324dSJerome Forissier                                     ssl->out_msglen,
2723*7901324dSJerome Forissier                                     (size_t) MBEDTLS_SSL_OUT_CONTENT_LEN ) );
272411fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
272511fa71b9SJerome Forissier     }
272611fa71b9SJerome Forissier 
272711fa71b9SJerome Forissier     /*
272811fa71b9SJerome Forissier      * Fill handshake headers
272911fa71b9SJerome Forissier      */
273011fa71b9SJerome Forissier     if( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE )
273111fa71b9SJerome Forissier     {
273211fa71b9SJerome Forissier         ssl->out_msg[1] = (unsigned char)( hs_len >> 16 );
273311fa71b9SJerome Forissier         ssl->out_msg[2] = (unsigned char)( hs_len >>  8 );
273411fa71b9SJerome Forissier         ssl->out_msg[3] = (unsigned char)( hs_len       );
273511fa71b9SJerome Forissier 
273611fa71b9SJerome Forissier         /*
273711fa71b9SJerome Forissier          * DTLS has additional fields in the Handshake layer,
273811fa71b9SJerome Forissier          * between the length field and the actual payload:
273911fa71b9SJerome Forissier          *      uint16 message_seq;
274011fa71b9SJerome Forissier          *      uint24 fragment_offset;
274111fa71b9SJerome Forissier          *      uint24 fragment_length;
274211fa71b9SJerome Forissier          */
274311fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
274411fa71b9SJerome Forissier         if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
274511fa71b9SJerome Forissier         {
274611fa71b9SJerome Forissier             /* Make room for the additional DTLS fields */
274711fa71b9SJerome Forissier             if( MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen < 8 )
274811fa71b9SJerome Forissier             {
274911fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS handshake message too large: "
2750*7901324dSJerome Forissier                               "size %" MBEDTLS_PRINTF_SIZET ", maximum %" MBEDTLS_PRINTF_SIZET,
2751*7901324dSJerome Forissier                                hs_len,
2752*7901324dSJerome Forissier                                (size_t) ( MBEDTLS_SSL_OUT_CONTENT_LEN - 12 ) ) );
275311fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
275411fa71b9SJerome Forissier             }
275511fa71b9SJerome Forissier 
275611fa71b9SJerome Forissier             memmove( ssl->out_msg + 12, ssl->out_msg + 4, hs_len );
275711fa71b9SJerome Forissier             ssl->out_msglen += 8;
275811fa71b9SJerome Forissier 
275911fa71b9SJerome Forissier             /* Write message_seq and update it, except for HelloRequest */
276011fa71b9SJerome Forissier             if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST )
276111fa71b9SJerome Forissier             {
276211fa71b9SJerome Forissier                 ssl->out_msg[4] = ( ssl->handshake->out_msg_seq >> 8 ) & 0xFF;
276311fa71b9SJerome Forissier                 ssl->out_msg[5] = ( ssl->handshake->out_msg_seq      ) & 0xFF;
276411fa71b9SJerome Forissier                 ++( ssl->handshake->out_msg_seq );
276511fa71b9SJerome Forissier             }
276611fa71b9SJerome Forissier             else
276711fa71b9SJerome Forissier             {
276811fa71b9SJerome Forissier                 ssl->out_msg[4] = 0;
276911fa71b9SJerome Forissier                 ssl->out_msg[5] = 0;
277011fa71b9SJerome Forissier             }
277111fa71b9SJerome Forissier 
277211fa71b9SJerome Forissier             /* Handshake hashes are computed without fragmentation,
277311fa71b9SJerome Forissier              * so set frag_offset = 0 and frag_len = hs_len for now */
277411fa71b9SJerome Forissier             memset( ssl->out_msg + 6, 0x00, 3 );
277511fa71b9SJerome Forissier             memcpy( ssl->out_msg + 9, ssl->out_msg + 1, 3 );
277611fa71b9SJerome Forissier         }
277711fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
277811fa71b9SJerome Forissier 
277911fa71b9SJerome Forissier         /* Update running hashes of handshake messages seen */
278011fa71b9SJerome Forissier         if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST )
278111fa71b9SJerome Forissier             ssl->handshake->update_checksum( ssl, ssl->out_msg, ssl->out_msglen );
278211fa71b9SJerome Forissier     }
278311fa71b9SJerome Forissier 
278411fa71b9SJerome Forissier     /* Either send now, or just save to be sent (and resent) later */
278511fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
278611fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
278711fa71b9SJerome Forissier         ! ( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
278811fa71b9SJerome Forissier             hs_type          == MBEDTLS_SSL_HS_HELLO_REQUEST ) )
278911fa71b9SJerome Forissier     {
279011fa71b9SJerome Forissier         if( ( ret = ssl_flight_append( ssl ) ) != 0 )
279111fa71b9SJerome Forissier         {
279211fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "ssl_flight_append", ret );
279311fa71b9SJerome Forissier             return( ret );
279411fa71b9SJerome Forissier         }
279511fa71b9SJerome Forissier     }
279611fa71b9SJerome Forissier     else
279711fa71b9SJerome Forissier #endif
279811fa71b9SJerome Forissier     {
279911fa71b9SJerome Forissier         if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 )
280011fa71b9SJerome Forissier         {
280111fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_record", ret );
280211fa71b9SJerome Forissier             return( ret );
280311fa71b9SJerome Forissier         }
280411fa71b9SJerome Forissier     }
280511fa71b9SJerome Forissier 
280611fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write handshake message" ) );
280711fa71b9SJerome Forissier 
280811fa71b9SJerome Forissier     return( 0 );
280911fa71b9SJerome Forissier }
281011fa71b9SJerome Forissier 
281111fa71b9SJerome Forissier /*
281211fa71b9SJerome Forissier  * Record layer functions
281311fa71b9SJerome Forissier  */
281411fa71b9SJerome Forissier 
281511fa71b9SJerome Forissier /*
281611fa71b9SJerome Forissier  * Write current record.
281711fa71b9SJerome Forissier  *
281811fa71b9SJerome Forissier  * Uses:
281911fa71b9SJerome Forissier  *  - ssl->out_msgtype: type of the message (AppData, Handshake, Alert, CCS)
282011fa71b9SJerome Forissier  *  - ssl->out_msglen: length of the record content (excl headers)
282111fa71b9SJerome Forissier  *  - ssl->out_msg: record content
282211fa71b9SJerome Forissier  */
282311fa71b9SJerome Forissier int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush )
282411fa71b9SJerome Forissier {
282511fa71b9SJerome Forissier     int ret, done = 0;
282611fa71b9SJerome Forissier     size_t len = ssl->out_msglen;
282711fa71b9SJerome Forissier     uint8_t flush = force_flush;
282811fa71b9SJerome Forissier 
282911fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write record" ) );
283011fa71b9SJerome Forissier 
283111fa71b9SJerome Forissier #if defined(MBEDTLS_ZLIB_SUPPORT)
283211fa71b9SJerome Forissier     if( ssl->transform_out != NULL &&
283311fa71b9SJerome Forissier         ssl->session_out->compression == MBEDTLS_SSL_COMPRESS_DEFLATE )
283411fa71b9SJerome Forissier     {
283511fa71b9SJerome Forissier         if( ( ret = ssl_compress_buf( ssl ) ) != 0 )
283611fa71b9SJerome Forissier         {
283711fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "ssl_compress_buf", ret );
283811fa71b9SJerome Forissier             return( ret );
283911fa71b9SJerome Forissier         }
284011fa71b9SJerome Forissier 
284111fa71b9SJerome Forissier         len = ssl->out_msglen;
284211fa71b9SJerome Forissier     }
284311fa71b9SJerome Forissier #endif /*MBEDTLS_ZLIB_SUPPORT */
284411fa71b9SJerome Forissier 
284511fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
284611fa71b9SJerome Forissier     if( mbedtls_ssl_hw_record_write != NULL )
284711fa71b9SJerome Forissier     {
284811fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_write()" ) );
284911fa71b9SJerome Forissier 
285011fa71b9SJerome Forissier         ret = mbedtls_ssl_hw_record_write( ssl );
285111fa71b9SJerome Forissier         if( ret != 0 && ret != MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH )
285211fa71b9SJerome Forissier         {
285311fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_write", ret );
285411fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
285511fa71b9SJerome Forissier         }
285611fa71b9SJerome Forissier 
285711fa71b9SJerome Forissier         if( ret == 0 )
285811fa71b9SJerome Forissier             done = 1;
285911fa71b9SJerome Forissier     }
286011fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */
286111fa71b9SJerome Forissier     if( !done )
286211fa71b9SJerome Forissier     {
286311fa71b9SJerome Forissier         unsigned i;
286411fa71b9SJerome Forissier         size_t protected_record_size;
286511fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
286611fa71b9SJerome Forissier         size_t out_buf_len = ssl->out_buf_len;
286711fa71b9SJerome Forissier #else
286811fa71b9SJerome Forissier         size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN;
286911fa71b9SJerome Forissier #endif
287011fa71b9SJerome Forissier         /* Skip writing the record content type to after the encryption,
287111fa71b9SJerome Forissier          * as it may change when using the CID extension. */
287211fa71b9SJerome Forissier 
287311fa71b9SJerome Forissier         mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver,
287411fa71b9SJerome Forissier                            ssl->conf->transport, ssl->out_hdr + 1 );
287511fa71b9SJerome Forissier 
287611fa71b9SJerome Forissier         memcpy( ssl->out_ctr, ssl->cur_out_ctr, 8 );
287711fa71b9SJerome Forissier         ssl->out_len[0] = (unsigned char)( len >> 8 );
287811fa71b9SJerome Forissier         ssl->out_len[1] = (unsigned char)( len      );
287911fa71b9SJerome Forissier 
288011fa71b9SJerome Forissier         if( ssl->transform_out != NULL )
288111fa71b9SJerome Forissier         {
288211fa71b9SJerome Forissier             mbedtls_record rec;
288311fa71b9SJerome Forissier 
288411fa71b9SJerome Forissier             rec.buf         = ssl->out_iv;
288511fa71b9SJerome Forissier             rec.buf_len     = out_buf_len - ( ssl->out_iv - ssl->out_buf );
288611fa71b9SJerome Forissier             rec.data_len    = ssl->out_msglen;
288711fa71b9SJerome Forissier             rec.data_offset = ssl->out_msg - rec.buf;
288811fa71b9SJerome Forissier 
288911fa71b9SJerome Forissier             memcpy( &rec.ctr[0], ssl->out_ctr, 8 );
289011fa71b9SJerome Forissier             mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver,
289111fa71b9SJerome Forissier                                        ssl->conf->transport, rec.ver );
289211fa71b9SJerome Forissier             rec.type = ssl->out_msgtype;
289311fa71b9SJerome Forissier 
289411fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
289511fa71b9SJerome Forissier             /* The CID is set by mbedtls_ssl_encrypt_buf(). */
289611fa71b9SJerome Forissier             rec.cid_len = 0;
289711fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
289811fa71b9SJerome Forissier 
289911fa71b9SJerome Forissier             if( ( ret = mbedtls_ssl_encrypt_buf( ssl, ssl->transform_out, &rec,
290011fa71b9SJerome Forissier                                          ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
290111fa71b9SJerome Forissier             {
290211fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_RET( 1, "ssl_encrypt_buf", ret );
290311fa71b9SJerome Forissier                 return( ret );
290411fa71b9SJerome Forissier             }
290511fa71b9SJerome Forissier 
290611fa71b9SJerome Forissier             if( rec.data_offset != 0 )
290711fa71b9SJerome Forissier             {
290811fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
290911fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
291011fa71b9SJerome Forissier             }
291111fa71b9SJerome Forissier 
291211fa71b9SJerome Forissier             /* Update the record content type and CID. */
291311fa71b9SJerome Forissier             ssl->out_msgtype = rec.type;
291411fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID )
291511fa71b9SJerome Forissier             memcpy( ssl->out_cid, rec.cid, rec.cid_len );
291611fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
291711fa71b9SJerome Forissier             ssl->out_msglen = len = rec.data_len;
291811fa71b9SJerome Forissier             ssl->out_len[0] = (unsigned char)( rec.data_len >> 8 );
291911fa71b9SJerome Forissier             ssl->out_len[1] = (unsigned char)( rec.data_len      );
292011fa71b9SJerome Forissier         }
292111fa71b9SJerome Forissier 
292211fa71b9SJerome Forissier         protected_record_size = len + mbedtls_ssl_out_hdr_len( ssl );
292311fa71b9SJerome Forissier 
292411fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
292511fa71b9SJerome Forissier         /* In case of DTLS, double-check that we don't exceed
292611fa71b9SJerome Forissier          * the remaining space in the datagram. */
292711fa71b9SJerome Forissier         if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
292811fa71b9SJerome Forissier         {
292911fa71b9SJerome Forissier             ret = ssl_get_remaining_space_in_datagram( ssl );
293011fa71b9SJerome Forissier             if( ret < 0 )
293111fa71b9SJerome Forissier                 return( ret );
293211fa71b9SJerome Forissier 
293311fa71b9SJerome Forissier             if( protected_record_size > (size_t) ret )
293411fa71b9SJerome Forissier             {
293511fa71b9SJerome Forissier                 /* Should never happen */
293611fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
293711fa71b9SJerome Forissier             }
293811fa71b9SJerome Forissier         }
293911fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
294011fa71b9SJerome Forissier 
294111fa71b9SJerome Forissier         /* Now write the potentially updated record content type. */
294211fa71b9SJerome Forissier         ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype;
294311fa71b9SJerome Forissier 
2944*7901324dSJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 3, ( "output record: msgtype = %u, "
2945*7901324dSJerome Forissier                                     "version = [%u:%u], msglen = %" MBEDTLS_PRINTF_SIZET,
294611fa71b9SJerome Forissier                                     ssl->out_hdr[0], ssl->out_hdr[1],
294711fa71b9SJerome Forissier                                     ssl->out_hdr[2], len ) );
294811fa71b9SJerome Forissier 
294911fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network",
295011fa71b9SJerome Forissier                                ssl->out_hdr, protected_record_size );
295111fa71b9SJerome Forissier 
295211fa71b9SJerome Forissier         ssl->out_left += protected_record_size;
295311fa71b9SJerome Forissier         ssl->out_hdr  += protected_record_size;
295411fa71b9SJerome Forissier         mbedtls_ssl_update_out_pointers( ssl, ssl->transform_out );
295511fa71b9SJerome Forissier 
295611fa71b9SJerome Forissier         for( i = 8; i > mbedtls_ssl_ep_len( ssl ); i-- )
295711fa71b9SJerome Forissier             if( ++ssl->cur_out_ctr[i - 1] != 0 )
295811fa71b9SJerome Forissier                 break;
295911fa71b9SJerome Forissier 
296011fa71b9SJerome Forissier         /* The loop goes to its end iff the counter is wrapping */
296111fa71b9SJerome Forissier         if( i == mbedtls_ssl_ep_len( ssl ) )
296211fa71b9SJerome Forissier         {
296311fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "outgoing message counter would wrap" ) );
296411fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING );
296511fa71b9SJerome Forissier         }
296611fa71b9SJerome Forissier     }
296711fa71b9SJerome Forissier 
296811fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
296911fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
297011fa71b9SJerome Forissier         flush == SSL_DONT_FORCE_FLUSH )
297111fa71b9SJerome Forissier     {
297211fa71b9SJerome Forissier         size_t remaining;
297311fa71b9SJerome Forissier         ret = ssl_get_remaining_payload_in_datagram( ssl );
297411fa71b9SJerome Forissier         if( ret < 0 )
297511fa71b9SJerome Forissier         {
297611fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_remaining_payload_in_datagram",
297711fa71b9SJerome Forissier                                    ret );
297811fa71b9SJerome Forissier             return( ret );
297911fa71b9SJerome Forissier         }
298011fa71b9SJerome Forissier 
298111fa71b9SJerome Forissier         remaining = (size_t) ret;
298211fa71b9SJerome Forissier         if( remaining == 0 )
298311fa71b9SJerome Forissier         {
298411fa71b9SJerome Forissier             flush = SSL_FORCE_FLUSH;
298511fa71b9SJerome Forissier         }
298611fa71b9SJerome Forissier         else
298711fa71b9SJerome Forissier         {
298811fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 2, ( "Still %u bytes available in current datagram", (unsigned) remaining ) );
298911fa71b9SJerome Forissier         }
299011fa71b9SJerome Forissier     }
299111fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
299211fa71b9SJerome Forissier 
299311fa71b9SJerome Forissier     if( ( flush == SSL_FORCE_FLUSH ) &&
299411fa71b9SJerome Forissier         ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
299511fa71b9SJerome Forissier     {
299611fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret );
299711fa71b9SJerome Forissier         return( ret );
299811fa71b9SJerome Forissier     }
299911fa71b9SJerome Forissier 
300011fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write record" ) );
300111fa71b9SJerome Forissier 
300211fa71b9SJerome Forissier     return( 0 );
300311fa71b9SJerome Forissier }
300411fa71b9SJerome Forissier 
300511fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
300611fa71b9SJerome Forissier 
300711fa71b9SJerome Forissier static int ssl_hs_is_proper_fragment( mbedtls_ssl_context *ssl )
300811fa71b9SJerome Forissier {
300911fa71b9SJerome Forissier     if( ssl->in_msglen < ssl->in_hslen ||
301011fa71b9SJerome Forissier         memcmp( ssl->in_msg + 6, "\0\0\0",        3 ) != 0 ||
301111fa71b9SJerome Forissier         memcmp( ssl->in_msg + 9, ssl->in_msg + 1, 3 ) != 0 )
301211fa71b9SJerome Forissier     {
301311fa71b9SJerome Forissier         return( 1 );
301411fa71b9SJerome Forissier     }
301511fa71b9SJerome Forissier     return( 0 );
301611fa71b9SJerome Forissier }
301711fa71b9SJerome Forissier 
301811fa71b9SJerome Forissier static uint32_t ssl_get_hs_frag_len( mbedtls_ssl_context const *ssl )
301911fa71b9SJerome Forissier {
302011fa71b9SJerome Forissier     return( ( ssl->in_msg[9] << 16  ) |
302111fa71b9SJerome Forissier             ( ssl->in_msg[10] << 8  ) |
302211fa71b9SJerome Forissier               ssl->in_msg[11] );
302311fa71b9SJerome Forissier }
302411fa71b9SJerome Forissier 
302511fa71b9SJerome Forissier static uint32_t ssl_get_hs_frag_off( mbedtls_ssl_context const *ssl )
302611fa71b9SJerome Forissier {
302711fa71b9SJerome Forissier     return( ( ssl->in_msg[6] << 16 ) |
302811fa71b9SJerome Forissier             ( ssl->in_msg[7] << 8  ) |
302911fa71b9SJerome Forissier               ssl->in_msg[8] );
303011fa71b9SJerome Forissier }
303111fa71b9SJerome Forissier 
303211fa71b9SJerome Forissier static int ssl_check_hs_header( mbedtls_ssl_context const *ssl )
303311fa71b9SJerome Forissier {
303411fa71b9SJerome Forissier     uint32_t msg_len, frag_off, frag_len;
303511fa71b9SJerome Forissier 
303611fa71b9SJerome Forissier     msg_len  = ssl_get_hs_total_len( ssl );
303711fa71b9SJerome Forissier     frag_off = ssl_get_hs_frag_off( ssl );
303811fa71b9SJerome Forissier     frag_len = ssl_get_hs_frag_len( ssl );
303911fa71b9SJerome Forissier 
304011fa71b9SJerome Forissier     if( frag_off > msg_len )
304111fa71b9SJerome Forissier         return( -1 );
304211fa71b9SJerome Forissier 
304311fa71b9SJerome Forissier     if( frag_len > msg_len - frag_off )
304411fa71b9SJerome Forissier         return( -1 );
304511fa71b9SJerome Forissier 
304611fa71b9SJerome Forissier     if( frag_len + 12 > ssl->in_msglen )
304711fa71b9SJerome Forissier         return( -1 );
304811fa71b9SJerome Forissier 
304911fa71b9SJerome Forissier     return( 0 );
305011fa71b9SJerome Forissier }
305111fa71b9SJerome Forissier 
305211fa71b9SJerome Forissier /*
305311fa71b9SJerome Forissier  * Mark bits in bitmask (used for DTLS HS reassembly)
305411fa71b9SJerome Forissier  */
305511fa71b9SJerome Forissier static void ssl_bitmask_set( unsigned char *mask, size_t offset, size_t len )
305611fa71b9SJerome Forissier {
305711fa71b9SJerome Forissier     unsigned int start_bits, end_bits;
305811fa71b9SJerome Forissier 
305911fa71b9SJerome Forissier     start_bits = 8 - ( offset % 8 );
306011fa71b9SJerome Forissier     if( start_bits != 8 )
306111fa71b9SJerome Forissier     {
306211fa71b9SJerome Forissier         size_t first_byte_idx = offset / 8;
306311fa71b9SJerome Forissier 
306411fa71b9SJerome Forissier         /* Special case */
306511fa71b9SJerome Forissier         if( len <= start_bits )
306611fa71b9SJerome Forissier         {
306711fa71b9SJerome Forissier             for( ; len != 0; len-- )
306811fa71b9SJerome Forissier                 mask[first_byte_idx] |= 1 << ( start_bits - len );
306911fa71b9SJerome Forissier 
307011fa71b9SJerome Forissier             /* Avoid potential issues with offset or len becoming invalid */
307111fa71b9SJerome Forissier             return;
307211fa71b9SJerome Forissier         }
307311fa71b9SJerome Forissier 
307411fa71b9SJerome Forissier         offset += start_bits; /* Now offset % 8 == 0 */
307511fa71b9SJerome Forissier         len -= start_bits;
307611fa71b9SJerome Forissier 
307711fa71b9SJerome Forissier         for( ; start_bits != 0; start_bits-- )
307811fa71b9SJerome Forissier             mask[first_byte_idx] |= 1 << ( start_bits - 1 );
307911fa71b9SJerome Forissier     }
308011fa71b9SJerome Forissier 
308111fa71b9SJerome Forissier     end_bits = len % 8;
308211fa71b9SJerome Forissier     if( end_bits != 0 )
308311fa71b9SJerome Forissier     {
308411fa71b9SJerome Forissier         size_t last_byte_idx = ( offset + len ) / 8;
308511fa71b9SJerome Forissier 
308611fa71b9SJerome Forissier         len -= end_bits; /* Now len % 8 == 0 */
308711fa71b9SJerome Forissier 
308811fa71b9SJerome Forissier         for( ; end_bits != 0; end_bits-- )
308911fa71b9SJerome Forissier             mask[last_byte_idx] |= 1 << ( 8 - end_bits );
309011fa71b9SJerome Forissier     }
309111fa71b9SJerome Forissier 
309211fa71b9SJerome Forissier     memset( mask + offset / 8, 0xFF, len / 8 );
309311fa71b9SJerome Forissier }
309411fa71b9SJerome Forissier 
309511fa71b9SJerome Forissier /*
309611fa71b9SJerome Forissier  * Check that bitmask is full
309711fa71b9SJerome Forissier  */
309811fa71b9SJerome Forissier static int ssl_bitmask_check( unsigned char *mask, size_t len )
309911fa71b9SJerome Forissier {
310011fa71b9SJerome Forissier     size_t i;
310111fa71b9SJerome Forissier 
310211fa71b9SJerome Forissier     for( i = 0; i < len / 8; i++ )
310311fa71b9SJerome Forissier         if( mask[i] != 0xFF )
310411fa71b9SJerome Forissier             return( -1 );
310511fa71b9SJerome Forissier 
310611fa71b9SJerome Forissier     for( i = 0; i < len % 8; i++ )
310711fa71b9SJerome Forissier         if( ( mask[len / 8] & ( 1 << ( 7 - i ) ) ) == 0 )
310811fa71b9SJerome Forissier             return( -1 );
310911fa71b9SJerome Forissier 
311011fa71b9SJerome Forissier     return( 0 );
311111fa71b9SJerome Forissier }
311211fa71b9SJerome Forissier 
311311fa71b9SJerome Forissier /* msg_len does not include the handshake header */
311411fa71b9SJerome Forissier static size_t ssl_get_reassembly_buffer_size( size_t msg_len,
311511fa71b9SJerome Forissier                                               unsigned add_bitmap )
311611fa71b9SJerome Forissier {
311711fa71b9SJerome Forissier     size_t alloc_len;
311811fa71b9SJerome Forissier 
311911fa71b9SJerome Forissier     alloc_len  = 12;                                 /* Handshake header */
312011fa71b9SJerome Forissier     alloc_len += msg_len;                            /* Content buffer   */
312111fa71b9SJerome Forissier 
312211fa71b9SJerome Forissier     if( add_bitmap )
312311fa71b9SJerome Forissier         alloc_len += msg_len / 8 + ( msg_len % 8 != 0 ); /* Bitmap       */
312411fa71b9SJerome Forissier 
312511fa71b9SJerome Forissier     return( alloc_len );
312611fa71b9SJerome Forissier }
312711fa71b9SJerome Forissier 
312811fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
312911fa71b9SJerome Forissier 
313011fa71b9SJerome Forissier static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl )
313111fa71b9SJerome Forissier {
313211fa71b9SJerome Forissier     return( ( ssl->in_msg[1] << 16 ) |
313311fa71b9SJerome Forissier             ( ssl->in_msg[2] << 8  ) |
313411fa71b9SJerome Forissier               ssl->in_msg[3] );
313511fa71b9SJerome Forissier }
313611fa71b9SJerome Forissier 
313711fa71b9SJerome Forissier int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl )
313811fa71b9SJerome Forissier {
313911fa71b9SJerome Forissier     if( ssl->in_msglen < mbedtls_ssl_hs_hdr_len( ssl ) )
314011fa71b9SJerome Forissier     {
3141*7901324dSJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too short: %" MBEDTLS_PRINTF_SIZET,
314211fa71b9SJerome Forissier                             ssl->in_msglen ) );
314311fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INVALID_RECORD );
314411fa71b9SJerome Forissier     }
314511fa71b9SJerome Forissier 
314611fa71b9SJerome Forissier     ssl->in_hslen = mbedtls_ssl_hs_hdr_len( ssl ) + ssl_get_hs_total_len( ssl );
314711fa71b9SJerome Forissier 
314811fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 3, ( "handshake message: msglen ="
3149*7901324dSJerome Forissier                         " %" MBEDTLS_PRINTF_SIZET ", type = %u, hslen = %" MBEDTLS_PRINTF_SIZET,
315011fa71b9SJerome Forissier                         ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) );
315111fa71b9SJerome Forissier 
315211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
315311fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
315411fa71b9SJerome Forissier     {
315511fa71b9SJerome Forissier         int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
315611fa71b9SJerome Forissier         unsigned int recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5];
315711fa71b9SJerome Forissier 
315811fa71b9SJerome Forissier         if( ssl_check_hs_header( ssl ) != 0 )
315911fa71b9SJerome Forissier         {
316011fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid handshake header" ) );
316111fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INVALID_RECORD );
316211fa71b9SJerome Forissier         }
316311fa71b9SJerome Forissier 
316411fa71b9SJerome Forissier         if( ssl->handshake != NULL &&
316511fa71b9SJerome Forissier             ( ( ssl->state   != MBEDTLS_SSL_HANDSHAKE_OVER &&
316611fa71b9SJerome Forissier                 recv_msg_seq != ssl->handshake->in_msg_seq ) ||
316711fa71b9SJerome Forissier               ( ssl->state  == MBEDTLS_SSL_HANDSHAKE_OVER &&
316811fa71b9SJerome Forissier                 ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) ) )
316911fa71b9SJerome Forissier         {
317011fa71b9SJerome Forissier             if( recv_msg_seq > ssl->handshake->in_msg_seq )
317111fa71b9SJerome Forissier             {
317211fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 2, ( "received future handshake message of sequence number %u (next %u)",
317311fa71b9SJerome Forissier                                             recv_msg_seq,
317411fa71b9SJerome Forissier                                             ssl->handshake->in_msg_seq ) );
317511fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_EARLY_MESSAGE );
317611fa71b9SJerome Forissier             }
317711fa71b9SJerome Forissier 
317811fa71b9SJerome Forissier             /* Retransmit only on last message from previous flight, to avoid
317911fa71b9SJerome Forissier              * too many retransmissions.
318011fa71b9SJerome Forissier              * Besides, No sane server ever retransmits HelloVerifyRequest */
318111fa71b9SJerome Forissier             if( recv_msg_seq == ssl->handshake->in_flight_start_seq - 1 &&
318211fa71b9SJerome Forissier                 ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST )
318311fa71b9SJerome Forissier             {
318411fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 2, ( "received message from last flight, "
3185*7901324dSJerome Forissier                                     "message_seq = %u, start_of_flight = %u",
318611fa71b9SJerome Forissier                                     recv_msg_seq,
318711fa71b9SJerome Forissier                                     ssl->handshake->in_flight_start_seq ) );
318811fa71b9SJerome Forissier 
318911fa71b9SJerome Forissier                 if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 )
319011fa71b9SJerome Forissier                 {
319111fa71b9SJerome Forissier                     MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret );
319211fa71b9SJerome Forissier                     return( ret );
319311fa71b9SJerome Forissier                 }
319411fa71b9SJerome Forissier             }
319511fa71b9SJerome Forissier             else
319611fa71b9SJerome Forissier             {
319711fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 2, ( "dropping out-of-sequence message: "
3198*7901324dSJerome Forissier                                     "message_seq = %u, expected = %u",
319911fa71b9SJerome Forissier                                     recv_msg_seq,
320011fa71b9SJerome Forissier                                     ssl->handshake->in_msg_seq ) );
320111fa71b9SJerome Forissier             }
320211fa71b9SJerome Forissier 
320311fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
320411fa71b9SJerome Forissier         }
320511fa71b9SJerome Forissier         /* Wait until message completion to increment in_msg_seq */
320611fa71b9SJerome Forissier 
320711fa71b9SJerome Forissier         /* Message reassembly is handled alongside buffering of future
320811fa71b9SJerome Forissier          * messages; the commonality is that both handshake fragments and
320911fa71b9SJerome Forissier          * future messages cannot be forwarded immediately to the
321011fa71b9SJerome Forissier          * handshake logic layer. */
321111fa71b9SJerome Forissier         if( ssl_hs_is_proper_fragment( ssl ) == 1 )
321211fa71b9SJerome Forissier         {
321311fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 2, ( "found fragmented DTLS handshake message" ) );
321411fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_EARLY_MESSAGE );
321511fa71b9SJerome Forissier         }
321611fa71b9SJerome Forissier     }
321711fa71b9SJerome Forissier     else
321811fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
321911fa71b9SJerome Forissier     /* With TLS we don't handle fragmentation (for now) */
322011fa71b9SJerome Forissier     if( ssl->in_msglen < ssl->in_hslen )
322111fa71b9SJerome Forissier     {
322211fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLS handshake fragmentation not supported" ) );
322311fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
322411fa71b9SJerome Forissier     }
322511fa71b9SJerome Forissier 
322611fa71b9SJerome Forissier     return( 0 );
322711fa71b9SJerome Forissier }
322811fa71b9SJerome Forissier 
322911fa71b9SJerome Forissier void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl )
323011fa71b9SJerome Forissier {
323111fa71b9SJerome Forissier     mbedtls_ssl_handshake_params * const hs = ssl->handshake;
323211fa71b9SJerome Forissier 
323311fa71b9SJerome Forissier     if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && hs != NULL )
323411fa71b9SJerome Forissier     {
323511fa71b9SJerome Forissier         ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen );
323611fa71b9SJerome Forissier     }
323711fa71b9SJerome Forissier 
323811fa71b9SJerome Forissier     /* Handshake message is complete, increment counter */
323911fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
324011fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
324111fa71b9SJerome Forissier         ssl->handshake != NULL )
324211fa71b9SJerome Forissier     {
324311fa71b9SJerome Forissier         unsigned offset;
324411fa71b9SJerome Forissier         mbedtls_ssl_hs_buffer *hs_buf;
324511fa71b9SJerome Forissier 
324611fa71b9SJerome Forissier         /* Increment handshake sequence number */
324711fa71b9SJerome Forissier         hs->in_msg_seq++;
324811fa71b9SJerome Forissier 
324911fa71b9SJerome Forissier         /*
325011fa71b9SJerome Forissier          * Clear up handshake buffering and reassembly structure.
325111fa71b9SJerome Forissier          */
325211fa71b9SJerome Forissier 
325311fa71b9SJerome Forissier         /* Free first entry */
325411fa71b9SJerome Forissier         ssl_buffering_free_slot( ssl, 0 );
325511fa71b9SJerome Forissier 
325611fa71b9SJerome Forissier         /* Shift all other entries */
325711fa71b9SJerome Forissier         for( offset = 0, hs_buf = &hs->buffering.hs[0];
325811fa71b9SJerome Forissier              offset + 1 < MBEDTLS_SSL_MAX_BUFFERED_HS;
325911fa71b9SJerome Forissier              offset++, hs_buf++ )
326011fa71b9SJerome Forissier         {
326111fa71b9SJerome Forissier             *hs_buf = *(hs_buf + 1);
326211fa71b9SJerome Forissier         }
326311fa71b9SJerome Forissier 
326411fa71b9SJerome Forissier         /* Create a fresh last entry */
326511fa71b9SJerome Forissier         memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) );
326611fa71b9SJerome Forissier     }
326711fa71b9SJerome Forissier #endif
326811fa71b9SJerome Forissier }
326911fa71b9SJerome Forissier 
327011fa71b9SJerome Forissier /*
327111fa71b9SJerome Forissier  * DTLS anti-replay: RFC 6347 4.1.2.6
327211fa71b9SJerome Forissier  *
327311fa71b9SJerome Forissier  * in_window is a field of bits numbered from 0 (lsb) to 63 (msb).
327411fa71b9SJerome Forissier  * Bit n is set iff record number in_window_top - n has been seen.
327511fa71b9SJerome Forissier  *
327611fa71b9SJerome Forissier  * Usually, in_window_top is the last record number seen and the lsb of
327711fa71b9SJerome Forissier  * in_window is set. The only exception is the initial state (record number 0
327811fa71b9SJerome Forissier  * not seen yet).
327911fa71b9SJerome Forissier  */
328011fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
328111fa71b9SJerome Forissier void mbedtls_ssl_dtls_replay_reset( mbedtls_ssl_context *ssl )
328211fa71b9SJerome Forissier {
328311fa71b9SJerome Forissier     ssl->in_window_top = 0;
328411fa71b9SJerome Forissier     ssl->in_window = 0;
328511fa71b9SJerome Forissier }
328611fa71b9SJerome Forissier 
328711fa71b9SJerome Forissier static inline uint64_t ssl_load_six_bytes( unsigned char *buf )
328811fa71b9SJerome Forissier {
328911fa71b9SJerome Forissier     return( ( (uint64_t) buf[0] << 40 ) |
329011fa71b9SJerome Forissier             ( (uint64_t) buf[1] << 32 ) |
329111fa71b9SJerome Forissier             ( (uint64_t) buf[2] << 24 ) |
329211fa71b9SJerome Forissier             ( (uint64_t) buf[3] << 16 ) |
329311fa71b9SJerome Forissier             ( (uint64_t) buf[4] <<  8 ) |
329411fa71b9SJerome Forissier             ( (uint64_t) buf[5]       ) );
329511fa71b9SJerome Forissier }
329611fa71b9SJerome Forissier 
329711fa71b9SJerome Forissier static int mbedtls_ssl_dtls_record_replay_check( mbedtls_ssl_context *ssl, uint8_t *record_in_ctr )
329811fa71b9SJerome Forissier {
329911fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
330011fa71b9SJerome Forissier     unsigned char *original_in_ctr;
330111fa71b9SJerome Forissier 
330211fa71b9SJerome Forissier     // save original in_ctr
330311fa71b9SJerome Forissier     original_in_ctr = ssl->in_ctr;
330411fa71b9SJerome Forissier 
330511fa71b9SJerome Forissier     // use counter from record
330611fa71b9SJerome Forissier     ssl->in_ctr = record_in_ctr;
330711fa71b9SJerome Forissier 
330811fa71b9SJerome Forissier     ret = mbedtls_ssl_dtls_replay_check( (mbedtls_ssl_context const *) ssl );
330911fa71b9SJerome Forissier 
331011fa71b9SJerome Forissier     // restore the counter
331111fa71b9SJerome Forissier     ssl->in_ctr = original_in_ctr;
331211fa71b9SJerome Forissier 
331311fa71b9SJerome Forissier     return ret;
331411fa71b9SJerome Forissier }
331511fa71b9SJerome Forissier 
331611fa71b9SJerome Forissier /*
331711fa71b9SJerome Forissier  * Return 0 if sequence number is acceptable, -1 otherwise
331811fa71b9SJerome Forissier  */
331911fa71b9SJerome Forissier int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context const *ssl )
332011fa71b9SJerome Forissier {
332111fa71b9SJerome Forissier     uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 );
332211fa71b9SJerome Forissier     uint64_t bit;
332311fa71b9SJerome Forissier 
332411fa71b9SJerome Forissier     if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED )
332511fa71b9SJerome Forissier         return( 0 );
332611fa71b9SJerome Forissier 
332711fa71b9SJerome Forissier     if( rec_seqnum > ssl->in_window_top )
332811fa71b9SJerome Forissier         return( 0 );
332911fa71b9SJerome Forissier 
333011fa71b9SJerome Forissier     bit = ssl->in_window_top - rec_seqnum;
333111fa71b9SJerome Forissier 
333211fa71b9SJerome Forissier     if( bit >= 64 )
333311fa71b9SJerome Forissier         return( -1 );
333411fa71b9SJerome Forissier 
333511fa71b9SJerome Forissier     if( ( ssl->in_window & ( (uint64_t) 1 << bit ) ) != 0 )
333611fa71b9SJerome Forissier         return( -1 );
333711fa71b9SJerome Forissier 
333811fa71b9SJerome Forissier     return( 0 );
333911fa71b9SJerome Forissier }
334011fa71b9SJerome Forissier 
334111fa71b9SJerome Forissier /*
334211fa71b9SJerome Forissier  * Update replay window on new validated record
334311fa71b9SJerome Forissier  */
334411fa71b9SJerome Forissier void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl )
334511fa71b9SJerome Forissier {
334611fa71b9SJerome Forissier     uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 );
334711fa71b9SJerome Forissier 
334811fa71b9SJerome Forissier     if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED )
334911fa71b9SJerome Forissier         return;
335011fa71b9SJerome Forissier 
335111fa71b9SJerome Forissier     if( rec_seqnum > ssl->in_window_top )
335211fa71b9SJerome Forissier     {
335311fa71b9SJerome Forissier         /* Update window_top and the contents of the window */
335411fa71b9SJerome Forissier         uint64_t shift = rec_seqnum - ssl->in_window_top;
335511fa71b9SJerome Forissier 
335611fa71b9SJerome Forissier         if( shift >= 64 )
335711fa71b9SJerome Forissier             ssl->in_window = 1;
335811fa71b9SJerome Forissier         else
335911fa71b9SJerome Forissier         {
336011fa71b9SJerome Forissier             ssl->in_window <<= shift;
336111fa71b9SJerome Forissier             ssl->in_window |= 1;
336211fa71b9SJerome Forissier         }
336311fa71b9SJerome Forissier 
336411fa71b9SJerome Forissier         ssl->in_window_top = rec_seqnum;
336511fa71b9SJerome Forissier     }
336611fa71b9SJerome Forissier     else
336711fa71b9SJerome Forissier     {
336811fa71b9SJerome Forissier         /* Mark that number as seen in the current window */
336911fa71b9SJerome Forissier         uint64_t bit = ssl->in_window_top - rec_seqnum;
337011fa71b9SJerome Forissier 
337111fa71b9SJerome Forissier         if( bit < 64 ) /* Always true, but be extra sure */
337211fa71b9SJerome Forissier             ssl->in_window |= (uint64_t) 1 << bit;
337311fa71b9SJerome Forissier     }
337411fa71b9SJerome Forissier }
337511fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */
337611fa71b9SJerome Forissier 
337711fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
337811fa71b9SJerome Forissier /*
337911fa71b9SJerome Forissier  * Without any SSL context, check if a datagram looks like a ClientHello with
338011fa71b9SJerome Forissier  * a valid cookie, and if it doesn't, generate a HelloVerifyRequest message.
338111fa71b9SJerome Forissier  * Both input and output include full DTLS headers.
338211fa71b9SJerome Forissier  *
338311fa71b9SJerome Forissier  * - if cookie is valid, return 0
338411fa71b9SJerome Forissier  * - if ClientHello looks superficially valid but cookie is not,
338511fa71b9SJerome Forissier  *   fill obuf and set olen, then
338611fa71b9SJerome Forissier  *   return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED
338711fa71b9SJerome Forissier  * - otherwise return a specific error code
338811fa71b9SJerome Forissier  */
338911fa71b9SJerome Forissier static int ssl_check_dtls_clihlo_cookie(
339011fa71b9SJerome Forissier                            mbedtls_ssl_cookie_write_t *f_cookie_write,
339111fa71b9SJerome Forissier                            mbedtls_ssl_cookie_check_t *f_cookie_check,
339211fa71b9SJerome Forissier                            void *p_cookie,
339311fa71b9SJerome Forissier                            const unsigned char *cli_id, size_t cli_id_len,
339411fa71b9SJerome Forissier                            const unsigned char *in, size_t in_len,
339511fa71b9SJerome Forissier                            unsigned char *obuf, size_t buf_len, size_t *olen )
339611fa71b9SJerome Forissier {
339711fa71b9SJerome Forissier     size_t sid_len, cookie_len;
339811fa71b9SJerome Forissier     unsigned char *p;
339911fa71b9SJerome Forissier 
340011fa71b9SJerome Forissier     /*
340111fa71b9SJerome Forissier      * Structure of ClientHello with record and handshake headers,
340211fa71b9SJerome Forissier      * and expected values. We don't need to check a lot, more checks will be
340311fa71b9SJerome Forissier      * done when actually parsing the ClientHello - skipping those checks
340411fa71b9SJerome Forissier      * avoids code duplication and does not make cookie forging any easier.
340511fa71b9SJerome Forissier      *
340611fa71b9SJerome Forissier      *  0-0  ContentType type;                  copied, must be handshake
340711fa71b9SJerome Forissier      *  1-2  ProtocolVersion version;           copied
340811fa71b9SJerome Forissier      *  3-4  uint16 epoch;                      copied, must be 0
340911fa71b9SJerome Forissier      *  5-10 uint48 sequence_number;            copied
341011fa71b9SJerome Forissier      * 11-12 uint16 length;                     (ignored)
341111fa71b9SJerome Forissier      *
341211fa71b9SJerome Forissier      * 13-13 HandshakeType msg_type;            (ignored)
341311fa71b9SJerome Forissier      * 14-16 uint24 length;                     (ignored)
341411fa71b9SJerome Forissier      * 17-18 uint16 message_seq;                copied
341511fa71b9SJerome Forissier      * 19-21 uint24 fragment_offset;            copied, must be 0
341611fa71b9SJerome Forissier      * 22-24 uint24 fragment_length;            (ignored)
341711fa71b9SJerome Forissier      *
341811fa71b9SJerome Forissier      * 25-26 ProtocolVersion client_version;    (ignored)
341911fa71b9SJerome Forissier      * 27-58 Random random;                     (ignored)
342011fa71b9SJerome Forissier      * 59-xx SessionID session_id;              1 byte len + sid_len content
342111fa71b9SJerome Forissier      * 60+   opaque cookie<0..2^8-1>;           1 byte len + content
342211fa71b9SJerome Forissier      *       ...
342311fa71b9SJerome Forissier      *
342411fa71b9SJerome Forissier      * Minimum length is 61 bytes.
342511fa71b9SJerome Forissier      */
342611fa71b9SJerome Forissier     if( in_len < 61 ||
342711fa71b9SJerome Forissier         in[0] != MBEDTLS_SSL_MSG_HANDSHAKE ||
342811fa71b9SJerome Forissier         in[3] != 0 || in[4] != 0 ||
342911fa71b9SJerome Forissier         in[19] != 0 || in[20] != 0 || in[21] != 0 )
343011fa71b9SJerome Forissier     {
343111fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
343211fa71b9SJerome Forissier     }
343311fa71b9SJerome Forissier 
343411fa71b9SJerome Forissier     sid_len = in[59];
343511fa71b9SJerome Forissier     if( sid_len > in_len - 61 )
343611fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
343711fa71b9SJerome Forissier 
343811fa71b9SJerome Forissier     cookie_len = in[60 + sid_len];
343911fa71b9SJerome Forissier     if( cookie_len > in_len - 60 )
344011fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
344111fa71b9SJerome Forissier 
344211fa71b9SJerome Forissier     if( f_cookie_check( p_cookie, in + sid_len + 61, cookie_len,
344311fa71b9SJerome Forissier                         cli_id, cli_id_len ) == 0 )
344411fa71b9SJerome Forissier     {
344511fa71b9SJerome Forissier         /* Valid cookie */
344611fa71b9SJerome Forissier         return( 0 );
344711fa71b9SJerome Forissier     }
344811fa71b9SJerome Forissier 
344911fa71b9SJerome Forissier     /*
345011fa71b9SJerome Forissier      * If we get here, we've got an invalid cookie, let's prepare HVR.
345111fa71b9SJerome Forissier      *
345211fa71b9SJerome Forissier      *  0-0  ContentType type;                  copied
345311fa71b9SJerome Forissier      *  1-2  ProtocolVersion version;           copied
345411fa71b9SJerome Forissier      *  3-4  uint16 epoch;                      copied
345511fa71b9SJerome Forissier      *  5-10 uint48 sequence_number;            copied
345611fa71b9SJerome Forissier      * 11-12 uint16 length;                     olen - 13
345711fa71b9SJerome Forissier      *
345811fa71b9SJerome Forissier      * 13-13 HandshakeType msg_type;            hello_verify_request
345911fa71b9SJerome Forissier      * 14-16 uint24 length;                     olen - 25
346011fa71b9SJerome Forissier      * 17-18 uint16 message_seq;                copied
346111fa71b9SJerome Forissier      * 19-21 uint24 fragment_offset;            copied
346211fa71b9SJerome Forissier      * 22-24 uint24 fragment_length;            olen - 25
346311fa71b9SJerome Forissier      *
346411fa71b9SJerome Forissier      * 25-26 ProtocolVersion server_version;    0xfe 0xff
346511fa71b9SJerome Forissier      * 27-27 opaque cookie<0..2^8-1>;           cookie_len = olen - 27, cookie
346611fa71b9SJerome Forissier      *
346711fa71b9SJerome Forissier      * Minimum length is 28.
346811fa71b9SJerome Forissier      */
346911fa71b9SJerome Forissier     if( buf_len < 28 )
347011fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
347111fa71b9SJerome Forissier 
347211fa71b9SJerome Forissier     /* Copy most fields and adapt others */
347311fa71b9SJerome Forissier     memcpy( obuf, in, 25 );
347411fa71b9SJerome Forissier     obuf[13] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST;
347511fa71b9SJerome Forissier     obuf[25] = 0xfe;
347611fa71b9SJerome Forissier     obuf[26] = 0xff;
347711fa71b9SJerome Forissier 
347811fa71b9SJerome Forissier     /* Generate and write actual cookie */
347911fa71b9SJerome Forissier     p = obuf + 28;
348011fa71b9SJerome Forissier     if( f_cookie_write( p_cookie,
348111fa71b9SJerome Forissier                         &p, obuf + buf_len, cli_id, cli_id_len ) != 0 )
348211fa71b9SJerome Forissier     {
348311fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
348411fa71b9SJerome Forissier     }
348511fa71b9SJerome Forissier 
348611fa71b9SJerome Forissier     *olen = p - obuf;
348711fa71b9SJerome Forissier 
348811fa71b9SJerome Forissier     /* Go back and fill length fields */
348911fa71b9SJerome Forissier     obuf[27] = (unsigned char)( *olen - 28 );
349011fa71b9SJerome Forissier 
349111fa71b9SJerome Forissier     obuf[14] = obuf[22] = (unsigned char)( ( *olen - 25 ) >> 16 );
349211fa71b9SJerome Forissier     obuf[15] = obuf[23] = (unsigned char)( ( *olen - 25 ) >>  8 );
349311fa71b9SJerome Forissier     obuf[16] = obuf[24] = (unsigned char)( ( *olen - 25 )       );
349411fa71b9SJerome Forissier 
349511fa71b9SJerome Forissier     obuf[11] = (unsigned char)( ( *olen - 13 ) >>  8 );
349611fa71b9SJerome Forissier     obuf[12] = (unsigned char)( ( *olen - 13 )       );
349711fa71b9SJerome Forissier 
349811fa71b9SJerome Forissier     return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED );
349911fa71b9SJerome Forissier }
350011fa71b9SJerome Forissier 
350111fa71b9SJerome Forissier /*
350211fa71b9SJerome Forissier  * Handle possible client reconnect with the same UDP quadruplet
350311fa71b9SJerome Forissier  * (RFC 6347 Section 4.2.8).
350411fa71b9SJerome Forissier  *
350511fa71b9SJerome Forissier  * Called by ssl_parse_record_header() in case we receive an epoch 0 record
350611fa71b9SJerome Forissier  * that looks like a ClientHello.
350711fa71b9SJerome Forissier  *
350811fa71b9SJerome Forissier  * - if the input looks like a ClientHello without cookies,
350911fa71b9SJerome Forissier  *   send back HelloVerifyRequest, then return 0
351011fa71b9SJerome Forissier  * - if the input looks like a ClientHello with a valid cookie,
351111fa71b9SJerome Forissier  *   reset the session of the current context, and
351211fa71b9SJerome Forissier  *   return MBEDTLS_ERR_SSL_CLIENT_RECONNECT
351311fa71b9SJerome Forissier  * - if anything goes wrong, return a specific error code
351411fa71b9SJerome Forissier  *
351511fa71b9SJerome Forissier  * This function is called (through ssl_check_client_reconnect()) when an
351611fa71b9SJerome Forissier  * unexpected record is found in ssl_get_next_record(), which will discard the
351711fa71b9SJerome Forissier  * record if we return 0, and bubble up the return value otherwise (this
351811fa71b9SJerome Forissier  * includes the case of MBEDTLS_ERR_SSL_CLIENT_RECONNECT and of unexpected
351911fa71b9SJerome Forissier  * errors, and is the right thing to do in both cases).
352011fa71b9SJerome Forissier  */
352111fa71b9SJerome Forissier static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl )
352211fa71b9SJerome Forissier {
352311fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
352411fa71b9SJerome Forissier     size_t len;
352511fa71b9SJerome Forissier 
352611fa71b9SJerome Forissier     if( ssl->conf->f_cookie_write == NULL ||
352711fa71b9SJerome Forissier         ssl->conf->f_cookie_check == NULL )
352811fa71b9SJerome Forissier     {
352911fa71b9SJerome Forissier         /* If we can't use cookies to verify reachability of the peer,
353011fa71b9SJerome Forissier          * drop the record. */
353111fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "no cookie callbacks, "
353211fa71b9SJerome Forissier                                     "can't check reconnect validity" ) );
353311fa71b9SJerome Forissier         return( 0 );
353411fa71b9SJerome Forissier     }
353511fa71b9SJerome Forissier 
353611fa71b9SJerome Forissier     ret = ssl_check_dtls_clihlo_cookie(
353711fa71b9SJerome Forissier             ssl->conf->f_cookie_write,
353811fa71b9SJerome Forissier             ssl->conf->f_cookie_check,
353911fa71b9SJerome Forissier             ssl->conf->p_cookie,
354011fa71b9SJerome Forissier             ssl->cli_id, ssl->cli_id_len,
354111fa71b9SJerome Forissier             ssl->in_buf, ssl->in_left,
354211fa71b9SJerome Forissier             ssl->out_buf, MBEDTLS_SSL_OUT_CONTENT_LEN, &len );
354311fa71b9SJerome Forissier 
354411fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_RET( 2, "ssl_check_dtls_clihlo_cookie", ret );
354511fa71b9SJerome Forissier 
354611fa71b9SJerome Forissier     if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED )
354711fa71b9SJerome Forissier     {
354811fa71b9SJerome Forissier         int send_ret;
354911fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "sending HelloVerifyRequest" ) );
355011fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network",
355111fa71b9SJerome Forissier                                   ssl->out_buf, len );
355211fa71b9SJerome Forissier         /* Don't check write errors as we can't do anything here.
355311fa71b9SJerome Forissier          * If the error is permanent we'll catch it later,
355411fa71b9SJerome Forissier          * if it's not, then hopefully it'll work next time. */
355511fa71b9SJerome Forissier         send_ret = ssl->f_send( ssl->p_bio, ssl->out_buf, len );
355611fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_send", send_ret );
355711fa71b9SJerome Forissier         (void) send_ret;
355811fa71b9SJerome Forissier 
355911fa71b9SJerome Forissier         return( 0 );
356011fa71b9SJerome Forissier     }
356111fa71b9SJerome Forissier 
356211fa71b9SJerome Forissier     if( ret == 0 )
356311fa71b9SJerome Forissier     {
356411fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "cookie is valid, resetting context" ) );
356511fa71b9SJerome Forissier         if( ( ret = mbedtls_ssl_session_reset_int( ssl, 1 ) ) != 0 )
356611fa71b9SJerome Forissier         {
356711fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "reset", ret );
356811fa71b9SJerome Forissier             return( ret );
356911fa71b9SJerome Forissier         }
357011fa71b9SJerome Forissier 
357111fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_CLIENT_RECONNECT );
357211fa71b9SJerome Forissier     }
357311fa71b9SJerome Forissier 
357411fa71b9SJerome Forissier     return( ret );
357511fa71b9SJerome Forissier }
357611fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */
357711fa71b9SJerome Forissier 
357811fa71b9SJerome Forissier static int ssl_check_record_type( uint8_t record_type )
357911fa71b9SJerome Forissier {
358011fa71b9SJerome Forissier     if( record_type != MBEDTLS_SSL_MSG_HANDSHAKE &&
358111fa71b9SJerome Forissier         record_type != MBEDTLS_SSL_MSG_ALERT &&
358211fa71b9SJerome Forissier         record_type != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC &&
358311fa71b9SJerome Forissier         record_type != MBEDTLS_SSL_MSG_APPLICATION_DATA )
358411fa71b9SJerome Forissier     {
358511fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INVALID_RECORD );
358611fa71b9SJerome Forissier     }
358711fa71b9SJerome Forissier 
358811fa71b9SJerome Forissier     return( 0 );
358911fa71b9SJerome Forissier }
359011fa71b9SJerome Forissier 
359111fa71b9SJerome Forissier /*
359211fa71b9SJerome Forissier  * ContentType type;
359311fa71b9SJerome Forissier  * ProtocolVersion version;
359411fa71b9SJerome Forissier  * uint16 epoch;            // DTLS only
359511fa71b9SJerome Forissier  * uint48 sequence_number;  // DTLS only
359611fa71b9SJerome Forissier  * uint16 length;
359711fa71b9SJerome Forissier  *
359811fa71b9SJerome Forissier  * Return 0 if header looks sane (and, for DTLS, the record is expected)
359911fa71b9SJerome Forissier  * MBEDTLS_ERR_SSL_INVALID_RECORD if the header looks bad,
360011fa71b9SJerome Forissier  * MBEDTLS_ERR_SSL_UNEXPECTED_RECORD (DTLS only) if sane but unexpected.
360111fa71b9SJerome Forissier  *
360211fa71b9SJerome Forissier  * With DTLS, mbedtls_ssl_read_record() will:
360311fa71b9SJerome Forissier  * 1. proceed with the record if this function returns 0
360411fa71b9SJerome Forissier  * 2. drop only the current record if this function returns UNEXPECTED_RECORD
360511fa71b9SJerome Forissier  * 3. return CLIENT_RECONNECT if this function return that value
360611fa71b9SJerome Forissier  * 4. drop the whole datagram if this function returns anything else.
360711fa71b9SJerome Forissier  * Point 2 is needed when the peer is resending, and we have already received
360811fa71b9SJerome Forissier  * the first record from a datagram but are still waiting for the others.
360911fa71b9SJerome Forissier  */
361011fa71b9SJerome Forissier static int ssl_parse_record_header( mbedtls_ssl_context const *ssl,
361111fa71b9SJerome Forissier                                     unsigned char *buf,
361211fa71b9SJerome Forissier                                     size_t len,
361311fa71b9SJerome Forissier                                     mbedtls_record *rec )
361411fa71b9SJerome Forissier {
361511fa71b9SJerome Forissier     int major_ver, minor_ver;
361611fa71b9SJerome Forissier 
361711fa71b9SJerome Forissier     size_t const rec_hdr_type_offset    = 0;
361811fa71b9SJerome Forissier     size_t const rec_hdr_type_len       = 1;
361911fa71b9SJerome Forissier 
362011fa71b9SJerome Forissier     size_t const rec_hdr_version_offset = rec_hdr_type_offset +
362111fa71b9SJerome Forissier                                           rec_hdr_type_len;
362211fa71b9SJerome Forissier     size_t const rec_hdr_version_len    = 2;
362311fa71b9SJerome Forissier 
362411fa71b9SJerome Forissier     size_t const rec_hdr_ctr_len        = 8;
362511fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
362611fa71b9SJerome Forissier     uint32_t     rec_epoch;
362711fa71b9SJerome Forissier     size_t const rec_hdr_ctr_offset     = rec_hdr_version_offset +
362811fa71b9SJerome Forissier                                           rec_hdr_version_len;
362911fa71b9SJerome Forissier 
363011fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
363111fa71b9SJerome Forissier     size_t const rec_hdr_cid_offset     = rec_hdr_ctr_offset +
363211fa71b9SJerome Forissier                                           rec_hdr_ctr_len;
363311fa71b9SJerome Forissier     size_t       rec_hdr_cid_len        = 0;
363411fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
363511fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
363611fa71b9SJerome Forissier 
363711fa71b9SJerome Forissier     size_t       rec_hdr_len_offset; /* To be determined */
363811fa71b9SJerome Forissier     size_t const rec_hdr_len_len    = 2;
363911fa71b9SJerome Forissier 
364011fa71b9SJerome Forissier     /*
364111fa71b9SJerome Forissier      * Check minimum lengths for record header.
364211fa71b9SJerome Forissier      */
364311fa71b9SJerome Forissier 
364411fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
364511fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
364611fa71b9SJerome Forissier     {
364711fa71b9SJerome Forissier         rec_hdr_len_offset = rec_hdr_ctr_offset + rec_hdr_ctr_len;
364811fa71b9SJerome Forissier     }
364911fa71b9SJerome Forissier     else
365011fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
365111fa71b9SJerome Forissier     {
365211fa71b9SJerome Forissier         rec_hdr_len_offset = rec_hdr_version_offset + rec_hdr_version_len;
365311fa71b9SJerome Forissier     }
365411fa71b9SJerome Forissier 
365511fa71b9SJerome Forissier     if( len < rec_hdr_len_offset + rec_hdr_len_len )
365611fa71b9SJerome Forissier     {
365711fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "datagram of length %u too small to hold DTLS record header of length %u",
365811fa71b9SJerome Forissier                  (unsigned) len,
365911fa71b9SJerome Forissier                  (unsigned)( rec_hdr_len_len + rec_hdr_len_len ) ) );
366011fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INVALID_RECORD );
366111fa71b9SJerome Forissier     }
366211fa71b9SJerome Forissier 
366311fa71b9SJerome Forissier     /*
366411fa71b9SJerome Forissier      * Parse and validate record content type
366511fa71b9SJerome Forissier      */
366611fa71b9SJerome Forissier 
366711fa71b9SJerome Forissier     rec->type = buf[ rec_hdr_type_offset ];
366811fa71b9SJerome Forissier 
366911fa71b9SJerome Forissier     /* Check record content type */
367011fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
367111fa71b9SJerome Forissier     rec->cid_len = 0;
367211fa71b9SJerome Forissier 
367311fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
367411fa71b9SJerome Forissier         ssl->conf->cid_len != 0                                &&
367511fa71b9SJerome Forissier         rec->type == MBEDTLS_SSL_MSG_CID )
367611fa71b9SJerome Forissier     {
367711fa71b9SJerome Forissier         /* Shift pointers to account for record header including CID
367811fa71b9SJerome Forissier          * struct {
367911fa71b9SJerome Forissier          *   ContentType special_type = tls12_cid;
368011fa71b9SJerome Forissier          *   ProtocolVersion version;
368111fa71b9SJerome Forissier          *   uint16 epoch;
368211fa71b9SJerome Forissier          *   uint48 sequence_number;
368311fa71b9SJerome Forissier          *   opaque cid[cid_length]; // Additional field compared to
368411fa71b9SJerome Forissier          *                           // default DTLS record format
368511fa71b9SJerome Forissier          *   uint16 length;
368611fa71b9SJerome Forissier          *   opaque enc_content[DTLSCiphertext.length];
368711fa71b9SJerome Forissier          * } DTLSCiphertext;
368811fa71b9SJerome Forissier          */
368911fa71b9SJerome Forissier 
369011fa71b9SJerome Forissier         /* So far, we only support static CID lengths
369111fa71b9SJerome Forissier          * fixed in the configuration. */
369211fa71b9SJerome Forissier         rec_hdr_cid_len = ssl->conf->cid_len;
369311fa71b9SJerome Forissier         rec_hdr_len_offset += rec_hdr_cid_len;
369411fa71b9SJerome Forissier 
369511fa71b9SJerome Forissier         if( len < rec_hdr_len_offset + rec_hdr_len_len )
369611fa71b9SJerome Forissier         {
369711fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "datagram of length %u too small to hold DTLS record header including CID, length %u",
369811fa71b9SJerome Forissier                 (unsigned) len,
369911fa71b9SJerome Forissier                 (unsigned)( rec_hdr_len_offset + rec_hdr_len_len ) ) );
370011fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INVALID_RECORD );
370111fa71b9SJerome Forissier         }
370211fa71b9SJerome Forissier 
370311fa71b9SJerome Forissier         /* configured CID len is guaranteed at most 255, see
370411fa71b9SJerome Forissier          * MBEDTLS_SSL_CID_OUT_LEN_MAX in check_config.h */
370511fa71b9SJerome Forissier         rec->cid_len = (uint8_t) rec_hdr_cid_len;
370611fa71b9SJerome Forissier         memcpy( rec->cid, buf + rec_hdr_cid_offset, rec_hdr_cid_len );
370711fa71b9SJerome Forissier     }
370811fa71b9SJerome Forissier     else
370911fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
371011fa71b9SJerome Forissier     {
371111fa71b9SJerome Forissier         if( ssl_check_record_type( rec->type ) )
371211fa71b9SJerome Forissier         {
371311fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type %u",
371411fa71b9SJerome Forissier                                         (unsigned) rec->type ) );
371511fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INVALID_RECORD );
371611fa71b9SJerome Forissier         }
371711fa71b9SJerome Forissier     }
371811fa71b9SJerome Forissier 
371911fa71b9SJerome Forissier     /*
372011fa71b9SJerome Forissier      * Parse and validate record version
372111fa71b9SJerome Forissier      */
372211fa71b9SJerome Forissier 
372311fa71b9SJerome Forissier     rec->ver[0] = buf[ rec_hdr_version_offset + 0 ];
372411fa71b9SJerome Forissier     rec->ver[1] = buf[ rec_hdr_version_offset + 1 ];
372511fa71b9SJerome Forissier     mbedtls_ssl_read_version( &major_ver, &minor_ver,
372611fa71b9SJerome Forissier                               ssl->conf->transport,
372711fa71b9SJerome Forissier                               &rec->ver[0] );
372811fa71b9SJerome Forissier 
372911fa71b9SJerome Forissier     if( major_ver != ssl->major_ver )
373011fa71b9SJerome Forissier     {
373111fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "major version mismatch" ) );
373211fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INVALID_RECORD );
373311fa71b9SJerome Forissier     }
373411fa71b9SJerome Forissier 
373511fa71b9SJerome Forissier     if( minor_ver > ssl->conf->max_minor_ver )
373611fa71b9SJerome Forissier     {
373711fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "minor version mismatch" ) );
373811fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INVALID_RECORD );
373911fa71b9SJerome Forissier     }
374011fa71b9SJerome Forissier 
374111fa71b9SJerome Forissier     /*
374211fa71b9SJerome Forissier      * Parse/Copy record sequence number.
374311fa71b9SJerome Forissier      */
374411fa71b9SJerome Forissier 
374511fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
374611fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
374711fa71b9SJerome Forissier     {
374811fa71b9SJerome Forissier         /* Copy explicit record sequence number from input buffer. */
374911fa71b9SJerome Forissier         memcpy( &rec->ctr[0], buf + rec_hdr_ctr_offset,
375011fa71b9SJerome Forissier                 rec_hdr_ctr_len );
375111fa71b9SJerome Forissier     }
375211fa71b9SJerome Forissier     else
375311fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
375411fa71b9SJerome Forissier     {
375511fa71b9SJerome Forissier         /* Copy implicit record sequence number from SSL context structure. */
375611fa71b9SJerome Forissier         memcpy( &rec->ctr[0], ssl->in_ctr, rec_hdr_ctr_len );
375711fa71b9SJerome Forissier     }
375811fa71b9SJerome Forissier 
375911fa71b9SJerome Forissier     /*
376011fa71b9SJerome Forissier      * Parse record length.
376111fa71b9SJerome Forissier      */
376211fa71b9SJerome Forissier 
376311fa71b9SJerome Forissier     rec->data_offset = rec_hdr_len_offset + rec_hdr_len_len;
376411fa71b9SJerome Forissier     rec->data_len    = ( (size_t) buf[ rec_hdr_len_offset + 0 ] << 8 ) |
376511fa71b9SJerome Forissier                        ( (size_t) buf[ rec_hdr_len_offset + 1 ] << 0 );
376611fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_BUF( 4, "input record header", buf, rec->data_offset );
376711fa71b9SJerome Forissier 
3768*7901324dSJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 3, ( "input record: msgtype = %u, "
3769*7901324dSJerome Forissier                                 "version = [%d:%d], msglen = %" MBEDTLS_PRINTF_SIZET,
377011fa71b9SJerome Forissier                                 rec->type,
377111fa71b9SJerome Forissier                                 major_ver, minor_ver, rec->data_len ) );
377211fa71b9SJerome Forissier 
377311fa71b9SJerome Forissier     rec->buf     = buf;
377411fa71b9SJerome Forissier     rec->buf_len = rec->data_offset + rec->data_len;
377511fa71b9SJerome Forissier 
377611fa71b9SJerome Forissier     if( rec->data_len == 0 )
377711fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INVALID_RECORD );
377811fa71b9SJerome Forissier 
377911fa71b9SJerome Forissier     /*
378011fa71b9SJerome Forissier      * DTLS-related tests.
378111fa71b9SJerome Forissier      * Check epoch before checking length constraint because
378211fa71b9SJerome Forissier      * the latter varies with the epoch. E.g., if a ChangeCipherSpec
378311fa71b9SJerome Forissier      * message gets duplicated before the corresponding Finished message,
378411fa71b9SJerome Forissier      * the second ChangeCipherSpec should be discarded because it belongs
378511fa71b9SJerome Forissier      * to an old epoch, but not because its length is shorter than
378611fa71b9SJerome Forissier      * the minimum record length for packets using the new record transform.
378711fa71b9SJerome Forissier      * Note that these two kinds of failures are handled differently,
378811fa71b9SJerome Forissier      * as an unexpected record is silently skipped but an invalid
378911fa71b9SJerome Forissier      * record leads to the entire datagram being dropped.
379011fa71b9SJerome Forissier      */
379111fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
379211fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
379311fa71b9SJerome Forissier     {
379411fa71b9SJerome Forissier         rec_epoch = ( rec->ctr[0] << 8 ) | rec->ctr[1];
379511fa71b9SJerome Forissier 
379611fa71b9SJerome Forissier         /* Check that the datagram is large enough to contain a record
379711fa71b9SJerome Forissier          * of the advertised length. */
379811fa71b9SJerome Forissier         if( len < rec->data_offset + rec->data_len )
379911fa71b9SJerome Forissier         {
380011fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "Datagram of length %u too small to contain record of advertised length %u.",
380111fa71b9SJerome Forissier                              (unsigned) len,
380211fa71b9SJerome Forissier                              (unsigned)( rec->data_offset + rec->data_len ) ) );
380311fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INVALID_RECORD );
380411fa71b9SJerome Forissier         }
380511fa71b9SJerome Forissier 
380611fa71b9SJerome Forissier         /* Records from other, non-matching epochs are silently discarded.
380711fa71b9SJerome Forissier          * (The case of same-port Client reconnects must be considered in
380811fa71b9SJerome Forissier          *  the caller). */
380911fa71b9SJerome Forissier         if( rec_epoch != ssl->in_epoch )
381011fa71b9SJerome Forissier         {
381111fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "record from another epoch: "
3812*7901324dSJerome Forissier                                         "expected %u, received %lu",
3813*7901324dSJerome Forissier                                         ssl->in_epoch, (unsigned long) rec_epoch ) );
381411fa71b9SJerome Forissier 
381511fa71b9SJerome Forissier             /* Records from the next epoch are considered for buffering
381611fa71b9SJerome Forissier              * (concretely: early Finished messages). */
381711fa71b9SJerome Forissier             if( rec_epoch == (unsigned) ssl->in_epoch + 1 )
381811fa71b9SJerome Forissier             {
381911fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 2, ( "Consider record for buffering" ) );
382011fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_EARLY_MESSAGE );
382111fa71b9SJerome Forissier             }
382211fa71b9SJerome Forissier 
382311fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
382411fa71b9SJerome Forissier         }
382511fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
382611fa71b9SJerome Forissier         /* For records from the correct epoch, check whether their
382711fa71b9SJerome Forissier          * sequence number has been seen before. */
382811fa71b9SJerome Forissier         else if( mbedtls_ssl_dtls_record_replay_check( (mbedtls_ssl_context *) ssl,
382911fa71b9SJerome Forissier             &rec->ctr[0] ) != 0 )
383011fa71b9SJerome Forissier         {
383111fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "replayed record" ) );
383211fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
383311fa71b9SJerome Forissier         }
383411fa71b9SJerome Forissier #endif
383511fa71b9SJerome Forissier     }
383611fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
383711fa71b9SJerome Forissier 
383811fa71b9SJerome Forissier     return( 0 );
383911fa71b9SJerome Forissier }
384011fa71b9SJerome Forissier 
384111fa71b9SJerome Forissier 
384211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
384311fa71b9SJerome Forissier static int ssl_check_client_reconnect( mbedtls_ssl_context *ssl )
384411fa71b9SJerome Forissier {
384511fa71b9SJerome Forissier     unsigned int rec_epoch = ( ssl->in_ctr[0] << 8 ) | ssl->in_ctr[1];
384611fa71b9SJerome Forissier 
384711fa71b9SJerome Forissier     /*
384811fa71b9SJerome Forissier      * Check for an epoch 0 ClientHello. We can't use in_msg here to
384911fa71b9SJerome Forissier      * access the first byte of record content (handshake type), as we
385011fa71b9SJerome Forissier      * have an active transform (possibly iv_len != 0), so use the
385111fa71b9SJerome Forissier      * fact that the record header len is 13 instead.
385211fa71b9SJerome Forissier      */
385311fa71b9SJerome Forissier     if( rec_epoch == 0 &&
385411fa71b9SJerome Forissier         ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
385511fa71b9SJerome Forissier         ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER &&
385611fa71b9SJerome Forissier         ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
385711fa71b9SJerome Forissier         ssl->in_left > 13 &&
385811fa71b9SJerome Forissier         ssl->in_buf[13] == MBEDTLS_SSL_HS_CLIENT_HELLO )
385911fa71b9SJerome Forissier     {
386011fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "possible client reconnect "
386111fa71b9SJerome Forissier                                     "from the same port" ) );
386211fa71b9SJerome Forissier         return( ssl_handle_possible_reconnect( ssl ) );
386311fa71b9SJerome Forissier     }
386411fa71b9SJerome Forissier 
386511fa71b9SJerome Forissier     return( 0 );
386611fa71b9SJerome Forissier }
386711fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */
386811fa71b9SJerome Forissier 
386911fa71b9SJerome Forissier /*
387011fa71b9SJerome Forissier  * If applicable, decrypt record content
387111fa71b9SJerome Forissier  */
387211fa71b9SJerome Forissier static int ssl_prepare_record_content( mbedtls_ssl_context *ssl,
387311fa71b9SJerome Forissier                                        mbedtls_record *rec )
387411fa71b9SJerome Forissier {
387511fa71b9SJerome Forissier     int ret, done = 0;
387611fa71b9SJerome Forissier 
387711fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_BUF( 4, "input record from network",
387811fa71b9SJerome Forissier                            rec->buf, rec->buf_len );
387911fa71b9SJerome Forissier 
388011fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
388111fa71b9SJerome Forissier     if( mbedtls_ssl_hw_record_read != NULL )
388211fa71b9SJerome Forissier     {
388311fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_read()" ) );
388411fa71b9SJerome Forissier 
388511fa71b9SJerome Forissier         ret = mbedtls_ssl_hw_record_read( ssl );
388611fa71b9SJerome Forissier         if( ret != 0 && ret != MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH )
388711fa71b9SJerome Forissier         {
388811fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_read", ret );
388911fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
389011fa71b9SJerome Forissier         }
389111fa71b9SJerome Forissier 
389211fa71b9SJerome Forissier         if( ret == 0 )
389311fa71b9SJerome Forissier             done = 1;
389411fa71b9SJerome Forissier     }
389511fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */
389611fa71b9SJerome Forissier     if( !done && ssl->transform_in != NULL )
389711fa71b9SJerome Forissier     {
389811fa71b9SJerome Forissier         unsigned char const old_msg_type = rec->type;
389911fa71b9SJerome Forissier 
390011fa71b9SJerome Forissier         if( ( ret = mbedtls_ssl_decrypt_buf( ssl, ssl->transform_in,
390111fa71b9SJerome Forissier                                              rec ) ) != 0 )
390211fa71b9SJerome Forissier         {
390311fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decrypt_buf", ret );
390411fa71b9SJerome Forissier 
390511fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
390611fa71b9SJerome Forissier             if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_CID &&
390711fa71b9SJerome Forissier                 ssl->conf->ignore_unexpected_cid
390811fa71b9SJerome Forissier                     == MBEDTLS_SSL_UNEXPECTED_CID_IGNORE )
390911fa71b9SJerome Forissier             {
391011fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 3, ( "ignoring unexpected CID" ) );
391111fa71b9SJerome Forissier                 ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING;
391211fa71b9SJerome Forissier             }
391311fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
391411fa71b9SJerome Forissier 
391511fa71b9SJerome Forissier             return( ret );
391611fa71b9SJerome Forissier         }
391711fa71b9SJerome Forissier 
391811fa71b9SJerome Forissier         if( old_msg_type != rec->type )
391911fa71b9SJerome Forissier         {
392011fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 4, ( "record type after decrypt (before %d): %d",
392111fa71b9SJerome Forissier                                         old_msg_type, rec->type ) );
392211fa71b9SJerome Forissier         }
392311fa71b9SJerome Forissier 
392411fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_BUF( 4, "input payload after decrypt",
392511fa71b9SJerome Forissier                                rec->buf + rec->data_offset, rec->data_len );
392611fa71b9SJerome Forissier 
392711fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
392811fa71b9SJerome Forissier         /* We have already checked the record content type
392911fa71b9SJerome Forissier          * in ssl_parse_record_header(), failing or silently
393011fa71b9SJerome Forissier          * dropping the record in the case of an unknown type.
393111fa71b9SJerome Forissier          *
393211fa71b9SJerome Forissier          * Since with the use of CIDs, the record content type
393311fa71b9SJerome Forissier          * might change during decryption, re-check the record
393411fa71b9SJerome Forissier          * content type, but treat a failure as fatal this time. */
393511fa71b9SJerome Forissier         if( ssl_check_record_type( rec->type ) )
393611fa71b9SJerome Forissier         {
393711fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type" ) );
393811fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INVALID_RECORD );
393911fa71b9SJerome Forissier         }
394011fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
394111fa71b9SJerome Forissier 
394211fa71b9SJerome Forissier         if( rec->data_len == 0 )
394311fa71b9SJerome Forissier         {
394411fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
394511fa71b9SJerome Forissier             if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3
394611fa71b9SJerome Forissier                 && rec->type != MBEDTLS_SSL_MSG_APPLICATION_DATA )
394711fa71b9SJerome Forissier             {
394811fa71b9SJerome Forissier                 /* TLS v1.2 explicitly disallows zero-length messages which are not application data */
394911fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid zero-length message type: %d", ssl->in_msgtype ) );
395011fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_INVALID_RECORD );
395111fa71b9SJerome Forissier             }
395211fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
395311fa71b9SJerome Forissier 
395411fa71b9SJerome Forissier             ssl->nb_zero++;
395511fa71b9SJerome Forissier 
395611fa71b9SJerome Forissier             /*
395711fa71b9SJerome Forissier              * Three or more empty messages may be a DoS attack
395811fa71b9SJerome Forissier              * (excessive CPU consumption).
395911fa71b9SJerome Forissier              */
396011fa71b9SJerome Forissier             if( ssl->nb_zero > 3 )
396111fa71b9SJerome Forissier             {
396211fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "received four consecutive empty "
396311fa71b9SJerome Forissier                                             "messages, possible DoS attack" ) );
396411fa71b9SJerome Forissier                 /* Treat the records as if they were not properly authenticated,
396511fa71b9SJerome Forissier                  * thereby failing the connection if we see more than allowed
396611fa71b9SJerome Forissier                  * by the configured bad MAC threshold. */
396711fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_INVALID_MAC );
396811fa71b9SJerome Forissier             }
396911fa71b9SJerome Forissier         }
397011fa71b9SJerome Forissier         else
397111fa71b9SJerome Forissier             ssl->nb_zero = 0;
397211fa71b9SJerome Forissier 
397311fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
397411fa71b9SJerome Forissier         if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
397511fa71b9SJerome Forissier         {
397611fa71b9SJerome Forissier             ; /* in_ctr read from peer, not maintained internally */
397711fa71b9SJerome Forissier         }
397811fa71b9SJerome Forissier         else
397911fa71b9SJerome Forissier #endif
398011fa71b9SJerome Forissier         {
398111fa71b9SJerome Forissier             unsigned i;
398211fa71b9SJerome Forissier             for( i = 8; i > mbedtls_ssl_ep_len( ssl ); i-- )
398311fa71b9SJerome Forissier                 if( ++ssl->in_ctr[i - 1] != 0 )
398411fa71b9SJerome Forissier                     break;
398511fa71b9SJerome Forissier 
398611fa71b9SJerome Forissier             /* The loop goes to its end iff the counter is wrapping */
398711fa71b9SJerome Forissier             if( i == mbedtls_ssl_ep_len( ssl ) )
398811fa71b9SJerome Forissier             {
398911fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "incoming message counter would wrap" ) );
399011fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING );
399111fa71b9SJerome Forissier             }
399211fa71b9SJerome Forissier         }
399311fa71b9SJerome Forissier 
399411fa71b9SJerome Forissier     }
399511fa71b9SJerome Forissier 
399611fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
399711fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
399811fa71b9SJerome Forissier     {
399911fa71b9SJerome Forissier         mbedtls_ssl_dtls_replay_update( ssl );
400011fa71b9SJerome Forissier     }
400111fa71b9SJerome Forissier #endif
400211fa71b9SJerome Forissier 
400311fa71b9SJerome Forissier     /* Check actual (decrypted) record content length against
400411fa71b9SJerome Forissier      * configured maximum. */
400511fa71b9SJerome Forissier     if( ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN )
400611fa71b9SJerome Forissier     {
400711fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
400811fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INVALID_RECORD );
400911fa71b9SJerome Forissier     }
401011fa71b9SJerome Forissier 
401111fa71b9SJerome Forissier     return( 0 );
401211fa71b9SJerome Forissier }
401311fa71b9SJerome Forissier 
401411fa71b9SJerome Forissier /*
401511fa71b9SJerome Forissier  * Read a record.
401611fa71b9SJerome Forissier  *
401711fa71b9SJerome Forissier  * Silently ignore non-fatal alert (and for DTLS, invalid records as well,
401811fa71b9SJerome Forissier  * RFC 6347 4.1.2.7) and continue reading until a valid record is found.
401911fa71b9SJerome Forissier  *
402011fa71b9SJerome Forissier  */
402111fa71b9SJerome Forissier 
402211fa71b9SJerome Forissier /* Helper functions for mbedtls_ssl_read_record(). */
402311fa71b9SJerome Forissier static int ssl_consume_current_message( mbedtls_ssl_context *ssl );
402411fa71b9SJerome Forissier static int ssl_get_next_record( mbedtls_ssl_context *ssl );
402511fa71b9SJerome Forissier static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl );
402611fa71b9SJerome Forissier 
402711fa71b9SJerome Forissier int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl,
402811fa71b9SJerome Forissier                              unsigned update_hs_digest )
402911fa71b9SJerome Forissier {
403011fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
403111fa71b9SJerome Forissier 
403211fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read record" ) );
403311fa71b9SJerome Forissier 
403411fa71b9SJerome Forissier     if( ssl->keep_current_message == 0 )
403511fa71b9SJerome Forissier     {
403611fa71b9SJerome Forissier         do {
403711fa71b9SJerome Forissier 
403811fa71b9SJerome Forissier             ret = ssl_consume_current_message( ssl );
403911fa71b9SJerome Forissier             if( ret != 0 )
404011fa71b9SJerome Forissier                 return( ret );
404111fa71b9SJerome Forissier 
404211fa71b9SJerome Forissier             if( ssl_record_is_in_progress( ssl ) == 0 )
404311fa71b9SJerome Forissier             {
404411fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
404511fa71b9SJerome Forissier                 int have_buffered = 0;
404611fa71b9SJerome Forissier 
404711fa71b9SJerome Forissier                 /* We only check for buffered messages if the
404811fa71b9SJerome Forissier                  * current datagram is fully consumed. */
404911fa71b9SJerome Forissier                 if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
405011fa71b9SJerome Forissier                     ssl_next_record_is_in_datagram( ssl ) == 0 )
405111fa71b9SJerome Forissier                 {
405211fa71b9SJerome Forissier                     if( ssl_load_buffered_message( ssl ) == 0 )
405311fa71b9SJerome Forissier                         have_buffered = 1;
405411fa71b9SJerome Forissier                 }
405511fa71b9SJerome Forissier 
405611fa71b9SJerome Forissier                 if( have_buffered == 0 )
405711fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
405811fa71b9SJerome Forissier                 {
405911fa71b9SJerome Forissier                     ret = ssl_get_next_record( ssl );
406011fa71b9SJerome Forissier                     if( ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING )
406111fa71b9SJerome Forissier                         continue;
406211fa71b9SJerome Forissier 
406311fa71b9SJerome Forissier                     if( ret != 0 )
406411fa71b9SJerome Forissier                     {
406511fa71b9SJerome Forissier                         MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_get_next_record" ), ret );
406611fa71b9SJerome Forissier                         return( ret );
406711fa71b9SJerome Forissier                     }
406811fa71b9SJerome Forissier                 }
406911fa71b9SJerome Forissier             }
407011fa71b9SJerome Forissier 
407111fa71b9SJerome Forissier             ret = mbedtls_ssl_handle_message_type( ssl );
407211fa71b9SJerome Forissier 
407311fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
407411fa71b9SJerome Forissier             if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE )
407511fa71b9SJerome Forissier             {
407611fa71b9SJerome Forissier                 /* Buffer future message */
407711fa71b9SJerome Forissier                 ret = ssl_buffer_message( ssl );
407811fa71b9SJerome Forissier                 if( ret != 0 )
407911fa71b9SJerome Forissier                     return( ret );
408011fa71b9SJerome Forissier 
408111fa71b9SJerome Forissier                 ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING;
408211fa71b9SJerome Forissier             }
408311fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
408411fa71b9SJerome Forissier 
408511fa71b9SJerome Forissier         } while( MBEDTLS_ERR_SSL_NON_FATAL           == ret  ||
408611fa71b9SJerome Forissier                  MBEDTLS_ERR_SSL_CONTINUE_PROCESSING == ret );
408711fa71b9SJerome Forissier 
408811fa71b9SJerome Forissier         if( 0 != ret )
408911fa71b9SJerome Forissier         {
409011fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_handle_message_type" ), ret );
409111fa71b9SJerome Forissier             return( ret );
409211fa71b9SJerome Forissier         }
409311fa71b9SJerome Forissier 
409411fa71b9SJerome Forissier         if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
409511fa71b9SJerome Forissier             update_hs_digest == 1 )
409611fa71b9SJerome Forissier         {
409711fa71b9SJerome Forissier             mbedtls_ssl_update_handshake_status( ssl );
409811fa71b9SJerome Forissier         }
409911fa71b9SJerome Forissier     }
410011fa71b9SJerome Forissier     else
410111fa71b9SJerome Forissier     {
410211fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 2, ( "reuse previously read message" ) );
410311fa71b9SJerome Forissier         ssl->keep_current_message = 0;
410411fa71b9SJerome Forissier     }
410511fa71b9SJerome Forissier 
410611fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read record" ) );
410711fa71b9SJerome Forissier 
410811fa71b9SJerome Forissier     return( 0 );
410911fa71b9SJerome Forissier }
411011fa71b9SJerome Forissier 
411111fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
411211fa71b9SJerome Forissier static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl )
411311fa71b9SJerome Forissier {
411411fa71b9SJerome Forissier     if( ssl->in_left > ssl->next_record_offset )
411511fa71b9SJerome Forissier         return( 1 );
411611fa71b9SJerome Forissier 
411711fa71b9SJerome Forissier     return( 0 );
411811fa71b9SJerome Forissier }
411911fa71b9SJerome Forissier 
412011fa71b9SJerome Forissier static int ssl_load_buffered_message( mbedtls_ssl_context *ssl )
412111fa71b9SJerome Forissier {
412211fa71b9SJerome Forissier     mbedtls_ssl_handshake_params * const hs = ssl->handshake;
412311fa71b9SJerome Forissier     mbedtls_ssl_hs_buffer * hs_buf;
412411fa71b9SJerome Forissier     int ret = 0;
412511fa71b9SJerome Forissier 
412611fa71b9SJerome Forissier     if( hs == NULL )
412711fa71b9SJerome Forissier         return( -1 );
412811fa71b9SJerome Forissier 
412911fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_messsage" ) );
413011fa71b9SJerome Forissier 
413111fa71b9SJerome Forissier     if( ssl->state == MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC ||
413211fa71b9SJerome Forissier         ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC )
413311fa71b9SJerome Forissier     {
413411fa71b9SJerome Forissier         /* Check if we have seen a ChangeCipherSpec before.
413511fa71b9SJerome Forissier          * If yes, synthesize a CCS record. */
413611fa71b9SJerome Forissier         if( !hs->buffering.seen_ccs )
413711fa71b9SJerome Forissier         {
413811fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 2, ( "CCS not seen in the current flight" ) );
413911fa71b9SJerome Forissier             ret = -1;
414011fa71b9SJerome Forissier             goto exit;
414111fa71b9SJerome Forissier         }
414211fa71b9SJerome Forissier 
414311fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 2, ( "Injecting buffered CCS message" ) );
414411fa71b9SJerome Forissier         ssl->in_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC;
414511fa71b9SJerome Forissier         ssl->in_msglen = 1;
414611fa71b9SJerome Forissier         ssl->in_msg[0] = 1;
414711fa71b9SJerome Forissier 
414811fa71b9SJerome Forissier         /* As long as they are equal, the exact value doesn't matter. */
414911fa71b9SJerome Forissier         ssl->in_left            = 0;
415011fa71b9SJerome Forissier         ssl->next_record_offset = 0;
415111fa71b9SJerome Forissier 
415211fa71b9SJerome Forissier         hs->buffering.seen_ccs = 0;
415311fa71b9SJerome Forissier         goto exit;
415411fa71b9SJerome Forissier     }
415511fa71b9SJerome Forissier 
415611fa71b9SJerome Forissier #if defined(MBEDTLS_DEBUG_C)
415711fa71b9SJerome Forissier     /* Debug only */
415811fa71b9SJerome Forissier     {
415911fa71b9SJerome Forissier         unsigned offset;
416011fa71b9SJerome Forissier         for( offset = 1; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++ )
416111fa71b9SJerome Forissier         {
416211fa71b9SJerome Forissier             hs_buf = &hs->buffering.hs[offset];
416311fa71b9SJerome Forissier             if( hs_buf->is_valid == 1 )
416411fa71b9SJerome Forissier             {
416511fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 2, ( "Future message with sequence number %u %s buffered.",
416611fa71b9SJerome Forissier                             hs->in_msg_seq + offset,
416711fa71b9SJerome Forissier                             hs_buf->is_complete ? "fully" : "partially" ) );
416811fa71b9SJerome Forissier             }
416911fa71b9SJerome Forissier         }
417011fa71b9SJerome Forissier     }
417111fa71b9SJerome Forissier #endif /* MBEDTLS_DEBUG_C */
417211fa71b9SJerome Forissier 
417311fa71b9SJerome Forissier     /* Check if we have buffered and/or fully reassembled the
417411fa71b9SJerome Forissier      * next handshake message. */
417511fa71b9SJerome Forissier     hs_buf = &hs->buffering.hs[0];
417611fa71b9SJerome Forissier     if( ( hs_buf->is_valid == 1 ) && ( hs_buf->is_complete == 1 ) )
417711fa71b9SJerome Forissier     {
417811fa71b9SJerome Forissier         /* Synthesize a record containing the buffered HS message. */
417911fa71b9SJerome Forissier         size_t msg_len = ( hs_buf->data[1] << 16 ) |
418011fa71b9SJerome Forissier                          ( hs_buf->data[2] << 8  ) |
418111fa71b9SJerome Forissier                            hs_buf->data[3];
418211fa71b9SJerome Forissier 
418311fa71b9SJerome Forissier         /* Double-check that we haven't accidentally buffered
418411fa71b9SJerome Forissier          * a message that doesn't fit into the input buffer. */
418511fa71b9SJerome Forissier         if( msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN )
418611fa71b9SJerome Forissier         {
418711fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
418811fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
418911fa71b9SJerome Forissier         }
419011fa71b9SJerome Forissier 
419111fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 2, ( "Next handshake message has been buffered - load" ) );
419211fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered handshake message (incl. header)",
419311fa71b9SJerome Forissier                                hs_buf->data, msg_len + 12 );
419411fa71b9SJerome Forissier 
419511fa71b9SJerome Forissier         ssl->in_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
419611fa71b9SJerome Forissier         ssl->in_hslen   = msg_len + 12;
419711fa71b9SJerome Forissier         ssl->in_msglen  = msg_len + 12;
419811fa71b9SJerome Forissier         memcpy( ssl->in_msg, hs_buf->data, ssl->in_hslen );
419911fa71b9SJerome Forissier 
420011fa71b9SJerome Forissier         ret = 0;
420111fa71b9SJerome Forissier         goto exit;
420211fa71b9SJerome Forissier     }
420311fa71b9SJerome Forissier     else
420411fa71b9SJerome Forissier     {
420511fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 2, ( "Next handshake message %u not or only partially bufffered",
420611fa71b9SJerome Forissier                                     hs->in_msg_seq ) );
420711fa71b9SJerome Forissier     }
420811fa71b9SJerome Forissier 
420911fa71b9SJerome Forissier     ret = -1;
421011fa71b9SJerome Forissier 
421111fa71b9SJerome Forissier exit:
421211fa71b9SJerome Forissier 
421311fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_load_buffered_message" ) );
421411fa71b9SJerome Forissier     return( ret );
421511fa71b9SJerome Forissier }
421611fa71b9SJerome Forissier 
421711fa71b9SJerome Forissier static int ssl_buffer_make_space( mbedtls_ssl_context *ssl,
421811fa71b9SJerome Forissier                                   size_t desired )
421911fa71b9SJerome Forissier {
422011fa71b9SJerome Forissier     int offset;
422111fa71b9SJerome Forissier     mbedtls_ssl_handshake_params * const hs = ssl->handshake;
422211fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "Attempt to free buffered messages to have %u bytes available",
422311fa71b9SJerome Forissier                                 (unsigned) desired ) );
422411fa71b9SJerome Forissier 
422511fa71b9SJerome Forissier     /* Get rid of future records epoch first, if such exist. */
422611fa71b9SJerome Forissier     ssl_free_buffered_record( ssl );
422711fa71b9SJerome Forissier 
422811fa71b9SJerome Forissier     /* Check if we have enough space available now. */
422911fa71b9SJerome Forissier     if( desired <= ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
423011fa71b9SJerome Forissier                      hs->buffering.total_bytes_buffered ) )
423111fa71b9SJerome Forissier     {
423211fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 2, ( "Enough space available after freeing future epoch record" ) );
423311fa71b9SJerome Forissier         return( 0 );
423411fa71b9SJerome Forissier     }
423511fa71b9SJerome Forissier 
423611fa71b9SJerome Forissier     /* We don't have enough space to buffer the next expected handshake
423711fa71b9SJerome Forissier      * message. Remove buffers used for future messages to gain space,
423811fa71b9SJerome Forissier      * starting with the most distant one. */
423911fa71b9SJerome Forissier     for( offset = MBEDTLS_SSL_MAX_BUFFERED_HS - 1;
424011fa71b9SJerome Forissier          offset >= 0; offset-- )
424111fa71b9SJerome Forissier     {
424211fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 2, ( "Free buffering slot %d to make space for reassembly of next handshake message",
424311fa71b9SJerome Forissier                                     offset ) );
424411fa71b9SJerome Forissier 
424511fa71b9SJerome Forissier         ssl_buffering_free_slot( ssl, (uint8_t) offset );
424611fa71b9SJerome Forissier 
424711fa71b9SJerome Forissier         /* Check if we have enough space available now. */
424811fa71b9SJerome Forissier         if( desired <= ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
424911fa71b9SJerome Forissier                          hs->buffering.total_bytes_buffered ) )
425011fa71b9SJerome Forissier         {
425111fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 2, ( "Enough space available after freeing buffered HS messages" ) );
425211fa71b9SJerome Forissier             return( 0 );
425311fa71b9SJerome Forissier         }
425411fa71b9SJerome Forissier     }
425511fa71b9SJerome Forissier 
425611fa71b9SJerome Forissier     return( -1 );
425711fa71b9SJerome Forissier }
425811fa71b9SJerome Forissier 
425911fa71b9SJerome Forissier static int ssl_buffer_message( mbedtls_ssl_context *ssl )
426011fa71b9SJerome Forissier {
426111fa71b9SJerome Forissier     int ret = 0;
426211fa71b9SJerome Forissier     mbedtls_ssl_handshake_params * const hs = ssl->handshake;
426311fa71b9SJerome Forissier 
426411fa71b9SJerome Forissier     if( hs == NULL )
426511fa71b9SJerome Forissier         return( 0 );
426611fa71b9SJerome Forissier 
426711fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_buffer_message" ) );
426811fa71b9SJerome Forissier 
426911fa71b9SJerome Forissier     switch( ssl->in_msgtype )
427011fa71b9SJerome Forissier     {
427111fa71b9SJerome Forissier         case MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC:
427211fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 2, ( "Remember CCS message" ) );
427311fa71b9SJerome Forissier 
427411fa71b9SJerome Forissier             hs->buffering.seen_ccs = 1;
427511fa71b9SJerome Forissier             break;
427611fa71b9SJerome Forissier 
427711fa71b9SJerome Forissier         case MBEDTLS_SSL_MSG_HANDSHAKE:
427811fa71b9SJerome Forissier         {
427911fa71b9SJerome Forissier             unsigned recv_msg_seq_offset;
428011fa71b9SJerome Forissier             unsigned recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5];
428111fa71b9SJerome Forissier             mbedtls_ssl_hs_buffer *hs_buf;
428211fa71b9SJerome Forissier             size_t msg_len = ssl->in_hslen - 12;
428311fa71b9SJerome Forissier 
428411fa71b9SJerome Forissier             /* We should never receive an old handshake
428511fa71b9SJerome Forissier              * message - double-check nonetheless. */
428611fa71b9SJerome Forissier             if( recv_msg_seq < ssl->handshake->in_msg_seq )
428711fa71b9SJerome Forissier             {
428811fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
428911fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
429011fa71b9SJerome Forissier             }
429111fa71b9SJerome Forissier 
429211fa71b9SJerome Forissier             recv_msg_seq_offset = recv_msg_seq - ssl->handshake->in_msg_seq;
429311fa71b9SJerome Forissier             if( recv_msg_seq_offset >= MBEDTLS_SSL_MAX_BUFFERED_HS )
429411fa71b9SJerome Forissier             {
429511fa71b9SJerome Forissier                 /* Silently ignore -- message too far in the future */
429611fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 2,
429711fa71b9SJerome Forissier                  ( "Ignore future HS message with sequence number %u, "
429811fa71b9SJerome Forissier                    "buffering window %u - %u",
429911fa71b9SJerome Forissier                    recv_msg_seq, ssl->handshake->in_msg_seq,
430011fa71b9SJerome Forissier                    ssl->handshake->in_msg_seq + MBEDTLS_SSL_MAX_BUFFERED_HS - 1 ) );
430111fa71b9SJerome Forissier 
430211fa71b9SJerome Forissier                 goto exit;
430311fa71b9SJerome Forissier             }
430411fa71b9SJerome Forissier 
430511fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering HS message with sequence number %u, offset %u ",
430611fa71b9SJerome Forissier                                         recv_msg_seq, recv_msg_seq_offset ) );
430711fa71b9SJerome Forissier 
430811fa71b9SJerome Forissier             hs_buf = &hs->buffering.hs[ recv_msg_seq_offset ];
430911fa71b9SJerome Forissier 
431011fa71b9SJerome Forissier             /* Check if the buffering for this seq nr has already commenced. */
431111fa71b9SJerome Forissier             if( !hs_buf->is_valid )
431211fa71b9SJerome Forissier             {
431311fa71b9SJerome Forissier                 size_t reassembly_buf_sz;
431411fa71b9SJerome Forissier 
431511fa71b9SJerome Forissier                 hs_buf->is_fragmented =
431611fa71b9SJerome Forissier                     ( ssl_hs_is_proper_fragment( ssl ) == 1 );
431711fa71b9SJerome Forissier 
431811fa71b9SJerome Forissier                 /* We copy the message back into the input buffer
431911fa71b9SJerome Forissier                  * after reassembly, so check that it's not too large.
432011fa71b9SJerome Forissier                  * This is an implementation-specific limitation
432111fa71b9SJerome Forissier                  * and not one from the standard, hence it is not
432211fa71b9SJerome Forissier                  * checked in ssl_check_hs_header(). */
432311fa71b9SJerome Forissier                 if( msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN )
432411fa71b9SJerome Forissier                 {
432511fa71b9SJerome Forissier                     /* Ignore message */
432611fa71b9SJerome Forissier                     goto exit;
432711fa71b9SJerome Forissier                 }
432811fa71b9SJerome Forissier 
432911fa71b9SJerome Forissier                 /* Check if we have enough space to buffer the message. */
433011fa71b9SJerome Forissier                 if( hs->buffering.total_bytes_buffered >
433111fa71b9SJerome Forissier                     MBEDTLS_SSL_DTLS_MAX_BUFFERING )
433211fa71b9SJerome Forissier                 {
433311fa71b9SJerome Forissier                     MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
433411fa71b9SJerome Forissier                     return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
433511fa71b9SJerome Forissier                 }
433611fa71b9SJerome Forissier 
433711fa71b9SJerome Forissier                 reassembly_buf_sz = ssl_get_reassembly_buffer_size( msg_len,
433811fa71b9SJerome Forissier                                                        hs_buf->is_fragmented );
433911fa71b9SJerome Forissier 
434011fa71b9SJerome Forissier                 if( reassembly_buf_sz > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
434111fa71b9SJerome Forissier                                           hs->buffering.total_bytes_buffered ) )
434211fa71b9SJerome Forissier                 {
434311fa71b9SJerome Forissier                     if( recv_msg_seq_offset > 0 )
434411fa71b9SJerome Forissier                     {
434511fa71b9SJerome Forissier                         /* If we can't buffer a future message because
434611fa71b9SJerome Forissier                          * of space limitations -- ignore. */
4347*7901324dSJerome Forissier                         MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %" MBEDTLS_PRINTF_SIZET
4348*7901324dSJerome Forissier                                                     " would exceed the compile-time limit %" MBEDTLS_PRINTF_SIZET
4349*7901324dSJerome Forissier                                                     " (already %" MBEDTLS_PRINTF_SIZET
4350*7901324dSJerome Forissier                                                     " bytes buffered) -- ignore\n",
4351*7901324dSJerome Forissier                              msg_len, (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING,
4352*7901324dSJerome Forissier                              hs->buffering.total_bytes_buffered ) );
435311fa71b9SJerome Forissier                         goto exit;
435411fa71b9SJerome Forissier                     }
435511fa71b9SJerome Forissier                     else
435611fa71b9SJerome Forissier                     {
4357*7901324dSJerome Forissier                         MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %" MBEDTLS_PRINTF_SIZET
4358*7901324dSJerome Forissier                                                     " would exceed the compile-time limit %" MBEDTLS_PRINTF_SIZET
4359*7901324dSJerome Forissier                                                     " (already %" MBEDTLS_PRINTF_SIZET
4360*7901324dSJerome Forissier                                                     " bytes buffered) -- attempt to make space by freeing buffered future messages\n",
4361*7901324dSJerome Forissier                              msg_len, (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING,
4362*7901324dSJerome Forissier                              hs->buffering.total_bytes_buffered ) );
436311fa71b9SJerome Forissier                     }
436411fa71b9SJerome Forissier 
436511fa71b9SJerome Forissier                     if( ssl_buffer_make_space( ssl, reassembly_buf_sz ) != 0 )
436611fa71b9SJerome Forissier                     {
4367*7901324dSJerome Forissier                         MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reassembly of next message of size %" MBEDTLS_PRINTF_SIZET
4368*7901324dSJerome Forissier                                                     " (%" MBEDTLS_PRINTF_SIZET " with bitmap) would exceed"
4369*7901324dSJerome Forissier                                                     " the compile-time limit %" MBEDTLS_PRINTF_SIZET
4370*7901324dSJerome Forissier                                                     " (already %" MBEDTLS_PRINTF_SIZET
4371*7901324dSJerome Forissier                                                     " bytes buffered) -- fail\n",
4372*7901324dSJerome Forissier                              msg_len,
4373*7901324dSJerome Forissier                              reassembly_buf_sz,
4374*7901324dSJerome Forissier                              (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING,
4375*7901324dSJerome Forissier                              hs->buffering.total_bytes_buffered ) );
437611fa71b9SJerome Forissier                         ret = MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
437711fa71b9SJerome Forissier                         goto exit;
437811fa71b9SJerome Forissier                     }
437911fa71b9SJerome Forissier                 }
438011fa71b9SJerome Forissier 
4381*7901324dSJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %" MBEDTLS_PRINTF_SIZET,
438211fa71b9SJerome Forissier                                             msg_len ) );
438311fa71b9SJerome Forissier 
438411fa71b9SJerome Forissier                 hs_buf->data = mbedtls_calloc( 1, reassembly_buf_sz );
438511fa71b9SJerome Forissier                 if( hs_buf->data == NULL )
438611fa71b9SJerome Forissier                 {
438711fa71b9SJerome Forissier                     ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
438811fa71b9SJerome Forissier                     goto exit;
438911fa71b9SJerome Forissier                 }
439011fa71b9SJerome Forissier                 hs_buf->data_len = reassembly_buf_sz;
439111fa71b9SJerome Forissier 
439211fa71b9SJerome Forissier                 /* Prepare final header: copy msg_type, length and message_seq,
439311fa71b9SJerome Forissier                  * then add standardised fragment_offset and fragment_length */
439411fa71b9SJerome Forissier                 memcpy( hs_buf->data, ssl->in_msg, 6 );
439511fa71b9SJerome Forissier                 memset( hs_buf->data + 6, 0, 3 );
439611fa71b9SJerome Forissier                 memcpy( hs_buf->data + 9, hs_buf->data + 1, 3 );
439711fa71b9SJerome Forissier 
439811fa71b9SJerome Forissier                 hs_buf->is_valid = 1;
439911fa71b9SJerome Forissier 
440011fa71b9SJerome Forissier                 hs->buffering.total_bytes_buffered += reassembly_buf_sz;
440111fa71b9SJerome Forissier             }
440211fa71b9SJerome Forissier             else
440311fa71b9SJerome Forissier             {
440411fa71b9SJerome Forissier                 /* Make sure msg_type and length are consistent */
440511fa71b9SJerome Forissier                 if( memcmp( hs_buf->data, ssl->in_msg, 4 ) != 0 )
440611fa71b9SJerome Forissier                 {
440711fa71b9SJerome Forissier                     MBEDTLS_SSL_DEBUG_MSG( 1, ( "Fragment header mismatch - ignore" ) );
440811fa71b9SJerome Forissier                     /* Ignore */
440911fa71b9SJerome Forissier                     goto exit;
441011fa71b9SJerome Forissier                 }
441111fa71b9SJerome Forissier             }
441211fa71b9SJerome Forissier 
441311fa71b9SJerome Forissier             if( !hs_buf->is_complete )
441411fa71b9SJerome Forissier             {
441511fa71b9SJerome Forissier                 size_t frag_len, frag_off;
441611fa71b9SJerome Forissier                 unsigned char * const msg = hs_buf->data + 12;
441711fa71b9SJerome Forissier 
441811fa71b9SJerome Forissier                 /*
441911fa71b9SJerome Forissier                  * Check and copy current fragment
442011fa71b9SJerome Forissier                  */
442111fa71b9SJerome Forissier 
442211fa71b9SJerome Forissier                 /* Validation of header fields already done in
442311fa71b9SJerome Forissier                  * mbedtls_ssl_prepare_handshake_record(). */
442411fa71b9SJerome Forissier                 frag_off = ssl_get_hs_frag_off( ssl );
442511fa71b9SJerome Forissier                 frag_len = ssl_get_hs_frag_len( ssl );
442611fa71b9SJerome Forissier 
4427*7901324dSJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 2, ( "adding fragment, offset = %" MBEDTLS_PRINTF_SIZET
4428*7901324dSJerome Forissier                                             ", length = %" MBEDTLS_PRINTF_SIZET,
442911fa71b9SJerome Forissier                                             frag_off, frag_len ) );
443011fa71b9SJerome Forissier                 memcpy( msg + frag_off, ssl->in_msg + 12, frag_len );
443111fa71b9SJerome Forissier 
443211fa71b9SJerome Forissier                 if( hs_buf->is_fragmented )
443311fa71b9SJerome Forissier                 {
443411fa71b9SJerome Forissier                     unsigned char * const bitmask = msg + msg_len;
443511fa71b9SJerome Forissier                     ssl_bitmask_set( bitmask, frag_off, frag_len );
443611fa71b9SJerome Forissier                     hs_buf->is_complete = ( ssl_bitmask_check( bitmask,
443711fa71b9SJerome Forissier                                                                msg_len ) == 0 );
443811fa71b9SJerome Forissier                 }
443911fa71b9SJerome Forissier                 else
444011fa71b9SJerome Forissier                 {
444111fa71b9SJerome Forissier                     hs_buf->is_complete = 1;
444211fa71b9SJerome Forissier                 }
444311fa71b9SJerome Forissier 
444411fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 2, ( "message %scomplete",
444511fa71b9SJerome Forissier                                    hs_buf->is_complete ? "" : "not yet " ) );
444611fa71b9SJerome Forissier             }
444711fa71b9SJerome Forissier 
444811fa71b9SJerome Forissier             break;
444911fa71b9SJerome Forissier         }
445011fa71b9SJerome Forissier 
445111fa71b9SJerome Forissier         default:
445211fa71b9SJerome Forissier             /* We don't buffer other types of messages. */
445311fa71b9SJerome Forissier             break;
445411fa71b9SJerome Forissier     }
445511fa71b9SJerome Forissier 
445611fa71b9SJerome Forissier exit:
445711fa71b9SJerome Forissier 
445811fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_buffer_message" ) );
445911fa71b9SJerome Forissier     return( ret );
446011fa71b9SJerome Forissier }
446111fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
446211fa71b9SJerome Forissier 
446311fa71b9SJerome Forissier static int ssl_consume_current_message( mbedtls_ssl_context *ssl )
446411fa71b9SJerome Forissier {
446511fa71b9SJerome Forissier     /*
446611fa71b9SJerome Forissier      * Consume last content-layer message and potentially
446711fa71b9SJerome Forissier      * update in_msglen which keeps track of the contents'
446811fa71b9SJerome Forissier      * consumption state.
446911fa71b9SJerome Forissier      *
447011fa71b9SJerome Forissier      * (1) Handshake messages:
447111fa71b9SJerome Forissier      *     Remove last handshake message, move content
447211fa71b9SJerome Forissier      *     and adapt in_msglen.
447311fa71b9SJerome Forissier      *
447411fa71b9SJerome Forissier      * (2) Alert messages:
447511fa71b9SJerome Forissier      *     Consume whole record content, in_msglen = 0.
447611fa71b9SJerome Forissier      *
447711fa71b9SJerome Forissier      * (3) Change cipher spec:
447811fa71b9SJerome Forissier      *     Consume whole record content, in_msglen = 0.
447911fa71b9SJerome Forissier      *
448011fa71b9SJerome Forissier      * (4) Application data:
448111fa71b9SJerome Forissier      *     Don't do anything - the record layer provides
448211fa71b9SJerome Forissier      *     the application data as a stream transport
448311fa71b9SJerome Forissier      *     and consumes through mbedtls_ssl_read only.
448411fa71b9SJerome Forissier      *
448511fa71b9SJerome Forissier      */
448611fa71b9SJerome Forissier 
448711fa71b9SJerome Forissier     /* Case (1): Handshake messages */
448811fa71b9SJerome Forissier     if( ssl->in_hslen != 0 )
448911fa71b9SJerome Forissier     {
449011fa71b9SJerome Forissier         /* Hard assertion to be sure that no application data
449111fa71b9SJerome Forissier          * is in flight, as corrupting ssl->in_msglen during
449211fa71b9SJerome Forissier          * ssl->in_offt != NULL is fatal. */
449311fa71b9SJerome Forissier         if( ssl->in_offt != NULL )
449411fa71b9SJerome Forissier         {
449511fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
449611fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
449711fa71b9SJerome Forissier         }
449811fa71b9SJerome Forissier 
449911fa71b9SJerome Forissier         /*
450011fa71b9SJerome Forissier          * Get next Handshake message in the current record
450111fa71b9SJerome Forissier          */
450211fa71b9SJerome Forissier 
450311fa71b9SJerome Forissier         /* Notes:
450411fa71b9SJerome Forissier          * (1) in_hslen is not necessarily the size of the
450511fa71b9SJerome Forissier          *     current handshake content: If DTLS handshake
450611fa71b9SJerome Forissier          *     fragmentation is used, that's the fragment
450711fa71b9SJerome Forissier          *     size instead. Using the total handshake message
450811fa71b9SJerome Forissier          *     size here is faulty and should be changed at
450911fa71b9SJerome Forissier          *     some point.
451011fa71b9SJerome Forissier          * (2) While it doesn't seem to cause problems, one
451111fa71b9SJerome Forissier          *     has to be very careful not to assume that in_hslen
451211fa71b9SJerome Forissier          *     is always <= in_msglen in a sensible communication.
451311fa71b9SJerome Forissier          *     Again, it's wrong for DTLS handshake fragmentation.
451411fa71b9SJerome Forissier          *     The following check is therefore mandatory, and
451511fa71b9SJerome Forissier          *     should not be treated as a silently corrected assertion.
451611fa71b9SJerome Forissier          *     Additionally, ssl->in_hslen might be arbitrarily out of
451711fa71b9SJerome Forissier          *     bounds after handling a DTLS message with an unexpected
451811fa71b9SJerome Forissier          *     sequence number, see mbedtls_ssl_prepare_handshake_record.
451911fa71b9SJerome Forissier          */
452011fa71b9SJerome Forissier         if( ssl->in_hslen < ssl->in_msglen )
452111fa71b9SJerome Forissier         {
452211fa71b9SJerome Forissier             ssl->in_msglen -= ssl->in_hslen;
452311fa71b9SJerome Forissier             memmove( ssl->in_msg, ssl->in_msg + ssl->in_hslen,
452411fa71b9SJerome Forissier                      ssl->in_msglen );
452511fa71b9SJerome Forissier 
452611fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_BUF( 4, "remaining content in record",
452711fa71b9SJerome Forissier                                    ssl->in_msg, ssl->in_msglen );
452811fa71b9SJerome Forissier         }
452911fa71b9SJerome Forissier         else
453011fa71b9SJerome Forissier         {
453111fa71b9SJerome Forissier             ssl->in_msglen = 0;
453211fa71b9SJerome Forissier         }
453311fa71b9SJerome Forissier 
453411fa71b9SJerome Forissier         ssl->in_hslen   = 0;
453511fa71b9SJerome Forissier     }
453611fa71b9SJerome Forissier     /* Case (4): Application data */
453711fa71b9SJerome Forissier     else if( ssl->in_offt != NULL )
453811fa71b9SJerome Forissier     {
453911fa71b9SJerome Forissier         return( 0 );
454011fa71b9SJerome Forissier     }
454111fa71b9SJerome Forissier     /* Everything else (CCS & Alerts) */
454211fa71b9SJerome Forissier     else
454311fa71b9SJerome Forissier     {
454411fa71b9SJerome Forissier         ssl->in_msglen = 0;
454511fa71b9SJerome Forissier     }
454611fa71b9SJerome Forissier 
454711fa71b9SJerome Forissier     return( 0 );
454811fa71b9SJerome Forissier }
454911fa71b9SJerome Forissier 
455011fa71b9SJerome Forissier static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl )
455111fa71b9SJerome Forissier {
455211fa71b9SJerome Forissier     if( ssl->in_msglen > 0 )
455311fa71b9SJerome Forissier         return( 1 );
455411fa71b9SJerome Forissier 
455511fa71b9SJerome Forissier     return( 0 );
455611fa71b9SJerome Forissier }
455711fa71b9SJerome Forissier 
455811fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
455911fa71b9SJerome Forissier 
456011fa71b9SJerome Forissier static void ssl_free_buffered_record( mbedtls_ssl_context *ssl )
456111fa71b9SJerome Forissier {
456211fa71b9SJerome Forissier     mbedtls_ssl_handshake_params * const hs = ssl->handshake;
456311fa71b9SJerome Forissier     if( hs == NULL )
456411fa71b9SJerome Forissier         return;
456511fa71b9SJerome Forissier 
456611fa71b9SJerome Forissier     if( hs->buffering.future_record.data != NULL )
456711fa71b9SJerome Forissier     {
456811fa71b9SJerome Forissier         hs->buffering.total_bytes_buffered -=
456911fa71b9SJerome Forissier             hs->buffering.future_record.len;
457011fa71b9SJerome Forissier 
457111fa71b9SJerome Forissier         mbedtls_free( hs->buffering.future_record.data );
457211fa71b9SJerome Forissier         hs->buffering.future_record.data = NULL;
457311fa71b9SJerome Forissier     }
457411fa71b9SJerome Forissier }
457511fa71b9SJerome Forissier 
457611fa71b9SJerome Forissier static int ssl_load_buffered_record( mbedtls_ssl_context *ssl )
457711fa71b9SJerome Forissier {
457811fa71b9SJerome Forissier     mbedtls_ssl_handshake_params * const hs = ssl->handshake;
457911fa71b9SJerome Forissier     unsigned char * rec;
458011fa71b9SJerome Forissier     size_t rec_len;
458111fa71b9SJerome Forissier     unsigned rec_epoch;
458211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
458311fa71b9SJerome Forissier     size_t in_buf_len = ssl->in_buf_len;
458411fa71b9SJerome Forissier #else
458511fa71b9SJerome Forissier     size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN;
458611fa71b9SJerome Forissier #endif
458711fa71b9SJerome Forissier     if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM )
458811fa71b9SJerome Forissier         return( 0 );
458911fa71b9SJerome Forissier 
459011fa71b9SJerome Forissier     if( hs == NULL )
459111fa71b9SJerome Forissier         return( 0 );
459211fa71b9SJerome Forissier 
459311fa71b9SJerome Forissier     rec       = hs->buffering.future_record.data;
459411fa71b9SJerome Forissier     rec_len   = hs->buffering.future_record.len;
459511fa71b9SJerome Forissier     rec_epoch = hs->buffering.future_record.epoch;
459611fa71b9SJerome Forissier 
459711fa71b9SJerome Forissier     if( rec == NULL )
459811fa71b9SJerome Forissier         return( 0 );
459911fa71b9SJerome Forissier 
460011fa71b9SJerome Forissier     /* Only consider loading future records if the
460111fa71b9SJerome Forissier      * input buffer is empty. */
460211fa71b9SJerome Forissier     if( ssl_next_record_is_in_datagram( ssl ) == 1 )
460311fa71b9SJerome Forissier         return( 0 );
460411fa71b9SJerome Forissier 
460511fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_record" ) );
460611fa71b9SJerome Forissier 
460711fa71b9SJerome Forissier     if( rec_epoch != ssl->in_epoch )
460811fa71b9SJerome Forissier     {
460911fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffered record not from current epoch." ) );
461011fa71b9SJerome Forissier         goto exit;
461111fa71b9SJerome Forissier     }
461211fa71b9SJerome Forissier 
461311fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "Found buffered record from current epoch - load" ) );
461411fa71b9SJerome Forissier 
461511fa71b9SJerome Forissier     /* Double-check that the record is not too large */
461611fa71b9SJerome Forissier     if( rec_len > in_buf_len - (size_t)( ssl->in_hdr - ssl->in_buf ) )
461711fa71b9SJerome Forissier     {
461811fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
461911fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
462011fa71b9SJerome Forissier     }
462111fa71b9SJerome Forissier 
462211fa71b9SJerome Forissier     memcpy( ssl->in_hdr, rec, rec_len );
462311fa71b9SJerome Forissier     ssl->in_left = rec_len;
462411fa71b9SJerome Forissier     ssl->next_record_offset = 0;
462511fa71b9SJerome Forissier 
462611fa71b9SJerome Forissier     ssl_free_buffered_record( ssl );
462711fa71b9SJerome Forissier 
462811fa71b9SJerome Forissier exit:
462911fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_load_buffered_record" ) );
463011fa71b9SJerome Forissier     return( 0 );
463111fa71b9SJerome Forissier }
463211fa71b9SJerome Forissier 
463311fa71b9SJerome Forissier static int ssl_buffer_future_record( mbedtls_ssl_context *ssl,
463411fa71b9SJerome Forissier                                      mbedtls_record const *rec )
463511fa71b9SJerome Forissier {
463611fa71b9SJerome Forissier     mbedtls_ssl_handshake_params * const hs = ssl->handshake;
463711fa71b9SJerome Forissier 
463811fa71b9SJerome Forissier     /* Don't buffer future records outside handshakes. */
463911fa71b9SJerome Forissier     if( hs == NULL )
464011fa71b9SJerome Forissier         return( 0 );
464111fa71b9SJerome Forissier 
464211fa71b9SJerome Forissier     /* Only buffer handshake records (we are only interested
464311fa71b9SJerome Forissier      * in Finished messages). */
464411fa71b9SJerome Forissier     if( rec->type != MBEDTLS_SSL_MSG_HANDSHAKE )
464511fa71b9SJerome Forissier         return( 0 );
464611fa71b9SJerome Forissier 
464711fa71b9SJerome Forissier     /* Don't buffer more than one future epoch record. */
464811fa71b9SJerome Forissier     if( hs->buffering.future_record.data != NULL )
464911fa71b9SJerome Forissier         return( 0 );
465011fa71b9SJerome Forissier 
465111fa71b9SJerome Forissier     /* Don't buffer record if there's not enough buffering space remaining. */
465211fa71b9SJerome Forissier     if( rec->buf_len > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
465311fa71b9SJerome Forissier                          hs->buffering.total_bytes_buffered ) )
465411fa71b9SJerome Forissier     {
4655*7901324dSJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future epoch record of size %" MBEDTLS_PRINTF_SIZET
4656*7901324dSJerome Forissier                                     " would exceed the compile-time limit %" MBEDTLS_PRINTF_SIZET
4657*7901324dSJerome Forissier                                     " (already %" MBEDTLS_PRINTF_SIZET
4658*7901324dSJerome Forissier                                     " bytes buffered) -- ignore\n",
4659*7901324dSJerome Forissier                         rec->buf_len, (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING,
4660*7901324dSJerome Forissier                         hs->buffering.total_bytes_buffered ) );
466111fa71b9SJerome Forissier         return( 0 );
466211fa71b9SJerome Forissier     }
466311fa71b9SJerome Forissier 
466411fa71b9SJerome Forissier     /* Buffer record */
466511fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffer record from epoch %u",
4666*7901324dSJerome Forissier                                 ssl->in_epoch + 1U ) );
466711fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered record", rec->buf, rec->buf_len );
466811fa71b9SJerome Forissier 
466911fa71b9SJerome Forissier     /* ssl_parse_record_header() only considers records
467011fa71b9SJerome Forissier      * of the next epoch as candidates for buffering. */
467111fa71b9SJerome Forissier     hs->buffering.future_record.epoch = ssl->in_epoch + 1;
467211fa71b9SJerome Forissier     hs->buffering.future_record.len   = rec->buf_len;
467311fa71b9SJerome Forissier 
467411fa71b9SJerome Forissier     hs->buffering.future_record.data =
467511fa71b9SJerome Forissier         mbedtls_calloc( 1, hs->buffering.future_record.len );
467611fa71b9SJerome Forissier     if( hs->buffering.future_record.data == NULL )
467711fa71b9SJerome Forissier     {
467811fa71b9SJerome Forissier         /* If we run out of RAM trying to buffer a
467911fa71b9SJerome Forissier          * record from the next epoch, just ignore. */
468011fa71b9SJerome Forissier         return( 0 );
468111fa71b9SJerome Forissier     }
468211fa71b9SJerome Forissier 
468311fa71b9SJerome Forissier     memcpy( hs->buffering.future_record.data, rec->buf, rec->buf_len );
468411fa71b9SJerome Forissier 
468511fa71b9SJerome Forissier     hs->buffering.total_bytes_buffered += rec->buf_len;
468611fa71b9SJerome Forissier     return( 0 );
468711fa71b9SJerome Forissier }
468811fa71b9SJerome Forissier 
468911fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
469011fa71b9SJerome Forissier 
469111fa71b9SJerome Forissier static int ssl_get_next_record( mbedtls_ssl_context *ssl )
469211fa71b9SJerome Forissier {
469311fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
469411fa71b9SJerome Forissier     mbedtls_record rec;
469511fa71b9SJerome Forissier 
469611fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
469711fa71b9SJerome Forissier     /* We might have buffered a future record; if so,
469811fa71b9SJerome Forissier      * and if the epoch matches now, load it.
469911fa71b9SJerome Forissier      * On success, this call will set ssl->in_left to
470011fa71b9SJerome Forissier      * the length of the buffered record, so that
470111fa71b9SJerome Forissier      * the calls to ssl_fetch_input() below will
470211fa71b9SJerome Forissier      * essentially be no-ops. */
470311fa71b9SJerome Forissier     ret = ssl_load_buffered_record( ssl );
470411fa71b9SJerome Forissier     if( ret != 0 )
470511fa71b9SJerome Forissier         return( ret );
470611fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
470711fa71b9SJerome Forissier 
470811fa71b9SJerome Forissier     /* Ensure that we have enough space available for the default form
470911fa71b9SJerome Forissier      * of TLS / DTLS record headers (5 Bytes for TLS, 13 Bytes for DTLS,
471011fa71b9SJerome Forissier      * with no space for CIDs counted in). */
471111fa71b9SJerome Forissier     ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_in_hdr_len( ssl ) );
471211fa71b9SJerome Forissier     if( ret != 0 )
471311fa71b9SJerome Forissier     {
471411fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret );
471511fa71b9SJerome Forissier         return( ret );
471611fa71b9SJerome Forissier     }
471711fa71b9SJerome Forissier 
471811fa71b9SJerome Forissier     ret = ssl_parse_record_header( ssl, ssl->in_hdr, ssl->in_left, &rec );
471911fa71b9SJerome Forissier     if( ret != 0 )
472011fa71b9SJerome Forissier     {
472111fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
472211fa71b9SJerome Forissier         if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
472311fa71b9SJerome Forissier         {
472411fa71b9SJerome Forissier             if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE )
472511fa71b9SJerome Forissier             {
472611fa71b9SJerome Forissier                 ret = ssl_buffer_future_record( ssl, &rec );
472711fa71b9SJerome Forissier                 if( ret != 0 )
472811fa71b9SJerome Forissier                     return( ret );
472911fa71b9SJerome Forissier 
473011fa71b9SJerome Forissier                 /* Fall through to handling of unexpected records */
473111fa71b9SJerome Forissier                 ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD;
473211fa71b9SJerome Forissier             }
473311fa71b9SJerome Forissier 
473411fa71b9SJerome Forissier             if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD )
473511fa71b9SJerome Forissier             {
473611fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
473711fa71b9SJerome Forissier                 /* Reset in pointers to default state for TLS/DTLS records,
473811fa71b9SJerome Forissier                  * assuming no CID and no offset between record content and
473911fa71b9SJerome Forissier                  * record plaintext. */
474011fa71b9SJerome Forissier                 mbedtls_ssl_update_in_pointers( ssl );
474111fa71b9SJerome Forissier 
474211fa71b9SJerome Forissier                 /* Setup internal message pointers from record structure. */
474311fa71b9SJerome Forissier                 ssl->in_msgtype = rec.type;
474411fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
474511fa71b9SJerome Forissier                 ssl->in_len = ssl->in_cid + rec.cid_len;
474611fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
474711fa71b9SJerome Forissier                 ssl->in_iv  = ssl->in_msg = ssl->in_len + 2;
474811fa71b9SJerome Forissier                 ssl->in_msglen = rec.data_len;
474911fa71b9SJerome Forissier 
475011fa71b9SJerome Forissier                 ret = ssl_check_client_reconnect( ssl );
475111fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_RET( 2, "ssl_check_client_reconnect", ret );
475211fa71b9SJerome Forissier                 if( ret != 0 )
475311fa71b9SJerome Forissier                     return( ret );
475411fa71b9SJerome Forissier #endif
475511fa71b9SJerome Forissier 
475611fa71b9SJerome Forissier                 /* Skip unexpected record (but not whole datagram) */
475711fa71b9SJerome Forissier                 ssl->next_record_offset = rec.buf_len;
475811fa71b9SJerome Forissier 
475911fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding unexpected record "
476011fa71b9SJerome Forissier                                             "(header)" ) );
476111fa71b9SJerome Forissier             }
476211fa71b9SJerome Forissier             else
476311fa71b9SJerome Forissier             {
476411fa71b9SJerome Forissier                 /* Skip invalid record and the rest of the datagram */
476511fa71b9SJerome Forissier                 ssl->next_record_offset = 0;
476611fa71b9SJerome Forissier                 ssl->in_left = 0;
476711fa71b9SJerome Forissier 
476811fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record "
476911fa71b9SJerome Forissier                                             "(header)" ) );
477011fa71b9SJerome Forissier             }
477111fa71b9SJerome Forissier 
477211fa71b9SJerome Forissier             /* Get next record */
477311fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
477411fa71b9SJerome Forissier         }
477511fa71b9SJerome Forissier         else
477611fa71b9SJerome Forissier #endif
477711fa71b9SJerome Forissier         {
477811fa71b9SJerome Forissier             return( ret );
477911fa71b9SJerome Forissier         }
478011fa71b9SJerome Forissier     }
478111fa71b9SJerome Forissier 
478211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
478311fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
478411fa71b9SJerome Forissier     {
478511fa71b9SJerome Forissier         /* Remember offset of next record within datagram. */
478611fa71b9SJerome Forissier         ssl->next_record_offset = rec.buf_len;
478711fa71b9SJerome Forissier         if( ssl->next_record_offset < ssl->in_left )
478811fa71b9SJerome Forissier         {
478911fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 3, ( "more than one record within datagram" ) );
479011fa71b9SJerome Forissier         }
479111fa71b9SJerome Forissier     }
479211fa71b9SJerome Forissier     else
479311fa71b9SJerome Forissier #endif
479411fa71b9SJerome Forissier     {
479511fa71b9SJerome Forissier         /*
479611fa71b9SJerome Forissier          * Fetch record contents from underlying transport.
479711fa71b9SJerome Forissier          */
479811fa71b9SJerome Forissier         ret = mbedtls_ssl_fetch_input( ssl, rec.buf_len );
479911fa71b9SJerome Forissier         if( ret != 0 )
480011fa71b9SJerome Forissier         {
480111fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret );
480211fa71b9SJerome Forissier             return( ret );
480311fa71b9SJerome Forissier         }
480411fa71b9SJerome Forissier 
480511fa71b9SJerome Forissier         ssl->in_left = 0;
480611fa71b9SJerome Forissier     }
480711fa71b9SJerome Forissier 
480811fa71b9SJerome Forissier     /*
480911fa71b9SJerome Forissier      * Decrypt record contents.
481011fa71b9SJerome Forissier      */
481111fa71b9SJerome Forissier 
481211fa71b9SJerome Forissier     if( ( ret = ssl_prepare_record_content( ssl, &rec ) ) != 0 )
481311fa71b9SJerome Forissier     {
481411fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
481511fa71b9SJerome Forissier         if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
481611fa71b9SJerome Forissier         {
481711fa71b9SJerome Forissier             /* Silently discard invalid records */
481811fa71b9SJerome Forissier             if( ret == MBEDTLS_ERR_SSL_INVALID_MAC )
481911fa71b9SJerome Forissier             {
482011fa71b9SJerome Forissier                 /* Except when waiting for Finished as a bad mac here
482111fa71b9SJerome Forissier                  * probably means something went wrong in the handshake
482211fa71b9SJerome Forissier                  * (eg wrong psk used, mitm downgrade attempt, etc.) */
482311fa71b9SJerome Forissier                 if( ssl->state == MBEDTLS_SSL_CLIENT_FINISHED ||
482411fa71b9SJerome Forissier                     ssl->state == MBEDTLS_SSL_SERVER_FINISHED )
482511fa71b9SJerome Forissier                 {
482611fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES)
482711fa71b9SJerome Forissier                     if( ret == MBEDTLS_ERR_SSL_INVALID_MAC )
482811fa71b9SJerome Forissier                     {
482911fa71b9SJerome Forissier                         mbedtls_ssl_send_alert_message( ssl,
483011fa71b9SJerome Forissier                                 MBEDTLS_SSL_ALERT_LEVEL_FATAL,
483111fa71b9SJerome Forissier                                 MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC );
483211fa71b9SJerome Forissier                     }
483311fa71b9SJerome Forissier #endif
483411fa71b9SJerome Forissier                     return( ret );
483511fa71b9SJerome Forissier                 }
483611fa71b9SJerome Forissier 
483711fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT)
483811fa71b9SJerome Forissier                 if( ssl->conf->badmac_limit != 0 &&
483911fa71b9SJerome Forissier                     ++ssl->badmac_seen >= ssl->conf->badmac_limit )
484011fa71b9SJerome Forissier                 {
484111fa71b9SJerome Forissier                     MBEDTLS_SSL_DEBUG_MSG( 1, ( "too many records with bad MAC" ) );
484211fa71b9SJerome Forissier                     return( MBEDTLS_ERR_SSL_INVALID_MAC );
484311fa71b9SJerome Forissier                 }
484411fa71b9SJerome Forissier #endif
484511fa71b9SJerome Forissier 
484611fa71b9SJerome Forissier                 /* As above, invalid records cause
484711fa71b9SJerome Forissier                  * dismissal of the whole datagram. */
484811fa71b9SJerome Forissier 
484911fa71b9SJerome Forissier                 ssl->next_record_offset = 0;
485011fa71b9SJerome Forissier                 ssl->in_left = 0;
485111fa71b9SJerome Forissier 
485211fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record (mac)" ) );
485311fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
485411fa71b9SJerome Forissier             }
485511fa71b9SJerome Forissier 
485611fa71b9SJerome Forissier             return( ret );
485711fa71b9SJerome Forissier         }
485811fa71b9SJerome Forissier         else
485911fa71b9SJerome Forissier #endif
486011fa71b9SJerome Forissier         {
486111fa71b9SJerome Forissier             /* Error out (and send alert) on invalid records */
486211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES)
486311fa71b9SJerome Forissier             if( ret == MBEDTLS_ERR_SSL_INVALID_MAC )
486411fa71b9SJerome Forissier             {
486511fa71b9SJerome Forissier                 mbedtls_ssl_send_alert_message( ssl,
486611fa71b9SJerome Forissier                         MBEDTLS_SSL_ALERT_LEVEL_FATAL,
486711fa71b9SJerome Forissier                         MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC );
486811fa71b9SJerome Forissier             }
486911fa71b9SJerome Forissier #endif
487011fa71b9SJerome Forissier             return( ret );
487111fa71b9SJerome Forissier         }
487211fa71b9SJerome Forissier     }
487311fa71b9SJerome Forissier 
487411fa71b9SJerome Forissier 
487511fa71b9SJerome Forissier     /* Reset in pointers to default state for TLS/DTLS records,
487611fa71b9SJerome Forissier      * assuming no CID and no offset between record content and
487711fa71b9SJerome Forissier      * record plaintext. */
487811fa71b9SJerome Forissier     mbedtls_ssl_update_in_pointers( ssl );
487911fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
488011fa71b9SJerome Forissier     ssl->in_len = ssl->in_cid + rec.cid_len;
488111fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
488211fa71b9SJerome Forissier     ssl->in_iv  = ssl->in_len + 2;
488311fa71b9SJerome Forissier 
488411fa71b9SJerome Forissier     /* The record content type may change during decryption,
488511fa71b9SJerome Forissier      * so re-read it. */
488611fa71b9SJerome Forissier     ssl->in_msgtype = rec.type;
488711fa71b9SJerome Forissier     /* Also update the input buffer, because unfortunately
488811fa71b9SJerome Forissier      * the server-side ssl_parse_client_hello() reparses the
488911fa71b9SJerome Forissier      * record header when receiving a ClientHello initiating
489011fa71b9SJerome Forissier      * a renegotiation. */
489111fa71b9SJerome Forissier     ssl->in_hdr[0] = rec.type;
489211fa71b9SJerome Forissier     ssl->in_msg    = rec.buf + rec.data_offset;
489311fa71b9SJerome Forissier     ssl->in_msglen = rec.data_len;
489411fa71b9SJerome Forissier     ssl->in_len[0] = (unsigned char)( rec.data_len >> 8 );
489511fa71b9SJerome Forissier     ssl->in_len[1] = (unsigned char)( rec.data_len      );
489611fa71b9SJerome Forissier 
489711fa71b9SJerome Forissier #if defined(MBEDTLS_ZLIB_SUPPORT)
489811fa71b9SJerome Forissier     if( ssl->transform_in != NULL &&
489911fa71b9SJerome Forissier         ssl->session_in->compression == MBEDTLS_SSL_COMPRESS_DEFLATE )
490011fa71b9SJerome Forissier     {
490111fa71b9SJerome Forissier         if( ( ret = ssl_decompress_buf( ssl ) ) != 0 )
490211fa71b9SJerome Forissier         {
490311fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decompress_buf", ret );
490411fa71b9SJerome Forissier             return( ret );
490511fa71b9SJerome Forissier         }
490611fa71b9SJerome Forissier 
490711fa71b9SJerome Forissier         /* Check actual (decompress) record content length against
490811fa71b9SJerome Forissier          * configured maximum. */
490911fa71b9SJerome Forissier         if( ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN )
491011fa71b9SJerome Forissier         {
491111fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
491211fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INVALID_RECORD );
491311fa71b9SJerome Forissier         }
491411fa71b9SJerome Forissier     }
491511fa71b9SJerome Forissier #endif /* MBEDTLS_ZLIB_SUPPORT */
491611fa71b9SJerome Forissier 
491711fa71b9SJerome Forissier     return( 0 );
491811fa71b9SJerome Forissier }
491911fa71b9SJerome Forissier 
492011fa71b9SJerome Forissier int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl )
492111fa71b9SJerome Forissier {
492211fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
492311fa71b9SJerome Forissier 
492411fa71b9SJerome Forissier     /*
492511fa71b9SJerome Forissier      * Handle particular types of records
492611fa71b9SJerome Forissier      */
492711fa71b9SJerome Forissier     if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE )
492811fa71b9SJerome Forissier     {
492911fa71b9SJerome Forissier         if( ( ret = mbedtls_ssl_prepare_handshake_record( ssl ) ) != 0 )
493011fa71b9SJerome Forissier         {
493111fa71b9SJerome Forissier             return( ret );
493211fa71b9SJerome Forissier         }
493311fa71b9SJerome Forissier     }
493411fa71b9SJerome Forissier 
493511fa71b9SJerome Forissier     if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC )
493611fa71b9SJerome Forissier     {
493711fa71b9SJerome Forissier         if( ssl->in_msglen != 1 )
493811fa71b9SJerome Forissier         {
4939*7901324dSJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, len: %" MBEDTLS_PRINTF_SIZET,
494011fa71b9SJerome Forissier                            ssl->in_msglen ) );
494111fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INVALID_RECORD );
494211fa71b9SJerome Forissier         }
494311fa71b9SJerome Forissier 
494411fa71b9SJerome Forissier         if( ssl->in_msg[0] != 1 )
494511fa71b9SJerome Forissier         {
494611fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, content: %02x",
494711fa71b9SJerome Forissier                                         ssl->in_msg[0] ) );
494811fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INVALID_RECORD );
494911fa71b9SJerome Forissier         }
495011fa71b9SJerome Forissier 
495111fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
495211fa71b9SJerome Forissier         if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
495311fa71b9SJerome Forissier             ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC    &&
495411fa71b9SJerome Forissier             ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC )
495511fa71b9SJerome Forissier         {
495611fa71b9SJerome Forissier             if( ssl->handshake == NULL )
495711fa71b9SJerome Forissier             {
495811fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping ChangeCipherSpec outside handshake" ) );
495911fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
496011fa71b9SJerome Forissier             }
496111fa71b9SJerome Forissier 
496211fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "received out-of-order ChangeCipherSpec - remember" ) );
496311fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_EARLY_MESSAGE );
496411fa71b9SJerome Forissier         }
496511fa71b9SJerome Forissier #endif
496611fa71b9SJerome Forissier     }
496711fa71b9SJerome Forissier 
496811fa71b9SJerome Forissier     if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT )
496911fa71b9SJerome Forissier     {
497011fa71b9SJerome Forissier         if( ssl->in_msglen != 2 )
497111fa71b9SJerome Forissier         {
497211fa71b9SJerome Forissier             /* Note: Standard allows for more than one 2 byte alert
497311fa71b9SJerome Forissier                to be packed in a single message, but Mbed TLS doesn't
497411fa71b9SJerome Forissier                currently support this. */
4975*7901324dSJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid alert message, len: %" MBEDTLS_PRINTF_SIZET,
497611fa71b9SJerome Forissier                            ssl->in_msglen ) );
497711fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INVALID_RECORD );
497811fa71b9SJerome Forissier         }
497911fa71b9SJerome Forissier 
4980*7901324dSJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 2, ( "got an alert message, type: [%u:%u]",
498111fa71b9SJerome Forissier                        ssl->in_msg[0], ssl->in_msg[1] ) );
498211fa71b9SJerome Forissier 
498311fa71b9SJerome Forissier         /*
498411fa71b9SJerome Forissier          * Ignore non-fatal alerts, except close_notify and no_renegotiation
498511fa71b9SJerome Forissier          */
498611fa71b9SJerome Forissier         if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_FATAL )
498711fa71b9SJerome Forissier         {
498811fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "is a fatal alert message (msg %d)",
498911fa71b9SJerome Forissier                            ssl->in_msg[1] ) );
499011fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE );
499111fa71b9SJerome Forissier         }
499211fa71b9SJerome Forissier 
499311fa71b9SJerome Forissier         if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING &&
499411fa71b9SJerome Forissier             ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY )
499511fa71b9SJerome Forissier         {
499611fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a close notify message" ) );
499711fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY );
499811fa71b9SJerome Forissier         }
499911fa71b9SJerome Forissier 
500011fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_RENEGOTIATION_ENABLED)
500111fa71b9SJerome Forissier         if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING &&
500211fa71b9SJerome Forissier             ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION )
500311fa71b9SJerome Forissier         {
500411fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no renegotiation alert" ) );
500511fa71b9SJerome Forissier             /* Will be handled when trying to parse ServerHello */
500611fa71b9SJerome Forissier             return( 0 );
500711fa71b9SJerome Forissier         }
500811fa71b9SJerome Forissier #endif
500911fa71b9SJerome Forissier 
501011fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_SRV_C)
501111fa71b9SJerome Forissier         if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 &&
501211fa71b9SJerome Forissier             ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
501311fa71b9SJerome Forissier             ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING &&
501411fa71b9SJerome Forissier             ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_CERT )
501511fa71b9SJerome Forissier         {
501611fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no_cert" ) );
501711fa71b9SJerome Forissier             /* Will be handled in mbedtls_ssl_parse_certificate() */
501811fa71b9SJerome Forissier             return( 0 );
501911fa71b9SJerome Forissier         }
502011fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */
502111fa71b9SJerome Forissier 
502211fa71b9SJerome Forissier         /* Silently ignore: fetch new message */
502311fa71b9SJerome Forissier         return MBEDTLS_ERR_SSL_NON_FATAL;
502411fa71b9SJerome Forissier     }
502511fa71b9SJerome Forissier 
502611fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
502711fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
502811fa71b9SJerome Forissier     {
502911fa71b9SJerome Forissier         /* Drop unexpected ApplicationData records,
503011fa71b9SJerome Forissier          * except at the beginning of renegotiations */
503111fa71b9SJerome Forissier         if( ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA &&
503211fa71b9SJerome Forissier             ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER
503311fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_RENEGOTIATION)
503411fa71b9SJerome Forissier             && ! ( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
503511fa71b9SJerome Forissier                    ssl->state == MBEDTLS_SSL_SERVER_HELLO )
503611fa71b9SJerome Forissier #endif
503711fa71b9SJerome Forissier             )
503811fa71b9SJerome Forissier         {
503911fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ApplicationData" ) );
504011fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_NON_FATAL );
504111fa71b9SJerome Forissier         }
504211fa71b9SJerome Forissier 
504311fa71b9SJerome Forissier         if( ssl->handshake != NULL &&
504411fa71b9SJerome Forissier             ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER  )
504511fa71b9SJerome Forissier         {
504611fa71b9SJerome Forissier             mbedtls_ssl_handshake_wrapup_free_hs_transform( ssl );
504711fa71b9SJerome Forissier         }
504811fa71b9SJerome Forissier     }
504911fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
505011fa71b9SJerome Forissier 
505111fa71b9SJerome Forissier     return( 0 );
505211fa71b9SJerome Forissier }
505311fa71b9SJerome Forissier 
505411fa71b9SJerome Forissier int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl )
505511fa71b9SJerome Forissier {
505611fa71b9SJerome Forissier     return( mbedtls_ssl_send_alert_message( ssl,
505711fa71b9SJerome Forissier                   MBEDTLS_SSL_ALERT_LEVEL_FATAL,
505811fa71b9SJerome Forissier                   MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ) );
505911fa71b9SJerome Forissier }
506011fa71b9SJerome Forissier 
506111fa71b9SJerome Forissier int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl,
506211fa71b9SJerome Forissier                             unsigned char level,
506311fa71b9SJerome Forissier                             unsigned char message )
506411fa71b9SJerome Forissier {
506511fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
506611fa71b9SJerome Forissier 
506711fa71b9SJerome Forissier     if( ssl == NULL || ssl->conf == NULL )
506811fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
506911fa71b9SJerome Forissier 
507011fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> send alert message" ) );
507111fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 3, ( "send alert level=%u message=%u", level, message ));
507211fa71b9SJerome Forissier 
507311fa71b9SJerome Forissier     ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT;
507411fa71b9SJerome Forissier     ssl->out_msglen = 2;
507511fa71b9SJerome Forissier     ssl->out_msg[0] = level;
507611fa71b9SJerome Forissier     ssl->out_msg[1] = message;
507711fa71b9SJerome Forissier 
507811fa71b9SJerome Forissier     if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 )
507911fa71b9SJerome Forissier     {
508011fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
508111fa71b9SJerome Forissier         return( ret );
508211fa71b9SJerome Forissier     }
508311fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= send alert message" ) );
508411fa71b9SJerome Forissier 
508511fa71b9SJerome Forissier     return( 0 );
508611fa71b9SJerome Forissier }
508711fa71b9SJerome Forissier 
508811fa71b9SJerome Forissier int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl )
508911fa71b9SJerome Forissier {
509011fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
509111fa71b9SJerome Forissier 
509211fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write change cipher spec" ) );
509311fa71b9SJerome Forissier 
509411fa71b9SJerome Forissier     ssl->out_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC;
509511fa71b9SJerome Forissier     ssl->out_msglen  = 1;
509611fa71b9SJerome Forissier     ssl->out_msg[0]  = 1;
509711fa71b9SJerome Forissier 
509811fa71b9SJerome Forissier     ssl->state++;
509911fa71b9SJerome Forissier 
510011fa71b9SJerome Forissier     if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
510111fa71b9SJerome Forissier     {
510211fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
510311fa71b9SJerome Forissier         return( ret );
510411fa71b9SJerome Forissier     }
510511fa71b9SJerome Forissier 
510611fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write change cipher spec" ) );
510711fa71b9SJerome Forissier 
510811fa71b9SJerome Forissier     return( 0 );
510911fa71b9SJerome Forissier }
511011fa71b9SJerome Forissier 
511111fa71b9SJerome Forissier int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl )
511211fa71b9SJerome Forissier {
511311fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
511411fa71b9SJerome Forissier 
511511fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse change cipher spec" ) );
511611fa71b9SJerome Forissier 
511711fa71b9SJerome Forissier     if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
511811fa71b9SJerome Forissier     {
511911fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
512011fa71b9SJerome Forissier         return( ret );
512111fa71b9SJerome Forissier     }
512211fa71b9SJerome Forissier 
512311fa71b9SJerome Forissier     if( ssl->in_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC )
512411fa71b9SJerome Forissier     {
512511fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) );
512611fa71b9SJerome Forissier         mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
512711fa71b9SJerome Forissier                                         MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
512811fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
512911fa71b9SJerome Forissier     }
513011fa71b9SJerome Forissier 
513111fa71b9SJerome Forissier     /* CCS records are only accepted if they have length 1 and content '1',
513211fa71b9SJerome Forissier      * so we don't need to check this here. */
513311fa71b9SJerome Forissier 
513411fa71b9SJerome Forissier     /*
513511fa71b9SJerome Forissier      * Switch to our negotiated transform and session parameters for inbound
513611fa71b9SJerome Forissier      * data.
513711fa71b9SJerome Forissier      */
513811fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 3, ( "switching to new transform spec for inbound data" ) );
513911fa71b9SJerome Forissier     ssl->transform_in = ssl->transform_negotiate;
514011fa71b9SJerome Forissier     ssl->session_in = ssl->session_negotiate;
514111fa71b9SJerome Forissier 
514211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
514311fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
514411fa71b9SJerome Forissier     {
514511fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
514611fa71b9SJerome Forissier         mbedtls_ssl_dtls_replay_reset( ssl );
514711fa71b9SJerome Forissier #endif
514811fa71b9SJerome Forissier 
514911fa71b9SJerome Forissier         /* Increment epoch */
515011fa71b9SJerome Forissier         if( ++ssl->in_epoch == 0 )
515111fa71b9SJerome Forissier         {
515211fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS epoch would wrap" ) );
515311fa71b9SJerome Forissier             /* This is highly unlikely to happen for legitimate reasons, so
515411fa71b9SJerome Forissier                treat it as an attack and don't send an alert. */
515511fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING );
515611fa71b9SJerome Forissier         }
515711fa71b9SJerome Forissier     }
515811fa71b9SJerome Forissier     else
515911fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
516011fa71b9SJerome Forissier     memset( ssl->in_ctr, 0, 8 );
516111fa71b9SJerome Forissier 
516211fa71b9SJerome Forissier     mbedtls_ssl_update_in_pointers( ssl );
516311fa71b9SJerome Forissier 
516411fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
516511fa71b9SJerome Forissier     if( mbedtls_ssl_hw_record_activate != NULL )
516611fa71b9SJerome Forissier     {
516711fa71b9SJerome Forissier         if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_INBOUND ) ) != 0 )
516811fa71b9SJerome Forissier         {
516911fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret );
517011fa71b9SJerome Forissier             mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
517111fa71b9SJerome Forissier                                             MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
517211fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
517311fa71b9SJerome Forissier         }
517411fa71b9SJerome Forissier     }
517511fa71b9SJerome Forissier #endif
517611fa71b9SJerome Forissier 
517711fa71b9SJerome Forissier     ssl->state++;
517811fa71b9SJerome Forissier 
517911fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse change cipher spec" ) );
518011fa71b9SJerome Forissier 
518111fa71b9SJerome Forissier     return( 0 );
518211fa71b9SJerome Forissier }
518311fa71b9SJerome Forissier 
518411fa71b9SJerome Forissier /* Once ssl->out_hdr as the address of the beginning of the
518511fa71b9SJerome Forissier  * next outgoing record is set, deduce the other pointers.
518611fa71b9SJerome Forissier  *
518711fa71b9SJerome Forissier  * Note: For TLS, we save the implicit record sequence number
518811fa71b9SJerome Forissier  *       (entering MAC computation) in the 8 bytes before ssl->out_hdr,
518911fa71b9SJerome Forissier  *       and the caller has to make sure there's space for this.
519011fa71b9SJerome Forissier  */
519111fa71b9SJerome Forissier 
5192*7901324dSJerome Forissier static size_t ssl_transform_get_explicit_iv_len(
5193*7901324dSJerome Forissier                         mbedtls_ssl_transform const *transform )
5194*7901324dSJerome Forissier {
5195*7901324dSJerome Forissier     if( transform->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 )
5196*7901324dSJerome Forissier         return( 0 );
5197*7901324dSJerome Forissier 
5198*7901324dSJerome Forissier     return( transform->ivlen - transform->fixed_ivlen );
5199*7901324dSJerome Forissier }
5200*7901324dSJerome Forissier 
520111fa71b9SJerome Forissier void mbedtls_ssl_update_out_pointers( mbedtls_ssl_context *ssl,
520211fa71b9SJerome Forissier                                       mbedtls_ssl_transform *transform )
520311fa71b9SJerome Forissier {
520411fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
520511fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
520611fa71b9SJerome Forissier     {
520711fa71b9SJerome Forissier         ssl->out_ctr = ssl->out_hdr +  3;
520811fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
520911fa71b9SJerome Forissier         ssl->out_cid = ssl->out_ctr +  8;
521011fa71b9SJerome Forissier         ssl->out_len = ssl->out_cid;
521111fa71b9SJerome Forissier         if( transform != NULL )
521211fa71b9SJerome Forissier             ssl->out_len += transform->out_cid_len;
521311fa71b9SJerome Forissier #else /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
521411fa71b9SJerome Forissier         ssl->out_len = ssl->out_ctr + 8;
521511fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
521611fa71b9SJerome Forissier         ssl->out_iv  = ssl->out_len + 2;
521711fa71b9SJerome Forissier     }
521811fa71b9SJerome Forissier     else
521911fa71b9SJerome Forissier #endif
522011fa71b9SJerome Forissier     {
522111fa71b9SJerome Forissier         ssl->out_ctr = ssl->out_hdr - 8;
522211fa71b9SJerome Forissier         ssl->out_len = ssl->out_hdr + 3;
522311fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
522411fa71b9SJerome Forissier         ssl->out_cid = ssl->out_len;
522511fa71b9SJerome Forissier #endif
522611fa71b9SJerome Forissier         ssl->out_iv  = ssl->out_hdr + 5;
522711fa71b9SJerome Forissier     }
522811fa71b9SJerome Forissier 
522911fa71b9SJerome Forissier     ssl->out_msg = ssl->out_iv;
5230*7901324dSJerome Forissier     /* Adjust out_msg to make space for explicit IV, if used. */
5231*7901324dSJerome Forissier     if( transform != NULL )
5232*7901324dSJerome Forissier         ssl->out_msg += ssl_transform_get_explicit_iv_len( transform );
523311fa71b9SJerome Forissier }
523411fa71b9SJerome Forissier 
523511fa71b9SJerome Forissier /* Once ssl->in_hdr as the address of the beginning of the
523611fa71b9SJerome Forissier  * next incoming record is set, deduce the other pointers.
523711fa71b9SJerome Forissier  *
523811fa71b9SJerome Forissier  * Note: For TLS, we save the implicit record sequence number
523911fa71b9SJerome Forissier  *       (entering MAC computation) in the 8 bytes before ssl->in_hdr,
524011fa71b9SJerome Forissier  *       and the caller has to make sure there's space for this.
524111fa71b9SJerome Forissier  */
524211fa71b9SJerome Forissier 
524311fa71b9SJerome Forissier void mbedtls_ssl_update_in_pointers( mbedtls_ssl_context *ssl )
524411fa71b9SJerome Forissier {
524511fa71b9SJerome Forissier     /* This function sets the pointers to match the case
524611fa71b9SJerome Forissier      * of unprotected TLS/DTLS records, with both  ssl->in_iv
524711fa71b9SJerome Forissier      * and ssl->in_msg pointing to the beginning of the record
524811fa71b9SJerome Forissier      * content.
524911fa71b9SJerome Forissier      *
525011fa71b9SJerome Forissier      * When decrypting a protected record, ssl->in_msg
525111fa71b9SJerome Forissier      * will be shifted to point to the beginning of the
525211fa71b9SJerome Forissier      * record plaintext.
525311fa71b9SJerome Forissier      */
525411fa71b9SJerome Forissier 
525511fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
525611fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
525711fa71b9SJerome Forissier     {
525811fa71b9SJerome Forissier         /* This sets the header pointers to match records
525911fa71b9SJerome Forissier          * without CID. When we receive a record containing
526011fa71b9SJerome Forissier          * a CID, the fields are shifted accordingly in
526111fa71b9SJerome Forissier          * ssl_parse_record_header(). */
526211fa71b9SJerome Forissier         ssl->in_ctr = ssl->in_hdr +  3;
526311fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
526411fa71b9SJerome Forissier         ssl->in_cid = ssl->in_ctr +  8;
526511fa71b9SJerome Forissier         ssl->in_len = ssl->in_cid; /* Default: no CID */
526611fa71b9SJerome Forissier #else /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
526711fa71b9SJerome Forissier         ssl->in_len = ssl->in_ctr + 8;
526811fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
526911fa71b9SJerome Forissier         ssl->in_iv  = ssl->in_len + 2;
527011fa71b9SJerome Forissier     }
527111fa71b9SJerome Forissier     else
527211fa71b9SJerome Forissier #endif
527311fa71b9SJerome Forissier     {
527411fa71b9SJerome Forissier         ssl->in_ctr = ssl->in_hdr - 8;
527511fa71b9SJerome Forissier         ssl->in_len = ssl->in_hdr + 3;
527611fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
527711fa71b9SJerome Forissier         ssl->in_cid = ssl->in_len;
527811fa71b9SJerome Forissier #endif
527911fa71b9SJerome Forissier         ssl->in_iv  = ssl->in_hdr + 5;
528011fa71b9SJerome Forissier     }
528111fa71b9SJerome Forissier 
528211fa71b9SJerome Forissier     /* This will be adjusted at record decryption time. */
528311fa71b9SJerome Forissier     ssl->in_msg = ssl->in_iv;
528411fa71b9SJerome Forissier }
528511fa71b9SJerome Forissier 
528611fa71b9SJerome Forissier /*
528711fa71b9SJerome Forissier  * Setup an SSL context
528811fa71b9SJerome Forissier  */
528911fa71b9SJerome Forissier 
529011fa71b9SJerome Forissier void mbedtls_ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl )
529111fa71b9SJerome Forissier {
529211fa71b9SJerome Forissier     /* Set the incoming and outgoing record pointers. */
529311fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
529411fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
529511fa71b9SJerome Forissier     {
529611fa71b9SJerome Forissier         ssl->out_hdr = ssl->out_buf;
529711fa71b9SJerome Forissier         ssl->in_hdr  = ssl->in_buf;
529811fa71b9SJerome Forissier     }
529911fa71b9SJerome Forissier     else
530011fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
530111fa71b9SJerome Forissier     {
530211fa71b9SJerome Forissier         ssl->out_hdr = ssl->out_buf + 8;
530311fa71b9SJerome Forissier         ssl->in_hdr  = ssl->in_buf  + 8;
530411fa71b9SJerome Forissier     }
530511fa71b9SJerome Forissier 
530611fa71b9SJerome Forissier     /* Derive other internal pointers. */
530711fa71b9SJerome Forissier     mbedtls_ssl_update_out_pointers( ssl, NULL /* no transform enabled */ );
530811fa71b9SJerome Forissier     mbedtls_ssl_update_in_pointers ( ssl );
530911fa71b9SJerome Forissier }
531011fa71b9SJerome Forissier 
531111fa71b9SJerome Forissier /*
531211fa71b9SJerome Forissier  * SSL get accessors
531311fa71b9SJerome Forissier  */
531411fa71b9SJerome Forissier size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl )
531511fa71b9SJerome Forissier {
531611fa71b9SJerome Forissier     return( ssl->in_offt == NULL ? 0 : ssl->in_msglen );
531711fa71b9SJerome Forissier }
531811fa71b9SJerome Forissier 
531911fa71b9SJerome Forissier int mbedtls_ssl_check_pending( const mbedtls_ssl_context *ssl )
532011fa71b9SJerome Forissier {
532111fa71b9SJerome Forissier     /*
532211fa71b9SJerome Forissier      * Case A: We're currently holding back
532311fa71b9SJerome Forissier      * a message for further processing.
532411fa71b9SJerome Forissier      */
532511fa71b9SJerome Forissier 
532611fa71b9SJerome Forissier     if( ssl->keep_current_message == 1 )
532711fa71b9SJerome Forissier     {
532811fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: record held back for processing" ) );
532911fa71b9SJerome Forissier         return( 1 );
533011fa71b9SJerome Forissier     }
533111fa71b9SJerome Forissier 
533211fa71b9SJerome Forissier     /*
533311fa71b9SJerome Forissier      * Case B: Further records are pending in the current datagram.
533411fa71b9SJerome Forissier      */
533511fa71b9SJerome Forissier 
533611fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
533711fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
533811fa71b9SJerome Forissier         ssl->in_left > ssl->next_record_offset )
533911fa71b9SJerome Forissier     {
534011fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: more records within current datagram" ) );
534111fa71b9SJerome Forissier         return( 1 );
534211fa71b9SJerome Forissier     }
534311fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
534411fa71b9SJerome Forissier 
534511fa71b9SJerome Forissier     /*
534611fa71b9SJerome Forissier      * Case C: A handshake message is being processed.
534711fa71b9SJerome Forissier      */
534811fa71b9SJerome Forissier 
534911fa71b9SJerome Forissier     if( ssl->in_hslen > 0 && ssl->in_hslen < ssl->in_msglen )
535011fa71b9SJerome Forissier     {
535111fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: more handshake messages within current record" ) );
535211fa71b9SJerome Forissier         return( 1 );
535311fa71b9SJerome Forissier     }
535411fa71b9SJerome Forissier 
535511fa71b9SJerome Forissier     /*
535611fa71b9SJerome Forissier      * Case D: An application data message is being processed
535711fa71b9SJerome Forissier      */
535811fa71b9SJerome Forissier     if( ssl->in_offt != NULL )
535911fa71b9SJerome Forissier     {
536011fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: application data record is being processed" ) );
536111fa71b9SJerome Forissier         return( 1 );
536211fa71b9SJerome Forissier     }
536311fa71b9SJerome Forissier 
536411fa71b9SJerome Forissier     /*
536511fa71b9SJerome Forissier      * In all other cases, the rest of the message can be dropped.
536611fa71b9SJerome Forissier      * As in ssl_get_next_record, this needs to be adapted if
536711fa71b9SJerome Forissier      * we implement support for multiple alerts in single records.
536811fa71b9SJerome Forissier      */
536911fa71b9SJerome Forissier 
537011fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: nothing pending" ) );
537111fa71b9SJerome Forissier     return( 0 );
537211fa71b9SJerome Forissier }
537311fa71b9SJerome Forissier 
537411fa71b9SJerome Forissier 
537511fa71b9SJerome Forissier int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl )
537611fa71b9SJerome Forissier {
537711fa71b9SJerome Forissier     size_t transform_expansion = 0;
537811fa71b9SJerome Forissier     const mbedtls_ssl_transform *transform = ssl->transform_out;
537911fa71b9SJerome Forissier     unsigned block_size;
538011fa71b9SJerome Forissier 
538111fa71b9SJerome Forissier     size_t out_hdr_len = mbedtls_ssl_out_hdr_len( ssl );
538211fa71b9SJerome Forissier 
538311fa71b9SJerome Forissier     if( transform == NULL )
538411fa71b9SJerome Forissier         return( (int) out_hdr_len );
538511fa71b9SJerome Forissier 
538611fa71b9SJerome Forissier #if defined(MBEDTLS_ZLIB_SUPPORT)
538711fa71b9SJerome Forissier     if( ssl->session_out->compression != MBEDTLS_SSL_COMPRESS_NULL )
538811fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
538911fa71b9SJerome Forissier #endif
539011fa71b9SJerome Forissier 
539111fa71b9SJerome Forissier     switch( mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc ) )
539211fa71b9SJerome Forissier     {
539311fa71b9SJerome Forissier         case MBEDTLS_MODE_GCM:
539411fa71b9SJerome Forissier         case MBEDTLS_MODE_CCM:
539511fa71b9SJerome Forissier         case MBEDTLS_MODE_CHACHAPOLY:
539611fa71b9SJerome Forissier         case MBEDTLS_MODE_STREAM:
539711fa71b9SJerome Forissier             transform_expansion = transform->minlen;
539811fa71b9SJerome Forissier             break;
539911fa71b9SJerome Forissier 
540011fa71b9SJerome Forissier         case MBEDTLS_MODE_CBC:
540111fa71b9SJerome Forissier 
540211fa71b9SJerome Forissier             block_size = mbedtls_cipher_get_block_size(
540311fa71b9SJerome Forissier                 &transform->cipher_ctx_enc );
540411fa71b9SJerome Forissier 
540511fa71b9SJerome Forissier             /* Expansion due to the addition of the MAC. */
540611fa71b9SJerome Forissier             transform_expansion += transform->maclen;
540711fa71b9SJerome Forissier 
540811fa71b9SJerome Forissier             /* Expansion due to the addition of CBC padding;
540911fa71b9SJerome Forissier              * Theoretically up to 256 bytes, but we never use
541011fa71b9SJerome Forissier              * more than the block size of the underlying cipher. */
541111fa71b9SJerome Forissier             transform_expansion += block_size;
541211fa71b9SJerome Forissier 
541311fa71b9SJerome Forissier             /* For TLS 1.1 or higher, an explicit IV is added
541411fa71b9SJerome Forissier              * after the record header. */
541511fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)
541611fa71b9SJerome Forissier             if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
541711fa71b9SJerome Forissier                 transform_expansion += block_size;
541811fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */
541911fa71b9SJerome Forissier 
542011fa71b9SJerome Forissier             break;
542111fa71b9SJerome Forissier 
542211fa71b9SJerome Forissier         default:
542311fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
542411fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
542511fa71b9SJerome Forissier     }
542611fa71b9SJerome Forissier 
542711fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
542811fa71b9SJerome Forissier     if( transform->out_cid_len != 0 )
542911fa71b9SJerome Forissier         transform_expansion += MBEDTLS_SSL_MAX_CID_EXPANSION;
543011fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
543111fa71b9SJerome Forissier 
543211fa71b9SJerome Forissier     return( (int)( out_hdr_len + transform_expansion ) );
543311fa71b9SJerome Forissier }
543411fa71b9SJerome Forissier 
543511fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_RENEGOTIATION)
543611fa71b9SJerome Forissier /*
543711fa71b9SJerome Forissier  * Check record counters and renegotiate if they're above the limit.
543811fa71b9SJerome Forissier  */
543911fa71b9SJerome Forissier static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl )
544011fa71b9SJerome Forissier {
544111fa71b9SJerome Forissier     size_t ep_len = mbedtls_ssl_ep_len( ssl );
544211fa71b9SJerome Forissier     int in_ctr_cmp;
544311fa71b9SJerome Forissier     int out_ctr_cmp;
544411fa71b9SJerome Forissier 
544511fa71b9SJerome Forissier     if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ||
544611fa71b9SJerome Forissier         ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ||
544711fa71b9SJerome Forissier         ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED )
544811fa71b9SJerome Forissier     {
544911fa71b9SJerome Forissier         return( 0 );
545011fa71b9SJerome Forissier     }
545111fa71b9SJerome Forissier 
545211fa71b9SJerome Forissier     in_ctr_cmp = memcmp( ssl->in_ctr + ep_len,
545311fa71b9SJerome Forissier                         ssl->conf->renego_period + ep_len, 8 - ep_len );
545411fa71b9SJerome Forissier     out_ctr_cmp = memcmp( ssl->cur_out_ctr + ep_len,
545511fa71b9SJerome Forissier                           ssl->conf->renego_period + ep_len, 8 - ep_len );
545611fa71b9SJerome Forissier 
545711fa71b9SJerome Forissier     if( in_ctr_cmp <= 0 && out_ctr_cmp <= 0 )
545811fa71b9SJerome Forissier     {
545911fa71b9SJerome Forissier         return( 0 );
546011fa71b9SJerome Forissier     }
546111fa71b9SJerome Forissier 
546211fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 1, ( "record counter limit reached: renegotiate" ) );
546311fa71b9SJerome Forissier     return( mbedtls_ssl_renegotiate( ssl ) );
546411fa71b9SJerome Forissier }
546511fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_RENEGOTIATION */
546611fa71b9SJerome Forissier 
546711fa71b9SJerome Forissier /*
546811fa71b9SJerome Forissier  * Receive application data decrypted from the SSL layer
546911fa71b9SJerome Forissier  */
547011fa71b9SJerome Forissier int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
547111fa71b9SJerome Forissier {
547211fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
547311fa71b9SJerome Forissier     size_t n;
547411fa71b9SJerome Forissier 
547511fa71b9SJerome Forissier     if( ssl == NULL || ssl->conf == NULL )
547611fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
547711fa71b9SJerome Forissier 
547811fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read" ) );
547911fa71b9SJerome Forissier 
548011fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
548111fa71b9SJerome Forissier     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
548211fa71b9SJerome Forissier     {
548311fa71b9SJerome Forissier         if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
548411fa71b9SJerome Forissier             return( ret );
548511fa71b9SJerome Forissier 
548611fa71b9SJerome Forissier         if( ssl->handshake != NULL &&
548711fa71b9SJerome Forissier             ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING )
548811fa71b9SJerome Forissier         {
548911fa71b9SJerome Forissier             if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
549011fa71b9SJerome Forissier                 return( ret );
549111fa71b9SJerome Forissier         }
549211fa71b9SJerome Forissier     }
549311fa71b9SJerome Forissier #endif
549411fa71b9SJerome Forissier 
549511fa71b9SJerome Forissier     /*
549611fa71b9SJerome Forissier      * Check if renegotiation is necessary and/or handshake is
549711fa71b9SJerome Forissier      * in process. If yes, perform/continue, and fall through
549811fa71b9SJerome Forissier      * if an unexpected packet is received while the client
549911fa71b9SJerome Forissier      * is waiting for the ServerHello.
550011fa71b9SJerome Forissier      *
550111fa71b9SJerome Forissier      * (There is no equivalent to the last condition on
550211fa71b9SJerome Forissier      *  the server-side as it is not treated as within
550311fa71b9SJerome Forissier      *  a handshake while waiting for the ClientHello
550411fa71b9SJerome Forissier      *  after a renegotiation request.)
550511fa71b9SJerome Forissier      */
550611fa71b9SJerome Forissier 
550711fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_RENEGOTIATION)
550811fa71b9SJerome Forissier     ret = ssl_check_ctr_renegotiate( ssl );
550911fa71b9SJerome Forissier     if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO &&
551011fa71b9SJerome Forissier         ret != 0 )
551111fa71b9SJerome Forissier     {
551211fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret );
551311fa71b9SJerome Forissier         return( ret );
551411fa71b9SJerome Forissier     }
551511fa71b9SJerome Forissier #endif
551611fa71b9SJerome Forissier 
551711fa71b9SJerome Forissier     if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
551811fa71b9SJerome Forissier     {
551911fa71b9SJerome Forissier         ret = mbedtls_ssl_handshake( ssl );
552011fa71b9SJerome Forissier         if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO &&
552111fa71b9SJerome Forissier             ret != 0 )
552211fa71b9SJerome Forissier         {
552311fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret );
552411fa71b9SJerome Forissier             return( ret );
552511fa71b9SJerome Forissier         }
552611fa71b9SJerome Forissier     }
552711fa71b9SJerome Forissier 
552811fa71b9SJerome Forissier     /* Loop as long as no application data record is available */
552911fa71b9SJerome Forissier     while( ssl->in_offt == NULL )
553011fa71b9SJerome Forissier     {
553111fa71b9SJerome Forissier         /* Start timer if not already running */
553211fa71b9SJerome Forissier         if( ssl->f_get_timer != NULL &&
553311fa71b9SJerome Forissier             ssl->f_get_timer( ssl->p_timer ) == -1 )
553411fa71b9SJerome Forissier         {
553511fa71b9SJerome Forissier             mbedtls_ssl_set_timer( ssl, ssl->conf->read_timeout );
553611fa71b9SJerome Forissier         }
553711fa71b9SJerome Forissier 
553811fa71b9SJerome Forissier         if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
553911fa71b9SJerome Forissier         {
554011fa71b9SJerome Forissier             if( ret == MBEDTLS_ERR_SSL_CONN_EOF )
554111fa71b9SJerome Forissier                 return( 0 );
554211fa71b9SJerome Forissier 
554311fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
554411fa71b9SJerome Forissier             return( ret );
554511fa71b9SJerome Forissier         }
554611fa71b9SJerome Forissier 
554711fa71b9SJerome Forissier         if( ssl->in_msglen  == 0 &&
554811fa71b9SJerome Forissier             ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA )
554911fa71b9SJerome Forissier         {
555011fa71b9SJerome Forissier             /*
555111fa71b9SJerome Forissier              * OpenSSL sends empty messages to randomize the IV
555211fa71b9SJerome Forissier              */
555311fa71b9SJerome Forissier             if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
555411fa71b9SJerome Forissier             {
555511fa71b9SJerome Forissier                 if( ret == MBEDTLS_ERR_SSL_CONN_EOF )
555611fa71b9SJerome Forissier                     return( 0 );
555711fa71b9SJerome Forissier 
555811fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
555911fa71b9SJerome Forissier                 return( ret );
556011fa71b9SJerome Forissier             }
556111fa71b9SJerome Forissier         }
556211fa71b9SJerome Forissier 
556311fa71b9SJerome Forissier         if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE )
556411fa71b9SJerome Forissier         {
556511fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "received handshake message" ) );
556611fa71b9SJerome Forissier 
556711fa71b9SJerome Forissier             /*
556811fa71b9SJerome Forissier              * - For client-side, expect SERVER_HELLO_REQUEST.
556911fa71b9SJerome Forissier              * - For server-side, expect CLIENT_HELLO.
557011fa71b9SJerome Forissier              * - Fail (TLS) or silently drop record (DTLS) in other cases.
557111fa71b9SJerome Forissier              */
557211fa71b9SJerome Forissier 
557311fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_CLI_C)
557411fa71b9SJerome Forissier             if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
557511fa71b9SJerome Forissier                 ( ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_REQUEST ||
557611fa71b9SJerome Forissier                   ssl->in_hslen  != mbedtls_ssl_hs_hdr_len( ssl ) ) )
557711fa71b9SJerome Forissier             {
557811fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not HelloRequest)" ) );
557911fa71b9SJerome Forissier 
558011fa71b9SJerome Forissier                 /* With DTLS, drop the packet (probably from last handshake) */
558111fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
558211fa71b9SJerome Forissier                 if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
558311fa71b9SJerome Forissier                 {
558411fa71b9SJerome Forissier                     continue;
558511fa71b9SJerome Forissier                 }
558611fa71b9SJerome Forissier #endif
558711fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
558811fa71b9SJerome Forissier             }
558911fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_CLI_C */
559011fa71b9SJerome Forissier 
559111fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_SRV_C)
559211fa71b9SJerome Forissier             if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
559311fa71b9SJerome Forissier                 ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO )
559411fa71b9SJerome Forissier             {
559511fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not ClientHello)" ) );
559611fa71b9SJerome Forissier 
559711fa71b9SJerome Forissier                 /* With DTLS, drop the packet (probably from last handshake) */
559811fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
559911fa71b9SJerome Forissier                 if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
560011fa71b9SJerome Forissier                 {
560111fa71b9SJerome Forissier                     continue;
560211fa71b9SJerome Forissier                 }
560311fa71b9SJerome Forissier #endif
560411fa71b9SJerome Forissier                 return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
560511fa71b9SJerome Forissier             }
560611fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_SRV_C */
560711fa71b9SJerome Forissier 
560811fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_RENEGOTIATION)
560911fa71b9SJerome Forissier             /* Determine whether renegotiation attempt should be accepted */
561011fa71b9SJerome Forissier             if( ! ( ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED ||
561111fa71b9SJerome Forissier                     ( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
561211fa71b9SJerome Forissier                       ssl->conf->allow_legacy_renegotiation ==
561311fa71b9SJerome Forissier                                                    MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) ) )
561411fa71b9SJerome Forissier             {
561511fa71b9SJerome Forissier                 /*
561611fa71b9SJerome Forissier                  * Accept renegotiation request
561711fa71b9SJerome Forissier                  */
561811fa71b9SJerome Forissier 
561911fa71b9SJerome Forissier                 /* DTLS clients need to know renego is server-initiated */
562011fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
562111fa71b9SJerome Forissier                 if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
562211fa71b9SJerome Forissier                     ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
562311fa71b9SJerome Forissier                 {
562411fa71b9SJerome Forissier                     ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING;
562511fa71b9SJerome Forissier                 }
562611fa71b9SJerome Forissier #endif
562711fa71b9SJerome Forissier                 ret = mbedtls_ssl_start_renegotiation( ssl );
562811fa71b9SJerome Forissier                 if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO &&
562911fa71b9SJerome Forissier                     ret != 0 )
563011fa71b9SJerome Forissier                 {
563111fa71b9SJerome Forissier                     MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_start_renegotiation",
563211fa71b9SJerome Forissier                                            ret );
563311fa71b9SJerome Forissier                     return( ret );
563411fa71b9SJerome Forissier                 }
563511fa71b9SJerome Forissier             }
563611fa71b9SJerome Forissier             else
563711fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_RENEGOTIATION */
563811fa71b9SJerome Forissier             {
563911fa71b9SJerome Forissier                 /*
564011fa71b9SJerome Forissier                  * Refuse renegotiation
564111fa71b9SJerome Forissier                  */
564211fa71b9SJerome Forissier 
564311fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_MSG( 3, ( "refusing renegotiation, sending alert" ) );
564411fa71b9SJerome Forissier 
564511fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_SSL3)
564611fa71b9SJerome Forissier                 if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
564711fa71b9SJerome Forissier                 {
564811fa71b9SJerome Forissier                     /* SSLv3 does not have a "no_renegotiation" warning, so
564911fa71b9SJerome Forissier                        we send a fatal alert and abort the connection. */
565011fa71b9SJerome Forissier                     mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
565111fa71b9SJerome Forissier                                                     MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
565211fa71b9SJerome Forissier                     return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
565311fa71b9SJerome Forissier                 }
565411fa71b9SJerome Forissier                 else
565511fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_SSL3 */
565611fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
565711fa71b9SJerome Forissier     defined(MBEDTLS_SSL_PROTO_TLS1_2)
565811fa71b9SJerome Forissier                 if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 )
565911fa71b9SJerome Forissier                 {
566011fa71b9SJerome Forissier                     if( ( ret = mbedtls_ssl_send_alert_message( ssl,
566111fa71b9SJerome Forissier                                     MBEDTLS_SSL_ALERT_LEVEL_WARNING,
566211fa71b9SJerome Forissier                                     MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION ) ) != 0 )
566311fa71b9SJerome Forissier                     {
566411fa71b9SJerome Forissier                         return( ret );
566511fa71b9SJerome Forissier                     }
566611fa71b9SJerome Forissier                 }
566711fa71b9SJerome Forissier                 else
566811fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 ||
566911fa71b9SJerome Forissier           MBEDTLS_SSL_PROTO_TLS1_2 */
567011fa71b9SJerome Forissier                 {
567111fa71b9SJerome Forissier                     MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
567211fa71b9SJerome Forissier                     return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
567311fa71b9SJerome Forissier                 }
567411fa71b9SJerome Forissier             }
567511fa71b9SJerome Forissier 
567611fa71b9SJerome Forissier             /* At this point, we don't know whether the renegotiation has been
567711fa71b9SJerome Forissier              * completed or not. The cases to consider are the following:
567811fa71b9SJerome Forissier              * 1) The renegotiation is complete. In this case, no new record
567911fa71b9SJerome Forissier              *    has been read yet.
568011fa71b9SJerome Forissier              * 2) The renegotiation is incomplete because the client received
568111fa71b9SJerome Forissier              *    an application data record while awaiting the ServerHello.
568211fa71b9SJerome Forissier              * 3) The renegotiation is incomplete because the client received
568311fa71b9SJerome Forissier              *    a non-handshake, non-application data message while awaiting
568411fa71b9SJerome Forissier              *    the ServerHello.
568511fa71b9SJerome Forissier              * In each of these case, looping will be the proper action:
568611fa71b9SJerome Forissier              * - For 1), the next iteration will read a new record and check
568711fa71b9SJerome Forissier              *   if it's application data.
568811fa71b9SJerome Forissier              * - For 2), the loop condition isn't satisfied as application data
568911fa71b9SJerome Forissier              *   is present, hence continue is the same as break
569011fa71b9SJerome Forissier              * - For 3), the loop condition is satisfied and read_record
569111fa71b9SJerome Forissier              *   will re-deliver the message that was held back by the client
569211fa71b9SJerome Forissier              *   when expecting the ServerHello.
569311fa71b9SJerome Forissier              */
569411fa71b9SJerome Forissier             continue;
569511fa71b9SJerome Forissier         }
569611fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_RENEGOTIATION)
569711fa71b9SJerome Forissier         else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING )
569811fa71b9SJerome Forissier         {
569911fa71b9SJerome Forissier             if( ssl->conf->renego_max_records >= 0 )
570011fa71b9SJerome Forissier             {
570111fa71b9SJerome Forissier                 if( ++ssl->renego_records_seen > ssl->conf->renego_max_records )
570211fa71b9SJerome Forissier                 {
570311fa71b9SJerome Forissier                     MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation requested, "
570411fa71b9SJerome Forissier                                         "but not honored by client" ) );
570511fa71b9SJerome Forissier                     return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
570611fa71b9SJerome Forissier                 }
570711fa71b9SJerome Forissier             }
570811fa71b9SJerome Forissier         }
570911fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_RENEGOTIATION */
571011fa71b9SJerome Forissier 
571111fa71b9SJerome Forissier         /* Fatal and closure alerts handled by mbedtls_ssl_read_record() */
571211fa71b9SJerome Forissier         if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT )
571311fa71b9SJerome Forissier         {
571411fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 2, ( "ignoring non-fatal non-closure alert" ) );
571511fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_WANT_READ );
571611fa71b9SJerome Forissier         }
571711fa71b9SJerome Forissier 
571811fa71b9SJerome Forissier         if( ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA )
571911fa71b9SJerome Forissier         {
572011fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad application data message" ) );
572111fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
572211fa71b9SJerome Forissier         }
572311fa71b9SJerome Forissier 
572411fa71b9SJerome Forissier         ssl->in_offt = ssl->in_msg;
572511fa71b9SJerome Forissier 
572611fa71b9SJerome Forissier         /* We're going to return something now, cancel timer,
572711fa71b9SJerome Forissier          * except if handshake (renegotiation) is in progress */
572811fa71b9SJerome Forissier         if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
572911fa71b9SJerome Forissier             mbedtls_ssl_set_timer( ssl, 0 );
573011fa71b9SJerome Forissier 
573111fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
573211fa71b9SJerome Forissier         /* If we requested renego but received AppData, resend HelloRequest.
573311fa71b9SJerome Forissier          * Do it now, after setting in_offt, to avoid taking this branch
573411fa71b9SJerome Forissier          * again if ssl_write_hello_request() returns WANT_WRITE */
573511fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION)
573611fa71b9SJerome Forissier         if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
573711fa71b9SJerome Forissier             ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING )
573811fa71b9SJerome Forissier         {
573911fa71b9SJerome Forissier             if( ( ret = mbedtls_ssl_resend_hello_request( ssl ) ) != 0 )
574011fa71b9SJerome Forissier             {
574111fa71b9SJerome Forissier                 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend_hello_request",
574211fa71b9SJerome Forissier                                        ret );
574311fa71b9SJerome Forissier                 return( ret );
574411fa71b9SJerome Forissier             }
574511fa71b9SJerome Forissier         }
574611fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */
574711fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
574811fa71b9SJerome Forissier     }
574911fa71b9SJerome Forissier 
575011fa71b9SJerome Forissier     n = ( len < ssl->in_msglen )
575111fa71b9SJerome Forissier         ? len : ssl->in_msglen;
575211fa71b9SJerome Forissier 
575311fa71b9SJerome Forissier     memcpy( buf, ssl->in_offt, n );
575411fa71b9SJerome Forissier     ssl->in_msglen -= n;
575511fa71b9SJerome Forissier 
5756*7901324dSJerome Forissier     /* Zeroising the plaintext buffer to erase unused application data
5757*7901324dSJerome Forissier        from the memory. */
5758*7901324dSJerome Forissier     mbedtls_platform_zeroize( ssl->in_offt, n );
5759*7901324dSJerome Forissier 
576011fa71b9SJerome Forissier     if( ssl->in_msglen == 0 )
576111fa71b9SJerome Forissier     {
576211fa71b9SJerome Forissier         /* all bytes consumed */
576311fa71b9SJerome Forissier         ssl->in_offt = NULL;
576411fa71b9SJerome Forissier         ssl->keep_current_message = 0;
576511fa71b9SJerome Forissier     }
576611fa71b9SJerome Forissier     else
576711fa71b9SJerome Forissier     {
576811fa71b9SJerome Forissier         /* more data available */
576911fa71b9SJerome Forissier         ssl->in_offt += n;
577011fa71b9SJerome Forissier     }
577111fa71b9SJerome Forissier 
577211fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read" ) );
577311fa71b9SJerome Forissier 
577411fa71b9SJerome Forissier     return( (int) n );
577511fa71b9SJerome Forissier }
577611fa71b9SJerome Forissier 
577711fa71b9SJerome Forissier /*
577811fa71b9SJerome Forissier  * Send application data to be encrypted by the SSL layer, taking care of max
577911fa71b9SJerome Forissier  * fragment length and buffer size.
578011fa71b9SJerome Forissier  *
578111fa71b9SJerome Forissier  * According to RFC 5246 Section 6.2.1:
578211fa71b9SJerome Forissier  *
578311fa71b9SJerome Forissier  *      Zero-length fragments of Application data MAY be sent as they are
578411fa71b9SJerome Forissier  *      potentially useful as a traffic analysis countermeasure.
578511fa71b9SJerome Forissier  *
578611fa71b9SJerome Forissier  * Therefore, it is possible that the input message length is 0 and the
578711fa71b9SJerome Forissier  * corresponding return code is 0 on success.
578811fa71b9SJerome Forissier  */
578911fa71b9SJerome Forissier static int ssl_write_real( mbedtls_ssl_context *ssl,
579011fa71b9SJerome Forissier                            const unsigned char *buf, size_t len )
579111fa71b9SJerome Forissier {
579211fa71b9SJerome Forissier     int ret = mbedtls_ssl_get_max_out_record_payload( ssl );
579311fa71b9SJerome Forissier     const size_t max_len = (size_t) ret;
579411fa71b9SJerome Forissier 
579511fa71b9SJerome Forissier     if( ret < 0 )
579611fa71b9SJerome Forissier     {
579711fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_get_max_out_record_payload", ret );
579811fa71b9SJerome Forissier         return( ret );
579911fa71b9SJerome Forissier     }
580011fa71b9SJerome Forissier 
580111fa71b9SJerome Forissier     if( len > max_len )
580211fa71b9SJerome Forissier     {
580311fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
580411fa71b9SJerome Forissier         if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
580511fa71b9SJerome Forissier         {
580611fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_MSG( 1, ( "fragment larger than the (negotiated) "
5807*7901324dSJerome Forissier                                 "maximum fragment length: %" MBEDTLS_PRINTF_SIZET
5808*7901324dSJerome Forissier                                 " > %" MBEDTLS_PRINTF_SIZET,
580911fa71b9SJerome Forissier                                 len, max_len ) );
581011fa71b9SJerome Forissier             return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
581111fa71b9SJerome Forissier         }
581211fa71b9SJerome Forissier         else
581311fa71b9SJerome Forissier #endif
581411fa71b9SJerome Forissier             len = max_len;
581511fa71b9SJerome Forissier     }
581611fa71b9SJerome Forissier 
581711fa71b9SJerome Forissier     if( ssl->out_left != 0 )
581811fa71b9SJerome Forissier     {
581911fa71b9SJerome Forissier         /*
582011fa71b9SJerome Forissier          * The user has previously tried to send the data and
582111fa71b9SJerome Forissier          * MBEDTLS_ERR_SSL_WANT_WRITE or the message was only partially
582211fa71b9SJerome Forissier          * written. In this case, we expect the high-level write function
582311fa71b9SJerome Forissier          * (e.g. mbedtls_ssl_write()) to be called with the same parameters
582411fa71b9SJerome Forissier          */
582511fa71b9SJerome Forissier         if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
582611fa71b9SJerome Forissier         {
582711fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret );
582811fa71b9SJerome Forissier             return( ret );
582911fa71b9SJerome Forissier         }
583011fa71b9SJerome Forissier     }
583111fa71b9SJerome Forissier     else
583211fa71b9SJerome Forissier     {
583311fa71b9SJerome Forissier         /*
583411fa71b9SJerome Forissier          * The user is trying to send a message the first time, so we need to
583511fa71b9SJerome Forissier          * copy the data into the internal buffers and setup the data structure
583611fa71b9SJerome Forissier          * to keep track of partial writes
583711fa71b9SJerome Forissier          */
583811fa71b9SJerome Forissier         ssl->out_msglen  = len;
583911fa71b9SJerome Forissier         ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA;
584011fa71b9SJerome Forissier         memcpy( ssl->out_msg, buf, len );
584111fa71b9SJerome Forissier 
584211fa71b9SJerome Forissier         if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 )
584311fa71b9SJerome Forissier         {
584411fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
584511fa71b9SJerome Forissier             return( ret );
584611fa71b9SJerome Forissier         }
584711fa71b9SJerome Forissier     }
584811fa71b9SJerome Forissier 
584911fa71b9SJerome Forissier     return( (int) len );
585011fa71b9SJerome Forissier }
585111fa71b9SJerome Forissier 
585211fa71b9SJerome Forissier /*
585311fa71b9SJerome Forissier  * Write application data, doing 1/n-1 splitting if necessary.
585411fa71b9SJerome Forissier  *
585511fa71b9SJerome Forissier  * With non-blocking I/O, ssl_write_real() may return WANT_WRITE,
585611fa71b9SJerome Forissier  * then the caller will call us again with the same arguments, so
585711fa71b9SJerome Forissier  * remember whether we already did the split or not.
585811fa71b9SJerome Forissier  */
585911fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING)
586011fa71b9SJerome Forissier static int ssl_write_split( mbedtls_ssl_context *ssl,
586111fa71b9SJerome Forissier                             const unsigned char *buf, size_t len )
586211fa71b9SJerome Forissier {
586311fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
586411fa71b9SJerome Forissier 
586511fa71b9SJerome Forissier     if( ssl->conf->cbc_record_splitting ==
586611fa71b9SJerome Forissier             MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED ||
586711fa71b9SJerome Forissier         len <= 1 ||
586811fa71b9SJerome Forissier         ssl->minor_ver > MBEDTLS_SSL_MINOR_VERSION_1 ||
586911fa71b9SJerome Forissier         mbedtls_cipher_get_cipher_mode( &ssl->transform_out->cipher_ctx_enc )
587011fa71b9SJerome Forissier                                 != MBEDTLS_MODE_CBC )
587111fa71b9SJerome Forissier     {
587211fa71b9SJerome Forissier         return( ssl_write_real( ssl, buf, len ) );
587311fa71b9SJerome Forissier     }
587411fa71b9SJerome Forissier 
587511fa71b9SJerome Forissier     if( ssl->split_done == 0 )
587611fa71b9SJerome Forissier     {
587711fa71b9SJerome Forissier         if( ( ret = ssl_write_real( ssl, buf, 1 ) ) <= 0 )
587811fa71b9SJerome Forissier             return( ret );
587911fa71b9SJerome Forissier         ssl->split_done = 1;
588011fa71b9SJerome Forissier     }
588111fa71b9SJerome Forissier 
588211fa71b9SJerome Forissier     if( ( ret = ssl_write_real( ssl, buf + 1, len - 1 ) ) <= 0 )
588311fa71b9SJerome Forissier         return( ret );
588411fa71b9SJerome Forissier     ssl->split_done = 0;
588511fa71b9SJerome Forissier 
588611fa71b9SJerome Forissier     return( ret + 1 );
588711fa71b9SJerome Forissier }
588811fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */
588911fa71b9SJerome Forissier 
589011fa71b9SJerome Forissier /*
589111fa71b9SJerome Forissier  * Write application data (public-facing wrapper)
589211fa71b9SJerome Forissier  */
589311fa71b9SJerome Forissier int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len )
589411fa71b9SJerome Forissier {
589511fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
589611fa71b9SJerome Forissier 
589711fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write" ) );
589811fa71b9SJerome Forissier 
589911fa71b9SJerome Forissier     if( ssl == NULL || ssl->conf == NULL )
590011fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
590111fa71b9SJerome Forissier 
590211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_RENEGOTIATION)
590311fa71b9SJerome Forissier     if( ( ret = ssl_check_ctr_renegotiate( ssl ) ) != 0 )
590411fa71b9SJerome Forissier     {
590511fa71b9SJerome Forissier         MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret );
590611fa71b9SJerome Forissier         return( ret );
590711fa71b9SJerome Forissier     }
590811fa71b9SJerome Forissier #endif
590911fa71b9SJerome Forissier 
591011fa71b9SJerome Forissier     if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
591111fa71b9SJerome Forissier     {
591211fa71b9SJerome Forissier         if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 )
591311fa71b9SJerome Forissier         {
591411fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret );
591511fa71b9SJerome Forissier             return( ret );
591611fa71b9SJerome Forissier         }
591711fa71b9SJerome Forissier     }
591811fa71b9SJerome Forissier 
591911fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING)
592011fa71b9SJerome Forissier     ret = ssl_write_split( ssl, buf, len );
592111fa71b9SJerome Forissier #else
592211fa71b9SJerome Forissier     ret = ssl_write_real( ssl, buf, len );
592311fa71b9SJerome Forissier #endif
592411fa71b9SJerome Forissier 
592511fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write" ) );
592611fa71b9SJerome Forissier 
592711fa71b9SJerome Forissier     return( ret );
592811fa71b9SJerome Forissier }
592911fa71b9SJerome Forissier 
593011fa71b9SJerome Forissier /*
593111fa71b9SJerome Forissier  * Notify the peer that the connection is being closed
593211fa71b9SJerome Forissier  */
593311fa71b9SJerome Forissier int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl )
593411fa71b9SJerome Forissier {
593511fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
593611fa71b9SJerome Forissier 
593711fa71b9SJerome Forissier     if( ssl == NULL || ssl->conf == NULL )
593811fa71b9SJerome Forissier         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
593911fa71b9SJerome Forissier 
594011fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write close notify" ) );
594111fa71b9SJerome Forissier 
594211fa71b9SJerome Forissier     if( ssl->out_left != 0 )
594311fa71b9SJerome Forissier         return( mbedtls_ssl_flush_output( ssl ) );
594411fa71b9SJerome Forissier 
594511fa71b9SJerome Forissier     if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
594611fa71b9SJerome Forissier     {
594711fa71b9SJerome Forissier         if( ( ret = mbedtls_ssl_send_alert_message( ssl,
594811fa71b9SJerome Forissier                         MBEDTLS_SSL_ALERT_LEVEL_WARNING,
594911fa71b9SJerome Forissier                         MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY ) ) != 0 )
595011fa71b9SJerome Forissier         {
595111fa71b9SJerome Forissier             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_send_alert_message", ret );
595211fa71b9SJerome Forissier             return( ret );
595311fa71b9SJerome Forissier         }
595411fa71b9SJerome Forissier     }
595511fa71b9SJerome Forissier 
595611fa71b9SJerome Forissier     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write close notify" ) );
595711fa71b9SJerome Forissier 
595811fa71b9SJerome Forissier     return( 0 );
595911fa71b9SJerome Forissier }
596011fa71b9SJerome Forissier 
596111fa71b9SJerome Forissier void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform )
596211fa71b9SJerome Forissier {
596311fa71b9SJerome Forissier     if( transform == NULL )
596411fa71b9SJerome Forissier         return;
596511fa71b9SJerome Forissier 
596611fa71b9SJerome Forissier #if defined(MBEDTLS_ZLIB_SUPPORT)
596711fa71b9SJerome Forissier     deflateEnd( &transform->ctx_deflate );
596811fa71b9SJerome Forissier     inflateEnd( &transform->ctx_inflate );
596911fa71b9SJerome Forissier #endif
597011fa71b9SJerome Forissier 
597111fa71b9SJerome Forissier     mbedtls_cipher_free( &transform->cipher_ctx_enc );
597211fa71b9SJerome Forissier     mbedtls_cipher_free( &transform->cipher_ctx_dec );
597311fa71b9SJerome Forissier 
597411fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
597511fa71b9SJerome Forissier     mbedtls_md_free( &transform->md_ctx_enc );
597611fa71b9SJerome Forissier     mbedtls_md_free( &transform->md_ctx_dec );
597711fa71b9SJerome Forissier #endif
597811fa71b9SJerome Forissier 
597911fa71b9SJerome Forissier     mbedtls_platform_zeroize( transform, sizeof( mbedtls_ssl_transform ) );
598011fa71b9SJerome Forissier }
598111fa71b9SJerome Forissier 
598211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
598311fa71b9SJerome Forissier 
598411fa71b9SJerome Forissier void mbedtls_ssl_buffering_free( mbedtls_ssl_context *ssl )
598511fa71b9SJerome Forissier {
598611fa71b9SJerome Forissier     unsigned offset;
598711fa71b9SJerome Forissier     mbedtls_ssl_handshake_params * const hs = ssl->handshake;
598811fa71b9SJerome Forissier 
598911fa71b9SJerome Forissier     if( hs == NULL )
599011fa71b9SJerome Forissier         return;
599111fa71b9SJerome Forissier 
599211fa71b9SJerome Forissier     ssl_free_buffered_record( ssl );
599311fa71b9SJerome Forissier 
599411fa71b9SJerome Forissier     for( offset = 0; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++ )
599511fa71b9SJerome Forissier         ssl_buffering_free_slot( ssl, offset );
599611fa71b9SJerome Forissier }
599711fa71b9SJerome Forissier 
599811fa71b9SJerome Forissier static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl,
599911fa71b9SJerome Forissier                                      uint8_t slot )
600011fa71b9SJerome Forissier {
600111fa71b9SJerome Forissier     mbedtls_ssl_handshake_params * const hs = ssl->handshake;
600211fa71b9SJerome Forissier     mbedtls_ssl_hs_buffer * const hs_buf = &hs->buffering.hs[slot];
600311fa71b9SJerome Forissier 
600411fa71b9SJerome Forissier     if( slot >= MBEDTLS_SSL_MAX_BUFFERED_HS )
600511fa71b9SJerome Forissier         return;
600611fa71b9SJerome Forissier 
600711fa71b9SJerome Forissier     if( hs_buf->is_valid == 1 )
600811fa71b9SJerome Forissier     {
600911fa71b9SJerome Forissier         hs->buffering.total_bytes_buffered -= hs_buf->data_len;
601011fa71b9SJerome Forissier         mbedtls_platform_zeroize( hs_buf->data, hs_buf->data_len );
601111fa71b9SJerome Forissier         mbedtls_free( hs_buf->data );
601211fa71b9SJerome Forissier         memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) );
601311fa71b9SJerome Forissier     }
601411fa71b9SJerome Forissier }
601511fa71b9SJerome Forissier 
601611fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_PROTO_DTLS */
601711fa71b9SJerome Forissier 
601811fa71b9SJerome Forissier /*
601911fa71b9SJerome Forissier  * Convert version numbers to/from wire format
602011fa71b9SJerome Forissier  * and, for DTLS, to/from TLS equivalent.
602111fa71b9SJerome Forissier  *
602211fa71b9SJerome Forissier  * For TLS this is the identity.
602311fa71b9SJerome Forissier  * For DTLS, use 1's complement (v -> 255 - v, and then map as follows:
602411fa71b9SJerome Forissier  * 1.0 <-> 3.2      (DTLS 1.0 is based on TLS 1.1)
602511fa71b9SJerome Forissier  * 1.x <-> 3.x+1    for x != 0 (DTLS 1.2 based on TLS 1.2)
602611fa71b9SJerome Forissier  */
602711fa71b9SJerome Forissier void mbedtls_ssl_write_version( int major, int minor, int transport,
602811fa71b9SJerome Forissier                         unsigned char ver[2] )
602911fa71b9SJerome Forissier {
603011fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
603111fa71b9SJerome Forissier     if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
603211fa71b9SJerome Forissier     {
603311fa71b9SJerome Forissier         if( minor == MBEDTLS_SSL_MINOR_VERSION_2 )
603411fa71b9SJerome Forissier             --minor; /* DTLS 1.0 stored as TLS 1.1 internally */
603511fa71b9SJerome Forissier 
603611fa71b9SJerome Forissier         ver[0] = (unsigned char)( 255 - ( major - 2 ) );
603711fa71b9SJerome Forissier         ver[1] = (unsigned char)( 255 - ( minor - 1 ) );
603811fa71b9SJerome Forissier     }
603911fa71b9SJerome Forissier     else
604011fa71b9SJerome Forissier #else
604111fa71b9SJerome Forissier     ((void) transport);
604211fa71b9SJerome Forissier #endif
604311fa71b9SJerome Forissier     {
604411fa71b9SJerome Forissier         ver[0] = (unsigned char) major;
604511fa71b9SJerome Forissier         ver[1] = (unsigned char) minor;
604611fa71b9SJerome Forissier     }
604711fa71b9SJerome Forissier }
604811fa71b9SJerome Forissier 
604911fa71b9SJerome Forissier void mbedtls_ssl_read_version( int *major, int *minor, int transport,
605011fa71b9SJerome Forissier                        const unsigned char ver[2] )
605111fa71b9SJerome Forissier {
605211fa71b9SJerome Forissier #if defined(MBEDTLS_SSL_PROTO_DTLS)
605311fa71b9SJerome Forissier     if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
605411fa71b9SJerome Forissier     {
605511fa71b9SJerome Forissier         *major = 255 - ver[0] + 2;
605611fa71b9SJerome Forissier         *minor = 255 - ver[1] + 1;
605711fa71b9SJerome Forissier 
605811fa71b9SJerome Forissier         if( *minor == MBEDTLS_SSL_MINOR_VERSION_1 )
605911fa71b9SJerome Forissier             ++*minor; /* DTLS 1.0 stored as TLS 1.1 internally */
606011fa71b9SJerome Forissier     }
606111fa71b9SJerome Forissier     else
606211fa71b9SJerome Forissier #else
606311fa71b9SJerome Forissier     ((void) transport);
606411fa71b9SJerome Forissier #endif
606511fa71b9SJerome Forissier     {
606611fa71b9SJerome Forissier         *major = ver[0];
606711fa71b9SJerome Forissier         *minor = ver[1];
606811fa71b9SJerome Forissier     }
606911fa71b9SJerome Forissier }
607011fa71b9SJerome Forissier 
607111fa71b9SJerome Forissier #endif /* MBEDTLS_SSL_TLS_C */
6072