certificate_compression.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /*
  2. * Copyright (c) 2018 Fastly
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy
  5. * of this software and associated documentation files (the "Software"), to
  6. * deal in the Software without restriction, including without limitation the
  7. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. * sell copies of the Software, and to permit persons to whom the Software is
  9. * furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. * IN THE SOFTWARE.
  21. */
  22. #include <assert.h>
  23. #include <stdlib.h>
  24. #include "brotli/decode.h"
  25. #include "brotli/encode.h"
  26. #include "picotls/certificate_compression.h"
  27. static inline int decompress_certificate(ptls_decompress_certificate_t *self, ptls_t *tls, uint16_t algorithm, ptls_iovec_t output,
  28. ptls_iovec_t input)
  29. {
  30. if (algorithm != PTLS_CERTIFICATE_COMPRESSION_ALGORITHM_BROTLI)
  31. goto Fail;
  32. size_t decoded_size = output.len;
  33. if (BrotliDecoderDecompress(input.len, input.base, &decoded_size, output.base) != BROTLI_DECODER_RESULT_SUCCESS)
  34. goto Fail;
  35. if (decoded_size != output.len)
  36. goto Fail;
  37. return 0;
  38. Fail:
  39. return PTLS_ALERT_BAD_CERTIFICATE;
  40. }
  41. static const uint16_t algorithms[] = {PTLS_CERTIFICATE_COMPRESSION_ALGORITHM_BROTLI, UINT16_MAX};
  42. ptls_decompress_certificate_t ptls_decompress_certificate = {algorithms, decompress_certificate};
  43. static int emit_compressed_certificate(ptls_emit_certificate_t *_self, ptls_t *tls, ptls_message_emitter_t *emitter,
  44. ptls_key_schedule_t *key_sched, ptls_iovec_t context, int push_status_request,
  45. const uint16_t *compress_algos, size_t num_compress_algos)
  46. {
  47. ptls_emit_compressed_certificate_t *self = (void *)_self;
  48. struct st_ptls_compressed_certificate_entry_t *entry;
  49. int ret;
  50. assert(context.len == 0 || !"precompressed mode can only be used for server certificates");
  51. for (size_t i = 0; i != num_compress_algos; ++i) {
  52. if (compress_algos[i] == PTLS_CERTIFICATE_COMPRESSION_ALGORITHM_BROTLI)
  53. goto FoundBrotli;
  54. }
  55. /* brotli not found, delegate to the core */
  56. ret = PTLS_ERROR_DELEGATE;
  57. goto Exit;
  58. FoundBrotli:
  59. entry = &self->without_ocsp_status;
  60. if (push_status_request && self->with_ocsp_status.uncompressed_length != 0)
  61. entry = &self->with_ocsp_status;
  62. ptls_push_message(emitter, key_sched, PTLS_HANDSHAKE_TYPE_COMPRESSED_CERTIFICATE, {
  63. ptls_buffer_push16(emitter->buf, PTLS_CERTIFICATE_COMPRESSION_ALGORITHM_BROTLI);
  64. ptls_buffer_push24(emitter->buf, entry->uncompressed_length);
  65. ptls_buffer_push_block(emitter->buf, 3, { ptls_buffer_pushv(emitter->buf, entry->bytes.base, entry->bytes.len); });
  66. });
  67. ret = 0;
  68. Exit:
  69. return ret;
  70. }
  71. static int build_compressed(struct st_ptls_compressed_certificate_entry_t *entry, ptls_iovec_t *certificates,
  72. size_t num_certificates, ptls_iovec_t ocsp_status)
  73. {
  74. ptls_buffer_t uncompressed;
  75. int ret;
  76. ptls_buffer_init(&uncompressed, "", 0);
  77. /* build uncompressed */
  78. if ((ret = ptls_build_certificate_message(&uncompressed, ptls_iovec_init(NULL, 0), certificates, num_certificates,
  79. ocsp_status)) != 0)
  80. goto Exit;
  81. entry->uncompressed_length = (uint32_t)uncompressed.off;
  82. /* compress */
  83. entry->bytes.len = uncompressed.off - 1;
  84. if ((entry->bytes.base = malloc(entry->bytes.len)) == NULL) {
  85. ret = PTLS_ERROR_NO_MEMORY;
  86. goto Exit;
  87. }
  88. if (BrotliEncoderCompress(BROTLI_MAX_QUALITY, BROTLI_DEFAULT_WINDOW, BROTLI_MODE_GENERIC, uncompressed.off, uncompressed.base,
  89. &entry->bytes.len, entry->bytes.base) != BROTLI_TRUE) {
  90. ret = PTLS_ERROR_COMPRESSION_FAILURE;
  91. goto Exit;
  92. }
  93. ret = 0;
  94. Exit:
  95. if (ret != 0) {
  96. free(entry->bytes.base);
  97. *entry = (struct st_ptls_compressed_certificate_entry_t){0};
  98. }
  99. ptls_buffer_dispose(&uncompressed);
  100. return ret;
  101. }
  102. int ptls_init_compressed_certificate(ptls_emit_compressed_certificate_t *self, ptls_iovec_t *certificates, size_t num_certificates,
  103. ptls_iovec_t ocsp_status)
  104. {
  105. int ret;
  106. *self = (ptls_emit_compressed_certificate_t){{emit_compressed_certificate}, PTLS_CERTIFICATE_COMPRESSION_ALGORITHM_BROTLI};
  107. /* build entries */
  108. if ((ret = build_compressed(&self->without_ocsp_status, certificates, num_certificates, ptls_iovec_init(NULL, 0))) != 0)
  109. goto Exit;
  110. if (ocsp_status.len != 0) {
  111. if ((ret = build_compressed(&self->with_ocsp_status, certificates, num_certificates, ocsp_status)) != 0)
  112. goto Exit;
  113. }
  114. ret = 0;
  115. Exit:
  116. if (ret != 0)
  117. ptls_dispose_compressed_certificate(self);
  118. return ret;
  119. }
  120. void ptls_dispose_compressed_certificate(ptls_emit_compressed_certificate_t *self)
  121. {
  122. free(self->with_ocsp_status.bytes.base);
  123. free(self->without_ocsp_status.bytes.base);
  124. }