]> git.ipfire.org Git - thirdparty/openssl.git/blob - test/quicapitest.c
QUIC APL: Fix locking in XSO code and fix tests
[thirdparty/openssl.git] / test / quicapitest.c
1 /*
2 * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10 #include <stdio.h>
11 #include <string.h>
12
13 #include <openssl/opensslconf.h>
14 #include <openssl/quic.h>
15
16 #include "helpers/ssltestlib.h"
17 #include "helpers/quictestlib.h"
18 #include "testutil.h"
19 #include "testutil/output.h"
20
21 static OSSL_LIB_CTX *libctx = NULL;
22 static OSSL_PROVIDER *defctxnull = NULL;
23 static char *certsdir = NULL;
24 static char *cert = NULL;
25 static char *privkey = NULL;
26
27 static int is_fips = 0;
28
29 /*
30 * Test that we read what we've written.
31 * Test 0: Non-blocking
32 * Test 1: Blocking
33 */
34 static int test_quic_write_read(int idx)
35 {
36 SSL_CTX *cctx = SSL_CTX_new_ex(libctx, NULL, OSSL_QUIC_client_method());
37 SSL *clientquic = NULL;
38 QUIC_TSERVER *qtserv = NULL;
39 int j, ret = 0;
40 unsigned char buf[20];
41 static char *msg = "A test message";
42 size_t msglen = strlen(msg);
43 size_t numbytes = 0;
44 int ssock = 0, csock = 0;
45 uint64_t sid = UINT64_MAX;
46
47 if (idx == 1 && !qtest_supports_blocking())
48 return TEST_skip("Blocking tests not supported in this build");
49
50 if (!TEST_ptr(cctx)
51 || !TEST_true(qtest_create_quic_objects(libctx, cctx, cert, privkey,
52 idx, &qtserv, &clientquic,
53 NULL))
54 || !TEST_true(SSL_set_tlsext_host_name(clientquic, "localhost"))
55 || !TEST_true(qtest_create_quic_connection(qtserv, clientquic)))
56 goto end;
57
58 if (idx == 1) {
59 if (!TEST_true(BIO_get_fd(ossl_quic_tserver_get0_rbio(qtserv), &ssock)))
60 goto end;
61 if (!TEST_int_gt(csock = SSL_get_rfd(clientquic), 0))
62 goto end;
63 }
64
65 sid = 0; /* client-initiated bidirectional stream */
66
67 for (j = 0; j < 2; j++) {
68 /* Check that sending and receiving app data is ok */
69 if (!TEST_true(SSL_write_ex(clientquic, msg, msglen, &numbytes))
70 || !TEST_size_t_eq(numbytes, msglen))
71 goto end;
72 if (idx == 1) {
73 do {
74 if (!TEST_true(wait_until_sock_readable(ssock)))
75 goto end;
76
77 ossl_quic_tserver_tick(qtserv);
78
79 if (!TEST_true(ossl_quic_tserver_read(qtserv, sid, buf, sizeof(buf),
80 &numbytes)))
81 goto end;
82 } while (numbytes == 0);
83
84 if (!TEST_mem_eq(buf, numbytes, msg, msglen))
85 goto end;
86 }
87
88 ossl_quic_tserver_tick(qtserv);
89 if (!TEST_true(ossl_quic_tserver_write(qtserv, sid, (unsigned char *)msg,
90 msglen, &numbytes)))
91 goto end;
92 ossl_quic_tserver_tick(qtserv);
93 SSL_tick(clientquic);
94 /*
95 * In blocking mode the SSL_read_ex call will block until the socket is
96 * readable and has our data. In non-blocking mode we're doing everything
97 * in memory, so it should be immediately available
98 */
99 if (!TEST_true(SSL_read_ex(clientquic, buf, 1, &numbytes))
100 || !TEST_size_t_eq(numbytes, 1)
101 || !TEST_true(SSL_has_pending(clientquic))
102 || !TEST_int_eq(SSL_pending(clientquic), msglen - 1)
103 || !TEST_true(SSL_read_ex(clientquic, buf + 1, sizeof(buf) - 1, &numbytes))
104 || !TEST_mem_eq(buf, numbytes + 1, msg, msglen))
105 goto end;
106 }
107
108 if (!TEST_true(qtest_shutdown(qtserv, clientquic)))
109 goto end;
110
111 ret = 1;
112
113 end:
114 ossl_quic_tserver_free(qtserv);
115 SSL_free(clientquic);
116 SSL_CTX_free(cctx);
117
118 return ret;
119 }
120
121 /* Test that a vanilla QUIC SSL object has the expected ciphersuites available */
122 static int test_ciphersuites(void)
123 {
124 SSL_CTX *ctx = SSL_CTX_new_ex(libctx, NULL, OSSL_QUIC_client_method());
125 SSL *ssl;
126 int testresult = 0;
127 const STACK_OF(SSL_CIPHER) *ciphers = NULL;
128 const SSL_CIPHER *cipher;
129 /* We expect this exact list of ciphersuites by default */
130 int cipherids[] = {
131 TLS1_3_CK_AES_256_GCM_SHA384,
132 #if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
133 TLS1_3_CK_CHACHA20_POLY1305_SHA256,
134 #endif
135 TLS1_3_CK_AES_128_GCM_SHA256
136 };
137 size_t i, j;
138
139 if (!TEST_ptr(ctx))
140 return 0;
141
142 ssl = SSL_new(ctx);
143 if (!TEST_ptr(ssl))
144 goto err;
145
146 ciphers = SSL_get_ciphers(ssl);
147
148 for (i = 0, j = 0; i < OSSL_NELEM(cipherids); i++) {
149 if (cipherids[i] == TLS1_3_CK_CHACHA20_POLY1305_SHA256 && is_fips)
150 continue;
151 cipher = sk_SSL_CIPHER_value(ciphers, j++);
152 if (!TEST_ptr(cipher))
153 goto err;
154 if (!TEST_uint_eq(SSL_CIPHER_get_id(cipher), cipherids[i]))
155 goto err;
156 }
157
158 /* We should have checked all the ciphers in the stack */
159 if (!TEST_int_eq(sk_SSL_CIPHER_num(ciphers), j))
160 goto err;
161
162 testresult = 1;
163 err:
164 SSL_free(ssl);
165 SSL_CTX_free(ctx);
166
167 return testresult;
168 }
169
170 /*
171 * Test that SSL_version, SSL_get_version, SSL_is_quic, SSL_is_tls and
172 * SSL_is_dtls return the expected results for a QUIC connection. Compare with
173 * test_version() in sslapitest.c which does the same thing for TLS/DTLS
174 * connections.
175 */
176 static int test_version(void)
177 {
178 SSL_CTX *cctx = SSL_CTX_new_ex(libctx, NULL, OSSL_QUIC_client_method());
179 SSL *clientquic = NULL;
180 QUIC_TSERVER *qtserv = NULL;
181 int testresult = 0;
182
183 if (!TEST_ptr(cctx)
184 || !TEST_true(qtest_create_quic_objects(libctx, cctx, cert, privkey,
185 0, &qtserv, &clientquic,
186 NULL))
187 || !TEST_true(qtest_create_quic_connection(qtserv, clientquic)))
188 goto err;
189
190 if (!TEST_int_eq(SSL_version(clientquic), OSSL_QUIC1_VERSION)
191 || !TEST_str_eq(SSL_get_version(clientquic), "QUICv1"))
192 goto err;
193
194 if (!TEST_true(SSL_is_quic(clientquic))
195 || !TEST_false(SSL_is_tls(clientquic))
196 || !TEST_false(SSL_is_dtls(clientquic)))
197 goto err;
198
199
200 testresult = 1;
201 err:
202 ossl_quic_tserver_free(qtserv);
203 SSL_free(clientquic);
204 SSL_CTX_free(cctx);
205
206 return testresult;
207 }
208
209 OPT_TEST_DECLARE_USAGE("provider config\n")
210
211 int setup_tests(void)
212 {
213 char *modulename;
214 char *configfile;
215
216 libctx = OSSL_LIB_CTX_new();
217 if (!TEST_ptr(libctx))
218 return 0;
219
220 defctxnull = OSSL_PROVIDER_load(NULL, "null");
221
222 /*
223 * Verify that the default and fips providers in the default libctx are not
224 * available
225 */
226 if (!TEST_false(OSSL_PROVIDER_available(NULL, "default"))
227 || !TEST_false(OSSL_PROVIDER_available(NULL, "fips")))
228 goto err;
229
230 if (!test_skip_common_options()) {
231 TEST_error("Error parsing test options\n");
232 goto err;
233 }
234
235 if (!TEST_ptr(modulename = test_get_argument(0))
236 || !TEST_ptr(configfile = test_get_argument(1))
237 || !TEST_ptr(certsdir = test_get_argument(2)))
238 goto err;
239
240 if (!TEST_true(OSSL_LIB_CTX_load_config(libctx, configfile)))
241 goto err;
242
243 /* Check we have the expected provider available */
244 if (!TEST_true(OSSL_PROVIDER_available(libctx, modulename)))
245 goto err;
246
247 /* Check the default provider is not available */
248 if (strcmp(modulename, "default") != 0
249 && !TEST_false(OSSL_PROVIDER_available(libctx, "default")))
250 goto err;
251
252 if (strcmp(modulename, "fips") == 0)
253 is_fips = 1;
254
255 cert = test_mk_file_path(certsdir, "servercert.pem");
256 if (cert == NULL)
257 goto err;
258
259 privkey = test_mk_file_path(certsdir, "serverkey.pem");
260 if (privkey == NULL)
261 goto err;
262
263 ADD_ALL_TESTS(test_quic_write_read, 2);
264 ADD_TEST(test_ciphersuites);
265 ADD_TEST(test_version);
266
267 return 1;
268 err:
269 cleanup_tests();
270 return 0;
271 }
272
273 void cleanup_tests(void)
274 {
275 OPENSSL_free(cert);
276 OPENSSL_free(privkey);
277 OSSL_PROVIDER_unload(defctxnull);
278 OSSL_LIB_CTX_free(libctx);
279 }