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