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