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