ssl_cert_comp.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. /*
  2. * Copyright 2022 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 <stdio.h>
  10. #include "ssl_local.h"
  11. #include "internal/e_os.h"
  12. #include "internal/refcount.h"
  13. size_t ossl_calculate_comp_expansion(int alg, size_t length)
  14. {
  15. size_t ret;
  16. /*
  17. * Uncompressibility expansion:
  18. * ZLIB: N + 11 + 5 * (N >> 14)
  19. * Brotli: per RFC7932: N + 5 + 3 * (N >> 16)
  20. * ZSTD: N + 4 + 14 + 3 * (N >> 17) + 4
  21. */
  22. switch (alg) {
  23. case TLSEXT_comp_cert_zlib:
  24. ret = length + 11 + 5 * (length >> 14);
  25. break;
  26. case TLSEXT_comp_cert_brotli:
  27. ret = length + 5 + 3 * (length >> 16);
  28. break;
  29. case TLSEXT_comp_cert_zstd:
  30. ret = length + 22 + 3 * (length >> 17);
  31. break;
  32. default:
  33. return 0;
  34. }
  35. /* Check for overflow */
  36. if (ret < length)
  37. return 0;
  38. return ret;
  39. }
  40. int ossl_comp_has_alg(int a)
  41. {
  42. #ifndef OPENSSL_NO_COMP_ALG
  43. /* 0 means "any" algorithm */
  44. if ((a == 0 || a == TLSEXT_comp_cert_brotli) && BIO_f_brotli() != NULL)
  45. return 1;
  46. if ((a == 0 || a == TLSEXT_comp_cert_zstd) && BIO_f_zstd() != NULL)
  47. return 1;
  48. if ((a == 0 || a == TLSEXT_comp_cert_zlib) && BIO_f_zlib() != NULL)
  49. return 1;
  50. #endif
  51. return 0;
  52. }
  53. /* New operation Helper routine */
  54. #ifndef OPENSSL_NO_COMP_ALG
  55. static OSSL_COMP_CERT *OSSL_COMP_CERT_new(unsigned char *data, size_t len, size_t orig_len, int alg)
  56. {
  57. OSSL_COMP_CERT *ret = NULL;
  58. if (!ossl_comp_has_alg(alg)
  59. || data == NULL
  60. || (ret = OPENSSL_zalloc(sizeof(*ret))) == NULL
  61. || (ret->lock = CRYPTO_THREAD_lock_new()) == NULL)
  62. goto err;
  63. ret->references = 1;
  64. ret->data = data;
  65. ret->len = len;
  66. ret->orig_len = orig_len;
  67. ret->alg = alg;
  68. return ret;
  69. err:
  70. ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
  71. OPENSSL_free(data);
  72. OPENSSL_free(ret);
  73. return NULL;
  74. }
  75. __owur static OSSL_COMP_CERT *OSSL_COMP_CERT_from_compressed_data(unsigned char *data, size_t len,
  76. size_t orig_len, int alg)
  77. {
  78. return OSSL_COMP_CERT_new(OPENSSL_memdup(data, len), len, orig_len, alg);
  79. }
  80. __owur static OSSL_COMP_CERT *OSSL_COMP_CERT_from_uncompressed_data(unsigned char *data, size_t len,
  81. int alg)
  82. {
  83. OSSL_COMP_CERT *ret = NULL;
  84. size_t max_length;
  85. int comp_length;
  86. COMP_METHOD *method;
  87. unsigned char *comp_data = NULL;
  88. COMP_CTX *comp_ctx = NULL;
  89. switch (alg) {
  90. case TLSEXT_comp_cert_brotli:
  91. method = COMP_brotli_oneshot();
  92. break;
  93. case TLSEXT_comp_cert_zlib:
  94. method = COMP_zlib_oneshot();
  95. break;
  96. case TLSEXT_comp_cert_zstd:
  97. method = COMP_zstd_oneshot();
  98. break;
  99. default:
  100. goto err;
  101. }
  102. if ((max_length = ossl_calculate_comp_expansion(alg, len)) == 0
  103. || method == NULL
  104. || (comp_ctx = COMP_CTX_new(method)) == NULL
  105. || (comp_data = OPENSSL_zalloc(max_length)) == NULL)
  106. goto err;
  107. comp_length = COMP_compress_block(comp_ctx, comp_data, max_length, data, len);
  108. if (comp_length <= 0)
  109. goto err;
  110. ret = OSSL_COMP_CERT_new(comp_data, comp_length, len, alg);
  111. comp_data = NULL;
  112. err:
  113. OPENSSL_free(comp_data);
  114. COMP_CTX_free(comp_ctx);
  115. return ret;
  116. }
  117. void OSSL_COMP_CERT_free(OSSL_COMP_CERT *cc)
  118. {
  119. int i;
  120. if (cc == NULL)
  121. return;
  122. CRYPTO_DOWN_REF(&cc->references, &i, cc->lock);
  123. REF_PRINT_COUNT("OSSL_COMP_CERT", cc);
  124. if (i > 0)
  125. return;
  126. REF_ASSERT_ISNT(i < 0);
  127. OPENSSL_free(cc->data);
  128. CRYPTO_THREAD_lock_free(cc->lock);
  129. OPENSSL_free(cc);
  130. }
  131. int OSSL_COMP_CERT_up_ref(OSSL_COMP_CERT *cc)
  132. {
  133. int i;
  134. if (CRYPTO_UP_REF(&cc->references, &i, cc->lock) <= 0)
  135. return 0;
  136. REF_PRINT_COUNT("OSSL_COMP_CERT", cc);
  137. REF_ASSERT_ISNT(i < 2);
  138. return ((i > 1) ? 1 : 0);
  139. }
  140. static int ssl_set_cert_comp_pref(int *prefs, int *algs, size_t len)
  141. {
  142. size_t j = 0;
  143. size_t i;
  144. int found = 0;
  145. int already_set[TLSEXT_comp_cert_limit];
  146. int tmp_prefs[TLSEXT_comp_cert_limit];
  147. /* Note that |len| is the number of |algs| elements */
  148. /* clear all algorithms */
  149. if (len == 0 || algs == NULL) {
  150. memset(prefs, 0, sizeof(tmp_prefs));
  151. return 1;
  152. }
  153. /* This will 0-terminate the array */
  154. memset(tmp_prefs, 0, sizeof(tmp_prefs));
  155. memset(already_set, 0, sizeof(already_set));
  156. /* Include only those algorithms we support, ignoring duplicates and unknowns */
  157. for (i = 0; i < len; i++) {
  158. if (algs[i] != 0 && ossl_comp_has_alg(algs[i])) {
  159. /* Check for duplicate */
  160. if (already_set[algs[i]])
  161. return 0;
  162. tmp_prefs[j++] = algs[i];
  163. already_set[algs[i]] = 1;
  164. found = 1;
  165. }
  166. }
  167. if (found)
  168. memcpy(prefs, tmp_prefs, sizeof(tmp_prefs));
  169. return found;
  170. }
  171. static size_t ssl_get_cert_to_compress(SSL *ssl, CERT_PKEY *cpk, unsigned char **data)
  172. {
  173. SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(ssl);
  174. WPACKET tmppkt;
  175. BUF_MEM buf = { 0 };
  176. size_t ret = 0;
  177. if (sc == NULL
  178. || cpk == NULL
  179. || !sc->server
  180. || !SSL_in_before(ssl))
  181. return 0;
  182. /* Use the |tmppkt| for the to-be-compressed data */
  183. if (!WPACKET_init(&tmppkt, &buf))
  184. goto out;
  185. /* no context present, add 0-length context */
  186. if (!WPACKET_put_bytes_u8(&tmppkt, 0))
  187. goto out;
  188. /*
  189. * ssl3_output_cert_chain() may generate an SSLfatal() error,
  190. * for this case, we want to ignore it, argument for_comp = 1
  191. */
  192. if (!ssl3_output_cert_chain(sc, &tmppkt, cpk, 1))
  193. goto out;
  194. WPACKET_get_total_written(&tmppkt, &ret);
  195. out:
  196. WPACKET_cleanup(&tmppkt);
  197. if (ret != 0 && data != NULL)
  198. *data = (unsigned char *)buf.data;
  199. else
  200. OPENSSL_free(buf.data);
  201. return ret;
  202. }
  203. static int ssl_compress_one_cert(SSL *ssl, CERT_PKEY *cpk, int alg)
  204. {
  205. unsigned char *cert_data = NULL;
  206. OSSL_COMP_CERT *comp_cert = NULL;
  207. size_t length;
  208. if (cpk == NULL
  209. || alg == TLSEXT_comp_cert_none
  210. || !ossl_comp_has_alg(alg))
  211. return 0;
  212. if ((length = ssl_get_cert_to_compress(ssl, cpk, &cert_data)) == 0)
  213. return 0;
  214. comp_cert = OSSL_COMP_CERT_from_uncompressed_data(cert_data, length, alg);
  215. OPENSSL_free(cert_data);
  216. if (comp_cert == NULL)
  217. return 0;
  218. OSSL_COMP_CERT_free(cpk->comp_cert[alg]);
  219. cpk->comp_cert[alg] = comp_cert;
  220. return 1;
  221. }
  222. /* alg_in can be 0, meaning any/all algorithms */
  223. static int ssl_compress_certs(SSL *ssl, CERT_PKEY *cpks, int alg_in)
  224. {
  225. SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(ssl);
  226. int i;
  227. int j;
  228. int alg;
  229. int count = 0;
  230. if (sc == NULL
  231. || cpks == NULL
  232. || !ossl_comp_has_alg(alg_in))
  233. return 0;
  234. /* Look through the preferences to see what we have */
  235. for (i = 0; i < TLSEXT_comp_cert_limit; i++) {
  236. /*
  237. * alg = 0 means compress for everything, but only for algorithms enabled
  238. * alg != 0 means compress for that algorithm if enabled
  239. */
  240. alg = sc->cert_comp_prefs[i];
  241. if ((alg_in == 0 && alg != TLSEXT_comp_cert_none)
  242. || (alg_in != 0 && alg == alg_in)) {
  243. for (j = 0; j < SSL_PKEY_NUM; j++) {
  244. /* No cert, move on */
  245. if (cpks[j].x509 == NULL)
  246. continue;
  247. if (!ssl_compress_one_cert(ssl, &cpks[j], alg))
  248. return 0;
  249. /* if the cert expanded, set the value in the CERT_PKEY to NULL */
  250. if (cpks[j].comp_cert[alg]->len >= cpks[j].comp_cert[alg]->orig_len) {
  251. OSSL_COMP_CERT_free(cpks[j].comp_cert[alg]);
  252. cpks[j].comp_cert[alg] = NULL;
  253. } else {
  254. count++;
  255. }
  256. }
  257. }
  258. }
  259. return (count > 0);
  260. }
  261. static size_t ssl_get_compressed_cert(SSL *ssl, CERT_PKEY *cpk, int alg, unsigned char **data,
  262. size_t *orig_len)
  263. {
  264. SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(ssl);
  265. size_t cert_len = 0;
  266. size_t comp_len = 0;
  267. unsigned char *cert_data = NULL;
  268. OSSL_COMP_CERT *comp_cert = NULL;
  269. if (sc == NULL
  270. || cpk == NULL
  271. || data == NULL
  272. || orig_len == NULL
  273. || !sc->server
  274. || !SSL_in_before(ssl)
  275. || !ossl_comp_has_alg(alg))
  276. return 0;
  277. if ((cert_len = ssl_get_cert_to_compress(ssl, cpk, &cert_data)) == 0)
  278. goto err;
  279. comp_cert = OSSL_COMP_CERT_from_uncompressed_data(cert_data, cert_len, alg);
  280. OPENSSL_free(cert_data);
  281. if (comp_cert == NULL)
  282. goto err;
  283. comp_len = comp_cert->len;
  284. *orig_len = comp_cert->orig_len;
  285. *data = comp_cert->data;
  286. comp_cert->data = NULL;
  287. err:
  288. OSSL_COMP_CERT_free(comp_cert);
  289. return comp_len;
  290. }
  291. static int ossl_set1_compressed_cert(CERT *cert, int algorithm,
  292. unsigned char *comp_data, size_t comp_length,
  293. size_t orig_length)
  294. {
  295. OSSL_COMP_CERT *comp_cert;
  296. /* No explicit cert set */
  297. if (cert == NULL || cert->key == NULL)
  298. return 0;
  299. comp_cert = OSSL_COMP_CERT_from_compressed_data(comp_data, comp_length,
  300. orig_length, algorithm);
  301. if (comp_cert == NULL)
  302. return 0;
  303. OSSL_COMP_CERT_free(cert->key->comp_cert[algorithm]);
  304. cert->key->comp_cert[algorithm] = comp_cert;
  305. return 1;
  306. }
  307. #endif
  308. /*-
  309. * Public API
  310. */
  311. int SSL_CTX_set1_cert_comp_preference(SSL_CTX *ctx, int *algs, size_t len)
  312. {
  313. #ifndef OPENSSL_NO_COMP_ALG
  314. return ssl_set_cert_comp_pref(ctx->cert_comp_prefs, algs, len);
  315. #else
  316. return 0;
  317. #endif
  318. }
  319. int SSL_set1_cert_comp_preference(SSL *ssl, int *algs, size_t len)
  320. {
  321. #ifndef OPENSSL_NO_COMP_ALG
  322. SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(ssl);
  323. if (sc == NULL)
  324. return 0;
  325. return ssl_set_cert_comp_pref(sc->cert_comp_prefs, algs, len);
  326. #else
  327. return 0;
  328. #endif
  329. }
  330. int SSL_compress_certs(SSL *ssl, int alg)
  331. {
  332. #ifndef OPENSSL_NO_COMP_ALG
  333. SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(ssl);
  334. if (sc == NULL || sc->cert == NULL)
  335. return 0;
  336. return ssl_compress_certs(ssl, sc->cert->pkeys, alg);
  337. #endif
  338. return 0;
  339. }
  340. int SSL_CTX_compress_certs(SSL_CTX *ctx, int alg)
  341. {
  342. int ret = 0;
  343. #ifndef OPENSSL_NO_COMP_ALG
  344. SSL *new = SSL_new(ctx);
  345. if (new == NULL)
  346. return 0;
  347. ret = ssl_compress_certs(new, ctx->cert->pkeys, alg);
  348. SSL_free(new);
  349. #endif
  350. return ret;
  351. }
  352. size_t SSL_get1_compressed_cert(SSL *ssl, int alg, unsigned char **data, size_t *orig_len)
  353. {
  354. #ifndef OPENSSL_NO_COMP_ALG
  355. SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(ssl);
  356. CERT_PKEY *cpk = NULL;
  357. if (sc->cert != NULL)
  358. cpk = sc->cert->key;
  359. else
  360. cpk = ssl->ctx->cert->key;
  361. return ssl_get_compressed_cert(ssl, cpk, alg, data, orig_len);
  362. #else
  363. return 0;
  364. #endif
  365. }
  366. size_t SSL_CTX_get1_compressed_cert(SSL_CTX *ctx, int alg, unsigned char **data, size_t *orig_len)
  367. {
  368. #ifndef OPENSSL_NO_COMP_ALG
  369. size_t ret;
  370. SSL *new = SSL_new(ctx);
  371. ret = ssl_get_compressed_cert(new, ctx->cert->key, alg, data, orig_len);
  372. SSL_free(new);
  373. return ret;
  374. #else
  375. return 0;
  376. #endif
  377. }
  378. int SSL_CTX_set1_compressed_cert(SSL_CTX *ctx, int algorithm, unsigned char *comp_data,
  379. size_t comp_length, size_t orig_length)
  380. {
  381. #ifndef OPENSSL_NO_COMP_ALG
  382. return ossl_set1_compressed_cert(ctx->cert, algorithm, comp_data, comp_length, orig_length);
  383. #else
  384. return 0;
  385. #endif
  386. }
  387. int SSL_set1_compressed_cert(SSL *ssl, int algorithm, unsigned char *comp_data,
  388. size_t comp_length, size_t orig_length)
  389. {
  390. #ifndef OPENSSL_NO_COMP_ALG
  391. SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(ssl);
  392. /* Cannot set a pre-compressed certificate on a client */
  393. if (sc == NULL || !sc->server)
  394. return 0;
  395. return ossl_set1_compressed_cert(sc->cert, algorithm, comp_data, comp_length, orig_length);
  396. #else
  397. return 0;
  398. #endif
  399. }