aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/restricted/aws/s2n/tls/s2n_handshake.h
blob: 6ff1664cf48ef08a5662e161d6f1839e9201e6bf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

#pragma once

#include <stdint.h>

#include "api/s2n.h"
#include "crypto/s2n_certificate.h"
#include "crypto/s2n_hash.h"
#include "stuffer/s2n_stuffer.h"
#include "tls/s2n_crypto.h"
#include "tls/s2n_handshake_hashes.h"
#include "tls/s2n_handshake_type.h"
#include "tls/s2n_signature_algorithms.h"
#include "tls/s2n_tls_parameters.h"

/* From RFC 8446: https://tools.ietf.org/html/rfc8446#appendix-B.3 */
#define TLS_HELLO_REQUEST             0
#define TLS_CLIENT_HELLO              1
#define TLS_SERVER_HELLO              2
#define TLS_SERVER_NEW_SESSION_TICKET 4
#define TLS_END_OF_EARLY_DATA         5
#define TLS_ENCRYPTED_EXTENSIONS      8
#define TLS_CERTIFICATE               11
#define TLS_SERVER_KEY                12
#define TLS_CERT_REQ                  13
#define TLS_SERVER_HELLO_DONE         14
#define TLS_CERT_VERIFY               15
#define TLS_CLIENT_KEY                16
#define TLS_FINISHED                  20
#define TLS_SERVER_CERT_STATUS        22
#define TLS_SERVER_SESSION_LOOKUP     23
#define TLS_KEY_UPDATE                24
#define TLS_NPN                       67
#define TLS_MESSAGE_HASH              254

/* This is the list of message types that we support */
typedef enum {
    CLIENT_HELLO = 0,
    SERVER_HELLO,
    SERVER_CERT,
    SERVER_NEW_SESSION_TICKET,
    SERVER_CERT_STATUS,
    SERVER_KEY,
    SERVER_CERT_REQ,
    SERVER_HELLO_DONE,
    CLIENT_CERT,
    CLIENT_KEY,
    CLIENT_CERT_VERIFY,
    CLIENT_CHANGE_CIPHER_SPEC,
    /* Not a standardized message. Defined: https://datatracker.ietf.org/doc/html/draft-agl-tls-nextprotoneg-04 */
    CLIENT_NPN,
    CLIENT_FINISHED,
    SERVER_CHANGE_CIPHER_SPEC,
    SERVER_FINISHED,

    /* TLS1.3 message types. Defined: https://tools.ietf.org/html/rfc8446#appendix-B.3 */
    ENCRYPTED_EXTENSIONS,
    SERVER_CERT_VERIFY,
    HELLO_RETRY_MSG,
    END_OF_EARLY_DATA,

    APPLICATION_DATA,
} message_type_t;

typedef enum {
    S2N_ASYNC_NOT_INVOKED = 0,
    S2N_ASYNC_INVOKED,
    S2N_ASYNC_COMPLETE,
} s2n_async_state;

/* Indicates which state machine is being used. The handshake
 * starts off on the initial enum, which indicates we're using
 * the TLS12 state machine. Once the handshake version is determined
 * the enum is set to either the TLS12 or TLS13 state machine.
 * This works because the initial entries in both the TLS12 and 
 * TLS13 state machines are the same. */
typedef enum {
    S2N_STATE_MACHINE_INITIAL = 0,
    S2N_STATE_MACHINE_TLS12,
    S2N_STATE_MACHINE_TLS13,
} s2n_state_machine;

struct s2n_handshake_parameters {
    /* Public keys for server / client */
    struct s2n_pkey server_public_key;
    struct s2n_pkey client_public_key;
    struct s2n_blob client_cert_chain;
    s2n_pkey_type client_cert_pkey_type;

    /* Signature/hash algorithm pairs offered by the client in the signature_algorithms extension */
    struct s2n_sig_scheme_list client_sig_hash_algs;
    /* Signature scheme chosen by the server */
    const struct s2n_signature_scheme *server_cert_sig_scheme;

    /* Signature/hash algorithm pairs offered by the server in the certificate request */
    struct s2n_sig_scheme_list server_sig_hash_algs;
    /* Signature scheme chosen by the client */
    const struct s2n_signature_scheme *client_cert_sig_scheme;

    /* The cert chain we will send the peer. */
    struct s2n_cert_chain_and_key *our_chain_and_key;

    /* The subset of certificates that match the server_name presented in the ClientHello.
     * In the case of multiple certificates matching a server_name, s2n will prefer certificates
     * in FIFO order based on calls to s2n_config_add_cert_chain_and_key_to_store
     *
     * Note that in addition to domain matching, the key type for the certificate must also be
     * suitable for a negotiation in order to be selected. The set of matching certs here are indexed
     * by s2n_authentication_method.
     *
     * Example:
     *    - Assume certA is added to s2n_config via s2n_config_add_cert_chain_and_key_to_store
     *    - Next certB is added.
     *    - if certA matches www.foo.com and certB matches www.foo.com, s2n will prefer certA
     *
     * Note that in addition to domain matching, the key type for the certificate must also be
     * suitable for a negotiation in order to be selected.
     *
     * Example:
     *    - Assume certA and certB match server_name www.foo.com
     *    - certA is ECDSA and certB is RSA.
     *    - Client only supports RSA ciphers
     *    - certB will be selected.
     */
    struct s2n_cert_chain_and_key *exact_sni_matches[S2N_CERT_TYPE_COUNT];
    struct s2n_cert_chain_and_key *wc_sni_matches[S2N_CERT_TYPE_COUNT];
    uint8_t exact_sni_match_exists;
    uint8_t wc_sni_match_exists;

