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 */
test_func(int test)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 */
test_free_buffers(int test)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
setup_tests(void)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
cleanup_tests(void)353e0c4386eSCy Schubert void cleanup_tests(void)
354e0c4386eSCy Schubert {
355e0c4386eSCy Schubert SSL_CTX_free(clientctx);
356e0c4386eSCy Schubert SSL_CTX_free(serverctx);
357e0c4386eSCy Schubert }
358