Home | History | Annotate | Line # | Download | only in test
      1 /*
      2  * Copyright 2017-2024 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 <openssl/ssl.h>
     11 #include <string.h>
     12 #include "helpers/ssltestlib.h"
     13 #include "testutil.h"
     14 #include "internal/packet.h"
     15 
     16 static char *cert = NULL;
     17 static char *privkey = NULL;
     18 
     19 static BIO *s_to_c_fbio = NULL, *c_to_s_fbio = NULL;
     20 static int chseen = 0, shseen = 0, sccsseen = 0, ccsaftersh = 0;
     21 static int ccsbeforesh = 0, sappdataseen = 0, cappdataseen = 0, badccs = 0;
     22 static int badvers = 0, badsessid = 0;
     23 
     24 static unsigned char chsessid[SSL_MAX_SSL_SESSION_ID_LENGTH];
     25 static size_t chsessidlen = 0;
     26 
     27 static int watchccs_new(BIO *bi);
     28 static int watchccs_free(BIO *a);
     29 static int watchccs_read(BIO *b, char *out, int outl);
     30 static int watchccs_write(BIO *b, const char *in, int inl);
     31 static long watchccs_ctrl(BIO *b, int cmd, long num, void *ptr);
     32 static int watchccs_gets(BIO *bp, char *buf, int size);
     33 static 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 
     38 static BIO_METHOD *method_watchccs = NULL;
     39 
     40 static 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 
     58 static int watchccs_new(BIO *bio)
     59 {
     60     BIO_set_init(bio, 1);
     61     return 1;
     62 }
     63 
     64 static int watchccs_free(BIO *bio)
     65 {
     66     BIO_set_init(bio, 0);
     67     return 1;
     68 }
     69 
     70 static 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 
     89 static 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)
    146                                 != 0))
    147                         badsessid = 1;
    148                 }
    149             } else if (msgtype == SSL3_MT_SERVER_HELLO) {
    150                 shseen++;
    151                 /*
    152                  * Skip legacy_version (2 bytes) and Random (32 bytes) to read
    153                  * session_id.
    154                  */
    155                 if (!PACKET_forward(&msgbody, 34)
    156                     || !PACKET_get_length_prefixed_1(&msgbody, &sessionid))
    157                     return 0;
    158 
    159                 /*
    160                  * Check the session id is the same as the one in the
    161                  * ClientHello
    162                  */
    163                 if (PACKET_remaining(&sessionid) != chsessidlen
    164                     || (chsessidlen > 0
    165                         && memcmp(chsessid, PACKET_data(&sessionid),
    166                                chsessidlen)
    167                             != 0))
    168                     badsessid = 1;
    169             }
    170         } else if (rectype == SSL3_RT_CHANGE_CIPHER_SPEC) {
    171             if (bio == s_to_c_fbio) {
    172                 /*
    173                  * Server writing. We shouldn't have written any app data
    174                  * yet, and we should have seen both the ClientHello and the
    175                  * ServerHello
    176                  */
    177                 if (!sappdataseen
    178                     && chseen == 1
    179                     && shseen == 1
    180                     && !sccsseen)
    181                     sccsseen = 1;
    182                 else
    183                     badccs = 1;
    184             } else if (!cappdataseen) {
    185                 /*
    186                  * Client writing. We shouldn't have written any app data
    187                  * yet, and we should have seen the ClientHello
    188                  */
    189                 if (shseen == 1 && !ccsaftersh)
    190                     ccsaftersh = 1;
    191                 else if (shseen == 0 && !ccsbeforesh)
    192                     ccsbeforesh = 1;
    193                 else
    194                     badccs = 1;
    195             } else {
    196                 badccs = 1;
    197             }
    198         } else if (rectype == SSL3_RT_APPLICATION_DATA) {
    199             if (bio == s_to_c_fbio)
    200                 sappdataseen = 1;
    201             else
    202                 cappdataseen = 1;
    203         }
    204         if (recvers != expectedrecvers)
    205             badvers = 1;
    206     }
    207 
    208     ret = BIO_write(next, in, inl);
    209     if (ret <= 0 && BIO_should_write(next))
    210         BIO_set_retry_write(bio);
    211 
    212     return ret;
    213 }
    214 
    215 static long watchccs_ctrl(BIO *bio, int cmd, long num, void *ptr)
    216 {
    217     long ret;
    218     BIO *next = BIO_next(bio);
    219 
    220     if (next == NULL)
    221         return 0;
    222 
    223     switch (cmd) {
    224     case BIO_CTRL_DUP:
    225         ret = 0;
    226         break;
    227     default:
    228         ret = BIO_ctrl(next, cmd, num, ptr);
    229         break;
    230     }
    231     return ret;
    232 }
    233 
    234 static int watchccs_gets(BIO *bio, char *buf, int size)
    235 {
    236     /* We don't support this - not needed anyway */
    237     return -1;
    238 }
    239 
    240 static int watchccs_puts(BIO *bio, const char *str)
    241 {
    242     return watchccs_write(bio, str, strlen(str));
    243 }
    244 
    245 static int test_tls13ccs(int tst)
    246 {
    247     SSL_CTX *sctx = NULL, *cctx = NULL;
    248     SSL *sssl = NULL, *cssl = NULL;
    249     int ret = 0;
    250     const char msg[] = "Dummy data";
    251     char buf[80];
    252     size_t written, readbytes;
    253     SSL_SESSION *sess = NULL;
    254 
    255     chseen = shseen = sccsseen = ccsaftersh = ccsbeforesh = 0;
    256     sappdataseen = cappdataseen = badccs = badvers = badsessid = 0;
    257     chsessidlen = 0;
    258 
    259     if (!TEST_true(create_ssl_ctx_pair(NULL, TLS_server_method(),
    260             TLS_client_method(), TLS1_VERSION, 0,
    261             &sctx, &cctx, cert, privkey))
    262         || !TEST_true(SSL_CTX_set_max_early_data(sctx,
    263             SSL3_RT_MAX_PLAIN_LENGTH)))
    264         goto err;
    265 
    266     /*
    267      * Test 0: Simple Handshake
    268      * Test 1: Simple Handshake, client middlebox compat mode disabled
    269      * Test 2: Simple Handshake, server middlebox compat mode disabled
    270      * Test 3: HRR Handshake
    271      * Test 4: HRR Handshake, client middlebox compat mode disabled
    272      * Test 5: HRR Handshake, server middlebox compat mode disabled
    273      * Test 6: Early data handshake
    274      * Test 7: Early data handshake, client middlebox compat mode disabled
    275      * Test 8: Early data handshake, server middlebox compat mode disabled
    276      * Test 9: Early data then HRR
    277      * Test 10: Early data then HRR, client middlebox compat mode disabled
    278      * Test 11: Early data then HRR, server middlebox compat mode disabled
    279      */
    280     switch (tst) {
    281     case 0:
    282     case 3:
    283     case 6:
    284     case 9:
    285         break;
    286     case 1:
    287     case 4:
    288     case 7:
    289     case 10:
    290         SSL_CTX_clear_options(cctx, SSL_OP_ENABLE_MIDDLEBOX_COMPAT);
    291         break;
    292     case 2:
    293     case 5:
    294     case 8:
    295     case 11:
    296         SSL_CTX_clear_options(sctx, SSL_OP_ENABLE_MIDDLEBOX_COMPAT);
    297         break;
    298     default:
    299         TEST_error("Invalid test value");
    300         goto err;
    301     }
    302 
    303     if (tst >= 6) {
    304         /* Get a session suitable for early_data */
    305         if (!TEST_true(create_ssl_objects(sctx, cctx, &sssl, &cssl, NULL, NULL))
    306             || !TEST_true(create_ssl_connection(sssl, cssl, SSL_ERROR_NONE)))
    307             goto err;
    308         sess = SSL_get1_session(cssl);
    309         if (!TEST_ptr(sess))
    310             goto err;
    311         SSL_shutdown(cssl);
    312         SSL_shutdown(sssl);
    313         SSL_free(sssl);
    314         SSL_free(cssl);
    315         sssl = cssl = NULL;
    316     }
    317 
    318     if ((tst >= 3 && tst <= 5) || tst >= 9) {
    319         /* HRR handshake */
    320 #if defined(OPENSSL_NO_EC)
    321 #if !defined(OPENSSL_NO_DH)
    322         if (!TEST_true(SSL_CTX_set1_groups_list(sctx, "ffdhe3072")))
    323             goto err;
    324 #endif
    325 #else
    326         if (!TEST_true(SSL_CTX_set1_groups_list(sctx, "P-384")))
    327             goto err;
    328 #endif
    329     }
    330 
    331     s_to_c_fbio = BIO_new(bio_f_watchccs_filter());
    332     c_to_s_fbio = BIO_new(bio_f_watchccs_filter());
    333     if (!TEST_ptr(s_to_c_fbio)
    334         || !TEST_ptr(c_to_s_fbio)) {
    335         BIO_free(s_to_c_fbio);
    336         BIO_free(c_to_s_fbio);
    337         goto err;
    338     }
    339 
    340     /* BIOs get freed on error */
    341     if (!TEST_true(create_ssl_objects(sctx, cctx, &sssl, &cssl, s_to_c_fbio,
    342             c_to_s_fbio)))
    343         goto err;
    344 
    345     if (tst >= 6) {
    346         /* Early data */
    347         if (!TEST_true(SSL_set_session(cssl, sess))
    348             || !TEST_true(SSL_write_early_data(cssl, msg, strlen(msg),
    349                 &written))
    350             || (tst <= 8
    351                 && !TEST_int_eq(SSL_read_early_data(sssl, buf, sizeof(buf),
    352                                     &readbytes),
    353                     SSL_READ_EARLY_DATA_SUCCESS)))
    354             goto err;
    355         if (tst <= 8) {
    356             if (!TEST_int_gt(SSL_connect(cssl), 0))
    357                 goto err;
    358         } else {
    359             if (!TEST_int_le(SSL_connect(cssl), 0))
    360                 goto err;
    361         }
    362         if (!TEST_int_eq(SSL_read_early_data(sssl, buf, sizeof(buf),
    363                              &readbytes),
    364                 SSL_READ_EARLY_DATA_FINISH))
    365             goto err;
    366     }
    367 
    368     /* Perform handshake (or complete it if doing early data ) */
    369     if (!TEST_true(create_ssl_connection(sssl, cssl, SSL_ERROR_NONE)))
    370         goto err;
    371 
    372     /*
    373      * Check there were no unexpected CCS messages, all record versions
    374      * were as expected, and that the session ids were reflected by the server
    375      * correctly.
    376      */
    377     if (!TEST_false(badccs) || !TEST_false(badvers) || !TEST_false(badsessid))
    378         goto err;
    379 
    380     switch (tst) {
    381     case 0:
    382         if (!TEST_true(sccsseen)
    383             || !TEST_true(ccsaftersh)
    384             || !TEST_false(ccsbeforesh)
    385             || !TEST_size_t_gt(chsessidlen, 0))
    386             goto err;
    387         break;
    388 
    389     case 1:
    390         if (!TEST_true(sccsseen)
    391             || !TEST_false(ccsaftersh)
    392             || !TEST_false(ccsbeforesh)
    393             || !TEST_size_t_eq(chsessidlen, 0))
    394             goto err;
    395         break;
    396 
    397     case 2:
    398         if (!TEST_false(sccsseen)
    399             || !TEST_true(ccsaftersh)
    400             || !TEST_false(ccsbeforesh)
    401             || !TEST_size_t_gt(chsessidlen, 0))
    402             goto err;
    403         break;
    404 
    405     case 3:
    406         if (!TEST_true(sccsseen)
    407             || !TEST_true(ccsaftersh)
    408             || !TEST_false(ccsbeforesh)
    409             || !TEST_size_t_gt(chsessidlen, 0))
    410             goto err;
    411         break;
    412 
    413     case 4:
    414         if (!TEST_true(sccsseen)
    415             || !TEST_false(ccsaftersh)
    416             || !TEST_false(ccsbeforesh)
    417             || !TEST_size_t_eq(chsessidlen, 0))
    418             goto err;
    419         break;
    420 
    421     case 5:
    422         if (!TEST_false(sccsseen)
    423             || !TEST_true(ccsaftersh)
    424             || !TEST_false(ccsbeforesh)
    425             || !TEST_size_t_gt(chsessidlen, 0))
    426             goto err;
    427         break;
    428 
    429     case 6:
    430         if (!TEST_true(sccsseen)
    431             || !TEST_false(ccsaftersh)
    432             || !TEST_true(ccsbeforesh)
    433             || !TEST_size_t_gt(chsessidlen, 0))
    434             goto err;
    435         break;
    436 
    437     case 7:
    438         if (!TEST_true(sccsseen)
    439             || !TEST_false(ccsaftersh)
    440             || !TEST_false(ccsbeforesh)
    441             || !TEST_size_t_eq(chsessidlen, 0))
    442             goto err;
    443         break;
    444 
    445     case 8:
    446         if (!TEST_false(sccsseen)
    447             || !TEST_false(ccsaftersh)
    448             || !TEST_true(ccsbeforesh)
    449             || !TEST_size_t_gt(chsessidlen, 0))
    450             goto err;
    451         break;
    452 
    453     case 9:
    454         if (!TEST_true(sccsseen)
    455             || !TEST_false(ccsaftersh)
    456             || !TEST_true(ccsbeforesh)
    457             || !TEST_size_t_gt(chsessidlen, 0))
    458             goto err;
    459         break;
    460 
    461     case 10:
    462         if (!TEST_true(sccsseen)
    463             || !TEST_false(ccsaftersh)
    464             || !TEST_false(ccsbeforesh)
    465             || !TEST_size_t_eq(chsessidlen, 0))
    466             goto err;
    467         break;
    468 
    469     case 11:
    470         if (!TEST_false(sccsseen)
    471             || !TEST_false(ccsaftersh)
    472             || !TEST_true(ccsbeforesh)
    473             || !TEST_size_t_gt(chsessidlen, 0))
    474             goto err;
    475         break;
    476     }
    477 
    478     ret = 1;
    479 err:
    480     SSL_SESSION_free(sess);
    481     SSL_free(sssl);
    482     SSL_free(cssl);
    483     SSL_CTX_free(sctx);
    484     SSL_CTX_free(cctx);
    485 
    486     return ret;
    487 }
    488 
    489 OPT_TEST_DECLARE_USAGE("certfile privkeyfile\n")
    490 
    491 int setup_tests(void)
    492 {
    493     if (!test_skip_common_options()) {
    494         TEST_error("Error parsing test options\n");
    495         return 0;
    496     }
    497 
    498     if (!TEST_ptr(cert = test_get_argument(0))
    499         || !TEST_ptr(privkey = test_get_argument(1)))
    500         return 0;
    501 
    502     ADD_ALL_TESTS(test_tls13ccs, 12);
    503 
    504     return 1;
    505 }
    506 
    507 void cleanup_tests(void)
    508 {
    509     BIO_meth_free(method_watchccs);
    510 }
    511