1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License");
5e1051a39Sopenharmony_ci * you may not use this file except in compliance with the License.
6e1051a39Sopenharmony_ci * You may obtain a copy of the License at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci * or in the file LICENSE in the source distribution.
9e1051a39Sopenharmony_ci */
10e1051a39Sopenharmony_ci
11e1051a39Sopenharmony_ci#include <string.h>
12e1051a39Sopenharmony_ci#include <openssl/ssl.h>
13e1051a39Sopenharmony_ci#include <openssl/bio.h>
14e1051a39Sopenharmony_ci#include <openssl/err.h>
15e1051a39Sopenharmony_ci
16e1051a39Sopenharmony_ci#include "internal/packet.h"
17e1051a39Sopenharmony_ci
18e1051a39Sopenharmony_ci#include "helpers/ssltestlib.h"
19e1051a39Sopenharmony_ci#include "testutil.h"
20e1051a39Sopenharmony_ci
21e1051a39Sopenharmony_ci/* Should we fragment records or not? 0 = no, !0 = yes*/
22e1051a39Sopenharmony_cistatic int fragment = 0;
23e1051a39Sopenharmony_ci
24e1051a39Sopenharmony_cistatic char *cert = NULL;
25e1051a39Sopenharmony_cistatic char *privkey = NULL;
26e1051a39Sopenharmony_ci
27e1051a39Sopenharmony_cistatic int async_new(BIO *bi);
28e1051a39Sopenharmony_cistatic int async_free(BIO *a);
29e1051a39Sopenharmony_cistatic int async_read(BIO *b, char *out, int outl);
30e1051a39Sopenharmony_cistatic int async_write(BIO *b, const char *in, int inl);
31e1051a39Sopenharmony_cistatic long async_ctrl(BIO *b, int cmd, long num, void *ptr);
32e1051a39Sopenharmony_cistatic int async_gets(BIO *bp, char *buf, int size);
33e1051a39Sopenharmony_cistatic int async_puts(BIO *bp, const char *str);
34e1051a39Sopenharmony_ci
35e1051a39Sopenharmony_ci/* Choose a sufficiently large type likely to be unused for this custom BIO */
36e1051a39Sopenharmony_ci# define BIO_TYPE_ASYNC_FILTER  (0x80 | BIO_TYPE_FILTER)
37e1051a39Sopenharmony_ci
38e1051a39Sopenharmony_cistatic BIO_METHOD *methods_async = NULL;
39e1051a39Sopenharmony_ci
40e1051a39Sopenharmony_cistruct async_ctrs {
41e1051a39Sopenharmony_ci    unsigned int rctr;
42e1051a39Sopenharmony_ci    unsigned int wctr;
43e1051a39Sopenharmony_ci};
44e1051a39Sopenharmony_ci
45e1051a39Sopenharmony_cistatic const BIO_METHOD *bio_f_async_filter(void)
46e1051a39Sopenharmony_ci{
47e1051a39Sopenharmony_ci    if (methods_async == NULL) {
48e1051a39Sopenharmony_ci        methods_async = BIO_meth_new(BIO_TYPE_ASYNC_FILTER, "Async filter");
49e1051a39Sopenharmony_ci        if (   methods_async == NULL
50e1051a39Sopenharmony_ci            || !BIO_meth_set_write(methods_async, async_write)
51e1051a39Sopenharmony_ci            || !BIO_meth_set_read(methods_async, async_read)
52e1051a39Sopenharmony_ci            || !BIO_meth_set_puts(methods_async, async_puts)
53e1051a39Sopenharmony_ci            || !BIO_meth_set_gets(methods_async, async_gets)
54e1051a39Sopenharmony_ci            || !BIO_meth_set_ctrl(methods_async, async_ctrl)
55e1051a39Sopenharmony_ci            || !BIO_meth_set_create(methods_async, async_new)
56e1051a39Sopenharmony_ci            || !BIO_meth_set_destroy(methods_async, async_free))
57e1051a39Sopenharmony_ci            return NULL;
58e1051a39Sopenharmony_ci    }
59e1051a39Sopenharmony_ci    return methods_async;
60e1051a39Sopenharmony_ci}
61e1051a39Sopenharmony_ci
62e1051a39Sopenharmony_cistatic int async_new(BIO *bio)
63e1051a39Sopenharmony_ci{
64e1051a39Sopenharmony_ci    struct async_ctrs *ctrs;
65e1051a39Sopenharmony_ci
66e1051a39Sopenharmony_ci    ctrs = OPENSSL_zalloc(sizeof(struct async_ctrs));
67e1051a39Sopenharmony_ci    if (ctrs == NULL)
68e1051a39Sopenharmony_ci        return 0;
69e1051a39Sopenharmony_ci
70e1051a39Sopenharmony_ci    BIO_set_data(bio, ctrs);
71e1051a39Sopenharmony_ci    BIO_set_init(bio, 1);
72e1051a39Sopenharmony_ci    return 1;
73e1051a39Sopenharmony_ci}
74e1051a39Sopenharmony_ci
75e1051a39Sopenharmony_cistatic int async_free(BIO *bio)
76e1051a39Sopenharmony_ci{
77e1051a39Sopenharmony_ci    struct async_ctrs *ctrs;
78e1051a39Sopenharmony_ci
79e1051a39Sopenharmony_ci    if (bio == NULL)
80e1051a39Sopenharmony_ci        return 0;
81e1051a39Sopenharmony_ci    ctrs = BIO_get_data(bio);
82e1051a39Sopenharmony_ci    OPENSSL_free(ctrs);
83e1051a39Sopenharmony_ci    BIO_set_data(bio, NULL);
84e1051a39Sopenharmony_ci    BIO_set_init(bio, 0);
85e1051a39Sopenharmony_ci
86e1051a39Sopenharmony_ci    return 1;
87e1051a39Sopenharmony_ci}
88e1051a39Sopenharmony_ci
89e1051a39Sopenharmony_cistatic int async_read(BIO *bio, char *out, int outl)
90e1051a39Sopenharmony_ci{
91e1051a39Sopenharmony_ci    struct async_ctrs *ctrs;
92e1051a39Sopenharmony_ci    int ret = 0;
93e1051a39Sopenharmony_ci    BIO *next = BIO_next(bio);
94e1051a39Sopenharmony_ci
95e1051a39Sopenharmony_ci    if (outl <= 0)
96e1051a39Sopenharmony_ci        return 0;
97e1051a39Sopenharmony_ci    if (next == NULL)
98e1051a39Sopenharmony_ci        return 0;
99e1051a39Sopenharmony_ci
100e1051a39Sopenharmony_ci    ctrs = BIO_get_data(bio);
101e1051a39Sopenharmony_ci
102e1051a39Sopenharmony_ci    BIO_clear_retry_flags(bio);
103e1051a39Sopenharmony_ci
104e1051a39Sopenharmony_ci    if (ctrs->rctr > 0) {
105e1051a39Sopenharmony_ci        ret = BIO_read(next, out, 1);
106e1051a39Sopenharmony_ci        if (ret <= 0 && BIO_should_read(next))
107e1051a39Sopenharmony_ci            BIO_set_retry_read(bio);
108e1051a39Sopenharmony_ci        ctrs->rctr = 0;
109e1051a39Sopenharmony_ci    } else {
110e1051a39Sopenharmony_ci        ctrs->rctr++;
111e1051a39Sopenharmony_ci        BIO_set_retry_read(bio);
112e1051a39Sopenharmony_ci    }
113e1051a39Sopenharmony_ci
114e1051a39Sopenharmony_ci    return ret;
115e1051a39Sopenharmony_ci}
116e1051a39Sopenharmony_ci
117e1051a39Sopenharmony_ci#define MIN_RECORD_LEN  6
118e1051a39Sopenharmony_ci
119e1051a39Sopenharmony_ci#define CONTENTTYPEPOS  0
120e1051a39Sopenharmony_ci#define VERSIONHIPOS    1
121e1051a39Sopenharmony_ci#define VERSIONLOPOS    2
122e1051a39Sopenharmony_ci#define DATAPOS         5
123e1051a39Sopenharmony_ci
124e1051a39Sopenharmony_cistatic int async_write(BIO *bio, const char *in, int inl)
125e1051a39Sopenharmony_ci{
126e1051a39Sopenharmony_ci    struct async_ctrs *ctrs;
127e1051a39Sopenharmony_ci    int ret = 0;
128e1051a39Sopenharmony_ci    size_t written = 0;
129e1051a39Sopenharmony_ci    BIO *next = BIO_next(bio);
130e1051a39Sopenharmony_ci
131e1051a39Sopenharmony_ci    if (inl <= 0)
132e1051a39Sopenharmony_ci        return 0;
133e1051a39Sopenharmony_ci    if (next == NULL)
134e1051a39Sopenharmony_ci        return 0;
135e1051a39Sopenharmony_ci
136e1051a39Sopenharmony_ci    ctrs = BIO_get_data(bio);
137e1051a39Sopenharmony_ci
138e1051a39Sopenharmony_ci    BIO_clear_retry_flags(bio);
139e1051a39Sopenharmony_ci
140e1051a39Sopenharmony_ci    if (ctrs->wctr > 0) {
141e1051a39Sopenharmony_ci        ctrs->wctr = 0;
142e1051a39Sopenharmony_ci        if (fragment) {
143e1051a39Sopenharmony_ci            PACKET pkt;
144e1051a39Sopenharmony_ci
145e1051a39Sopenharmony_ci            if (!PACKET_buf_init(&pkt, (const unsigned char *)in, inl))
146e1051a39Sopenharmony_ci                return -1;
147e1051a39Sopenharmony_ci
148e1051a39Sopenharmony_ci            while (PACKET_remaining(&pkt) > 0) {
149e1051a39Sopenharmony_ci                PACKET payload, wholebody, sessionid, extensions;
150e1051a39Sopenharmony_ci                unsigned int contenttype, versionhi, versionlo, data;
151e1051a39Sopenharmony_ci                unsigned int msgtype = 0, negversion = 0;
152e1051a39Sopenharmony_ci
153e1051a39Sopenharmony_ci                if (!PACKET_get_1(&pkt, &contenttype)
154e1051a39Sopenharmony_ci                        || !PACKET_get_1(&pkt, &versionhi)
155e1051a39Sopenharmony_ci                        || !PACKET_get_1(&pkt, &versionlo)
156e1051a39Sopenharmony_ci                        || !PACKET_get_length_prefixed_2(&pkt, &payload))
157e1051a39Sopenharmony_ci                    return -1;
158e1051a39Sopenharmony_ci
159e1051a39Sopenharmony_ci                /* Pretend we wrote out the record header */
160e1051a39Sopenharmony_ci                written += SSL3_RT_HEADER_LENGTH;
161e1051a39Sopenharmony_ci
162e1051a39Sopenharmony_ci                wholebody = payload;
163e1051a39Sopenharmony_ci                if (contenttype == SSL3_RT_HANDSHAKE
164e1051a39Sopenharmony_ci                        && !PACKET_get_1(&wholebody, &msgtype))
165e1051a39Sopenharmony_ci                    return -1;
166e1051a39Sopenharmony_ci
167e1051a39Sopenharmony_ci                if (msgtype == SSL3_MT_SERVER_HELLO) {
168e1051a39Sopenharmony_ci                    if (!PACKET_forward(&wholebody,
169e1051a39Sopenharmony_ci                                            SSL3_HM_HEADER_LENGTH - 1)
170e1051a39Sopenharmony_ci                            || !PACKET_get_net_2(&wholebody, &negversion)
171e1051a39Sopenharmony_ci                               /* Skip random (32 bytes) */
172e1051a39Sopenharmony_ci                            || !PACKET_forward(&wholebody, 32)
173e1051a39Sopenharmony_ci                               /* Skip session id */
174e1051a39Sopenharmony_ci                            || !PACKET_get_length_prefixed_1(&wholebody,
175e1051a39Sopenharmony_ci                                                             &sessionid)
176e1051a39Sopenharmony_ci                               /*
177e1051a39Sopenharmony_ci                                * Skip ciphersuite (2 bytes) and compression
178e1051a39Sopenharmony_ci                                * method (1 byte)
179e1051a39Sopenharmony_ci                                */
180e1051a39Sopenharmony_ci                            || !PACKET_forward(&wholebody, 2 + 1)
181e1051a39Sopenharmony_ci                            || !PACKET_get_length_prefixed_2(&wholebody,
182e1051a39Sopenharmony_ci                                                             &extensions))
183e1051a39Sopenharmony_ci                        return -1;
184e1051a39Sopenharmony_ci
185e1051a39Sopenharmony_ci                    /*
186e1051a39Sopenharmony_ci                     * Find the negotiated version in supported_versions
187e1051a39Sopenharmony_ci                     * extension, if present.
188e1051a39Sopenharmony_ci                     */
189e1051a39Sopenharmony_ci                    while (PACKET_remaining(&extensions)) {
190e1051a39Sopenharmony_ci                        unsigned int type;
191e1051a39Sopenharmony_ci                        PACKET extbody;
192e1051a39Sopenharmony_ci
193e1051a39Sopenharmony_ci                        if (!PACKET_get_net_2(&extensions, &type)
194e1051a39Sopenharmony_ci                                || !PACKET_get_length_prefixed_2(&extensions,
195e1051a39Sopenharmony_ci                                &extbody))
196e1051a39Sopenharmony_ci                            return -1;
197e1051a39Sopenharmony_ci
198e1051a39Sopenharmony_ci                        if (type == TLSEXT_TYPE_supported_versions
199e1051a39Sopenharmony_ci                                && (!PACKET_get_net_2(&extbody, &negversion)
200e1051a39Sopenharmony_ci                                    || PACKET_remaining(&extbody) != 0))
201e1051a39Sopenharmony_ci                            return -1;
202e1051a39Sopenharmony_ci                    }
203e1051a39Sopenharmony_ci                }
204e1051a39Sopenharmony_ci
205e1051a39Sopenharmony_ci                while (PACKET_get_1(&payload, &data)) {
206e1051a39Sopenharmony_ci                    /* Create a new one byte long record for each byte in the
207e1051a39Sopenharmony_ci                     * record in the input buffer
208e1051a39Sopenharmony_ci                     */
209e1051a39Sopenharmony_ci                    char smallrec[MIN_RECORD_LEN] = {
210e1051a39Sopenharmony_ci                        0, /* Content type */
211e1051a39Sopenharmony_ci                        0, /* Version hi */
212e1051a39Sopenharmony_ci                        0, /* Version lo */
213e1051a39Sopenharmony_ci                        0, /* Length hi */
214e1051a39Sopenharmony_ci                        1, /* Length lo */
215e1051a39Sopenharmony_ci                        0  /* Data */
216e1051a39Sopenharmony_ci                    };
217e1051a39Sopenharmony_ci
218e1051a39Sopenharmony_ci                    smallrec[CONTENTTYPEPOS] = contenttype;
219e1051a39Sopenharmony_ci                    smallrec[VERSIONHIPOS] = versionhi;
220e1051a39Sopenharmony_ci                    smallrec[VERSIONLOPOS] = versionlo;
221e1051a39Sopenharmony_ci                    smallrec[DATAPOS] = data;
222e1051a39Sopenharmony_ci                    ret = BIO_write(next, smallrec, MIN_RECORD_LEN);
223e1051a39Sopenharmony_ci                    if (ret <= 0)
224e1051a39Sopenharmony_ci                        return -1;
225e1051a39Sopenharmony_ci                    written++;
226e1051a39Sopenharmony_ci                }
227e1051a39Sopenharmony_ci                /*
228e1051a39Sopenharmony_ci                 * We can't fragment anything after the ServerHello (or CCS <=
229e1051a39Sopenharmony_ci                 * TLS1.2), otherwise we get a bad record MAC
230e1051a39Sopenharmony_ci                 */
231e1051a39Sopenharmony_ci                if (contenttype == SSL3_RT_CHANGE_CIPHER_SPEC
232e1051a39Sopenharmony_ci                        || (negversion == TLS1_3_VERSION
233e1051a39Sopenharmony_ci                            && msgtype == SSL3_MT_SERVER_HELLO)) {
234e1051a39Sopenharmony_ci                    fragment = 0;
235e1051a39Sopenharmony_ci                    break;
236e1051a39Sopenharmony_ci                }
237e1051a39Sopenharmony_ci            }
238e1051a39Sopenharmony_ci        }
239e1051a39Sopenharmony_ci        /* Write any data we have left after fragmenting */
240e1051a39Sopenharmony_ci        ret = 0;
241e1051a39Sopenharmony_ci        if ((int)written < inl) {
242e1051a39Sopenharmony_ci            ret = BIO_write(next, in + written, inl - written);
243e1051a39Sopenharmony_ci        }
244e1051a39Sopenharmony_ci
245e1051a39Sopenharmony_ci        if (ret <= 0 && BIO_should_write(next))
246e1051a39Sopenharmony_ci            BIO_set_retry_write(bio);
247e1051a39Sopenharmony_ci        else
248e1051a39Sopenharmony_ci            ret += written;
249e1051a39Sopenharmony_ci    } else {
250e1051a39Sopenharmony_ci        ctrs->wctr++;
251e1051a39Sopenharmony_ci        BIO_set_retry_write(bio);
252e1051a39Sopenharmony_ci    }
253e1051a39Sopenharmony_ci
254e1051a39Sopenharmony_ci    return ret;
255e1051a39Sopenharmony_ci}
256e1051a39Sopenharmony_ci
257e1051a39Sopenharmony_cistatic long async_ctrl(BIO *bio, int cmd, long num, void *ptr)
258e1051a39Sopenharmony_ci{
259e1051a39Sopenharmony_ci    long ret;
260e1051a39Sopenharmony_ci    BIO *next = BIO_next(bio);
261e1051a39Sopenharmony_ci
262e1051a39Sopenharmony_ci    if (next == NULL)
263e1051a39Sopenharmony_ci        return 0;
264e1051a39Sopenharmony_ci
265e1051a39Sopenharmony_ci    switch (cmd) {
266e1051a39Sopenharmony_ci    case BIO_CTRL_DUP:
267e1051a39Sopenharmony_ci        ret = 0L;
268e1051a39Sopenharmony_ci        break;
269e1051a39Sopenharmony_ci    default:
270e1051a39Sopenharmony_ci        ret = BIO_ctrl(next, cmd, num, ptr);
271e1051a39Sopenharmony_ci        break;
272e1051a39Sopenharmony_ci    }
273e1051a39Sopenharmony_ci    return ret;
274e1051a39Sopenharmony_ci}
275e1051a39Sopenharmony_ci
276e1051a39Sopenharmony_cistatic int async_gets(BIO *bio, char *buf, int size)
277e1051a39Sopenharmony_ci{
278e1051a39Sopenharmony_ci    /* We don't support this - not needed anyway */
279e1051a39Sopenharmony_ci    return -1;
280e1051a39Sopenharmony_ci}
281e1051a39Sopenharmony_ci
282e1051a39Sopenharmony_cistatic int async_puts(BIO *bio, const char *str)
283e1051a39Sopenharmony_ci{
284e1051a39Sopenharmony_ci    return async_write(bio, str, strlen(str));
285e1051a39Sopenharmony_ci}
286e1051a39Sopenharmony_ci
287e1051a39Sopenharmony_ci#define MAX_ATTEMPTS    100
288e1051a39Sopenharmony_ci
289e1051a39Sopenharmony_cistatic int test_asyncio(int test)
290e1051a39Sopenharmony_ci{
291e1051a39Sopenharmony_ci    SSL_CTX *serverctx = NULL, *clientctx = NULL;
292e1051a39Sopenharmony_ci    SSL *serverssl = NULL, *clientssl = NULL;
293e1051a39Sopenharmony_ci    BIO *s_to_c_fbio = NULL, *c_to_s_fbio = NULL;
294e1051a39Sopenharmony_ci    int testresult = 0, ret;
295e1051a39Sopenharmony_ci    size_t i, j;
296e1051a39Sopenharmony_ci    const char testdata[] = "Test data";
297e1051a39Sopenharmony_ci    char buf[sizeof(testdata)];
298e1051a39Sopenharmony_ci
299e1051a39Sopenharmony_ci    if (!TEST_true(create_ssl_ctx_pair(NULL, TLS_server_method(),
300e1051a39Sopenharmony_ci                                       TLS_client_method(),
301e1051a39Sopenharmony_ci                                       TLS1_VERSION, 0,
302e1051a39Sopenharmony_ci                                       &serverctx, &clientctx, cert, privkey)))
303e1051a39Sopenharmony_ci        goto end;
304e1051a39Sopenharmony_ci
305e1051a39Sopenharmony_ci    /*
306e1051a39Sopenharmony_ci     * We do 2 test runs. The first time around we just do a normal handshake
307e1051a39Sopenharmony_ci     * with lots of async io going on. The second time around we also break up
308e1051a39Sopenharmony_ci     * all records so that the content is only one byte length (up until the
309e1051a39Sopenharmony_ci     * CCS)
310e1051a39Sopenharmony_ci     */
311e1051a39Sopenharmony_ci    if (test == 1)
312e1051a39Sopenharmony_ci        fragment = 1;
313e1051a39Sopenharmony_ci
314e1051a39Sopenharmony_ci
315e1051a39Sopenharmony_ci    s_to_c_fbio = BIO_new(bio_f_async_filter());
316e1051a39Sopenharmony_ci    c_to_s_fbio = BIO_new(bio_f_async_filter());
317e1051a39Sopenharmony_ci    if (!TEST_ptr(s_to_c_fbio)
318e1051a39Sopenharmony_ci            || !TEST_ptr(c_to_s_fbio)) {
319e1051a39Sopenharmony_ci        BIO_free(s_to_c_fbio);
320e1051a39Sopenharmony_ci        BIO_free(c_to_s_fbio);
321e1051a39Sopenharmony_ci        goto end;
322e1051a39Sopenharmony_ci    }
323e1051a39Sopenharmony_ci
324e1051a39Sopenharmony_ci    /* BIOs get freed on error */
325e1051a39Sopenharmony_ci    if (!TEST_true(create_ssl_objects(serverctx, clientctx, &serverssl,
326e1051a39Sopenharmony_ci                                      &clientssl, s_to_c_fbio, c_to_s_fbio))
327e1051a39Sopenharmony_ci            || !TEST_true(create_ssl_connection(serverssl, clientssl,
328e1051a39Sopenharmony_ci                          SSL_ERROR_NONE)))
329e1051a39Sopenharmony_ci        goto end;
330e1051a39Sopenharmony_ci
331e1051a39Sopenharmony_ci    /*
332e1051a39Sopenharmony_ci     * Send and receive some test data. Do the whole thing twice to ensure
333e1051a39Sopenharmony_ci     * we hit at least one async event in both reading and writing
334e1051a39Sopenharmony_ci     */
335e1051a39Sopenharmony_ci    for (j = 0; j < 2; j++) {
336e1051a39Sopenharmony_ci        int len;
337e1051a39Sopenharmony_ci
338e1051a39Sopenharmony_ci        /*
339e1051a39Sopenharmony_ci         * Write some test data. It should never take more than 2 attempts
340e1051a39Sopenharmony_ci         * (the first one might be a retryable fail).
341e1051a39Sopenharmony_ci         */
342e1051a39Sopenharmony_ci        for (ret = -1, i = 0, len = 0; len != sizeof(testdata) && i < 2;
343e1051a39Sopenharmony_ci            i++) {
344e1051a39Sopenharmony_ci            ret = SSL_write(clientssl, testdata + len,
345e1051a39Sopenharmony_ci                sizeof(testdata) - len);
346e1051a39Sopenharmony_ci            if (ret > 0) {
347e1051a39Sopenharmony_ci                len += ret;
348e1051a39Sopenharmony_ci            } else {
349e1051a39Sopenharmony_ci                int ssl_error = SSL_get_error(clientssl, ret);
350e1051a39Sopenharmony_ci
351e1051a39Sopenharmony_ci                if (!TEST_false(ssl_error == SSL_ERROR_SYSCALL ||
352e1051a39Sopenharmony_ci                                ssl_error == SSL_ERROR_SSL))
353e1051a39Sopenharmony_ci                    goto end;
354e1051a39Sopenharmony_ci            }
355e1051a39Sopenharmony_ci        }
356e1051a39Sopenharmony_ci        if (!TEST_size_t_eq(len, sizeof(testdata)))
357e1051a39Sopenharmony_ci            goto end;
358e1051a39Sopenharmony_ci
359e1051a39Sopenharmony_ci        /*
360e1051a39Sopenharmony_ci         * Now read the test data. It may take more attempts here because
361e1051a39Sopenharmony_ci         * it could fail once for each byte read, including all overhead
362e1051a39Sopenharmony_ci         * bytes from the record header/padding etc.
363e1051a39Sopenharmony_ci         */
364e1051a39Sopenharmony_ci        for (ret = -1, i = 0, len = 0; len != sizeof(testdata) &&
365e1051a39Sopenharmony_ci                i < MAX_ATTEMPTS; i++) {
366e1051a39Sopenharmony_ci            ret = SSL_read(serverssl, buf + len, sizeof(buf) - len);
367e1051a39Sopenharmony_ci            if (ret > 0) {
368e1051a39Sopenharmony_ci                len += ret;
369e1051a39Sopenharmony_ci            } else {
370e1051a39Sopenharmony_ci                int ssl_error = SSL_get_error(serverssl, ret);
371e1051a39Sopenharmony_ci
372e1051a39Sopenharmony_ci                if (!TEST_false(ssl_error == SSL_ERROR_SYSCALL ||
373e1051a39Sopenharmony_ci                                ssl_error == SSL_ERROR_SSL))
374e1051a39Sopenharmony_ci                    goto end;
375e1051a39Sopenharmony_ci            }
376e1051a39Sopenharmony_ci        }
377e1051a39Sopenharmony_ci        if (!TEST_mem_eq(testdata, sizeof(testdata), buf, len))
378e1051a39Sopenharmony_ci            goto end;
379e1051a39Sopenharmony_ci    }
380e1051a39Sopenharmony_ci
381e1051a39Sopenharmony_ci    /* Also frees the BIOs */
382e1051a39Sopenharmony_ci    SSL_free(clientssl);
383e1051a39Sopenharmony_ci    SSL_free(serverssl);
384e1051a39Sopenharmony_ci    clientssl = serverssl = NULL;
385e1051a39Sopenharmony_ci
386e1051a39Sopenharmony_ci    testresult = 1;
387e1051a39Sopenharmony_ci
388e1051a39Sopenharmony_ci end:
389e1051a39Sopenharmony_ci    SSL_free(clientssl);
390e1051a39Sopenharmony_ci    SSL_free(serverssl);
391e1051a39Sopenharmony_ci    SSL_CTX_free(clientctx);
392e1051a39Sopenharmony_ci    SSL_CTX_free(serverctx);
393e1051a39Sopenharmony_ci
394e1051a39Sopenharmony_ci    return testresult;
395e1051a39Sopenharmony_ci}
396e1051a39Sopenharmony_ci
397e1051a39Sopenharmony_ciOPT_TEST_DECLARE_USAGE("certname privkey\n")
398e1051a39Sopenharmony_ci
399e1051a39Sopenharmony_ciint setup_tests(void)
400e1051a39Sopenharmony_ci{
401e1051a39Sopenharmony_ci    if (!test_skip_common_options()) {
402e1051a39Sopenharmony_ci        TEST_error("Error parsing test options\n");
403e1051a39Sopenharmony_ci        return 0;
404e1051a39Sopenharmony_ci    }
405e1051a39Sopenharmony_ci
406e1051a39Sopenharmony_ci    if (!TEST_ptr(cert = test_get_argument(0))
407e1051a39Sopenharmony_ci            || !TEST_ptr(privkey = test_get_argument(1)))
408e1051a39Sopenharmony_ci        return 0;
409e1051a39Sopenharmony_ci
410e1051a39Sopenharmony_ci    ADD_ALL_TESTS(test_asyncio, 2);
411e1051a39Sopenharmony_ci    return 1;
412e1051a39Sopenharmony_ci}
413e1051a39Sopenharmony_ci
414e1051a39Sopenharmony_civoid cleanup_tests(void)
415e1051a39Sopenharmony_ci{
416e1051a39Sopenharmony_ci    BIO_meth_free(methods_async);
417e1051a39Sopenharmony_ci}
418