1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci#include <stdio.h> 11e1051a39Sopenharmony_ci#include <string.h> 12e1051a39Sopenharmony_ci 13e1051a39Sopenharmony_ci#include <openssl/dtls1.h> 14e1051a39Sopenharmony_ci#include <openssl/ssl.h> 15e1051a39Sopenharmony_ci#include <openssl/err.h> 16e1051a39Sopenharmony_ci 17e1051a39Sopenharmony_ci#include "helpers/ssltestlib.h" 18e1051a39Sopenharmony_ci#include "testutil.h" 19e1051a39Sopenharmony_ci 20e1051a39Sopenharmony_ci/* for SSL_READ_ETM() */ 21e1051a39Sopenharmony_ci#include "../ssl/ssl_local.h" 22e1051a39Sopenharmony_ci 23e1051a39Sopenharmony_cistatic int debug = 0; 24e1051a39Sopenharmony_ci 25e1051a39Sopenharmony_cistatic unsigned int clnt_psk_callback(SSL *ssl, const char *hint, 26e1051a39Sopenharmony_ci char *ident, unsigned int max_ident_len, 27e1051a39Sopenharmony_ci unsigned char *psk, 28e1051a39Sopenharmony_ci unsigned int max_psk_len) 29e1051a39Sopenharmony_ci{ 30e1051a39Sopenharmony_ci BIO_snprintf(ident, max_ident_len, "psk"); 31e1051a39Sopenharmony_ci 32e1051a39Sopenharmony_ci if (max_psk_len > 20) 33e1051a39Sopenharmony_ci max_psk_len = 20; 34e1051a39Sopenharmony_ci memset(psk, 0x5a, max_psk_len); 35e1051a39Sopenharmony_ci 36e1051a39Sopenharmony_ci return max_psk_len; 37e1051a39Sopenharmony_ci} 38e1051a39Sopenharmony_ci 39e1051a39Sopenharmony_cistatic unsigned int srvr_psk_callback(SSL *ssl, const char *identity, 40e1051a39Sopenharmony_ci unsigned char *psk, 41e1051a39Sopenharmony_ci unsigned int max_psk_len) 42e1051a39Sopenharmony_ci{ 43e1051a39Sopenharmony_ci if (max_psk_len > 20) 44e1051a39Sopenharmony_ci max_psk_len = 20; 45e1051a39Sopenharmony_ci memset(psk, 0x5a, max_psk_len); 46e1051a39Sopenharmony_ci return max_psk_len; 47e1051a39Sopenharmony_ci} 48e1051a39Sopenharmony_ci 49e1051a39Sopenharmony_cistatic int mtu_test(SSL_CTX *ctx, const char *cs, int no_etm) 50e1051a39Sopenharmony_ci{ 51e1051a39Sopenharmony_ci SSL *srvr_ssl = NULL, *clnt_ssl = NULL; 52e1051a39Sopenharmony_ci BIO *sc_bio = NULL; 53e1051a39Sopenharmony_ci int i; 54e1051a39Sopenharmony_ci size_t s; 55e1051a39Sopenharmony_ci size_t mtus[30]; 56e1051a39Sopenharmony_ci unsigned char buf[600]; 57e1051a39Sopenharmony_ci int rv = 0; 58e1051a39Sopenharmony_ci 59e1051a39Sopenharmony_ci memset(buf, 0x5a, sizeof(buf)); 60e1051a39Sopenharmony_ci 61e1051a39Sopenharmony_ci if (!TEST_true(create_ssl_objects(ctx, ctx, &srvr_ssl, &clnt_ssl, 62e1051a39Sopenharmony_ci NULL, NULL))) 63e1051a39Sopenharmony_ci goto end; 64e1051a39Sopenharmony_ci 65e1051a39Sopenharmony_ci if (no_etm) 66e1051a39Sopenharmony_ci SSL_set_options(srvr_ssl, SSL_OP_NO_ENCRYPT_THEN_MAC); 67e1051a39Sopenharmony_ci 68e1051a39Sopenharmony_ci if (!TEST_true(SSL_set_cipher_list(srvr_ssl, cs)) 69e1051a39Sopenharmony_ci || !TEST_true(SSL_set_cipher_list(clnt_ssl, cs)) 70e1051a39Sopenharmony_ci || !TEST_ptr(sc_bio = SSL_get_rbio(srvr_ssl)) 71e1051a39Sopenharmony_ci || !TEST_true(create_ssl_connection(clnt_ssl, srvr_ssl, 72e1051a39Sopenharmony_ci SSL_ERROR_NONE))) 73e1051a39Sopenharmony_ci goto end; 74e1051a39Sopenharmony_ci 75e1051a39Sopenharmony_ci if (debug) 76e1051a39Sopenharmony_ci TEST_info("Channel established"); 77e1051a39Sopenharmony_ci 78e1051a39Sopenharmony_ci /* For record MTU values between 500 and 539, call DTLS_get_data_mtu() 79e1051a39Sopenharmony_ci * to query the payload MTU which will fit. */ 80e1051a39Sopenharmony_ci for (i = 0; i < 30; i++) { 81e1051a39Sopenharmony_ci SSL_set_mtu(clnt_ssl, 500 + i); 82e1051a39Sopenharmony_ci mtus[i] = DTLS_get_data_mtu(clnt_ssl); 83e1051a39Sopenharmony_ci if (debug) 84e1051a39Sopenharmony_ci TEST_info("%s%s MTU for record mtu %d = %lu", 85e1051a39Sopenharmony_ci cs, no_etm ? "-noEtM" : "", 86e1051a39Sopenharmony_ci 500 + i, (unsigned long)mtus[i]); 87e1051a39Sopenharmony_ci if (!TEST_size_t_ne(mtus[i], 0)) { 88e1051a39Sopenharmony_ci TEST_info("Cipher %s MTU %d", cs, 500 + i); 89e1051a39Sopenharmony_ci goto end; 90e1051a39Sopenharmony_ci } 91e1051a39Sopenharmony_ci } 92e1051a39Sopenharmony_ci 93e1051a39Sopenharmony_ci /* Now get out of the way */ 94e1051a39Sopenharmony_ci SSL_set_mtu(clnt_ssl, 1000); 95e1051a39Sopenharmony_ci 96e1051a39Sopenharmony_ci /* 97e1051a39Sopenharmony_ci * Now for all values in the range of payload MTUs, send a payload of 98e1051a39Sopenharmony_ci * that size and see what actual record size we end up with. 99e1051a39Sopenharmony_ci */ 100e1051a39Sopenharmony_ci for (s = mtus[0]; s <= mtus[29]; s++) { 101e1051a39Sopenharmony_ci size_t reclen; 102e1051a39Sopenharmony_ci 103e1051a39Sopenharmony_ci if (!TEST_int_eq(SSL_write(clnt_ssl, buf, s), (int)s)) 104e1051a39Sopenharmony_ci goto end; 105e1051a39Sopenharmony_ci reclen = BIO_read(sc_bio, buf, sizeof(buf)); 106e1051a39Sopenharmony_ci if (debug) 107e1051a39Sopenharmony_ci TEST_info("record %zu for payload %zu", reclen, s); 108e1051a39Sopenharmony_ci 109e1051a39Sopenharmony_ci for (i = 0; i < 30; i++) { 110e1051a39Sopenharmony_ci /* DTLS_get_data_mtu() with record MTU 500+i returned mtus[i] ... */ 111e1051a39Sopenharmony_ci 112e1051a39Sopenharmony_ci if (!TEST_false(s <= mtus[i] && reclen > (size_t)(500 + i))) { 113e1051a39Sopenharmony_ci /* 114e1051a39Sopenharmony_ci * We sent a packet smaller than or equal to mtus[j] and 115e1051a39Sopenharmony_ci * that made a record *larger* than the record MTU 500+j! 116e1051a39Sopenharmony_ci */ 117e1051a39Sopenharmony_ci TEST_error("%s: s=%lu, mtus[i]=%lu, reclen=%lu, i=%d", 118e1051a39Sopenharmony_ci cs, (unsigned long)s, (unsigned long)mtus[i], 119e1051a39Sopenharmony_ci (unsigned long)reclen, 500 + i); 120e1051a39Sopenharmony_ci goto end; 121e1051a39Sopenharmony_ci } 122e1051a39Sopenharmony_ci if (!TEST_false(s > mtus[i] && reclen <= (size_t)(500 + i))) { 123e1051a39Sopenharmony_ci /* 124e1051a39Sopenharmony_ci * We sent a *larger* packet than mtus[i] and that *still* 125e1051a39Sopenharmony_ci * fits within the record MTU 500+i, so DTLS_get_data_mtu() 126e1051a39Sopenharmony_ci * was overly pessimistic. 127e1051a39Sopenharmony_ci */ 128e1051a39Sopenharmony_ci TEST_error("%s: s=%lu, mtus[i]=%lu, reclen=%lu, i=%d", 129e1051a39Sopenharmony_ci cs, (unsigned long)s, (unsigned long)mtus[i], 130e1051a39Sopenharmony_ci (unsigned long)reclen, 500 + i); 131e1051a39Sopenharmony_ci goto end; 132e1051a39Sopenharmony_ci } 133e1051a39Sopenharmony_ci } 134e1051a39Sopenharmony_ci } 135e1051a39Sopenharmony_ci rv = 1; 136e1051a39Sopenharmony_ci if (SSL_READ_ETM(clnt_ssl)) 137e1051a39Sopenharmony_ci rv = 2; 138e1051a39Sopenharmony_ci end: 139e1051a39Sopenharmony_ci SSL_free(clnt_ssl); 140e1051a39Sopenharmony_ci SSL_free(srvr_ssl); 141e1051a39Sopenharmony_ci return rv; 142e1051a39Sopenharmony_ci} 143e1051a39Sopenharmony_ci 144e1051a39Sopenharmony_cistatic int run_mtu_tests(void) 145e1051a39Sopenharmony_ci{ 146e1051a39Sopenharmony_ci SSL_CTX *ctx = NULL; 147e1051a39Sopenharmony_ci STACK_OF(SSL_CIPHER) *ciphers; 148e1051a39Sopenharmony_ci int i, ret = 0; 149e1051a39Sopenharmony_ci 150e1051a39Sopenharmony_ci if (!TEST_ptr(ctx = SSL_CTX_new(DTLS_method()))) 151e1051a39Sopenharmony_ci goto end; 152e1051a39Sopenharmony_ci 153e1051a39Sopenharmony_ci SSL_CTX_set_psk_server_callback(ctx, srvr_psk_callback); 154e1051a39Sopenharmony_ci SSL_CTX_set_psk_client_callback(ctx, clnt_psk_callback); 155e1051a39Sopenharmony_ci SSL_CTX_set_security_level(ctx, 0); 156e1051a39Sopenharmony_ci 157e1051a39Sopenharmony_ci /* 158e1051a39Sopenharmony_ci * We only care about iterating over each enc/mac; we don't want to 159e1051a39Sopenharmony_ci * repeat the test for each auth/kx variant. So keep life simple and 160e1051a39Sopenharmony_ci * only do (non-DH) PSK. 161e1051a39Sopenharmony_ci */ 162e1051a39Sopenharmony_ci if (!TEST_true(SSL_CTX_set_cipher_list(ctx, "PSK"))) 163e1051a39Sopenharmony_ci goto end; 164e1051a39Sopenharmony_ci 165e1051a39Sopenharmony_ci ciphers = SSL_CTX_get_ciphers(ctx); 166e1051a39Sopenharmony_ci for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) { 167e1051a39Sopenharmony_ci const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(ciphers, i); 168e1051a39Sopenharmony_ci const char *cipher_name = SSL_CIPHER_get_name(cipher); 169e1051a39Sopenharmony_ci 170e1051a39Sopenharmony_ci /* As noted above, only one test for each enc/mac variant. */ 171e1051a39Sopenharmony_ci if (strncmp(cipher_name, "PSK-", 4) != 0) 172e1051a39Sopenharmony_ci continue; 173e1051a39Sopenharmony_ci 174e1051a39Sopenharmony_ci if (!TEST_int_gt(ret = mtu_test(ctx, cipher_name, 0), 0)) 175e1051a39Sopenharmony_ci break; 176e1051a39Sopenharmony_ci TEST_info("%s OK", cipher_name); 177e1051a39Sopenharmony_ci if (ret == 1) 178e1051a39Sopenharmony_ci continue; 179e1051a39Sopenharmony_ci 180e1051a39Sopenharmony_ci /* mtu_test() returns 2 if it used Encrypt-then-MAC */ 181e1051a39Sopenharmony_ci if (!TEST_int_gt(ret = mtu_test(ctx, cipher_name, 1), 0)) 182e1051a39Sopenharmony_ci break; 183e1051a39Sopenharmony_ci TEST_info("%s without EtM OK", cipher_name); 184e1051a39Sopenharmony_ci } 185e1051a39Sopenharmony_ci 186e1051a39Sopenharmony_ci end: 187e1051a39Sopenharmony_ci SSL_CTX_free(ctx); 188e1051a39Sopenharmony_ci return ret; 189e1051a39Sopenharmony_ci} 190e1051a39Sopenharmony_ci 191e1051a39Sopenharmony_cistatic int test_server_mtu_larger_than_max_fragment_length(void) 192e1051a39Sopenharmony_ci{ 193e1051a39Sopenharmony_ci SSL_CTX *ctx = NULL; 194e1051a39Sopenharmony_ci SSL *srvr_ssl = NULL, *clnt_ssl = NULL; 195e1051a39Sopenharmony_ci int rv = 0; 196e1051a39Sopenharmony_ci 197e1051a39Sopenharmony_ci if (!TEST_ptr(ctx = SSL_CTX_new(DTLS_method()))) 198e1051a39Sopenharmony_ci goto end; 199e1051a39Sopenharmony_ci 200e1051a39Sopenharmony_ci SSL_CTX_set_psk_server_callback(ctx, srvr_psk_callback); 201e1051a39Sopenharmony_ci SSL_CTX_set_psk_client_callback(ctx, clnt_psk_callback); 202e1051a39Sopenharmony_ci 203e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DH 204e1051a39Sopenharmony_ci if (!TEST_true(SSL_CTX_set_dh_auto(ctx, 1))) 205e1051a39Sopenharmony_ci goto end; 206e1051a39Sopenharmony_ci#endif 207e1051a39Sopenharmony_ci 208e1051a39Sopenharmony_ci if (!TEST_true(create_ssl_objects(ctx, ctx, &srvr_ssl, &clnt_ssl, 209e1051a39Sopenharmony_ci NULL, NULL))) 210e1051a39Sopenharmony_ci goto end; 211e1051a39Sopenharmony_ci 212e1051a39Sopenharmony_ci SSL_set_options(srvr_ssl, SSL_OP_NO_QUERY_MTU); 213e1051a39Sopenharmony_ci if (!TEST_true(DTLS_set_link_mtu(srvr_ssl, 1500))) 214e1051a39Sopenharmony_ci goto end; 215e1051a39Sopenharmony_ci 216e1051a39Sopenharmony_ci SSL_set_tlsext_max_fragment_length(clnt_ssl, 217e1051a39Sopenharmony_ci TLSEXT_max_fragment_length_512); 218e1051a39Sopenharmony_ci 219e1051a39Sopenharmony_ci if (!TEST_true(create_ssl_connection(srvr_ssl, clnt_ssl, 220e1051a39Sopenharmony_ci SSL_ERROR_NONE))) 221e1051a39Sopenharmony_ci goto end; 222e1051a39Sopenharmony_ci 223e1051a39Sopenharmony_ci rv = 1; 224e1051a39Sopenharmony_ci 225e1051a39Sopenharmony_ci end: 226e1051a39Sopenharmony_ci SSL_free(clnt_ssl); 227e1051a39Sopenharmony_ci SSL_free(srvr_ssl); 228e1051a39Sopenharmony_ci SSL_CTX_free(ctx); 229e1051a39Sopenharmony_ci return rv; 230e1051a39Sopenharmony_ci} 231e1051a39Sopenharmony_ci 232e1051a39Sopenharmony_ciint setup_tests(void) 233e1051a39Sopenharmony_ci{ 234e1051a39Sopenharmony_ci ADD_TEST(run_mtu_tests); 235e1051a39Sopenharmony_ci ADD_TEST(test_server_mtu_larger_than_max_fragment_length); 236e1051a39Sopenharmony_ci return 1; 237e1051a39Sopenharmony_ci} 238e1051a39Sopenharmony_ci 239e1051a39Sopenharmony_civoid cleanup_tests(void) 240e1051a39Sopenharmony_ci{ 241e1051a39Sopenharmony_ci bio_s_mempacket_test_free(); 242e1051a39Sopenharmony_ci} 243