Home | History | Annotate | Line # | Download | only in test
      1 /*
      2  * Copyright 2023 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 <string.h>
     11 #include <openssl/ssl.h>
     12 #include "helpers/quictestlib.h"
     13 #include "internal/quic_error.h"
     14 #include "testutil.h"
     15 
     16 static char *cert = NULL;
     17 static char *privkey = NULL;
     18 
     19 /*
     20  * Inject NEW_CONNECTION_ID frame
     21  */
     22 static size_t ncid_injected;
     23 static int add_ncid_frame_cb(QTEST_FAULT *fault, QUIC_PKT_HDR *hdr,
     24     unsigned char *buf, size_t len, void *cbarg)
     25 {
     26     /*
     27      * We inject NEW_CONNECTION_ID frame to trigger change of the DCID.
     28      * The connection id length must be 8, otherwise the tserver won't be
     29      * able to receive packets with this new id.
     30      */
     31     static unsigned char new_conn_id_frame[] = {
     32         0x18, /* Type */
     33         0x01, /* Sequence Number */
     34         0x01, /* Retire Prior To */
     35         0x08, /* Connection ID Length */
     36         0x33, 0x44, 0x55, 0x66, 0xde, 0xad, 0xbe, 0xef, /* Connection ID */
     37         0xab, 0xcd, 0xef, 0x01, 0x12, 0x32, 0x23, 0x45, /* Stateless Reset Token */
     38         0x56, 0x06, 0x08, 0x89, 0xa1, 0xb2, 0xc3, 0xd4
     39     };
     40 
     41     /* We only ever add the unknown frame to one packet */
     42     if (ncid_injected++)
     43         return 1;
     44 
     45     return qtest_fault_prepend_frame(fault, new_conn_id_frame,
     46         sizeof(new_conn_id_frame));
     47 }
     48 
     49 static int test_ncid_frame(int fail)
     50 {
     51     int testresult = 0;
     52     SSL_CTX *cctx = SSL_CTX_new(OSSL_QUIC_client_method());
     53     QUIC_TSERVER *qtserv = NULL;
     54     SSL *cssl = NULL;
     55     char *msg = "Hello World!";
     56     size_t msglen = strlen(msg);
     57     unsigned char buf[80];
     58     size_t byteswritten;
     59     size_t bytesread;
     60     QTEST_FAULT *fault = NULL;
     61     static const QUIC_CONN_ID conn_id = {
     62         0x08,
     63         { 0x33, 0x44, 0x55, 0x66, 0xde, 0xad, 0xbe, 0xef }
     64     };
     65 
     66     ncid_injected = 0;
     67     if (!TEST_ptr(cctx))
     68         goto err;
     69 
     70     if (!TEST_true(qtest_create_quic_objects(NULL, cctx, NULL, cert, privkey, 0,
     71             &qtserv, &cssl, &fault, NULL)))
     72         goto err;
     73 
     74     if (!TEST_true(qtest_create_quic_connection(qtserv, cssl)))
     75         goto err;
     76 
     77     if (!TEST_int_eq(SSL_write(cssl, msg, msglen), msglen))
     78         goto err;
     79 
     80     ossl_quic_tserver_tick(qtserv);
     81     if (!TEST_true(ossl_quic_tserver_read(qtserv, 0, buf, sizeof(buf),
     82             &bytesread)))
     83         goto err;
     84 
     85     /*
     86      * We assume the entire message is read from the server in one go. In
     87      * theory this could get fragmented but its a small message so we assume
     88      * not.
     89      */
     90     if (!TEST_mem_eq(msg, msglen, buf, bytesread))
     91         goto err;
     92 
     93     /*
     94      * Write a message from the server to the client and add
     95      * a NEW_CONNECTION_ID frame.
     96      */
     97     if (!TEST_true(qtest_fault_set_packet_plain_listener(fault,
     98             add_ncid_frame_cb,
     99             NULL)))
    100         goto err;
    101     if (!fail && !TEST_true(ossl_quic_tserver_set_new_local_cid(qtserv, &conn_id)))
    102         goto err;
    103     if (!TEST_true(ossl_quic_tserver_write(qtserv, 0,
    104             (unsigned char *)msg, msglen,
    105             &byteswritten)))
    106         goto err;
    107 
    108     if (!TEST_true(ncid_injected))
    109         goto err;
    110 
    111     if (!TEST_size_t_eq(msglen, byteswritten))
    112         goto err;
    113 
    114     ossl_quic_tserver_tick(qtserv);
    115     if (!TEST_true(SSL_handle_events(cssl)))
    116         goto err;
    117 
    118     if (!TEST_int_eq(SSL_read(cssl, buf, sizeof(buf)), msglen))
    119         goto err;
    120 
    121     if (!TEST_mem_eq(msg, msglen, buf, bytesread))
    122         goto err;
    123 
    124     if (!TEST_int_eq(SSL_write(cssl, msg, msglen), msglen))
    125         goto err;
    126 
    127     ossl_quic_tserver_tick(qtserv);
    128     if (!TEST_true(ossl_quic_tserver_read(qtserv, 0, buf, sizeof(buf),
    129             &bytesread)))
    130         goto err;
    131 
    132     if (fail) {
    133         if (!TEST_size_t_eq(bytesread, 0))
    134             goto err;
    135     } else {
    136         if (!TEST_mem_eq(msg, msglen, buf, bytesread))
    137             goto err;
    138     }
    139 
    140     testresult = 1;
    141 err:
    142     qtest_fault_free(fault);
    143     SSL_free(cssl);
    144     ossl_quic_tserver_free(qtserv);
    145     SSL_CTX_free(cctx);
    146     return testresult;
    147 }
    148 
    149 OPT_TEST_DECLARE_USAGE("certsdir\n")
    150 
    151 int setup_tests(void)
    152 {
    153     char *certsdir = NULL;
    154 
    155     if (!test_skip_common_options()) {
    156         TEST_error("Error parsing test options\n");
    157         return 0;
    158     }
    159 
    160     if (!TEST_ptr(certsdir = test_get_argument(0)))
    161         return 0;
    162 
    163     cert = test_mk_file_path(certsdir, "servercert.pem");
    164     if (cert == NULL)
    165         goto err;
    166 
    167     privkey = test_mk_file_path(certsdir, "serverkey.pem");
    168     if (privkey == NULL)
    169         goto err;
    170 
    171     ADD_ALL_TESTS(test_ncid_frame, 2);
    172 
    173     return 1;
    174 
    175 err:
    176     OPENSSL_free(cert);
    177     OPENSSL_free(privkey);
    178     return 0;
    179 }
    180 
    181 void cleanup_tests(void)
    182 {
    183     OPENSSL_free(cert);
    184     OPENSSL_free(privkey);
    185 }
    186