Home | History | Annotate | Line # | Download | only in test
      1 /*
      2  * Copyright 2016-2025 The OpenSSL Project Authors. All Rights Reserved.
      3  *
      4  * Licensed under the Apache License 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  * https://www.openssl.org/source/license.html
      8  * or in the file LICENSE in the source distribution.
      9  */
     10 
     11 /*
     12  * We need access to the deprecated low level Engine APIs for legacy purposes
     13  * when the deprecated calls are not hidden
     14  */
     15 #ifndef OPENSSL_NO_DEPRECATED_3_0
     16 #define OPENSSL_SUPPRESS_DEPRECATED
     17 #endif
     18 
     19 #include <string.h>
     20 #include <openssl/ssl.h>
     21 #include <openssl/bio.h>
     22 #include <openssl/err.h>
     23 #include <openssl/engine.h>
     24 
     25 #ifndef OPENSSL_NO_QUIC
     26 /* This test does not link libssl so avoid pulling in QUIC unwrappers. */
     27 #define OPENSSL_NO_QUIC
     28 #endif
     29 
     30 /* We include internal headers so we can check if the buffers are allocated */
     31 #include "../ssl/ssl_local.h"
     32 #include "../ssl/record/record_local.h"
     33 #include "internal/recordmethod.h"
     34 #include "../ssl/record/methods/recmethod_local.h"
     35 #include "internal/ssl_unwrap.h"
     36 
     37 #include "internal/packet.h"
     38 
     39 #include "helpers/ssltestlib.h"
     40 #include "testutil.h"
     41 
     42 struct async_ctrs {
     43     unsigned int rctr;
     44     unsigned int wctr;
     45 };
     46 
     47 static SSL_CTX *serverctx = NULL;
     48 static SSL_CTX *clientctx = NULL;
     49 
     50 #define MAX_ATTEMPTS 100
     51 
     52 static int checkbuffers(SSL *s, int isalloced)
     53 {
     54     SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
     55     OSSL_RECORD_LAYER *rrl = sc->rlayer.rrl;
     56     OSSL_RECORD_LAYER *wrl = sc->rlayer.wrl;
     57 
     58     if (isalloced)
     59         return rrl->rbuf.buf != NULL && wrl->wbuf[0].buf != NULL;
     60 
     61     return rrl->rbuf.buf == NULL && wrl->wbuf[0].buf == NULL;
     62 }
     63 
     64 /*
     65  * There are 9 passes in the tests
     66  * 0 = control test
     67  * tests during writes
     68  * 1 = free buffers
     69  * 2 = + allocate buffers after free
     70  * 3 = + allocate buffers again
     71  * 4 = + free buffers after allocation
     72  * tests during reads
     73  * 5 = + free buffers
     74  * 6 = + free buffers again
     75  * 7 = + allocate buffers after free
     76  * 8 = + free buffers after allocation
     77  */
     78 static int test_func(int test)
     79 {
     80     int result = 0;
     81     SSL *serverssl = NULL, *clientssl = NULL;
     82     int ret;
     83     size_t i, j;
     84     const char testdata[] = "Test data";
     85     char buf[sizeof(testdata)];
     86 
     87     if (!TEST_true(create_ssl_objects(serverctx, clientctx, &serverssl, &clientssl,
     88             NULL, NULL))) {
     89         TEST_error("Test %d failed: Create SSL objects failed\n", test);
     90         goto end;
     91     }
     92 
     93     if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) {
     94         TEST_error("Test %d failed: Create SSL connection failed\n", test);
     95         goto end;
     96     }
     97 
     98     /*
     99      * Send and receive some test data. Do the whole thing twice to ensure
    100      * we hit at least one async event in both reading and writing
    101      */
    102     for (j = 0; j < 2; j++) {
    103         int len;
    104 
    105         /*
    106 
    107          * Write some test data. It should never take more than 2 attempts
    108          * (the first one might be a retryable fail).
    109          */
    110         for (ret = -1, i = 0, len = 0; len != sizeof(testdata) && i < 2;
    111             i++) {
    112             /* test == 0 mean to free/allocate = control */
    113             if (test >= 1 && (!TEST_true(SSL_free_buffers(clientssl)) || !TEST_true(checkbuffers(clientssl, 0))))
    114                 goto end;
    115             if (test >= 2 && (!TEST_true(SSL_alloc_buffers(clientssl)) || !TEST_true(checkbuffers(clientssl, 1))))
    116                 goto end;
    117             /* allocate a second time */
    118             if (test >= 3 && (!TEST_true(SSL_alloc_buffers(clientssl)) || !TEST_true(checkbuffers(clientssl, 1))))
    119                 goto end;
    120             if (test >= 4 && (!TEST_true(SSL_free_buffers(clientssl)) || !TEST_true(checkbuffers(clientssl, 0))))
    121                 goto end;
    122 
    123             ret = SSL_write(clientssl, testdata + len,
    124                 sizeof(testdata) - len);
    125             if (ret > 0) {
    126                 len += ret;
    127             } else {
    128                 int ssl_error = SSL_get_error(clientssl, ret);
    129 
    130                 if (ssl_error == SSL_ERROR_SYSCALL || ssl_error == SSL_ERROR_SSL) {
    131                     TEST_error("Test %d failed: Failed to write app data\n", test);
    132                     goto end;
    133                 }
    134             }
    135         }
    136         if (!TEST_size_t_eq(len, sizeof(testdata)))
    137             goto end;
    138         /*
    139          * Now read the test data. It may take more attempts here because
    140          * it could fail once for each byte read, including all overhead
    141          * bytes from the record header/padding etc.
    142          */
    143         for (ret = -1, i = 0, len = 0; len != sizeof(testdata) && i < MAX_ATTEMPTS; i++) {
    144             if (test >= 5 && (!TEST_true(SSL_free_buffers(serverssl)) || !TEST_true(checkbuffers(serverssl, 0))))
    145                 goto end;
    146             /* free a second time */
    147             if (test >= 6 && (!TEST_true(SSL_free_buffers(serverssl)) || !TEST_true(checkbuffers(serverssl, 0))))
    148                 goto end;
    149             if (test >= 7 && (!TEST_true(SSL_alloc_buffers(serverssl)) || !TEST_true(checkbuffers(serverssl, 1))))
    150                 goto end;
    151             if (test >= 8 && (!TEST_true(SSL_free_buffers(serverssl)) || !TEST_true(checkbuffers(serverssl, 0))))
    152                 goto end;
    153 
    154             ret = SSL_read(serverssl, buf + len, sizeof(buf) - len);
    155             if (ret > 0) {
    156                 len += ret;
    157             } else {
    158                 int ssl_error = SSL_get_error(serverssl, ret);
    159 
    160                 if (ssl_error == SSL_ERROR_SYSCALL || ssl_error == SSL_ERROR_SSL) {
    161                     TEST_error("Test %d failed: Failed to read app data\n", test);
    162                     goto end;
    163                 }
    164             }
    165         }
    166         if (!TEST_mem_eq(buf, len, testdata, sizeof(testdata)))
    167             goto end;
    168     }
    169 
    170     result = 1;
    171 end:
    172     if (!result)
    173         ERR_print_errors_fp(stderr);
    174 
    175     SSL_free(clientssl);
    176     SSL_free(serverssl);
    177 
    178     return result;
    179 }
    180 
    181 /*
    182  * Test that attempting to free the buffers at points where they cannot be freed
    183  * works as expected
    184  * Test 0: Attempt to free buffers after a full record has been processed, but
    185  *         the application has only performed a partial read
    186  * Test 1: Attempt to free buffers after only a partial record header has been
    187  *         received
    188  * Test 2: Attempt to free buffers after a full record header but no record body
    189  * Test 3: Attempt to free buffers after a full record hedaer and partial record
    190  *         body
    191  * Test 4-7: We repeat tests 0-3 but including data from a second pipelined
    192  *           record
    193  */
    194 static int test_free_buffers(int test)
    195 {
    196     int result = 0;
    197     SSL *serverssl = NULL, *clientssl = NULL;
    198     const char testdata[] = "Test data";
    199     char buf[120];
    200     size_t written, readbytes;
    201     int i, pipeline = test > 3;
    202     ENGINE *e = NULL;
    203 
    204     if (pipeline) {
    205         e = load_dasync();
    206         if (e == NULL)
    207             goto end;
    208         test -= 4;
    209     }
    210 
    211     if (!TEST_true(create_ssl_objects(serverctx, clientctx, &serverssl,
    212             &clientssl, NULL, NULL)))
    213         goto end;
    214 
    215     if (pipeline) {
    216         if (!TEST_true(SSL_set_cipher_list(serverssl, "AES128-SHA"))
    217             || !TEST_true(SSL_set_max_proto_version(serverssl,
    218                 TLS1_2_VERSION))
    219             || !TEST_true(SSL_set_max_pipelines(serverssl, 2)))
    220             goto end;
    221     }
    222 
    223     if (!TEST_true(create_ssl_connection(serverssl, clientssl,
    224             SSL_ERROR_NONE)))
    225         goto end;
    226 
    227     /*
    228      * For the non-pipeline case we write one record. For pipelining we write
    229      * two records.
    230      */
    231     for (i = 0; i <= pipeline; i++) {
    232         if (!TEST_true(SSL_write_ex(clientssl, testdata, strlen(testdata),
    233                 &written)))
    234             goto end;
    235     }
    236 
    237     if (test == 0) {
    238         size_t readlen = 1;
    239 
    240         /*
    241          * Deliberately only read the first byte - so the remaining bytes are
    242          * still buffered. In the pipelining case we read as far as the first
    243          * byte from the second record.
    244          */
    245         if (pipeline)
    246             readlen += strlen(testdata);
    247 
    248         if (!TEST_true(SSL_read_ex(serverssl, buf, readlen, &readbytes))
    249             || !TEST_size_t_eq(readlen, readbytes))
    250             goto end;
    251     } else {
    252         BIO *tmp;
    253         size_t partial_len;
    254 
    255         /* Remove all the data that is pending for read by the server */
    256         tmp = SSL_get_rbio(serverssl);
    257         if (!TEST_true(BIO_read_ex(tmp, buf, sizeof(buf), &readbytes))
    258             || !TEST_size_t_lt(readbytes, sizeof(buf))
    259             || !TEST_size_t_gt(readbytes, SSL3_RT_HEADER_LENGTH))
    260             goto end;
    261 
    262         switch (test) {
    263         case 1:
    264             partial_len = SSL3_RT_HEADER_LENGTH - 1;
    265             break;
    266         case 2:
    267             partial_len = SSL3_RT_HEADER_LENGTH;
    268             break;
    269         case 3:
    270             partial_len = readbytes - 1;
    271             break;
    272         default:
    273             TEST_error("Invalid test index");
    274             goto end;
    275         }
    276 
    277         if (pipeline) {
    278             /* We happen to know the first record is 57 bytes long */
    279             const size_t first_rec_len = 57;
    280 
    281             if (test != 3)
    282                 partial_len += first_rec_len;
    283 
    284             /*
    285              * Sanity check. If we got the record len right then this should
    286              * never fail.
    287              */
    288             if (!TEST_int_eq(buf[first_rec_len], SSL3_RT_APPLICATION_DATA))
    289                 goto end;
    290         }
    291 
    292         /*
    293          * Put back just the partial record (plus the whole initial record in
    294          * the pipelining case)
    295          */
    296         if (!TEST_true(BIO_write_ex(tmp, buf, partial_len, &written)))
    297             goto end;
    298 
    299         if (pipeline) {
    300             /*
    301              * Attempt a read. This should pass but only return data from the
    302              * first record. Only a partial record is available for the second
    303              * record.
    304              */
    305             if (!TEST_true(SSL_read_ex(serverssl, buf, sizeof(buf),
    306                     &readbytes))
    307                 || !TEST_size_t_eq(readbytes, strlen(testdata)))
    308                 goto end;
    309         } else {
    310             /*
    311              * Attempt a read. This should fail because only a partial record is
    312              * available.
    313              */
    314             if (!TEST_false(SSL_read_ex(serverssl, buf, sizeof(buf),
    315                     &readbytes)))
    316                 goto end;
    317         }
    318     }
    319 
    320     /*
    321      * Attempting to free the buffers at this point should fail because they are
    322      * still in use
    323      */
    324     if (!TEST_false(SSL_free_buffers(serverssl)))
    325         goto end;
    326 
    327     result = 1;
    328 end:
    329     SSL_free(clientssl);
    330     SSL_free(serverssl);
    331 #ifndef OPENSSL_NO_DYNAMIC_ENGINE
    332     if (e != NULL) {
    333         ENGINE_unregister_ciphers(e);
    334         ENGINE_finish(e);
    335         ENGINE_free(e);
    336     }
    337 #endif
    338     return result;
    339 }
    340 
    341 OPT_TEST_DECLARE_USAGE("certfile privkeyfile\n")
    342 
    343 int setup_tests(void)
    344 {
    345     char *cert, *pkey;
    346 
    347     if (!test_skip_common_options()) {
    348         TEST_error("Error parsing test options\n");
    349         return 0;
    350     }
    351 
    352     if (!TEST_ptr(cert = test_get_argument(0))
    353         || !TEST_ptr(pkey = test_get_argument(1)))
    354         return 0;
    355 
    356     if (!create_ssl_ctx_pair(NULL, TLS_server_method(), TLS_client_method(),
    357             TLS1_VERSION, 0,
    358             &serverctx, &clientctx, cert, pkey)) {
    359         TEST_error("Failed to create SSL_CTX pair\n");
    360         return 0;
    361     }
    362 
    363     ADD_ALL_TESTS(test_func, 9);
    364 #if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_DYNAMIC_ENGINE)
    365     ADD_ALL_TESTS(test_free_buffers, 8);
    366 #else
    367     ADD_ALL_TESTS(test_free_buffers, 4);
    368 #endif
    369     return 1;
    370 }
    371 
    372 void cleanup_tests(void)
    373 {
    374     SSL_CTX_free(clientctx);
    375     SSL_CTX_free(serverctx);
    376 }
    377