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 /* Target Functions: s2n_client_key_recv s2n_kex_client_key_recv calculate_keys
17 s2n_hybrid_client_action s2n_kex_tls_prf s2n_prf_key_expansion
18 s2n_rsa_client_key_recv s2n_dhe_client_key_recv
19 s2n_ecdhe_client_key_recv s2n_kem_client_key_recv */
20
21 #include <stdint.h>
22
23 #include <openssl/crypto.h>
24 #include <openssl/err.h>
25
26 #include "tls/s2n_kem.h"
27 #include "tls/s2n_client_key_exchange.h"
28 #include "tls/s2n_kex.h"
29 #include "tls/s2n_security_policies.h"
30
31 #include "api/s2n.h"
32 #include "stuffer/s2n_stuffer.h"
33 #include "tls/s2n_cipher_preferences.h"
34 #include "tls/s2n_cipher_suites.h"
35 #include "tls/s2n_connection.h"
36 #include "tls/s2n_tls.h"
37 #include "utils/s2n_safety.h"
38 #include "s2n_test.h"
39 #include "testlib/s2n_testlib.h"
40
41 static const uint8_t TLS_VERSIONS[] = {S2N_TLS10, S2N_TLS11, S2N_TLS12};
42
43 /* Connection setup variables */
44 uint8_t *cert_chain_pem = NULL;
45 uint8_t *private_key_pem = NULL;
46 char *dhparams_pem = NULL;
47 uint32_t cert_chain_len = 0;
48 uint32_t private_key_len = 0;
49 struct s2n_config *config;
50 struct s2n_cert_chain_and_key *chain_and_key;
51 struct s2n_cert_chain_and_key *cert;
52 struct s2n_cipher_suite **test_suites;
53 int num_suites;
54
s2n_fuzz_init(int * argc,char ** argv[])55 int s2n_fuzz_init(int *argc, char **argv[])
56 {
57 #ifdef S2N_TEST_IN_FIPS_MODE
58 test_suites = cipher_preferences_test_all_fips.suites;
59 num_suites = cipher_preferences_test_all_fips.count;
60 #else
61 test_suites = cipher_preferences_test_all.suites;
62 num_suites = cipher_preferences_test_all.count;
63 #endif
64
65 /* One time Diffie-Hellman negotiation to speed along fuzz tests*/
66 cert_chain_pem = malloc(S2N_MAX_TEST_PEM_SIZE);
67 private_key_pem = malloc(S2N_MAX_TEST_PEM_SIZE);
68 dhparams_pem = malloc(S2N_MAX_TEST_PEM_SIZE);
69
70 POSIX_ENSURE_REF(cert_chain_pem);
71 POSIX_ENSURE_REF(private_key_pem);
72 POSIX_ENSURE_REF(dhparams_pem);
73
74 s2n_read_test_pem_and_len(S2N_DEFAULT_TEST_CERT_CHAIN, cert_chain_pem, &cert_chain_len, S2N_MAX_TEST_PEM_SIZE);
75 s2n_read_test_pem_and_len(S2N_DEFAULT_TEST_PRIVATE_KEY, private_key_pem, &private_key_len, S2N_MAX_TEST_PEM_SIZE);
76 s2n_read_test_pem(S2N_DEFAULT_TEST_DHPARAMS, dhparams_pem, S2N_MAX_TEST_PEM_SIZE);
77
78 config = s2n_config_new();
79 chain_and_key = s2n_cert_chain_and_key_new();
80
81 POSIX_ENSURE_REF(config);
82 POSIX_ENSURE_REF(chain_and_key);
83
84 s2n_cert_chain_and_key_load_pem_bytes(chain_and_key, cert_chain_pem, cert_chain_len, private_key_pem, private_key_len);
85 s2n_config_add_cert_chain_and_key_to_store(config, chain_and_key);
86 s2n_config_add_dhparams(config, dhparams_pem);
87
88 cert = s2n_config_get_single_default_cert(config);
89 POSIX_ENSURE_REF(cert);
90
91 return S2N_SUCCESS;
92 }
93
s2n_fuzz_test(const uint8_t * buf,size_t len)94 int s2n_fuzz_test(const uint8_t *buf, size_t len)
95 {
96 /* We need at least two bytes of input to set parameters */
97 S2N_FUZZ_ENSURE_MIN_LEN(len, 2);
98
99 /* Setup */
100 struct s2n_connection *server_conn = s2n_connection_new(S2N_SERVER);
101 POSIX_ENSURE_REF(server_conn);
102 POSIX_GUARD(s2n_stuffer_write_bytes(&server_conn->handshake.io, buf, len));
103
104 /* Read bytes from the libfuzzer input and use them to set parameters */
105 uint8_t randval = 0;
106 POSIX_GUARD(s2n_stuffer_read_uint8(&server_conn->handshake.io, &randval));
107 server_conn->server_protocol_version = TLS_VERSIONS[randval % s2n_array_len(TLS_VERSIONS)];
108
109 POSIX_GUARD(s2n_stuffer_read_uint8(&server_conn->handshake.io, &randval));
110 server_conn->secure.cipher_suite = test_suites[randval % num_suites];
111
112 /* Skip incompatible TLS 1.3 cipher suites */
113 if (server_conn->secure.cipher_suite->key_exchange_alg == NULL) {
114 POSIX_GUARD(s2n_connection_free(server_conn));
115 return S2N_SUCCESS;
116 }
117
118 server_conn->handshake_params.our_chain_and_key = cert;
119
120 const struct s2n_ecc_preferences *ecc_preferences = NULL;
121 POSIX_GUARD(s2n_connection_get_ecc_preferences(server_conn, &ecc_preferences));
122 POSIX_ENSURE_REF(ecc_preferences);
123
124 if (server_conn->secure.cipher_suite->key_exchange_alg->client_key_recv == s2n_ecdhe_client_key_recv || server_conn->secure.cipher_suite->key_exchange_alg->client_key_recv == s2n_hybrid_client_key_recv) {
125 server_conn->kex_params.server_ecc_evp_params.negotiated_curve = ecc_preferences->ecc_curves[0];
126 s2n_ecc_evp_generate_ephemeral_key(&server_conn->kex_params.server_ecc_evp_params);
127 }
128
129 if (server_conn->secure.cipher_suite->key_exchange_alg->client_key_recv == s2n_kem_client_key_recv || server_conn->secure.cipher_suite->key_exchange_alg->client_key_recv == s2n_hybrid_client_key_recv) {
130 server_conn->kex_params.kem_params.kem = &s2n_sike_p503_r1;
131 }
132
133 /* Run Test
134 * Do not use GUARD macro here since the connection memory hasn't been freed.
135 */
136 s2n_client_key_recv(server_conn);
137
138 /* Cleanup */
139 POSIX_GUARD(s2n_connection_free(server_conn));
140
141 return S2N_SUCCESS;
142 }
143
s2n_fuzz_cleanup()144 static void s2n_fuzz_cleanup()
145 {
146 free(cert_chain_pem);
147 free(private_key_pem);
148 free(dhparams_pem);
149 s2n_config_free(config);
150 s2n_cert_chain_and_key_free(chain_and_key);
151 }
152
153 S2N_FUZZ_TARGET(s2n_fuzz_init, s2n_fuzz_test, s2n_fuzz_cleanup)
154