    uint8_t client_random[S2N_TLS_RANDOM_DATA_LEN];
    uint8_t server_random[S2N_TLS_RANDOM_DATA_LEN];
};

struct s2n_handshake {
    struct s2n_stuffer io;

    struct s2n_handshake_hashes *hashes;

    /* Hash algorithms required for this handshake. The set of required hashes can be reduced as session parameters are
     * negotiated, i.e. cipher suite and protocol version.
     */
    uint8_t required_hash_algs[S2N_HASH_SENTINEL];

    /*
     * Data required by the Finished messages.
     * In TLS1.2 and earlier, the data is the verify_data.
     * In TLS1.3, the data is the finished_key used to calculate the verify_data.
     *
     * The data will be different for the client and server.
     * The length of the data will be the same for the client and server.
     * The length of the data depends on protocol version and cipher suite.
     */
    uint8_t server_finished[S2N_TLS_SECRET_LEN];
    uint8_t client_finished[S2N_TLS_SECRET_LEN];
    uint8_t finished_len;

    /* Which message-order affecting features are enabled */
    uint32_t handshake_type;

    /* Which handshake message number are we processing */
    int message_number;

    /* Last message in the handshake. Unless using early data or testing,
     * should always be APPLICATION_DATA. */
    message_type_t end_of_messages;

    /* State of the async pkey operation during handshake */
    s2n_async_state async_state;

    /* State of the async early data callback.
     * If not initialized, then the callback has not been triggered yet. */
    struct s2n_offered_early_data early_data_async_state;

    /* Indicates the CLIENT_HELLO message has been completely received */
    unsigned client_hello_received : 1;

    /* Indicates the handshake blocked while trying to read or write data, and has been paused */
    unsigned paused : 1;

    /* Set to 1 if the RSA verification failed */
    unsigned rsa_failed : 1;

    /* Indicates that this is a renegotiation handshake */
    unsigned renegotiation : 1;

    s2n_state_machine state_machine;
};

/* Only used in our test cases. */
message_type_t s2n_conn_get_current_message_type(struct s2n_connection *conn);

/* s2n_handshake */
int s2n_handshake_require_all_hashes(struct s2n_handshake *handshake);
uint8_t s2n_handshake_is_hash_required(struct s2n_handshake *handshake, s2n_hash_algorithm hash_alg);
int s2n_conn_update_required_handshake_hashes(struct s2n_connection *conn);
S2N_RESULT s2n_handshake_copy_hash_state(struct s2n_connection *conn, s2n_hash_algorithm hash_alg, struct s2n_hash_state *hash_state);
S2N_RESULT s2n_handshake_reset_hash_state(struct s2n_connection *conn, s2n_hash_algorithm hash_alg);
int s2n_conn_find_name_matching_certs(struct s2n_connection *conn);
int s2n_create_wildcard_hostname(struct s2n_stuffer *hostname, struct s2n_stuffer *output);
struct s2n_cert_chain_and_key *s2n_get_compatible_cert_chain_and_key(struct s2n_connection *conn, const s2n_pkey_type cert_type);
S2N_RESULT s2n_negotiate_until_message(struct s2n_connection *conn, s2n_blocked_status *blocked, message_type_t end_message);
S2N_RESULT s2n_handshake_validate(const struct s2n_handshake *s2n_handshake);
S2N_RESULT s2n_handshake_set_finished_len(struct s2n_connection *conn, uint8_t len);
bool s2n_handshake_is_renegotiation(struct s2n_connection *conn);
S2N_RESULT s2n_handshake_message_send(struct s2n_connection *conn, uint8_t content_type, s2n_blocked_status *blocked);

/* s2n_handshake_io */
int s2n_conn_set_handshake_type(struct s2n_connection *conn);
int s2n_conn_set_handshake_no_client_cert(struct s2n_connection *conn);
S2N_RESULT s2n_conn_choose_state_machine(struct s2n_connection *conn, uint8_t protocol_version);
bool s2n_handshake_is_complete(struct s2n_connection *conn);

/* s2n_handshake_transcript */
S2N_RESULT s2n_handshake_transcript_update(struct s2n_connection *conn);
int s2n_conn_update_handshake_hashes(struct s2n_connection *conn, struct s2n_blob *data);

/* s2n_quic_support */
S2N_RESULT s2n_quic_read_handshake_message(struct s2n_connection *conn, uint8_t *message_type);
S2N_RESULT s2n_quic_write_handshake_message(struct s2n_connection *conn);