tls13ccstest.c revision 1.1.1.1
1/* 2 * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the OpenSSL license (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 <openssl/ssl.h> 11#include <string.h> 12#include "ssltestlib.h" 13#include "testutil.h" 14#include "../ssl/packet_local.h" 15 16static char *cert = NULL; 17static char *privkey = NULL; 18 19static BIO *s_to_c_fbio = NULL, *c_to_s_fbio = NULL; 20static int chseen = 0, shseen = 0, sccsseen = 0, ccsaftersh = 0; 21static int ccsbeforesh = 0, sappdataseen = 0, cappdataseen = 0, badccs = 0; 22static int badvers = 0, badsessid = 0; 23 24static unsigned char chsessid[SSL_MAX_SSL_SESSION_ID_LENGTH]; 25static size_t chsessidlen = 0; 26 27static int watchccs_new(BIO *bi); 28static int watchccs_free(BIO *a); 29static int watchccs_read(BIO *b, char *out, int outl); 30static int watchccs_write(BIO *b, const char *in, int inl); 31static long watchccs_ctrl(BIO *b, int cmd, long num, void *ptr); 32static int watchccs_gets(BIO *bp, char *buf, int size); 33static int watchccs_puts(BIO *bp, const char *str); 34 35/* Choose a sufficiently large type likely to be unused for this custom BIO */ 36# define BIO_TYPE_WATCHCCS_FILTER (0x80 | BIO_TYPE_FILTER) 37 38static BIO_METHOD *method_watchccs = NULL; 39 40static const BIO_METHOD *bio_f_watchccs_filter(void) 41{ 42 if (method_watchccs == NULL) { 43 method_watchccs = BIO_meth_new(BIO_TYPE_WATCHCCS_FILTER, 44 "Watch CCS filter"); 45 if ( method_watchccs == NULL 46 || !BIO_meth_set_write(method_watchccs, watchccs_write) 47 || !BIO_meth_set_read(method_watchccs, watchccs_read) 48 || !BIO_meth_set_puts(method_watchccs, watchccs_puts) 49 || !BIO_meth_set_gets(method_watchccs, watchccs_gets) 50 || !BIO_meth_set_ctrl(method_watchccs, watchccs_ctrl) 51 || !BIO_meth_set_create(method_watchccs, watchccs_new) 52 || !BIO_meth_set_destroy(method_watchccs, watchccs_free)) 53 return NULL; 54 } 55 return method_watchccs; 56} 57 58static int watchccs_new(BIO *bio) 59{ 60 BIO_set_init(bio, 1); 61 return 1; 62} 63 64static int watchccs_free(BIO *bio) 65{ 66 BIO_set_init(bio, 0); 67 return 1; 68} 69 70static int watchccs_read(BIO *bio, char *out, int outl) 71{ 72 int ret = 0; 73 BIO *next = BIO_next(bio); 74 75 if (outl <= 0) 76 return 0; 77 if (next == NULL) 78 return 0; 79 80 BIO_clear_retry_flags(bio); 81 82 ret = BIO_read(next, out, outl); 83 if (ret <= 0 && BIO_should_read(next)) 84 BIO_set_retry_read(bio); 85 86 return ret; 87} 88 89static int watchccs_write(BIO *bio, const char *in, int inl) 90{ 91 int ret = 0; 92 BIO *next = BIO_next(bio); 93 PACKET pkt, msg, msgbody, sessionid; 94 unsigned int rectype, recvers, msgtype, expectedrecvers; 95 96 if (inl <= 0) 97 return 0; 98 if (next == NULL) 99 return 0; 100 101 BIO_clear_retry_flags(bio); 102 103 if (!PACKET_buf_init(&pkt, (const unsigned char *)in, inl)) 104 return 0; 105 106 /* We assume that we always write complete records each time */ 107 while (PACKET_remaining(&pkt)) { 108 if (!PACKET_get_1(&pkt, &rectype) 109 || !PACKET_get_net_2(&pkt, &recvers) 110 || !PACKET_get_length_prefixed_2(&pkt, &msg)) 111 return 0; 112 113 expectedrecvers = TLS1_2_VERSION; 114 115 if (rectype == SSL3_RT_HANDSHAKE) { 116 if (!PACKET_get_1(&msg, &msgtype) 117 || !PACKET_get_length_prefixed_3(&msg, &msgbody)) 118 return 0; 119 if (msgtype == SSL3_MT_CLIENT_HELLO) { 120 chseen++; 121 122 /* 123 * Skip legacy_version (2 bytes) and Random (32 bytes) to read 124 * session_id. 125 */ 126 if (!PACKET_forward(&msgbody, 34) 127 || !PACKET_get_length_prefixed_1(&msgbody, &sessionid)) 128 return 0; 129 130 if (chseen == 1) { 131 expectedrecvers = TLS1_VERSION; 132 133 /* Save the session id for later */ 134 chsessidlen = PACKET_remaining(&sessionid); 135 if (!PACKET_copy_bytes(&sessionid, chsessid, chsessidlen)) 136 return 0; 137 } else { 138 /* 139 * Check the session id for the second ClientHello is the 140 * same as the first one. 141 */ 142 if (PACKET_remaining(&sessionid) != chsessidlen 143 || (chsessidlen > 0 144 && memcmp(chsessid, PACKET_data(&sessionid), 145 chsessidlen) != 0)) 146 badsessid = 1; 147 } 148 } else if (msgtype == SSL3_MT_SERVER_HELLO) { 149 shseen++; 150 /* 151 * Skip legacy_version (2 bytes) and Random (32 bytes) to read 152 * session_id. 153 */ 154 if (!PACKET_forward(&msgbody, 34) 155 || !PACKET_get_length_prefixed_1(&msgbody, &sessionid)) 156 return 0; 157 158 /* 159 * Check the session id is the same as the one in the 160 * ClientHello 161 */ 162 if (PACKET_remaining(&sessionid) != chsessidlen 163 || (chsessidlen > 0 164 && memcmp(chsessid, PACKET_data(&sessionid), 165 chsessidlen) != 0)) 166 badsessid = 1; 167 } 168 } else if (rectype == SSL3_RT_CHANGE_CIPHER_SPEC) { 169 if (bio == s_to_c_fbio) { 170 /* 171 * Server writing. We shouldn't have written any app data 172 * yet, and we should have seen both the ClientHello and the 173 * ServerHello 174 */ 175 if (!sappdataseen 176 && chseen == 1 177 && shseen == 1 178 && !sccsseen) 179 sccsseen = 1; 180 else 181 badccs = 1; 182 } else if (!cappdataseen) { 183 /* 184 * Client writing. We shouldn't have written any app data 185 * yet, and we should have seen the ClientHello 186 */ 187 if (shseen == 1 && !ccsaftersh) 188 ccsaftersh = 1; 189 else if (shseen == 0 && !ccsbeforesh) 190 ccsbeforesh = 1; 191 else 192 badccs = 1; 193 } else { 194 badccs = 1; 195 } 196 } else if(rectype == SSL3_RT_APPLICATION_DATA) { 197 if (bio == s_to_c_fbio) 198 sappdataseen = 1; 199 else 200 cappdataseen = 1; 201 } 202 if (recvers != expectedrecvers) 203 badvers = 1; 204 } 205 206 ret = BIO_write(next, in, inl); 207 if (ret <= 0 && BIO_should_write(next)) 208 BIO_set_retry_write(bio); 209 210 return ret; 211} 212 213static long watchccs_ctrl(BIO *bio, int cmd, long num, void *ptr) 214{ 215 long ret; 216 BIO *next = BIO_next(bio); 217 218 if (next == NULL) 219 return 0; 220 221 switch (cmd) { 222 case BIO_CTRL_DUP: 223 ret = 0; 224 break; 225 default: 226 ret = BIO_ctrl(next, cmd, num, ptr); 227 break; 228 } 229 return ret; 230} 231 232static int watchccs_gets(BIO *bio, char *buf, int size) 233{ 234 /* We don't support this - not needed anyway */ 235 return -1; 236} 237 238static int watchccs_puts(BIO *bio, const char *str) 239{ 240 return watchccs_write(bio, str, strlen(str)); 241} 242 243static int test_tls13ccs(int tst) 244{ 245 SSL_CTX *sctx = NULL, *cctx = NULL; 246 SSL *sssl = NULL, *cssl = NULL; 247 int ret = 0; 248 const char msg[] = "Dummy data"; 249 char buf[80]; 250 size_t written, readbytes; 251 SSL_SESSION *sess = NULL; 252 253 chseen = shseen = sccsseen = ccsaftersh = ccsbeforesh = 0; 254 sappdataseen = cappdataseen = badccs = badvers = badsessid = 0; 255 chsessidlen = 0; 256 257 if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), 258 TLS1_VERSION, TLS_MAX_VERSION, 259 &sctx, &cctx, cert, privkey)) 260 || !TEST_true(SSL_CTX_set_max_early_data(sctx, 261 SSL3_RT_MAX_PLAIN_LENGTH))) 262 goto err; 263 264 /* 265 * Test 0: Simple Handshake 266 * Test 1: Simple Handshake, client middlebox compat mode disabled 267 * Test 2: Simple Handshake, server middlebox compat mode disabled 268 * Test 3: HRR Handshake 269 * Test 4: HRR Handshake, client middlebox compat mode disabled 270 * Test 5: HRR Handshake, server middlebox compat mode disabled 271 * Test 6: Early data handshake 272 * Test 7: Early data handshake, client middlebox compat mode disabled 273 * Test 8: Early data handshake, server middlebox compat mode disabled 274 * Test 9: Early data then HRR 275 * Test 10: Early data then HRR, client middlebox compat mode disabled 276 * Test 11: Early data then HRR, server middlebox compat mode disabled 277 */ 278 switch (tst) { 279 case 0: 280 case 3: 281 case 6: 282 case 9: 283 break; 284 case 1: 285 case 4: 286 case 7: 287 case 10: 288 SSL_CTX_clear_options(cctx, SSL_OP_ENABLE_MIDDLEBOX_COMPAT); 289 break; 290 case 2: 291 case 5: 292 case 8: 293 case 11: 294 SSL_CTX_clear_options(sctx, SSL_OP_ENABLE_MIDDLEBOX_COMPAT); 295 break; 296 default: 297 TEST_error("Invalid test value"); 298 goto err; 299 } 300 301 if (tst >= 6) { 302 /* Get a session suitable for early_data */ 303 if (!TEST_true(create_ssl_objects(sctx, cctx, &sssl, &cssl, NULL, NULL)) 304 || !TEST_true(create_ssl_connection(sssl, cssl, SSL_ERROR_NONE))) 305 goto err; 306 sess = SSL_get1_session(cssl); 307 if (!TEST_ptr(sess)) 308 goto err; 309 SSL_shutdown(cssl); 310 SSL_shutdown(sssl); 311 SSL_free(sssl); 312 SSL_free(cssl); 313 sssl = cssl = NULL; 314 } 315 316 if ((tst >= 3 && tst <= 5) || tst >= 9) { 317 /* HRR handshake */ 318 if (!TEST_true(SSL_CTX_set1_groups_list(sctx, "P-256"))) 319 goto err; 320 } 321 322 s_to_c_fbio = BIO_new(bio_f_watchccs_filter()); 323 c_to_s_fbio = BIO_new(bio_f_watchccs_filter()); 324 if (!TEST_ptr(s_to_c_fbio) 325 || !TEST_ptr(c_to_s_fbio)) { 326 BIO_free(s_to_c_fbio); 327 BIO_free(c_to_s_fbio); 328 goto err; 329 } 330 331 /* BIOs get freed on error */ 332 if (!TEST_true(create_ssl_objects(sctx, cctx, &sssl, &cssl, s_to_c_fbio, 333 c_to_s_fbio))) 334 goto err; 335 336 if (tst >= 6) { 337 /* Early data */ 338 if (!TEST_true(SSL_set_session(cssl, sess)) 339 || !TEST_true(SSL_write_early_data(cssl, msg, strlen(msg), 340 &written)) 341 || (tst <= 8 342 && !TEST_int_eq(SSL_read_early_data(sssl, buf, sizeof(buf), 343 &readbytes), 344 SSL_READ_EARLY_DATA_SUCCESS))) 345 goto err; 346 if (tst <= 8) { 347 if (!TEST_int_gt(SSL_connect(cssl), 0)) 348 goto err; 349 } else { 350 if (!TEST_int_le(SSL_connect(cssl), 0)) 351 goto err; 352 } 353 if (!TEST_int_eq(SSL_read_early_data(sssl, buf, sizeof(buf), 354 &readbytes), 355 SSL_READ_EARLY_DATA_FINISH)) 356 goto err; 357 } 358 359 /* Perform handshake (or complete it if doing early data ) */ 360 if (!TEST_true(create_ssl_connection(sssl, cssl, SSL_ERROR_NONE))) 361 goto err; 362 363 /* 364 * Check there were no unexpected CCS messages, all record versions 365 * were as expected, and that the session ids were reflected by the server 366 * correctly. 367 */ 368 if (!TEST_false(badccs) || !TEST_false(badvers) || !TEST_false(badsessid)) 369 goto err; 370 371 switch (tst) { 372 case 0: 373 if (!TEST_true(sccsseen) 374 || !TEST_true(ccsaftersh) 375 || !TEST_false(ccsbeforesh) 376 || !TEST_size_t_gt(chsessidlen, 0)) 377 goto err; 378 break; 379 380 case 1: 381 if (!TEST_true(sccsseen) 382 || !TEST_false(ccsaftersh) 383 || !TEST_false(ccsbeforesh) 384 || !TEST_size_t_eq(chsessidlen, 0)) 385 goto err; 386 break; 387 388 case 2: 389 if (!TEST_false(sccsseen) 390 || !TEST_true(ccsaftersh) 391 || !TEST_false(ccsbeforesh) 392 || !TEST_size_t_gt(chsessidlen, 0)) 393 goto err; 394 break; 395 396 case 3: 397 if (!TEST_true(sccsseen) 398 || !TEST_true(ccsaftersh) 399 || !TEST_false(ccsbeforesh) 400 || !TEST_size_t_gt(chsessidlen, 0)) 401 goto err; 402 break; 403 404 case 4: 405 if (!TEST_true(sccsseen) 406 || !TEST_false(ccsaftersh) 407 || !TEST_false(ccsbeforesh) 408 || !TEST_size_t_eq(chsessidlen, 0)) 409 goto err; 410 break; 411 412 case 5: 413 if (!TEST_false(sccsseen) 414 || !TEST_true(ccsaftersh) 415 || !TEST_false(ccsbeforesh) 416 || !TEST_size_t_gt(chsessidlen, 0)) 417 goto err; 418 break; 419 420 case 6: 421 if (!TEST_true(sccsseen) 422 || !TEST_false(ccsaftersh) 423 || !TEST_true(ccsbeforesh) 424 || !TEST_size_t_gt(chsessidlen, 0)) 425 goto err; 426 break; 427 428 case 7: 429 if (!TEST_true(sccsseen) 430 || !TEST_false(ccsaftersh) 431 || !TEST_false(ccsbeforesh) 432 || !TEST_size_t_eq(chsessidlen, 0)) 433 goto err; 434 break; 435 436 case 8: 437 if (!TEST_false(sccsseen) 438 || !TEST_false(ccsaftersh) 439 || !TEST_true(ccsbeforesh) 440 || !TEST_size_t_gt(chsessidlen, 0)) 441 goto err; 442 break; 443 444 case 9: 445 if (!TEST_true(sccsseen) 446 || !TEST_false(ccsaftersh) 447 || !TEST_true(ccsbeforesh) 448 || !TEST_size_t_gt(chsessidlen, 0)) 449 goto err; 450 break; 451 452 case 10: 453 if (!TEST_true(sccsseen) 454 || !TEST_false(ccsaftersh) 455 || !TEST_false(ccsbeforesh) 456 || !TEST_size_t_eq(chsessidlen, 0)) 457 goto err; 458 break; 459 460 case 11: 461 if (!TEST_false(sccsseen) 462 || !TEST_false(ccsaftersh) 463 || !TEST_true(ccsbeforesh) 464 || !TEST_size_t_gt(chsessidlen, 0)) 465 goto err; 466 break; 467 468 default: 469 TEST_error("Invalid test value"); 470 goto err; 471 } 472 473 ret = 1; 474 err: 475 SSL_SESSION_free(sess); 476 SSL_free(sssl); 477 SSL_free(cssl); 478 SSL_CTX_free(sctx); 479 SSL_CTX_free(cctx); 480 481 return ret; 482} 483 484int setup_tests(void) 485{ 486 if (!TEST_ptr(cert = test_get_argument(0)) 487 || !TEST_ptr(privkey = test_get_argument(1))) 488 return 0; 489 490 ADD_ALL_TESTS(test_tls13ccs, 12); 491 492 return 1; 493} 494 495void cleanup_tests(void) 496{ 497 BIO_meth_free(method_watchccs); 498} 499