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