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
|
/*
* 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.
*/
#include "crypto/s2n_pq.h"
#include "s2n_testlib.h"
#include "tests/testlib/s2n_nist_kats.h"
#include "tls/s2n_kem.h"
#include "utils/s2n_safety.h"
int s2n_kem_recv_ciphertext_fuzz_test_init(const char *kat_file_path, struct s2n_kem_params *kem_params)
{
POSIX_ENSURE_REF(kat_file_path);
POSIX_ENSURE_REF(kem_params);
POSIX_ENSURE_REF(kem_params->kem);
POSIX_GUARD(s2n_alloc(&kem_params->private_key, kem_params->kem->private_key_length));
FILE *kat_file = fopen(kat_file_path, "r");
POSIX_ENSURE_REF(kat_file);
POSIX_GUARD(ReadHex(kat_file, kem_params->private_key.data, kem_params->kem->private_key_length, "sk = "));
fclose(kat_file);
return S2N_SUCCESS;
}
int s2n_kem_recv_ciphertext_fuzz_test(const uint8_t *buf, size_t len, struct s2n_kem_params *kem_params)
{
POSIX_ENSURE_REF(buf);
POSIX_ENSURE_REF(kem_params);
POSIX_ENSURE_REF(kem_params->kem);
DEFER_CLEANUP(struct s2n_stuffer ciphertext = { 0 }, s2n_stuffer_free);
POSIX_GUARD(s2n_stuffer_alloc(&ciphertext, len));
POSIX_GUARD(s2n_stuffer_write_bytes(&ciphertext, buf, len));
/* Don't GUARD the call to recv_ciphertext().
* recv_ciphertext() parses the would-be ciphertext bytes from the
* handshake, then passes them to the KEM's decaps function.
* recv_ciphertext() may fail appropriately during parsing if the
* ciphertext bytes do not correspond to TLS specification (e.g.
* improperly length-encoded).
*
* All but one of the KEM's decaps functions are written in such
* a way that they should never fail, regardless of the input provided
* by the fuzzer. If the fuzzer-provided "ciphertext" is not a
* valid PQ ciphertext (and it probably won't be), the decaps function
* should still succeed and return 0, but the output plaintext will
* be garbage. Therefore, if recv_ciphertext() fails for these KEMs,
* it should not have been due to S2N_ERR_PQ_CRYPTO.
*
* If PQ is not enabled, then recv_ciphertext() should always fail. */
int recv_ciphertext_ret = s2n_kem_recv_ciphertext(&ciphertext, kem_params);
if (s2n_pq_is_enabled() && recv_ciphertext_ret != S2N_SUCCESS) {
POSIX_ENSURE_NE(s2n_errno, S2N_ERR_PQ_CRYPTO);
}
if (!s2n_pq_is_enabled()) {
POSIX_ENSURE_NE(recv_ciphertext_ret, S2N_SUCCESS);
}
/* Shared secret may have been alloc'ed in recv_ciphertext */
POSIX_GUARD(s2n_free(&kem_params->shared_secret));
return S2N_SUCCESS;
}
int s2n_kem_recv_public_key_fuzz_test(const uint8_t *buf, size_t len, struct s2n_kem_params *kem_params)
{
POSIX_ENSURE_REF(buf);
POSIX_ENSURE_REF(kem_params);
POSIX_ENSURE_REF(kem_params->kem);
DEFER_CLEANUP(struct s2n_stuffer public_key = { 0 }, s2n_stuffer_free);
POSIX_GUARD(s2n_stuffer_alloc(&public_key, len));
POSIX_GUARD(s2n_stuffer_write_bytes(&public_key, buf, len));
/* s2n_kem_recv_public_key performs only very basic checks, like ensuring
* that the public key size is correct. If the received public key passes,
* we continue by calling s2n_kem_send_ciphertext to attempt to use the key
* for encryption. */
if (s2n_kem_recv_public_key(&public_key, kem_params) == S2N_SUCCESS) {
DEFER_CLEANUP(struct s2n_stuffer out = { 0 }, s2n_stuffer_free);
POSIX_GUARD(s2n_stuffer_growable_alloc(&out, 8192));
int send_ct_ret = s2n_kem_send_ciphertext(&out, kem_params);
/* The KEM encaps functions are written in such a way that
* s2n_kem_send_ciphertext() should always succeed as long
* as PQ is enabled, even if the previously received public
* key is not valid. If PQ is not enabled, send_ciphertext()
* should always fail because of a PQ crypto errno. */
if (s2n_pq_is_enabled()) {
POSIX_ENSURE_EQ(send_ct_ret, S2N_SUCCESS);
} else {
POSIX_ENSURE_NE(send_ct_ret, S2N_SUCCESS);
POSIX_ENSURE_EQ(s2n_errno, S2N_ERR_PQ_CRYPTO);
}
}
/* Clean up */
POSIX_GUARD(s2n_kem_free(kem_params));
return S2N_SUCCESS;
}
|