1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci */
9e1051a39Sopenharmony_ci
10e1051a39Sopenharmony_ci#include <string.h>
11e1051a39Sopenharmony_ci
12e1051a39Sopenharmony_ci#include "internal/nelem.h"
13e1051a39Sopenharmony_ci#include "ssltestlib.h"
14e1051a39Sopenharmony_ci#include "../testutil.h"
15e1051a39Sopenharmony_ci#include "e_os.h" /* for ossl_sleep() etc. */
16e1051a39Sopenharmony_ci
17e1051a39Sopenharmony_ci#ifdef OPENSSL_SYS_UNIX
18e1051a39Sopenharmony_ci# include <unistd.h>
19e1051a39Sopenharmony_ci# ifndef OPENSSL_NO_KTLS
20e1051a39Sopenharmony_ci#  include <netinet/in.h>
21e1051a39Sopenharmony_ci#  include <netinet/in.h>
22e1051a39Sopenharmony_ci#  include <arpa/inet.h>
23e1051a39Sopenharmony_ci#  include <sys/socket.h>
24e1051a39Sopenharmony_ci#  include <unistd.h>
25e1051a39Sopenharmony_ci#  include <fcntl.h>
26e1051a39Sopenharmony_ci# endif
27e1051a39Sopenharmony_ci#endif
28e1051a39Sopenharmony_ci
29e1051a39Sopenharmony_cistatic int tls_dump_new(BIO *bi);
30e1051a39Sopenharmony_cistatic int tls_dump_free(BIO *a);
31e1051a39Sopenharmony_cistatic int tls_dump_read(BIO *b, char *out, int outl);
32e1051a39Sopenharmony_cistatic int tls_dump_write(BIO *b, const char *in, int inl);
33e1051a39Sopenharmony_cistatic long tls_dump_ctrl(BIO *b, int cmd, long num, void *ptr);
34e1051a39Sopenharmony_cistatic int tls_dump_gets(BIO *bp, char *buf, int size);
35e1051a39Sopenharmony_cistatic int tls_dump_puts(BIO *bp, const char *str);
36e1051a39Sopenharmony_ci
37e1051a39Sopenharmony_ci/* Choose a sufficiently large type likely to be unused for this custom BIO */
38e1051a39Sopenharmony_ci#define BIO_TYPE_TLS_DUMP_FILTER  (0x80 | BIO_TYPE_FILTER)
39e1051a39Sopenharmony_ci#define BIO_TYPE_MEMPACKET_TEST    0x81
40e1051a39Sopenharmony_ci#define BIO_TYPE_ALWAYS_RETRY      0x82
41e1051a39Sopenharmony_ci
42e1051a39Sopenharmony_cistatic BIO_METHOD *method_tls_dump = NULL;
43e1051a39Sopenharmony_cistatic BIO_METHOD *meth_mem = NULL;
44e1051a39Sopenharmony_cistatic BIO_METHOD *meth_always_retry = NULL;
45e1051a39Sopenharmony_ci
46e1051a39Sopenharmony_ci/* Note: Not thread safe! */
47e1051a39Sopenharmony_ciconst BIO_METHOD *bio_f_tls_dump_filter(void)
48e1051a39Sopenharmony_ci{
49e1051a39Sopenharmony_ci    if (method_tls_dump == NULL) {
50e1051a39Sopenharmony_ci        method_tls_dump = BIO_meth_new(BIO_TYPE_TLS_DUMP_FILTER,
51e1051a39Sopenharmony_ci                                        "TLS dump filter");
52e1051a39Sopenharmony_ci        if (   method_tls_dump == NULL
53e1051a39Sopenharmony_ci            || !BIO_meth_set_write(method_tls_dump, tls_dump_write)
54e1051a39Sopenharmony_ci            || !BIO_meth_set_read(method_tls_dump, tls_dump_read)
55e1051a39Sopenharmony_ci            || !BIO_meth_set_puts(method_tls_dump, tls_dump_puts)
56e1051a39Sopenharmony_ci            || !BIO_meth_set_gets(method_tls_dump, tls_dump_gets)
57e1051a39Sopenharmony_ci            || !BIO_meth_set_ctrl(method_tls_dump, tls_dump_ctrl)
58e1051a39Sopenharmony_ci            || !BIO_meth_set_create(method_tls_dump, tls_dump_new)
59e1051a39Sopenharmony_ci            || !BIO_meth_set_destroy(method_tls_dump, tls_dump_free))
60e1051a39Sopenharmony_ci            return NULL;
61e1051a39Sopenharmony_ci    }
62e1051a39Sopenharmony_ci    return method_tls_dump;
63e1051a39Sopenharmony_ci}
64e1051a39Sopenharmony_ci
65e1051a39Sopenharmony_civoid bio_f_tls_dump_filter_free(void)
66e1051a39Sopenharmony_ci{
67e1051a39Sopenharmony_ci    BIO_meth_free(method_tls_dump);
68e1051a39Sopenharmony_ci}
69e1051a39Sopenharmony_ci
70e1051a39Sopenharmony_cistatic int tls_dump_new(BIO *bio)
71e1051a39Sopenharmony_ci{
72e1051a39Sopenharmony_ci    BIO_set_init(bio, 1);
73e1051a39Sopenharmony_ci    return 1;
74e1051a39Sopenharmony_ci}
75e1051a39Sopenharmony_ci
76e1051a39Sopenharmony_cistatic int tls_dump_free(BIO *bio)
77e1051a39Sopenharmony_ci{
78e1051a39Sopenharmony_ci    BIO_set_init(bio, 0);
79e1051a39Sopenharmony_ci
80e1051a39Sopenharmony_ci    return 1;
81e1051a39Sopenharmony_ci}
82e1051a39Sopenharmony_ci
83e1051a39Sopenharmony_cistatic void copy_flags(BIO *bio)
84e1051a39Sopenharmony_ci{
85e1051a39Sopenharmony_ci    int flags;
86e1051a39Sopenharmony_ci    BIO *next = BIO_next(bio);
87e1051a39Sopenharmony_ci
88e1051a39Sopenharmony_ci    flags = BIO_test_flags(next, BIO_FLAGS_SHOULD_RETRY | BIO_FLAGS_RWS);
89e1051a39Sopenharmony_ci    BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY | BIO_FLAGS_RWS);
90e1051a39Sopenharmony_ci    BIO_set_flags(bio, flags);
91e1051a39Sopenharmony_ci}
92e1051a39Sopenharmony_ci
93e1051a39Sopenharmony_ci#define RECORD_CONTENT_TYPE     0
94e1051a39Sopenharmony_ci#define RECORD_VERSION_HI       1
95e1051a39Sopenharmony_ci#define RECORD_VERSION_LO       2
96e1051a39Sopenharmony_ci#define RECORD_EPOCH_HI         3
97e1051a39Sopenharmony_ci#define RECORD_EPOCH_LO         4
98e1051a39Sopenharmony_ci#define RECORD_SEQUENCE_START   5
99e1051a39Sopenharmony_ci#define RECORD_SEQUENCE_END     10
100e1051a39Sopenharmony_ci#define RECORD_LEN_HI           11
101e1051a39Sopenharmony_ci#define RECORD_LEN_LO           12
102e1051a39Sopenharmony_ci
103e1051a39Sopenharmony_ci#define MSG_TYPE                0
104e1051a39Sopenharmony_ci#define MSG_LEN_HI              1
105e1051a39Sopenharmony_ci#define MSG_LEN_MID             2
106e1051a39Sopenharmony_ci#define MSG_LEN_LO              3
107e1051a39Sopenharmony_ci#define MSG_SEQ_HI              4
108e1051a39Sopenharmony_ci#define MSG_SEQ_LO              5
109e1051a39Sopenharmony_ci#define MSG_FRAG_OFF_HI         6
110e1051a39Sopenharmony_ci#define MSG_FRAG_OFF_MID        7
111e1051a39Sopenharmony_ci#define MSG_FRAG_OFF_LO         8
112e1051a39Sopenharmony_ci#define MSG_FRAG_LEN_HI         9
113e1051a39Sopenharmony_ci#define MSG_FRAG_LEN_MID        10
114e1051a39Sopenharmony_ci#define MSG_FRAG_LEN_LO         11
115e1051a39Sopenharmony_ci
116e1051a39Sopenharmony_ci
117e1051a39Sopenharmony_cistatic void dump_data(const char *data, int len)
118e1051a39Sopenharmony_ci{
119e1051a39Sopenharmony_ci    int rem, i, content, reclen, msglen, fragoff, fraglen, epoch;
120e1051a39Sopenharmony_ci    unsigned char *rec;
121e1051a39Sopenharmony_ci
122e1051a39Sopenharmony_ci    printf("---- START OF PACKET ----\n");
123e1051a39Sopenharmony_ci
124e1051a39Sopenharmony_ci    rem = len;
125e1051a39Sopenharmony_ci    rec = (unsigned char *)data;
126e1051a39Sopenharmony_ci
127e1051a39Sopenharmony_ci    while (rem > 0) {
128e1051a39Sopenharmony_ci        if (rem != len)
129e1051a39Sopenharmony_ci            printf("*\n");
130e1051a39Sopenharmony_ci        printf("*---- START OF RECORD ----\n");
131e1051a39Sopenharmony_ci        if (rem < DTLS1_RT_HEADER_LENGTH) {
132e1051a39Sopenharmony_ci            printf("*---- RECORD TRUNCATED ----\n");
133e1051a39Sopenharmony_ci            break;
134e1051a39Sopenharmony_ci        }
135e1051a39Sopenharmony_ci        content = rec[RECORD_CONTENT_TYPE];
136e1051a39Sopenharmony_ci        printf("** Record Content-type: %d\n", content);
137e1051a39Sopenharmony_ci        printf("** Record Version: %02x%02x\n",
138e1051a39Sopenharmony_ci               rec[RECORD_VERSION_HI], rec[RECORD_VERSION_LO]);
139e1051a39Sopenharmony_ci        epoch = (rec[RECORD_EPOCH_HI] << 8) | rec[RECORD_EPOCH_LO];
140e1051a39Sopenharmony_ci        printf("** Record Epoch: %d\n", epoch);
141e1051a39Sopenharmony_ci        printf("** Record Sequence: ");
142e1051a39Sopenharmony_ci        for (i = RECORD_SEQUENCE_START; i <= RECORD_SEQUENCE_END; i++)
143e1051a39Sopenharmony_ci            printf("%02x", rec[i]);
144e1051a39Sopenharmony_ci        reclen = (rec[RECORD_LEN_HI] << 8) | rec[RECORD_LEN_LO];
145e1051a39Sopenharmony_ci        printf("\n** Record Length: %d\n", reclen);
146e1051a39Sopenharmony_ci
147e1051a39Sopenharmony_ci        /* Now look at message */
148e1051a39Sopenharmony_ci        rec += DTLS1_RT_HEADER_LENGTH;
149e1051a39Sopenharmony_ci        rem -= DTLS1_RT_HEADER_LENGTH;
150e1051a39Sopenharmony_ci        if (content == SSL3_RT_HANDSHAKE) {
151e1051a39Sopenharmony_ci            printf("**---- START OF HANDSHAKE MESSAGE FRAGMENT ----\n");
152e1051a39Sopenharmony_ci            if (epoch > 0) {
153e1051a39Sopenharmony_ci                printf("**---- HANDSHAKE MESSAGE FRAGMENT ENCRYPTED ----\n");
154e1051a39Sopenharmony_ci            } else if (rem < DTLS1_HM_HEADER_LENGTH
155e1051a39Sopenharmony_ci                    || reclen < DTLS1_HM_HEADER_LENGTH) {
156e1051a39Sopenharmony_ci                printf("**---- HANDSHAKE MESSAGE FRAGMENT TRUNCATED ----\n");
157e1051a39Sopenharmony_ci            } else {
158e1051a39Sopenharmony_ci                printf("*** Message Type: %d\n", rec[MSG_TYPE]);
159e1051a39Sopenharmony_ci                msglen = (rec[MSG_LEN_HI] << 16) | (rec[MSG_LEN_MID] << 8)
160e1051a39Sopenharmony_ci                         | rec[MSG_LEN_LO];
161e1051a39Sopenharmony_ci                printf("*** Message Length: %d\n", msglen);
162e1051a39Sopenharmony_ci                printf("*** Message sequence: %d\n",
163e1051a39Sopenharmony_ci                       (rec[MSG_SEQ_HI] << 8) | rec[MSG_SEQ_LO]);
164e1051a39Sopenharmony_ci                fragoff = (rec[MSG_FRAG_OFF_HI] << 16)
165e1051a39Sopenharmony_ci                          | (rec[MSG_FRAG_OFF_MID] << 8)
166e1051a39Sopenharmony_ci                          | rec[MSG_FRAG_OFF_LO];
167e1051a39Sopenharmony_ci                printf("*** Message Fragment offset: %d\n", fragoff);
168e1051a39Sopenharmony_ci                fraglen = (rec[MSG_FRAG_LEN_HI] << 16)
169e1051a39Sopenharmony_ci                          | (rec[MSG_FRAG_LEN_MID] << 8)
170e1051a39Sopenharmony_ci                          | rec[MSG_FRAG_LEN_LO];
171e1051a39Sopenharmony_ci                printf("*** Message Fragment len: %d\n", fraglen);
172e1051a39Sopenharmony_ci                if (fragoff + fraglen > msglen)
173e1051a39Sopenharmony_ci                    printf("***---- HANDSHAKE MESSAGE FRAGMENT INVALID ----\n");
174e1051a39Sopenharmony_ci                else if (reclen < fraglen)
175e1051a39Sopenharmony_ci                    printf("**---- HANDSHAKE MESSAGE FRAGMENT TRUNCATED ----\n");
176e1051a39Sopenharmony_ci                else
177e1051a39Sopenharmony_ci                    printf("**---- END OF HANDSHAKE MESSAGE FRAGMENT ----\n");
178e1051a39Sopenharmony_ci            }
179e1051a39Sopenharmony_ci        }
180e1051a39Sopenharmony_ci        if (rem < reclen) {
181e1051a39Sopenharmony_ci            printf("*---- RECORD TRUNCATED ----\n");
182e1051a39Sopenharmony_ci            rem = 0;
183e1051a39Sopenharmony_ci        } else {
184e1051a39Sopenharmony_ci            rec += reclen;
185e1051a39Sopenharmony_ci            rem -= reclen;
186e1051a39Sopenharmony_ci            printf("*---- END OF RECORD ----\n");
187e1051a39Sopenharmony_ci        }
188e1051a39Sopenharmony_ci    }
189e1051a39Sopenharmony_ci    printf("---- END OF PACKET ----\n\n");
190e1051a39Sopenharmony_ci    fflush(stdout);
191e1051a39Sopenharmony_ci}
192e1051a39Sopenharmony_ci
193e1051a39Sopenharmony_cistatic int tls_dump_read(BIO *bio, char *out, int outl)
194e1051a39Sopenharmony_ci{
195e1051a39Sopenharmony_ci    int ret;
196e1051a39Sopenharmony_ci    BIO *next = BIO_next(bio);
197e1051a39Sopenharmony_ci
198e1051a39Sopenharmony_ci    ret = BIO_read(next, out, outl);
199e1051a39Sopenharmony_ci    copy_flags(bio);
200e1051a39Sopenharmony_ci
201e1051a39Sopenharmony_ci    if (ret > 0) {
202e1051a39Sopenharmony_ci        dump_data(out, ret);
203e1051a39Sopenharmony_ci    }
204e1051a39Sopenharmony_ci
205e1051a39Sopenharmony_ci    return ret;
206e1051a39Sopenharmony_ci}
207e1051a39Sopenharmony_ci
208e1051a39Sopenharmony_cistatic int tls_dump_write(BIO *bio, const char *in, int inl)
209e1051a39Sopenharmony_ci{
210e1051a39Sopenharmony_ci    int ret;
211e1051a39Sopenharmony_ci    BIO *next = BIO_next(bio);
212e1051a39Sopenharmony_ci
213e1051a39Sopenharmony_ci    ret = BIO_write(next, in, inl);
214e1051a39Sopenharmony_ci    copy_flags(bio);
215e1051a39Sopenharmony_ci
216e1051a39Sopenharmony_ci    return ret;
217e1051a39Sopenharmony_ci}
218e1051a39Sopenharmony_ci
219e1051a39Sopenharmony_cistatic long tls_dump_ctrl(BIO *bio, int cmd, long num, void *ptr)
220e1051a39Sopenharmony_ci{
221e1051a39Sopenharmony_ci    long ret;
222e1051a39Sopenharmony_ci    BIO *next = BIO_next(bio);
223e1051a39Sopenharmony_ci
224e1051a39Sopenharmony_ci    if (next == NULL)
225e1051a39Sopenharmony_ci        return 0;
226e1051a39Sopenharmony_ci
227e1051a39Sopenharmony_ci    switch (cmd) {
228e1051a39Sopenharmony_ci    case BIO_CTRL_DUP:
229e1051a39Sopenharmony_ci        ret = 0L;
230e1051a39Sopenharmony_ci        break;
231e1051a39Sopenharmony_ci    default:
232e1051a39Sopenharmony_ci        ret = BIO_ctrl(next, cmd, num, ptr);
233e1051a39Sopenharmony_ci        break;
234e1051a39Sopenharmony_ci    }
235e1051a39Sopenharmony_ci    return ret;
236e1051a39Sopenharmony_ci}
237e1051a39Sopenharmony_ci
238e1051a39Sopenharmony_cistatic int tls_dump_gets(BIO *bio, char *buf, int size)
239e1051a39Sopenharmony_ci{
240e1051a39Sopenharmony_ci    /* We don't support this - not needed anyway */
241e1051a39Sopenharmony_ci    return -1;
242e1051a39Sopenharmony_ci}
243e1051a39Sopenharmony_ci
244e1051a39Sopenharmony_cistatic int tls_dump_puts(BIO *bio, const char *str)
245e1051a39Sopenharmony_ci{
246e1051a39Sopenharmony_ci    return tls_dump_write(bio, str, strlen(str));
247e1051a39Sopenharmony_ci}
248e1051a39Sopenharmony_ci
249e1051a39Sopenharmony_ci
250e1051a39Sopenharmony_cistruct mempacket_st {
251e1051a39Sopenharmony_ci    unsigned char *data;
252e1051a39Sopenharmony_ci    int len;
253e1051a39Sopenharmony_ci    unsigned int num;
254e1051a39Sopenharmony_ci    unsigned int type;
255e1051a39Sopenharmony_ci};
256e1051a39Sopenharmony_ci
257e1051a39Sopenharmony_cistatic void mempacket_free(MEMPACKET *pkt)
258e1051a39Sopenharmony_ci{
259e1051a39Sopenharmony_ci    if (pkt->data != NULL)
260e1051a39Sopenharmony_ci        OPENSSL_free(pkt->data);
261e1051a39Sopenharmony_ci    OPENSSL_free(pkt);
262e1051a39Sopenharmony_ci}
263e1051a39Sopenharmony_ci
264e1051a39Sopenharmony_citypedef struct mempacket_test_ctx_st {
265e1051a39Sopenharmony_ci    STACK_OF(MEMPACKET) *pkts;
266e1051a39Sopenharmony_ci    unsigned int epoch;
267e1051a39Sopenharmony_ci    unsigned int currrec;
268e1051a39Sopenharmony_ci    unsigned int currpkt;
269e1051a39Sopenharmony_ci    unsigned int lastpkt;
270e1051a39Sopenharmony_ci    unsigned int injected;
271e1051a39Sopenharmony_ci    unsigned int noinject;
272e1051a39Sopenharmony_ci    unsigned int dropepoch;
273e1051a39Sopenharmony_ci    int droprec;
274e1051a39Sopenharmony_ci    int duprec;
275e1051a39Sopenharmony_ci} MEMPACKET_TEST_CTX;
276e1051a39Sopenharmony_ci
277e1051a39Sopenharmony_cistatic int mempacket_test_new(BIO *bi);
278e1051a39Sopenharmony_cistatic int mempacket_test_free(BIO *a);
279e1051a39Sopenharmony_cistatic int mempacket_test_read(BIO *b, char *out, int outl);
280e1051a39Sopenharmony_cistatic int mempacket_test_write(BIO *b, const char *in, int inl);
281e1051a39Sopenharmony_cistatic long mempacket_test_ctrl(BIO *b, int cmd, long num, void *ptr);
282e1051a39Sopenharmony_cistatic int mempacket_test_gets(BIO *bp, char *buf, int size);
283e1051a39Sopenharmony_cistatic int mempacket_test_puts(BIO *bp, const char *str);
284e1051a39Sopenharmony_ci
285e1051a39Sopenharmony_ciconst BIO_METHOD *bio_s_mempacket_test(void)
286e1051a39Sopenharmony_ci{
287e1051a39Sopenharmony_ci    if (meth_mem == NULL) {
288e1051a39Sopenharmony_ci        if (!TEST_ptr(meth_mem = BIO_meth_new(BIO_TYPE_MEMPACKET_TEST,
289e1051a39Sopenharmony_ci                                              "Mem Packet Test"))
290e1051a39Sopenharmony_ci            || !TEST_true(BIO_meth_set_write(meth_mem, mempacket_test_write))
291e1051a39Sopenharmony_ci            || !TEST_true(BIO_meth_set_read(meth_mem, mempacket_test_read))
292e1051a39Sopenharmony_ci            || !TEST_true(BIO_meth_set_puts(meth_mem, mempacket_test_puts))
293e1051a39Sopenharmony_ci            || !TEST_true(BIO_meth_set_gets(meth_mem, mempacket_test_gets))
294e1051a39Sopenharmony_ci            || !TEST_true(BIO_meth_set_ctrl(meth_mem, mempacket_test_ctrl))
295e1051a39Sopenharmony_ci            || !TEST_true(BIO_meth_set_create(meth_mem, mempacket_test_new))
296e1051a39Sopenharmony_ci            || !TEST_true(BIO_meth_set_destroy(meth_mem, mempacket_test_free)))
297e1051a39Sopenharmony_ci            return NULL;
298e1051a39Sopenharmony_ci    }
299e1051a39Sopenharmony_ci    return meth_mem;
300e1051a39Sopenharmony_ci}
301e1051a39Sopenharmony_ci
302e1051a39Sopenharmony_civoid bio_s_mempacket_test_free(void)
303e1051a39Sopenharmony_ci{
304e1051a39Sopenharmony_ci    BIO_meth_free(meth_mem);
305e1051a39Sopenharmony_ci}
306e1051a39Sopenharmony_ci
307e1051a39Sopenharmony_cistatic int mempacket_test_new(BIO *bio)
308e1051a39Sopenharmony_ci{
309e1051a39Sopenharmony_ci    MEMPACKET_TEST_CTX *ctx;
310e1051a39Sopenharmony_ci
311e1051a39Sopenharmony_ci    if (!TEST_ptr(ctx = OPENSSL_zalloc(sizeof(*ctx))))
312e1051a39Sopenharmony_ci        return 0;
313e1051a39Sopenharmony_ci    if (!TEST_ptr(ctx->pkts = sk_MEMPACKET_new_null())) {
314e1051a39Sopenharmony_ci        OPENSSL_free(ctx);
315e1051a39Sopenharmony_ci        return 0;
316e1051a39Sopenharmony_ci    }
317e1051a39Sopenharmony_ci    ctx->dropepoch = 0;
318e1051a39Sopenharmony_ci    ctx->droprec = -1;
319e1051a39Sopenharmony_ci    BIO_set_init(bio, 1);
320e1051a39Sopenharmony_ci    BIO_set_data(bio, ctx);
321e1051a39Sopenharmony_ci    return 1;
322e1051a39Sopenharmony_ci}
323e1051a39Sopenharmony_ci
324e1051a39Sopenharmony_cistatic int mempacket_test_free(BIO *bio)
325e1051a39Sopenharmony_ci{
326e1051a39Sopenharmony_ci    MEMPACKET_TEST_CTX *ctx = BIO_get_data(bio);
327e1051a39Sopenharmony_ci
328e1051a39Sopenharmony_ci    sk_MEMPACKET_pop_free(ctx->pkts, mempacket_free);
329e1051a39Sopenharmony_ci    OPENSSL_free(ctx);
330e1051a39Sopenharmony_ci    BIO_set_data(bio, NULL);
331e1051a39Sopenharmony_ci    BIO_set_init(bio, 0);
332e1051a39Sopenharmony_ci    return 1;
333e1051a39Sopenharmony_ci}
334e1051a39Sopenharmony_ci
335e1051a39Sopenharmony_ci/* Record Header values */
336e1051a39Sopenharmony_ci#define EPOCH_HI        3
337e1051a39Sopenharmony_ci#define EPOCH_LO        4
338e1051a39Sopenharmony_ci#define RECORD_SEQUENCE 10
339e1051a39Sopenharmony_ci#define RECORD_LEN_HI   11
340e1051a39Sopenharmony_ci#define RECORD_LEN_LO   12
341e1051a39Sopenharmony_ci
342e1051a39Sopenharmony_ci#define STANDARD_PACKET                 0
343e1051a39Sopenharmony_ci
344e1051a39Sopenharmony_cistatic int mempacket_test_read(BIO *bio, char *out, int outl)
345e1051a39Sopenharmony_ci{
346e1051a39Sopenharmony_ci    MEMPACKET_TEST_CTX *ctx = BIO_get_data(bio);
347e1051a39Sopenharmony_ci    MEMPACKET *thispkt;
348e1051a39Sopenharmony_ci    unsigned char *rec;
349e1051a39Sopenharmony_ci    int rem;
350e1051a39Sopenharmony_ci    unsigned int seq, offset, len, epoch;
351e1051a39Sopenharmony_ci
352e1051a39Sopenharmony_ci    BIO_clear_retry_flags(bio);
353e1051a39Sopenharmony_ci    if ((thispkt = sk_MEMPACKET_value(ctx->pkts, 0)) == NULL
354e1051a39Sopenharmony_ci        || thispkt->num != ctx->currpkt) {
355e1051a39Sopenharmony_ci        /* Probably run out of data */
356e1051a39Sopenharmony_ci        BIO_set_retry_read(bio);
357e1051a39Sopenharmony_ci        return -1;
358e1051a39Sopenharmony_ci    }
359e1051a39Sopenharmony_ci    (void)sk_MEMPACKET_shift(ctx->pkts);
360e1051a39Sopenharmony_ci    ctx->currpkt++;
361e1051a39Sopenharmony_ci
362e1051a39Sopenharmony_ci    if (outl > thispkt->len)
363e1051a39Sopenharmony_ci        outl = thispkt->len;
364e1051a39Sopenharmony_ci
365e1051a39Sopenharmony_ci    if (thispkt->type != INJECT_PACKET_IGNORE_REC_SEQ
366e1051a39Sopenharmony_ci            && (ctx->injected || ctx->droprec >= 0)) {
367e1051a39Sopenharmony_ci        /*
368e1051a39Sopenharmony_ci         * Overwrite the record sequence number. We strictly number them in
369e1051a39Sopenharmony_ci         * the order received. Since we are actually a reliable transport
370e1051a39Sopenharmony_ci         * we know that there won't be any re-ordering. We overwrite to deal
371e1051a39Sopenharmony_ci         * with any packets that have been injected
372e1051a39Sopenharmony_ci         */
373e1051a39Sopenharmony_ci        for (rem = thispkt->len, rec = thispkt->data; rem > 0; rem -= len) {
374e1051a39Sopenharmony_ci            if (rem < DTLS1_RT_HEADER_LENGTH)
375e1051a39Sopenharmony_ci                return -1;
376e1051a39Sopenharmony_ci            epoch = (rec[EPOCH_HI] << 8) | rec[EPOCH_LO];
377e1051a39Sopenharmony_ci            if (epoch != ctx->epoch) {
378e1051a39Sopenharmony_ci                ctx->epoch = epoch;
379e1051a39Sopenharmony_ci                ctx->currrec = 0;
380e1051a39Sopenharmony_ci            }
381e1051a39Sopenharmony_ci            seq = ctx->currrec;
382e1051a39Sopenharmony_ci            offset = 0;
383e1051a39Sopenharmony_ci            do {
384e1051a39Sopenharmony_ci                rec[RECORD_SEQUENCE - offset] = seq & 0xFF;
385e1051a39Sopenharmony_ci                seq >>= 8;
386e1051a39Sopenharmony_ci                offset++;
387e1051a39Sopenharmony_ci            } while (seq > 0);
388e1051a39Sopenharmony_ci
389e1051a39Sopenharmony_ci            len = ((rec[RECORD_LEN_HI] << 8) | rec[RECORD_LEN_LO])
390e1051a39Sopenharmony_ci                  + DTLS1_RT_HEADER_LENGTH;
391e1051a39Sopenharmony_ci            if (rem < (int)len)
392e1051a39Sopenharmony_ci                return -1;
393e1051a39Sopenharmony_ci            if (ctx->droprec == (int)ctx->currrec && ctx->dropepoch == epoch) {
394e1051a39Sopenharmony_ci                if (rem > (int)len)
395e1051a39Sopenharmony_ci                    memmove(rec, rec + len, rem - len);
396e1051a39Sopenharmony_ci                outl -= len;
397e1051a39Sopenharmony_ci                ctx->droprec = -1;
398e1051a39Sopenharmony_ci                if (outl == 0)
399e1051a39Sopenharmony_ci                    BIO_set_retry_read(bio);
400e1051a39Sopenharmony_ci            } else {
401e1051a39Sopenharmony_ci                rec += len;
402e1051a39Sopenharmony_ci            }
403e1051a39Sopenharmony_ci
404e1051a39Sopenharmony_ci            ctx->currrec++;
405e1051a39Sopenharmony_ci        }
406e1051a39Sopenharmony_ci    }
407e1051a39Sopenharmony_ci
408e1051a39Sopenharmony_ci    memcpy(out, thispkt->data, outl);
409e1051a39Sopenharmony_ci    mempacket_free(thispkt);
410e1051a39Sopenharmony_ci    return outl;
411e1051a39Sopenharmony_ci}
412e1051a39Sopenharmony_ci
413e1051a39Sopenharmony_ci/*
414e1051a39Sopenharmony_ci * Look for records from different epochs in the last datagram and swap them
415e1051a39Sopenharmony_ci * around
416e1051a39Sopenharmony_ci */
417e1051a39Sopenharmony_ciint mempacket_swap_epoch(BIO *bio)
418e1051a39Sopenharmony_ci{
419e1051a39Sopenharmony_ci    MEMPACKET_TEST_CTX *ctx = BIO_get_data(bio);
420e1051a39Sopenharmony_ci    MEMPACKET *thispkt;
421e1051a39Sopenharmony_ci    int rem, len, prevlen = 0, pktnum;
422e1051a39Sopenharmony_ci    unsigned char *rec, *prevrec = NULL, *tmp;
423e1051a39Sopenharmony_ci    unsigned int epoch;
424e1051a39Sopenharmony_ci    int numpkts = sk_MEMPACKET_num(ctx->pkts);
425e1051a39Sopenharmony_ci
426e1051a39Sopenharmony_ci    if (numpkts <= 0)
427e1051a39Sopenharmony_ci        return 0;
428e1051a39Sopenharmony_ci
429e1051a39Sopenharmony_ci    /*
430e1051a39Sopenharmony_ci     * If there are multiple packets we only look in the last one. This should
431e1051a39Sopenharmony_ci     * always be the one where any epoch change occurs.
432e1051a39Sopenharmony_ci     */
433e1051a39Sopenharmony_ci    thispkt = sk_MEMPACKET_value(ctx->pkts, numpkts - 1);
434e1051a39Sopenharmony_ci    if (thispkt == NULL)
435e1051a39Sopenharmony_ci        return 0;
436e1051a39Sopenharmony_ci
437e1051a39Sopenharmony_ci    for (rem = thispkt->len, rec = thispkt->data; rem > 0; rem -= len, rec += len) {
438e1051a39Sopenharmony_ci        if (rem < DTLS1_RT_HEADER_LENGTH)
439e1051a39Sopenharmony_ci            return 0;
440e1051a39Sopenharmony_ci        epoch = (rec[EPOCH_HI] << 8) | rec[EPOCH_LO];
441e1051a39Sopenharmony_ci        len = ((rec[RECORD_LEN_HI] << 8) | rec[RECORD_LEN_LO])
442e1051a39Sopenharmony_ci                + DTLS1_RT_HEADER_LENGTH;
443e1051a39Sopenharmony_ci        if (rem < len)
444e1051a39Sopenharmony_ci            return 0;
445e1051a39Sopenharmony_ci
446e1051a39Sopenharmony_ci        /* Assumes the epoch change does not happen on the first record */
447e1051a39Sopenharmony_ci        if (epoch != ctx->epoch) {
448e1051a39Sopenharmony_ci            if (prevrec == NULL)
449e1051a39Sopenharmony_ci                return 0;
450e1051a39Sopenharmony_ci
451e1051a39Sopenharmony_ci            /*
452e1051a39Sopenharmony_ci             * We found 2 records with different epochs. Take a copy of the
453e1051a39Sopenharmony_ci             * earlier record
454e1051a39Sopenharmony_ci             */
455e1051a39Sopenharmony_ci            tmp = OPENSSL_malloc(prevlen);
456e1051a39Sopenharmony_ci            if (tmp == NULL)
457e1051a39Sopenharmony_ci                return 0;
458e1051a39Sopenharmony_ci
459e1051a39Sopenharmony_ci            memcpy(tmp, prevrec, prevlen);
460e1051a39Sopenharmony_ci            /*
461e1051a39Sopenharmony_ci             * Move everything from this record onwards, including any trailing
462e1051a39Sopenharmony_ci             * records, and overwrite the earlier record
463e1051a39Sopenharmony_ci             */
464e1051a39Sopenharmony_ci            memmove(prevrec, rec, rem);
465e1051a39Sopenharmony_ci            thispkt->len -= prevlen;
466e1051a39Sopenharmony_ci            pktnum = thispkt->num;
467e1051a39Sopenharmony_ci
468e1051a39Sopenharmony_ci            /*
469e1051a39Sopenharmony_ci             * Create a new packet for the earlier record that we took out and
470e1051a39Sopenharmony_ci             * add it to the end of the packet list.
471e1051a39Sopenharmony_ci             */
472e1051a39Sopenharmony_ci            thispkt = OPENSSL_malloc(sizeof(*thispkt));
473e1051a39Sopenharmony_ci            if (thispkt == NULL) {
474e1051a39Sopenharmony_ci                OPENSSL_free(tmp);
475e1051a39Sopenharmony_ci                return 0;
476e1051a39Sopenharmony_ci            }
477e1051a39Sopenharmony_ci            thispkt->type = INJECT_PACKET;
478e1051a39Sopenharmony_ci            thispkt->data = tmp;
479e1051a39Sopenharmony_ci            thispkt->len = prevlen;
480e1051a39Sopenharmony_ci            thispkt->num = pktnum + 1;
481e1051a39Sopenharmony_ci            if (sk_MEMPACKET_insert(ctx->pkts, thispkt, numpkts) <= 0) {
482e1051a39Sopenharmony_ci                OPENSSL_free(tmp);
483e1051a39Sopenharmony_ci                OPENSSL_free(thispkt);
484e1051a39Sopenharmony_ci                return 0;
485e1051a39Sopenharmony_ci            }
486e1051a39Sopenharmony_ci
487e1051a39Sopenharmony_ci            return 1;
488e1051a39Sopenharmony_ci        }
489e1051a39Sopenharmony_ci        prevrec = rec;
490e1051a39Sopenharmony_ci        prevlen = len;
491e1051a39Sopenharmony_ci    }
492e1051a39Sopenharmony_ci
493e1051a39Sopenharmony_ci    return 0;
494e1051a39Sopenharmony_ci}
495e1051a39Sopenharmony_ci
496e1051a39Sopenharmony_ci/* Move packet from position s to position d in the list (d < s) */
497e1051a39Sopenharmony_ciint mempacket_move_packet(BIO *bio, int d, int s)
498e1051a39Sopenharmony_ci{
499e1051a39Sopenharmony_ci    MEMPACKET_TEST_CTX *ctx = BIO_get_data(bio);
500e1051a39Sopenharmony_ci    MEMPACKET *thispkt;
501e1051a39Sopenharmony_ci    int numpkts = sk_MEMPACKET_num(ctx->pkts);
502e1051a39Sopenharmony_ci    int i;
503e1051a39Sopenharmony_ci
504e1051a39Sopenharmony_ci    if (d >= s)
505e1051a39Sopenharmony_ci        return 0;
506e1051a39Sopenharmony_ci
507e1051a39Sopenharmony_ci    /* We need at least s + 1 packets to be able to swap them */
508e1051a39Sopenharmony_ci    if (numpkts <= s)
509e1051a39Sopenharmony_ci        return 0;
510e1051a39Sopenharmony_ci
511e1051a39Sopenharmony_ci    /* Get the packet at position s */
512e1051a39Sopenharmony_ci    thispkt = sk_MEMPACKET_value(ctx->pkts, s);
513e1051a39Sopenharmony_ci    if (thispkt == NULL)
514e1051a39Sopenharmony_ci        return 0;
515e1051a39Sopenharmony_ci
516e1051a39Sopenharmony_ci    /* Remove and re-add it */
517e1051a39Sopenharmony_ci    if (sk_MEMPACKET_delete(ctx->pkts, s) != thispkt)
518e1051a39Sopenharmony_ci        return 0;
519e1051a39Sopenharmony_ci
520e1051a39Sopenharmony_ci    thispkt->num -= (s - d);
521e1051a39Sopenharmony_ci    if (sk_MEMPACKET_insert(ctx->pkts, thispkt, d) <= 0)
522e1051a39Sopenharmony_ci        return 0;
523e1051a39Sopenharmony_ci
524e1051a39Sopenharmony_ci    /* Increment the packet numbers for moved packets */
525e1051a39Sopenharmony_ci    for (i = d + 1; i <= s; i++) {
526e1051a39Sopenharmony_ci        thispkt = sk_MEMPACKET_value(ctx->pkts, i);
527e1051a39Sopenharmony_ci        thispkt->num++;
528e1051a39Sopenharmony_ci    }
529e1051a39Sopenharmony_ci    return 1;
530e1051a39Sopenharmony_ci}
531e1051a39Sopenharmony_ci
532e1051a39Sopenharmony_ciint mempacket_test_inject(BIO *bio, const char *in, int inl, int pktnum,
533e1051a39Sopenharmony_ci                          int type)
534e1051a39Sopenharmony_ci{
535e1051a39Sopenharmony_ci    MEMPACKET_TEST_CTX *ctx = BIO_get_data(bio);
536e1051a39Sopenharmony_ci    MEMPACKET *thispkt = NULL, *looppkt, *nextpkt, *allpkts[3];
537e1051a39Sopenharmony_ci    int i, duprec;
538e1051a39Sopenharmony_ci    const unsigned char *inu = (const unsigned char *)in;
539e1051a39Sopenharmony_ci    size_t len = ((inu[RECORD_LEN_HI] << 8) | inu[RECORD_LEN_LO])
540e1051a39Sopenharmony_ci                 + DTLS1_RT_HEADER_LENGTH;
541e1051a39Sopenharmony_ci
542e1051a39Sopenharmony_ci    if (ctx == NULL)
543e1051a39Sopenharmony_ci        return -1;
544e1051a39Sopenharmony_ci
545e1051a39Sopenharmony_ci    if ((size_t)inl < len)
546e1051a39Sopenharmony_ci        return -1;
547e1051a39Sopenharmony_ci
548e1051a39Sopenharmony_ci    if ((size_t)inl == len)
549e1051a39Sopenharmony_ci        duprec = 0;
550e1051a39Sopenharmony_ci    else
551e1051a39Sopenharmony_ci        duprec = ctx->duprec > 0;
552e1051a39Sopenharmony_ci
553e1051a39Sopenharmony_ci    /* We don't support arbitrary injection when duplicating records */
554e1051a39Sopenharmony_ci    if (duprec && pktnum != -1)
555e1051a39Sopenharmony_ci        return -1;
556e1051a39Sopenharmony_ci
557e1051a39Sopenharmony_ci    /* We only allow injection before we've started writing any data */
558e1051a39Sopenharmony_ci    if (pktnum >= 0) {
559e1051a39Sopenharmony_ci        if (ctx->noinject)
560e1051a39Sopenharmony_ci            return -1;
561e1051a39Sopenharmony_ci        ctx->injected  = 1;
562e1051a39Sopenharmony_ci    } else {
563e1051a39Sopenharmony_ci        ctx->noinject = 1;
564e1051a39Sopenharmony_ci    }
565e1051a39Sopenharmony_ci
566e1051a39Sopenharmony_ci    for (i = 0; i < (duprec ? 3 : 1); i++) {
567e1051a39Sopenharmony_ci        if (!TEST_ptr(allpkts[i] = OPENSSL_malloc(sizeof(*thispkt))))
568e1051a39Sopenharmony_ci            goto err;
569e1051a39Sopenharmony_ci        thispkt = allpkts[i];
570e1051a39Sopenharmony_ci
571e1051a39Sopenharmony_ci        if (!TEST_ptr(thispkt->data = OPENSSL_malloc(inl)))
572e1051a39Sopenharmony_ci            goto err;
573e1051a39Sopenharmony_ci        /*
574e1051a39Sopenharmony_ci         * If we are duplicating the packet, we duplicate it three times. The
575e1051a39Sopenharmony_ci         * first two times we drop the first record if there are more than one.
576e1051a39Sopenharmony_ci         * In this way we know that libssl will not be able to make progress
577e1051a39Sopenharmony_ci         * until it receives the last packet, and hence will be forced to
578e1051a39Sopenharmony_ci         * buffer these records.
579e1051a39Sopenharmony_ci         */
580e1051a39Sopenharmony_ci        if (duprec && i != 2) {
581e1051a39Sopenharmony_ci            memcpy(thispkt->data, in + len, inl - len);
582e1051a39Sopenharmony_ci            thispkt->len = inl - len;
583e1051a39Sopenharmony_ci        } else {
584e1051a39Sopenharmony_ci            memcpy(thispkt->data, in, inl);
585e1051a39Sopenharmony_ci            thispkt->len = inl;
586e1051a39Sopenharmony_ci        }
587e1051a39Sopenharmony_ci        thispkt->num = (pktnum >= 0) ? (unsigned int)pktnum : ctx->lastpkt + i;
588e1051a39Sopenharmony_ci        thispkt->type = type;
589e1051a39Sopenharmony_ci    }
590e1051a39Sopenharmony_ci
591e1051a39Sopenharmony_ci    for (i = 0; i < sk_MEMPACKET_num(ctx->pkts); i++) {
592e1051a39Sopenharmony_ci        if (!TEST_ptr(looppkt = sk_MEMPACKET_value(ctx->pkts, i)))
593e1051a39Sopenharmony_ci            goto err;
594e1051a39Sopenharmony_ci        /* Check if we found the right place to insert this packet */
595e1051a39Sopenharmony_ci        if (looppkt->num > thispkt->num) {
596e1051a39Sopenharmony_ci            if (sk_MEMPACKET_insert(ctx->pkts, thispkt, i) == 0)
597e1051a39Sopenharmony_ci                goto err;
598e1051a39Sopenharmony_ci            /* If we're doing up front injection then we're done */
599e1051a39Sopenharmony_ci            if (pktnum >= 0)
600e1051a39Sopenharmony_ci                return inl;
601e1051a39Sopenharmony_ci            /*
602e1051a39Sopenharmony_ci             * We need to do some accounting on lastpkt. We increment it first,
603e1051a39Sopenharmony_ci             * but it might now equal the value of injected packets, so we need
604e1051a39Sopenharmony_ci             * to skip over those
605e1051a39Sopenharmony_ci             */
606e1051a39Sopenharmony_ci            ctx->lastpkt++;
607e1051a39Sopenharmony_ci            do {
608e1051a39Sopenharmony_ci                i++;
609e1051a39Sopenharmony_ci                nextpkt = sk_MEMPACKET_value(ctx->pkts, i);
610e1051a39Sopenharmony_ci                if (nextpkt != NULL && nextpkt->num == ctx->lastpkt)
611e1051a39Sopenharmony_ci                    ctx->lastpkt++;
612e1051a39Sopenharmony_ci                else
613e1051a39Sopenharmony_ci                    return inl;
614e1051a39Sopenharmony_ci            } while(1);
615e1051a39Sopenharmony_ci        } else if (looppkt->num == thispkt->num) {
616e1051a39Sopenharmony_ci            if (!ctx->noinject) {
617e1051a39Sopenharmony_ci                /* We injected two packets with the same packet number! */
618e1051a39Sopenharmony_ci                goto err;
619e1051a39Sopenharmony_ci            }
620e1051a39Sopenharmony_ci            ctx->lastpkt++;
621e1051a39Sopenharmony_ci            thispkt->num++;
622e1051a39Sopenharmony_ci        }
623e1051a39Sopenharmony_ci    }
624e1051a39Sopenharmony_ci    /*
625e1051a39Sopenharmony_ci     * We didn't find any packets with a packet number equal to or greater than
626e1051a39Sopenharmony_ci     * this one, so we just add it onto the end
627e1051a39Sopenharmony_ci     */
628e1051a39Sopenharmony_ci    for (i = 0; i < (duprec ? 3 : 1); i++) {
629e1051a39Sopenharmony_ci        thispkt = allpkts[i];
630e1051a39Sopenharmony_ci        if (!sk_MEMPACKET_push(ctx->pkts, thispkt))
631e1051a39Sopenharmony_ci            goto err;
632e1051a39Sopenharmony_ci
633e1051a39Sopenharmony_ci        if (pktnum < 0)
634e1051a39Sopenharmony_ci            ctx->lastpkt++;
635e1051a39Sopenharmony_ci    }
636e1051a39Sopenharmony_ci
637e1051a39Sopenharmony_ci    return inl;
638e1051a39Sopenharmony_ci
639e1051a39Sopenharmony_ci err:
640e1051a39Sopenharmony_ci    for (i = 0; i < (ctx->duprec > 0 ? 3 : 1); i++)
641e1051a39Sopenharmony_ci        mempacket_free(allpkts[i]);
642e1051a39Sopenharmony_ci    return -1;
643e1051a39Sopenharmony_ci}
644e1051a39Sopenharmony_ci
645e1051a39Sopenharmony_cistatic int mempacket_test_write(BIO *bio, const char *in, int inl)
646e1051a39Sopenharmony_ci{
647e1051a39Sopenharmony_ci    return mempacket_test_inject(bio, in, inl, -1, STANDARD_PACKET);
648e1051a39Sopenharmony_ci}
649e1051a39Sopenharmony_ci
650e1051a39Sopenharmony_cistatic long mempacket_test_ctrl(BIO *bio, int cmd, long num, void *ptr)
651e1051a39Sopenharmony_ci{
652e1051a39Sopenharmony_ci    long ret = 1;
653e1051a39Sopenharmony_ci    MEMPACKET_TEST_CTX *ctx = BIO_get_data(bio);
654e1051a39Sopenharmony_ci    MEMPACKET *thispkt;
655e1051a39Sopenharmony_ci
656e1051a39Sopenharmony_ci    switch (cmd) {
657e1051a39Sopenharmony_ci    case BIO_CTRL_EOF:
658e1051a39Sopenharmony_ci        ret = (long)(sk_MEMPACKET_num(ctx->pkts) == 0);
659e1051a39Sopenharmony_ci        break;
660e1051a39Sopenharmony_ci    case BIO_CTRL_GET_CLOSE:
661e1051a39Sopenharmony_ci        ret = BIO_get_shutdown(bio);
662e1051a39Sopenharmony_ci        break;
663e1051a39Sopenharmony_ci    case BIO_CTRL_SET_CLOSE:
664e1051a39Sopenharmony_ci        BIO_set_shutdown(bio, (int)num);
665e1051a39Sopenharmony_ci        break;
666e1051a39Sopenharmony_ci    case BIO_CTRL_WPENDING:
667e1051a39Sopenharmony_ci        ret = 0L;
668e1051a39Sopenharmony_ci        break;
669e1051a39Sopenharmony_ci    case BIO_CTRL_PENDING:
670e1051a39Sopenharmony_ci        thispkt = sk_MEMPACKET_value(ctx->pkts, 0);
671e1051a39Sopenharmony_ci        if (thispkt == NULL)
672e1051a39Sopenharmony_ci            ret = 0;
673e1051a39Sopenharmony_ci        else
674e1051a39Sopenharmony_ci            ret = thispkt->len;
675e1051a39Sopenharmony_ci        break;
676e1051a39Sopenharmony_ci    case BIO_CTRL_FLUSH:
677e1051a39Sopenharmony_ci        ret = 1;
678e1051a39Sopenharmony_ci        break;
679e1051a39Sopenharmony_ci    case MEMPACKET_CTRL_SET_DROP_EPOCH:
680e1051a39Sopenharmony_ci        ctx->dropepoch = (unsigned int)num;
681e1051a39Sopenharmony_ci        break;
682e1051a39Sopenharmony_ci    case MEMPACKET_CTRL_SET_DROP_REC:
683e1051a39Sopenharmony_ci        ctx->droprec = (int)num;
684e1051a39Sopenharmony_ci        break;
685e1051a39Sopenharmony_ci    case MEMPACKET_CTRL_GET_DROP_REC:
686e1051a39Sopenharmony_ci        ret = ctx->droprec;
687e1051a39Sopenharmony_ci        break;
688e1051a39Sopenharmony_ci    case MEMPACKET_CTRL_SET_DUPLICATE_REC:
689e1051a39Sopenharmony_ci        ctx->duprec = (int)num;
690e1051a39Sopenharmony_ci        break;
691e1051a39Sopenharmony_ci    case BIO_CTRL_RESET:
692e1051a39Sopenharmony_ci    case BIO_CTRL_DUP:
693e1051a39Sopenharmony_ci    case BIO_CTRL_PUSH:
694e1051a39Sopenharmony_ci    case BIO_CTRL_POP:
695e1051a39Sopenharmony_ci    default:
696e1051a39Sopenharmony_ci        ret = 0;
697e1051a39Sopenharmony_ci        break;
698e1051a39Sopenharmony_ci    }
699e1051a39Sopenharmony_ci    return ret;
700e1051a39Sopenharmony_ci}
701e1051a39Sopenharmony_ci
702e1051a39Sopenharmony_cistatic int mempacket_test_gets(BIO *bio, char *buf, int size)
703e1051a39Sopenharmony_ci{
704e1051a39Sopenharmony_ci    /* We don't support this - not needed anyway */
705e1051a39Sopenharmony_ci    return -1;
706e1051a39Sopenharmony_ci}
707e1051a39Sopenharmony_ci
708e1051a39Sopenharmony_cistatic int mempacket_test_puts(BIO *bio, const char *str)
709e1051a39Sopenharmony_ci{
710e1051a39Sopenharmony_ci    return mempacket_test_write(bio, str, strlen(str));
711e1051a39Sopenharmony_ci}
712e1051a39Sopenharmony_ci
713e1051a39Sopenharmony_cistatic int always_retry_new(BIO *bi);
714e1051a39Sopenharmony_cistatic int always_retry_free(BIO *a);
715e1051a39Sopenharmony_cistatic int always_retry_read(BIO *b, char *out, int outl);
716e1051a39Sopenharmony_cistatic int always_retry_write(BIO *b, const char *in, int inl);
717e1051a39Sopenharmony_cistatic long always_retry_ctrl(BIO *b, int cmd, long num, void *ptr);
718e1051a39Sopenharmony_cistatic int always_retry_gets(BIO *bp, char *buf, int size);
719e1051a39Sopenharmony_cistatic int always_retry_puts(BIO *bp, const char *str);
720e1051a39Sopenharmony_ci
721e1051a39Sopenharmony_ciconst BIO_METHOD *bio_s_always_retry(void)
722e1051a39Sopenharmony_ci{
723e1051a39Sopenharmony_ci    if (meth_always_retry == NULL) {
724e1051a39Sopenharmony_ci        if (!TEST_ptr(meth_always_retry = BIO_meth_new(BIO_TYPE_ALWAYS_RETRY,
725e1051a39Sopenharmony_ci                                                       "Always Retry"))
726e1051a39Sopenharmony_ci            || !TEST_true(BIO_meth_set_write(meth_always_retry,
727e1051a39Sopenharmony_ci                                             always_retry_write))
728e1051a39Sopenharmony_ci            || !TEST_true(BIO_meth_set_read(meth_always_retry,
729e1051a39Sopenharmony_ci                                            always_retry_read))
730e1051a39Sopenharmony_ci            || !TEST_true(BIO_meth_set_puts(meth_always_retry,
731e1051a39Sopenharmony_ci                                            always_retry_puts))
732e1051a39Sopenharmony_ci            || !TEST_true(BIO_meth_set_gets(meth_always_retry,
733e1051a39Sopenharmony_ci                                            always_retry_gets))
734e1051a39Sopenharmony_ci            || !TEST_true(BIO_meth_set_ctrl(meth_always_retry,
735e1051a39Sopenharmony_ci                                            always_retry_ctrl))
736e1051a39Sopenharmony_ci            || !TEST_true(BIO_meth_set_create(meth_always_retry,
737e1051a39Sopenharmony_ci                                              always_retry_new))
738e1051a39Sopenharmony_ci            || !TEST_true(BIO_meth_set_destroy(meth_always_retry,
739e1051a39Sopenharmony_ci                                               always_retry_free)))
740e1051a39Sopenharmony_ci            return NULL;
741e1051a39Sopenharmony_ci    }
742e1051a39Sopenharmony_ci    return meth_always_retry;
743e1051a39Sopenharmony_ci}
744e1051a39Sopenharmony_ci
745e1051a39Sopenharmony_civoid bio_s_always_retry_free(void)
746e1051a39Sopenharmony_ci{
747e1051a39Sopenharmony_ci    BIO_meth_free(meth_always_retry);
748e1051a39Sopenharmony_ci}
749e1051a39Sopenharmony_ci
750e1051a39Sopenharmony_cistatic int always_retry_new(BIO *bio)
751e1051a39Sopenharmony_ci{
752e1051a39Sopenharmony_ci    BIO_set_init(bio, 1);
753e1051a39Sopenharmony_ci    return 1;
754e1051a39Sopenharmony_ci}
755e1051a39Sopenharmony_ci
756e1051a39Sopenharmony_cistatic int always_retry_free(BIO *bio)
757e1051a39Sopenharmony_ci{
758e1051a39Sopenharmony_ci    BIO_set_data(bio, NULL);
759e1051a39Sopenharmony_ci    BIO_set_init(bio, 0);
760e1051a39Sopenharmony_ci    return 1;
761e1051a39Sopenharmony_ci}
762e1051a39Sopenharmony_ci
763e1051a39Sopenharmony_cistatic int always_retry_read(BIO *bio, char *out, int outl)
764e1051a39Sopenharmony_ci{
765e1051a39Sopenharmony_ci    BIO_set_retry_read(bio);
766e1051a39Sopenharmony_ci    return -1;
767e1051a39Sopenharmony_ci}
768e1051a39Sopenharmony_ci
769e1051a39Sopenharmony_cistatic int always_retry_write(BIO *bio, const char *in, int inl)
770e1051a39Sopenharmony_ci{
771e1051a39Sopenharmony_ci    BIO_set_retry_write(bio);
772e1051a39Sopenharmony_ci    return -1;
773e1051a39Sopenharmony_ci}
774e1051a39Sopenharmony_ci
775e1051a39Sopenharmony_cistatic long always_retry_ctrl(BIO *bio, int cmd, long num, void *ptr)
776e1051a39Sopenharmony_ci{
777e1051a39Sopenharmony_ci    long ret = 1;
778e1051a39Sopenharmony_ci
779e1051a39Sopenharmony_ci    switch (cmd) {
780e1051a39Sopenharmony_ci    case BIO_CTRL_FLUSH:
781e1051a39Sopenharmony_ci        BIO_set_retry_write(bio);
782e1051a39Sopenharmony_ci        /* fall through */
783e1051a39Sopenharmony_ci    case BIO_CTRL_EOF:
784e1051a39Sopenharmony_ci    case BIO_CTRL_RESET:
785e1051a39Sopenharmony_ci    case BIO_CTRL_DUP:
786e1051a39Sopenharmony_ci    case BIO_CTRL_PUSH:
787e1051a39Sopenharmony_ci    case BIO_CTRL_POP:
788e1051a39Sopenharmony_ci    default:
789e1051a39Sopenharmony_ci        ret = 0;
790e1051a39Sopenharmony_ci        break;
791e1051a39Sopenharmony_ci    }
792e1051a39Sopenharmony_ci    return ret;
793e1051a39Sopenharmony_ci}
794e1051a39Sopenharmony_ci
795e1051a39Sopenharmony_cistatic int always_retry_gets(BIO *bio, char *buf, int size)
796e1051a39Sopenharmony_ci{
797e1051a39Sopenharmony_ci    BIO_set_retry_read(bio);
798e1051a39Sopenharmony_ci    return -1;
799e1051a39Sopenharmony_ci}
800e1051a39Sopenharmony_ci
801e1051a39Sopenharmony_cistatic int always_retry_puts(BIO *bio, const char *str)
802e1051a39Sopenharmony_ci{
803e1051a39Sopenharmony_ci    BIO_set_retry_write(bio);
804e1051a39Sopenharmony_ci    return -1;
805e1051a39Sopenharmony_ci}
806e1051a39Sopenharmony_ci
807e1051a39Sopenharmony_ciint create_ssl_ctx_pair(OSSL_LIB_CTX *libctx, const SSL_METHOD *sm,
808e1051a39Sopenharmony_ci                        const SSL_METHOD *cm, int min_proto_version,
809e1051a39Sopenharmony_ci                        int max_proto_version, SSL_CTX **sctx, SSL_CTX **cctx,
810e1051a39Sopenharmony_ci                        char *certfile, char *privkeyfile)
811e1051a39Sopenharmony_ci{
812e1051a39Sopenharmony_ci    SSL_CTX *serverctx = NULL;
813e1051a39Sopenharmony_ci    SSL_CTX *clientctx = NULL;
814e1051a39Sopenharmony_ci
815e1051a39Sopenharmony_ci    if (sctx != NULL) {
816e1051a39Sopenharmony_ci        if (*sctx != NULL)
817e1051a39Sopenharmony_ci            serverctx = *sctx;
818e1051a39Sopenharmony_ci        else if (!TEST_ptr(serverctx = SSL_CTX_new_ex(libctx, NULL, sm))
819e1051a39Sopenharmony_ci            || !TEST_true(SSL_CTX_set_options(serverctx,
820e1051a39Sopenharmony_ci                                              SSL_OP_ALLOW_CLIENT_RENEGOTIATION)))
821e1051a39Sopenharmony_ci            goto err;
822e1051a39Sopenharmony_ci    }
823e1051a39Sopenharmony_ci
824e1051a39Sopenharmony_ci    if (cctx != NULL) {
825e1051a39Sopenharmony_ci        if (*cctx != NULL)
826e1051a39Sopenharmony_ci            clientctx = *cctx;
827e1051a39Sopenharmony_ci        else if (!TEST_ptr(clientctx = SSL_CTX_new_ex(libctx, NULL, cm)))
828e1051a39Sopenharmony_ci            goto err;
829e1051a39Sopenharmony_ci    }
830e1051a39Sopenharmony_ci
831e1051a39Sopenharmony_ci#if !defined(OPENSSL_NO_TLS1_3) \
832e1051a39Sopenharmony_ci    && defined(OPENSSL_NO_EC) \
833e1051a39Sopenharmony_ci    && defined(OPENSSL_NO_DH)
834e1051a39Sopenharmony_ci    /*
835e1051a39Sopenharmony_ci     * There are no usable built-in TLSv1.3 groups if ec and dh are both
836e1051a39Sopenharmony_ci     * disabled
837e1051a39Sopenharmony_ci     */
838e1051a39Sopenharmony_ci    if (max_proto_version == 0
839e1051a39Sopenharmony_ci            && (sm == TLS_server_method() || cm == TLS_client_method()))
840e1051a39Sopenharmony_ci        max_proto_version = TLS1_2_VERSION;
841e1051a39Sopenharmony_ci#endif
842e1051a39Sopenharmony_ci
843e1051a39Sopenharmony_ci    if (serverctx != NULL
844e1051a39Sopenharmony_ci            && ((min_proto_version > 0
845e1051a39Sopenharmony_ci                 && !TEST_true(SSL_CTX_set_min_proto_version(serverctx,
846e1051a39Sopenharmony_ci                                                            min_proto_version)))
847e1051a39Sopenharmony_ci                || (max_proto_version > 0
848e1051a39Sopenharmony_ci                    && !TEST_true(SSL_CTX_set_max_proto_version(serverctx,
849e1051a39Sopenharmony_ci                                                                max_proto_version)))))
850e1051a39Sopenharmony_ci        goto err;
851e1051a39Sopenharmony_ci    if (clientctx != NULL
852e1051a39Sopenharmony_ci        && ((min_proto_version > 0
853e1051a39Sopenharmony_ci             && !TEST_true(SSL_CTX_set_min_proto_version(clientctx,
854e1051a39Sopenharmony_ci                                                         min_proto_version)))
855e1051a39Sopenharmony_ci            || (max_proto_version > 0
856e1051a39Sopenharmony_ci                && !TEST_true(SSL_CTX_set_max_proto_version(clientctx,
857e1051a39Sopenharmony_ci                                                            max_proto_version)))))
858e1051a39Sopenharmony_ci        goto err;
859e1051a39Sopenharmony_ci
860e1051a39Sopenharmony_ci    if (serverctx != NULL && certfile != NULL && privkeyfile != NULL) {
861e1051a39Sopenharmony_ci        if (!TEST_int_eq(SSL_CTX_use_certificate_file(serverctx, certfile,
862e1051a39Sopenharmony_ci                                                      SSL_FILETYPE_PEM), 1)
863e1051a39Sopenharmony_ci                || !TEST_int_eq(SSL_CTX_use_PrivateKey_file(serverctx,
864e1051a39Sopenharmony_ci                                                            privkeyfile,
865e1051a39Sopenharmony_ci                                                            SSL_FILETYPE_PEM), 1)
866e1051a39Sopenharmony_ci                || !TEST_int_eq(SSL_CTX_check_private_key(serverctx), 1))
867e1051a39Sopenharmony_ci            goto err;
868e1051a39Sopenharmony_ci    }
869e1051a39Sopenharmony_ci
870e1051a39Sopenharmony_ci    if (sctx != NULL)
871e1051a39Sopenharmony_ci        *sctx = serverctx;
872e1051a39Sopenharmony_ci    if (cctx != NULL)
873e1051a39Sopenharmony_ci        *cctx = clientctx;
874e1051a39Sopenharmony_ci    return 1;
875e1051a39Sopenharmony_ci
876e1051a39Sopenharmony_ci err:
877e1051a39Sopenharmony_ci    if (sctx != NULL && *sctx == NULL)
878e1051a39Sopenharmony_ci        SSL_CTX_free(serverctx);
879e1051a39Sopenharmony_ci    if (cctx != NULL && *cctx == NULL)
880e1051a39Sopenharmony_ci        SSL_CTX_free(clientctx);
881e1051a39Sopenharmony_ci    return 0;
882e1051a39Sopenharmony_ci}
883e1051a39Sopenharmony_ci
884e1051a39Sopenharmony_ci#define MAXLOOPS    1000000
885e1051a39Sopenharmony_ci
886e1051a39Sopenharmony_ci#if !defined(OPENSSL_NO_KTLS) && !defined(OPENSSL_NO_SOCK)
887e1051a39Sopenharmony_cistatic int set_nb(int fd)
888e1051a39Sopenharmony_ci{
889e1051a39Sopenharmony_ci    int flags;
890e1051a39Sopenharmony_ci
891e1051a39Sopenharmony_ci    flags = fcntl(fd,F_GETFL,0);
892e1051a39Sopenharmony_ci    if (flags == -1)
893e1051a39Sopenharmony_ci        return flags;
894e1051a39Sopenharmony_ci    flags = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
895e1051a39Sopenharmony_ci    return flags;
896e1051a39Sopenharmony_ci}
897e1051a39Sopenharmony_ci
898e1051a39Sopenharmony_ciint create_test_sockets(int *cfdp, int *sfdp)
899e1051a39Sopenharmony_ci{
900e1051a39Sopenharmony_ci    struct sockaddr_in sin;
901e1051a39Sopenharmony_ci    const char *host = "127.0.0.1";
902e1051a39Sopenharmony_ci    int cfd_connected = 0, ret = 0;
903e1051a39Sopenharmony_ci    socklen_t slen = sizeof(sin);
904e1051a39Sopenharmony_ci    int afd = -1, cfd = -1, sfd = -1;
905e1051a39Sopenharmony_ci
906e1051a39Sopenharmony_ci    memset ((char *) &sin, 0, sizeof(sin));
907e1051a39Sopenharmony_ci    sin.sin_family = AF_INET;
908e1051a39Sopenharmony_ci    sin.sin_addr.s_addr = inet_addr(host);
909e1051a39Sopenharmony_ci
910e1051a39Sopenharmony_ci    afd = socket(AF_INET, SOCK_STREAM, 0);
911e1051a39Sopenharmony_ci    if (afd < 0)
912e1051a39Sopenharmony_ci        return 0;
913e1051a39Sopenharmony_ci
914e1051a39Sopenharmony_ci    if (bind(afd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
915e1051a39Sopenharmony_ci        goto out;
916e1051a39Sopenharmony_ci
917e1051a39Sopenharmony_ci    if (getsockname(afd, (struct sockaddr*)&sin, &slen) < 0)
918e1051a39Sopenharmony_ci        goto out;
919e1051a39Sopenharmony_ci
920e1051a39Sopenharmony_ci    if (listen(afd, 1) < 0)
921e1051a39Sopenharmony_ci        goto out;
922e1051a39Sopenharmony_ci
923e1051a39Sopenharmony_ci    cfd = socket(AF_INET, SOCK_STREAM, 0);
924e1051a39Sopenharmony_ci    if (cfd < 0)
925e1051a39Sopenharmony_ci        goto out;
926e1051a39Sopenharmony_ci
927e1051a39Sopenharmony_ci    if (set_nb(afd) == -1)
928e1051a39Sopenharmony_ci        goto out;
929e1051a39Sopenharmony_ci
930e1051a39Sopenharmony_ci    while (sfd == -1 || !cfd_connected ) {
931e1051a39Sopenharmony_ci        sfd = accept(afd, NULL, 0);
932e1051a39Sopenharmony_ci        if (sfd == -1 && errno != EAGAIN)
933e1051a39Sopenharmony_ci            goto out;
934e1051a39Sopenharmony_ci
935e1051a39Sopenharmony_ci        if (!cfd_connected && connect(cfd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
936e1051a39Sopenharmony_ci            goto out;
937e1051a39Sopenharmony_ci        else
938e1051a39Sopenharmony_ci            cfd_connected = 1;
939e1051a39Sopenharmony_ci    }
940e1051a39Sopenharmony_ci
941e1051a39Sopenharmony_ci    if (set_nb(cfd) == -1 || set_nb(sfd) == -1)
942e1051a39Sopenharmony_ci        goto out;
943e1051a39Sopenharmony_ci    ret = 1;
944e1051a39Sopenharmony_ci    *cfdp = cfd;
945e1051a39Sopenharmony_ci    *sfdp = sfd;
946e1051a39Sopenharmony_ci    goto success;
947e1051a39Sopenharmony_ci
948e1051a39Sopenharmony_ciout:
949e1051a39Sopenharmony_ci    if (cfd != -1)
950e1051a39Sopenharmony_ci        close(cfd);
951e1051a39Sopenharmony_ci    if (sfd != -1)
952e1051a39Sopenharmony_ci        close(sfd);
953e1051a39Sopenharmony_cisuccess:
954e1051a39Sopenharmony_ci    if (afd != -1)
955e1051a39Sopenharmony_ci        close(afd);
956e1051a39Sopenharmony_ci    return ret;
957e1051a39Sopenharmony_ci}
958e1051a39Sopenharmony_ci
959e1051a39Sopenharmony_ciint create_ssl_objects2(SSL_CTX *serverctx, SSL_CTX *clientctx, SSL **sssl,
960e1051a39Sopenharmony_ci                          SSL **cssl, int sfd, int cfd)
961e1051a39Sopenharmony_ci{
962e1051a39Sopenharmony_ci    SSL *serverssl = NULL, *clientssl = NULL;
963e1051a39Sopenharmony_ci    BIO *s_to_c_bio = NULL, *c_to_s_bio = NULL;
964e1051a39Sopenharmony_ci
965e1051a39Sopenharmony_ci    if (*sssl != NULL)
966e1051a39Sopenharmony_ci        serverssl = *sssl;
967e1051a39Sopenharmony_ci    else if (!TEST_ptr(serverssl = SSL_new(serverctx)))
968e1051a39Sopenharmony_ci        goto error;
969e1051a39Sopenharmony_ci    if (*cssl != NULL)
970e1051a39Sopenharmony_ci        clientssl = *cssl;
971e1051a39Sopenharmony_ci    else if (!TEST_ptr(clientssl = SSL_new(clientctx)))
972e1051a39Sopenharmony_ci        goto error;
973e1051a39Sopenharmony_ci
974e1051a39Sopenharmony_ci    if (!TEST_ptr(s_to_c_bio = BIO_new_socket(sfd, BIO_NOCLOSE))
975e1051a39Sopenharmony_ci            || !TEST_ptr(c_to_s_bio = BIO_new_socket(cfd, BIO_NOCLOSE)))
976e1051a39Sopenharmony_ci        goto error;
977e1051a39Sopenharmony_ci
978e1051a39Sopenharmony_ci    SSL_set_bio(clientssl, c_to_s_bio, c_to_s_bio);
979e1051a39Sopenharmony_ci    SSL_set_bio(serverssl, s_to_c_bio, s_to_c_bio);
980e1051a39Sopenharmony_ci    *sssl = serverssl;
981e1051a39Sopenharmony_ci    *cssl = clientssl;
982e1051a39Sopenharmony_ci    return 1;
983e1051a39Sopenharmony_ci
984e1051a39Sopenharmony_ci error:
985e1051a39Sopenharmony_ci    SSL_free(serverssl);
986e1051a39Sopenharmony_ci    SSL_free(clientssl);
987e1051a39Sopenharmony_ci    BIO_free(s_to_c_bio);
988e1051a39Sopenharmony_ci    BIO_free(c_to_s_bio);
989e1051a39Sopenharmony_ci    return 0;
990e1051a39Sopenharmony_ci}
991e1051a39Sopenharmony_ci#endif
992e1051a39Sopenharmony_ci
993e1051a39Sopenharmony_ci/*
994e1051a39Sopenharmony_ci * NOTE: Transfers control of the BIOs - this function will free them on error
995e1051a39Sopenharmony_ci */
996e1051a39Sopenharmony_ciint create_ssl_objects(SSL_CTX *serverctx, SSL_CTX *clientctx, SSL **sssl,
997e1051a39Sopenharmony_ci                          SSL **cssl, BIO *s_to_c_fbio, BIO *c_to_s_fbio)
998e1051a39Sopenharmony_ci{
999e1051a39Sopenharmony_ci    SSL *serverssl = NULL, *clientssl = NULL;
1000e1051a39Sopenharmony_ci    BIO *s_to_c_bio = NULL, *c_to_s_bio = NULL;
1001e1051a39Sopenharmony_ci
1002e1051a39Sopenharmony_ci    if (*sssl != NULL)
1003e1051a39Sopenharmony_ci        serverssl = *sssl;
1004e1051a39Sopenharmony_ci    else if (!TEST_ptr(serverssl = SSL_new(serverctx)))
1005e1051a39Sopenharmony_ci        goto error;
1006e1051a39Sopenharmony_ci    if (*cssl != NULL)
1007e1051a39Sopenharmony_ci        clientssl = *cssl;
1008e1051a39Sopenharmony_ci    else if (!TEST_ptr(clientssl = SSL_new(clientctx)))
1009e1051a39Sopenharmony_ci        goto error;
1010e1051a39Sopenharmony_ci
1011e1051a39Sopenharmony_ci    if (SSL_is_dtls(clientssl)) {
1012e1051a39Sopenharmony_ci        if (!TEST_ptr(s_to_c_bio = BIO_new(bio_s_mempacket_test()))
1013e1051a39Sopenharmony_ci                || !TEST_ptr(c_to_s_bio = BIO_new(bio_s_mempacket_test())))
1014e1051a39Sopenharmony_ci            goto error;
1015e1051a39Sopenharmony_ci    } else {
1016e1051a39Sopenharmony_ci        if (!TEST_ptr(s_to_c_bio = BIO_new(BIO_s_mem()))
1017e1051a39Sopenharmony_ci                || !TEST_ptr(c_to_s_bio = BIO_new(BIO_s_mem())))
1018e1051a39Sopenharmony_ci            goto error;
1019e1051a39Sopenharmony_ci    }
1020e1051a39Sopenharmony_ci
1021e1051a39Sopenharmony_ci    if (s_to_c_fbio != NULL
1022e1051a39Sopenharmony_ci            && !TEST_ptr(s_to_c_bio = BIO_push(s_to_c_fbio, s_to_c_bio)))
1023e1051a39Sopenharmony_ci        goto error;
1024e1051a39Sopenharmony_ci    if (c_to_s_fbio != NULL
1025e1051a39Sopenharmony_ci            && !TEST_ptr(c_to_s_bio = BIO_push(c_to_s_fbio, c_to_s_bio)))
1026e1051a39Sopenharmony_ci        goto error;
1027e1051a39Sopenharmony_ci
1028e1051a39Sopenharmony_ci    /* Set Non-blocking IO behaviour */
1029e1051a39Sopenharmony_ci    BIO_set_mem_eof_return(s_to_c_bio, -1);
1030e1051a39Sopenharmony_ci    BIO_set_mem_eof_return(c_to_s_bio, -1);
1031e1051a39Sopenharmony_ci
1032e1051a39Sopenharmony_ci    /* Up ref these as we are passing them to two SSL objects */
1033e1051a39Sopenharmony_ci    SSL_set_bio(serverssl, c_to_s_bio, s_to_c_bio);
1034e1051a39Sopenharmony_ci    BIO_up_ref(s_to_c_bio);
1035e1051a39Sopenharmony_ci    BIO_up_ref(c_to_s_bio);
1036e1051a39Sopenharmony_ci    SSL_set_bio(clientssl, s_to_c_bio, c_to_s_bio);
1037e1051a39Sopenharmony_ci    *sssl = serverssl;
1038e1051a39Sopenharmony_ci    *cssl = clientssl;
1039e1051a39Sopenharmony_ci    return 1;
1040e1051a39Sopenharmony_ci
1041e1051a39Sopenharmony_ci error:
1042e1051a39Sopenharmony_ci    SSL_free(serverssl);
1043e1051a39Sopenharmony_ci    SSL_free(clientssl);
1044e1051a39Sopenharmony_ci    BIO_free(s_to_c_bio);
1045e1051a39Sopenharmony_ci    BIO_free(c_to_s_bio);
1046e1051a39Sopenharmony_ci    BIO_free(s_to_c_fbio);
1047e1051a39Sopenharmony_ci    BIO_free(c_to_s_fbio);
1048e1051a39Sopenharmony_ci
1049e1051a39Sopenharmony_ci    return 0;
1050e1051a39Sopenharmony_ci}
1051e1051a39Sopenharmony_ci
1052e1051a39Sopenharmony_ci/*
1053e1051a39Sopenharmony_ci * Create an SSL connection, but does not read any post-handshake
1054e1051a39Sopenharmony_ci * NewSessionTicket messages.
1055e1051a39Sopenharmony_ci * If |read| is set and we're using DTLS then we will attempt to SSL_read on
1056e1051a39Sopenharmony_ci * the connection once we've completed one half of it, to ensure any retransmits
1057e1051a39Sopenharmony_ci * get triggered.
1058e1051a39Sopenharmony_ci * We stop the connection attempt (and return a failure value) if either peer
1059e1051a39Sopenharmony_ci * has SSL_get_error() return the value in the |want| parameter. The connection
1060e1051a39Sopenharmony_ci * attempt could be restarted by a subsequent call to this function.
1061e1051a39Sopenharmony_ci */
1062e1051a39Sopenharmony_ciint create_bare_ssl_connection(SSL *serverssl, SSL *clientssl, int want,
1063e1051a39Sopenharmony_ci                               int read)
1064e1051a39Sopenharmony_ci{
1065e1051a39Sopenharmony_ci    int retc = -1, rets = -1, err, abortctr = 0;
1066e1051a39Sopenharmony_ci    int clienterr = 0, servererr = 0;
1067e1051a39Sopenharmony_ci    int isdtls = SSL_is_dtls(serverssl);
1068e1051a39Sopenharmony_ci
1069e1051a39Sopenharmony_ci    do {
1070e1051a39Sopenharmony_ci        err = SSL_ERROR_WANT_WRITE;
1071e1051a39Sopenharmony_ci        while (!clienterr && retc <= 0 && err == SSL_ERROR_WANT_WRITE) {
1072e1051a39Sopenharmony_ci            retc = SSL_connect(clientssl);
1073e1051a39Sopenharmony_ci            if (retc <= 0)
1074e1051a39Sopenharmony_ci                err = SSL_get_error(clientssl, retc);
1075e1051a39Sopenharmony_ci        }
1076e1051a39Sopenharmony_ci
1077e1051a39Sopenharmony_ci        if (!clienterr && retc <= 0 && err != SSL_ERROR_WANT_READ) {
1078e1051a39Sopenharmony_ci            TEST_info("SSL_connect() failed %d, %d", retc, err);
1079e1051a39Sopenharmony_ci            if (want != SSL_ERROR_SSL)
1080e1051a39Sopenharmony_ci                TEST_openssl_errors();
1081e1051a39Sopenharmony_ci            clienterr = 1;
1082e1051a39Sopenharmony_ci        }
1083e1051a39Sopenharmony_ci        if (want != SSL_ERROR_NONE && err == want)
1084e1051a39Sopenharmony_ci            return 0;
1085e1051a39Sopenharmony_ci
1086e1051a39Sopenharmony_ci        err = SSL_ERROR_WANT_WRITE;
1087e1051a39Sopenharmony_ci        while (!servererr && rets <= 0 && err == SSL_ERROR_WANT_WRITE) {
1088e1051a39Sopenharmony_ci            rets = SSL_accept(serverssl);
1089e1051a39Sopenharmony_ci            if (rets <= 0)
1090e1051a39Sopenharmony_ci                err = SSL_get_error(serverssl, rets);
1091e1051a39Sopenharmony_ci        }
1092e1051a39Sopenharmony_ci
1093e1051a39Sopenharmony_ci        if (!servererr && rets <= 0
1094e1051a39Sopenharmony_ci                && err != SSL_ERROR_WANT_READ
1095e1051a39Sopenharmony_ci                && err != SSL_ERROR_WANT_X509_LOOKUP) {
1096e1051a39Sopenharmony_ci            TEST_info("SSL_accept() failed %d, %d", rets, err);
1097e1051a39Sopenharmony_ci            if (want != SSL_ERROR_SSL)
1098e1051a39Sopenharmony_ci                TEST_openssl_errors();
1099e1051a39Sopenharmony_ci            servererr = 1;
1100e1051a39Sopenharmony_ci        }
1101e1051a39Sopenharmony_ci        if (want != SSL_ERROR_NONE && err == want)
1102e1051a39Sopenharmony_ci            return 0;
1103e1051a39Sopenharmony_ci        if (clienterr && servererr)
1104e1051a39Sopenharmony_ci            return 0;
1105e1051a39Sopenharmony_ci        if (isdtls && read) {
1106e1051a39Sopenharmony_ci            unsigned char buf[20];
1107e1051a39Sopenharmony_ci
1108e1051a39Sopenharmony_ci            /* Trigger any retransmits that may be appropriate */
1109e1051a39Sopenharmony_ci            if (rets > 0 && retc <= 0) {
1110e1051a39Sopenharmony_ci                if (SSL_read(serverssl, buf, sizeof(buf)) > 0) {
1111e1051a39Sopenharmony_ci                    /* We don't expect this to succeed! */
1112e1051a39Sopenharmony_ci                    TEST_info("Unexpected SSL_read() success!");
1113e1051a39Sopenharmony_ci                    return 0;
1114e1051a39Sopenharmony_ci                }
1115e1051a39Sopenharmony_ci            }
1116e1051a39Sopenharmony_ci            if (retc > 0 && rets <= 0) {
1117e1051a39Sopenharmony_ci                if (SSL_read(clientssl, buf, sizeof(buf)) > 0) {
1118e1051a39Sopenharmony_ci                    /* We don't expect this to succeed! */
1119e1051a39Sopenharmony_ci                    TEST_info("Unexpected SSL_read() success!");
1120e1051a39Sopenharmony_ci                    return 0;
1121e1051a39Sopenharmony_ci                }
1122e1051a39Sopenharmony_ci            }
1123e1051a39Sopenharmony_ci        }
1124e1051a39Sopenharmony_ci        if (++abortctr == MAXLOOPS) {
1125e1051a39Sopenharmony_ci            TEST_info("No progress made");
1126e1051a39Sopenharmony_ci            return 0;
1127e1051a39Sopenharmony_ci        }
1128e1051a39Sopenharmony_ci        if (isdtls && abortctr <= 50 && (abortctr % 10) == 0) {
1129e1051a39Sopenharmony_ci            /*
1130e1051a39Sopenharmony_ci             * It looks like we're just spinning. Pause for a short period to
1131e1051a39Sopenharmony_ci             * give the DTLS timer a chance to do something. We only do this for
1132e1051a39Sopenharmony_ci             * the first few times to prevent hangs.
1133e1051a39Sopenharmony_ci             */
1134e1051a39Sopenharmony_ci            ossl_sleep(50);
1135e1051a39Sopenharmony_ci        }
1136e1051a39Sopenharmony_ci    } while (retc <=0 || rets <= 0);
1137e1051a39Sopenharmony_ci
1138e1051a39Sopenharmony_ci    return 1;
1139e1051a39Sopenharmony_ci}
1140e1051a39Sopenharmony_ci
1141e1051a39Sopenharmony_ci/*
1142e1051a39Sopenharmony_ci * Create an SSL connection including any post handshake NewSessionTicket
1143e1051a39Sopenharmony_ci * messages.
1144e1051a39Sopenharmony_ci */
1145e1051a39Sopenharmony_ciint create_ssl_connection(SSL *serverssl, SSL *clientssl, int want)
1146e1051a39Sopenharmony_ci{
1147e1051a39Sopenharmony_ci    int i;
1148e1051a39Sopenharmony_ci    unsigned char buf;
1149e1051a39Sopenharmony_ci    size_t readbytes;
1150e1051a39Sopenharmony_ci
1151e1051a39Sopenharmony_ci    if (!create_bare_ssl_connection(serverssl, clientssl, want, 1))
1152e1051a39Sopenharmony_ci        return 0;
1153e1051a39Sopenharmony_ci
1154e1051a39Sopenharmony_ci    /*
1155e1051a39Sopenharmony_ci     * We attempt to read some data on the client side which we expect to fail.
1156e1051a39Sopenharmony_ci     * This will ensure we have received the NewSessionTicket in TLSv1.3 where
1157e1051a39Sopenharmony_ci     * appropriate. We do this twice because there are 2 NewSessionTickets.
1158e1051a39Sopenharmony_ci     */
1159e1051a39Sopenharmony_ci    for (i = 0; i < 2; i++) {
1160e1051a39Sopenharmony_ci        if (SSL_read_ex(clientssl, &buf, sizeof(buf), &readbytes) > 0) {
1161e1051a39Sopenharmony_ci            if (!TEST_ulong_eq(readbytes, 0))
1162e1051a39Sopenharmony_ci                return 0;
1163e1051a39Sopenharmony_ci        } else if (!TEST_int_eq(SSL_get_error(clientssl, 0),
1164e1051a39Sopenharmony_ci                                SSL_ERROR_WANT_READ)) {
1165e1051a39Sopenharmony_ci            return 0;
1166e1051a39Sopenharmony_ci        }
1167e1051a39Sopenharmony_ci    }
1168e1051a39Sopenharmony_ci
1169e1051a39Sopenharmony_ci    return 1;
1170e1051a39Sopenharmony_ci}
1171e1051a39Sopenharmony_ci
1172e1051a39Sopenharmony_civoid shutdown_ssl_connection(SSL *serverssl, SSL *clientssl)
1173e1051a39Sopenharmony_ci{
1174e1051a39Sopenharmony_ci    SSL_shutdown(clientssl);
1175e1051a39Sopenharmony_ci    SSL_shutdown(serverssl);
1176e1051a39Sopenharmony_ci    SSL_free(serverssl);
1177e1051a39Sopenharmony_ci    SSL_free(clientssl);
1178e1051a39Sopenharmony_ci}
1179