VirtualBox

source: vbox/trunk/src/libs/openssl-3.3.1/test/sslbuffertest.c@ 105963

Last change on this file since 105963 was 105918, checked in by vboxsync, 8 months ago

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

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

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