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.
*/
#include "api/s2n.h"
#include "s2n_test.h"
#include "testlib/s2n_testlib.h"
#include "utils/s2n_result.h"
/* Get access to s2n_handshake_read_io */
#include "tls/s2n_handshake_io.c"
int main(int argc, char **argv)
{
BEGIN_TEST();
uint8_t bad_record[] = {
0x17, /* ContentType opaque_type = application_data */
0x03, 0x03, /* ProtocolVersion legacy_record_version = 0x0303 */
0x00, 0x10, /* uint16 length */
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* opaque encrypted_record[TLSCiphertext.length] */
};
struct s2n_cipher_suite *test_cipher_suite = &s2n_tls13_aes_256_gcm_sha384;
uint8_t test_key_bytes[S2N_TLS13_SECRET_MAX_LEN] = "gibberish key";
struct s2n_blob test_key = { 0 };
EXPECT_SUCCESS(s2n_blob_init(&test_key, test_key_bytes,
test_cipher_suite->record_alg->cipher->key_material_size));
/**
*= https://www.rfc-editor.org/rfc/rfc8446#section-4.2.10
*= type=test
*# If the client attempts a 0-RTT handshake but the server
*# rejects it, the server will generally not have the 0-RTT record
*# protection keys and must instead use trial decryption (either with
*# the 1-RTT handshake keys or by looking for a cleartext ClientHello in
*# the case of a HelloRetryRequest) to find the first non-0-RTT message.
*#
*# If the server chooses to accept the "early_data" extension, then it
*# MUST comply with the same error-handling requirements specified for
*# all records when processing early data records. Specifically, if the
*# server fails to decrypt a 0-RTT record following an accepted
*# "early_data" extension, it MUST terminate the connection with a
*# "bad_record_mac" alert as per Section 5.2.
*/
{
/* Server */
{
struct s2n_connection *server_conn = s2n_connection_new(S2N_SERVER);
EXPECT_NOT_NULL(server_conn);
EXPECT_SUCCESS(s2n_connection_set_blinding(server_conn, S2N_SELF_SERVICE_BLINDING));
server_conn->secure->cipher_suite = test_cipher_suite;
POSIX_GUARD_RESULT(server_conn->secure->cipher_suite->record_alg->cipher->init(&server_conn->secure->client_key));
POSIX_GUARD_RESULT(server_conn->secure->cipher_suite->record_alg->cipher->set_decryption_key(&server_conn->secure->client_key, &test_key));
server_conn->client = server_conn->secure;
DEFER_CLEANUP(struct s2n_stuffer io_stuffer = { 0 }, s2n_stuffer_free);
EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&io_stuffer, S2N_DEFAULT_RECORD_LENGTH));
EXPECT_SUCCESS(s2n_connection_set_io_stuffers(&io_stuffer, &io_stuffer, server_conn));
EXPECT_SUCCESS(s2n_stuffer_write_bytes(&io_stuffer, bad_record, sizeof(bad_record)));
/* Fail for bad record if early data was not requested */
{
EXPECT_SUCCESS(s2n_stuffer_reread(&io_stuffer));
server_conn->early_data_state = S2N_EARLY_DATA_NOT_REQUESTED;
EXPECT_FAILURE_WITH_ERRNO(s2n_handshake_read_io(server_conn), S2N_ERR_DECRYPT);
};
/* Fail for bad record if early data was accepted */
{
EXPECT_SUCCESS(s2n_stuffer_reread(&io_stuffer));
server_conn->early_data_state = S2N_EARLY_DATA_ACCEPTED;
EXPECT_FAILURE_WITH_ERRNO(s2n_handshake_read_io(server_conn), S2N_ERR_DECRYPT);
};
/* Succeed for bad record if early data was rejected */
{
EXPECT_SUCCESS(s2n_stuffer_reread(&io_stuffer));
server_conn->early_data_state = S2N_EARLY_DATA_REJECTED;
EXPECT_SUCCESS(s2n_handshake_read_io(server_conn));
};
EXPECT_SUCCESS(s2n_connection_free(server_conn));
};
/* Client */
{
/* Fail for bad record if early data was rejected.
* Clients send early data but do not receive it, so a bad record is still an error. */
{
struct s2n_connection *client_conn = s2n_connection_new(S2N_CLIENT);
EXPECT_NOT_NULL(client_conn);
EXPECT_SUCCESS(s2n_connection_set_blinding(client_conn, S2N_SELF_SERVICE_BLINDING));
client_conn->secure->cipher_suite = test_cipher_suite;
POSIX_GUARD_RESULT(client_conn->secure->cipher_suite->record_alg->cipher->init(&client_conn->secure->server_key));
POSIX_GUARD_RESULT(client_conn->secure->cipher_suite->record_alg->cipher->set_decryption_key(&client_conn->secure->server_key, &test_key));
client_conn->server = client_conn->secure;
DEFER_CLEANUP(struct s2n_stuffer io_stuffer = { 0 }, s2n_stuffer_free);
EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&io_stuffer, S2N_DEFAULT_RECORD_LENGTH));
EXPECT_SUCCESS(s2n_connection_set_io_stuffers(&io_stuffer, &io_stuffer, client_conn));
EXPECT_SUCCESS(s2n_stuffer_write_bytes(&io_stuffer, bad_record, sizeof(bad_record)));
client_conn->early_data_state = S2N_EARLY_DATA_REJECTED;
EXPECT_FAILURE_WITH_ERRNO(s2n_handshake_read_io(client_conn), S2N_ERR_DECRYPT);
EXPECT_SUCCESS(s2n_connection_free(client_conn));
};
};
};
END_TEST();
}
|