1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1995-2021 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 <stdio.h> 11e1051a39Sopenharmony_ci#include <errno.h> 12e1051a39Sopenharmony_ci#include "bio_local.h" 13e1051a39Sopenharmony_ci#include "internal/cryptlib.h" 14e1051a39Sopenharmony_ci#include "internal/ktls.h" 15e1051a39Sopenharmony_ci 16e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_SOCK 17e1051a39Sopenharmony_ci 18e1051a39Sopenharmony_ci# include <openssl/bio.h> 19e1051a39Sopenharmony_ci 20e1051a39Sopenharmony_ci# ifdef WATT32 21e1051a39Sopenharmony_ci/* Watt-32 uses same names */ 22e1051a39Sopenharmony_ci# undef sock_write 23e1051a39Sopenharmony_ci# undef sock_read 24e1051a39Sopenharmony_ci# undef sock_puts 25e1051a39Sopenharmony_ci# define sock_write SockWrite 26e1051a39Sopenharmony_ci# define sock_read SockRead 27e1051a39Sopenharmony_ci# define sock_puts SockPuts 28e1051a39Sopenharmony_ci# endif 29e1051a39Sopenharmony_ci 30e1051a39Sopenharmony_cistatic int sock_write(BIO *h, const char *buf, int num); 31e1051a39Sopenharmony_cistatic int sock_read(BIO *h, char *buf, int size); 32e1051a39Sopenharmony_cistatic int sock_puts(BIO *h, const char *str); 33e1051a39Sopenharmony_cistatic long sock_ctrl(BIO *h, int cmd, long arg1, void *arg2); 34e1051a39Sopenharmony_cistatic int sock_new(BIO *h); 35e1051a39Sopenharmony_cistatic int sock_free(BIO *data); 36e1051a39Sopenharmony_ciint BIO_sock_should_retry(int s); 37e1051a39Sopenharmony_ci 38e1051a39Sopenharmony_cistatic const BIO_METHOD methods_sockp = { 39e1051a39Sopenharmony_ci BIO_TYPE_SOCKET, 40e1051a39Sopenharmony_ci "socket", 41e1051a39Sopenharmony_ci bwrite_conv, 42e1051a39Sopenharmony_ci sock_write, 43e1051a39Sopenharmony_ci bread_conv, 44e1051a39Sopenharmony_ci sock_read, 45e1051a39Sopenharmony_ci sock_puts, 46e1051a39Sopenharmony_ci NULL, /* sock_gets, */ 47e1051a39Sopenharmony_ci sock_ctrl, 48e1051a39Sopenharmony_ci sock_new, 49e1051a39Sopenharmony_ci sock_free, 50e1051a39Sopenharmony_ci NULL, /* sock_callback_ctrl */ 51e1051a39Sopenharmony_ci}; 52e1051a39Sopenharmony_ci 53e1051a39Sopenharmony_ciconst BIO_METHOD *BIO_s_socket(void) 54e1051a39Sopenharmony_ci{ 55e1051a39Sopenharmony_ci return &methods_sockp; 56e1051a39Sopenharmony_ci} 57e1051a39Sopenharmony_ci 58e1051a39Sopenharmony_ciBIO *BIO_new_socket(int fd, int close_flag) 59e1051a39Sopenharmony_ci{ 60e1051a39Sopenharmony_ci BIO *ret; 61e1051a39Sopenharmony_ci 62e1051a39Sopenharmony_ci ret = BIO_new(BIO_s_socket()); 63e1051a39Sopenharmony_ci if (ret == NULL) 64e1051a39Sopenharmony_ci return NULL; 65e1051a39Sopenharmony_ci BIO_set_fd(ret, fd, close_flag); 66e1051a39Sopenharmony_ci# ifndef OPENSSL_NO_KTLS 67e1051a39Sopenharmony_ci { 68e1051a39Sopenharmony_ci /* 69e1051a39Sopenharmony_ci * The new socket is created successfully regardless of ktls_enable. 70e1051a39Sopenharmony_ci * ktls_enable doesn't change any functionality of the socket, except 71e1051a39Sopenharmony_ci * changing the setsockopt to enable the processing of ktls_start. 72e1051a39Sopenharmony_ci * Thus, it is not a problem to call it for non-TLS sockets. 73e1051a39Sopenharmony_ci */ 74e1051a39Sopenharmony_ci ktls_enable(fd); 75e1051a39Sopenharmony_ci } 76e1051a39Sopenharmony_ci# endif 77e1051a39Sopenharmony_ci return ret; 78e1051a39Sopenharmony_ci} 79e1051a39Sopenharmony_ci 80e1051a39Sopenharmony_cistatic int sock_new(BIO *bi) 81e1051a39Sopenharmony_ci{ 82e1051a39Sopenharmony_ci bi->init = 0; 83e1051a39Sopenharmony_ci bi->num = 0; 84e1051a39Sopenharmony_ci bi->ptr = NULL; 85e1051a39Sopenharmony_ci bi->flags = 0; 86e1051a39Sopenharmony_ci return 1; 87e1051a39Sopenharmony_ci} 88e1051a39Sopenharmony_ci 89e1051a39Sopenharmony_cistatic int sock_free(BIO *a) 90e1051a39Sopenharmony_ci{ 91e1051a39Sopenharmony_ci if (a == NULL) 92e1051a39Sopenharmony_ci return 0; 93e1051a39Sopenharmony_ci if (a->shutdown) { 94e1051a39Sopenharmony_ci if (a->init) { 95e1051a39Sopenharmony_ci BIO_closesocket(a->num); 96e1051a39Sopenharmony_ci } 97e1051a39Sopenharmony_ci a->init = 0; 98e1051a39Sopenharmony_ci a->flags = 0; 99e1051a39Sopenharmony_ci } 100e1051a39Sopenharmony_ci return 1; 101e1051a39Sopenharmony_ci} 102e1051a39Sopenharmony_ci 103e1051a39Sopenharmony_cistatic int sock_read(BIO *b, char *out, int outl) 104e1051a39Sopenharmony_ci{ 105e1051a39Sopenharmony_ci int ret = 0; 106e1051a39Sopenharmony_ci 107e1051a39Sopenharmony_ci if (out != NULL) { 108e1051a39Sopenharmony_ci clear_socket_error(); 109e1051a39Sopenharmony_ci# ifndef OPENSSL_NO_KTLS 110e1051a39Sopenharmony_ci if (BIO_get_ktls_recv(b)) 111e1051a39Sopenharmony_ci ret = ktls_read_record(b->num, out, outl); 112e1051a39Sopenharmony_ci else 113e1051a39Sopenharmony_ci# endif 114e1051a39Sopenharmony_ci ret = readsocket(b->num, out, outl); 115e1051a39Sopenharmony_ci BIO_clear_retry_flags(b); 116e1051a39Sopenharmony_ci if (ret <= 0) { 117e1051a39Sopenharmony_ci if (BIO_sock_should_retry(ret)) 118e1051a39Sopenharmony_ci BIO_set_retry_read(b); 119e1051a39Sopenharmony_ci else if (ret == 0) 120e1051a39Sopenharmony_ci b->flags |= BIO_FLAGS_IN_EOF; 121e1051a39Sopenharmony_ci } 122e1051a39Sopenharmony_ci } 123e1051a39Sopenharmony_ci return ret; 124e1051a39Sopenharmony_ci} 125e1051a39Sopenharmony_ci 126e1051a39Sopenharmony_cistatic int sock_write(BIO *b, const char *in, int inl) 127e1051a39Sopenharmony_ci{ 128e1051a39Sopenharmony_ci int ret = 0; 129e1051a39Sopenharmony_ci 130e1051a39Sopenharmony_ci clear_socket_error(); 131e1051a39Sopenharmony_ci# ifndef OPENSSL_NO_KTLS 132e1051a39Sopenharmony_ci if (BIO_should_ktls_ctrl_msg_flag(b)) { 133e1051a39Sopenharmony_ci unsigned char record_type = (intptr_t)b->ptr; 134e1051a39Sopenharmony_ci ret = ktls_send_ctrl_message(b->num, record_type, in, inl); 135e1051a39Sopenharmony_ci if (ret >= 0) { 136e1051a39Sopenharmony_ci ret = inl; 137e1051a39Sopenharmony_ci BIO_clear_ktls_ctrl_msg_flag(b); 138e1051a39Sopenharmony_ci } 139e1051a39Sopenharmony_ci } else 140e1051a39Sopenharmony_ci# endif 141e1051a39Sopenharmony_ci ret = writesocket(b->num, in, inl); 142e1051a39Sopenharmony_ci BIO_clear_retry_flags(b); 143e1051a39Sopenharmony_ci if (ret <= 0) { 144e1051a39Sopenharmony_ci if (BIO_sock_should_retry(ret)) 145e1051a39Sopenharmony_ci BIO_set_retry_write(b); 146e1051a39Sopenharmony_ci } 147e1051a39Sopenharmony_ci return ret; 148e1051a39Sopenharmony_ci} 149e1051a39Sopenharmony_ci 150e1051a39Sopenharmony_cistatic long sock_ctrl(BIO *b, int cmd, long num, void *ptr) 151e1051a39Sopenharmony_ci{ 152e1051a39Sopenharmony_ci long ret = 1; 153e1051a39Sopenharmony_ci int *ip; 154e1051a39Sopenharmony_ci# ifndef OPENSSL_NO_KTLS 155e1051a39Sopenharmony_ci ktls_crypto_info_t *crypto_info; 156e1051a39Sopenharmony_ci# endif 157e1051a39Sopenharmony_ci 158e1051a39Sopenharmony_ci switch (cmd) { 159e1051a39Sopenharmony_ci case BIO_C_SET_FD: 160e1051a39Sopenharmony_ci sock_free(b); 161e1051a39Sopenharmony_ci b->num = *((int *)ptr); 162e1051a39Sopenharmony_ci b->shutdown = (int)num; 163e1051a39Sopenharmony_ci b->init = 1; 164e1051a39Sopenharmony_ci break; 165e1051a39Sopenharmony_ci case BIO_C_GET_FD: 166e1051a39Sopenharmony_ci if (b->init) { 167e1051a39Sopenharmony_ci ip = (int *)ptr; 168e1051a39Sopenharmony_ci if (ip != NULL) 169e1051a39Sopenharmony_ci *ip = b->num; 170e1051a39Sopenharmony_ci ret = b->num; 171e1051a39Sopenharmony_ci } else 172e1051a39Sopenharmony_ci ret = -1; 173e1051a39Sopenharmony_ci break; 174e1051a39Sopenharmony_ci case BIO_CTRL_GET_CLOSE: 175e1051a39Sopenharmony_ci ret = b->shutdown; 176e1051a39Sopenharmony_ci break; 177e1051a39Sopenharmony_ci case BIO_CTRL_SET_CLOSE: 178e1051a39Sopenharmony_ci b->shutdown = (int)num; 179e1051a39Sopenharmony_ci break; 180e1051a39Sopenharmony_ci case BIO_CTRL_DUP: 181e1051a39Sopenharmony_ci case BIO_CTRL_FLUSH: 182e1051a39Sopenharmony_ci ret = 1; 183e1051a39Sopenharmony_ci break; 184e1051a39Sopenharmony_ci# ifndef OPENSSL_NO_KTLS 185e1051a39Sopenharmony_ci case BIO_CTRL_SET_KTLS: 186e1051a39Sopenharmony_ci crypto_info = (ktls_crypto_info_t *)ptr; 187e1051a39Sopenharmony_ci ret = ktls_start(b->num, crypto_info, num); 188e1051a39Sopenharmony_ci if (ret) 189e1051a39Sopenharmony_ci BIO_set_ktls_flag(b, num); 190e1051a39Sopenharmony_ci break; 191e1051a39Sopenharmony_ci case BIO_CTRL_GET_KTLS_SEND: 192e1051a39Sopenharmony_ci return BIO_should_ktls_flag(b, 1) != 0; 193e1051a39Sopenharmony_ci case BIO_CTRL_GET_KTLS_RECV: 194e1051a39Sopenharmony_ci return BIO_should_ktls_flag(b, 0) != 0; 195e1051a39Sopenharmony_ci case BIO_CTRL_SET_KTLS_TX_SEND_CTRL_MSG: 196e1051a39Sopenharmony_ci BIO_set_ktls_ctrl_msg_flag(b); 197e1051a39Sopenharmony_ci b->ptr = (void *)num; 198e1051a39Sopenharmony_ci ret = 0; 199e1051a39Sopenharmony_ci break; 200e1051a39Sopenharmony_ci case BIO_CTRL_CLEAR_KTLS_TX_CTRL_MSG: 201e1051a39Sopenharmony_ci BIO_clear_ktls_ctrl_msg_flag(b); 202e1051a39Sopenharmony_ci ret = 0; 203e1051a39Sopenharmony_ci break; 204e1051a39Sopenharmony_ci# endif 205e1051a39Sopenharmony_ci case BIO_CTRL_EOF: 206e1051a39Sopenharmony_ci ret = (b->flags & BIO_FLAGS_IN_EOF) != 0; 207e1051a39Sopenharmony_ci break; 208e1051a39Sopenharmony_ci default: 209e1051a39Sopenharmony_ci ret = 0; 210e1051a39Sopenharmony_ci break; 211e1051a39Sopenharmony_ci } 212e1051a39Sopenharmony_ci return ret; 213e1051a39Sopenharmony_ci} 214e1051a39Sopenharmony_ci 215e1051a39Sopenharmony_cistatic int sock_puts(BIO *bp, const char *str) 216e1051a39Sopenharmony_ci{ 217e1051a39Sopenharmony_ci int n, ret; 218e1051a39Sopenharmony_ci 219e1051a39Sopenharmony_ci n = strlen(str); 220e1051a39Sopenharmony_ci ret = sock_write(bp, str, n); 221e1051a39Sopenharmony_ci return ret; 222e1051a39Sopenharmony_ci} 223e1051a39Sopenharmony_ci 224e1051a39Sopenharmony_ciint BIO_sock_should_retry(int i) 225e1051a39Sopenharmony_ci{ 226e1051a39Sopenharmony_ci int err; 227e1051a39Sopenharmony_ci 228e1051a39Sopenharmony_ci if ((i == 0) || (i == -1)) { 229e1051a39Sopenharmony_ci err = get_last_socket_error(); 230e1051a39Sopenharmony_ci 231e1051a39Sopenharmony_ci return BIO_sock_non_fatal_error(err); 232e1051a39Sopenharmony_ci } 233e1051a39Sopenharmony_ci return 0; 234e1051a39Sopenharmony_ci} 235e1051a39Sopenharmony_ci 236e1051a39Sopenharmony_ciint BIO_sock_non_fatal_error(int err) 237e1051a39Sopenharmony_ci{ 238e1051a39Sopenharmony_ci switch (err) { 239e1051a39Sopenharmony_ci# if defined(OPENSSL_SYS_WINDOWS) 240e1051a39Sopenharmony_ci# if defined(WSAEWOULDBLOCK) 241e1051a39Sopenharmony_ci case WSAEWOULDBLOCK: 242e1051a39Sopenharmony_ci# endif 243e1051a39Sopenharmony_ci# endif 244e1051a39Sopenharmony_ci 245e1051a39Sopenharmony_ci# ifdef EWOULDBLOCK 246e1051a39Sopenharmony_ci# ifdef WSAEWOULDBLOCK 247e1051a39Sopenharmony_ci# if WSAEWOULDBLOCK != EWOULDBLOCK 248e1051a39Sopenharmony_ci case EWOULDBLOCK: 249e1051a39Sopenharmony_ci# endif 250e1051a39Sopenharmony_ci# else 251e1051a39Sopenharmony_ci case EWOULDBLOCK: 252e1051a39Sopenharmony_ci# endif 253e1051a39Sopenharmony_ci# endif 254e1051a39Sopenharmony_ci 255e1051a39Sopenharmony_ci# if defined(ENOTCONN) 256e1051a39Sopenharmony_ci case ENOTCONN: 257e1051a39Sopenharmony_ci# endif 258e1051a39Sopenharmony_ci 259e1051a39Sopenharmony_ci# ifdef EINTR 260e1051a39Sopenharmony_ci case EINTR: 261e1051a39Sopenharmony_ci# endif 262e1051a39Sopenharmony_ci 263e1051a39Sopenharmony_ci# ifdef EAGAIN 264e1051a39Sopenharmony_ci# if EWOULDBLOCK != EAGAIN 265e1051a39Sopenharmony_ci case EAGAIN: 266e1051a39Sopenharmony_ci# endif 267e1051a39Sopenharmony_ci# endif 268e1051a39Sopenharmony_ci 269e1051a39Sopenharmony_ci# ifdef EPROTO 270e1051a39Sopenharmony_ci case EPROTO: 271e1051a39Sopenharmony_ci# endif 272e1051a39Sopenharmony_ci 273e1051a39Sopenharmony_ci# ifdef EINPROGRESS 274e1051a39Sopenharmony_ci case EINPROGRESS: 275e1051a39Sopenharmony_ci# endif 276e1051a39Sopenharmony_ci 277e1051a39Sopenharmony_ci# ifdef EALREADY 278e1051a39Sopenharmony_ci case EALREADY: 279e1051a39Sopenharmony_ci# endif 280e1051a39Sopenharmony_ci return 1; 281e1051a39Sopenharmony_ci default: 282e1051a39Sopenharmony_ci break; 283e1051a39Sopenharmony_ci } 284e1051a39Sopenharmony_ci return 0; 285e1051a39Sopenharmony_ci} 286e1051a39Sopenharmony_ci 287e1051a39Sopenharmony_ci#endif /* #ifndef OPENSSL_NO_SOCK */ 288