LCOV - code coverage report
Current view: top level - tls - s2n_handshake_io.c (source / functions) Hit Total Coverage
Test: unit_test_coverage.info Lines: 549 557 98.6 %
Date: 2026-07-04 07:27:58 Functions: 27 29 93.1 %
Branches: 558 804 69.4 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
       3                 :            :  *
       4                 :            :  * Licensed under the Apache License, Version 2.0 (the "License").
       5                 :            :  * You may not use this file except in compliance with the License.
       6                 :            :  * A copy of the License is located at
       7                 :            :  *
       8                 :            :  *  http://aws.amazon.com/apache2.0
       9                 :            :  *
      10                 :            :  * or in the "license" file accompanying this file. This file is distributed
      11                 :            :  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
      12                 :            :  * express or implied. See the License for the specific language governing
      13                 :            :  * permissions and limitations under the License.
      14                 :            :  */
      15                 :            : 
      16                 :            : #include <errno.h>
      17                 :            : 
      18                 :            : #include "api/s2n.h"
      19                 :            : #include "crypto/s2n_fips.h"
      20                 :            : #include "error/s2n_errno.h"
      21                 :            : #include "stuffer/s2n_stuffer.h"
      22                 :            : #include "tls/s2n_alerts.h"
      23                 :            : #include "tls/s2n_async_pkey.h"
      24                 :            : #include "tls/s2n_cipher_suites.h"
      25                 :            : #include "tls/s2n_connection.h"
      26                 :            : #include "tls/s2n_kex.h"
      27                 :            : #include "tls/s2n_post_handshake.h"
      28                 :            : #include "tls/s2n_record.h"
      29                 :            : #include "tls/s2n_resume.h"
      30                 :            : #include "tls/s2n_tls.h"
      31                 :            : #include "tls/s2n_tls13.h"
      32                 :            : #include "tls/s2n_tls13_handshake.h"
      33                 :            : #include "tls/s2n_tls13_key_schedule.h"
      34                 :            : #include "utils/s2n_bitmap.h"
      35                 :            : #include "utils/s2n_events.h"
      36                 :            : #include "utils/s2n_random.h"
      37                 :            : #include "utils/s2n_safety.h"
      38                 :            : #ifndef _WIN32
      39                 :            :     #include "utils/s2n_socket.h"
      40                 :            : #endif
      41                 :            : 
      42                 :            : /* clang-format off */
      43                 :            : struct s2n_handshake_action {
      44                 :            :     uint8_t record_type;
      45                 :            :     uint8_t message_type;
      46                 :            :     char writer;                /* 'S' or 'C' for server or client, 'B' for both */
      47                 :            :     int (*handler[2]) (struct s2n_connection * conn);
      48                 :            : };
      49                 :            : 
      50                 :            : static int s2n_always_fail_send(struct s2n_connection *conn)
      51                 :          0 : {
      52                 :            :     /* This state should never be sending a handshake message. */
      53         [ #  # ]:          0 :     POSIX_BAIL(S2N_ERR_HANDSHAKE_UNREACHABLE);
      54                 :          0 : }
      55                 :            : 
      56                 :            : static int s2n_always_fail_recv(struct s2n_connection *conn)
      57                 :          0 : {
      58                 :            :     /* This state should never have an incoming handshake message. */
      59         [ #  # ]:          0 :     POSIX_BAIL(S2N_ERR_HANDSHAKE_UNREACHABLE);
      60                 :          0 : }
      61                 :            : 
      62                 :            : /* Client and Server handlers for each message type we support.
      63                 :            :  * See http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-7 for the list of handshake message types
      64                 :            :  */
      65                 :            : static struct s2n_handshake_action state_machine[] = {
      66                 :            :     /* message_type_t           = {Record type   Message type     Writer S2N_SERVER                S2N_CLIENT }  */
      67                 :            :     [CLIENT_HELLO]              = {TLS_HANDSHAKE, TLS_CLIENT_HELLO, 'C', {s2n_establish_session, s2n_client_hello_send}},
      68                 :            :     [SERVER_HELLO]              = {TLS_HANDSHAKE, TLS_SERVER_HELLO, 'S', {s2n_server_hello_send, s2n_server_hello_recv}},
      69                 :            :     [SERVER_NEW_SESSION_TICKET] = {TLS_HANDSHAKE, TLS_SERVER_NEW_SESSION_TICKET,'S', {s2n_server_nst_send, s2n_server_nst_recv}},
      70                 :            :     [SERVER_CERT]               = {TLS_HANDSHAKE, TLS_CERTIFICATE, 'S', {s2n_server_cert_send, s2n_server_cert_recv}},
      71                 :            :     [SERVER_CERT_STATUS]        = {TLS_HANDSHAKE, TLS_SERVER_CERT_STATUS, 'S', {s2n_server_status_send, s2n_server_status_recv}},
      72                 :            :     [SERVER_KEY]                = {TLS_HANDSHAKE, TLS_SERVER_KEY, 'S', {s2n_server_key_send, s2n_server_key_recv}},
      73                 :            :     [SERVER_CERT_REQ]           = {TLS_HANDSHAKE, TLS_CERT_REQ, 'S', {s2n_cert_req_send, s2n_cert_req_recv}},
      74                 :            :     [SERVER_HELLO_DONE]         = {TLS_HANDSHAKE, TLS_SERVER_HELLO_DONE, 'S', {s2n_server_done_send, s2n_server_done_recv}},
      75                 :            :     [CLIENT_CERT]               = {TLS_HANDSHAKE, TLS_CERTIFICATE, 'C', {s2n_client_cert_recv, s2n_client_cert_send}},
      76                 :            :     [CLIENT_KEY]                = {TLS_HANDSHAKE, TLS_CLIENT_KEY, 'C', {s2n_client_key_recv, s2n_client_key_send}},
      77                 :            :     [CLIENT_CERT_VERIFY]        = {TLS_HANDSHAKE, TLS_CERT_VERIFY, 'C', {s2n_client_cert_verify_recv, s2n_client_cert_verify_send}},
      78                 :            :     [CLIENT_CHANGE_CIPHER_SPEC] = {TLS_CHANGE_CIPHER_SPEC, 0, 'C', {s2n_client_ccs_recv, s2n_ccs_send}},
      79                 :            :     [CLIENT_NPN]                = {TLS_HANDSHAKE, TLS_NPN, 'C', {s2n_next_protocol_recv, s2n_next_protocol_send}},
      80                 :            :     [CLIENT_FINISHED]           = {TLS_HANDSHAKE, TLS_FINISHED, 'C', {s2n_client_finished_recv, s2n_client_finished_send}},
      81                 :            :     [SERVER_CHANGE_CIPHER_SPEC] = {TLS_CHANGE_CIPHER_SPEC, 0, 'S', {s2n_ccs_send, s2n_server_ccs_recv}},
      82                 :            :     [SERVER_FINISHED]           = {TLS_HANDSHAKE, TLS_FINISHED, 'S', {s2n_server_finished_send, s2n_server_finished_recv}},
      83                 :            :     [APPLICATION_DATA]          = {TLS_APPLICATION_DATA, 0, 'B', {s2n_always_fail_send, s2n_always_fail_recv}},
      84                 :            : };
      85                 :            : 
      86                 :            : /*
      87                 :            :  * Client and Server handlers for TLS1.3.
      88                 :            :  */
      89                 :            : static struct s2n_handshake_action tls13_state_machine[] = {
      90                 :            :     /* message_type_t           = {Record type, Message type, Writer, {Server handler, client handler} }  */
      91                 :            :     [CLIENT_HELLO]              = {TLS_HANDSHAKE, TLS_CLIENT_HELLO, 'C', {s2n_establish_session, s2n_client_hello_send}},
      92                 :            :     [SERVER_HELLO]              = {TLS_HANDSHAKE, TLS_SERVER_HELLO, 'S', {s2n_server_hello_send, s2n_server_hello_recv}},
      93                 :            :     [HELLO_RETRY_MSG]           = {TLS_HANDSHAKE, TLS_SERVER_HELLO, 'S', {s2n_server_hello_retry_send, s2n_server_hello_retry_recv}},
      94                 :            :     [ENCRYPTED_EXTENSIONS]      = {TLS_HANDSHAKE, TLS_ENCRYPTED_EXTENSIONS, 'S', {s2n_encrypted_extensions_send, s2n_encrypted_extensions_recv}},
      95                 :            :     [SERVER_CERT_REQ]           = {TLS_HANDSHAKE, TLS_CERT_REQ, 'S', {s2n_tls13_cert_req_send, s2n_tls13_cert_req_recv}},
      96                 :            :     [SERVER_CERT]               = {TLS_HANDSHAKE, TLS_CERTIFICATE, 'S', {s2n_server_cert_send, s2n_server_cert_recv}},
      97                 :            :     [SERVER_CERT_VERIFY]        = {TLS_HANDSHAKE, TLS_CERT_VERIFY, 'S', {s2n_tls13_cert_verify_send, s2n_tls13_cert_verify_recv}},
      98                 :            :     [SERVER_FINISHED]           = {TLS_HANDSHAKE, TLS_FINISHED, 'S', {s2n_tls13_server_finished_send, s2n_tls13_server_finished_recv}},
      99                 :            : 
     100                 :            :     [CLIENT_CERT]               = {TLS_HANDSHAKE, TLS_CERTIFICATE, 'C', {s2n_client_cert_recv, s2n_client_cert_send}},
     101                 :            :     [CLIENT_CERT_VERIFY]        = {TLS_HANDSHAKE, TLS_CERT_VERIFY, 'C', {s2n_tls13_cert_verify_recv, s2n_tls13_cert_verify_send}},
     102                 :            :     [CLIENT_FINISHED]           = {TLS_HANDSHAKE, TLS_FINISHED, 'C', {s2n_tls13_client_finished_recv, s2n_tls13_client_finished_send}},
     103                 :            :     [END_OF_EARLY_DATA]         = {TLS_HANDSHAKE, TLS_END_OF_EARLY_DATA, 'C', {s2n_end_of_early_data_recv, s2n_end_of_early_data_send}},
     104                 :            : 
     105                 :            :     /* Not used by TLS1.3, except to maintain middlebox compatibility */
     106                 :            :     [CLIENT_CHANGE_CIPHER_SPEC] = {TLS_CHANGE_CIPHER_SPEC, 0, 'C', {s2n_basic_ccs_recv, s2n_ccs_send}},
     107                 :            :     [SERVER_CHANGE_CIPHER_SPEC] = {TLS_CHANGE_CIPHER_SPEC, 0, 'S', {s2n_ccs_send, s2n_basic_ccs_recv}},
     108                 :            : 
     109                 :            :     [APPLICATION_DATA]          = {TLS_APPLICATION_DATA, 0, 'B', {s2n_always_fail_send, s2n_always_fail_recv}},
     110                 :            : };
     111                 :            : 
     112                 :            : #define MESSAGE_NAME_ENTRY(msg) [msg] = #msg
     113                 :            : 
     114                 :            : static const char *message_names[] = {
     115                 :            :     MESSAGE_NAME_ENTRY(CLIENT_HELLO),
     116                 :            :     MESSAGE_NAME_ENTRY(SERVER_HELLO),
     117                 :            :     MESSAGE_NAME_ENTRY(ENCRYPTED_EXTENSIONS),
     118                 :            :     MESSAGE_NAME_ENTRY(SERVER_NEW_SESSION_TICKET),
     119                 :            :     MESSAGE_NAME_ENTRY(SERVER_CERT),
     120                 :            :     MESSAGE_NAME_ENTRY(SERVER_CERT_STATUS),
     121                 :            :     MESSAGE_NAME_ENTRY(SERVER_CERT_VERIFY),
     122                 :            :     MESSAGE_NAME_ENTRY(SERVER_KEY),
     123                 :            :     MESSAGE_NAME_ENTRY(SERVER_CERT_REQ),
     124                 :            :     MESSAGE_NAME_ENTRY(SERVER_HELLO_DONE),
     125                 :            :     MESSAGE_NAME_ENTRY(CLIENT_CERT),
     126                 :            :     MESSAGE_NAME_ENTRY(CLIENT_KEY),
     127                 :            :     MESSAGE_NAME_ENTRY(CLIENT_CERT_VERIFY),
     128                 :            :     MESSAGE_NAME_ENTRY(CLIENT_CHANGE_CIPHER_SPEC),
     129                 :            :     MESSAGE_NAME_ENTRY(CLIENT_FINISHED),
     130                 :            :     MESSAGE_NAME_ENTRY(SERVER_CHANGE_CIPHER_SPEC),
     131                 :            :     MESSAGE_NAME_ENTRY(SERVER_FINISHED),
     132                 :            :     MESSAGE_NAME_ENTRY(HELLO_RETRY_MSG),
     133                 :            :     MESSAGE_NAME_ENTRY(END_OF_EARLY_DATA),
     134                 :            :     MESSAGE_NAME_ENTRY(APPLICATION_DATA),
     135                 :            :     MESSAGE_NAME_ENTRY(CLIENT_NPN),
     136                 :            : };
     137                 :            : 
     138                 :            : /* We support different ordering of TLS Handshake messages, depending on what is being negotiated. There's also a dummy "INITIAL" handshake
     139                 :            :  * that everything starts out as until we know better.
     140                 :            :  */
     141                 :            : 
     142                 :            : static message_type_t handshakes[S2N_HANDSHAKES_COUNT][S2N_MAX_HANDSHAKE_LENGTH] = {
     143                 :            :     [INITIAL] = {
     144                 :            :             CLIENT_HELLO,
     145                 :            :             SERVER_HELLO
     146                 :            :     },
     147                 :            : 
     148                 :            :     [NEGOTIATED] = {
     149                 :            :             CLIENT_HELLO,
     150                 :            :             SERVER_HELLO, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     151                 :            :             CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED,
     152                 :            :             APPLICATION_DATA
     153                 :            :     },
     154                 :            : 
     155                 :            :     [NEGOTIATED | WITH_NPN ] = {
     156                 :            :             CLIENT_HELLO,
     157                 :            :             SERVER_HELLO, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     158                 :            :             CLIENT_CHANGE_CIPHER_SPEC, CLIENT_NPN, CLIENT_FINISHED,
     159                 :            :             APPLICATION_DATA
     160                 :            :     },
     161                 :            : 
     162                 :            :     [NEGOTIATED | WITH_SESSION_TICKET ] = {
     163                 :            :             CLIENT_HELLO,
     164                 :            :             SERVER_HELLO, SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     165                 :            :             CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED,
     166                 :            :             APPLICATION_DATA},
     167                 :            : 
     168                 :            :     [NEGOTIATED | WITH_SESSION_TICKET | WITH_NPN ] = {
     169                 :            :             CLIENT_HELLO,
     170                 :            :             SERVER_HELLO, SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     171                 :            :             CLIENT_CHANGE_CIPHER_SPEC, CLIENT_NPN, CLIENT_FINISHED,
     172                 :            :             APPLICATION_DATA},
     173                 :            : 
     174                 :            :     [NEGOTIATED | FULL_HANDSHAKE ] = {
     175                 :            :             CLIENT_HELLO,
     176                 :            :             SERVER_HELLO, SERVER_CERT, SERVER_HELLO_DONE,
     177                 :            :             CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED,
     178                 :            :             SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     179                 :            :             APPLICATION_DATA
     180                 :            :     },
     181                 :            : 
     182                 :            :     [NEGOTIATED | FULL_HANDSHAKE | WITH_NPN ] = {
     183                 :            :             CLIENT_HELLO,
     184                 :            :             SERVER_HELLO, SERVER_CERT, SERVER_HELLO_DONE,
     185                 :            :             CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_NPN, CLIENT_FINISHED,
     186                 :            :             SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     187                 :            :             APPLICATION_DATA
     188                 :            :     },
     189                 :            : 
     190                 :            :     [NEGOTIATED | FULL_HANDSHAKE | WITH_SESSION_TICKET ] = {
     191                 :            :             CLIENT_HELLO,
     192                 :            :             SERVER_HELLO, SERVER_CERT, SERVER_HELLO_DONE,
     193                 :            :             CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED,
     194                 :            :             SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     195                 :            :             APPLICATION_DATA
     196                 :            :     },
     197                 :            : 
     198                 :            :     [NEGOTIATED | FULL_HANDSHAKE | WITH_SESSION_TICKET | WITH_NPN ] = {
     199                 :            :             CLIENT_HELLO,
     200                 :            :             SERVER_HELLO, SERVER_CERT, SERVER_HELLO_DONE,
     201                 :            :             CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_NPN, CLIENT_FINISHED,
     202                 :            :             SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     203                 :            :             APPLICATION_DATA
     204                 :            :     },
     205                 :            : 
     206                 :            :     [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY ] = {
     207                 :            :             CLIENT_HELLO,
     208                 :            :             SERVER_HELLO, SERVER_CERT, SERVER_KEY, SERVER_HELLO_DONE,
     209                 :            :             CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED,
     210                 :            :             SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     211                 :            :             APPLICATION_DATA
     212                 :            :     },
     213                 :            : 
     214                 :            :     [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | WITH_NPN ] = {
     215                 :            :             CLIENT_HELLO,
     216                 :            :             SERVER_HELLO, SERVER_CERT, SERVER_KEY, SERVER_HELLO_DONE,
     217                 :            :             CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_NPN, CLIENT_FINISHED,
     218                 :            :             SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     219                 :            :             APPLICATION_DATA
     220                 :            :     },
     221                 :            : 
     222                 :            :     [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | WITH_SESSION_TICKET ] = {
     223                 :            :             CLIENT_HELLO,
     224                 :            :             SERVER_HELLO, SERVER_CERT, SERVER_KEY, SERVER_HELLO_DONE,
     225                 :            :             CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED,
     226                 :            :             SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     227                 :            :             APPLICATION_DATA
     228                 :            :     },
     229                 :            : 
     230                 :            :     [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | WITH_SESSION_TICKET | WITH_NPN ] = {
     231                 :            :             CLIENT_HELLO,
     232                 :            :             SERVER_HELLO, SERVER_CERT, SERVER_KEY, SERVER_HELLO_DONE,
     233                 :            :             CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_NPN, CLIENT_FINISHED,
     234                 :            :             SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     235                 :            :             APPLICATION_DATA
     236                 :            :     },
     237                 :            : 
     238                 :            :     [NEGOTIATED | FULL_HANDSHAKE | OCSP_STATUS ] ={
     239                 :            :             CLIENT_HELLO,
     240                 :            :             SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_HELLO_DONE,
     241                 :            :             CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED,
     242                 :            :             SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     243                 :            :             APPLICATION_DATA
     244                 :            :     },
     245                 :            : 
     246                 :            :     [NEGOTIATED | FULL_HANDSHAKE | OCSP_STATUS | WITH_NPN ] ={
     247                 :            :             CLIENT_HELLO,
     248                 :            :             SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_HELLO_DONE,
     249                 :            :             CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_NPN, CLIENT_FINISHED,
     250                 :            :             SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     251                 :            :             APPLICATION_DATA
     252                 :            :     },
     253                 :            : 
     254                 :            :     [NEGOTIATED | FULL_HANDSHAKE | OCSP_STATUS | WITH_SESSION_TICKET ] = {
     255                 :            :             CLIENT_HELLO,
     256                 :            :             SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_HELLO_DONE,
     257                 :            :             CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED,
     258                 :            :             SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     259                 :            :             APPLICATION_DATA
     260                 :            :     },
     261                 :            : 
     262                 :            :     [NEGOTIATED | FULL_HANDSHAKE | OCSP_STATUS | WITH_SESSION_TICKET | WITH_NPN ] = {
     263                 :            :             CLIENT_HELLO,
     264                 :            :             SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_HELLO_DONE,
     265                 :            :             CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_NPN, CLIENT_FINISHED,
     266                 :            :             SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     267                 :            :             APPLICATION_DATA
     268                 :            :     },
     269                 :            : 
     270                 :            :     [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | OCSP_STATUS ] = {
     271                 :            :             CLIENT_HELLO,
     272                 :            :             SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_KEY, SERVER_HELLO_DONE,
     273                 :            :             CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED,
     274                 :            :             SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     275                 :            :             APPLICATION_DATA
     276                 :            :     },
     277                 :            : 
     278                 :            :     [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | OCSP_STATUS | WITH_NPN ] = {
     279                 :            :             CLIENT_HELLO,
     280                 :            :             SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_KEY, SERVER_HELLO_DONE,
     281                 :            :             CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_NPN, CLIENT_FINISHED,
     282                 :            :             SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     283                 :            :             APPLICATION_DATA
     284                 :            :     },
     285                 :            : 
     286                 :            :     [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | OCSP_STATUS  | WITH_SESSION_TICKET ] ={
     287                 :            :             CLIENT_HELLO,
     288                 :            :             SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_KEY, SERVER_HELLO_DONE,
     289                 :            :             CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED,
     290                 :            :             SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     291                 :            :             APPLICATION_DATA
     292                 :            :     },
     293                 :            : 
     294                 :            :     [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | OCSP_STATUS  | WITH_SESSION_TICKET | WITH_NPN ] ={
     295                 :            :             CLIENT_HELLO,
     296                 :            :             SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_KEY, SERVER_HELLO_DONE,
     297                 :            :             CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_NPN, CLIENT_FINISHED,
     298                 :            :             SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     299                 :            :             APPLICATION_DATA
     300                 :            :     },
     301                 :            : 
     302                 :            :     [NEGOTIATED | FULL_HANDSHAKE | CLIENT_AUTH] = {
     303                 :            :             CLIENT_HELLO,
     304                 :            :             SERVER_HELLO, SERVER_CERT, SERVER_CERT_REQ, SERVER_HELLO_DONE,
     305                 :            :             CLIENT_CERT, CLIENT_KEY, CLIENT_CERT_VERIFY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED,
     306                 :            :             SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     307                 :            :             APPLICATION_DATA
     308                 :            :     },
     309                 :            : 
     310                 :            :     [NEGOTIATED | FULL_HANDSHAKE | CLIENT_AUTH| WITH_NPN ] = {
     311                 :            :             CLIENT_HELLO,
     312                 :            :             SERVER_HELLO, SERVER_CERT, SERVER_CERT_REQ, SERVER_HELLO_DONE,
     313                 :            :             CLIENT_CERT, CLIENT_KEY, CLIENT_CERT_VERIFY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_NPN, CLIENT_FINISHED,
     314                 :            :             SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     315                 :            :             APPLICATION_DATA
     316                 :            :     },
     317                 :            : 
     318                 :            :     [NEGOTIATED | FULL_HANDSHAKE | CLIENT_AUTH | NO_CLIENT_CERT ] = {
     319                 :            :             CLIENT_HELLO,
     320                 :            :             SERVER_HELLO, SERVER_CERT, SERVER_CERT_REQ, SERVER_HELLO_DONE,
     321                 :            :             CLIENT_CERT, CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED,
     322                 :            :             SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     323                 :            :             APPLICATION_DATA
     324                 :            :     },
     325                 :            : 
     326                 :            :     [NEGOTIATED | FULL_HANDSHAKE | CLIENT_AUTH | NO_CLIENT_CERT | WITH_NPN ] = {
     327                 :            :             CLIENT_HELLO,
     328                 :            :             SERVER_HELLO, SERVER_CERT, SERVER_CERT_REQ, SERVER_HELLO_DONE,
     329                 :            :             CLIENT_CERT, CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_NPN, CLIENT_FINISHED,
     330                 :            :             SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     331                 :            :             APPLICATION_DATA
     332                 :            :     },
     333                 :            : 
     334                 :            :     [NEGOTIATED | FULL_HANDSHAKE | CLIENT_AUTH | WITH_SESSION_TICKET] = {
     335                 :            :             CLIENT_HELLO,
     336                 :            :             SERVER_HELLO, SERVER_CERT, SERVER_CERT_REQ, SERVER_HELLO_DONE,
     337                 :            :             CLIENT_CERT, CLIENT_KEY, CLIENT_CERT_VERIFY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED,
     338                 :            :             SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     339                 :            :             APPLICATION_DATA
     340                 :            :     },
     341                 :            : 
     342                 :            :     [NEGOTIATED | FULL_HANDSHAKE | CLIENT_AUTH | WITH_SESSION_TICKET | WITH_NPN ] = {
     343                 :            :             CLIENT_HELLO,
     344                 :            :             SERVER_HELLO, SERVER_CERT, SERVER_CERT_REQ, SERVER_HELLO_DONE,
     345                 :            :             CLIENT_CERT, CLIENT_KEY, CLIENT_CERT_VERIFY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_NPN, CLIENT_FINISHED,
     346                 :            :             SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     347                 :            :             APPLICATION_DATA
     348                 :            :     },
     349                 :            : 
     350                 :            :     [NEGOTIATED | FULL_HANDSHAKE | CLIENT_AUTH | NO_CLIENT_CERT | WITH_SESSION_TICKET ] = {
     351                 :            :             CLIENT_HELLO,
     352                 :            :             SERVER_HELLO, SERVER_CERT, SERVER_CERT_REQ, SERVER_HELLO_DONE,
     353                 :            :             CLIENT_CERT, CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED,
     354                 :            :             SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     355                 :            :             APPLICATION_DATA
     356                 :            :     },
     357                 :            : 
     358                 :            :     [NEGOTIATED | FULL_HANDSHAKE | CLIENT_AUTH | NO_CLIENT_CERT | WITH_SESSION_TICKET | WITH_NPN ] = {
     359                 :            :             CLIENT_HELLO,
     360                 :            :             SERVER_HELLO, SERVER_CERT, SERVER_CERT_REQ, SERVER_HELLO_DONE,
     361                 :            :             CLIENT_CERT, CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_NPN, CLIENT_FINISHED,
     362                 :            :             SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     363                 :            :             APPLICATION_DATA
     364                 :            :     },
     365                 :            : 
     366                 :            :     [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | CLIENT_AUTH] = {
     367                 :            :            CLIENT_HELLO,
     368                 :            :            SERVER_HELLO, SERVER_CERT, SERVER_KEY, SERVER_CERT_REQ, SERVER_HELLO_DONE,
     369                 :            :            CLIENT_CERT, CLIENT_KEY, CLIENT_CERT_VERIFY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED,
     370                 :            :            SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     371                 :            :            APPLICATION_DATA
     372                 :            :     },
     373                 :            : 
     374                 :            :     [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | CLIENT_AUTH | WITH_NPN ] = {
     375                 :            :            CLIENT_HELLO,
     376                 :            :            SERVER_HELLO, SERVER_CERT, SERVER_KEY, SERVER_CERT_REQ, SERVER_HELLO_DONE,
     377                 :            :            CLIENT_CERT, CLIENT_KEY, CLIENT_CERT_VERIFY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_NPN, CLIENT_FINISHED,
     378                 :            :            SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     379                 :            :            APPLICATION_DATA
     380                 :            :     },
     381                 :            : 
     382                 :            :     [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | CLIENT_AUTH | NO_CLIENT_CERT ] = {
     383                 :            :            CLIENT_HELLO,
     384                 :            :            SERVER_HELLO, SERVER_CERT, SERVER_KEY, SERVER_CERT_REQ, SERVER_HELLO_DONE,
     385                 :            :            CLIENT_CERT, CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED,
     386                 :            :            SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     387                 :            :            APPLICATION_DATA
     388                 :            :     },
     389                 :            : 
     390                 :            :    [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | CLIENT_AUTH | NO_CLIENT_CERT | WITH_NPN ] = {
     391                 :            :            CLIENT_HELLO,
     392                 :            :            SERVER_HELLO, SERVER_CERT, SERVER_KEY, SERVER_CERT_REQ, SERVER_HELLO_DONE,
     393                 :            :            CLIENT_CERT, CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_NPN, CLIENT_FINISHED,
     394                 :            :            SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     395                 :            :            APPLICATION_DATA
     396                 :            :     },
     397                 :            : 
     398                 :            :     [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | CLIENT_AUTH | WITH_SESSION_TICKET] = {
     399                 :            :            CLIENT_HELLO,
     400                 :            :            SERVER_HELLO, SERVER_CERT, SERVER_KEY, SERVER_CERT_REQ, SERVER_HELLO_DONE,
     401                 :            :            CLIENT_CERT, CLIENT_KEY, CLIENT_CERT_VERIFY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED,
     402                 :            :            SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     403                 :            :            APPLICATION_DATA
     404                 :            :     },
     405                 :            : 
     406                 :            :     [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | CLIENT_AUTH | WITH_SESSION_TICKET | WITH_NPN ] = {
     407                 :            :            CLIENT_HELLO,
     408                 :            :            SERVER_HELLO, SERVER_CERT, SERVER_KEY, SERVER_CERT_REQ, SERVER_HELLO_DONE,
     409                 :            :            CLIENT_CERT, CLIENT_KEY, CLIENT_CERT_VERIFY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_NPN, CLIENT_FINISHED,
     410                 :            :            SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     411                 :            :            APPLICATION_DATA
     412                 :            :     },
     413                 :            : 
     414                 :            :     [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | CLIENT_AUTH | NO_CLIENT_CERT | WITH_SESSION_TICKET ] = {
     415                 :            :            CLIENT_HELLO,
     416                 :            :            SERVER_HELLO, SERVER_CERT, SERVER_KEY, SERVER_CERT_REQ, SERVER_HELLO_DONE,
     417                 :            :            CLIENT_CERT, CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED,
     418                 :            :            SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     419                 :            :            APPLICATION_DATA
     420                 :            :     },
     421                 :            : 
     422                 :            :     [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | CLIENT_AUTH | NO_CLIENT_CERT | WITH_SESSION_TICKET | WITH_NPN ] = {
     423                 :            :            CLIENT_HELLO,
     424                 :            :            SERVER_HELLO, SERVER_CERT, SERVER_KEY, SERVER_CERT_REQ, SERVER_HELLO_DONE,
     425                 :            :            CLIENT_CERT, CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_NPN, CLIENT_FINISHED,
     426                 :            :            SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     427                 :            :            APPLICATION_DATA
     428                 :            :     },
     429                 :            : 
     430                 :            :     [NEGOTIATED | FULL_HANDSHAKE | OCSP_STATUS | CLIENT_AUTH] = {
     431                 :            :            CLIENT_HELLO,
     432                 :            :            SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_CERT_REQ, SERVER_HELLO_DONE,
     433                 :            :            CLIENT_CERT, CLIENT_KEY, CLIENT_CERT_VERIFY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED,
     434                 :            :            SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     435                 :            :            APPLICATION_DATA
     436                 :            :     },
     437                 :            : 
     438                 :            :     [NEGOTIATED | FULL_HANDSHAKE | OCSP_STATUS | CLIENT_AUTH | WITH_NPN ] = {
     439                 :            :            CLIENT_HELLO,
     440                 :            :            SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_CERT_REQ, SERVER_HELLO_DONE,
     441                 :            :            CLIENT_CERT, CLIENT_KEY, CLIENT_CERT_VERIFY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_NPN, CLIENT_FINISHED,
     442                 :            :            SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     443                 :            :            APPLICATION_DATA
     444                 :            :     },
     445                 :            : 
     446                 :            :     [NEGOTIATED | FULL_HANDSHAKE | OCSP_STATUS | CLIENT_AUTH | NO_CLIENT_CERT ] = {
     447                 :            :            CLIENT_HELLO,
     448                 :            :            SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_CERT_REQ, SERVER_HELLO_DONE,
     449                 :            :            CLIENT_CERT, CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED,
     450                 :            :            SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     451                 :            :            APPLICATION_DATA
     452                 :            :     },
     453                 :            : 
     454                 :            :     [NEGOTIATED | FULL_HANDSHAKE | OCSP_STATUS | CLIENT_AUTH | NO_CLIENT_CERT | WITH_NPN ] = {
     455                 :            :            CLIENT_HELLO,
     456                 :            :            SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_CERT_REQ, SERVER_HELLO_DONE,
     457                 :            :            CLIENT_CERT, CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_NPN, CLIENT_FINISHED,
     458                 :            :            SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     459                 :            :            APPLICATION_DATA
     460                 :            :     },
     461                 :            : 
     462                 :            :     [NEGOTIATED | FULL_HANDSHAKE | OCSP_STATUS | CLIENT_AUTH | WITH_SESSION_TICKET] = {
     463                 :            :            CLIENT_HELLO,
     464                 :            :            SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_CERT_REQ, SERVER_HELLO_DONE,
     465                 :            :            CLIENT_CERT, CLIENT_KEY, CLIENT_CERT_VERIFY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED,
     466                 :            :            SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     467                 :            :            APPLICATION_DATA
     468                 :            :     },
     469                 :            : 
     470                 :            :     [NEGOTIATED | FULL_HANDSHAKE | OCSP_STATUS | CLIENT_AUTH | WITH_SESSION_TICKET | WITH_NPN ] = {
     471                 :            :            CLIENT_HELLO,
     472                 :            :            SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_CERT_REQ, SERVER_HELLO_DONE,
     473                 :            :            CLIENT_CERT, CLIENT_KEY, CLIENT_CERT_VERIFY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_NPN, CLIENT_FINISHED,
     474                 :            :            SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     475                 :            :            APPLICATION_DATA
     476                 :            :     },
     477                 :            : 
     478                 :            :     [NEGOTIATED | FULL_HANDSHAKE | OCSP_STATUS | CLIENT_AUTH | NO_CLIENT_CERT | WITH_SESSION_TICKET ] = {
     479                 :            :            CLIENT_HELLO,
     480                 :            :            SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_CERT_REQ, SERVER_HELLO_DONE,
     481                 :            :            CLIENT_CERT, CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED,
     482                 :            :            SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     483                 :            :            APPLICATION_DATA
     484                 :            :     },
     485                 :            : 
     486                 :            :     [NEGOTIATED | FULL_HANDSHAKE | OCSP_STATUS | CLIENT_AUTH | NO_CLIENT_CERT | WITH_SESSION_TICKET | WITH_NPN ] = {
     487                 :            :            CLIENT_HELLO,
     488                 :            :            SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_CERT_REQ, SERVER_HELLO_DONE,
     489                 :            :            CLIENT_CERT, CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_NPN, CLIENT_FINISHED,
     490                 :            :            SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     491                 :            :            APPLICATION_DATA
     492                 :            :     },
     493                 :            : 
     494                 :            :     [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | OCSP_STATUS | CLIENT_AUTH ] = {
     495                 :            :             CLIENT_HELLO,
     496                 :            :             SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_KEY, SERVER_CERT_REQ, SERVER_HELLO_DONE,
     497                 :            :             CLIENT_CERT, CLIENT_KEY, CLIENT_CERT_VERIFY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED,
     498                 :            :             SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     499                 :            :             APPLICATION_DATA
     500                 :            :     },
     501                 :            : 
     502                 :            :     [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | OCSP_STATUS | CLIENT_AUTH | WITH_NPN ] = {
     503                 :            :             CLIENT_HELLO,
     504                 :            :             SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_KEY, SERVER_CERT_REQ, SERVER_HELLO_DONE,
     505                 :            :             CLIENT_CERT, CLIENT_KEY, CLIENT_CERT_VERIFY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_NPN, CLIENT_FINISHED,
     506                 :            :             SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     507                 :            :             APPLICATION_DATA
     508                 :            :     },
     509                 :            : 
     510                 :            :     [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | OCSP_STATUS | CLIENT_AUTH | NO_CLIENT_CERT ] = {
     511                 :            :             CLIENT_HELLO,
     512                 :            :             SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_KEY, SERVER_CERT_REQ, SERVER_HELLO_DONE,
     513                 :            :             CLIENT_CERT, CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED,
     514                 :            :             SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     515                 :            :             APPLICATION_DATA
     516                 :            :     },
     517                 :            : 
     518                 :            :     [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | OCSP_STATUS | CLIENT_AUTH | NO_CLIENT_CERT | WITH_NPN ] = {
     519                 :            :             CLIENT_HELLO,
     520                 :            :             SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_KEY, SERVER_CERT_REQ, SERVER_HELLO_DONE,
     521                 :            :             CLIENT_CERT, CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_NPN, CLIENT_FINISHED,
     522                 :            :             SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     523                 :            :             APPLICATION_DATA
     524                 :            :     },
     525                 :            : 
     526                 :            :     [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | OCSP_STATUS | CLIENT_AUTH | WITH_SESSION_TICKET ] = {
     527                 :            :             CLIENT_HELLO,
     528                 :            :             SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_KEY, SERVER_CERT_REQ, SERVER_HELLO_DONE,
     529                 :            :             CLIENT_CERT, CLIENT_KEY, CLIENT_CERT_VERIFY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED,
     530                 :            :             SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     531                 :            :             APPLICATION_DATA
     532                 :            :     },
     533                 :            : 
     534                 :            :     [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | OCSP_STATUS | CLIENT_AUTH | WITH_SESSION_TICKET | WITH_NPN ] = {
     535                 :            :             CLIENT_HELLO,
     536                 :            :             SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_KEY, SERVER_CERT_REQ, SERVER_HELLO_DONE,
     537                 :            :             CLIENT_CERT, CLIENT_KEY, CLIENT_CERT_VERIFY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_NPN, CLIENT_FINISHED,
     538                 :            :             SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     539                 :            :             APPLICATION_DATA
     540                 :            :     },
     541                 :            : 
     542                 :            :     [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | OCSP_STATUS | CLIENT_AUTH | NO_CLIENT_CERT | WITH_SESSION_TICKET ] = {
     543                 :            :             CLIENT_HELLO,
     544                 :            :             SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_KEY, SERVER_CERT_REQ, SERVER_HELLO_DONE,
     545                 :            :             CLIENT_CERT, CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED,
     546                 :            :             SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     547                 :            :             APPLICATION_DATA
     548                 :            :     },
     549                 :            : 
     550                 :            :     [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | OCSP_STATUS | CLIENT_AUTH | NO_CLIENT_CERT | WITH_SESSION_TICKET | WITH_NPN ] = {
     551                 :            :             CLIENT_HELLO,
     552                 :            :             SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_KEY, SERVER_CERT_REQ, SERVER_HELLO_DONE,
     553                 :            :             CLIENT_CERT, CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_NPN, CLIENT_FINISHED,
     554                 :            :             SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
     555                 :            :             APPLICATION_DATA
     556                 :            :     },
     557                 :            : };
     558                 :            : 
     559                 :            : /*
     560                 :            :  * This selection of handshakes resembles the standard set, but with changes made to support tls1.3.
     561                 :            :  *
     562                 :            :  * The CHANGE_CIPHER_SPEC messages are included only for middlebox compatibility.
     563                 :            :  * See https://tools.ietf.org/html/rfc8446#appendix-D.4
     564                 :            :  */
     565                 :            : static message_type_t tls13_handshakes[S2N_HANDSHAKES_COUNT][S2N_MAX_HANDSHAKE_LENGTH] = {
     566                 :            :     [INITIAL] = {
     567                 :            :             CLIENT_HELLO,
     568                 :            :             SERVER_HELLO
     569                 :            :     },
     570                 :            : 
     571                 :            :     [INITIAL | MIDDLEBOX_COMPAT | EARLY_CLIENT_CCS] = {
     572                 :            :             CLIENT_HELLO, CLIENT_CHANGE_CIPHER_SPEC,
     573                 :            :             SERVER_HELLO
     574                 :            :     },
     575                 :            : 
     576                 :            :     [INITIAL | HELLO_RETRY_REQUEST] = {
     577                 :            :             CLIENT_HELLO,
     578                 :            :             HELLO_RETRY_MSG
     579                 :            :     },
     580                 :            : 
     581                 :            :     [INITIAL | HELLO_RETRY_REQUEST | MIDDLEBOX_COMPAT | EARLY_CLIENT_CCS] = {
     582                 :            :             CLIENT_HELLO, CLIENT_CHANGE_CIPHER_SPEC,
     583                 :            :             HELLO_RETRY_MSG
     584                 :            :     },
     585                 :            : 
     586                 :            :     [NEGOTIATED] = {
     587                 :            :             CLIENT_HELLO,
     588                 :            :             SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_FINISHED,
     589                 :            :             CLIENT_FINISHED,
     590                 :            :             APPLICATION_DATA
     591                 :            :     },
     592                 :            : 
     593                 :            :     [NEGOTIATED | WITH_EARLY_DATA] = {
     594                 :            :             CLIENT_HELLO,
     595                 :            :             SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_FINISHED,
     596                 :            :             END_OF_EARLY_DATA, CLIENT_FINISHED,
     597                 :            :             APPLICATION_DATA
     598                 :            :     },
     599                 :            : 
     600                 :            :     [NEGOTIATED | MIDDLEBOX_COMPAT] = {
     601                 :            :             CLIENT_HELLO,
     602                 :            :             SERVER_HELLO, SERVER_CHANGE_CIPHER_SPEC, ENCRYPTED_EXTENSIONS, SERVER_FINISHED,
     603                 :            :             CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED,
     604                 :            :             APPLICATION_DATA
     605                 :            :     },
     606                 :            : 
     607                 :            :     [NEGOTIATED | MIDDLEBOX_COMPAT | EARLY_CLIENT_CCS] = {
     608                 :            :             CLIENT_HELLO, CLIENT_CHANGE_CIPHER_SPEC,
     609                 :            :             SERVER_HELLO, SERVER_CHANGE_CIPHER_SPEC, ENCRYPTED_EXTENSIONS, SERVER_FINISHED,
     610                 :            :             CLIENT_FINISHED,
     611                 :            :             APPLICATION_DATA
     612                 :            :     },
     613                 :            : 
     614                 :            :     [NEGOTIATED | MIDDLEBOX_COMPAT | WITH_EARLY_DATA] = {
     615                 :            :             CLIENT_HELLO,
     616                 :            :             SERVER_HELLO, SERVER_CHANGE_CIPHER_SPEC, ENCRYPTED_EXTENSIONS, SERVER_FINISHED,
     617                 :            :             CLIENT_CHANGE_CIPHER_SPEC, END_OF_EARLY_DATA, CLIENT_FINISHED,
     618                 :            :             APPLICATION_DATA
     619                 :            :     },
     620                 :            : 
     621                 :            :     [NEGOTIATED | MIDDLEBOX_COMPAT | EARLY_CLIENT_CCS | WITH_EARLY_DATA] = {
     622                 :            :             CLIENT_HELLO, CLIENT_CHANGE_CIPHER_SPEC,
     623                 :            :             SERVER_HELLO, SERVER_CHANGE_CIPHER_SPEC, ENCRYPTED_EXTENSIONS, SERVER_FINISHED,
     624                 :            :             END_OF_EARLY_DATA, CLIENT_FINISHED,
     625                 :            :             APPLICATION_DATA
     626                 :            :     },
     627                 :            : 
     628                 :            :     [NEGOTIATED | HELLO_RETRY_REQUEST] = {
     629                 :            :             CLIENT_HELLO,
     630                 :            :             HELLO_RETRY_MSG,
     631                 :            :             CLIENT_HELLO,
     632                 :            :             SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_FINISHED,
     633                 :            :             CLIENT_FINISHED,
     634                 :            :             APPLICATION_DATA
     635                 :            :     },
     636                 :            : 
     637                 :            :     [NEGOTIATED | HELLO_RETRY_REQUEST | MIDDLEBOX_COMPAT] = {
     638                 :            :             CLIENT_HELLO,
     639                 :            :             HELLO_RETRY_MSG, SERVER_CHANGE_CIPHER_SPEC,
     640                 :            :             CLIENT_CHANGE_CIPHER_SPEC, CLIENT_HELLO,
     641                 :            :             SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_FINISHED,
     642                 :            :             CLIENT_FINISHED,
     643                 :            :             APPLICATION_DATA
     644                 :            :     },
     645                 :            : 
     646                 :            :     [NEGOTIATED | HELLO_RETRY_REQUEST | MIDDLEBOX_COMPAT | EARLY_CLIENT_CCS] = {
     647                 :            :             CLIENT_HELLO, CLIENT_CHANGE_CIPHER_SPEC,
     648                 :            :             HELLO_RETRY_MSG, SERVER_CHANGE_CIPHER_SPEC,
     649                 :            :             CLIENT_HELLO,
     650                 :            :             SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_FINISHED,
     651                 :            :             CLIENT_FINISHED,
     652                 :            :             APPLICATION_DATA
     653                 :            :     },
     654                 :            : 
     655                 :            :     [NEGOTIATED | FULL_HANDSHAKE] = {
     656                 :            :             CLIENT_HELLO,
     657                 :            :             SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED,
     658                 :            :             CLIENT_FINISHED,
     659                 :            :             APPLICATION_DATA
     660                 :            :     },
     661                 :            : 
     662                 :            :     [NEGOTIATED | FULL_HANDSHAKE | MIDDLEBOX_COMPAT] = {
     663                 :            :             CLIENT_HELLO,
     664                 :            :             SERVER_HELLO, SERVER_CHANGE_CIPHER_SPEC, ENCRYPTED_EXTENSIONS, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED,
     665                 :            :             CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED,
     666                 :            :             APPLICATION_DATA
     667                 :            :     },
     668                 :            : 
     669                 :            :     [NEGOTIATED | FULL_HANDSHAKE | MIDDLEBOX_COMPAT | EARLY_CLIENT_CCS] = {
     670                 :            :             CLIENT_HELLO, CLIENT_CHANGE_CIPHER_SPEC,
     671                 :            :             SERVER_HELLO, SERVER_CHANGE_CIPHER_SPEC, ENCRYPTED_EXTENSIONS, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED,
     672                 :            :             CLIENT_FINISHED,
     673                 :            :             APPLICATION_DATA
     674                 :            :     },
     675                 :            : 
     676                 :            :     [NEGOTIATED | FULL_HANDSHAKE | HELLO_RETRY_REQUEST] = {
     677                 :            :             CLIENT_HELLO,
     678                 :            :             HELLO_RETRY_MSG,
     679                 :            :             CLIENT_HELLO,
     680                 :            :             SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED,
     681                 :            :             CLIENT_FINISHED,
     682                 :            :             APPLICATION_DATA
     683                 :            :     },
     684                 :            : 
     685                 :            :     [NEGOTIATED | FULL_HANDSHAKE | HELLO_RETRY_REQUEST | MIDDLEBOX_COMPAT] = {
     686                 :            :             CLIENT_HELLO,
     687                 :            :             HELLO_RETRY_MSG, SERVER_CHANGE_CIPHER_SPEC,
     688                 :            :             CLIENT_CHANGE_CIPHER_SPEC, CLIENT_HELLO,
     689                 :            :             SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED,
     690                 :            :             CLIENT_FINISHED,
     691                 :            :             APPLICATION_DATA
     692                 :            :     },
     693                 :            : 
     694                 :            :     [NEGOTIATED | FULL_HANDSHAKE | HELLO_RETRY_REQUEST | MIDDLEBOX_COMPAT | EARLY_CLIENT_CCS] = {
     695                 :            :             CLIENT_HELLO, CLIENT_CHANGE_CIPHER_SPEC,
     696                 :            :             HELLO_RETRY_MSG, SERVER_CHANGE_CIPHER_SPEC,
     697                 :            :             CLIENT_HELLO,
     698                 :            :             SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED,
     699                 :            :             CLIENT_FINISHED,
     700                 :            :             APPLICATION_DATA
     701                 :            :     },
     702                 :            : 
     703                 :            :     [NEGOTIATED | FULL_HANDSHAKE | HELLO_RETRY_REQUEST | CLIENT_AUTH] = {
     704                 :            :             CLIENT_HELLO,
     705                 :            :             HELLO_RETRY_MSG,
     706                 :            :             CLIENT_HELLO,
     707                 :            :             SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_CERT_REQ, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED,
     708                 :            :             CLIENT_CERT, CLIENT_CERT_VERIFY, CLIENT_FINISHED,
     709                 :            :             APPLICATION_DATA
     710                 :            :     },
     711                 :            : 
     712                 :            :     [NEGOTIATED | FULL_HANDSHAKE | HELLO_RETRY_REQUEST | CLIENT_AUTH | MIDDLEBOX_COMPAT] = {
     713                 :            :             CLIENT_HELLO,
     714                 :            :             HELLO_RETRY_MSG, SERVER_CHANGE_CIPHER_SPEC,
     715                 :            :             CLIENT_CHANGE_CIPHER_SPEC, CLIENT_HELLO,
     716                 :            :             SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_CERT_REQ, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED,
     717                 :            :             CLIENT_CERT, CLIENT_CERT_VERIFY, CLIENT_FINISHED,
     718                 :            :             APPLICATION_DATA
     719                 :            :     },
     720                 :            : 
     721                 :            :     [NEGOTIATED | FULL_HANDSHAKE | HELLO_RETRY_REQUEST | CLIENT_AUTH | MIDDLEBOX_COMPAT | EARLY_CLIENT_CCS] = {
     722                 :            :             CLIENT_HELLO, CLIENT_CHANGE_CIPHER_SPEC,
     723                 :            :             HELLO_RETRY_MSG, SERVER_CHANGE_CIPHER_SPEC,
     724                 :            :             CLIENT_HELLO,
     725                 :            :             SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_CERT_REQ, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED,
     726                 :            :             CLIENT_CERT, CLIENT_CERT_VERIFY, CLIENT_FINISHED,
     727                 :            :             APPLICATION_DATA
     728                 :            :     },
     729                 :            : 
     730                 :            :     [NEGOTIATED | FULL_HANDSHAKE | HELLO_RETRY_REQUEST | CLIENT_AUTH | NO_CLIENT_CERT] = {
     731                 :            :             CLIENT_HELLO,
     732                 :            :             HELLO_RETRY_MSG,
     733                 :            :             CLIENT_HELLO,
     734                 :            :             SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_CERT_REQ, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED,
     735                 :            :             CLIENT_CERT, CLIENT_FINISHED,
     736                 :            :             APPLICATION_DATA
     737                 :            :     },
     738                 :            : 
     739                 :            :     [NEGOTIATED | FULL_HANDSHAKE | HELLO_RETRY_REQUEST | CLIENT_AUTH | NO_CLIENT_CERT | MIDDLEBOX_COMPAT] = {
     740                 :            :             CLIENT_HELLO,
     741                 :            :             HELLO_RETRY_MSG, SERVER_CHANGE_CIPHER_SPEC,
     742                 :            :             CLIENT_CHANGE_CIPHER_SPEC, CLIENT_HELLO,
     743                 :            :             SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_CERT_REQ, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED,
     744                 :            :             CLIENT_CERT, CLIENT_FINISHED,
     745                 :            :             APPLICATION_DATA
     746                 :            :     },
     747                 :            : 
     748                 :            :     [NEGOTIATED | FULL_HANDSHAKE | HELLO_RETRY_REQUEST | CLIENT_AUTH | NO_CLIENT_CERT | MIDDLEBOX_COMPAT | EARLY_CLIENT_CCS] = {
     749                 :            :             CLIENT_HELLO, CLIENT_CHANGE_CIPHER_SPEC,
     750                 :            :             HELLO_RETRY_MSG, SERVER_CHANGE_CIPHER_SPEC,
     751                 :            :             CLIENT_HELLO,
     752                 :            :             SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_CERT_REQ, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED,
     753                 :            :             CLIENT_CERT, CLIENT_FINISHED,
     754                 :            :             APPLICATION_DATA
     755                 :            :     },
     756                 :            : 
     757                 :            :     [NEGOTIATED | FULL_HANDSHAKE | CLIENT_AUTH] = {
     758                 :            :             CLIENT_HELLO,
     759                 :            :             SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_CERT_REQ, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED,
     760                 :            :             CLIENT_CERT, CLIENT_CERT_VERIFY, CLIENT_FINISHED,
     761                 :            :             APPLICATION_DATA
     762                 :            :     },
     763                 :            : 
     764                 :            :     [NEGOTIATED | FULL_HANDSHAKE | CLIENT_AUTH | MIDDLEBOX_COMPAT] = {
     765                 :            :             CLIENT_HELLO,
     766                 :            :             SERVER_HELLO, SERVER_CHANGE_CIPHER_SPEC, ENCRYPTED_EXTENSIONS, SERVER_CERT_REQ, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED,
     767                 :            :             CLIENT_CHANGE_CIPHER_SPEC, CLIENT_CERT, CLIENT_CERT_VERIFY, CLIENT_FINISHED,
     768                 :            :             APPLICATION_DATA
     769                 :            :     },
     770                 :            : 
     771                 :            :     [NEGOTIATED | FULL_HANDSHAKE | CLIENT_AUTH | MIDDLEBOX_COMPAT | EARLY_CLIENT_CCS] = {
     772                 :            :             CLIENT_HELLO, CLIENT_CHANGE_CIPHER_SPEC,
     773                 :            :             SERVER_HELLO, SERVER_CHANGE_CIPHER_SPEC, ENCRYPTED_EXTENSIONS, SERVER_CERT_REQ, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED,
     774                 :            :             CLIENT_CERT, CLIENT_CERT_VERIFY, CLIENT_FINISHED,
     775                 :            :             APPLICATION_DATA
     776                 :            :     },
     777                 :            : 
     778                 :            :     [NEGOTIATED | FULL_HANDSHAKE | CLIENT_AUTH | NO_CLIENT_CERT] = {
     779                 :            :             CLIENT_HELLO,
     780                 :            :             SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_CERT_REQ, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED,
     781                 :            :             CLIENT_CERT, CLIENT_FINISHED,
     782                 :            :             APPLICATION_DATA
     783                 :            :     },
     784                 :            : 
     785                 :            :     [NEGOTIATED | FULL_HANDSHAKE | CLIENT_AUTH | NO_CLIENT_CERT | MIDDLEBOX_COMPAT] = {
     786                 :            :             CLIENT_HELLO,
     787                 :            :             SERVER_HELLO, SERVER_CHANGE_CIPHER_SPEC, ENCRYPTED_EXTENSIONS, SERVER_CERT_REQ, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED,
     788                 :            :             CLIENT_CHANGE_CIPHER_SPEC, CLIENT_CERT, CLIENT_FINISHED,
     789                 :            :             APPLICATION_DATA
     790                 :            :     },
     791                 :            : 
     792                 :            :     [NEGOTIATED | FULL_HANDSHAKE | CLIENT_AUTH | NO_CLIENT_CERT | MIDDLEBOX_COMPAT | EARLY_CLIENT_CCS] = {
     793                 :            :             CLIENT_HELLO, CLIENT_CHANGE_CIPHER_SPEC,
     794                 :            :             SERVER_HELLO, SERVER_CHANGE_CIPHER_SPEC, ENCRYPTED_EXTENSIONS, SERVER_CERT_REQ, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED,
     795                 :            :             CLIENT_CERT, CLIENT_FINISHED,
     796                 :            :             APPLICATION_DATA
     797                 :            :     },
     798                 :            : };
     799                 :            : /* clang-format on */
     800                 :            : 
     801                 :         85 : #define MAX_HANDSHAKE_TYPE_LEN 142
     802                 :            : /* The handshake type labels used for TLS 1.0 - TLS 1.2, e.g. `NEGOTIATED|WITH_SESSION_TICKET` */
     803                 :            : static char handshake_type_str_tls12ish[S2N_HANDSHAKES_COUNT][MAX_HANDSHAKE_TYPE_LEN] = { 0 };
     804                 :            : 
     805                 :            : /* The handshake type labels used for TLS 1.3, e.g. `NEGOTIATED|HELLO_RETRY_REQUEST` */
     806                 :            : static char handshake_type_str_tls13[S2N_HANDSHAKES_COUNT][MAX_HANDSHAKE_TYPE_LEN] = { 0 };
     807                 :            : 
     808                 :            : static const char *tls12_handshake_type_names[] = {
     809                 :            :     "NEGOTIATED|",
     810                 :            :     "FULL_HANDSHAKE|",
     811                 :            :     "CLIENT_AUTH|",
     812                 :            :     "NO_CLIENT_CERT|",
     813                 :            :     "TLS12_PERFECT_FORWARD_SECRECY|",
     814                 :            :     "OCSP_STATUS|",
     815                 :            :     "WITH_SESSION_TICKET|",
     816                 :            :     "WITH_NPN|",
     817                 :            : };
     818                 :            : 
     819                 :            : static const char *tls13_handshake_type_names[] = {
     820                 :            :     "NEGOTIATED|",
     821                 :            :     "FULL_HANDSHAKE|",
     822                 :            :     "CLIENT_AUTH|",
     823                 :            :     "NO_CLIENT_CERT|",
     824                 :            :     "HELLO_RETRY_REQUEST|",
     825                 :            :     "MIDDLEBOX_COMPAT|",
     826                 :            :     "WITH_EARLY_DATA|",
     827                 :            :     "EARLY_CLIENT_CCS|",
     828                 :            : };
     829                 :            : 
     830                 :    3110766 : #define IS_TLS13_HANDSHAKE(conn) ((conn)->handshake.state_machine == S2N_STATE_MACHINE_TLS13)
     831                 :            : 
     832                 :     946238 : #define ACTIVE_STATE_MACHINE(conn) (IS_TLS13_HANDSHAKE(conn) ? tls13_state_machine : state_machine)
     833                 :    2114612 : #define ACTIVE_HANDSHAKES(conn)    (IS_TLS13_HANDSHAKE(conn) ? tls13_handshakes : handshakes)
     834                 :            : 
     835                 :    2114612 : #define ACTIVE_MESSAGE(conn) ACTIVE_HANDSHAKES(conn)[(conn)->handshake.handshake_type][(conn)->handshake.message_number]
     836                 :            : 
     837                 :     946238 : #define ACTIVE_STATE(conn) ACTIVE_STATE_MACHINE(conn)[ACTIVE_MESSAGE((conn))]
     838                 :            : 
     839                 :            : #define CCS_STATE(conn) (((conn)->mode == S2N_CLIENT) ?                 \
     840                 :            :                 ACTIVE_STATE_MACHINE(conn)[SERVER_CHANGE_CIPHER_SPEC] : \
     841                 :            :                 ACTIVE_STATE_MACHINE(conn)[CLIENT_CHANGE_CIPHER_SPEC])
     842                 :            : 
     843                 :     175743 : #define EXPECTED_RECORD_TYPE(conn)  ACTIVE_STATE(conn).record_type
     844                 :      67065 : #define EXPECTED_MESSAGE_TYPE(conn) ACTIVE_STATE(conn).message_type
     845                 :            : 
     846                 :     347257 : #define CONNECTION_WRITER(conn)    (conn->mode == S2N_CLIENT ? 'C' : 'S')
     847                 :     247713 : #define CONNECTION_IS_WRITER(conn) (ACTIVE_STATE(conn).writer == CONNECTION_WRITER(conn))
     848                 :            : 
     849                 :            : /* Only used in our test cases. */
     850                 :            : message_type_t s2n_conn_get_current_message_type(const struct s2n_connection *conn)
     851                 :     852700 : {
     852         [ +  + ]:     852700 :     return ACTIVE_MESSAGE(conn);
     853                 :     852700 : }
     854                 :            : 
     855                 :            : static int s2n_advance_message(struct s2n_connection *conn)
     856                 :      99544 : {
     857                 :            :     /* Get the mode: 'C'lient or 'S'erver */
     858                 :      99544 : #ifndef _WIN32
     859 [ +  + ][ +  + ]:      99544 :     char previous_writer = ACTIVE_STATE(conn).writer;
     860                 :      99544 : #endif
     861         [ +  + ]:      99544 :     char this_mode = CONNECTION_WRITER(conn);
     862                 :            : 
     863                 :            :     /* Actually advance the message number */
     864                 :      99544 :     conn->handshake.message_number++;
     865                 :            : 
     866                 :            :     /* When reading and using TLS1.3, skip optional change_cipher_spec states. */
     867 [ +  + ][ +  + ]:      99544 :     if (ACTIVE_STATE(conn).writer != this_mode && EXPECTED_RECORD_TYPE(conn) == TLS_CHANGE_CIPHER_SPEC && IS_TLS13_HANDSHAKE(conn)) {
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
                 [ +  + ]
     868                 :       8199 :         conn->handshake.message_number++;
     869                 :       8199 :     }
     870                 :            : 
     871                 :      99544 : #ifndef _WIN32
     872                 :            :     /* Set TCP_QUICKACK to avoid artificial delay during the handshake */
     873         [ -  + ]:      99544 :     POSIX_GUARD(s2n_socket_quickack(conn));
     874                 :            : 
     875                 :            :     /* If optimized io hasn't been enabled or if the caller started out with a corked socket,
     876                 :            :      * we don't mess with it
     877                 :            :      */
     878 [ +  + ][ -  + ]:      99544 :     if (!conn->corked_io || s2n_socket_was_corked(conn)) {
     879                 :      99204 :         return S2N_SUCCESS;
     880                 :      99204 :     }
     881                 :            : 
     882                 :            :     /* Are we changing I/O directions */
     883 [ +  + ][ +  + ]:        340 :     if (ACTIVE_STATE(conn).writer == previous_writer || ACTIVE_STATE(conn).writer == 'A') {
         [ +  + ][ +  + ]
         [ +  + ][ -  + ]
     884                 :        206 :         return S2N_SUCCESS;
     885                 :        206 :     }
     886                 :            : 
     887                 :            :     /* We're the new writer */
     888 [ +  + ][ +  + ]:        134 :     if (ACTIVE_STATE(conn).writer == this_mode) {
                 [ +  + ]
     889         [ +  - ]:         62 :         if (s2n_connection_is_managed_corked(conn)) {
     890                 :            :             /* Set TCP_CORK/NOPUSH */
     891         [ -  + ]:         62 :             POSIX_GUARD(s2n_socket_write_cork(conn));
     892                 :         62 :         }
     893                 :            : 
     894                 :         62 :         return S2N_SUCCESS;
     895                 :         62 :     }
     896                 :            : 
     897                 :            :     /* We're the new reader, or we reached the "B" writer stage indicating that
     898                 :            :        we're at the application data stage  - uncork the data */
     899         [ +  - ]:         72 :     if (s2n_connection_is_managed_corked(conn)) {
     900         [ -  + ]:         72 :         POSIX_GUARD(s2n_socket_write_uncork(conn));
     901                 :         72 :     }
     902                 :         72 : #endif
     903                 :            : 
     904                 :         72 :     return S2N_SUCCESS;
     905                 :         72 : }
     906                 :            : 
     907                 :            : int s2n_generate_new_client_session_id(struct s2n_connection *conn)
     908                 :       4725 : {
     909         [ +  + ]:       4725 :     if (conn->mode == S2N_SERVER) {
     910                 :       2411 :         struct s2n_blob session_id = { 0 };
     911         [ -  + ]:       2411 :         POSIX_GUARD(s2n_blob_init(&session_id, conn->session_id, S2N_TLS_SESSION_ID_MAX_LEN));
     912                 :            : 
     913                 :            :         /* Generate a new session id */
     914         [ -  + ]:       2411 :         POSIX_GUARD_RESULT(s2n_get_public_random_data(&session_id));
     915                 :       2411 :         conn->session_id_len = S2N_TLS_SESSION_ID_MAX_LEN;
     916                 :       2411 :     }
     917                 :            : 
     918                 :       4725 :     return S2N_SUCCESS;
     919                 :       4725 : }
     920                 :            : 
     921                 :            : /* Lets the server flag whether a HelloRetryRequest is needed while processing extensions */
     922                 :            : int s2n_set_hello_retry_required(struct s2n_connection *conn)
     923                 :       2018 : {
     924 [ -  + ][ #  # ]:       2018 :     POSIX_ENSURE_REF(conn);
     925                 :            : 
     926 [ +  - ][ +  + ]:       2018 :     POSIX_ENSURE(conn->actual_protocol_version >= S2N_TLS13, S2N_ERR_INVALID_HELLO_RETRY);
     927         [ -  + ]:       2017 :     POSIX_GUARD_RESULT(s2n_handshake_type_set_tls13_flag(conn, HELLO_RETRY_REQUEST));
     928                 :            : 
     929                 :            :     /* HelloRetryRequests also indicate rejection of early data.
     930                 :            :      *
     931                 :            :      *= https://www.rfc-editor.org/rfc/rfc8446#section-4.2.10
     932                 :            :      *# A server which receives an "early_data" extension MUST behave in one
     933                 :            :      *# of three ways:
     934                 :            :      *
     935                 :            :      *= https://www.rfc-editor.org/rfc/rfc8446#section-4.2.10
     936                 :            :      *# -  Request that the client send another ClientHello by responding
     937                 :            :      *#    with a HelloRetryRequest.
     938                 :            :      **/
     939         [ +  + ]:       2017 :     if (conn->early_data_state == S2N_EARLY_DATA_REQUESTED) {
     940         [ -  + ]:        916 :         POSIX_GUARD_RESULT(s2n_connection_set_early_data_state(conn, S2N_EARLY_DATA_REJECTED));
     941                 :        916 :     }
     942                 :            : 
     943                 :       2017 :     return S2N_SUCCESS;
     944                 :       2017 : }
     945                 :            : 
     946                 :            : bool s2n_is_hello_retry_message(struct s2n_connection *conn)
     947                 :      44768 : {
     948 [ +  - ][ +  - ]:      44768 :     return (conn != NULL && s2n_result_is_ok(s2n_handshake_validate(&(conn->handshake))) && ACTIVE_MESSAGE(conn) == HELLO_RETRY_MSG);
         [ +  + ][ +  + ]
     949                 :      44768 : }
     950                 :            : 
     951                 :            : bool s2n_is_hello_retry_handshake(struct s2n_connection *conn)
     952                 :      91288 : {
     953                 :      91288 :     return IS_HELLO_RETRY_HANDSHAKE(conn);
     954                 :      91288 : }
     955                 :            : 
     956                 :            : static S2N_RESULT s2n_conn_set_tls13_handshake_type(struct s2n_connection *conn)
     957                 :      10277 : {
     958 [ #  # ][ -  + ]:      10277 :     RESULT_ENSURE_REF(conn);
     959                 :            : 
     960                 :            :     /* Most handshake type flags should be reset before we calculate the handshake type,
     961                 :            :      * in order to handle changes during retries.
     962                 :            :      * However, flags that have already affected the message order must be kept to avoid
     963                 :            :      * rewriting the past.
     964                 :            :      */
     965                 :      10277 :     conn->handshake.handshake_type &= (HELLO_RETRY_REQUEST | MIDDLEBOX_COMPAT | EARLY_CLIENT_CCS);
     966                 :            : 
     967                 :            :     /* A handshake type has been negotiated */
     968         [ -  + ]:      10277 :     RESULT_GUARD(s2n_handshake_type_set_flag(conn, NEGOTIATED));
     969                 :            : 
     970         [ +  + ]:      10277 :     if (conn->psk_params.chosen_psk == NULL) {
     971         [ -  + ]:       8625 :         RESULT_GUARD(s2n_handshake_type_set_flag(conn, FULL_HANDSHAKE));
     972                 :       8625 :     }
     973                 :            : 
     974         [ +  + ]:      10277 :     if (conn->early_data_state == S2N_EARLY_DATA_ACCEPTED) {
     975                 :         46 :         conn->handshake.handshake_type |= WITH_EARLY_DATA;
     976                 :         46 :     }
     977                 :            : 
     978                 :      10277 :     s2n_cert_auth_type client_cert_auth_type;
     979         [ -  + ]:      10277 :     RESULT_GUARD_POSIX(s2n_connection_get_client_auth_type(conn, &client_cert_auth_type));
     980                 :            : 
     981 [ +  + ][ +  + ]:      10277 :     if (conn->mode == S2N_CLIENT && client_cert_auth_type == S2N_CERT_AUTH_REQUIRED
     982         [ +  + ]:      10277 :             && IS_FULL_HANDSHAKE(conn)) {
     983                 :            :         /* If we're a client, and Client Auth is REQUIRED, then the Client must expect the CLIENT_CERT_REQ Message */
     984         [ -  + ]:         44 :         RESULT_GUARD(s2n_handshake_type_set_flag(conn, CLIENT_AUTH));
     985 [ +  + ][ +  + ]:      10233 :     } else if (conn->mode == S2N_SERVER && client_cert_auth_type != S2N_CERT_AUTH_NONE
     986         [ +  + ]:      10233 :             && IS_FULL_HANDSHAKE(conn)) {
     987                 :            :         /* If we're a server, and Client Auth is REQUIRED or OPTIONAL, then the server must send the CLIENT_CERT_REQ Message*/
     988         [ -  + ]:         99 :         RESULT_GUARD(s2n_handshake_type_set_flag(conn, CLIENT_AUTH));
     989                 :         99 :     }
     990                 :            : 
     991         [ +  + ]:      10277 :     if (s2n_is_middlebox_compat_enabled(conn)) {
     992         [ -  + ]:      10260 :         RESULT_GUARD(s2n_handshake_type_set_tls13_flag(conn, MIDDLEBOX_COMPAT));
     993                 :      10260 :     }
     994                 :            : 
     995                 :      10277 :     return S2N_RESULT_OK;
     996                 :      10277 : }
     997                 :            : 
     998                 :            : static S2N_RESULT s2n_validate_ems_status(struct s2n_connection *conn)
     999                 :         13 : {
    1000 [ #  # ][ -  + ]:         13 :     RESULT_ENSURE_REF(conn);
    1001                 :            : 
    1002                 :         13 :     s2n_extension_type_id ems_ext_id = 0;
    1003         [ -  + ]:         13 :     RESULT_GUARD_POSIX(s2n_extension_supported_iana_value_to_id(TLS_EXTENSION_EMS, &ems_ext_id));
    1004                 :         13 :     bool ems_extension_recv = S2N_CBIT_TEST(conn->extension_requests_received, ems_ext_id);
    1005                 :            : 
    1006                 :            :     /**
    1007                 :            :      *= https://www.rfc-editor.org/rfc/rfc7627#section-5.3
    1008                 :            :      *# If the original session used the "extended_master_secret"
    1009                 :            :      *# extension but the new ClientHello does not contain it, the server
    1010                 :            :      *# MUST abort the abbreviated handshake.
    1011                 :            :      **/
    1012         [ +  + ]:         13 :     if (conn->ems_negotiated) {
    1013 [ +  - ][ +  + ]:         11 :         RESULT_ENSURE(ems_extension_recv, S2N_ERR_MISSING_EXTENSION);
    1014                 :         11 :     }
    1015                 :            : 
    1016                 :            :     /* Since we're discarding the resumption ticket, ignore EMS value from the ticket */
    1017                 :         11 :     conn->ems_negotiated = ems_extension_recv;
    1018                 :            : 
    1019                 :         11 :     return S2N_RESULT_OK;
    1020                 :         13 : }
    1021                 :            : 
    1022                 :            : int s2n_conn_set_handshake_type(struct s2n_connection *conn)
    1023                 :      15200 : {
    1024 [ #  # ][ -  + ]:      15200 :     POSIX_ENSURE_REF(conn);
    1025 [ -  + ][ #  # ]:      15200 :     POSIX_ENSURE_REF(conn->secure);
    1026                 :            : 
    1027         [ -  + ]:      15200 :     POSIX_GUARD_RESULT(s2n_conn_choose_state_machine(conn, conn->actual_protocol_version));
    1028                 :            : 
    1029         [ +  + ]:      15200 :     if (IS_TLS13_HANDSHAKE(conn)) {
    1030         [ -  + ]:      10419 :         POSIX_GUARD_RESULT(s2n_conn_set_tls13_handshake_type(conn));
    1031                 :      10419 :         return S2N_SUCCESS;
    1032                 :      10419 :     }
    1033                 :            : 
    1034         [ -  + ]:       4781 :     POSIX_GUARD_RESULT(s2n_handshake_type_reset(conn));
    1035                 :            : 
    1036                 :            :     /* A handshake type has been negotiated */
    1037         [ -  + ]:       4781 :     POSIX_GUARD_RESULT(s2n_handshake_type_set_flag(conn, NEGOTIATED));
    1038                 :            : 
    1039                 :       4781 :     s2n_cert_auth_type client_cert_auth_type;
    1040         [ -  + ]:       4781 :     POSIX_GUARD(s2n_connection_get_client_auth_type(conn, &client_cert_auth_type));
    1041                 :            : 
    1042 [ +  + ][ +  + ]:       4781 :     if (conn->mode == S2N_CLIENT && client_cert_auth_type == S2N_CERT_AUTH_REQUIRED) {
    1043                 :            :         /* If we're a client, and Client Auth is REQUIRED, then the Client must expect the CLIENT_CERT_REQ Message */
    1044         [ -  + ]:         61 :         POSIX_GUARD_RESULT(s2n_handshake_type_set_flag(conn, CLIENT_AUTH));
    1045 [ +  + ][ +  + ]:       4720 :     } else if (conn->mode == S2N_SERVER && client_cert_auth_type != S2N_CERT_AUTH_NONE) {
    1046                 :            :         /* If we're a server, and Client Auth is REQUIRED or OPTIONAL, then the server must send the CLIENT_CERT_REQ Message*/
    1047         [ -  + ]:        114 :         POSIX_GUARD_RESULT(s2n_handshake_type_set_flag(conn, CLIENT_AUTH));
    1048                 :        114 :     }
    1049                 :            : 
    1050         [ +  + ]:       4781 :     if (conn->npn_negotiated) {
    1051         [ -  + ]:          4 :         POSIX_GUARD_RESULT(s2n_handshake_type_set_tls12_flag(conn, WITH_NPN));
    1052                 :          4 :     }
    1053                 :            : 
    1054         [ +  + ]:       4781 :     if (conn->config->use_tickets) {
    1055         [ +  + ]:        122 :         if (conn->session_ticket_status == S2N_DECRYPT_TICKET) {
    1056                 :            :             /* We reuse the session if a valid TLS12 ticket is provided.
    1057                 :            :              * Otherwise, we will perform a full handshake and then generate
    1058                 :            :              * a new session ticket. */
    1059         [ +  + ]:         29 :             if (s2n_result_is_ok(s2n_resume_decrypt_session(conn, &conn->client_ticket_to_decrypt))) {
    1060                 :         23 :                 return S2N_SUCCESS;
    1061                 :         23 :             }
    1062                 :            : 
    1063         [ +  + ]:          6 :             POSIX_GUARD_RESULT(s2n_validate_ems_status(conn));
    1064                 :            : 
    1065                 :            :             /* Set up the handshake to send a session ticket since a valid ticket was not provided */
    1066         [ +  + ]:          5 :             if (s2n_result_is_ok(s2n_config_is_encrypt_key_available(conn->config))) {
    1067                 :          3 :                 conn->session_ticket_status = S2N_NEW_TICKET;
    1068         [ -  + ]:          3 :                 POSIX_GUARD_RESULT(s2n_handshake_type_set_tls12_flag(conn, WITH_SESSION_TICKET));
    1069                 :          3 :             }
    1070                 :            : 
    1071                 :            :             /* If a session ticket is presented by the client, then skip lookup in Session ID server cache */
    1072                 :          5 :             goto skip_cache_lookup;
    1073                 :          5 :         }
    1074                 :            : 
    1075         [ +  + ]:         93 :         if (conn->session_ticket_status == S2N_NEW_TICKET) {
    1076         [ -  + ]:         35 :             POSIX_GUARD_RESULT(s2n_handshake_type_set_tls12_flag(conn, WITH_SESSION_TICKET));
    1077                 :         35 :         }
    1078                 :         93 :     }
    1079                 :            : 
    1080                 :            :     /* If a TLS session is resumed, the Server should respond in its ServerHello with the same SessionId the
    1081                 :            :      * Client sent in the ClientHello. */
    1082 [ +  - ][ +  + ]:       4752 :     if (conn->actual_protocol_version <= S2N_TLS12 && conn->mode == S2N_SERVER && s2n_allowed_to_cache_connection(conn)) {
                 [ +  + ]
    1083                 :         16 :         int r = s2n_resume_from_cache(conn);
    1084 [ +  + ][ +  + ]:         16 :         if (r == S2N_SUCCESS || (r < S2N_SUCCESS && S2N_ERROR_IS_BLOCKING(s2n_errno))) {
                 [ +  - ]
    1085                 :          9 :             return r;
    1086                 :          9 :         }
    1087         [ +  + ]:          7 :         POSIX_GUARD_RESULT(s2n_validate_ems_status(conn));
    1088                 :          7 :     }
    1089                 :            : 
    1090                 :       4747 : skip_cache_lookup:
    1091 [ +  + ][ +  + ]:       4747 :     if (conn->mode == S2N_CLIENT && conn->client_session_resumed == 1) {
    1092                 :         22 :         return S2N_SUCCESS;
    1093                 :         22 :     }
    1094                 :            : 
    1095                 :            :     /* If we're doing full handshake, generate a new session id. */
    1096         [ -  + ]:       4725 :     POSIX_GUARD(s2n_generate_new_client_session_id(conn));
    1097                 :            : 
    1098                 :            :     /* If we get this far, it's a full handshake */
    1099         [ -  + ]:       4725 :     POSIX_GUARD_RESULT(s2n_handshake_type_set_flag(conn, FULL_HANDSHAKE));
    1100                 :            : 
    1101                 :       4725 :     bool is_ephemeral = false;
    1102         [ -  + ]:       4725 :     POSIX_GUARD_RESULT(s2n_kex_is_ephemeral(conn->secure->cipher_suite->key_exchange_alg, &is_ephemeral));
    1103         [ +  + ]:       4725 :     if (is_ephemeral) {
    1104         [ -  + ]:       1730 :         POSIX_GUARD_RESULT(s2n_handshake_type_set_tls12_flag(conn, TLS12_PERFECT_FORWARD_SECRECY));
    1105                 :       1730 :     }
    1106                 :            : 
    1107 [ +  + ][ +  - ]:       4725 :     if (s2n_server_can_send_ocsp(conn) || s2n_server_sent_ocsp(conn)) {
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
    1108         [ -  + ]:          5 :         POSIX_GUARD_RESULT(s2n_handshake_type_set_tls12_flag(conn, OCSP_STATUS));
    1109                 :          5 :     }
    1110                 :            : 
    1111                 :       4725 :     return S2N_SUCCESS;
    1112                 :       4725 : }
    1113                 :            : 
    1114                 :            : int s2n_conn_set_handshake_no_client_cert(struct s2n_connection *conn)
    1115                 :         69 : {
    1116                 :         69 :     s2n_cert_auth_type client_cert_auth_type;
    1117         [ -  + ]:         69 :     POSIX_GUARD(s2n_connection_get_client_auth_type(conn, &client_cert_auth_type));
    1118 [ +  - ][ +  + ]:         69 :     POSIX_ENSURE(client_cert_auth_type == S2N_CERT_AUTH_OPTIONAL, S2N_ERR_MISSING_CLIENT_CERT);
    1119                 :            : 
    1120         [ -  + ]:         60 :     POSIX_GUARD_RESULT(s2n_handshake_type_set_flag(conn, NO_CLIENT_CERT));
    1121                 :            : 
    1122                 :         60 :     return S2N_SUCCESS;
    1123                 :         60 : }
    1124                 :            : 
    1125                 :            : S2N_RESULT s2n_conn_choose_state_machine(struct s2n_connection *conn, uint8_t protocol_version)
    1126                 :      32521 : {
    1127 [ #  # ][ -  + ]:      32521 :     RESULT_ENSURE_REF(conn);
    1128                 :            : 
    1129                 :            :     /* This should never be called before we know what version we're on */
    1130 [ -  + ][ #  # ]:      32521 :     RESULT_ENSURE_NE(protocol_version, S2N_UNKNOWN_PROTOCOL_VERSION);
    1131                 :            : 
    1132         [ +  + ]:      32521 :     if (protocol_version == S2N_TLS13) {
    1133                 :            :         /* State machine should not change once set */
    1134 [ #  # ][ -  + ]:      25912 :         RESULT_ENSURE_NE(conn->handshake.state_machine, S2N_STATE_MACHINE_TLS12);
    1135                 :      25912 :         conn->handshake.state_machine = S2N_STATE_MACHINE_TLS13;
    1136                 :      25912 :     } else {
    1137                 :            :         /* State machine should not change once set */
    1138 [ #  # ][ -  + ]:       6609 :         RESULT_ENSURE_NE(conn->handshake.state_machine, S2N_STATE_MACHINE_TLS13);
    1139                 :       6609 :         conn->handshake.state_machine = S2N_STATE_MACHINE_TLS12;
    1140                 :       6609 :     }
    1141                 :            : 
    1142                 :      32521 :     return S2N_RESULT_OK;
    1143                 :      32521 : }
    1144                 :            : 
    1145                 :            : const char *s2n_connection_get_last_message_name(struct s2n_connection *conn)
    1146                 :        362 : {
    1147 [ #  # ][ -  + ]:        362 :     PTR_ENSURE_REF(conn);
    1148         [ -  + ]:        362 :     PTR_GUARD_RESULT(s2n_handshake_validate(&(conn->handshake)));
    1149         [ +  + ]:        362 :     return message_names[ACTIVE_MESSAGE(conn)];
    1150                 :        362 : }
    1151                 :            : 
    1152                 :            : const char *s2n_connection_get_handshake_type_name(struct s2n_connection *conn)
    1153                 :       3863 : {
    1154 [ -  + ][ #  # ]:       3863 :     PTR_ENSURE_REF(conn);
    1155 [ -  + ][ +  - ]:       3863 :     PTR_PRECONDITION(s2n_handshake_validate(&(conn->handshake)));
    1156                 :            : 
    1157                 :       3863 :     uint32_t handshake_type = conn->handshake.handshake_type;
    1158                 :            : 
    1159         [ +  + ]:       3863 :     if (handshake_type == INITIAL) {
    1160                 :         88 :         return "INITIAL";
    1161                 :         88 :     }
    1162                 :            : 
    1163                 :       3775 :     const char **handshake_labels = tls13_handshake_type_names;
    1164                 :       3775 :     size_t handshake_labels_len = s2n_array_len(tls13_handshake_type_names);
    1165                 :       3775 :     char(*names)[MAX_HANDSHAKE_TYPE_LEN] = handshake_type_str_tls13;
    1166         [ +  + ]:       3775 :     if (s2n_connection_get_protocol_version(conn) < S2N_TLS13) {
    1167                 :       2811 :         handshake_labels = tls12_handshake_type_names;
    1168                 :       2811 :         handshake_labels_len = s2n_array_len(tls12_handshake_type_names);
    1169                 :       2811 :         names = handshake_type_str_tls12ish;
    1170                 :       2811 :     }
    1171                 :            : 
    1172                 :            :     /* Not all handshake strings will be created already. If the handshake string
    1173                 :            :      * is not null, we can just return the handshake. Otherwise we have to compute
    1174                 :            :      * it down below. */
    1175         [ +  + ]:       3775 :     if (names[handshake_type][0] != '\0') {
    1176                 :       3690 :         return names[handshake_type];
    1177                 :       3690 :     }
    1178                 :            : 
    1179                 :            :     /* Compute the cached string by concatenating each applicable handshake_type.
    1180                 :            :      *
    1181                 :            :      * Unit tests enforce that the elements of the cache are always
    1182                 :            :      * long enough to contain the longest possible valid handshake_type, but
    1183                 :            :      * for safety we still handle the case where we need to truncate.
    1184                 :            :      */
    1185                 :         85 :     char *p = names[handshake_type];
    1186                 :         85 :     size_t remaining = MAX_HANDSHAKE_TYPE_LEN;
    1187         [ +  + ]:        765 :     for (size_t i = 0; i < handshake_labels_len; i++) {
    1188                 :        680 :         bool label_applies = handshake_type & (1 << i);
    1189         [ +  + ]:        680 :         if (label_applies) {
    1190         [ -  + ]:        372 :             size_t bytes_to_copy = S2N_MIN(remaining, strlen(handshake_labels[i]));
    1191 [ #  # ][ -  + ]:        372 :             PTR_CHECKED_MEMCPY(p, handshake_labels[i], bytes_to_copy);
                 [ +  - ]
    1192                 :        372 :             p[bytes_to_copy] = '\0';
    1193                 :        372 :             p += bytes_to_copy;
    1194                 :        372 :             remaining -= bytes_to_copy;
    1195                 :        372 :         }
    1196                 :        680 :     }
    1197                 :            : 
    1198 [ +  - ][ +  - ]:         85 :     if (p != names[handshake_type] && '|' == *(p - 1)) {
    1199                 :         85 :         *(p - 1) = '\0';
    1200                 :         85 :     }
    1201                 :            : 
    1202                 :         85 :     return names[handshake_type];
    1203                 :         85 : }
    1204                 :            : 
    1205                 :            : S2N_RESULT s2n_handshake_message_send(struct s2n_connection *conn, uint8_t content_type, s2n_blocked_status *blocked)
    1206                 :     117683 : {
    1207 [ -  + ][ #  # ]:     117683 :     RESULT_ENSURE_REF(conn);
    1208                 :     117683 :     struct s2n_stuffer *in = &conn->handshake.io;
    1209                 :            : 
    1210                 :     117683 :     uint32_t size = s2n_stuffer_data_available(in);
    1211         [ +  + ]:     117683 :     if (size == 0) {
    1212                 :      50848 :         return S2N_RESULT_OK;
    1213                 :      50848 :     }
    1214                 :            : 
    1215         [ +  + ]:      66835 :     if (s2n_connection_is_quic_enabled(conn)) {
    1216         [ -  + ]:         50 :         RESULT_GUARD(s2n_quic_write_handshake_message(conn));
    1217         [ +  + ]:         50 :         RESULT_GUARD_POSIX(s2n_flush(conn, blocked));
    1218                 :         49 :         return S2N_RESULT_OK;
    1219                 :         50 :     }
    1220                 :            : 
    1221                 :      66785 :     struct iovec iov = { 0 };
    1222                 :      66785 :     iov.iov_len = size;
    1223                 :      66785 :     iov.iov_base = s2n_stuffer_raw_read(in, size);
    1224 [ -  + ][ #  # ]:      66785 :     RESULT_ENSURE_REF(iov.iov_base);
    1225         [ -  + ]:      66785 :     RESULT_GUARD_POSIX(s2n_stuffer_rewind_read(in, size));
    1226                 :            : 
    1227                 :      66785 :     uint32_t total_bytes_written = 0;
    1228         [ +  + ]:     124443 :     while (total_bytes_written < size) {
    1229                 :      68410 :         int bytes_written = s2n_record_writev(conn, content_type, &iov, 1,
    1230                 :      68410 :                 total_bytes_written, size - total_bytes_written);
    1231         [ -  + ]:      68410 :         RESULT_GUARD_POSIX(bytes_written);
    1232                 :      68410 :         total_bytes_written += bytes_written;
    1233         [ -  + ]:      68410 :         RESULT_GUARD_POSIX(s2n_stuffer_skip_read(in, bytes_written));
    1234         [ +  + ]:      68410 :         RESULT_GUARD_POSIX(s2n_flush(conn, blocked));
    1235                 :      68410 :     }
    1236                 :      56033 :     return S2N_RESULT_OK;
    1237                 :      66785 : }
    1238                 :            : 
    1239                 :            : /* Writing is relatively straight forward, simply write each message out as a record,
    1240                 :            :  * we may fragment a message across multiple records, but we never coalesce multiple
    1241                 :            :  * messages into single records.
    1242                 :            :  * Precondition: secure outbound I/O has already been flushed
    1243                 :            :  */
    1244                 :            : static int s2n_handshake_write_io(struct s2n_connection *conn)
    1245                 :      65134 : {
    1246 [ +  + ][ +  + ]:      65134 :     uint8_t record_type = EXPECTED_RECORD_TYPE(conn);
    1247                 :      65134 :     s2n_blocked_status blocked = S2N_NOT_BLOCKED;
    1248                 :            : 
    1249                 :            :     /* Populate handshake.io with header/payload for the current state, once.
    1250                 :            :      * Check wiped instead of s2n_stuffer_data_available to differentiate between the initial call
    1251                 :            :      * to s2n_handshake_write_io and a repeated call after an EWOULDBLOCK.
    1252                 :            :      */
    1253         [ +  + ]:      65134 :     if (s2n_stuffer_is_wiped(&conn->handshake.io)) {
    1254         [ +  + ]:      55355 :         if (record_type == TLS_HANDSHAKE) {
    1255 [ -  + ][ +  + ]:      44304 :             POSIX_GUARD(s2n_handshake_write_header(&conn->handshake.io, ACTIVE_STATE(conn).message_type));
                 [ +  + ]
    1256                 :      44304 :         }
    1257 [ +  + ][ +  + ]:      55355 :         POSIX_GUARD(ACTIVE_STATE(conn).handler[conn->mode](conn));
                 [ +  + ]
    1258         [ +  + ]:      55245 :         if (record_type == TLS_HANDSHAKE) {
    1259         [ -  + ]:      44194 :             POSIX_GUARD(s2n_handshake_finish_header(&conn->handshake.io));
    1260                 :      44194 :         }
    1261                 :      55245 :     }
    1262                 :            : 
    1263         [ +  + ]:      65024 :     POSIX_GUARD_RESULT(s2n_handshake_message_send(conn, record_type, &blocked));
    1264         [ +  + ]:      55307 :     if (record_type == TLS_HANDSHAKE) {
    1265         [ -  + ]:      44256 :         POSIX_GUARD_RESULT(s2n_handshake_transcript_update(conn));
    1266                 :      44256 :     }
    1267                 :            : 
    1268                 :            :     /* We're done sending the last record, reset everything */
    1269         [ -  + ]:      55307 :     POSIX_GUARD(s2n_stuffer_wipe(&conn->out));
    1270         [ -  + ]:      55307 :     POSIX_GUARD(s2n_stuffer_wipe(&conn->handshake.io));
    1271                 :            : 
    1272                 :            :     /* Update the secrets, if necessary */
    1273         [ -  + ]:      55307 :     POSIX_GUARD_RESULT(s2n_tls13_secrets_update(conn));
    1274         [ -  + ]:      55307 :     POSIX_GUARD_RESULT(s2n_tls13_key_schedule_update(conn));
    1275                 :            : 
    1276                 :            :     /* Advance the state machine */
    1277         [ -  + ]:      55307 :     POSIX_GUARD(s2n_advance_message(conn));
    1278                 :            : 
    1279                 :      55307 :     return S2N_SUCCESS;
    1280                 :      55307 : }
    1281                 :            : 
    1282                 :            : /*
    1283                 :            :  * Returns:
    1284                 :            :  *  1  - more data is needed to complete the handshake message.
    1285                 :            :  *  0  - we read the whole handshake message.
    1286                 :            :  * -1  - error processing the handshake message.
    1287                 :            :  */
    1288                 :            : static int s2n_read_full_handshake_message(struct s2n_connection *conn, uint8_t *message_type)
    1289                 :      50822 : {
    1290                 :      50822 :     uint32_t current_handshake_data = s2n_stuffer_data_available(&conn->handshake.io);
    1291         [ +  + ]:      50822 :     if (current_handshake_data < TLS_HANDSHAKE_HEADER_LENGTH) {
    1292                 :            :         /* The message may be so badly fragmented that we don't even read the full header, take
    1293                 :            :          * what we can and then continue to the next record read iteration.
    1294                 :            :          */
    1295         [ +  + ]:      40849 :         if (s2n_stuffer_data_available(&conn->in) < (TLS_HANDSHAKE_HEADER_LENGTH - current_handshake_data)) {
    1296         [ -  + ]:        116 :             POSIX_GUARD(s2n_stuffer_copy(&conn->in, &conn->handshake.io, s2n_stuffer_data_available(&conn->in)));
    1297                 :        116 :             return 1;
    1298                 :        116 :         }
    1299                 :            : 
    1300                 :            :         /* Get the remainder of the header */
    1301         [ -  + ]:      40733 :         POSIX_GUARD(s2n_stuffer_copy(&conn->in, &conn->handshake.io, (TLS_HANDSHAKE_HEADER_LENGTH - current_handshake_data)));
    1302                 :      40733 :     }
    1303                 :            : 
    1304                 :      50706 :     uint32_t handshake_message_length = 0;
    1305         [ -  + ]:      50706 :     POSIX_GUARD_RESULT(s2n_handshake_parse_header(&conn->handshake.io, message_type, &handshake_message_length));
    1306                 :            : 
    1307 [ +  + ][ +  - ]:      50706 :     S2N_ERROR_IF(handshake_message_length > S2N_MAXIMUM_HANDSHAKE_MESSAGE_LENGTH, S2N_ERR_BAD_MESSAGE);
    1308                 :            : 
    1309                 :      50705 :     uint32_t bytes_to_take = handshake_message_length - s2n_stuffer_data_available(&conn->handshake.io);
    1310         [ +  + ]:      50705 :     bytes_to_take = S2N_MIN(bytes_to_take, s2n_stuffer_data_available(&conn->in));
    1311                 :            : 
    1312                 :            :     /* If the record is handshake data, add it to the handshake buffer */
    1313         [ -  + ]:      50705 :     POSIX_GUARD(s2n_stuffer_copy(&conn->in, &conn->handshake.io, bytes_to_take));
    1314                 :            : 
    1315                 :            :     /* If we have the whole handshake message, then success */
    1316         [ +  + ]:      50705 :     if (s2n_stuffer_data_available(&conn->handshake.io) == handshake_message_length) {
    1317                 :      40775 :         return 0;
    1318                 :      40775 :     }
    1319                 :            : 
    1320                 :            :     /* We don't have the whole message, so we'll need to go again */
    1321         [ -  + ]:       9930 :     POSIX_GUARD(s2n_stuffer_reread(&conn->handshake.io));
    1322                 :            : 
    1323                 :       9930 :     return 1;
    1324                 :       9930 : }
    1325                 :            : 
    1326                 :            : static int s2n_handshake_handle_sslv2(struct s2n_connection *conn)
    1327                 :          3 : {
    1328 [ -  + ][ -  + ]:          3 :     S2N_ERROR_IF(ACTIVE_MESSAGE(conn) != CLIENT_HELLO, S2N_ERR_BAD_MESSAGE);
                 [ #  # ]
    1329                 :            : 
    1330                 :            :     /* Add the message to our handshake hashes */
    1331                 :          3 :     struct s2n_blob hashed = { 0 };
    1332         [ -  + ]:          3 :     POSIX_GUARD(s2n_blob_init(&hashed, conn->header_in.blob.data + 2, 3));
    1333         [ -  + ]:          3 :     POSIX_GUARD(s2n_conn_update_handshake_hashes(conn, &hashed));
    1334                 :            : 
    1335                 :          3 :     hashed.data = conn->in.blob.data;
    1336                 :          3 :     hashed.size = s2n_stuffer_data_available(&conn->in);
    1337         [ -  + ]:          3 :     POSIX_GUARD(s2n_conn_update_handshake_hashes(conn, &hashed));
    1338                 :            : 
    1339                 :            :     /* Handle an SSLv2 client hello */
    1340         [ -  + ]:          3 :     POSIX_GUARD(s2n_stuffer_copy(&conn->in, &conn->handshake.io, s2n_stuffer_data_available(&conn->in)));
    1341                 :          3 :     conn->client_hello.sslv2 = true;
    1342                 :            :     /* Execute the state machine handler */
    1343 [ -  + ][ -  + ]:          3 :     int r = ACTIVE_STATE(conn).handler[conn->mode](conn);
    1344         [ -  + ]:          3 :     POSIX_GUARD(s2n_stuffer_wipe(&conn->handshake.io));
    1345                 :            : 
    1346                 :            :     /* We're done with the record, wipe it */
    1347         [ -  + ]:          3 :     POSIX_GUARD_RESULT(s2n_record_wipe(conn));
    1348                 :            : 
    1349 [ -  + ][ +  - ]:          3 :     WITH_ERROR_BLINDING(conn, POSIX_GUARD(r));
    1350                 :            : 
    1351                 :            :     /* Advance the state machine */
    1352         [ -  + ]:          3 :     POSIX_GUARD(s2n_advance_message(conn));
    1353                 :            : 
    1354                 :          3 :     return S2N_SUCCESS;
    1355                 :          3 : }
    1356                 :            : 
    1357                 :            : static int s2n_try_delete_session_cache(struct s2n_connection *conn)
    1358                 :       2521 : {
    1359 [ -  + ][ #  # ]:       2521 :     POSIX_ENSURE_REF(conn);
    1360                 :            : 
    1361         [ +  + ]:       2521 :     if (s2n_allowed_to_cache_connection(conn) > 0) {
    1362                 :          1 :         conn->config->cache_delete(conn, conn->config->cache_delete_data, conn->session_id, conn->session_id_len);
    1363                 :          1 :     }
    1364                 :            : 
    1365                 :       2521 :     return S2N_SUCCESS;
    1366                 :       2521 : }
    1367                 :            : 
    1368                 :            : static S2N_RESULT s2n_finish_read(struct s2n_connection *conn)
    1369                 :      40636 : {
    1370 [ #  # ][ -  + ]:      40636 :     RESULT_ENSURE_REF(conn);
    1371                 :            : 
    1372         [ -  + ]:      40636 :     RESULT_GUARD(s2n_handshake_transcript_update(conn));
    1373         [ -  + ]:      40636 :     RESULT_GUARD_POSIX(s2n_stuffer_wipe(&conn->handshake.io));
    1374         [ -  + ]:      40636 :     RESULT_GUARD(s2n_tls13_secrets_update(conn));
    1375         [ -  + ]:      40636 :     RESULT_GUARD(s2n_tls13_key_schedule_update(conn));
    1376         [ -  + ]:      40636 :     RESULT_GUARD_POSIX(s2n_advance_message(conn));
    1377                 :      40636 :     return S2N_RESULT_OK;
    1378                 :      40636 : }
    1379                 :            : 
    1380                 :            : static S2N_RESULT s2n_handshake_app_data_recv(struct s2n_connection *conn)
    1381                 :         89 : {
    1382         [ +  + ]:         89 :     if (conn->early_data_expected) {
    1383         [ -  + ]:         63 :         RESULT_GUARD(s2n_early_data_validate_recv(conn));
    1384         [ +  - ]:         63 :         RESULT_BAIL(S2N_ERR_EARLY_DATA_BLOCKED);
    1385                 :         63 :     }
    1386                 :            : 
    1387         [ +  + ]:         26 :     if (conn->handshake.renegotiation) {
    1388         [ -  + ]:         25 :         RESULT_GUARD(s2n_renegotiate_validate(conn));
    1389                 :            :         /* During renegotiation, Application Data may only be received until
    1390                 :            :          * the server acknowledges the new handshake with a ServerHello.
    1391                 :            :          */
    1392 [ +  + ][ +  - ]:         25 :         RESULT_ENSURE(ACTIVE_MESSAGE(conn) == SERVER_HELLO, S2N_ERR_BAD_MESSAGE);
                 [ -  + ]
    1393         [ +  - ]:         20 :         RESULT_BAIL(S2N_ERR_APP_DATA_BLOCKED);
    1394                 :         20 :     }
    1395                 :            : 
    1396         [ +  - ]:          1 :     RESULT_BAIL(S2N_ERR_BAD_MESSAGE);
    1397                 :          1 : }
    1398                 :            : 
    1399                 :            : static int s2n_handshake_message_process(struct s2n_connection *conn, uint8_t record_type)
    1400                 :      50889 : {
    1401 [ -  + ][ #  # ]:      50889 :     POSIX_ENSURE_REF(conn);
    1402                 :            : 
    1403                 :      50889 :     uint8_t message_type = 0;
    1404         [ +  + ]:      91459 :     while (s2n_stuffer_data_available(&conn->in)) {
    1405                 :            :         /* We're done with negotiating but we have trailing data in this record. Bail on the handshake. */
    1406 [ +  + ][ +  + ]:      50822 :         S2N_ERROR_IF(EXPECTED_RECORD_TYPE(conn) == TLS_APPLICATION_DATA, S2N_ERR_BAD_MESSAGE);
         [ -  + ][ #  # ]
    1407                 :      50822 :         int r = 0;
    1408         [ +  + ]:      50822 :         POSIX_GUARD((r = s2n_read_full_handshake_message(conn, &message_type)));
    1409                 :            : 
    1410                 :            :         /* Do we need more data? This happens for message fragmentation */
    1411         [ +  + ]:      50821 :         if (r == 1) {
    1412                 :            :             /* Break out of this inner loop, but since we're not changing the state, the
    1413                 :            :              * outer loop in s2n_handshake_io() will read another record.
    1414                 :            :              */
    1415         [ -  + ]:      10046 :             POSIX_GUARD_RESULT(s2n_record_wipe(conn));
    1416                 :      10046 :             return S2N_SUCCESS;
    1417                 :      10046 :         }
    1418                 :            : 
    1419         [ +  + ]:      40775 :         if (conn->mode == S2N_CLIENT) {
    1420                 :      26309 :             s2n_cert_auth_type client_cert_auth_type = { 0 };
    1421         [ -  + ]:      26309 :             POSIX_GUARD(s2n_connection_get_client_auth_type(conn, &client_cert_auth_type));
    1422                 :            :             /* If client auth is optional, we initially assume it will not be requested.
    1423                 :            :              * If we received a request, switch to a client auth handshake.
    1424                 :            :              */
    1425 [ +  + ][ +  + ]:      26309 :             if (client_cert_auth_type != S2N_CERT_AUTH_REQUIRED && message_type == TLS_CERT_REQ) {
    1426 [ +  - ][ +  + ]:        101 :                 POSIX_ENSURE(client_cert_auth_type == S2N_CERT_AUTH_OPTIONAL, S2N_ERR_UNEXPECTED_CERT_REQUEST);
    1427 [ -  + ][ #  # ]:         93 :                 POSIX_ENSURE(IS_FULL_HANDSHAKE(conn), S2N_ERR_HANDSHAKE_STATE);
    1428         [ -  + ]:         93 :                 POSIX_GUARD_RESULT(s2n_handshake_type_set_flag(conn, CLIENT_AUTH));
    1429                 :         93 :             }
    1430                 :            : 
    1431                 :            :             /* According to rfc6066 section 8, the server may choose not to send a "CertificateStatus"
    1432                 :            :              * message even if it has sent a "status_request" extension in the ServerHello message.
    1433                 :            :              */
    1434 [ +  + ][ +  + ]:      26301 :             if (EXPECTED_MESSAGE_TYPE(conn) == TLS_SERVER_CERT_STATUS
                 [ +  + ]
    1435         [ -  + ]:      26301 :                     && message_type != TLS_SERVER_CERT_STATUS) {
    1436         [ #  # ]:          0 :                 POSIX_GUARD_RESULT(s2n_handshake_type_unset_tls12_flag(conn, OCSP_STATUS));
    1437                 :          0 :             }
    1438                 :      26301 :         }
    1439                 :            : 
    1440                 :            :         /*
    1441                 :            :          *= https://www.rfc-editor.org/rfc/rfc5246#section-7.4
    1442                 :            :          *# The one message that is not bound by these ordering rules
    1443                 :            :          *# is the HelloRequest message, which can be sent at any time, but which
    1444                 :            :          *# SHOULD be ignored by the client if it arrives in the middle of a handshake.
    1445                 :            :          */
    1446         [ +  + ]:      40767 :         if (message_type == TLS_HELLO_REQUEST) {
    1447         [ +  + ]:          3 :             POSIX_GUARD_RESULT(s2n_client_hello_request_validate(conn));
    1448         [ -  + ]:          2 :             POSIX_GUARD(s2n_stuffer_wipe(&conn->handshake.io));
    1449                 :          2 :             continue;
    1450                 :          2 :         }
    1451                 :            : 
    1452                 :            :         /* Check for missing Certificate Requests to surface a more specific error */
    1453 [ +  + ][ +  + ]:      40764 :         if (EXPECTED_MESSAGE_TYPE(conn) == TLS_CERT_REQ) {
                 [ +  + ]
    1454 [ -  + ][ #  # ]:        188 :             POSIX_ENSURE(message_type == TLS_CERT_REQ,
    1455                 :        188 :                     S2N_ERR_MISSING_CERT_REQUEST);
    1456                 :        188 :         }
    1457                 :            : 
    1458 [ -  + ][ #  # ]:      40764 :         POSIX_ENSURE(record_type == EXPECTED_RECORD_TYPE(conn), S2N_ERR_BAD_MESSAGE);
         [ +  + ][ +  + ]
    1459 [ +  + ][ +  - ]:      40764 :         POSIX_ENSURE(message_type == EXPECTED_MESSAGE_TYPE(conn), S2N_ERR_BAD_MESSAGE);
         [ +  + ][ +  + ]
    1460 [ #  # ][ -  + ]:      40761 :         POSIX_ENSURE(!CONNECTION_IS_WRITER(conn), S2N_ERR_BAD_MESSAGE);
         [ +  + ][ +  + ]
                 [ +  + ]
    1461                 :            : 
    1462                 :            :         /* Call the relevant handler */
    1463 [ +  + ][ +  + ]:      40761 :         WITH_ERROR_BLINDING(conn, POSIX_GUARD(ACTIVE_STATE(conn).handler[conn->mode](conn)));
         [ +  + ][ +  - ]
    1464                 :            : 
    1465                 :            :         /* Advance the state machine */
    1466         [ -  + ]:      40568 :         POSIX_GUARD_RESULT(s2n_finish_read(conn));
    1467                 :      40568 :     }
    1468                 :            : 
    1469                 :            :     /* We're done with the record, wipe it */
    1470         [ -  + ]:      40637 :     POSIX_GUARD_RESULT(s2n_record_wipe(conn));
    1471                 :            : 
    1472                 :      40637 :     return S2N_SUCCESS;
    1473                 :      40637 : }
    1474                 :            : 
    1475                 :            : /* Reading is a little more complicated than writing as the TLS RFCs allow content
    1476                 :            :  * types to be interleaved at the record layer. We may get an alert message
    1477                 :            :  * during the handshake phase, or messages of types that we don't support (e.g.
    1478                 :            :  * HEARTBEAT messages), or during renegotiations we may even get application
    1479                 :            :  * data messages that need to be handled by the application.
    1480                 :            :  */
    1481                 :            : static int s2n_handshake_read_io(struct s2n_connection *conn)
    1482                 :     177348 : {
    1483                 :     177348 :     uint8_t record_type = 0;
    1484                 :     177348 :     int isSSLv2 = 0;
    1485                 :            : 
    1486                 :            :     /* Fill conn->in stuffer necessary for the handshake.
    1487                 :            :      * If using TCP, read a record. If using QUIC, read a message. */
    1488         [ +  + ]:     177348 :     if (s2n_connection_is_quic_enabled(conn)) {
    1489                 :         62 :         record_type = TLS_HANDSHAKE;
    1490                 :         62 :         uint8_t message_type = 0;
    1491         [ +  + ]:         62 :         POSIX_GUARD_RESULT(s2n_quic_read_handshake_message(conn, &message_type));
    1492                 :     177286 :     } else {
    1493                 :     177286 :         int r = s2n_read_full_record(conn, &record_type, &isSSLv2);
    1494                 :            : 
    1495                 :            :         /**
    1496                 :            :          *= https://www.rfc-editor.org/rfc/rfc8446#section-4.2.10
    1497                 :            :          *# If the client attempts a 0-RTT handshake but the server
    1498                 :            :          *# rejects it, the server will generally not have the 0-RTT record
    1499                 :            :          *# protection keys and must instead use trial decryption (either with
    1500                 :            :          *# the 1-RTT handshake keys or by looking for a cleartext ClientHello in
    1501                 :            :          *# the case of a HelloRetryRequest) to find the first non-0-RTT message.
    1502                 :            :          *#
    1503                 :            :          *# If the server chooses to accept the "early_data" extension, then it
    1504                 :            :          *# MUST comply with the same error-handling requirements specified for
    1505                 :            :          *# all records when processing early data records.  Specifically, if the
    1506                 :            :          *# server fails to decrypt a 0-RTT record following an accepted
    1507                 :            :          *# "early_data" extension, it MUST terminate the connection with a
    1508                 :            :          *# "bad_record_mac" alert as per Section 5.2.
    1509                 :            :          */
    1510 [ +  + ][ +  + ]:     177286 :         if ((r < S2N_SUCCESS) && (s2n_errno == S2N_ERR_EARLY_DATA_TRIAL_DECRYPT)) {
    1511         [ -  + ]:        505 :             POSIX_GUARD(s2n_stuffer_reread(&conn->in));
    1512         [ +  + ]:        505 :             POSIX_GUARD_RESULT(s2n_early_data_record_bytes(conn, s2n_stuffer_data_available(&conn->in)));
    1513         [ -  + ]:        504 :             POSIX_GUARD_RESULT(s2n_record_wipe(conn));
    1514                 :        504 :             return S2N_SUCCESS;
    1515                 :        504 :         }
    1516         [ +  + ]:     176781 :         POSIX_GUARD(r);
    1517                 :     176781 :     }
    1518                 :            : 
    1519         [ +  + ]:      63425 :     if (isSSLv2) {
    1520 [ -  + ][ #  # ]:          3 :         S2N_ERROR_IF(record_type != SSLv2_CLIENT_HELLO, S2N_ERR_BAD_MESSAGE);
    1521         [ -  + ]:          3 :         POSIX_GUARD(s2n_handshake_handle_sslv2(conn));
    1522                 :          3 :     }
    1523                 :            : 
    1524                 :            :     /* Now we have a record, but it could be a partial fragment of a message, or it might
    1525                 :            :      * contain several messages.
    1526                 :            :      */
    1527                 :            : 
    1528         [ +  + ]:      63425 :     if (record_type == TLS_APPLICATION_DATA) {
    1529         [ +  - ]:         89 :         POSIX_GUARD_RESULT(s2n_handshake_app_data_recv(conn));
    1530         [ +  + ]:      63336 :     } else if (record_type == TLS_CHANGE_CIPHER_SPEC) {
    1531                 :            :         /* TLS1.3 can receive unexpected CCS messages at any point in the handshake
    1532                 :            :          * due to a peer operating in middlebox compatibility mode.
    1533                 :            :          * However, when operating in QUIC mode, S2N should not accept ANY CCS messages,
    1534                 :            :          * including these unexpected ones.*/
    1535 [ +  + ][ -  + ]:      10998 :         if (!IS_TLS13_HANDSHAKE(conn) || s2n_connection_is_quic_enabled(conn)) {
    1536 [ -  + ][ #  # ]:       3598 :             POSIX_ENSURE(EXPECTED_RECORD_TYPE(conn) == TLS_CHANGE_CIPHER_SPEC, S2N_ERR_BAD_MESSAGE);
         [ -  + ][ -  + ]
    1537 [ -  + ][ #  # ]:       3598 :             POSIX_ENSURE(!CONNECTION_IS_WRITER(conn), S2N_ERR_BAD_MESSAGE);
         [ +  + ][ -  + ]
                 [ -  + ]
    1538                 :       3598 :         }
    1539                 :            : 
    1540 [ -  + ][ #  # ]:      10998 :         S2N_ERROR_IF(s2n_stuffer_data_available(&conn->in) != 1, S2N_ERR_BAD_MESSAGE);
    1541                 :            : 
    1542         [ -  + ]:      10998 :         POSIX_GUARD(s2n_stuffer_copy(&conn->in, &conn->handshake.io, s2n_stuffer_data_available(&conn->in)));
    1543 [ -  + ][ +  + ]:      10998 :         POSIX_GUARD(CCS_STATE(conn).handler[conn->mode](conn));
         [ +  + ][ +  + ]
    1544         [ -  + ]:      10998 :         POSIX_GUARD(s2n_stuffer_wipe(&conn->handshake.io));
    1545                 :            : 
    1546                 :            :         /* We're done with the record, wipe it */
    1547         [ -  + ]:      10998 :         POSIX_GUARD_RESULT(s2n_record_wipe(conn));
    1548                 :            : 
    1549                 :            :         /* Advance the state machine if this was an expected message */
    1550 [ +  + ][ +  + ]:      10998 :         if (EXPECTED_RECORD_TYPE(conn) == TLS_CHANGE_CIPHER_SPEC && !CONNECTION_IS_WRITER(conn)) {
         [ -  + ][ -  + ]
         [ +  + ][ +  + ]
                 [ +  - ]
    1551         [ -  + ]:       3598 :             POSIX_GUARD(s2n_advance_message(conn));
    1552                 :       3598 :         }
    1553                 :            : 
    1554                 :      10998 :         return S2N_SUCCESS;
    1555         [ +  + ]:      52338 :     } else if (record_type != TLS_HANDSHAKE) {
    1556         [ +  + ]:       1517 :         if (record_type == TLS_ALERT) {
    1557         [ +  + ]:       1513 :             POSIX_GUARD(s2n_process_alert_fragment(conn));
    1558                 :       1513 :         }
    1559                 :            : 
    1560                 :            :         /* Ignore record types that we don't support */
    1561                 :            : 
    1562                 :            :         /* We're done with the record, wipe it */
    1563         [ -  + ]:         10 :         POSIX_GUARD_RESULT(s2n_record_wipe(conn));
    1564                 :         10 :         return S2N_SUCCESS;
    1565                 :         10 :     }
    1566                 :            : 
    1567                 :            :     /* Record is a handshake message */
    1568 [ -  + ][ #  # ]:      50821 :     S2N_ERROR_IF(s2n_stuffer_data_available(&conn->in) == 0, S2N_ERR_BAD_MESSAGE);
    1569         [ +  + ]:      50821 :     POSIX_GUARD(s2n_handshake_message_process(conn, record_type));
    1570                 :            : 
    1571                 :      50615 :     return S2N_SUCCESS;
    1572                 :      50821 : }
    1573                 :            : 
    1574                 :            : static int s2n_handle_retry_state(struct s2n_connection *conn)
    1575                 :        249 : {
    1576                 :            :     /* If we were blocked reading or writing a record, then the handler is waiting on
    1577                 :            :      * external data. The handler will know how to continue, so we should call the
    1578                 :            :      * handler right away. We aren't going to read more handshake data yet or proceed
    1579                 :            :      * to the next handler because the current message has not finished processing. */
    1580                 :        249 :     s2n_errno = S2N_ERR_OK;
    1581 [ +  + ][ +  + ]:        249 :     const int r = ACTIVE_STATE(conn).handler[conn->mode](conn);
    1582                 :            : 
    1583 [ +  + ][ +  + ]:        249 :     if (r < S2N_SUCCESS && S2N_ERROR_IS_BLOCKING(s2n_errno)) {
    1584                 :            :         /* If the handler is still waiting for data, return control to the caller. */
    1585                 :        109 :         S2N_ERROR_PRESERVE_ERRNO();
    1586                 :        109 :     }
    1587                 :            : 
    1588                 :            :     /* Resume the handshake */
    1589                 :        140 :     conn->handshake.paused = false;
    1590                 :            : 
    1591 [ +  + ][ +  + ]:        140 :     if (CONNECTION_IS_WRITER(conn)) {
         [ +  + ][ +  + ]
    1592         [ -  + ]:         67 :         POSIX_GUARD(r);
    1593                 :            : 
    1594                 :            :         /* If we're the writer and handler just finished, update the record header if
    1595                 :            :          * needed and let the s2n_handshake_write_io write the data to the socket */
    1596 [ +  - ][ +  + ]:         67 :         if (EXPECTED_RECORD_TYPE(conn) == TLS_HANDSHAKE) {
                 [ +  + ]
    1597         [ -  + ]:         67 :             POSIX_GUARD(s2n_handshake_finish_header(&conn->handshake.io));
    1598                 :         67 :         }
    1599                 :         73 :     } else {
    1600 [ +  + ][ +  - ]:         73 :         if (r < S2N_SUCCESS && conn->session_id_len) {
    1601                 :          5 :             s2n_try_delete_session_cache(conn);
    1602                 :          5 :         }
    1603 [ +  + ][ +  - ]:         73 :         WITH_ERROR_BLINDING(conn, POSIX_GUARD(r));
    1604                 :            : 
    1605                 :            :         /* The read handler processed the message successfully, we are done with this
    1606                 :            :          * message. Advance the state machine. */
    1607         [ -  + ]:         68 :         POSIX_GUARD_RESULT(s2n_finish_read(conn));
    1608                 :            : 
    1609                 :            :         /* We may need to handle remaining handshake messages in the record */
    1610         [ -  + ]:         68 :         POSIX_GUARD(s2n_handshake_message_process(conn, TLS_HANDSHAKE));
    1611                 :         68 :     }
    1612                 :            : 
    1613                 :        135 :     return S2N_SUCCESS;
    1614                 :        140 : }
    1615                 :            : 
    1616                 :            : static S2N_RESULT s2n_set_blocked_error_from_errno(struct s2n_connection *conn, s2n_blocked_status *blocked)
    1617                 :     125150 : {
    1618 [ -  + ][ #  # ]:     125150 :     RESULT_ENSURE_REF(conn);
    1619 [ #  # ][ -  + ]:     125150 :     RESULT_ENSURE_REF(blocked);
    1620                 :            : 
    1621         [ +  + ]:     125150 :     if (s2n_errno == S2N_ERR_ASYNC_BLOCKED) {
    1622                 :        253 :         *blocked = S2N_BLOCKED_ON_APPLICATION_INPUT;
    1623                 :        253 :         conn->handshake.paused = true;
    1624         [ +  + ]:     124897 :     } else if (s2n_errno == S2N_ERR_EARLY_DATA_BLOCKED) {
    1625                 :        103 :         *blocked = S2N_BLOCKED_ON_EARLY_DATA;
    1626                 :        103 :     }
    1627                 :            : 
    1628                 :     125150 :     return S2N_RESULT_OK;
    1629                 :     125150 : }
    1630                 :            : 
    1631                 :            : bool s2n_handshake_is_complete(struct s2n_connection *conn)
    1632                 :     287748 : {
    1633                 :            :     /* A deserialized connection implies that the handshake is complete because
    1634                 :            :      * connections cannot be serialized before completing the handshake. */
    1635 [ +  - ][ +  + ]:     287748 :     return conn && (ACTIVE_STATE(conn).writer == 'B' || conn->deserialized_conn);
         [ +  + ][ +  + ]
                 [ +  + ]
    1636                 :     287748 : }
    1637                 :            : 
    1638                 :            : int s2n_negotiate_impl(struct s2n_connection *conn, s2n_blocked_status *blocked)
    1639                 :     162480 : {
    1640 [ -  + ][ #  # ]:     162480 :     POSIX_ENSURE_REF(conn);
    1641 [ +  + ][ +  - ]:     162480 :     POSIX_ENSURE_REF(blocked);
    1642                 :            : 
    1643 [ +  + ][ +  + ]:     281335 :     while (!s2n_handshake_is_complete(conn) && ACTIVE_MESSAGE(conn) != conn->handshake.end_of_messages) {
                 [ +  + ]
    1644                 :     265207 :         errno = 0;
    1645                 :     265207 :         s2n_errno = S2N_ERR_OK;
    1646                 :            : 
    1647                 :            :         /* Flush any pending I/O or alert messages */
    1648         [ +  + ]:     265207 :         POSIX_GUARD(s2n_flush(conn, blocked));
    1649                 :            : 
    1650 [ +  + ][ +  - ]:     245754 :         POSIX_ENSURE(s2n_connection_check_io_status(conn, S2N_IO_FULL_DUPLEX), S2N_ERR_CLOSED);
    1651                 :            : 
    1652                 :            :         /* If the handshake was paused, retry the current message */
    1653         [ +  + ]:     244250 :         if (conn->handshake.paused) {
    1654                 :        275 :             *blocked = S2N_BLOCKED_ON_APPLICATION_INPUT;
    1655                 :        275 :             const int retry_result = s2n_handle_retry_state(conn);
    1656         [ +  + ]:        275 :             if (retry_result != S2N_SUCCESS) {
    1657         [ -  + ]:        137 :                 POSIX_GUARD_RESULT(s2n_set_blocked_error_from_errno(conn, blocked));
    1658                 :        137 :                 S2N_ERROR_PRESERVE_ERRNO();
    1659                 :        137 :             }
    1660                 :            : 
    1661                 :        138 :             continue;
    1662                 :        275 :         }
    1663                 :            : 
    1664 [ +  + ][ +  + ]:     243975 :         if (CONNECTION_IS_WRITER(conn)) {
         [ +  + ][ +  + ]
    1665                 :      65812 :             *blocked = S2N_BLOCKED_ON_WRITE;
    1666                 :      65812 :             const int write_result = s2n_handshake_write_io(conn);
    1667                 :            : 
    1668         [ +  + ]:      65812 :             if (write_result < S2N_SUCCESS) {
    1669         [ +  + ]:       9834 :                 if (!S2N_ERROR_IS_BLOCKING(s2n_errno)) {
    1670                 :            :                     /* Non-retryable write error. The peer might have sent an alert. Try and read it. */
    1671                 :         11 :                     const int write_errno = errno;
    1672                 :         11 :                     const int write_s2n_errno = s2n_errno;
    1673                 :         11 :                     struct s2n_debug_info write_s2n_debug_info = _s2n_debug_info;
    1674                 :            : 
    1675 [ +  - ][ +  + ]:         11 :                     if (s2n_handshake_read_io(conn) < 0 && s2n_errno == S2N_ERR_ALERT) {
    1676                 :            :                         /* s2n_handshake_read_io has set s2n_errno */
    1677                 :          1 :                         S2N_ERROR_PRESERVE_ERRNO();
    1678                 :         10 :                     } else {
    1679                 :            :                         /* Let the write error take precedence if we didn't read an alert. */
    1680                 :         10 :                         errno = write_errno;
    1681                 :         10 :                         s2n_errno = write_s2n_errno;
    1682                 :         10 :                         _s2n_debug_info = write_s2n_debug_info;
    1683                 :         10 :                         S2N_ERROR_PRESERVE_ERRNO();
    1684                 :         10 :                     }
    1685                 :         11 :                 }
    1686                 :            : 
    1687         [ -  + ]:       9823 :                 POSIX_GUARD_RESULT(s2n_set_blocked_error_from_errno(conn, blocked));
    1688                 :            : 
    1689                 :       9823 :                 S2N_ERROR_PRESERVE_ERRNO();
    1690                 :       9823 :             }
    1691                 :     178163 :         } else {
    1692                 :     178163 :             *blocked = S2N_BLOCKED_ON_READ;
    1693                 :     178163 :             const int read_result = s2n_handshake_read_io(conn);
    1694                 :            : 
    1695         [ +  + ]:     178163 :             if (read_result < S2N_SUCCESS) {
    1696                 :            :                 /* One blocking condition is waiting on the session resumption cache. */
    1697                 :            :                 /* So we don't want to delete anything if we are blocked. */
    1698 [ +  + ][ +  + ]:     115423 :                 if (!S2N_ERROR_IS_BLOCKING(s2n_errno) && conn->session_id_len) {
    1699                 :       2538 :                     s2n_try_delete_session_cache(conn);
    1700                 :       2538 :                 }
    1701                 :            : 
    1702         [ -  + ]:     115423 :                 POSIX_GUARD_RESULT(s2n_set_blocked_error_from_errno(conn, blocked));
    1703                 :            : 
    1704                 :     115423 :                 S2N_ERROR_PRESERVE_ERRNO();
    1705                 :     115423 :             }
    1706                 :     178163 :         }
    1707                 :     243975 :     }
    1708                 :            : 
    1709 [ +  + ][ +  + ]:      16128 :     if (ACTIVE_STATE(conn).writer == 'B') {
                 [ +  + ]
    1710                 :            :         /* Clean up handshake secrets */
    1711         [ -  + ]:      10791 :         POSIX_GUARD_RESULT(s2n_tls13_secrets_clean(conn));
    1712                 :            : 
    1713                 :            :         /* Send any pending post-handshake messages */
    1714         [ -  + ]:      10791 :         POSIX_GUARD(s2n_post_handshake_send(conn, blocked));
    1715                 :            : 
    1716                 :            :         /* If the handshake has just ended, free up memory */
    1717         [ -  + ]:      10791 :         POSIX_GUARD(s2n_stuffer_resize(&conn->handshake.io, 0));
    1718                 :      10791 :     }
    1719                 :            : 
    1720                 :      16128 :     *blocked = S2N_NOT_BLOCKED;
    1721                 :            : 
    1722                 :      16128 :     return S2N_SUCCESS;
    1723                 :      16128 : }
    1724                 :            : 
    1725                 :            : int s2n_negotiate(struct s2n_connection *conn, s2n_blocked_status *blocked)
    1726                 :     162482 : {
    1727 [ +  + ][ +  - ]:     162482 :     POSIX_ENSURE_REF(conn);
    1728 [ +  + ][ +  - ]:     162481 :     POSIX_ENSURE(!conn->negotiate_in_use, S2N_ERR_REENTRANCY);
    1729                 :     162480 :     conn->negotiate_in_use = true;
    1730                 :            : 
    1731                 :            :     /* We use the default monotonic clock so that we can avoid referencing any
    1732                 :            :      * item on the config until after the client hello callback is invoked. */
    1733                 :     162480 :     uint64_t negotiate_start = 0;
    1734         [ -  + ]:     162480 :     POSIX_GUARD(s2n_default_monotonic_clock(NULL, &negotiate_start));
    1735         [ +  + ]:     162480 :     if (conn->handshake_event.handshake_start_ns == 0) {
    1736                 :      13989 :         conn->handshake_event.handshake_start_ns = negotiate_start;
    1737                 :      13989 :     }
    1738                 :            : 
    1739                 :     162480 :     int result = s2n_negotiate_impl(conn, blocked);
    1740                 :            : 
    1741                 :            :     /* finish up sending and receiving */
    1742         [ -  + ]:     162480 :     POSIX_GUARD_RESULT(s2n_connection_dynamic_free_in_buffer(conn));
    1743         [ -  + ]:     162480 :     POSIX_GUARD_RESULT(s2n_connection_dynamic_free_out_buffer(conn));
    1744                 :            : 
    1745                 :     162480 :     uint64_t negotiate_end = 0;
    1746         [ -  + ]:     162480 :     POSIX_GUARD(s2n_default_monotonic_clock(NULL, &negotiate_end));
    1747                 :     162480 :     conn->handshake_event.handshake_time_ns += negotiate_end - negotiate_start;
    1748                 :            : 
    1749         [ +  + ]:     162480 :     if (result == S2N_SUCCESS) {
    1750                 :      16128 :         conn->handshake_event.handshake_end_ns = negotiate_end;
    1751         [ -  + ]:      16128 :         POSIX_GUARD_RESULT(s2n_event_handshake_populate(conn, &conn->handshake_event));
    1752         [ -  + ]:      16128 :         POSIX_GUARD_RESULT(s2n_event_handshake_send(conn, &conn->handshake_event));
    1753 [ +  + ][ +  + ]:     146352 :     } else if (s2n_error_get_type(s2n_errno) != S2N_ERR_T_BLOCKED && conn->config) {
    1754                 :            :         /* S2N_ERR_T_BLOCKED is the only retryable error type -- it indicates
    1755                 :            :          * the handshake is still in progress but IO would block. All other
    1756                 :            :          * error types are terminal failures, so we emit the failure event. */
    1757                 :       4089 :         conn->handshake_event.handshake_end_ns = negotiate_end;
    1758                 :       4089 :         conn->handshake_event.error_code = s2n_errno;
    1759                 :            :         /* Save and restore error state because populate calls functions
    1760                 :            :          * that may overwrite them (e.g. s2n_connection_get_key_exchange_group). */
    1761                 :       4089 :         int saved_errno = s2n_errno;
    1762                 :       4089 :         struct s2n_debug_info saved_debug_info = _s2n_debug_info;
    1763         [ -  + ]:       4089 :         POSIX_GUARD_RESULT(s2n_event_handshake_populate(conn, &conn->handshake_event));
    1764         [ -  + ]:       4089 :         POSIX_GUARD_RESULT(s2n_event_handshake_send(conn, &conn->handshake_event));
    1765                 :       4089 :         s2n_errno = saved_errno;
    1766                 :       4089 :         _s2n_debug_info = saved_debug_info;
    1767                 :       4089 :     }
    1768                 :            : 
    1769                 :     162480 :     conn->negotiate_in_use = false;
    1770                 :     162480 :     return result;
    1771                 :     162480 : }

Generated by: LCOV version 1.14