openssl/test/recordlentest.c
Matt Caswell a763ca1177 Stop disabling TLSv1.3 if ec and dh are disabled
Even if EC and DH are disabled then we may still be able to use TLSv1.3
if we have groups that have been plugged in by an external provider.

Fixes #13767

Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/13916)
2021-02-05 15:22:40 +00:00

207 lines
5.4 KiB
C

/*
* Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <string.h>
#include "helpers/ssltestlib.h"
#include "testutil.h"
static char *cert = NULL;
static char *privkey = NULL;
#define TEST_PLAINTEXT_OVERFLOW_OK 0
#define TEST_PLAINTEXT_OVERFLOW_NOT_OK 1
#define TEST_ENCRYPTED_OVERFLOW_TLS1_3_OK 2
#define TEST_ENCRYPTED_OVERFLOW_TLS1_3_NOT_OK 3
#define TEST_ENCRYPTED_OVERFLOW_TLS1_2_OK 4
#define TEST_ENCRYPTED_OVERFLOW_TLS1_2_NOT_OK 5
#define TOTAL_RECORD_OVERFLOW_TESTS 6
static int write_record(BIO *b, size_t len, int rectype, int recversion)
{
unsigned char header[SSL3_RT_HEADER_LENGTH];
size_t written;
unsigned char buf[256];
memset(buf, 0, sizeof(buf));
header[0] = rectype;
header[1] = (recversion >> 8) & 0xff;
header[2] = recversion & 0xff;
header[3] = (len >> 8) & 0xff;
header[4] = len & 0xff;
if (!BIO_write_ex(b, header, SSL3_RT_HEADER_LENGTH, &written)
|| written != SSL3_RT_HEADER_LENGTH)
return 0;
while (len > 0) {
size_t outlen;
if (len > sizeof(buf))
outlen = sizeof(buf);
else
outlen = len;
if (!BIO_write_ex(b, buf, outlen, &written)
|| written != outlen)
return 0;
len -= outlen;
}
return 1;
}
static int fail_due_to_record_overflow(int enc)
{
long err = ERR_peek_error();
int reason;
if (enc)
reason = SSL_R_ENCRYPTED_LENGTH_TOO_LONG;
else
reason = SSL_R_DATA_LENGTH_TOO_LONG;
if (ERR_GET_LIB(err) == ERR_LIB_SSL
&& ERR_GET_REASON(err) == reason)
return 1;
return 0;
}
static int test_record_overflow(int idx)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
size_t len = 0;
size_t written;
int overf_expected;
unsigned char buf;
BIO *serverbio;
int recversion;
#ifdef OPENSSL_NO_TLS1_2
if (idx == TEST_ENCRYPTED_OVERFLOW_TLS1_2_OK
|| idx == TEST_ENCRYPTED_OVERFLOW_TLS1_2_NOT_OK)
return 1;
#endif
#if defined(OPENSSL_NO_TLS1_3) \
|| (defined(OPENSSL_NO_EC) && defined(OPENSSL_NO_DH))
if (idx == TEST_ENCRYPTED_OVERFLOW_TLS1_3_OK
|| idx == TEST_ENCRYPTED_OVERFLOW_TLS1_3_NOT_OK)
return 1;
#endif
ERR_clear_error();
if (!TEST_true(create_ssl_ctx_pair(NULL, TLS_server_method(),
TLS_client_method(),
TLS1_VERSION, 0,
&sctx, &cctx, cert, privkey)))
goto end;
if (idx == TEST_ENCRYPTED_OVERFLOW_TLS1_2_OK
|| idx == TEST_ENCRYPTED_OVERFLOW_TLS1_2_NOT_OK) {
len = SSL3_RT_MAX_ENCRYPTED_LENGTH;
#ifndef OPENSSL_NO_COMP
len -= SSL3_RT_MAX_COMPRESSED_OVERHEAD;
#endif
SSL_CTX_set_max_proto_version(sctx, TLS1_2_VERSION);
} else if (idx == TEST_ENCRYPTED_OVERFLOW_TLS1_3_OK
|| idx == TEST_ENCRYPTED_OVERFLOW_TLS1_3_NOT_OK) {
len = SSL3_RT_MAX_TLS13_ENCRYPTED_LENGTH;
}
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL)))
goto end;
serverbio = SSL_get_rbio(serverssl);
if (idx == TEST_PLAINTEXT_OVERFLOW_OK
|| idx == TEST_PLAINTEXT_OVERFLOW_NOT_OK) {
len = SSL3_RT_MAX_PLAIN_LENGTH;
if (idx == TEST_PLAINTEXT_OVERFLOW_NOT_OK)
len++;
if (!TEST_true(write_record(serverbio, len,
SSL3_RT_HANDSHAKE, TLS1_VERSION)))
goto end;
if (!TEST_int_le(SSL_accept(serverssl), 0))
goto end;
overf_expected = (idx == TEST_PLAINTEXT_OVERFLOW_OK) ? 0 : 1;
if (!TEST_int_eq(fail_due_to_record_overflow(0), overf_expected))
goto end;
goto success;
}
if (!TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
if (idx == TEST_ENCRYPTED_OVERFLOW_TLS1_2_NOT_OK
|| idx == TEST_ENCRYPTED_OVERFLOW_TLS1_3_NOT_OK) {
overf_expected = 1;
len++;
} else {
overf_expected = 0;
}
recversion = TLS1_2_VERSION;
if (!TEST_true(write_record(serverbio, len, SSL3_RT_APPLICATION_DATA,
recversion)))
goto end;
if (!TEST_false(SSL_read_ex(serverssl, &buf, sizeof(buf), &written)))
goto end;
if (!TEST_int_eq(fail_due_to_record_overflow(1), overf_expected))
goto end;
success:
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
OPT_TEST_DECLARE_USAGE("certfile privkeyfile\n")
int setup_tests(void)
{
if (!test_skip_common_options()) {
TEST_error("Error parsing test options\n");
return 0;
}
if (!TEST_ptr(cert = test_get_argument(0))
|| !TEST_ptr(privkey = test_get_argument(1)))
return 0;
ADD_ALL_TESTS(test_record_overflow, TOTAL_RECORD_OVERFLOW_TESTS);
return 1;
}
void cleanup_tests(void)
{
bio_s_mempacket_test_free();
}