1 /* 2 * Copyright 2022-2025 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 <assert.h> 11 #include <openssl/configuration.h> 12 #include <openssl/bio.h> 13 #include "internal/e_os.h" /* For struct timeval */ 14 #include "quictestlib.h" 15 #include "ssltestlib.h" 16 #include "../testutil.h" 17 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) 18 # include "../threadstest.h" 19 #endif 20 #include "internal/quic_ssl.h" 21 #include "internal/quic_wire_pkt.h" 22 #include "internal/quic_record_tx.h" 23 #include "internal/quic_error.h" 24 #include "internal/packet.h" 25 #include "internal/tsan_assist.h" 26 27 #define GROWTH_ALLOWANCE 1024 28 29 struct noise_args_data_st { 30 BIO *cbio; 31 BIO *sbio; 32 BIO *tracebio; 33 int flags; 34 }; 35 36 struct qtest_fault { 37 QUIC_TSERVER *qtserv; 38 39 /* Plain packet mutations */ 40 /* Header for the plaintext packet */ 41 QUIC_PKT_HDR pplainhdr; 42 /* iovec for the plaintext packet data buffer */ 43 OSSL_QTX_IOVEC pplainio; 44 /* Allocated size of the plaintext packet data buffer */ 45 size_t pplainbuf_alloc; 46 qtest_fault_on_packet_plain_cb pplaincb; 47 void *pplaincbarg; 48 49 /* Handshake message mutations */ 50 /* Handshake message buffer */ 51 unsigned char *handbuf; 52 /* Allocated size of the handshake message buffer */ 53 size_t handbufalloc; 54 /* Actual length of the handshake message */ 55 size_t handbuflen; 56 qtest_fault_on_handshake_cb handshakecb; 57 void *handshakecbarg; 58 qtest_fault_on_enc_ext_cb encextcb; 59 void *encextcbarg; 60 61 /* Cipher packet mutations */ 62 qtest_fault_on_packet_cipher_cb pciphercb; 63 void *pciphercbarg; 64 65 /* Datagram mutations */ 66 qtest_fault_on_datagram_cb datagramcb; 67 void *datagramcbarg; 68 /* The currently processed message */ 69 BIO_MSG msg; 70 /* Allocated size of msg data buffer */ 71 size_t msgalloc; 72 struct noise_args_data_st noiseargs; 73 }; 74 75 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) 76 static int client_ready = 0; 77 static CRYPTO_CONDVAR *client_ready_cond = NULL; 78 static CRYPTO_MUTEX *client_ready_mutex = NULL; 79 #endif 80 81 static void packet_plain_finish(void *arg); 82 static void handshake_finish(void *arg); 83 static OSSL_TIME qtest_get_time(void); 84 static void qtest_reset_time(void); 85 86 static int using_fake_time = 0; 87 static OSSL_TIME fake_now; 88 static CRYPTO_RWLOCK *fake_now_lock = NULL; 89 static OSSL_TIME start_time; 90 91 static OSSL_TIME fake_now_cb(void *arg) 92 { 93 return qtest_get_time(); 94 } 95 96 static void noise_msg_callback(int write_p, int version, int content_type, 97 const void *buf, size_t len, SSL *ssl, 98 void *arg) 99 { 100 struct noise_args_data_st *noiseargs = (struct noise_args_data_st *)arg; 101 102 if (content_type == SSL3_RT_QUIC_FRAME_FULL) { 103 PACKET pkt; 104 uint64_t frame_type; 105 106 if (!PACKET_buf_init(&pkt, buf, len)) 107 return; 108 109 if (!ossl_quic_wire_peek_frame_header(&pkt, &frame_type, NULL)) 110 return; 111 112 if (frame_type == OSSL_QUIC_FRAME_TYPE_PING) { 113 /* 114 * If either endpoint issues a ping frame then we are in danger 115 * of our noise being too much such that the connection itself 116 * fails. We back off on the noise for a bit to avoid that. 117 */ 118 (void)BIO_ctrl(noiseargs->cbio, BIO_CTRL_NOISE_BACK_OFF, 1, NULL); 119 (void)BIO_ctrl(noiseargs->sbio, BIO_CTRL_NOISE_BACK_OFF, 1, NULL); 120 } 121 } 122 123 #ifndef OPENSSL_NO_SSL_TRACE 124 if ((noiseargs->flags & QTEST_FLAG_CLIENT_TRACE) != 0 125 && !SSL_is_server(ssl)) 126 SSL_trace(write_p, version, content_type, buf, len, ssl, 127 noiseargs->tracebio); 128 #endif 129 } 130 131 int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx, 132 SSL_CTX *serverctx, char *certfile, char *keyfile, 133 int flags, QUIC_TSERVER **qtserv, SSL **cssl, 134 QTEST_FAULT **fault, BIO **tracebio) 135 { 136 /* ALPN value as recognised by QUIC_TSERVER */ 137 unsigned char alpn[] = { 8, 'o', 's', 's', 'l', 't', 'e', 's', 't' }; 138 QUIC_TSERVER_ARGS tserver_args = {0}; 139 BIO *cbio = NULL, *sbio = NULL, *fisbio = NULL; 140 BIO_ADDR *peeraddr = NULL; 141 struct in_addr ina = {0}; 142 BIO *tmpbio = NULL; 143 QTEST_DATA *bdata = NULL; 144 145 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) 146 if (client_ready_cond == NULL) { 147 client_ready_cond = ossl_crypto_condvar_new(); 148 if (client_ready_cond == NULL) 149 return 0; 150 } 151 152 if (client_ready_mutex == NULL) { 153 client_ready_mutex = ossl_crypto_mutex_new(); 154 if (client_ready_mutex == NULL) { 155 ossl_crypto_condvar_free(&client_ready_cond); 156 client_ready_cond = NULL; 157 return 0; 158 } 159 } 160 #endif 161 162 bdata = OPENSSL_zalloc(sizeof(QTEST_DATA)); 163 if (bdata == NULL) 164 return 0; 165 166 *qtserv = NULL; 167 168 if (fault != NULL) { 169 *fault = OPENSSL_zalloc(sizeof(**fault)); 170 if (*fault == NULL) 171 goto err; 172 bdata->fault = *fault; 173 } 174 175 if (*cssl == NULL) { 176 *cssl = SSL_new(clientctx); 177 if (!TEST_ptr(*cssl)) 178 goto err; 179 } 180 181 #ifndef OPENSSL_NO_SSL_TRACE 182 if ((flags & QTEST_FLAG_CLIENT_TRACE) != 0) { 183 tmpbio = BIO_new_fp(stdout, BIO_NOCLOSE); 184 if (!TEST_ptr(tmpbio)) 185 goto err; 186 187 SSL_set_msg_callback(*cssl, SSL_trace); 188 SSL_set_msg_callback_arg(*cssl, tmpbio); 189 } 190 #endif 191 if (tracebio != NULL) 192 *tracebio = tmpbio; 193 194 /* SSL_set_alpn_protos returns 0 for success! */ 195 if (!TEST_false(SSL_set_alpn_protos(*cssl, alpn, sizeof(alpn)))) 196 goto err; 197 198 if (!TEST_ptr(peeraddr = BIO_ADDR_new())) 199 goto err; 200 201 if ((flags & QTEST_FLAG_BLOCK) != 0) { 202 #if !defined(OPENSSL_NO_POSIX_IO) 203 int cfd, sfd; 204 205 /* 206 * For blocking mode we need to create actual sockets rather than doing 207 * everything in memory 208 */ 209 if (!TEST_true(create_test_sockets(&cfd, &sfd, SOCK_DGRAM, peeraddr))) 210 goto err; 211 cbio = BIO_new_dgram(cfd, 1); 212 if (!TEST_ptr(cbio)) { 213 close(cfd); 214 close(sfd); 215 goto err; 216 } 217 sbio = BIO_new_dgram(sfd, 1); 218 if (!TEST_ptr(sbio)) { 219 close(sfd); 220 goto err; 221 } 222 #else 223 goto err; 224 #endif 225 } else { 226 BIO_ADDR *localaddr = NULL; 227 228 if (!TEST_true(BIO_new_bio_dgram_pair(&cbio, 0, &sbio, 0))) 229 goto err; 230 231 if (!TEST_true(BIO_dgram_set_caps(cbio, BIO_DGRAM_CAP_HANDLES_DST_ADDR)) 232 || !TEST_true(BIO_dgram_set_caps(sbio, BIO_DGRAM_CAP_HANDLES_DST_ADDR))) 233 goto err; 234 235 if (!TEST_ptr(localaddr = BIO_ADDR_new())) 236 goto err; 237 /* Dummy client local addresses */ 238 if (!TEST_true(BIO_ADDR_rawmake(localaddr, AF_INET, &ina, sizeof(ina), 239 htons(0)))) { 240 BIO_ADDR_free(localaddr); 241 goto err; 242 } 243 if (!TEST_int_eq(BIO_dgram_set0_local_addr(cbio, localaddr), 1)) { 244 BIO_ADDR_free(localaddr); 245 goto err; 246 } 247 /* Dummy server address */ 248 if (!TEST_true(BIO_ADDR_rawmake(peeraddr, AF_INET, &ina, sizeof(ina), 249 htons(0)))) 250 goto err; 251 } 252 253 if ((flags & QTEST_FLAG_PACKET_SPLIT) != 0) { 254 BIO *pktsplitbio = BIO_new(bio_f_pkt_split_dgram_filter()); 255 256 if (!TEST_ptr(pktsplitbio)) 257 goto err; 258 cbio = BIO_push(pktsplitbio, cbio); 259 BIO_set_data(pktsplitbio, bdata); 260 261 pktsplitbio = BIO_new(bio_f_pkt_split_dgram_filter()); 262 if (!TEST_ptr(pktsplitbio)) 263 goto err; 264 sbio = BIO_push(pktsplitbio, sbio); 265 BIO_set_data(pktsplitbio, bdata); 266 } 267 268 if ((flags & QTEST_FLAG_NOISE) != 0) { 269 BIO *noisebio; 270 struct bio_noise_now_cb_st now_cb = { fake_now_cb, NULL }; 271 272 /* 273 * It is an error to not have a QTEST_FAULT object when introducing noise 274 */ 275 if (!TEST_ptr(fault)) 276 goto err; 277 278 noisebio = BIO_new(bio_f_noisy_dgram_filter()); 279 280 if (!TEST_ptr(noisebio)) 281 goto err; 282 cbio = BIO_push(noisebio, cbio); 283 if ((flags & QTEST_FLAG_FAKE_TIME) != 0) { 284 if (!TEST_int_eq(BIO_ctrl(cbio, BIO_CTRL_NOISE_SET_NOW_CB, 285 0, &now_cb), 1)) 286 goto err; 287 } 288 289 noisebio = BIO_new(bio_f_noisy_dgram_filter()); 290 291 if (!TEST_ptr(noisebio)) 292 goto err; 293 sbio = BIO_push(noisebio, sbio); 294 if ((flags & QTEST_FLAG_FAKE_TIME) != 0) { 295 if (!TEST_int_eq(BIO_ctrl(sbio, BIO_CTRL_NOISE_SET_NOW_CB, 296 0, &now_cb), 1)) 297 goto err; 298 } 299 300 (void)BIO_ctrl(sbio, BIO_CTRL_NOISE_BACK_OFF, 2, NULL); 301 302 (*fault)->noiseargs.cbio = cbio; 303 (*fault)->noiseargs.sbio = sbio; 304 (*fault)->noiseargs.tracebio = tmpbio; 305 (*fault)->noiseargs.flags = flags; 306 307 SSL_set_msg_callback(*cssl, noise_msg_callback); 308 SSL_set_msg_callback_arg(*cssl, &(*fault)->noiseargs); 309 } 310 311 SSL_set_bio(*cssl, cbio, cbio); 312 313 if (!TEST_true(SSL_set_blocking_mode(*cssl, 314 (flags & QTEST_FLAG_BLOCK) != 0 ? 1 : 0))) 315 goto err; 316 317 if (!TEST_true(SSL_set1_initial_peer_addr(*cssl, peeraddr))) 318 goto err; 319 320 fisbio = BIO_new(qtest_get_bio_method()); 321 if (!TEST_ptr(fisbio)) 322 goto err; 323 324 BIO_set_data(fisbio, bdata); 325 326 if (!BIO_up_ref(sbio)) 327 goto err; 328 if (!TEST_ptr(BIO_push(fisbio, sbio))) { 329 BIO_free(sbio); 330 goto err; 331 } 332 333 tserver_args.libctx = libctx; 334 tserver_args.net_rbio = sbio; 335 tserver_args.net_wbio = fisbio; 336 tserver_args.alpn = NULL; 337 if (serverctx != NULL && !TEST_true(SSL_CTX_up_ref(serverctx))) 338 goto err; 339 tserver_args.ctx = serverctx; 340 if (fake_now_lock == NULL) { 341 fake_now_lock = CRYPTO_THREAD_lock_new(); 342 if (fake_now_lock == NULL) 343 goto err; 344 } 345 if ((flags & QTEST_FLAG_FAKE_TIME) != 0) { 346 using_fake_time = 1; 347 qtest_reset_time(); 348 tserver_args.now_cb = fake_now_cb; 349 (void)ossl_quic_set_override_now_cb(*cssl, fake_now_cb, NULL); 350 } else { 351 using_fake_time = 0; 352 } 353 354 if (!TEST_ptr(*qtserv = ossl_quic_tserver_new(&tserver_args, certfile, 355 keyfile))) 356 goto err; 357 358 bdata->short_conn_id_len = ossl_quic_tserver_get_short_header_conn_id_len(*qtserv); 359 /* Ownership of fisbio and sbio is now held by *qtserv */ 360 sbio = NULL; 361 fisbio = NULL; 362 363 if ((flags & QTEST_FLAG_NOISE) != 0) 364 ossl_quic_tserver_set_msg_callback(*qtserv, noise_msg_callback, 365 &(*fault)->noiseargs); 366 367 if (fault != NULL) 368 (*fault)->qtserv = *qtserv; 369 370 BIO_ADDR_free(peeraddr); 371 372 return 1; 373 err: 374 SSL_CTX_free(tserver_args.ctx); 375 BIO_ADDR_free(peeraddr); 376 BIO_free_all(cbio); 377 BIO_free_all(fisbio); 378 BIO_free_all(sbio); 379 SSL_free(*cssl); 380 *cssl = NULL; 381 ossl_quic_tserver_free(*qtserv); 382 if (fault != NULL) 383 OPENSSL_free(*fault); 384 OPENSSL_free(bdata); 385 BIO_free(tmpbio); 386 if (tracebio != NULL) 387 *tracebio = NULL; 388 389 return 0; 390 } 391 392 void qtest_add_time(uint64_t millis) 393 { 394 if (!CRYPTO_THREAD_write_lock(fake_now_lock)) 395 return; 396 fake_now = ossl_time_add(fake_now, ossl_ms2time(millis)); 397 CRYPTO_THREAD_unlock(fake_now_lock); 398 } 399 400 static OSSL_TIME qtest_get_time(void) 401 { 402 OSSL_TIME ret; 403 404 if (!CRYPTO_THREAD_read_lock(fake_now_lock)) 405 return ossl_time_zero(); 406 ret = fake_now; 407 CRYPTO_THREAD_unlock(fake_now_lock); 408 return ret; 409 } 410 411 static void qtest_reset_time(void) 412 { 413 if (!CRYPTO_THREAD_write_lock(fake_now_lock)) 414 return; 415 fake_now = ossl_time_zero(); 416 CRYPTO_THREAD_unlock(fake_now_lock); 417 /* zero time can have a special meaning, bump it */ 418 qtest_add_time(1); 419 } 420 421 void qtest_start_stopwatch(void) 422 { 423 start_time = qtest_get_time(); 424 } 425 426 uint64_t qtest_get_stopwatch_time(void) 427 { 428 return ossl_time2ms(ossl_time_subtract(qtest_get_time(), start_time)); 429 } 430 431 QTEST_FAULT *qtest_create_injector(QUIC_TSERVER *ts) 432 { 433 QTEST_FAULT *f; 434 435 f = OPENSSL_zalloc(sizeof(*f)); 436 if (f == NULL) 437 return NULL; 438 439 f->qtserv = ts; 440 return f; 441 442 } 443 444 int qtest_supports_blocking(void) 445 { 446 #if !defined(OPENSSL_NO_POSIX_IO) && defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) 447 return 1; 448 #else 449 return 0; 450 #endif 451 } 452 453 #define MAXLOOPS 1000 454 455 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) 456 static int globserverret = 0; 457 static TSAN_QUALIFIER int abortserverthread = 0; 458 static QUIC_TSERVER *globtserv; 459 static const thread_t thread_zero; 460 static void run_server_thread(void) 461 { 462 /* 463 * This will operate in a busy loop because the server does not block, 464 * but should be acceptable because it is local and we expect this to be 465 * fast 466 */ 467 globserverret = qtest_create_quic_connection(globtserv, NULL); 468 } 469 #endif 470 471 int qtest_wait_for_timeout(SSL *s, QUIC_TSERVER *qtserv) 472 { 473 struct timeval tv; 474 OSSL_TIME ctimeout, stimeout, mintimeout, now; 475 int cinf; 476 477 /* We don't need to wait in blocking mode */ 478 if (s == NULL || SSL_get_blocking_mode(s)) 479 return 1; 480 481 /* Don't wait if either BIO has data waiting */ 482 if (BIO_pending(SSL_get_rbio(s)) > 0 483 || BIO_pending(ossl_quic_tserver_get0_rbio(qtserv)) > 0) 484 return 1; 485 486 /* 487 * Neither endpoint has data waiting to be read. We assume data transmission 488 * is instantaneous due to using mem based BIOs, so there is no data "in 489 * flight" and no more data will be sent by either endpoint until some time 490 * based event has occurred. Therefore, wait for a timeout to occur. This 491 * might happen if we are using the noisy BIO and datagrams have been lost. 492 */ 493 if (!SSL_get_event_timeout(s, &tv, &cinf)) 494 return 0; 495 496 if (using_fake_time) 497 now = qtest_get_time(); 498 else 499 now = ossl_time_now(); 500 501 ctimeout = cinf ? ossl_time_infinite() : ossl_time_from_timeval(tv); 502 stimeout = ossl_time_subtract(ossl_quic_tserver_get_deadline(qtserv), now); 503 mintimeout = ossl_time_min(ctimeout, stimeout); 504 if (ossl_time_is_infinite(mintimeout)) 505 return 0; 506 507 if (using_fake_time) 508 qtest_add_time(ossl_time2ms(mintimeout)); 509 else 510 OSSL_sleep(ossl_time2ms(mintimeout)); 511 512 return 1; 513 } 514 515 int qtest_create_quic_connection_ex(QUIC_TSERVER *qtserv, SSL *clientssl, 516 int wanterr) 517 { 518 int retc = -1, rets = 0, abortctr = 0, ret = 0; 519 int clienterr = 0, servererr = 0; 520 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) 521 522 /* 523 * Pointless initialisation to avoid bogus compiler warnings about using 524 * t uninitialised 525 */ 526 thread_t t = thread_zero; 527 528 if (clientssl != NULL) 529 abortserverthread = 0; 530 531 /* 532 * Only set the client_ready flag to zero if we are the client 533 */ 534 if (clientssl != NULL) { 535 ossl_crypto_mutex_lock(client_ready_mutex); 536 client_ready = 0; 537 ossl_crypto_mutex_unlock(client_ready_mutex); 538 } 539 #endif 540 541 if (!TEST_ptr(qtserv)) { 542 goto err; 543 } else if (clientssl == NULL) { 544 retc = 1; 545 } else if (SSL_get_blocking_mode(clientssl) > 0) { 546 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) 547 /* 548 * clientssl is blocking. We will need a thread to complete the 549 * connection 550 */ 551 globtserv = qtserv; 552 if (!TEST_true(run_thread(&t, run_server_thread))) 553 goto err; 554 555 qtserv = NULL; 556 rets = 1; 557 #else 558 TEST_error("No thread support in this build"); 559 goto err; 560 #endif 561 } 562 563 do { 564 if (!clienterr && retc <= 0) { 565 int err; 566 567 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) 568 ossl_crypto_mutex_lock(client_ready_mutex); 569 client_ready = 1; 570 ossl_crypto_condvar_broadcast(client_ready_cond); 571 ossl_crypto_mutex_unlock(client_ready_mutex); 572 #endif 573 retc = SSL_connect(clientssl); 574 if (retc <= 0) { 575 err = SSL_get_error(clientssl, retc); 576 577 if (err == wanterr) { 578 retc = 1; 579 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) 580 if (qtserv == NULL && rets > 0) 581 tsan_store(&abortserverthread, 1); 582 else 583 #endif 584 rets = 1; 585 } else { 586 if (err != SSL_ERROR_WANT_READ 587 && err != SSL_ERROR_WANT_WRITE) { 588 TEST_info("SSL_connect() failed %d, %d", retc, err); 589 TEST_openssl_errors(); 590 clienterr = 1; 591 } 592 } 593 } 594 } 595 596 qtest_add_time(1); 597 if (clientssl != NULL) 598 SSL_handle_events(clientssl); 599 if (qtserv != NULL) { 600 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) 601 ossl_crypto_mutex_lock(client_ready_mutex); 602 for (;;) { 603 if (client_ready == 1) 604 break; 605 ossl_crypto_condvar_wait(client_ready_cond, client_ready_mutex); 606 } 607 ossl_crypto_mutex_unlock(client_ready_mutex); 608 #endif 609 ossl_quic_tserver_tick(qtserv); 610 } 611 612 if (!servererr && rets <= 0) { 613 servererr = ossl_quic_tserver_is_term_any(qtserv); 614 if (!servererr) 615 rets = ossl_quic_tserver_is_handshake_confirmed(qtserv); 616 } 617 618 if (clienterr && servererr) 619 goto err; 620 621 if (clientssl != NULL && ++abortctr == MAXLOOPS) { 622 TEST_info("No progress made"); 623 goto err; 624 } 625 626 if ((retc <= 0 && !clienterr) || (rets <= 0 && !servererr)) { 627 if (!qtest_wait_for_timeout(clientssl, qtserv)) 628 goto err; 629 } 630 } while ((retc <= 0 && !clienterr) 631 || (rets <= 0 && !servererr 632 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) 633 && !tsan_load(&abortserverthread) 634 #endif 635 )); 636 637 if (qtserv == NULL && rets > 0) { 638 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) 639 /* 640 * Make sure we unblock the server before we wait on completion here 641 * in case it didn't happen in the connect loop above 642 */ 643 ossl_crypto_mutex_lock(client_ready_mutex); 644 client_ready = 1; 645 ossl_crypto_condvar_broadcast(client_ready_cond); 646 ossl_crypto_mutex_unlock(client_ready_mutex); 647 if (!TEST_true(wait_for_thread(t)) || !TEST_true(globserverret)) 648 goto err; 649 #else 650 TEST_error("Should not happen"); 651 goto err; 652 #endif 653 } 654 655 if (!clienterr && !servererr) 656 ret = 1; 657 err: 658 return ret; 659 } 660 661 int qtest_create_quic_connection(QUIC_TSERVER *qtserv, SSL *clientssl) 662 { 663 return qtest_create_quic_connection_ex(qtserv, clientssl, SSL_ERROR_NONE); 664 } 665 666 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) 667 static TSAN_QUALIFIER int shutdowndone; 668 669 static void run_server_shutdown_thread(void) 670 { 671 /* 672 * This will operate in a busy loop because the server does not block, 673 * but should be acceptable because it is local and we expect this to be 674 * fast 675 */ 676 do { 677 ossl_quic_tserver_tick(globtserv); 678 } while(!tsan_load(&shutdowndone)); 679 } 680 #endif 681 682 int qtest_shutdown(QUIC_TSERVER *qtserv, SSL *clientssl) 683 { 684 int tickserver = 1; 685 int ret = 0; 686 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) 687 /* 688 * Pointless initialisation to avoid bogus compiler warnings about using 689 * t uninitialised 690 */ 691 thread_t t = thread_zero; 692 693 ossl_crypto_condvar_free(&client_ready_cond); 694 client_ready_cond = NULL; 695 ossl_crypto_mutex_free(&client_ready_mutex); 696 client_ready_mutex = NULL; 697 #endif 698 699 if (SSL_get_blocking_mode(clientssl) > 0) { 700 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) 701 /* 702 * clientssl is blocking. We will need a thread to complete the 703 * connection 704 */ 705 globtserv = qtserv; 706 shutdowndone = 0; 707 if (!TEST_true(run_thread(&t, run_server_shutdown_thread))) 708 return 0; 709 710 tickserver = 0; 711 #else 712 TEST_error("No thread support in this build"); 713 return 0; 714 #endif 715 } 716 717 /* Busy loop in non-blocking mode. It should be quick because its local */ 718 for (;;) { 719 int rc = SSL_shutdown(clientssl); 720 721 if (rc == 1) { 722 ret = 1; 723 break; 724 } 725 726 if (rc < 0) 727 break; 728 729 if (tickserver) 730 ossl_quic_tserver_tick(qtserv); 731 } 732 733 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) 734 tsan_store(&shutdowndone, 1); 735 if (!tickserver) { 736 if (!TEST_true(wait_for_thread(t))) 737 ret = 0; 738 } 739 #endif 740 741 return ret; 742 } 743 744 int qtest_check_server_transport_err(QUIC_TSERVER *qtserv, uint64_t code) 745 { 746 const QUIC_TERMINATE_CAUSE *cause; 747 748 ossl_quic_tserver_tick(qtserv); 749 750 /* 751 * Check that the server has closed with the specified code from the client 752 */ 753 if (!TEST_true(ossl_quic_tserver_is_term_any(qtserv))) 754 return 0; 755 756 cause = ossl_quic_tserver_get_terminate_cause(qtserv); 757 if (!TEST_ptr(cause) 758 || !TEST_true(cause->remote) 759 || !TEST_false(cause->app) 760 || !TEST_uint64_t_eq(cause->error_code, code)) 761 return 0; 762 763 return 1; 764 } 765 766 int qtest_check_server_protocol_err(QUIC_TSERVER *qtserv) 767 { 768 return qtest_check_server_transport_err(qtserv, OSSL_QUIC_ERR_PROTOCOL_VIOLATION); 769 } 770 771 int qtest_check_server_frame_encoding_err(QUIC_TSERVER *qtserv) 772 { 773 return qtest_check_server_transport_err(qtserv, OSSL_QUIC_ERR_FRAME_ENCODING_ERROR); 774 } 775 776 void qtest_fault_free(QTEST_FAULT *fault) 777 { 778 if (fault == NULL) 779 return; 780 781 packet_plain_finish(fault); 782 handshake_finish(fault); 783 784 OPENSSL_free(fault); 785 } 786 787 static int packet_plain_mutate(const QUIC_PKT_HDR *hdrin, 788 const OSSL_QTX_IOVEC *iovecin, size_t numin, 789 QUIC_PKT_HDR **hdrout, 790 const OSSL_QTX_IOVEC **iovecout, 791 size_t *numout, 792 void *arg) 793 { 794 QTEST_FAULT *fault = arg; 795 size_t i, bufsz = 0; 796 unsigned char *cur; 797 int grow_allowance; 798 799 /* Coalesce our data into a single buffer */ 800 801 /* First calculate required buffer size */ 802 for (i = 0; i < numin; i++) 803 bufsz += iovecin[i].buf_len; 804 805 fault->pplainio.buf_len = bufsz; 806 807 /* 808 * 1200 is QUIC payload length we use 809 * bufsz is what we got from txp 810 * 16 is the length of tag added by encryption 811 * 14 long header (we assume token length is 0, 812 * which is fine for server not so fine for client) 813 */ 814 grow_allowance = 1200 - bufsz - 16 - 14; 815 grow_allowance -= hdrin->dst_conn_id.id_len; 816 grow_allowance -= hdrin->src_conn_id.id_len; 817 assert(grow_allowance >= 0); 818 bufsz += grow_allowance; 819 820 fault->pplainio.buf = cur = OPENSSL_malloc(bufsz); 821 if (cur == NULL) { 822 fault->pplainio.buf_len = 0; 823 return 0; 824 } 825 826 fault->pplainbuf_alloc = bufsz; 827 828 /* Copy in the data from the input buffers */ 829 for (i = 0; i < numin; i++) { 830 memcpy(cur, iovecin[i].buf, iovecin[i].buf_len); 831 cur += iovecin[i].buf_len; 832 } 833 834 fault->pplainhdr = *hdrin; 835 836 /* 837 * Cast below is safe because we allocated the buffer 838 * mutation is best effort. we can inject frame if 839 * there is enough space. If there is not enough space 840 * we must give up. 841 */ 842 if (fault->pplaincb != NULL) 843 fault->pplaincb(fault, &fault->pplainhdr, 844 (unsigned char *)fault->pplainio.buf, 845 fault->pplainio.buf_len, fault->pplaincbarg); 846 847 *hdrout = &fault->pplainhdr; 848 *iovecout = &fault->pplainio; 849 *numout = 1; 850 851 return 1; 852 } 853 854 static void packet_plain_finish(void *arg) 855 { 856 QTEST_FAULT *fault = arg; 857 858 /* Cast below is safe because we allocated the buffer */ 859 OPENSSL_free((unsigned char *)fault->pplainio.buf); 860 fault->pplainio.buf_len = 0; 861 fault->pplainbuf_alloc = 0; 862 fault->pplainio.buf = NULL; 863 } 864 865 int qtest_fault_set_packet_plain_listener(QTEST_FAULT *fault, 866 qtest_fault_on_packet_plain_cb pplaincb, 867 void *pplaincbarg) 868 { 869 fault->pplaincb = pplaincb; 870 fault->pplaincbarg = pplaincbarg; 871 872 return ossl_quic_tserver_set_plain_packet_mutator(fault->qtserv, 873 packet_plain_mutate, 874 packet_plain_finish, 875 fault); 876 } 877 878 /* To be called from a packet_plain_listener callback */ 879 int qtest_fault_resize_plain_packet(QTEST_FAULT *fault, size_t newlen) 880 { 881 unsigned char *buf; 882 size_t oldlen = fault->pplainio.buf_len; 883 884 /* 885 * Alloc'd size should always be non-zero, so if this fails we've been 886 * incorrectly called 887 */ 888 if (fault->pplainbuf_alloc == 0) 889 return 0; 890 891 if (newlen > fault->pplainbuf_alloc) { 892 /* This exceeds our growth allowance. Fail */ 893 return 0; 894 } 895 896 /* Cast below is safe because we allocated the buffer */ 897 buf = (unsigned char *)fault->pplainio.buf; 898 899 if (newlen > oldlen) { 900 /* Extend packet with 0 bytes */ 901 memset(buf + oldlen, 0, newlen - oldlen); 902 } /* else we're truncating or staying the same */ 903 904 fault->pplainio.buf_len = newlen; 905 fault->pplainhdr.len = newlen; 906 907 return 1; 908 } 909 910 /* 911 * Prepend frame data into a packet. To be called from a packet_plain_listener 912 * callback 913 */ 914 int qtest_fault_prepend_frame(QTEST_FAULT *fault, const unsigned char *frame, 915 size_t frame_len) 916 { 917 unsigned char *buf; 918 size_t old_len; 919 920 /* 921 * Alloc'd size should always be non-zero, so if this fails we've been 922 * incorrectly called 923 */ 924 if (fault->pplainbuf_alloc == 0) 925 return 0; 926 927 /* Cast below is safe because we allocated the buffer */ 928 buf = (unsigned char *)fault->pplainio.buf; 929 old_len = fault->pplainio.buf_len; 930 931 /* Extend the size of the packet by the size of the new frame */ 932 if (!TEST_true(qtest_fault_resize_plain_packet(fault, 933 old_len + frame_len))) 934 return 0; 935 936 memmove(buf + frame_len, buf, old_len); 937 memcpy(buf, frame, frame_len); 938 939 return 1; 940 } 941 942 static int handshake_mutate(const unsigned char *msgin, size_t msginlen, 943 unsigned char **msgout, size_t *msgoutlen, 944 void *arg) 945 { 946 QTEST_FAULT *fault = arg; 947 unsigned char *buf; 948 unsigned long payloadlen; 949 unsigned int msgtype; 950 PACKET pkt; 951 952 buf = OPENSSL_malloc(msginlen + GROWTH_ALLOWANCE); 953 if (buf == NULL) 954 return 0; 955 956 fault->handbuf = buf; 957 fault->handbuflen = msginlen; 958 fault->handbufalloc = msginlen + GROWTH_ALLOWANCE; 959 memcpy(buf, msgin, msginlen); 960 961 if (!PACKET_buf_init(&pkt, buf, msginlen) 962 || !PACKET_get_1(&pkt, &msgtype) 963 || !PACKET_get_net_3(&pkt, &payloadlen) 964 || PACKET_remaining(&pkt) != payloadlen) 965 return 0; 966 967 /* Parse specific message types */ 968 switch (msgtype) { 969 case SSL3_MT_ENCRYPTED_EXTENSIONS: 970 { 971 QTEST_ENCRYPTED_EXTENSIONS ee; 972 973 if (fault->encextcb == NULL) 974 break; 975 976 /* 977 * The EncryptedExtensions message is very simple. It just has an 978 * extensions block in it and nothing else. 979 */ 980 ee.extensions = (unsigned char *)PACKET_data(&pkt); 981 ee.extensionslen = payloadlen; 982 if (!fault->encextcb(fault, &ee, payloadlen, fault->encextcbarg)) 983 return 0; 984 } 985 986 default: 987 /* No specific handlers for these message types yet */ 988 break; 989 } 990 991 if (fault->handshakecb != NULL 992 && !fault->handshakecb(fault, buf, fault->handbuflen, 993 fault->handshakecbarg)) 994 return 0; 995 996 *msgout = buf; 997 *msgoutlen = fault->handbuflen; 998 999 return 1; 1000 } 1001 1002 static void handshake_finish(void *arg) 1003 { 1004 QTEST_FAULT *fault = arg; 1005 1006 OPENSSL_free(fault->handbuf); 1007 fault->handbuf = NULL; 1008 } 1009 1010 int qtest_fault_set_handshake_listener(QTEST_FAULT *fault, 1011 qtest_fault_on_handshake_cb handshakecb, 1012 void *handshakecbarg) 1013 { 1014 fault->handshakecb = handshakecb; 1015 fault->handshakecbarg = handshakecbarg; 1016 1017 return ossl_quic_tserver_set_handshake_mutator(fault->qtserv, 1018 handshake_mutate, 1019 handshake_finish, 1020 fault); 1021 } 1022 1023 int qtest_fault_set_hand_enc_ext_listener(QTEST_FAULT *fault, 1024 qtest_fault_on_enc_ext_cb encextcb, 1025 void *encextcbarg) 1026 { 1027 fault->encextcb = encextcb; 1028 fault->encextcbarg = encextcbarg; 1029 1030 return ossl_quic_tserver_set_handshake_mutator(fault->qtserv, 1031 handshake_mutate, 1032 handshake_finish, 1033 fault); 1034 } 1035 1036 /* To be called from a handshake_listener callback */ 1037 int qtest_fault_resize_handshake(QTEST_FAULT *fault, size_t newlen) 1038 { 1039 unsigned char *buf; 1040 size_t oldlen = fault->handbuflen; 1041 1042 /* 1043 * Alloc'd size should always be non-zero, so if this fails we've been 1044 * incorrectly called 1045 */ 1046 if (fault->handbufalloc == 0) 1047 return 0; 1048 1049 if (newlen > fault->handbufalloc) { 1050 /* This exceeds our growth allowance. Fail */ 1051 return 0; 1052 } 1053 1054 buf = (unsigned char *)fault->handbuf; 1055 1056 if (newlen > oldlen) { 1057 /* Extend packet with 0 bytes */ 1058 memset(buf + oldlen, 0, newlen - oldlen); 1059 } /* else we're truncating or staying the same */ 1060 1061 fault->handbuflen = newlen; 1062 return 1; 1063 } 1064 1065 /* To be called from message specific listener callbacks */ 1066 int qtest_fault_resize_message(QTEST_FAULT *fault, size_t newlen) 1067 { 1068 /* First resize the underlying message */ 1069 if (!qtest_fault_resize_handshake(fault, newlen + SSL3_HM_HEADER_LENGTH)) 1070 return 0; 1071 1072 /* Fixup the handshake message header */ 1073 fault->handbuf[1] = (unsigned char)((newlen >> 16) & 0xff); 1074 fault->handbuf[2] = (unsigned char)((newlen >> 8) & 0xff); 1075 fault->handbuf[3] = (unsigned char)((newlen ) & 0xff); 1076 1077 return 1; 1078 } 1079 1080 int qtest_fault_delete_extension(QTEST_FAULT *fault, 1081 unsigned int exttype, unsigned char *ext, 1082 size_t *extlen, 1083 BUF_MEM *old_ext) 1084 { 1085 PACKET pkt, sub, subext; 1086 WPACKET old_ext_wpkt; 1087 unsigned int type; 1088 const unsigned char *start, *end; 1089 size_t newlen, w; 1090 size_t msglen = fault->handbuflen; 1091 1092 if (!PACKET_buf_init(&pkt, ext, *extlen)) 1093 return 0; 1094 1095 /* Extension block starts with 2 bytes for extension block length */ 1096 if (!PACKET_as_length_prefixed_2(&pkt, &sub)) 1097 return 0; 1098 1099 do { 1100 start = PACKET_data(&sub); 1101 if (!PACKET_get_net_2(&sub, &type) 1102 || !PACKET_get_length_prefixed_2(&sub, &subext)) 1103 return 0; 1104 } while (type != exttype); 1105 1106 /* Found it */ 1107 end = PACKET_data(&sub); 1108 1109 if (old_ext != NULL) { 1110 if (!WPACKET_init(&old_ext_wpkt, old_ext)) 1111 return 0; 1112 1113 if (!WPACKET_memcpy(&old_ext_wpkt, PACKET_data(&subext), 1114 PACKET_remaining(&subext)) 1115 || !WPACKET_get_total_written(&old_ext_wpkt, &w)) { 1116 WPACKET_cleanup(&old_ext_wpkt); 1117 return 0; 1118 } 1119 1120 WPACKET_finish(&old_ext_wpkt); 1121 old_ext->length = w; 1122 } 1123 1124 /* 1125 * If we're not the last extension we need to move the rest earlier. The 1126 * cast below is safe because we own the underlying buffer and we're no 1127 * longer making PACKET calls. 1128 */ 1129 if (end < ext + *extlen) 1130 memmove((unsigned char *)start, end, end - start); 1131 1132 /* 1133 * Calculate new extensions payload length = 1134 * Original length 1135 * - 2 extension block length bytes 1136 * - length of removed extension 1137 */ 1138 newlen = *extlen - 2 - (end - start); 1139 1140 /* Fixup the length bytes for the extension block */ 1141 ext[0] = (unsigned char)((newlen >> 8) & 0xff); 1142 ext[1] = (unsigned char)((newlen ) & 0xff); 1143 1144 /* 1145 * Length of the whole extension block is the new payload length plus the 1146 * 2 bytes for the length 1147 */ 1148 *extlen = newlen + 2; 1149 1150 /* We can now resize the message */ 1151 if ((size_t)(end - start) + SSL3_HM_HEADER_LENGTH > msglen) 1152 return 0; /* Should not happen */ 1153 msglen -= (end - start) + SSL3_HM_HEADER_LENGTH; 1154 if (!qtest_fault_resize_message(fault, msglen)) 1155 return 0; 1156 1157 return 1; 1158 } 1159 1160 #define BIO_TYPE_CIPHER_PACKET_FILTER (0x80 | BIO_TYPE_FILTER) 1161 1162 static BIO_METHOD *pcipherbiometh = NULL; 1163 1164 # define BIO_MSG_N(array, stride, n) (*(BIO_MSG *)((char *)(array) + (n)*(stride))) 1165 1166 static int pcipher_sendmmsg(BIO *b, BIO_MSG *msg, size_t stride, 1167 size_t num_msg, uint64_t flags, 1168 size_t *num_processed) 1169 { 1170 BIO *next = BIO_next(b); 1171 ossl_ssize_t ret = 0; 1172 size_t i = 0, tmpnump; 1173 QUIC_PKT_HDR hdr; 1174 PACKET pkt; 1175 unsigned char *tmpdata; 1176 QTEST_DATA *bdata = NULL; 1177 1178 if (next == NULL) 1179 return 0; 1180 1181 bdata = BIO_get_data(b); 1182 if (bdata == NULL || bdata->fault == NULL 1183 || (bdata->fault->pciphercb == NULL && bdata->fault->datagramcb == NULL)) 1184 return BIO_sendmmsg(next, msg, stride, num_msg, flags, num_processed); 1185 1186 if (num_msg == 0) { 1187 *num_processed = 0; 1188 return 1; 1189 } 1190 1191 for (i = 0; i < num_msg; ++i) { 1192 bdata->fault->msg = BIO_MSG_N(msg, stride, i); 1193 1194 /* Take a copy of the data so that callbacks can modify it */ 1195 tmpdata = OPENSSL_malloc(bdata->fault->msg.data_len + GROWTH_ALLOWANCE); 1196 if (tmpdata == NULL) 1197 return 0; 1198 memcpy(tmpdata, bdata->fault->msg.data, bdata->fault->msg.data_len); 1199 bdata->fault->msg.data = tmpdata; 1200 bdata->fault->msgalloc = bdata->fault->msg.data_len + GROWTH_ALLOWANCE; 1201 1202 if (bdata->fault->pciphercb != NULL) { 1203 if (!PACKET_buf_init(&pkt, bdata->fault->msg.data, bdata->fault->msg.data_len)) 1204 return 0; 1205 1206 do { 1207 if (!ossl_quic_wire_decode_pkt_hdr(&pkt, 1208 bdata->short_conn_id_len, 1209 1, 0, &hdr, NULL, NULL)) 1210 goto out; 1211 1212 /* 1213 * hdr.data is const - but its our buffer so casting away the 1214 * const is safe 1215 */ 1216 if (!bdata->fault->pciphercb(bdata->fault, &hdr, 1217 (unsigned char *)hdr.data, hdr.len, 1218 bdata->fault->pciphercbarg)) 1219 goto out; 1220 1221 /* 1222 * At the moment modifications to hdr by the callback 1223 * are ignored. We might need to rewrite the QUIC header to 1224 * enable tests to change this. We also don't yet have a 1225 * mechanism for the callback to change the encrypted data 1226 * length. It's not clear if that's needed or not. 1227 */ 1228 } while (PACKET_remaining(&pkt) > 0); 1229 } 1230 1231 if (bdata->fault->datagramcb != NULL 1232 && !bdata->fault->datagramcb(bdata->fault, &bdata->fault->msg, stride, 1233 bdata->fault->datagramcbarg)) 1234 goto out; 1235 1236 if (!BIO_sendmmsg(next, &bdata->fault->msg, stride, 1, flags, &tmpnump)) { 1237 *num_processed = i; 1238 goto out; 1239 } 1240 1241 OPENSSL_free(bdata->fault->msg.data); 1242 bdata->fault->msg.data = NULL; 1243 bdata->fault->msgalloc = 0; 1244 } 1245 1246 *num_processed = i; 1247 out: 1248 ret = i > 0; 1249 OPENSSL_free(bdata->fault->msg.data); 1250 bdata->fault->msg.data = NULL; 1251 return ret; 1252 } 1253 1254 static long pcipher_ctrl(BIO *b, int cmd, long larg, void *parg) 1255 { 1256 BIO *next = BIO_next(b); 1257 1258 if (next == NULL) 1259 return -1; 1260 1261 return BIO_ctrl(next, cmd, larg, parg); 1262 } 1263 1264 static int pcipher_destroy(BIO *b) 1265 { 1266 OPENSSL_free(BIO_get_data(b)); 1267 return 1; 1268 } 1269 1270 BIO_METHOD *qtest_get_bio_method(void) 1271 { 1272 BIO_METHOD *tmp; 1273 1274 if (pcipherbiometh != NULL) 1275 return pcipherbiometh; 1276 1277 tmp = BIO_meth_new(BIO_TYPE_CIPHER_PACKET_FILTER, "Cipher Packet Filter"); 1278 1279 if (!TEST_ptr(tmp)) 1280 return NULL; 1281 1282 if (!TEST_true(BIO_meth_set_sendmmsg(tmp, pcipher_sendmmsg)) 1283 || !TEST_true(BIO_meth_set_ctrl(tmp, pcipher_ctrl)) 1284 || !TEST_true(BIO_meth_set_destroy(tmp, pcipher_destroy))) 1285 goto err; 1286 1287 pcipherbiometh = tmp; 1288 tmp = NULL; 1289 err: 1290 BIO_meth_free(tmp); 1291 return pcipherbiometh; 1292 } 1293 1294 int qtest_fault_set_packet_cipher_listener(QTEST_FAULT *fault, 1295 qtest_fault_on_packet_cipher_cb pciphercb, 1296 void *pciphercbarg) 1297 { 1298 fault->pciphercb = pciphercb; 1299 fault->pciphercbarg = pciphercbarg; 1300 1301 return 1; 1302 } 1303 1304 int qtest_fault_set_datagram_listener(QTEST_FAULT *fault, 1305 qtest_fault_on_datagram_cb datagramcb, 1306 void *datagramcbarg) 1307 { 1308 fault->datagramcb = datagramcb; 1309 fault->datagramcbarg = datagramcbarg; 1310 1311 return 1; 1312 } 1313 1314 /* To be called from a datagram_listener callback */ 1315 int qtest_fault_resize_datagram(QTEST_FAULT *fault, size_t newlen) 1316 { 1317 if (newlen > fault->msgalloc) 1318 return 0; 1319 1320 if (newlen > fault->msg.data_len) 1321 memset((unsigned char *)fault->msg.data + fault->msg.data_len, 0, 1322 newlen - fault->msg.data_len); 1323 1324 fault->msg.data_len = newlen; 1325 1326 return 1; 1327 } 1328 1329 int qtest_fault_set_bw_limit(QTEST_FAULT *fault, 1330 size_t ctos_bw, size_t stoc_bw, 1331 int noise_rate) 1332 { 1333 BIO *sbio = fault->noiseargs.sbio; 1334 BIO *cbio = fault->noiseargs.cbio; 1335 1336 if (!TEST_ptr(sbio) || !TEST_ptr(cbio)) 1337 return 0; 1338 if (!TEST_int_eq(BIO_ctrl(sbio, BIO_CTRL_NOISE_RATE, noise_rate, NULL), 1)) 1339 return 0; 1340 if (!TEST_int_eq(BIO_ctrl(cbio, BIO_CTRL_NOISE_RATE, noise_rate, NULL), 1)) 1341 return 0; 1342 /* We set the bandwidth limit on the sending side */ 1343 if (!TEST_int_eq(BIO_ctrl(cbio, BIO_CTRL_NOISE_SEND_BANDWIDTH, 1344 (long)ctos_bw, NULL), 1)) 1345 return 0; 1346 if (!TEST_int_eq(BIO_ctrl(sbio, BIO_CTRL_NOISE_SEND_BANDWIDTH, 1347 (long)stoc_bw, NULL), 1)) 1348 return 0; 1349 return 1; 1350 } 1351 1352 1353 int bio_msg_copy(BIO_MSG *dst, BIO_MSG *src) 1354 { 1355 /* 1356 * Note it is assumed that the originally allocated data sizes for dst and 1357 * src are the same 1358 */ 1359 memcpy(dst->data, src->data, src->data_len); 1360 dst->data_len = src->data_len; 1361 dst->flags = src->flags; 1362 if (dst->local != NULL) { 1363 if (src->local != NULL) { 1364 if (!TEST_true(BIO_ADDR_copy(dst->local, src->local))) 1365 return 0; 1366 } else { 1367 BIO_ADDR_clear(dst->local); 1368 } 1369 } 1370 if (!TEST_true(BIO_ADDR_copy(dst->peer, src->peer))) 1371 return 0; 1372 1373 return 1; 1374 } 1375