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
|
/*
* 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.
*/
/* Target Functions: s2n_client_key_recv s2n_kex_client_key_recv calculate_keys
s2n_kex_tls_prf s2n_prf_key_expansion s2n_ecdhe_client_key_recv
s2n_kem_client_key_recv s2n_hybrid_client_action */
#include "crypto/s2n_crypto.h"
#include "crypto/s2n_drbg.h"
#include "crypto/s2n_hash.h"
#include "crypto/s2n_openssl.h"
#include "crypto/s2n_pq.h"
#include "error/s2n_errno.h"
#include "stuffer/s2n_stuffer.h"
#include "tests/s2n_test.h"
#include "tests/testlib/s2n_testlib.h"
#include "tls/s2n_cipher_suites.h"
#include "tls/s2n_kem.h"
#include "tls/s2n_kex.h"
#include "tls/s2n_security_policies.h"
#include "tls/s2n_tls.h"
#include "utils/s2n_random.h"
#include "utils/s2n_safety.h"
static struct s2n_kem_params kyber512_r3_draft0_params = { .kem = &s2n_kyber_512_r3, .len_prefixed = true };
static struct s2n_kem_params kyber512_r3_draft5_params = { .kem = &s2n_kyber_512_r3, .len_prefixed = false };
/* Setup the connection in a state for a fuzz test run, s2n_client_key_recv modifies the state of the connection
* along the way and gets cleaned up at the end of each fuzz test.
* - Connection needs cipher suite, curve, and kem setup
* - Connection needs a ecdhe key and a kem private key, this would normally be setup when the server calls s2n_server_send_key
* */
static int setup_connection(struct s2n_connection *server_conn, struct s2n_kem_params *params)
{
server_conn->actual_protocol_version = S2N_TLS12;
const struct s2n_ecc_preferences *ecc_preferences = NULL;
POSIX_GUARD(s2n_connection_get_ecc_preferences(server_conn, &ecc_preferences));
POSIX_ENSURE_REF(ecc_preferences);
server_conn->kex_params.server_ecc_evp_params.negotiated_curve = ecc_preferences->ecc_curves[0];
server_conn->kex_params.server_ecc_evp_params.evp_pkey = NULL;
server_conn->kex_params.kem_params.kem = NULL;
server_conn->secure->cipher_suite = &s2n_ecdhe_rsa_with_aes_256_gcm_sha384;
server_conn->handshake_params.server_cert_sig_scheme = &s2n_rsa_pkcs1_sha384;
POSIX_GUARD(s2n_dup(¶ms->private_key, &server_conn->kex_params.kem_params.private_key));
POSIX_GUARD(s2n_ecc_evp_generate_ephemeral_key(&server_conn->kex_params.server_ecc_evp_params));
return S2N_SUCCESS;
}
int s2n_fuzz_init_kem_param(struct s2n_kem_params *param)
{
POSIX_ENSURE_REF(param->kem);
struct s2n_blob *public_key = ¶m->public_key;
POSIX_GUARD(s2n_alloc(public_key, S2N_KYBER_512_R3_PUBLIC_KEY_BYTES));
/* Do not GUARD this call to s2n_kem_generate_keypair(), as it will fail when attempting to generate the KEM
* key pair if !s2n_pq_is_enabled(). However, even if it does fail, it will have allocated zeroed memory for the
* public and private keys needed for setup_connection() to complete. */
s2n_result result = s2n_kem_generate_keypair(param);
POSIX_ENSURE_EQ(s2n_pq_is_enabled(), s2n_result_is_ok(result));
POSIX_ENSURE_REF(param->public_key.data);
POSIX_ENSURE_REF(param->private_key.data);
POSIX_GUARD(s2n_free(public_key));
return S2N_SUCCESS;
}
int s2n_fuzz_init(int *argc, char **argv[])
{
POSIX_GUARD(s2n_fuzz_init_kem_param(&kyber512_r3_draft0_params));
POSIX_GUARD(s2n_fuzz_init_kem_param(&kyber512_r3_draft5_params));
return S2N_SUCCESS;
}
int s2n_fuzz_test_with_params(const uint8_t *buf, size_t len, struct s2n_kem_params *params)
{
struct s2n_connection *server_conn;
POSIX_ENSURE_REF(server_conn = s2n_connection_new(S2N_SERVER));
POSIX_GUARD(setup_connection(server_conn, params));
/* You can't write 0 bytes to a stuffer but attempting to call s2n_client_key_recv with 0 data is an interesting test */
if (len > 0) {
POSIX_GUARD(s2n_stuffer_write_bytes(&server_conn->handshake.io, buf, len));
}
/* The missing GUARD is because s2n_client_key_recv might fail due to bad input which is okay, the connection
* must still be cleaned up. Don't return s2n_client_key_recv's result because the the test still passes as long as
* s2n_client_key_recv does not leak/contaminate any memory, the fuzz input is most likely not valid and will fail
* to be recv'd successfully. */
int result = s2n_client_key_recv(server_conn);
POSIX_GUARD(s2n_connection_free(server_conn));
return S2N_SUCCESS;
}
int s2n_fuzz_test(const uint8_t *buf, size_t len)
{
POSIX_GUARD(s2n_fuzz_test_with_params(buf, len, &kyber512_r3_draft0_params));
POSIX_GUARD(s2n_fuzz_test_with_params(buf, len, &kyber512_r3_draft5_params));
return S2N_SUCCESS;
}
static void s2n_fuzz_cleanup()
{
s2n_kem_free(&kyber512_r3_draft0_params);
s2n_kem_free(&kyber512_r3_draft5_params);
}
S2N_FUZZ_TARGET(s2n_fuzz_init, s2n_fuzz_test, s2n_fuzz_cleanup)
|