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 "tls/s2n_kex.h"
17 #include "pq-crypto/s2n_pq.h"
18 #include "tls/s2n_cipher_preferences.h"
19 #include "tls/s2n_cipher_suites.h"
20 #include "tls/s2n_client_key_exchange.h"
21 #include "tls/s2n_kem.h"
22 #include "tls/s2n_security_policies.h"
23 #include "tls/s2n_server_key_exchange.h"
24 #include "tls/s2n_tls.h"
25 #include "utils/s2n_safety.h"
26 
s2n_check_rsa_key(const struct s2n_cipher_suite * cipher_suite,struct s2n_connection * conn,bool * is_supported)27 static S2N_RESULT s2n_check_rsa_key(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn, bool *is_supported)
28 {
29     RESULT_ENSURE_REF(cipher_suite);
30     RESULT_ENSURE_REF(conn);
31     RESULT_ENSURE_REF(is_supported);
32 
33     *is_supported = s2n_get_compatible_cert_chain_and_key(conn, S2N_PKEY_TYPE_RSA) != NULL;
34 
35     return S2N_RESULT_OK;
36 }
37 
s2n_check_dhe(const struct s2n_cipher_suite * cipher_suite,struct s2n_connection * conn,bool * is_supported)38 static S2N_RESULT s2n_check_dhe(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn, bool *is_supported)
39 {
40     RESULT_ENSURE_REF(cipher_suite);
41     RESULT_ENSURE_REF(conn);
42     RESULT_ENSURE_REF(conn->config);
43     RESULT_ENSURE_REF(is_supported);
44 
45     *is_supported = conn->config->dhparams != NULL;
46 
47     return S2N_RESULT_OK;
48 }
49 
s2n_check_ecdhe(const struct s2n_cipher_suite * cipher_suite,struct s2n_connection * conn,bool * is_supported)50 static S2N_RESULT s2n_check_ecdhe(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn, bool *is_supported)
51 {
52     RESULT_ENSURE_REF(cipher_suite);
53     RESULT_ENSURE_REF(conn);
54     RESULT_ENSURE_REF(is_supported);
55 
56     *is_supported = conn->kex_params.server_ecc_evp_params.negotiated_curve != NULL;
57 
58     return S2N_RESULT_OK;
59 }
60 
s2n_check_kem(const struct s2n_cipher_suite * cipher_suite,struct s2n_connection * conn,bool * is_supported)61 static S2N_RESULT s2n_check_kem(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn, bool *is_supported)
62 {
63     RESULT_ENSURE_REF(cipher_suite);
64     RESULT_ENSURE_REF(conn);
65     RESULT_ENSURE_REF(is_supported);
66 
67     /* If any of the necessary conditions are not met, we will return early and indicate KEM is not supported. */
68     *is_supported = false;
69 
70     const struct s2n_kem_preferences *kem_preferences = NULL;
71     RESULT_GUARD_POSIX(s2n_connection_get_kem_preferences(conn, &kem_preferences));
72     RESULT_ENSURE_REF(kem_preferences);
73 
74     if (!s2n_pq_is_enabled() || kem_preferences->kem_count == 0) {
75         return S2N_RESULT_OK;
76     }
77 
78     const struct s2n_iana_to_kem *supported_params = NULL;
79     if (s2n_cipher_suite_to_kem(cipher_suite->iana_value, &supported_params) != S2N_SUCCESS) {
80         return S2N_RESULT_OK;
81     }
82 
83     RESULT_ENSURE_REF(supported_params);
84     if (supported_params->kem_count == 0) {
85         return S2N_RESULT_OK;
86     }
87 
88     struct s2n_blob *client_kem_pref_list = &(conn->kex_params.client_pq_kem_extension);
89     const struct s2n_kem *chosen_kem = NULL;
90     if (client_kem_pref_list == NULL || client_kem_pref_list->data == NULL) {
91         /* If the client did not send a PQ KEM extension, then the server can pick its preferred parameter */
92         if (s2n_choose_kem_without_peer_pref_list(cipher_suite->iana_value, kem_preferences->kems,
93                 kem_preferences->kem_count, &chosen_kem) != S2N_SUCCESS) {
94             return S2N_RESULT_OK;
95         }
96     } else {
97         /* If the client did send a PQ KEM extension, then the server must find a mutually supported parameter. */
98         if (s2n_choose_kem_with_peer_pref_list(cipher_suite->iana_value, client_kem_pref_list, kem_preferences->kems,
99                 kem_preferences->kem_count, &chosen_kem) != S2N_SUCCESS) {
100             return S2N_RESULT_OK;
101         }
102     }
103 
104     *is_supported = chosen_kem != NULL;
105     return S2N_RESULT_OK;
106 }
107 
s2n_configure_kem(const struct s2n_cipher_suite * cipher_suite,struct s2n_connection * conn)108 static S2N_RESULT s2n_configure_kem(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn)
109 {
110     RESULT_ENSURE_REF(cipher_suite);
111     RESULT_ENSURE_REF(conn);
112 
113     RESULT_ENSURE(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
114 
115     const struct s2n_kem_preferences *kem_preferences = NULL;
116     RESULT_GUARD_POSIX(s2n_connection_get_kem_preferences(conn, &kem_preferences));
117     RESULT_ENSURE_REF(kem_preferences);
118 
119     struct s2n_blob *proposed_kems = &(conn->kex_params.client_pq_kem_extension);
120     const struct s2n_kem *chosen_kem = NULL;
121     if (proposed_kems == NULL || proposed_kems->data == NULL) {
122         /* If the client did not send a PQ KEM extension, then the server can pick its preferred parameter */
123         RESULT_GUARD_POSIX(s2n_choose_kem_without_peer_pref_list(cipher_suite->iana_value, kem_preferences->kems,
124                 kem_preferences->kem_count, &chosen_kem));
125     } else {
126         /* If the client did send a PQ KEM extension, then the server must find a mutually supported parameter. */
127         RESULT_GUARD_POSIX(s2n_choose_kem_with_peer_pref_list(cipher_suite->iana_value, proposed_kems, kem_preferences->kems,
128                 kem_preferences->kem_count, &chosen_kem));
129     }
130 
131     conn->kex_params.kem_params.kem = chosen_kem;
132     return S2N_RESULT_OK;
133 }
134 
s2n_no_op_configure(const struct s2n_cipher_suite * cipher_suite,struct s2n_connection * conn)135 static S2N_RESULT s2n_no_op_configure(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn)
136 {
137     return S2N_RESULT_OK;
138 }
139 
s2n_check_hybrid_ecdhe_kem(const struct s2n_cipher_suite * cipher_suite,struct s2n_connection * conn,bool * is_supported)140 static S2N_RESULT s2n_check_hybrid_ecdhe_kem(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn, bool *is_supported)
141 {
142     RESULT_ENSURE_REF(cipher_suite);
143     RESULT_ENSURE_REF(conn);
144     RESULT_ENSURE_REF(is_supported);
145 
146     bool ecdhe_supported = false;
147     bool kem_supported = false;
148     RESULT_GUARD(s2n_check_ecdhe(cipher_suite, conn, &ecdhe_supported));
149     RESULT_GUARD(s2n_check_kem(cipher_suite, conn, &kem_supported));
150 
151     *is_supported = ecdhe_supported && kem_supported;
152 
153     return S2N_RESULT_OK;
154 }
155 
156 const struct s2n_kex s2n_kem = {
157     .is_ephemeral = true,
158     .connection_supported = &s2n_check_kem,
159     .configure_connection = &s2n_configure_kem,
160     .server_key_recv_read_data = &s2n_kem_server_key_recv_read_data,
161     .server_key_recv_parse_data = &s2n_kem_server_key_recv_parse_data,
162     .server_key_send = &s2n_kem_server_key_send,
163     .client_key_recv = &s2n_kem_client_key_recv,
164     .client_key_send = &s2n_kem_client_key_send,
165 };
166 
167 const struct s2n_kex s2n_rsa = {
168     .is_ephemeral = false,
169     .connection_supported = &s2n_check_rsa_key,
170     .configure_connection = &s2n_no_op_configure,
171     .server_key_recv_read_data = NULL,
172     .server_key_recv_parse_data = NULL,
173     .server_key_send = NULL,
174     .client_key_recv = &s2n_rsa_client_key_recv,
175     .client_key_send = &s2n_rsa_client_key_send,
176     .prf = &s2n_prf_calculate_master_secret,
177 };
178 
179 const struct s2n_kex s2n_dhe = {
180     .is_ephemeral = true,
181     .connection_supported = &s2n_check_dhe,
182     .configure_connection = &s2n_no_op_configure,
183     .server_key_recv_read_data = &s2n_dhe_server_key_recv_read_data,
184     .server_key_recv_parse_data = &s2n_dhe_server_key_recv_parse_data,
185     .server_key_send = &s2n_dhe_server_key_send,
186     .client_key_recv = &s2n_dhe_client_key_recv,
187     .client_key_send = &s2n_dhe_client_key_send,
188     .prf = &s2n_prf_calculate_master_secret,
189 };
190 
191 const struct s2n_kex s2n_ecdhe = {
192     .is_ephemeral = true,
193     .connection_supported = &s2n_check_ecdhe,
194     .configure_connection = &s2n_no_op_configure,
195     .server_key_recv_read_data = &s2n_ecdhe_server_key_recv_read_data,
196     .server_key_recv_parse_data = &s2n_ecdhe_server_key_recv_parse_data,
197     .server_key_send = &s2n_ecdhe_server_key_send,
198     .client_key_recv = &s2n_ecdhe_client_key_recv,
199     .client_key_send = &s2n_ecdhe_client_key_send,
200     .prf = &s2n_prf_calculate_master_secret,
201 };
202 
203 const struct s2n_kex s2n_hybrid_ecdhe_kem = {
204     .is_ephemeral = true,
205     .hybrid = { &s2n_ecdhe, &s2n_kem },
206     .connection_supported = &s2n_check_hybrid_ecdhe_kem,
207     .configure_connection = &s2n_configure_kem,
208     .server_key_recv_read_data = &s2n_hybrid_server_key_recv_read_data,
209     .server_key_recv_parse_data = &s2n_hybrid_server_key_recv_parse_data,
210     .server_key_send = &s2n_hybrid_server_key_send,
211     .client_key_recv = &s2n_hybrid_client_key_recv,
212     .client_key_send = &s2n_hybrid_client_key_send,
213     .prf = &s2n_hybrid_prf_master_secret,
214 };
215 
s2n_kex_supported(const struct s2n_cipher_suite * cipher_suite,struct s2n_connection * conn,bool * is_supported)216 S2N_RESULT s2n_kex_supported(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn, bool *is_supported)
217 {
218     RESULT_ENSURE_REF(cipher_suite);
219     RESULT_ENSURE_REF(cipher_suite->key_exchange_alg);
220     RESULT_ENSURE_REF(cipher_suite->key_exchange_alg->connection_supported);
221     RESULT_ENSURE_REF(conn);
222     RESULT_ENSURE_REF(is_supported);
223 
224     RESULT_GUARD(cipher_suite->key_exchange_alg->connection_supported(cipher_suite, conn, is_supported));
225 
226     return S2N_RESULT_OK;
227 }
228 
s2n_configure_kex(const struct s2n_cipher_suite * cipher_suite,struct s2n_connection * conn)229 S2N_RESULT s2n_configure_kex(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn)
230 {
231     RESULT_ENSURE_REF(cipher_suite);
232     RESULT_ENSURE_REF(cipher_suite->key_exchange_alg);
233     RESULT_ENSURE_REF(cipher_suite->key_exchange_alg->configure_connection);
234     RESULT_ENSURE_REF(conn);
235 
236     RESULT_GUARD(cipher_suite->key_exchange_alg->configure_connection(cipher_suite, conn));
237 
238     return S2N_RESULT_OK;
239 }
240 
s2n_kex_is_ephemeral(const struct s2n_kex * kex,bool * is_ephemeral)241 S2N_RESULT s2n_kex_is_ephemeral(const struct s2n_kex *kex, bool *is_ephemeral)
242 {
243     RESULT_ENSURE_REF(kex);
244     RESULT_ENSURE_REF(is_ephemeral);
245 
246     *is_ephemeral = kex->is_ephemeral;
247 
248     return S2N_RESULT_OK;
249 }
250 
s2n_kex_server_key_recv_parse_data(const struct s2n_kex * kex,struct s2n_connection * conn,struct s2n_kex_raw_server_data * raw_server_data)251 S2N_RESULT s2n_kex_server_key_recv_parse_data(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_kex_raw_server_data *raw_server_data)
252 {
253     RESULT_ENSURE_REF(kex);
254     RESULT_ENSURE_REF(kex->server_key_recv_parse_data);
255     RESULT_ENSURE_REF(conn);
256     RESULT_ENSURE_REF(raw_server_data);
257 
258     RESULT_GUARD_POSIX(kex->server_key_recv_parse_data(conn, raw_server_data));
259 
260     return S2N_RESULT_OK;
261 }
262 
s2n_kex_server_key_recv_read_data(const struct s2n_kex * kex,struct s2n_connection * conn,struct s2n_blob * data_to_verify,struct s2n_kex_raw_server_data * raw_server_data)263 S2N_RESULT s2n_kex_server_key_recv_read_data(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *data_to_verify,
264         struct s2n_kex_raw_server_data *raw_server_data)
265 {
266     RESULT_ENSURE_REF(kex);
267     RESULT_ENSURE_REF(kex->server_key_recv_read_data);
268     RESULT_ENSURE_REF(conn);
269     RESULT_ENSURE_REF(data_to_verify);
270 
271     RESULT_GUARD_POSIX(kex->server_key_recv_read_data(conn, data_to_verify, raw_server_data));
272 
273     return S2N_RESULT_OK;
274 }
275 
s2n_kex_server_key_send(const struct s2n_kex * kex,struct s2n_connection * conn,struct s2n_blob * data_to_sign)276 S2N_RESULT s2n_kex_server_key_send(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *data_to_sign)
277 {
278     RESULT_ENSURE_REF(kex);
279     RESULT_ENSURE_REF(kex->server_key_send);
280     RESULT_ENSURE_REF(conn);
281     RESULT_ENSURE_REF(data_to_sign);
282 
283     RESULT_GUARD_POSIX(kex->server_key_send(conn, data_to_sign));
284 
285     return S2N_RESULT_OK;
286 }
287 
s2n_kex_client_key_recv(const struct s2n_kex * kex,struct s2n_connection * conn,struct s2n_blob * shared_key)288 S2N_RESULT s2n_kex_client_key_recv(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *shared_key)
289 {
290     RESULT_ENSURE_REF(kex);
291     RESULT_ENSURE_REF(kex->client_key_recv);
292     RESULT_ENSURE_REF(conn);
293     RESULT_ENSURE_REF(shared_key);
294 
295     RESULT_GUARD_POSIX(kex->client_key_recv(conn, shared_key));
296 
297     return S2N_RESULT_OK;
298 }
299 
s2n_kex_client_key_send(const struct s2n_kex * kex,struct s2n_connection * conn,struct s2n_blob * shared_key)300 S2N_RESULT s2n_kex_client_key_send(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *shared_key)
301 {
302     RESULT_ENSURE_REF(kex);
303     RESULT_ENSURE_REF(kex->client_key_send);
304     RESULT_ENSURE_REF(conn);
305     RESULT_ENSURE_REF(shared_key);
306 
307     RESULT_GUARD_POSIX(kex->client_key_send(conn, shared_key));
308 
309     return S2N_RESULT_OK;
310 }
311 
s2n_kex_tls_prf(const struct s2n_kex * kex,struct s2n_connection * conn,struct s2n_blob * premaster_secret)312 S2N_RESULT s2n_kex_tls_prf(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *premaster_secret)
313 {
314     RESULT_ENSURE_REF(kex);
315     RESULT_ENSURE_REF(kex->prf);
316     RESULT_ENSURE_REF(conn);
317     RESULT_ENSURE_REF(premaster_secret);
318 
319     RESULT_GUARD_POSIX(kex->prf(conn, premaster_secret));
320 
321     return S2N_RESULT_OK;
322 }
323 
s2n_kex_includes(const struct s2n_kex * kex,const struct s2n_kex * query)324 bool s2n_kex_includes(const struct s2n_kex *kex, const struct s2n_kex *query)
325 {
326     if (kex == query) {
327         return true;
328     }
329 
330     if (kex == NULL || query == NULL) {
331         return false;
332     }
333 
334     return query == kex->hybrid[0] || query == kex->hybrid[1];
335 }
336