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