You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

442 line
13 KiB

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