1d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Copyright (c) 2014, Google Inc. 2d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 3d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Permission to use, copy, modify, and/or distribute this software for any 4d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * purpose with or without fee is hereby granted, provided that the above 5d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * copyright notice and this permission notice appear in all copies. 6d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 7d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ 14d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 15d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#if !defined(_POSIX_C_SOURCE) 16d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#define _POSIX_C_SOURCE 201410L 17d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#endif 18d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 19d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/base.h> 20d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 21d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#if !defined(OPENSSL_WINDOWS) 22d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <arpa/inet.h> 23d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <fcntl.h> 24d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <netinet/in.h> 25d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <string.h> 26d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <sys/socket.h> 27d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <unistd.h> 28d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#else 29d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <io.h> 30d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#pragma warning(push, 3) 31ac6c5371f5e5beafc345f312a097c3ebd4766afaKenny Root#include <winsock2.h> 32ac6c5371f5e5beafc345f312a097c3ebd4766afaKenny Root#include <ws2tcpip.h> 33d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#pragma warning(pop) 34d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#endif 35d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 36d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/bio.h> 37d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/crypto.h> 38d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/err.h> 39e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <openssl/mem.h> 40e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 41e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <algorithm> 42e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 43e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include "../test/scoped_types.h" 44d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 45d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 46d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#if !defined(OPENSSL_WINDOWS) 47d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int closesocket(int sock) { 48d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return close(sock); 49d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 50d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 51e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic void PrintSocketError(const char *func) { 52d9e397b599b13d642138480a28c14db7a136bf0Adam Langley perror(func); 53d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 54d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#else 55e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic void PrintSocketError(const char *func) { 56d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, "%s: %d\n", func, WSAGetLastError()); 57d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 58d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#endif 59d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 60e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleyclass ScopedSocket { 61e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley public: 62e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley ScopedSocket(int sock) : sock_(sock) {} 63e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley ~ScopedSocket() { 64e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley closesocket(sock_); 65e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 66e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 67e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley private: 68e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley const int sock_; 69e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley}; 70e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 71e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool TestSocketConnect() { 72d9e397b599b13d642138480a28c14db7a136bf0Adam Langley static const char kTestMessage[] = "test"; 73d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 74e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley int listening_sock = socket(AF_INET, SOCK_STREAM, 0); 75e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (listening_sock == -1) { 76e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley PrintSocketError("socket"); 77e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 78e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 79e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley ScopedSocket listening_sock_closer(listening_sock); 80e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 81e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley struct sockaddr_in sin; 82d9e397b599b13d642138480a28c14db7a136bf0Adam Langley memset(&sin, 0, sizeof(sin)); 83d9e397b599b13d642138480a28c14db7a136bf0Adam Langley sin.sin_family = AF_INET; 84d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr)) { 85e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley PrintSocketError("inet_pton"); 86e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 87d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 88d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (bind(listening_sock, (struct sockaddr *)&sin, sizeof(sin)) != 0) { 89e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley PrintSocketError("bind"); 90e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 91d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 92d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (listen(listening_sock, 1)) { 93e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley PrintSocketError("listen"); 94e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 95d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 96e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley socklen_t sockaddr_len = sizeof(sin); 97d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (getsockname(listening_sock, (struct sockaddr *)&sin, &sockaddr_len) || 98d9e397b599b13d642138480a28c14db7a136bf0Adam Langley sockaddr_len != sizeof(sin)) { 99e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley PrintSocketError("getsockname"); 100e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 101d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 102d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 103e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley char hostname[80]; 104d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BIO_snprintf(hostname, sizeof(hostname), "%s:%d", "127.0.0.1", 105d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ntohs(sin.sin_port)); 106e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley ScopedBIO bio(BIO_new_connect(hostname)); 107d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!bio) { 108d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, "BIO_new_connect failed.\n"); 109e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 110d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 111d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 112e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (BIO_write(bio.get(), kTestMessage, sizeof(kTestMessage)) != 113d9e397b599b13d642138480a28c14db7a136bf0Adam Langley sizeof(kTestMessage)) { 114d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, "BIO_write failed.\n"); 115e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley ERR_print_errors_fp(stderr); 116e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 117d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 118d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 119e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley int sock = accept(listening_sock, (struct sockaddr *) &sin, &sockaddr_len); 120e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (sock == -1) { 121e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley PrintSocketError("accept"); 122e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 123d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 124e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley ScopedSocket sock_closer(sock); 125d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 126e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley char buf[5]; 127d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (recv(sock, buf, sizeof(buf), 0) != sizeof(kTestMessage)) { 128e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley PrintSocketError("read"); 129e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 130d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 131d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (memcmp(buf, kTestMessage, sizeof(kTestMessage))) { 132e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 133d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 134d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 135e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return true; 136d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 137d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 138d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 139e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// BioReadZeroCopyWrapper is a wrapper around the zero-copy APIs to make 140e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// testing easier. 141e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic size_t BioReadZeroCopyWrapper(BIO *bio, uint8_t *data, size_t len) { 142d9e397b599b13d642138480a28c14db7a136bf0Adam Langley uint8_t *read_buf; 143d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t read_buf_offset; 144d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t available_bytes; 145d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t len_read = 0; 146d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 147d9e397b599b13d642138480a28c14db7a136bf0Adam Langley do { 148d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BIO_zero_copy_get_read_buf(bio, &read_buf, &read_buf_offset, 149d9e397b599b13d642138480a28c14db7a136bf0Adam Langley &available_bytes)) { 150d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 151d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 152d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 153e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley available_bytes = std::min(available_bytes, len - len_read); 154d9e397b599b13d642138480a28c14db7a136bf0Adam Langley memmove(data + len_read, read_buf + read_buf_offset, available_bytes); 155d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 156d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BIO_zero_copy_get_read_buf_done(bio, available_bytes); 157d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 158d9e397b599b13d642138480a28c14db7a136bf0Adam Langley len_read += available_bytes; 159d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } while (len - len_read > 0 && available_bytes > 0); 160d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 161d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return len_read; 162d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 163d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 164e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// BioWriteZeroCopyWrapper is a wrapper around the zero-copy APIs to make 165e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// testing easier. 166e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic size_t BioWriteZeroCopyWrapper(BIO *bio, const uint8_t *data, 167e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley size_t len) { 168d9e397b599b13d642138480a28c14db7a136bf0Adam Langley uint8_t *write_buf; 169d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t write_buf_offset; 170d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t available_bytes; 171d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t len_written = 0; 172d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 173d9e397b599b13d642138480a28c14db7a136bf0Adam Langley do { 174d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BIO_zero_copy_get_write_buf(bio, &write_buf, &write_buf_offset, 175d9e397b599b13d642138480a28c14db7a136bf0Adam Langley &available_bytes)) { 176d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 177d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 178d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 179e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley available_bytes = std::min(available_bytes, len - len_written); 180d9e397b599b13d642138480a28c14db7a136bf0Adam Langley memmove(write_buf + write_buf_offset, data + len_written, available_bytes); 181d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 182d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BIO_zero_copy_get_write_buf_done(bio, available_bytes); 183d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 184d9e397b599b13d642138480a28c14db7a136bf0Adam Langley len_written += available_bytes; 185d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } while (len - len_written > 0 && available_bytes > 0); 186d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 187d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return len_written; 188d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 189d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 190e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool TestZeroCopyBioPairs() { 191e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Test read and write, especially triggering the ring buffer wrap-around. 192d9e397b599b13d642138480a28c14db7a136bf0Adam Langley uint8_t bio1_application_send_buffer[1024]; 193d9e397b599b13d642138480a28c14db7a136bf0Adam Langley uint8_t bio2_application_recv_buffer[1024]; 194d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 195d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const size_t kLengths[] = {254, 255, 256, 257, 510, 511, 512, 513}; 196d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 197e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // These trigger ring buffer wrap around. 198d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const size_t kPartialLengths[] = {0, 1, 2, 3, 128, 255, 256, 257, 511, 512}; 199d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 200d9e397b599b13d642138480a28c14db7a136bf0Adam Langley static const size_t kBufferSize = 512; 201d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 202d9e397b599b13d642138480a28c14db7a136bf0Adam Langley srand(1); 203e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley for (size_t i = 0; i < sizeof(bio1_application_send_buffer); i++) { 204d9e397b599b13d642138480a28c14db7a136bf0Adam Langley bio1_application_send_buffer[i] = rand() & 255; 205d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 206d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 207e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Transfer bytes from bio1_application_send_buffer to 208e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // bio2_application_recv_buffer in various ways. 209e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley for (size_t i = 0; i < sizeof(kLengths) / sizeof(kLengths[0]); i++) { 210e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley for (size_t j = 0; j < sizeof(kPartialLengths) / sizeof(kPartialLengths[0]); 211e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley j++) { 212e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley size_t total_write = 0; 213e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley size_t total_read = 0; 214e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 215e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley BIO *bio1, *bio2; 216e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!BIO_new_bio_pair(&bio1, kBufferSize, &bio2, kBufferSize)) { 217e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 218e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 219e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley ScopedBIO bio1_scoper(bio1); 220e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley ScopedBIO bio2_scoper(bio2); 221d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 222e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley total_write += BioWriteZeroCopyWrapper( 223d9e397b599b13d642138480a28c14db7a136bf0Adam Langley bio1, bio1_application_send_buffer, kLengths[i]); 224d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 225e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // This tests interleaved read/write calls. Do a read between zero copy 226e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // write calls. 227e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley uint8_t *write_buf; 228e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley size_t write_buf_offset; 229e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley size_t available_bytes; 230d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BIO_zero_copy_get_write_buf(bio1, &write_buf, &write_buf_offset, 231d9e397b599b13d642138480a28c14db7a136bf0Adam Langley &available_bytes)) { 232e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 233d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 234d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 235e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Free kPartialLengths[j] bytes in the beginning of bio1 write buffer. 236e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // This enables ring buffer wrap around for the next write. 237d9e397b599b13d642138480a28c14db7a136bf0Adam Langley total_read += BIO_read(bio2, bio2_application_recv_buffer + total_read, 238d9e397b599b13d642138480a28c14db7a136bf0Adam Langley kPartialLengths[j]); 239d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 240e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley size_t interleaved_write_len = std::min(kPartialLengths[j], 241e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley available_bytes); 242d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 243e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Write the data for the interleaved write call. If the buffer becomes 244e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // empty after a read, the write offset is normally set to 0. Check that 245e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // this does not happen for interleaved read/write and that 246e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // |write_buf_offset| is still valid. 247d9e397b599b13d642138480a28c14db7a136bf0Adam Langley memcpy(write_buf + write_buf_offset, 248d9e397b599b13d642138480a28c14db7a136bf0Adam Langley bio1_application_send_buffer + total_write, interleaved_write_len); 249d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (BIO_zero_copy_get_write_buf_done(bio1, interleaved_write_len)) { 250d9e397b599b13d642138480a28c14db7a136bf0Adam Langley total_write += interleaved_write_len; 251d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 252d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 253e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Do another write in case |write_buf_offset| was wrapped. 254e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley total_write += BioWriteZeroCopyWrapper( 255d9e397b599b13d642138480a28c14db7a136bf0Adam Langley bio1, bio1_application_send_buffer + total_write, 256d9e397b599b13d642138480a28c14db7a136bf0Adam Langley kPartialLengths[j] - interleaved_write_len); 257d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 258e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Drain the rest. 259e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley size_t bytes_left = BIO_pending(bio2); 260e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley total_read += BioReadZeroCopyWrapper( 261d9e397b599b13d642138480a28c14db7a136bf0Adam Langley bio2, bio2_application_recv_buffer + total_read, bytes_left); 262d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 263d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (total_read != total_write) { 264d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, "Lengths not equal in round (%u, %u)\n", (unsigned)i, 265d9e397b599b13d642138480a28c14db7a136bf0Adam Langley (unsigned)j); 266e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 267d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 268d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (total_read > kLengths[i] + kPartialLengths[j]) { 269d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, "Bad lengths in round (%u, %u)\n", (unsigned)i, 270d9e397b599b13d642138480a28c14db7a136bf0Adam Langley (unsigned)j); 271e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 272d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 273d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (memcmp(bio1_application_send_buffer, bio2_application_recv_buffer, 274d9e397b599b13d642138480a28c14db7a136bf0Adam Langley total_read) != 0) { 275d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, "Buffers not equal in round (%u, %u)\n", (unsigned)i, 276d9e397b599b13d642138480a28c14db7a136bf0Adam Langley (unsigned)j); 277e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 278d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 279d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 280d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 281d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 282e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return true; 283d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 284d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 285e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool TestPrintf() { 286e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Test a short output, a very long one, and various sizes around 287e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // 256 (the size of the buffer) to ensure edge cases are correct. 288d9e397b599b13d642138480a28c14db7a136bf0Adam Langley static const size_t kLengths[] = { 5, 250, 251, 252, 253, 254, 1023 }; 289d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 290e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley ScopedBIO bio(BIO_new(BIO_s_mem())); 291d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!bio) { 292d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, "BIO_new failed\n"); 293e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 294d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 295d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 296e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley for (size_t i = 0; i < sizeof(kLengths) / sizeof(kLengths[0]); i++) { 297e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley char string[1024]; 298d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (kLengths[i] >= sizeof(string)) { 299d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, "Bad test string length\n"); 300e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 301d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 302d9e397b599b13d642138480a28c14db7a136bf0Adam Langley memset(string, 'a', sizeof(string)); 303d9e397b599b13d642138480a28c14db7a136bf0Adam Langley string[kLengths[i]] = '\0'; 304d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 305e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley int ret = BIO_printf(bio.get(), "test %s", string); 306e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (ret < 0 || static_cast<size_t>(ret) != 5 + kLengths[i]) { 307d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, "BIO_printf failed: %d\n", ret); 308e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 309d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 310e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley const uint8_t *contents; 311e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley size_t len; 312e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!BIO_mem_contents(bio.get(), &contents, &len)) { 313d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, "BIO_mem_contents failed\n"); 314e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 315d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 316d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (len != 5 + kLengths[i] || 317d9e397b599b13d642138480a28c14db7a136bf0Adam Langley strncmp((const char *)contents, "test ", 5) != 0 || 318d9e397b599b13d642138480a28c14db7a136bf0Adam Langley strncmp((const char *)contents + 5, string, kLengths[i]) != 0) { 319d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, "Contents did not match: %.*s\n", (int)len, contents); 320e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 321d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 322d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 323e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!BIO_reset(bio.get())) { 324d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, "BIO_reset failed\n"); 325e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 326d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 327d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 328d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 329e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return true; 330d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 331d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 3324f05b238eec1f3f026657a6da19058143d34ceaaAdam Langleystatic bool ReadASN1(bool should_succeed, const uint8_t *data, size_t data_len, 3334f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley size_t expected_len, size_t max_len) { 3344f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley ScopedBIO bio(BIO_new_mem_buf(const_cast<uint8_t*>(data), data_len)); 3354f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley 3364f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley uint8_t *out; 3374f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley size_t out_len; 3384f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley int ok = BIO_read_asn1(bio.get(), &out, &out_len, max_len); 3394f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley if (!ok) { 3404f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley out = nullptr; 3414f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley } 3424f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley ScopedOpenSSLBytes out_storage(out); 3434f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley 3444f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley if (should_succeed != (ok == 1)) { 3454f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley return false; 3464f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley } 3474f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley 3484f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley if (should_succeed && 3494f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley (out_len != expected_len || memcmp(data, out, expected_len) != 0)) { 3504f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley return false; 3514f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley } 3524f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley 3534f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley return true; 3544f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley} 3554f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley 3564f05b238eec1f3f026657a6da19058143d34ceaaAdam Langleystatic bool TestASN1() { 3574f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley static const uint8_t kData1[] = {0x30, 2, 1, 2, 0, 0}; 3584f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley static const uint8_t kData2[] = {0x30, 3, 1, 2}; /* truncated */ 3594f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley static const uint8_t kData3[] = {0x30, 0x81, 1, 1}; /* should be short len */ 3604f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley static const uint8_t kData4[] = {0x30, 0x82, 0, 1, 1}; /* zero padded. */ 3614f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley 3624f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley if (!ReadASN1(true, kData1, sizeof(kData1), 4, 100) || 3634f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley !ReadASN1(false, kData2, sizeof(kData2), 0, 100) || 3644f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley !ReadASN1(false, kData3, sizeof(kData3), 0, 100) || 3654f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley !ReadASN1(false, kData4, sizeof(kData4), 0, 100)) { 3664f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley return false; 3674f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley } 3684f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley 3694f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley static const size_t kLargePayloadLen = 8000; 3704f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley static const uint8_t kLargePrefix[] = {0x30, 0x82, kLargePayloadLen >> 8, 3714f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley kLargePayloadLen & 0xff}; 3724f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley ScopedOpenSSLBytes large(reinterpret_cast<uint8_t *>( 3734f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley OPENSSL_malloc(sizeof(kLargePrefix) + kLargePayloadLen))); 37453b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley if (!large) { 37553b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley return false; 37653b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley } 3774f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley memset(large.get() + sizeof(kLargePrefix), 0, kLargePayloadLen); 3784f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley memcpy(large.get(), kLargePrefix, sizeof(kLargePrefix)); 3794f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley 3804f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley if (!ReadASN1(true, large.get(), sizeof(kLargePrefix) + kLargePayloadLen, 3814f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley sizeof(kLargePrefix) + kLargePayloadLen, 3824f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley kLargePayloadLen * 2)) { 3834f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley fprintf(stderr, "Large payload test failed.\n"); 3844f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley return false; 3854f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley } 3864f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley 3874f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley if (!ReadASN1(false, large.get(), sizeof(kLargePrefix) + kLargePayloadLen, 3884f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley sizeof(kLargePrefix) + kLargePayloadLen, 3894f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley kLargePayloadLen - 1)) { 3904f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley fprintf(stderr, "max_len test failed.\n"); 3914f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley return false; 3924f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley } 3934f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley 3944f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley static const uint8_t kIndefPrefix[] = {0x30, 0x80}; 3954f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley memcpy(large.get(), kIndefPrefix, sizeof(kIndefPrefix)); 3964f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley if (!ReadASN1(true, large.get(), sizeof(kLargePrefix) + kLargePayloadLen, 3974f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley sizeof(kLargePrefix) + kLargePayloadLen, 3984f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley kLargePayloadLen*2)) { 3994f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley fprintf(stderr, "indefinite length test failed.\n"); 4004f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley return false; 4014f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley } 4024f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley 4034f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley if (!ReadASN1(false, large.get(), sizeof(kLargePrefix) + kLargePayloadLen, 4044f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley sizeof(kLargePrefix) + kLargePayloadLen, 4054f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley kLargePayloadLen-1)) { 4064f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley fprintf(stderr, "indefinite length, max_len test failed.\n"); 4074f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley return false; 4084f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley } 4094f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley 4104f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley return true; 4114f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley} 4124f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley 413d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint main(void) { 414d9e397b599b13d642138480a28c14db7a136bf0Adam Langley CRYPTO_library_init(); 415d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ERR_load_crypto_strings(); 416d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 417d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#if defined(OPENSSL_WINDOWS) 418e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Initialize Winsock. 419e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley WORD wsa_version = MAKEWORD(2, 2); 420e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley WSADATA wsa_data; 421e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley int wsa_err = WSAStartup(wsa_version, &wsa_data); 422d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (wsa_err != 0) { 423d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, "WSAStartup failed: %d\n", wsa_err); 424d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 1; 425d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 426d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (wsa_data.wVersion != wsa_version) { 427d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, "Didn't get expected version: %x\n", wsa_data.wVersion); 428d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 1; 429d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 430d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#endif 431d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 432e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!TestSocketConnect() || 433e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley !TestPrintf() || 4344f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley !TestZeroCopyBioPairs() || 4354f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley !TestASN1()) { 436d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 1; 437d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 438d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 439d9e397b599b13d642138480a28c14db7a136bf0Adam Langley printf("PASS\n"); 440d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 441d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 442