quic_lcidm.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  1. /*
  2. * Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License 2.0 (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. */
  9. #include "internal/quic_lcidm.h"
  10. #include "internal/quic_types.h"
  11. #include "internal/quic_vlint.h"
  12. #include "internal/common.h"
  13. #include <openssl/lhash.h>
  14. #include <openssl/rand.h>
  15. #include <openssl/err.h>
  16. /*
  17. * QUIC Local Connection ID Manager
  18. * ================================
  19. */
  20. typedef struct quic_lcidm_conn_st QUIC_LCIDM_CONN;
  21. enum {
  22. LCID_TYPE_ODCID, /* This LCID is the ODCID from the peer */
  23. LCID_TYPE_INITIAL, /* This is our Initial SCID */
  24. LCID_TYPE_NCID /* This LCID was issued via a NCID frame */
  25. };
  26. typedef struct quic_lcid_st {
  27. QUIC_CONN_ID cid;
  28. uint64_t seq_num;
  29. /* Back-pointer to the owning QUIC_LCIDM_CONN structure. */
  30. QUIC_LCIDM_CONN *conn;
  31. /* LCID_TYPE_* */
  32. unsigned int type : 2;
  33. } QUIC_LCID;
  34. DEFINE_LHASH_OF_EX(QUIC_LCID);
  35. DEFINE_LHASH_OF_EX(QUIC_LCIDM_CONN);
  36. struct quic_lcidm_conn_st {
  37. size_t num_active_lcid;
  38. LHASH_OF(QUIC_LCID) *lcids;
  39. void *opaque;
  40. QUIC_LCID *odcid_lcid_obj;
  41. uint64_t next_seq_num;
  42. /* Have we enrolled an ODCID? */
  43. unsigned int done_odcid : 1;
  44. };
  45. struct quic_lcidm_st {
  46. OSSL_LIB_CTX *libctx;
  47. LHASH_OF(QUIC_LCID) *lcids; /* (QUIC_CONN_ID) -> (QUIC_LCID *) */
  48. LHASH_OF(QUIC_LCIDM_CONN) *conns; /* (void *opaque) -> (QUIC_LCIDM_CONN *) */
  49. size_t lcid_len; /* Length in bytes for all LCIDs */
  50. #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
  51. QUIC_CONN_ID next_lcid;
  52. #endif
  53. };
  54. static unsigned long bin_hash(const unsigned char *buf, size_t buf_len)
  55. {
  56. unsigned long hash = 0;
  57. size_t i;
  58. for (i = 0; i < buf_len; ++i)
  59. hash ^= ((unsigned long)buf[i]) << (8 * (i % sizeof(unsigned long)));
  60. return hash;
  61. }
  62. static unsigned long lcid_hash(const QUIC_LCID *lcid_obj)
  63. {
  64. return bin_hash(lcid_obj->cid.id, lcid_obj->cid.id_len);
  65. }
  66. static int lcid_comp(const QUIC_LCID *a, const QUIC_LCID *b)
  67. {
  68. return !ossl_quic_conn_id_eq(&a->cid, &b->cid);
  69. }
  70. static unsigned long lcidm_conn_hash(const QUIC_LCIDM_CONN *conn)
  71. {
  72. return (unsigned long)(uintptr_t)conn->opaque;
  73. }
  74. static int lcidm_conn_comp(const QUIC_LCIDM_CONN *a, const QUIC_LCIDM_CONN *b)
  75. {
  76. return a->opaque != b->opaque;
  77. }
  78. QUIC_LCIDM *ossl_quic_lcidm_new(OSSL_LIB_CTX *libctx, size_t lcid_len)
  79. {
  80. QUIC_LCIDM *lcidm = NULL;
  81. if (lcid_len > QUIC_MAX_CONN_ID_LEN)
  82. goto err;
  83. if ((lcidm = OPENSSL_zalloc(sizeof(*lcidm))) == NULL)
  84. goto err;
  85. if ((lcidm->lcids = lh_QUIC_LCID_new(lcid_hash, lcid_comp)) == NULL)
  86. goto err;
  87. if ((lcidm->conns = lh_QUIC_LCIDM_CONN_new(lcidm_conn_hash,
  88. lcidm_conn_comp)) == NULL)
  89. goto err;
  90. lcidm->libctx = libctx;
  91. lcidm->lcid_len = lcid_len;
  92. return lcidm;
  93. err:
  94. if (lcidm != NULL) {
  95. lh_QUIC_LCID_free(lcidm->lcids);
  96. lh_QUIC_LCIDM_CONN_free(lcidm->conns);
  97. OPENSSL_free(lcidm);
  98. }
  99. return NULL;
  100. }
  101. static void lcidm_delete_conn(QUIC_LCIDM *lcidm, QUIC_LCIDM_CONN *conn);
  102. static void lcidm_delete_conn_(QUIC_LCIDM_CONN *conn, void *arg)
  103. {
  104. lcidm_delete_conn((QUIC_LCIDM *)arg, conn);
  105. }
  106. void ossl_quic_lcidm_free(QUIC_LCIDM *lcidm)
  107. {
  108. if (lcidm == NULL)
  109. return;
  110. /*
  111. * Calling OPENSSL_lh_delete during a doall call is unsafe with our
  112. * current LHASH implementation for several reasons:
  113. *
  114. * - firstly, because deletes can cause the hashtable to be contracted,
  115. * resulting in rehashing which might cause items in later buckets to
  116. * move to earlier buckets, which might cause doall to skip an item,
  117. * resulting in a memory leak;
  118. *
  119. * - secondly, because doall in general is not safe across hashtable
  120. * size changes, as it caches hashtable size and pointer values
  121. * while operating.
  122. *
  123. * The fix for this is to disable hashtable contraction using the following
  124. * call, which guarantees that no rehashing will occur so long as we only
  125. * call delete and not insert.
  126. */
  127. lh_QUIC_LCIDM_CONN_set_down_load(lcidm->conns, 0);
  128. lh_QUIC_LCIDM_CONN_doall_arg(lcidm->conns, lcidm_delete_conn_, lcidm);
  129. lh_QUIC_LCID_free(lcidm->lcids);
  130. lh_QUIC_LCIDM_CONN_free(lcidm->conns);
  131. OPENSSL_free(lcidm);
  132. }
  133. static QUIC_LCID *lcidm_get0_lcid(const QUIC_LCIDM *lcidm, const QUIC_CONN_ID *lcid)
  134. {
  135. QUIC_LCID key;
  136. key.cid = *lcid;
  137. if (key.cid.id_len > QUIC_MAX_CONN_ID_LEN)
  138. return NULL;
  139. return lh_QUIC_LCID_retrieve(lcidm->lcids, &key);
  140. }
  141. static QUIC_LCIDM_CONN *lcidm_get0_conn(const QUIC_LCIDM *lcidm, void *opaque)
  142. {
  143. QUIC_LCIDM_CONN key;
  144. key.opaque = opaque;
  145. return lh_QUIC_LCIDM_CONN_retrieve(lcidm->conns, &key);
  146. }
  147. static QUIC_LCIDM_CONN *lcidm_upsert_conn(const QUIC_LCIDM *lcidm, void *opaque)
  148. {
  149. QUIC_LCIDM_CONN *conn = lcidm_get0_conn(lcidm, opaque);
  150. if (conn != NULL)
  151. return conn;
  152. if ((conn = OPENSSL_zalloc(sizeof(*conn))) == NULL)
  153. goto err;
  154. if ((conn->lcids = lh_QUIC_LCID_new(lcid_hash, lcid_comp)) == NULL)
  155. goto err;
  156. conn->opaque = opaque;
  157. lh_QUIC_LCIDM_CONN_insert(lcidm->conns, conn);
  158. if (lh_QUIC_LCIDM_CONN_error(lcidm->conns))
  159. goto err;
  160. return conn;
  161. err:
  162. if (conn != NULL) {
  163. lh_QUIC_LCID_free(conn->lcids);
  164. OPENSSL_free(conn);
  165. }
  166. return NULL;
  167. }
  168. static void lcidm_delete_conn_lcid(QUIC_LCIDM *lcidm, QUIC_LCID *lcid_obj)
  169. {
  170. lh_QUIC_LCID_delete(lcidm->lcids, lcid_obj);
  171. lh_QUIC_LCID_delete(lcid_obj->conn->lcids, lcid_obj);
  172. assert(lcid_obj->conn->num_active_lcid > 0);
  173. --lcid_obj->conn->num_active_lcid;
  174. OPENSSL_free(lcid_obj);
  175. }
  176. /* doall_arg wrapper */
  177. static void lcidm_delete_conn_lcid_(QUIC_LCID *lcid_obj, void *arg)
  178. {
  179. lcidm_delete_conn_lcid((QUIC_LCIDM *)arg, lcid_obj);
  180. }
  181. static void lcidm_delete_conn(QUIC_LCIDM *lcidm, QUIC_LCIDM_CONN *conn)
  182. {
  183. /* See comment in ossl_quic_lcidm_free */
  184. lh_QUIC_LCID_set_down_load(conn->lcids, 0);
  185. lh_QUIC_LCID_doall_arg(conn->lcids, lcidm_delete_conn_lcid_, lcidm);
  186. lh_QUIC_LCIDM_CONN_delete(lcidm->conns, conn);
  187. lh_QUIC_LCID_free(conn->lcids);
  188. OPENSSL_free(conn);
  189. }
  190. static QUIC_LCID *lcidm_conn_new_lcid(QUIC_LCIDM *lcidm, QUIC_LCIDM_CONN *conn,
  191. const QUIC_CONN_ID *lcid)
  192. {
  193. QUIC_LCID *lcid_obj = NULL;
  194. if (lcid->id_len > QUIC_MAX_CONN_ID_LEN)
  195. return NULL;
  196. if ((lcid_obj = OPENSSL_zalloc(sizeof(*lcid_obj))) == NULL)
  197. goto err;
  198. lcid_obj->cid = *lcid;
  199. lcid_obj->conn = conn;
  200. lh_QUIC_LCID_insert(conn->lcids, lcid_obj);
  201. if (lh_QUIC_LCID_error(conn->lcids))
  202. goto err;
  203. lh_QUIC_LCID_insert(lcidm->lcids, lcid_obj);
  204. if (lh_QUIC_LCID_error(lcidm->lcids)) {
  205. lh_QUIC_LCID_delete(conn->lcids, lcid_obj);
  206. goto err;
  207. }
  208. ++conn->num_active_lcid;
  209. return lcid_obj;
  210. err:
  211. OPENSSL_free(lcid_obj);
  212. return NULL;
  213. }
  214. size_t ossl_quic_lcidm_get_lcid_len(const QUIC_LCIDM *lcidm)
  215. {
  216. return lcidm->lcid_len;
  217. }
  218. size_t ossl_quic_lcidm_get_num_active_lcid(const QUIC_LCIDM *lcidm,
  219. void *opaque)
  220. {
  221. QUIC_LCIDM_CONN *conn;
  222. conn = lcidm_get0_conn(lcidm, opaque);
  223. if (conn == NULL)
  224. return 0;
  225. return conn->num_active_lcid;
  226. }
  227. static int lcidm_generate_cid(QUIC_LCIDM *lcidm,
  228. QUIC_CONN_ID *cid)
  229. {
  230. #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
  231. int i;
  232. lcidm->next_lcid.id_len = (unsigned char)lcidm->lcid_len;
  233. *cid = lcidm->next_lcid;
  234. for (i = lcidm->lcid_len - 1; i >= 0; --i)
  235. if (++lcidm->next_lcid.id[i] != 0)
  236. break;
  237. return 1;
  238. #else
  239. return ossl_quic_gen_rand_conn_id(lcidm->libctx, lcidm->lcid_len, cid);
  240. #endif
  241. }
  242. static int lcidm_generate(QUIC_LCIDM *lcidm,
  243. void *opaque,
  244. unsigned int type,
  245. QUIC_CONN_ID *lcid_out,
  246. uint64_t *seq_num)
  247. {
  248. QUIC_LCIDM_CONN *conn;
  249. QUIC_LCID key, *lcid_obj;
  250. size_t i;
  251. #define MAX_RETRIES 8
  252. if ((conn = lcidm_upsert_conn(lcidm, opaque)) == NULL)
  253. return 0;
  254. if ((type == LCID_TYPE_INITIAL && conn->next_seq_num > 0)
  255. || conn->next_seq_num > OSSL_QUIC_VLINT_MAX)
  256. return 0;
  257. i = 0;
  258. do {
  259. if (i++ >= MAX_RETRIES)
  260. /*
  261. * Too many retries; should not happen but if it does, don't loop
  262. * endlessly.
  263. */
  264. return 0;
  265. if (!lcidm_generate_cid(lcidm, lcid_out))
  266. return 0;
  267. key.cid = *lcid_out;
  268. /* If a collision occurs, retry. */
  269. } while (lh_QUIC_LCID_retrieve(lcidm->lcids, &key) != NULL);
  270. if ((lcid_obj = lcidm_conn_new_lcid(lcidm, conn, lcid_out)) == NULL)
  271. return 0;
  272. lcid_obj->seq_num = conn->next_seq_num;
  273. lcid_obj->type = type;
  274. if (seq_num != NULL)
  275. *seq_num = lcid_obj->seq_num;
  276. ++conn->next_seq_num;
  277. return 1;
  278. }
  279. int ossl_quic_lcidm_enrol_odcid(QUIC_LCIDM *lcidm,
  280. void *opaque,
  281. const QUIC_CONN_ID *initial_odcid)
  282. {
  283. QUIC_LCIDM_CONN *conn;
  284. QUIC_LCID key, *lcid_obj;
  285. if (initial_odcid == NULL || initial_odcid->id_len < QUIC_MIN_ODCID_LEN
  286. || initial_odcid->id_len > QUIC_MAX_CONN_ID_LEN)
  287. return 0;
  288. if ((conn = lcidm_upsert_conn(lcidm, opaque)) == NULL)
  289. return 0;
  290. if (conn->done_odcid)
  291. return 0;
  292. key.cid = *initial_odcid;
  293. if (lh_QUIC_LCID_retrieve(lcidm->lcids, &key) != NULL)
  294. return 0;
  295. if ((lcid_obj = lcidm_conn_new_lcid(lcidm, conn, initial_odcid)) == NULL)
  296. return 0;
  297. lcid_obj->seq_num = LCIDM_ODCID_SEQ_NUM;
  298. lcid_obj->type = LCID_TYPE_ODCID;
  299. conn->odcid_lcid_obj = lcid_obj;
  300. conn->done_odcid = 1;
  301. return 1;
  302. }
  303. int ossl_quic_lcidm_generate_initial(QUIC_LCIDM *lcidm,
  304. void *opaque,
  305. QUIC_CONN_ID *initial_lcid)
  306. {
  307. return lcidm_generate(lcidm, opaque, LCID_TYPE_INITIAL,
  308. initial_lcid, NULL);
  309. }
  310. int ossl_quic_lcidm_generate(QUIC_LCIDM *lcidm,
  311. void *opaque,
  312. OSSL_QUIC_FRAME_NEW_CONN_ID *ncid_frame)
  313. {
  314. ncid_frame->seq_num = 0;
  315. ncid_frame->retire_prior_to = 0;
  316. return lcidm_generate(lcidm, opaque, LCID_TYPE_NCID,
  317. &ncid_frame->conn_id,
  318. &ncid_frame->seq_num);
  319. }
  320. int ossl_quic_lcidm_retire_odcid(QUIC_LCIDM *lcidm, void *opaque)
  321. {
  322. QUIC_LCIDM_CONN *conn;
  323. if ((conn = lcidm_upsert_conn(lcidm, opaque)) == NULL)
  324. return 0;
  325. if (conn->odcid_lcid_obj == NULL)
  326. return 0;
  327. lcidm_delete_conn_lcid(lcidm, conn->odcid_lcid_obj);
  328. conn->odcid_lcid_obj = NULL;
  329. return 1;
  330. }
  331. struct retire_args {
  332. QUIC_LCID *earliest_seq_num_lcid_obj;
  333. uint64_t earliest_seq_num, retire_prior_to;
  334. };
  335. static void retire_for_conn(QUIC_LCID *lcid_obj, void *arg)
  336. {
  337. struct retire_args *args = arg;
  338. /* ODCID LCID cannot be retired via this API */
  339. if (lcid_obj->type == LCID_TYPE_ODCID
  340. || lcid_obj->seq_num >= args->retire_prior_to)
  341. return;
  342. if (lcid_obj->seq_num < args->earliest_seq_num) {
  343. args->earliest_seq_num = lcid_obj->seq_num;
  344. args->earliest_seq_num_lcid_obj = lcid_obj;
  345. }
  346. }
  347. int ossl_quic_lcidm_retire(QUIC_LCIDM *lcidm,
  348. void *opaque,
  349. uint64_t retire_prior_to,
  350. const QUIC_CONN_ID *containing_pkt_dcid,
  351. QUIC_CONN_ID *retired_lcid,
  352. uint64_t *retired_seq_num,
  353. int *did_retire)
  354. {
  355. QUIC_LCIDM_CONN key, *conn;
  356. struct retire_args args = {0};
  357. key.opaque = opaque;
  358. if (did_retire == NULL)
  359. return 0;
  360. *did_retire = 0;
  361. if ((conn = lh_QUIC_LCIDM_CONN_retrieve(lcidm->conns, &key)) == NULL)
  362. return 1;
  363. args.retire_prior_to = retire_prior_to;
  364. args.earliest_seq_num = UINT64_MAX;
  365. lh_QUIC_LCID_doall_arg(conn->lcids, retire_for_conn, &args);
  366. if (args.earliest_seq_num_lcid_obj == NULL)
  367. return 1;
  368. if (containing_pkt_dcid != NULL
  369. && ossl_quic_conn_id_eq(&args.earliest_seq_num_lcid_obj->cid,
  370. containing_pkt_dcid))
  371. return 0;
  372. *did_retire = 1;
  373. if (retired_lcid != NULL)
  374. *retired_lcid = args.earliest_seq_num_lcid_obj->cid;
  375. if (retired_seq_num != NULL)
  376. *retired_seq_num = args.earliest_seq_num_lcid_obj->seq_num;
  377. lcidm_delete_conn_lcid(lcidm, args.earliest_seq_num_lcid_obj);
  378. return 1;
  379. }
  380. int ossl_quic_lcidm_cull(QUIC_LCIDM *lcidm, void *opaque)
  381. {
  382. QUIC_LCIDM_CONN key, *conn;
  383. key.opaque = opaque;
  384. if ((conn = lh_QUIC_LCIDM_CONN_retrieve(lcidm->conns, &key)) == NULL)
  385. return 0;
  386. lcidm_delete_conn(lcidm, conn);
  387. return 1;
  388. }
  389. int ossl_quic_lcidm_lookup(QUIC_LCIDM *lcidm,
  390. const QUIC_CONN_ID *lcid,
  391. uint64_t *seq_num,
  392. void **opaque)
  393. {
  394. QUIC_LCID *lcid_obj;
  395. if (lcid == NULL)
  396. return 0;
  397. if ((lcid_obj = lcidm_get0_lcid(lcidm, lcid)) == NULL)
  398. return 0;
  399. if (seq_num != NULL)
  400. *seq_num = lcid_obj->seq_num;
  401. if (opaque != NULL)
  402. *opaque = lcid_obj->conn->opaque;
  403. return 1;
  404. }
  405. int ossl_quic_lcidm_debug_remove(QUIC_LCIDM *lcidm,
  406. const QUIC_CONN_ID *lcid)
  407. {
  408. QUIC_LCID key, *lcid_obj;
  409. key.cid = *lcid;
  410. if ((lcid_obj = lh_QUIC_LCID_retrieve(lcidm->lcids, &key)) == NULL)
  411. return 0;
  412. lcidm_delete_conn_lcid(lcidm, lcid_obj);
  413. return 1;
  414. }
  415. int ossl_quic_lcidm_debug_add(QUIC_LCIDM *lcidm, void *opaque,
  416. const QUIC_CONN_ID *lcid,
  417. uint64_t seq_num)
  418. {
  419. QUIC_LCIDM_CONN *conn;
  420. QUIC_LCID key, *lcid_obj;
  421. if (lcid == NULL || lcid->id_len > QUIC_MAX_CONN_ID_LEN)
  422. return 0;
  423. if ((conn = lcidm_upsert_conn(lcidm, opaque)) == NULL)
  424. return 0;
  425. key.cid = *lcid;
  426. if (lh_QUIC_LCID_retrieve(lcidm->lcids, &key) != NULL)
  427. return 0;
  428. if ((lcid_obj = lcidm_conn_new_lcid(lcidm, conn, lcid)) == NULL)
  429. return 0;
  430. lcid_obj->seq_num = seq_num;
  431. lcid_obj->type = LCID_TYPE_NCID;
  432. return 1;
  433. }