quic-client.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. /*
  2. * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. * https://www.openssl.org/source/license.html
  8. * or in the file LICENSE in the source distribution.
  9. */
  10. #include <openssl/ssl.h>
  11. #include <openssl/err.h>
  12. #include <openssl/bio.h>
  13. #include "fuzzer.h"
  14. #include "internal/sockets.h"
  15. #include "internal/time.h"
  16. #include "internal/quic_ssl.h"
  17. /* unused, to avoid warning. */
  18. static int idx;
  19. static OSSL_TIME fake_now;
  20. static OSSL_TIME fake_now_cb(void *arg)
  21. {
  22. return fake_now;
  23. }
  24. int FuzzerInitialize(int *argc, char ***argv)
  25. {
  26. STACK_OF(SSL_COMP) *comp_methods;
  27. FuzzerSetRand();
  28. OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS | OPENSSL_INIT_ASYNC, NULL);
  29. OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
  30. ERR_clear_error();
  31. CRYPTO_free_ex_index(0, -1);
  32. idx = SSL_get_ex_data_X509_STORE_CTX_idx();
  33. comp_methods = SSL_COMP_get_compression_methods();
  34. if (comp_methods != NULL)
  35. sk_SSL_COMP_sort(comp_methods);
  36. return 1;
  37. }
  38. #define HANDSHAKING 0
  39. #define READING 1
  40. #define WRITING 2
  41. #define ACCEPTING_STREAM 3
  42. #define CREATING_STREAM 4
  43. #define SWAPPING_STREAM 5
  44. int FuzzerTestOneInput(const uint8_t *buf, size_t len)
  45. {
  46. SSL *client = NULL, *stream = NULL;
  47. SSL *allstreams[] = {NULL, NULL, NULL, NULL};
  48. size_t i, thisstream = 0, numstreams = 1;
  49. BIO *in;
  50. BIO *out;
  51. SSL_CTX *ctx;
  52. BIO_ADDR *peer_addr = NULL;
  53. struct in_addr ina = {0};
  54. struct timeval tv;
  55. int state = HANDSHAKING;
  56. uint8_t tmp[1024];
  57. int writelen = 0;
  58. if (len == 0)
  59. return 0;
  60. /* This only fuzzes the initial flow from the client so far. */
  61. ctx = SSL_CTX_new(OSSL_QUIC_client_method());
  62. if (ctx == NULL)
  63. goto end;
  64. client = SSL_new(ctx);
  65. if (client == NULL)
  66. goto end;
  67. fake_now = ossl_ms2time(1);
  68. if (!ossl_quic_conn_set_override_now_cb(client, fake_now_cb, NULL))
  69. goto end;
  70. peer_addr = BIO_ADDR_new();
  71. if (peer_addr == NULL)
  72. goto end;
  73. ina.s_addr = htonl(0x7f000001UL);
  74. if (!BIO_ADDR_rawmake(peer_addr, AF_INET, &ina, sizeof(ina), htons(4433)))
  75. goto end;
  76. SSL_set_tlsext_host_name(client, "localhost");
  77. in = BIO_new(BIO_s_dgram_mem());
  78. if (in == NULL)
  79. goto end;
  80. out = BIO_new(BIO_s_dgram_mem());
  81. if (out == NULL) {
  82. BIO_free(in);
  83. goto end;
  84. }
  85. if (!BIO_dgram_set_caps(out, BIO_DGRAM_CAP_HANDLES_DST_ADDR)) {
  86. BIO_free(in);
  87. BIO_free(out);
  88. goto end;
  89. }
  90. SSL_set_bio(client, in, out);
  91. if (SSL_set_alpn_protos(client, (const unsigned char *)"\x08ossltest", 9) != 0)
  92. goto end;
  93. if (SSL_set1_initial_peer_addr(client, peer_addr) != 1)
  94. goto end;
  95. SSL_set_connect_state(client);
  96. if (!SSL_set_incoming_stream_policy(client,
  97. SSL_INCOMING_STREAM_POLICY_ACCEPT,
  98. 0))
  99. goto end;
  100. allstreams[0] = stream = client;
  101. for (;;) {
  102. size_t size;
  103. uint64_t nxtpktms = 0;
  104. OSSL_TIME nxtpkt = ossl_time_zero(), nxttimeout;
  105. int isinf, ret = 0;
  106. if (len >= 2) {
  107. if (len >= 5 && buf[0] == 0xff && buf[1] == 0xff) {
  108. switch (buf[2]) {
  109. case 0x00:
  110. if (state == READING)
  111. state = ACCEPTING_STREAM;
  112. break;
  113. case 0x01:
  114. if (state == READING)
  115. state = CREATING_STREAM;
  116. break;
  117. case 0x02:
  118. if (state == READING)
  119. state = SWAPPING_STREAM;
  120. break;
  121. default:
  122. /*ignore*/
  123. break;
  124. }
  125. len -= 3;
  126. buf += 3;
  127. }
  128. nxtpktms = buf[0] + (buf[1] << 8);
  129. nxtpkt = ossl_time_add(fake_now, ossl_ms2time(nxtpktms));
  130. len -= 2;
  131. buf += 2;
  132. }
  133. for (;;) {
  134. switch (state) {
  135. case HANDSHAKING:
  136. ret = SSL_do_handshake(stream);
  137. if (ret == 1)
  138. state = READING;
  139. break;
  140. case READING:
  141. ret = SSL_read(stream, tmp, sizeof(tmp));
  142. if (ret > 0) {
  143. state = WRITING;
  144. writelen = ret;
  145. assert(writelen <= (int)sizeof(tmp));
  146. }
  147. break;
  148. case WRITING:
  149. ret = SSL_write(stream, tmp, writelen);
  150. if (ret > 0)
  151. state = READING;
  152. break;
  153. case ACCEPTING_STREAM:
  154. state = READING;
  155. ret = 1;
  156. if (numstreams == OSSL_NELEM(allstreams)
  157. || SSL_get_accept_stream_queue_len(client) == 0)
  158. break;
  159. thisstream = numstreams;
  160. stream = allstreams[numstreams++]
  161. = SSL_accept_stream(client, 0);
  162. if (stream == NULL)
  163. goto end;
  164. break;
  165. case CREATING_STREAM:
  166. state = READING;
  167. ret = 1;
  168. if (numstreams == OSSL_NELEM(allstreams))
  169. break;
  170. stream = SSL_new_stream(client, 0);
  171. if (stream == NULL) {
  172. /* Ignore, and go back to the previous stream */
  173. stream = allstreams[thisstream];
  174. break;
  175. }
  176. thisstream = numstreams;
  177. allstreams[numstreams++] = stream;
  178. break;
  179. case SWAPPING_STREAM:
  180. state = READING;
  181. ret = 1;
  182. if (numstreams == 1)
  183. break;
  184. if (++thisstream == numstreams)
  185. thisstream = 0;
  186. stream = allstreams[thisstream];
  187. break;
  188. }
  189. assert(stream != NULL);
  190. assert(thisstream < numstreams);
  191. if (ret <= 0) {
  192. switch (SSL_get_error(stream, ret)) {
  193. case SSL_ERROR_WANT_READ:
  194. case SSL_ERROR_WANT_WRITE:
  195. break;
  196. default:
  197. goto end;
  198. }
  199. }
  200. if (!SSL_get_event_timeout(client, &tv, &isinf))
  201. goto end;
  202. if (isinf) {
  203. fake_now = nxtpkt;
  204. break;
  205. } else {
  206. nxttimeout = ossl_time_add(fake_now,
  207. ossl_time_from_timeval(tv));
  208. if (len > 3 && ossl_time_compare(nxttimeout, nxtpkt) >= 0) {
  209. fake_now = nxtpkt;
  210. break;
  211. }
  212. fake_now = nxttimeout;
  213. }
  214. }
  215. if (len <= 3)
  216. break;
  217. size = buf[0] + (buf[1] << 8);
  218. if (size > len - 2)
  219. break;
  220. if (size > 0)
  221. BIO_write(in, buf+2, size);
  222. len -= size + 2;
  223. buf += size + 2;
  224. }
  225. end:
  226. for (i = 0; i < numstreams; i++)
  227. SSL_free(allstreams[i]);
  228. ERR_clear_error();
  229. SSL_CTX_free(ctx);
  230. BIO_ADDR_free(peer_addr);
  231. return 0;
  232. }
  233. void FuzzerCleanup(void)
  234. {
  235. FuzzerClearRand();
  236. }