LCOV - code coverage report
Current view: top level - tls - s2n_handshake_io.c (source / functions) Hit Total Coverage
Test: unit_test_coverage.info Lines: 509 517 98.5 %
Date: 2025-08-15 07:28:39 Functions: 25 27 92.6 %
Branches: 545 772 70.6 %

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

Generated by: LCOV version 1.14