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