VirtualBox

source: vbox/trunk/src/libs/openssl-3.1.7/test/sslbuffertest.c@ 105945

Last change on this file since 105945 was 105945, checked in by vboxsync, 6 months ago

openssl-3.1.7: Applied and adjusted our OpenSSL changes to 3.1.7. bugref:10757

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette