quic-server.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. /*
  2. * Copyright 2025 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. /*
  45. * This callback validates and negotiates the desired ALPN on the server side.
  46. * Accept any ALPN.
  47. */
  48. static int select_alpn(SSL *ssl, const unsigned char **out,
  49. unsigned char *out_len, const unsigned char *in,
  50. unsigned int in_len, void *arg)
  51. {
  52. return SSL_TLSEXT_ERR_OK;
  53. }
  54. int FuzzerTestOneInput(const uint8_t *buf, size_t len)
  55. {
  56. SSL *server = NULL, *stream = NULL;
  57. SSL *allstreams[] = {NULL, NULL, NULL, NULL};
  58. size_t i, thisstream = 0, numstreams = 1;
  59. BIO *in;
  60. BIO *out;
  61. SSL_CTX *ctx;
  62. struct timeval tv;
  63. int state = HANDSHAKING;
  64. uint8_t tmp[1024];
  65. int writelen = 0;
  66. if (len == 0)
  67. return 0;
  68. ctx = SSL_CTX_new(OSSL_QUIC_server_method());
  69. if (ctx == NULL)
  70. goto end;
  71. SSL_CTX_set_alpn_select_cb(ctx, select_alpn, NULL);
  72. server = SSL_new_listener(ctx, 0);
  73. allstreams[0] = stream = server;
  74. if (server == NULL)
  75. goto end;
  76. fake_now = ossl_ms2time(1);
  77. if (!ossl_quic_set_override_now_cb(server, fake_now_cb, NULL))
  78. goto end;
  79. in = BIO_new(BIO_s_dgram_mem());
  80. if (in == NULL)
  81. goto end;
  82. out = BIO_new(BIO_s_dgram_mem());
  83. if (out == NULL) {
  84. BIO_free(in);
  85. goto end;
  86. }
  87. if (!BIO_dgram_set_caps(out, BIO_DGRAM_CAP_HANDLES_DST_ADDR)) {
  88. BIO_free(in);
  89. BIO_free(out);
  90. goto end;
  91. }
  92. SSL_set_bio(server, in, out);
  93. SSL_set_accept_state(server);
  94. for (;;) {
  95. size_t size;
  96. uint64_t nxtpktms = 0;
  97. OSSL_TIME nxtpkt = ossl_time_zero(), nxttimeout;
  98. int isinf, ret = 0;
  99. if (len >= 2) {
  100. if (len >= 5 && buf[0] == 0xff && buf[1] == 0xff) {
  101. switch (buf[2]) {
  102. case 0x00:
  103. if (state == READING)
  104. state = ACCEPTING_STREAM;
  105. break;
  106. case 0x01:
  107. if (state == READING)
  108. state = CREATING_STREAM;
  109. break;
  110. case 0x02:
  111. if (state == READING)
  112. state = SWAPPING_STREAM;
  113. break;
  114. default:
  115. /* ignore */
  116. break;
  117. }
  118. len -= 3;
  119. buf += 3;
  120. }
  121. nxtpktms = buf[0] + (buf[1] << 8);
  122. nxtpkt = ossl_time_add(fake_now, ossl_ms2time(nxtpktms));
  123. len -= 2;
  124. buf += 2;
  125. }
  126. for (;;) {
  127. switch (state) {
  128. case HANDSHAKING:
  129. ret = SSL_accept_connection(stream, 0) != NULL;
  130. if (ret == 1)
  131. state = READING;
  132. break;
  133. case READING:
  134. ret = SSL_read(stream, tmp, sizeof(tmp));
  135. if (ret > 0) {
  136. state = WRITING;
  137. writelen = ret;
  138. assert(writelen <= (int)sizeof(tmp));
  139. }
  140. break;
  141. case WRITING:
  142. ret = SSL_write(stream, tmp, writelen);
  143. if (ret > 0)
  144. state = READING;
  145. break;
  146. case ACCEPTING_STREAM:
  147. state = READING;
  148. ret = 1;
  149. if (numstreams == OSSL_NELEM(allstreams)
  150. || SSL_get_accept_stream_queue_len(server) == 0)
  151. break;
  152. thisstream = numstreams;
  153. stream = allstreams[numstreams++] = SSL_accept_stream(server, 0);
  154. if (stream == NULL)
  155. goto end;
  156. break;
  157. case CREATING_STREAM:
  158. state = READING;
  159. ret = 1;
  160. if (numstreams == OSSL_NELEM(allstreams))
  161. break;
  162. stream = SSL_new_stream(server, 0);
  163. if (stream == NULL) {
  164. /* Ignore, and go back to the previous stream */
  165. stream = allstreams[thisstream];
  166. break;
  167. }
  168. thisstream = numstreams;
  169. allstreams[numstreams++] = stream;
  170. break;
  171. case SWAPPING_STREAM:
  172. state = READING;
  173. ret = 1;
  174. if (numstreams == 1)
  175. break;
  176. if (++thisstream == numstreams)
  177. thisstream = 0;
  178. stream = allstreams[thisstream];
  179. break;
  180. }
  181. assert(stream != NULL);
  182. assert(thisstream < numstreams);
  183. if (ret <= 0) {
  184. switch (SSL_get_error(stream, ret)) {
  185. case SSL_ERROR_WANT_READ:
  186. case SSL_ERROR_WANT_WRITE:
  187. break;
  188. default:
  189. goto end;
  190. }
  191. }
  192. if (!SSL_get_event_timeout(server, &tv, &isinf))
  193. goto end;
  194. if (isinf) {
  195. fake_now = nxtpkt;
  196. break;
  197. } else {
  198. nxttimeout = ossl_time_add(fake_now,
  199. ossl_time_from_timeval(tv));
  200. if (len > 3 && ossl_time_compare(nxttimeout, nxtpkt) >= 0) {
  201. fake_now = nxtpkt;
  202. break;
  203. }
  204. fake_now = nxttimeout;
  205. }
  206. }
  207. if (len <= 3)
  208. break;
  209. size = buf[0] + (buf[1] << 8);
  210. if (size > len - 2)
  211. break;
  212. if (size > 0)
  213. BIO_write(in, buf + 2, size);
  214. len -= size + 2;
  215. buf += size + 2;
  216. }
  217. end:
  218. for (i = 0; i < numstreams; i++)
  219. SSL_free(allstreams[i]);
  220. ERR_clear_error();
  221. SSL_CTX_free(ctx);
  222. return 0;
  223. }
  224. void FuzzerCleanup(void)
  225. {
  226. FuzzerClearRand();
  227. }