Preliminary support for compressed certificates.
This change adds server-side support for compressed certificates.
(Although some definitions for client-side support are included in the
headers, there's no code behind them yet.)
Change-Id: I0f98abf0b782b7337ddd014c58e19e6b8cc5a3c2
Reviewed-on: https://boringssl-review.googlesource.com/27964
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/ssl/t1_lib.cc b/ssl/t1_lib.cc
index 40b7ff0..4687f52 100644
--- a/ssl/t1_lib.cc
+++ b/ssl/t1_lib.cc
@@ -2761,6 +2761,93 @@
return true;
}
+// Certificate compression
+
+static bool cert_compression_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+ return true;
+}
+
+static bool cert_compression_parse_serverhello(SSL_HANDSHAKE *hs,
+ uint8_t *out_alert,
+ CBS *contents) {
+ if (contents == nullptr) {
+ return true;
+ }
+
+ // The server may not echo this extension. Any server to client negotiation is
+ // advertised in the CertificateRequest message.
+ return false;
+}
+
+static bool cert_compression_parse_clienthello(SSL_HANDSHAKE *hs,
+ uint8_t *out_alert,
+ CBS *contents) {
+ if (contents == nullptr) {
+ return true;
+ }
+
+ const size_t num_algs =
+ sk_CertCompressionAlg_num(hs->ssl->ctx->cert_compression_algs);
+
+ CBS alg_ids;
+ if (!CBS_get_u8_length_prefixed(contents, &alg_ids) ||
+ CBS_len(contents) != 0 ||
+ CBS_len(&alg_ids) == 0 ||
+ CBS_len(&alg_ids) % 2 == 1) {
+ return false;
+ }
+
+ const size_t num_given_alg_ids = CBS_len(&alg_ids) / 2;
+ Array<uint16_t> given_alg_ids;
+ if (!given_alg_ids.Init(num_given_alg_ids)) {
+ return false;
+ }
+
+ size_t best_index = num_algs;
+ size_t given_alg_idx = 0;
+
+ while (CBS_len(&alg_ids) > 0) {
+ uint16_t alg_id;
+ if (!CBS_get_u16(&alg_ids, &alg_id)) {
+ return false;
+ }
+
+ given_alg_ids[given_alg_idx++] = alg_id;
+
+ for (size_t i = 0; i < num_algs; i++) {
+ const auto *alg =
+ sk_CertCompressionAlg_value(hs->ssl->ctx->cert_compression_algs, i);
+ if (alg->alg_id == alg_id && alg->compress != nullptr) {
+ if (i < best_index) {
+ best_index = i;
+ }
+ break;
+ }
+ }
+ }
+
+ qsort(given_alg_ids.data(), given_alg_ids.size(), sizeof(uint16_t),
+ compare_uint16_t);
+ for (size_t i = 1; i < num_given_alg_ids; i++) {
+ if (given_alg_ids[i - 1] == given_alg_ids[i]) {
+ return false;
+ }
+ }
+
+ if (best_index < num_algs &&
+ ssl_protocol_version(hs->ssl) >= TLS1_3_VERSION) {
+ hs->cert_compression_negotiated = true;
+ hs->cert_compression_alg_id =
+ sk_CertCompressionAlg_value(hs->ssl->ctx->cert_compression_algs,
+ best_index)->alg_id;
+ }
+
+ return true;
+}
+
+static bool cert_compression_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
+ return true;
+}
// kExtensions contains all the supported extensions.
static const struct tls_extension kExtensions[] = {
@@ -2945,6 +3032,14 @@
ext_token_binding_parse_clienthello,
ext_token_binding_add_serverhello,
},
+ {
+ TLSEXT_TYPE_cert_compression,
+ NULL,
+ cert_compression_add_clienthello,
+ cert_compression_parse_serverhello,
+ cert_compression_parse_clienthello,
+ cert_compression_add_serverhello,
+ },
};
#define kNumExtensions (sizeof(kExtensions) / sizeof(struct tls_extension))