lsquic_crt_compress.c revision b93f59be
150aadb33SDmitri Tikhonov/* Copyright (c) 2017 LiteSpeed Technologies Inc.  See LICENSE. */
250aadb33SDmitri Tikhonov#include <assert.h>
350aadb33SDmitri Tikhonov#include <stdbool.h>
450aadb33SDmitri Tikhonov#include <string.h>
550aadb33SDmitri Tikhonov#include <time.h>
650aadb33SDmitri Tikhonov#include <zlib.h>
750aadb33SDmitri Tikhonov
850aadb33SDmitri Tikhonov#include <openssl/ssl.h>
9461e84d8SAmol Deshpande#ifndef WIN32
10461e84d8SAmol Deshpande#else
11461e84d8SAmol Deshpande#include <stdlib.h>
12461e84d8SAmol Deshpande#include <vc_compat.h>
13461e84d8SAmol Deshpande#endif
1450aadb33SDmitri Tikhonov
1550aadb33SDmitri Tikhonov#include "lsquic_int_types.h"
1650aadb33SDmitri Tikhonov#include "lsquic_crypto.h"
1750aadb33SDmitri Tikhonov#include "lsquic_crt_compress.h"
1850aadb33SDmitri Tikhonov#include "lsquic_util.h"
1950aadb33SDmitri Tikhonov
2050aadb33SDmitri Tikhonov#include "lsquic_str.h"
2150aadb33SDmitri Tikhonov
2250aadb33SDmitri Tikhonov#include "common_cert_set_2.c"
2350aadb33SDmitri Tikhonov#include "common_cert_set_3.c"
2450aadb33SDmitri Tikhonov
2550aadb33SDmitri Tikhonov/*
2650aadb33SDmitri Tikhonov * common_cert_sub_strings contains ~1500 bytes of common certificate substrings
2750aadb33SDmitri Tikhonov * as a dictionary of zlib from the Alexa Top 5000 set.
2850aadb33SDmitri Tikhonov */
2950aadb33SDmitri Tikhonovstatic const unsigned char common_cert_sub_strings[] = {
3050aadb33SDmitri Tikhonov    0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04,
3150aadb33SDmitri Tikhonov    0x16, 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03,
3250aadb33SDmitri Tikhonov    0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30,
3350aadb33SDmitri Tikhonov    0x5f, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x04, 0x01,
3450aadb33SDmitri Tikhonov    0x06, 0x06, 0x0b, 0x60, 0x86, 0x48, 0x01, 0x86, 0xfd, 0x6d, 0x01, 0x07,
3550aadb33SDmitri Tikhonov    0x17, 0x01, 0x30, 0x33, 0x20, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65,
3650aadb33SDmitri Tikhonov    0x64, 0x20, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e,
3750aadb33SDmitri Tikhonov    0x20, 0x53, 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x31, 0x34,
3850aadb33SDmitri Tikhonov    0x20, 0x53, 0x53, 0x4c, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31,
3950aadb33SDmitri Tikhonov    0x32, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x53, 0x65, 0x72,
4050aadb33SDmitri Tikhonov    0x76, 0x65, 0x72, 0x20, 0x43, 0x41, 0x30, 0x2d, 0x61, 0x69, 0x61, 0x2e,
4150aadb33SDmitri Tikhonov    0x76, 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d,
4250aadb33SDmitri Tikhonov    0x2f, 0x45, 0x2d, 0x63, 0x72, 0x6c, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x73,
4350aadb33SDmitri Tikhonov    0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x45, 0x2e, 0x63, 0x65,
4450aadb33SDmitri Tikhonov    0x72, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
4550aadb33SDmitri Tikhonov    0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x4a, 0x2e, 0x63,
4650aadb33SDmitri Tikhonov    0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
4750aadb33SDmitri Tikhonov    0x2f, 0x63, 0x70, 0x73, 0x20, 0x28, 0x63, 0x29, 0x30, 0x30, 0x09, 0x06,
4850aadb33SDmitri Tikhonov    0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x30, 0x0d,
4950aadb33SDmitri Tikhonov    0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05,
5050aadb33SDmitri Tikhonov    0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x7b, 0x30, 0x1d, 0x06, 0x03, 0x55,
5150aadb33SDmitri Tikhonov    0x1d, 0x0e, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
5250aadb33SDmitri Tikhonov    0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01,
5350aadb33SDmitri Tikhonov    0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xd2,
5450aadb33SDmitri Tikhonov    0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x2e,
5550aadb33SDmitri Tikhonov    0x63, 0x72, 0x6c, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16,
5650aadb33SDmitri Tikhonov    0x04, 0x14, 0xb4, 0x2e, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x69,
5750aadb33SDmitri Tikhonov    0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x30, 0x0b, 0x06, 0x03,
5850aadb33SDmitri Tikhonov    0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x01, 0x30, 0x0d, 0x06, 0x09,
5950aadb33SDmitri Tikhonov    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30,
6050aadb33SDmitri Tikhonov    0x81, 0xca, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
6150aadb33SDmitri Tikhonov    0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x08,
6250aadb33SDmitri Tikhonov    0x13, 0x07, 0x41, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x61, 0x31, 0x13, 0x30,
6350aadb33SDmitri Tikhonov    0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0a, 0x53, 0x63, 0x6f, 0x74,
6450aadb33SDmitri Tikhonov    0x74, 0x73, 0x64, 0x61, 0x6c, 0x65, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03,
6550aadb33SDmitri Tikhonov    0x55, 0x04, 0x0a, 0x13, 0x11, 0x47, 0x6f, 0x44, 0x61, 0x64, 0x64, 0x79,
6650aadb33SDmitri Tikhonov    0x2e, 0x63, 0x6f, 0x6d, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x33,
6750aadb33SDmitri Tikhonov    0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x68, 0x74, 0x74,
6850aadb33SDmitri Tikhonov    0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
6950aadb33SDmitri Tikhonov    0x61, 0x74, 0x65, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79,
7050aadb33SDmitri Tikhonov    0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74,
7150aadb33SDmitri Tikhonov    0x6f, 0x72, 0x79, 0x31, 0x30, 0x30, 0x2e, 0x06, 0x03, 0x55, 0x04, 0x03,
7250aadb33SDmitri Tikhonov    0x13, 0x27, 0x47, 0x6f, 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, 0x20, 0x53,
7350aadb33SDmitri Tikhonov    0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66,
7450aadb33SDmitri Tikhonov    0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68,
7550aadb33SDmitri Tikhonov    0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55,
7650aadb33SDmitri Tikhonov    0x04, 0x05, 0x13, 0x08, 0x30, 0x37, 0x39, 0x36, 0x39, 0x32, 0x38, 0x37,
7750aadb33SDmitri Tikhonov    0x30, 0x1e, 0x17, 0x0d, 0x31, 0x31, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d,
7850aadb33SDmitri Tikhonov    0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0c,
7950aadb33SDmitri Tikhonov    0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00,
8050aadb33SDmitri Tikhonov    0x30, 0x1d, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
8150aadb33SDmitri Tikhonov    0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55,
8250aadb33SDmitri Tikhonov    0x1d, 0x25, 0x04, 0x16, 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05,
8350aadb33SDmitri Tikhonov    0x05, 0x07, 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
8450aadb33SDmitri Tikhonov    0x03, 0x02, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff,
8550aadb33SDmitri Tikhonov    0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x33, 0x06, 0x03, 0x55, 0x1d,
8650aadb33SDmitri Tikhonov    0x1f, 0x04, 0x2c, 0x30, 0x2a, 0x30, 0x28, 0xa0, 0x26, 0xa0, 0x24, 0x86,
8750aadb33SDmitri Tikhonov    0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e,
8850aadb33SDmitri Tikhonov    0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
8950aadb33SDmitri Tikhonov    0x67, 0x64, 0x73, 0x31, 0x2d, 0x32, 0x30, 0x2a, 0x30, 0x28, 0x06, 0x08,
9050aadb33SDmitri Tikhonov    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x1c, 0x68, 0x74,
9150aadb33SDmitri Tikhonov    0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x65,
9250aadb33SDmitri Tikhonov    0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63,
9350aadb33SDmitri Tikhonov    0x70, 0x73, 0x30, 0x34, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17,
9450aadb33SDmitri Tikhonov    0x0d, 0x31, 0x33, 0x30, 0x35, 0x30, 0x39, 0x06, 0x08, 0x2b, 0x06, 0x01,
9550aadb33SDmitri Tikhonov    0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x2d, 0x68, 0x74, 0x74, 0x70, 0x3a,
9650aadb33SDmitri Tikhonov    0x2f, 0x2f, 0x73, 0x30, 0x39, 0x30, 0x37, 0x06, 0x08, 0x2b, 0x06, 0x01,
9750aadb33SDmitri Tikhonov    0x05, 0x05, 0x07, 0x02, 0x30, 0x44, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04,
9850aadb33SDmitri Tikhonov    0x3d, 0x30, 0x3b, 0x30, 0x39, 0x06, 0x0b, 0x60, 0x86, 0x48, 0x01, 0x86,
9950aadb33SDmitri Tikhonov    0xf8, 0x45, 0x01, 0x07, 0x17, 0x06, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
10050aadb33SDmitri Tikhonov    0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x1b, 0x53, 0x31, 0x17,
10150aadb33SDmitri Tikhonov    0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56, 0x65, 0x72,
10250aadb33SDmitri Tikhonov    0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31,
10350aadb33SDmitri Tikhonov    0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x16, 0x56, 0x65,
10450aadb33SDmitri Tikhonov    0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74,
10550aadb33SDmitri Tikhonov    0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x31, 0x3b, 0x30, 0x39,
10650aadb33SDmitri Tikhonov    0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x32, 0x54, 0x65, 0x72, 0x6d, 0x73,
10750aadb33SDmitri Tikhonov    0x20, 0x6f, 0x66, 0x20, 0x75, 0x73, 0x65, 0x20, 0x61, 0x74, 0x20, 0x68,
10850aadb33SDmitri Tikhonov    0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76,
10950aadb33SDmitri Tikhonov    0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
11050aadb33SDmitri Tikhonov    0x72, 0x70, 0x61, 0x20, 0x28, 0x63, 0x29, 0x30, 0x31, 0x10, 0x30, 0x0e,
11150aadb33SDmitri Tikhonov    0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x31, 0x13, 0x30, 0x11,
11250aadb33SDmitri Tikhonov    0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0a, 0x47, 0x31, 0x13, 0x30, 0x11,
11350aadb33SDmitri Tikhonov    0x06, 0x0b, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x3c, 0x02, 0x01,
11450aadb33SDmitri Tikhonov    0x03, 0x13, 0x02, 0x55, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04,
11550aadb33SDmitri Tikhonov    0x03, 0x14, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
11650aadb33SDmitri Tikhonov    0x31, 0x1d, 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x0f, 0x13, 0x14, 0x50,
11750aadb33SDmitri Tikhonov    0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x20, 0x4f, 0x72, 0x67, 0x61, 0x6e,
11850aadb33SDmitri Tikhonov    0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x12, 0x31, 0x21, 0x30,
11950aadb33SDmitri Tikhonov    0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x18, 0x44, 0x6f, 0x6d, 0x61,
12050aadb33SDmitri Tikhonov    0x69, 0x6e, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x20, 0x56,
12150aadb33SDmitri Tikhonov    0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x64, 0x31, 0x14, 0x31, 0x31,
12250aadb33SDmitri Tikhonov    0x30, 0x2f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x28, 0x53, 0x65, 0x65,
12350aadb33SDmitri Tikhonov    0x20, 0x77, 0x77, 0x77, 0x2e, 0x72, 0x3a, 0x2f, 0x2f, 0x73, 0x65, 0x63,
12450aadb33SDmitri Tikhonov    0x75, 0x72, 0x65, 0x2e, 0x67, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53,
12550aadb33SDmitri Tikhonov    0x69, 0x67, 0x6e, 0x31, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x41,
12650aadb33SDmitri Tikhonov    0x2e, 0x63, 0x72, 0x6c, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e,
12750aadb33SDmitri Tikhonov    0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x45, 0x63, 0x72,
12850aadb33SDmitri Tikhonov    0x6c, 0x2e, 0x67, 0x65, 0x6f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63,
12950aadb33SDmitri Tikhonov    0x6f, 0x6d, 0x2f, 0x63, 0x72, 0x6c, 0x73, 0x2f, 0x73, 0x64, 0x31, 0x1a,
13050aadb33SDmitri Tikhonov    0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x68, 0x74, 0x74, 0x70, 0x3a,
13150aadb33SDmitri Tikhonov    0x2f, 0x2f, 0x45, 0x56, 0x49, 0x6e, 0x74, 0x6c, 0x2d, 0x63, 0x63, 0x72,
13250aadb33SDmitri Tikhonov    0x74, 0x2e, 0x67, 0x77, 0x77, 0x77, 0x2e, 0x67, 0x69, 0x63, 0x65, 0x72,
13350aadb33SDmitri Tikhonov    0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x31, 0x6f, 0x63, 0x73, 0x70, 0x2e,
13450aadb33SDmitri Tikhonov    0x76, 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d,
13550aadb33SDmitri Tikhonov    0x30, 0x39, 0x72, 0x61, 0x70, 0x69, 0x64, 0x73, 0x73, 0x6c, 0x2e, 0x63,
13650aadb33SDmitri Tikhonov    0x6f, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79, 0x2e, 0x63,
13750aadb33SDmitri Tikhonov    0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72,
13850aadb33SDmitri Tikhonov    0x79, 0x2f, 0x30, 0x81, 0x80, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
13950aadb33SDmitri Tikhonov    0x07, 0x01, 0x01, 0x04, 0x74, 0x30, 0x72, 0x30, 0x24, 0x06, 0x08, 0x2b,
14050aadb33SDmitri Tikhonov    0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x18, 0x68, 0x74, 0x74,
14150aadb33SDmitri Tikhonov    0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x67, 0x6f, 0x64,
14250aadb33SDmitri Tikhonov    0x61, 0x64, 0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x30, 0x4a, 0x06,
14350aadb33SDmitri Tikhonov    0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x3e, 0x68,
14450aadb33SDmitri Tikhonov    0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66,
14550aadb33SDmitri Tikhonov    0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64,
14650aadb33SDmitri Tikhonov    0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73,
14750aadb33SDmitri Tikhonov    0x69, 0x74, 0x6f, 0x72, 0x79, 0x2f, 0x67, 0x64, 0x5f, 0x69, 0x6e, 0x74,
14850aadb33SDmitri Tikhonov    0x65, 0x72, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x63, 0x72,
14950aadb33SDmitri Tikhonov    0x74, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16,
15050aadb33SDmitri Tikhonov    0x80, 0x14, 0xfd, 0xac, 0x61, 0x32, 0x93, 0x6c, 0x45, 0xd6, 0xe2, 0xee,
15150aadb33SDmitri Tikhonov    0x85, 0x5f, 0x9a, 0xba, 0xe7, 0x76, 0x99, 0x68, 0xcc, 0xe7, 0x30, 0x27,
15250aadb33SDmitri Tikhonov    0x86, 0x29, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x86, 0x30,
15350aadb33SDmitri Tikhonov    0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x73,
15450aadb33SDmitri Tikhonov};
15550aadb33SDmitri Tikhonov
15650aadb33SDmitri Tikhonov#define common_certs_num 2
15750aadb33SDmitri Tikhonovconst common_cert_t common_cert_set[common_certs_num] = {
15850aadb33SDmitri Tikhonov    {common_certs2_num, common_certs2, common_certs2_lens, common_certs2_hash},
15950aadb33SDmitri Tikhonov    {common_certs3_num, common_certs3, common_certs3_lens, common_certs3_hash},
16050aadb33SDmitri Tikhonov};
16150aadb33SDmitri Tikhonov
16250aadb33SDmitri Tikhonov
16350aadb33SDmitri Tikhonovstatic lsquic_str_t *s_ccsbuf;
16450aadb33SDmitri Tikhonov
16550aadb33SDmitri Tikhonovlsquic_str_t * get_common_certs_hash()
16650aadb33SDmitri Tikhonov{
16750aadb33SDmitri Tikhonov    int i;
16850aadb33SDmitri Tikhonov    if (s_ccsbuf == NULL)
16950aadb33SDmitri Tikhonov    {
17050aadb33SDmitri Tikhonov        s_ccsbuf = lsquic_str_new(NULL, 0);
17150aadb33SDmitri Tikhonov        for (i=0 ;i<common_certs_num; ++i)
17250aadb33SDmitri Tikhonov        {
17350aadb33SDmitri Tikhonov            lsquic_str_append(s_ccsbuf, (const char *)&common_cert_set[i].hash, 8);
17450aadb33SDmitri Tikhonov        }
17550aadb33SDmitri Tikhonov    }
17650aadb33SDmitri Tikhonov    return s_ccsbuf;
17750aadb33SDmitri Tikhonov}
17850aadb33SDmitri Tikhonov
17950aadb33SDmitri Tikhonov
18050aadb33SDmitri Tikhonov/* return 0 found, -1 not found */
18150aadb33SDmitri Tikhonovint get_common_cert(uint64_t hash, uint32_t index, lsquic_str_t *buf)
18250aadb33SDmitri Tikhonov{
18350aadb33SDmitri Tikhonov    int i;
18450aadb33SDmitri Tikhonov    for (i = 0; i < common_certs_num; i++)
18550aadb33SDmitri Tikhonov    {
18650aadb33SDmitri Tikhonov        if (common_cert_set[i].hash == hash)
18750aadb33SDmitri Tikhonov        {
18850aadb33SDmitri Tikhonov            if (index < common_cert_set[i].num_certs)
18950aadb33SDmitri Tikhonov            {
19050aadb33SDmitri Tikhonov                lsquic_str_setto(buf, (const char *) common_cert_set[i].certs[index],
19150aadb33SDmitri Tikhonov                         common_cert_set[i].lens[index]);
19250aadb33SDmitri Tikhonov                return 0;
19350aadb33SDmitri Tikhonov            }
19450aadb33SDmitri Tikhonov            break;
19550aadb33SDmitri Tikhonov        }
19650aadb33SDmitri Tikhonov    }
19750aadb33SDmitri Tikhonov    return -1;
19850aadb33SDmitri Tikhonov}
19950aadb33SDmitri Tikhonov
20050aadb33SDmitri Tikhonov
20150aadb33SDmitri Tikhonov/* result is written to dict */
20250aadb33SDmitri Tikhonovstatic void
20350aadb33SDmitri Tikhonovmake_zlib_dict_for_entries(cert_entry_t *entries,
20450aadb33SDmitri Tikhonov                                lsquic_str_t **certs, size_t certs_count,
20550aadb33SDmitri Tikhonov                                lsquic_str_t *dict)
20650aadb33SDmitri Tikhonov{
20750aadb33SDmitri Tikhonov    int i;
20850aadb33SDmitri Tikhonov    size_t zlib_dict_size = 0;
20950aadb33SDmitri Tikhonov    for (i = certs_count - 1; i >= 0; --i)
21050aadb33SDmitri Tikhonov    {
21150aadb33SDmitri Tikhonov        if (entries[i].type != ENTRY_COMPRESSED)
21250aadb33SDmitri Tikhonov        {
21350aadb33SDmitri Tikhonov            zlib_dict_size += lsquic_str_len(certs[i]);
21450aadb33SDmitri Tikhonov        }
21550aadb33SDmitri Tikhonov    }
21650aadb33SDmitri Tikhonov
21750aadb33SDmitri Tikhonov    // At the end of the dictionary is a block of common certificate substrings.
21850aadb33SDmitri Tikhonov    zlib_dict_size += sizeof(common_cert_sub_strings);
21950aadb33SDmitri Tikhonov
22050aadb33SDmitri Tikhonov    for (i = certs_count - 1; i >= 0; --i)
22150aadb33SDmitri Tikhonov    {
22250aadb33SDmitri Tikhonov        if (entries[i].type != ENTRY_COMPRESSED)
22350aadb33SDmitri Tikhonov        {
22450aadb33SDmitri Tikhonov            lsquic_str_append(dict, lsquic_str_buf(certs[i]), lsquic_str_len(certs[i]));
22550aadb33SDmitri Tikhonov        }
22650aadb33SDmitri Tikhonov    }
22750aadb33SDmitri Tikhonov
22850aadb33SDmitri Tikhonov    lsquic_str_append(dict, (const char *)common_cert_sub_strings, sizeof(common_cert_sub_strings));
22950aadb33SDmitri Tikhonov    assert((size_t)lsquic_str_len(dict) == zlib_dict_size);
23050aadb33SDmitri Tikhonov}
23150aadb33SDmitri Tikhonov
23250aadb33SDmitri Tikhonov
23350aadb33SDmitri Tikhonovvoid get_certs_hash(lsquic_str_t *certs, size_t certs_count, uint64_t *hashs)
23450aadb33SDmitri Tikhonov{
23550aadb33SDmitri Tikhonov    size_t i;
23650aadb33SDmitri Tikhonov    for(i = 0; i < certs_count; ++i)
23750aadb33SDmitri Tikhonov    {
23850aadb33SDmitri Tikhonov        hashs[i] = fnv1a_64((const uint8_t *)lsquic_str_buf(&certs[i]), lsquic_str_len(&certs[i]));
23950aadb33SDmitri Tikhonov    }
24050aadb33SDmitri Tikhonov}
24150aadb33SDmitri Tikhonov
24250aadb33SDmitri Tikhonov
24350aadb33SDmitri Tikhonovsize_t get_entries_size(cert_entry_t *entries, size_t entries_count)
24450aadb33SDmitri Tikhonov{
24550aadb33SDmitri Tikhonov    size_t i;
24650aadb33SDmitri Tikhonov    size_t entries_size = 0;
24750aadb33SDmitri Tikhonov    for(i=0; i<entries_count; ++i)
24850aadb33SDmitri Tikhonov    {
24950aadb33SDmitri Tikhonov        entries_size++;
25050aadb33SDmitri Tikhonov        switch (entries[i].type)
25150aadb33SDmitri Tikhonov        {
25250aadb33SDmitri Tikhonov        case ENTRY_COMPRESSED:
25350aadb33SDmitri Tikhonov            break;
25450aadb33SDmitri Tikhonov        case ENTRY_CACHED:
25550aadb33SDmitri Tikhonov            entries_size += sizeof(uint64_t);
25650aadb33SDmitri Tikhonov            break;
25750aadb33SDmitri Tikhonov        case ENTRY_COMMON:
25850aadb33SDmitri Tikhonov            entries_size += sizeof(uint64_t) + sizeof(uint32_t);
25950aadb33SDmitri Tikhonov            break;
26050aadb33SDmitri Tikhonov        default:
26150aadb33SDmitri Tikhonov            break;
26250aadb33SDmitri Tikhonov        }
26350aadb33SDmitri Tikhonov    }
26450aadb33SDmitri Tikhonov    entries_size++;  /* for end marker */
26550aadb33SDmitri Tikhonov    return entries_size;
26650aadb33SDmitri Tikhonov}
26750aadb33SDmitri Tikhonov
26850aadb33SDmitri Tikhonov
26950aadb33SDmitri Tikhonovvoid serialize_cert_entries(uint8_t* out, int *out_len, cert_entry_t *entries,
27050aadb33SDmitri Tikhonov                            size_t entries_count)
27150aadb33SDmitri Tikhonov{
27250aadb33SDmitri Tikhonov    size_t i;
27350aadb33SDmitri Tikhonov    uint8_t *start = out;
27450aadb33SDmitri Tikhonov    for(i=0; i<entries_count; ++i)
27550aadb33SDmitri Tikhonov    {
27650aadb33SDmitri Tikhonov        *out++ = (uint8_t)(entries[i].type);
27750aadb33SDmitri Tikhonov        switch (entries[i].type)
27850aadb33SDmitri Tikhonov        {
27950aadb33SDmitri Tikhonov        case ENTRY_COMPRESSED:
28050aadb33SDmitri Tikhonov            break;
28150aadb33SDmitri Tikhonov        case ENTRY_CACHED:
28250aadb33SDmitri Tikhonov            memcpy(out, &entries[i].hash, sizeof(uint64_t));
28350aadb33SDmitri Tikhonov            out += sizeof(uint64_t);
28450aadb33SDmitri Tikhonov            break;
28550aadb33SDmitri Tikhonov        case ENTRY_COMMON:
28650aadb33SDmitri Tikhonov            memcpy(out, &entries[i].set_hash, sizeof(uint64_t));
28750aadb33SDmitri Tikhonov            out += sizeof(uint64_t);
28850aadb33SDmitri Tikhonov            memcpy(out, &entries[i].index, sizeof(uint32_t));
28950aadb33SDmitri Tikhonov            out += sizeof(uint32_t);
29050aadb33SDmitri Tikhonov            break;
29150aadb33SDmitri Tikhonov        default:
29250aadb33SDmitri Tikhonov            break;
29350aadb33SDmitri Tikhonov        }
29450aadb33SDmitri Tikhonov    }
29550aadb33SDmitri Tikhonov
29650aadb33SDmitri Tikhonov    *out++ = 0;  // end marker
29750aadb33SDmitri Tikhonov    *out_len = out - start;
29850aadb33SDmitri Tikhonov}
29950aadb33SDmitri Tikhonov
30050aadb33SDmitri Tikhonov
30150aadb33SDmitri Tikhonovint get_certs_count(lsquic_str_t *compressed_crt_buf)
30250aadb33SDmitri Tikhonov{
30350aadb33SDmitri Tikhonov    char *in = lsquic_str_buf(compressed_crt_buf);
30450aadb33SDmitri Tikhonov    char *in_end = in + lsquic_str_len(compressed_crt_buf);
30550aadb33SDmitri Tikhonov    size_t idx = 0;
30650aadb33SDmitri Tikhonov    uint8_t type_byte;
30750aadb33SDmitri Tikhonov
30850aadb33SDmitri Tikhonov    for (;;)
30950aadb33SDmitri Tikhonov    {
31050aadb33SDmitri Tikhonov        if (in >= in_end)
31150aadb33SDmitri Tikhonov            return -1;
31250aadb33SDmitri Tikhonov
31350aadb33SDmitri Tikhonov        type_byte = in[0];
31450aadb33SDmitri Tikhonov        ++in;
31550aadb33SDmitri Tikhonov        if (type_byte == 0)
31650aadb33SDmitri Tikhonov            break;
31750aadb33SDmitri Tikhonov
31850aadb33SDmitri Tikhonov        ++idx;
31950aadb33SDmitri Tikhonov        switch(type_byte)
32050aadb33SDmitri Tikhonov        {
32150aadb33SDmitri Tikhonov        case ENTRY_COMPRESSED:
32250aadb33SDmitri Tikhonov            break;
32350aadb33SDmitri Tikhonov        case ENTRY_CACHED:
32450aadb33SDmitri Tikhonov        {
32550aadb33SDmitri Tikhonov            if (in_end - in < (int)sizeof(uint64_t))
32650aadb33SDmitri Tikhonov                return -1;
32750aadb33SDmitri Tikhonov            in += sizeof(uint64_t);
32850aadb33SDmitri Tikhonov            break;
32950aadb33SDmitri Tikhonov        }
33050aadb33SDmitri Tikhonov        case ENTRY_COMMON:
33150aadb33SDmitri Tikhonov        {
33250aadb33SDmitri Tikhonov            if (in_end - in < (int)(sizeof(uint64_t) + sizeof(uint32_t)))
33350aadb33SDmitri Tikhonov                return -1;
33450aadb33SDmitri Tikhonov            in += sizeof(uint64_t) + sizeof(uint32_t);
33550aadb33SDmitri Tikhonov            break;
33650aadb33SDmitri Tikhonov        }
33750aadb33SDmitri Tikhonov        default:
33850aadb33SDmitri Tikhonov            return -1;
33950aadb33SDmitri Tikhonov        }
34050aadb33SDmitri Tikhonov    }
34150aadb33SDmitri Tikhonov    return idx;
34250aadb33SDmitri Tikhonov}
34350aadb33SDmitri Tikhonov
34450aadb33SDmitri Tikhonov
34550aadb33SDmitri Tikhonov/* return 0: OK, -1, error */
34650aadb33SDmitri Tikhonovstatic int parse_entries(const unsigned char **in_out, const unsigned char *const in_end,
34750aadb33SDmitri Tikhonov                         lsquic_str_t *cached_certs, size_t cached_certs_count,
34850aadb33SDmitri Tikhonov                         cert_entry_t *out_entries,
34950aadb33SDmitri Tikhonov                         lsquic_str_t **out_certs, size_t *out_certs_count)
35050aadb33SDmitri Tikhonov{
35150aadb33SDmitri Tikhonov    const unsigned char *in = *in_out;
35250aadb33SDmitri Tikhonov    size_t idx = 0;
35350aadb33SDmitri Tikhonov    uint64_t* cached_hashes;
35450aadb33SDmitri Tikhonov    cert_entry_t *entry;
35550aadb33SDmitri Tikhonov    lsquic_str_t *cert;
35650aadb33SDmitri Tikhonov    uint8_t type_byte;
35750aadb33SDmitri Tikhonov    int rv;
35850aadb33SDmitri Tikhonov    size_t i;
35950aadb33SDmitri Tikhonov
36050aadb33SDmitri Tikhonov    cached_hashes = NULL;
36150aadb33SDmitri Tikhonov
36250aadb33SDmitri Tikhonov    for (;;)
36350aadb33SDmitri Tikhonov    {
36450aadb33SDmitri Tikhonov        /* XXX potential invalid read */
36550aadb33SDmitri Tikhonov        type_byte = in[0];
36650aadb33SDmitri Tikhonov        ++in;
36750aadb33SDmitri Tikhonov
36850aadb33SDmitri Tikhonov        if (type_byte == 0)
36950aadb33SDmitri Tikhonov            break;
37050aadb33SDmitri Tikhonov
37150aadb33SDmitri Tikhonov        entry = &out_entries[idx];
37250aadb33SDmitri Tikhonov        cert = out_certs[idx];
37350aadb33SDmitri Tikhonov        /* XXX This seems dangerous -- there is no guard that `idx' does not
37450aadb33SDmitri Tikhonov         * exceed `out_certs_count'.
37550aadb33SDmitri Tikhonov         */
37650aadb33SDmitri Tikhonov        lsquic_str_d(cert);
37750aadb33SDmitri Tikhonov
37850aadb33SDmitri Tikhonov        ++idx;
37950aadb33SDmitri Tikhonov        entry->type = type_byte;
38050aadb33SDmitri Tikhonov        switch (entry->type)
38150aadb33SDmitri Tikhonov        {
38250aadb33SDmitri Tikhonov        case ENTRY_COMPRESSED:
38350aadb33SDmitri Tikhonov            break;
38450aadb33SDmitri Tikhonov        case ENTRY_CACHED:
38550aadb33SDmitri Tikhonov        {
38650aadb33SDmitri Tikhonov            memcpy(&entry->hash, in, sizeof(uint64_t));
38750aadb33SDmitri Tikhonov            in += sizeof(uint64_t);
38850aadb33SDmitri Tikhonov
38950aadb33SDmitri Tikhonov            if (!cached_hashes)
39050aadb33SDmitri Tikhonov            {
39150aadb33SDmitri Tikhonov                cached_hashes = malloc(cached_certs_count * sizeof(uint64_t));;
39250aadb33SDmitri Tikhonov                if (!cached_hashes)
39350aadb33SDmitri Tikhonov                    goto err;
39450aadb33SDmitri Tikhonov                get_certs_hash(cached_certs, cached_certs_count, cached_hashes);
39550aadb33SDmitri Tikhonov            }
39650aadb33SDmitri Tikhonov
39750aadb33SDmitri Tikhonov            for (i=0; i<cached_certs_count; ++i)
39850aadb33SDmitri Tikhonov            {
39950aadb33SDmitri Tikhonov                if (cached_hashes[i] == entry->hash)
40050aadb33SDmitri Tikhonov                {
40150aadb33SDmitri Tikhonov                    lsquic_str_append(cert, lsquic_str_buf(&cached_certs[i]),
40250aadb33SDmitri Tikhonov                                  lsquic_str_len(&cached_certs[i]));
40350aadb33SDmitri Tikhonov                    break;
40450aadb33SDmitri Tikhonov                }
40550aadb33SDmitri Tikhonov            }
40650aadb33SDmitri Tikhonov            /* XXX: return -1 if not found?  Logic removed in
40750aadb33SDmitri Tikhonov                                4fd7e76bc031ac637e76c7f0930aff53f5b71705 */
40850aadb33SDmitri Tikhonov            break;
40950aadb33SDmitri Tikhonov        }
41050aadb33SDmitri Tikhonov        case ENTRY_COMMON:
41150aadb33SDmitri Tikhonov        {
41250aadb33SDmitri Tikhonov            memcpy(&entry->set_hash, in, sizeof(uint64_t));
41350aadb33SDmitri Tikhonov            in += sizeof(uint64_t);
41450aadb33SDmitri Tikhonov            memcpy(&entry->index, in, sizeof(uint32_t));
41550aadb33SDmitri Tikhonov            in += sizeof(uint32_t);
41650aadb33SDmitri Tikhonov
41750aadb33SDmitri Tikhonov            if (0 == get_common_cert(entry->set_hash, entry->index, cert))
41850aadb33SDmitri Tikhonov                break;
41950aadb33SDmitri Tikhonov            else
42050aadb33SDmitri Tikhonov                goto err;
42150aadb33SDmitri Tikhonov        }
42250aadb33SDmitri Tikhonov        default:
42350aadb33SDmitri Tikhonov            goto err;
42450aadb33SDmitri Tikhonov        }
42550aadb33SDmitri Tikhonov    }
42650aadb33SDmitri Tikhonov
42750aadb33SDmitri Tikhonov    rv = 0;
42850aadb33SDmitri Tikhonov    *in_out = in;
42950aadb33SDmitri Tikhonov    *out_certs_count = idx;
43050aadb33SDmitri Tikhonov
43150aadb33SDmitri Tikhonov  cleanup:
43250aadb33SDmitri Tikhonov    free(cached_hashes);
43350aadb33SDmitri Tikhonov    return rv;
43450aadb33SDmitri Tikhonov
43550aadb33SDmitri Tikhonov  err:
43650aadb33SDmitri Tikhonov    rv = -1;
43750aadb33SDmitri Tikhonov    goto cleanup;
43850aadb33SDmitri Tikhonov}
43950aadb33SDmitri Tikhonov
44050aadb33SDmitri Tikhonov
44150aadb33SDmitri Tikhonov/* 0: ok */
44250aadb33SDmitri Tikhonovint decompress_certs(const unsigned char *in, const unsigned char *in_end,
44350aadb33SDmitri Tikhonov                     lsquic_str_t *cached_certs, size_t cached_certs_count,
44450aadb33SDmitri Tikhonov                     lsquic_str_t **out_certs, size_t *out_certs_count)
44550aadb33SDmitri Tikhonov{
44650aadb33SDmitri Tikhonov    int ret;
44750aadb33SDmitri Tikhonov    size_t i;
448b93f59beSBob Perper    uint8_t* uncompressed_data, *uncompressed_data_buf;
44950aadb33SDmitri Tikhonov    lsquic_str_t *dict;
45050aadb33SDmitri Tikhonov    uint32_t uncompressed_size;
45150aadb33SDmitri Tikhonov    size_t count = *out_certs_count;
45250aadb33SDmitri Tikhonov    cert_entry_t *entries;
45350aadb33SDmitri Tikhonov    z_stream z;
45450aadb33SDmitri Tikhonov
45550aadb33SDmitri Tikhonov    assert(*out_certs_count > 0 && *out_certs_count < 10000
45650aadb33SDmitri Tikhonov            && "Call get_certs_count() to get right certificates count first and make enough room for out_certs_count");
45750aadb33SDmitri Tikhonov
45850aadb33SDmitri Tikhonov    if (count == 0 || count > 10000)
45950aadb33SDmitri Tikhonov        return -1;
46050aadb33SDmitri Tikhonov
46150aadb33SDmitri Tikhonov    dict = lsquic_str_new(NULL, 0);
46250aadb33SDmitri Tikhonov    if (!dict)
46350aadb33SDmitri Tikhonov        return -1;
46450aadb33SDmitri Tikhonov
46550aadb33SDmitri Tikhonov    uncompressed_data_buf = NULL;
466b93f59beSBob Perper#ifdef WIN32
467b93f59beSBob Perper    uncompressed_data = NULL;
468b93f59beSBob Perper#endif
46950aadb33SDmitri Tikhonov    entries = malloc(count * sizeof(cert_entry_t));
47050aadb33SDmitri Tikhonov    if (!entries)
47150aadb33SDmitri Tikhonov        goto err;
47250aadb33SDmitri Tikhonov
47350aadb33SDmitri Tikhonov    ret = parse_entries(&in, in_end, cached_certs, cached_certs_count,
47450aadb33SDmitri Tikhonov                  entries, out_certs, out_certs_count);
47550aadb33SDmitri Tikhonov    if (ret)
47650aadb33SDmitri Tikhonov        goto err;
47750aadb33SDmitri Tikhonov
47850aadb33SDmitri Tikhonov    /* re-assign count with real valus */
47950aadb33SDmitri Tikhonov    count = *out_certs_count;
48050aadb33SDmitri Tikhonov
48150aadb33SDmitri Tikhonov    if (in < in_end)
48250aadb33SDmitri Tikhonov    {
48350aadb33SDmitri Tikhonov        if (in_end - in < (int)sizeof(uint32_t))
48450aadb33SDmitri Tikhonov            goto err;
48550aadb33SDmitri Tikhonov
48650aadb33SDmitri Tikhonov        memcpy(&uncompressed_size, in, sizeof(uncompressed_size));
48750aadb33SDmitri Tikhonov        in += sizeof(uint32_t);
48850aadb33SDmitri Tikhonov        /* XXX Is 128 KB an arbitrary limit or is there a reason behind it? */
48950aadb33SDmitri Tikhonov        if (uncompressed_size > 128 * 1024)
49050aadb33SDmitri Tikhonov            goto err;
49150aadb33SDmitri Tikhonov
49250aadb33SDmitri Tikhonov        uncompressed_data_buf = uncompressed_data = malloc(uncompressed_size);
493b93f59beSBob Perper        if (!uncompressed_data)
494b93f59beSBob Perper            goto err;
495b93f59beSBob Perper
49650aadb33SDmitri Tikhonov        memset(&z, 0, sizeof(z));
49750aadb33SDmitri Tikhonov        z.next_out  = uncompressed_data;
49850aadb33SDmitri Tikhonov        z.avail_out = uncompressed_size;
49950aadb33SDmitri Tikhonov        z.next_in   = (unsigned char *) in;
50050aadb33SDmitri Tikhonov        z.avail_in  = in_end - in;
50150aadb33SDmitri Tikhonov
50250aadb33SDmitri Tikhonov        if (Z_OK != inflateInit(&z))
50350aadb33SDmitri Tikhonov            goto err;
50450aadb33SDmitri Tikhonov
50550aadb33SDmitri Tikhonov        ret = inflate(&z, Z_FINISH);
50650aadb33SDmitri Tikhonov        if (ret == Z_NEED_DICT)
50750aadb33SDmitri Tikhonov        {
50850aadb33SDmitri Tikhonov            lsquic_str_d(dict);
50950aadb33SDmitri Tikhonov            make_zlib_dict_for_entries(entries, out_certs, count, dict);
51050aadb33SDmitri Tikhonov            if (Z_OK != inflateSetDictionary(&z, (const unsigned char *)lsquic_str_buf(dict), lsquic_str_len(dict)))
51150aadb33SDmitri Tikhonov                goto err;
51250aadb33SDmitri Tikhonov            ret = inflate(&z, Z_FINISH);
51350aadb33SDmitri Tikhonov        }
51450aadb33SDmitri Tikhonov
51550aadb33SDmitri Tikhonov        if (Z_STREAM_END != ret || z.avail_out > 0 || z.avail_in > 0)
51650aadb33SDmitri Tikhonov            goto err;
51750aadb33SDmitri Tikhonov    }
51850aadb33SDmitri Tikhonov    else
51950aadb33SDmitri Tikhonov        uncompressed_size = 0;
52050aadb33SDmitri Tikhonov
52150aadb33SDmitri Tikhonov    for (i = 0; i < count; i++)
52250aadb33SDmitri Tikhonov    {
52350aadb33SDmitri Tikhonov        switch (entries[i].type)
52450aadb33SDmitri Tikhonov        {
52550aadb33SDmitri Tikhonov          case ENTRY_COMPRESSED:
52650aadb33SDmitri Tikhonov              if (uncompressed_size < sizeof(uint32_t))
52750aadb33SDmitri Tikhonov                  goto err;
52850aadb33SDmitri Tikhonov              lsquic_str_d(out_certs[i]);
52950aadb33SDmitri Tikhonov              uint32_t cert_len;
53050aadb33SDmitri Tikhonov              memcpy(&cert_len, uncompressed_data, sizeof(cert_len));
53150aadb33SDmitri Tikhonov              uncompressed_data += sizeof(uint32_t);
53250aadb33SDmitri Tikhonov              uncompressed_size -= sizeof(uint32_t);
53350aadb33SDmitri Tikhonov              if (uncompressed_size < cert_len)
53450aadb33SDmitri Tikhonov                  goto err;
53550aadb33SDmitri Tikhonov              lsquic_str_append(out_certs[i], (const char *)uncompressed_data, cert_len);
53650aadb33SDmitri Tikhonov              uncompressed_data += cert_len;
53750aadb33SDmitri Tikhonov              uncompressed_size -= cert_len;
53850aadb33SDmitri Tikhonov              break;
53950aadb33SDmitri Tikhonov          case ENTRY_CACHED:
54050aadb33SDmitri Tikhonov          case ENTRY_COMMON:
54150aadb33SDmitri Tikhonov          default:
54250aadb33SDmitri Tikhonov            break;
54350aadb33SDmitri Tikhonov        }
54450aadb33SDmitri Tikhonov    }
54550aadb33SDmitri Tikhonov
54650aadb33SDmitri Tikhonov  cleanup:
54750aadb33SDmitri Tikhonov    lsquic_str_delete(dict);
54850aadb33SDmitri Tikhonov    free(entries);
54950aadb33SDmitri Tikhonov    if (uncompressed_data_buf)
55050aadb33SDmitri Tikhonov        inflateEnd(&z);
55150aadb33SDmitri Tikhonov    free(uncompressed_data_buf);
55250aadb33SDmitri Tikhonov    if (0 == uncompressed_size)
55350aadb33SDmitri Tikhonov        return 0;
55450aadb33SDmitri Tikhonov    else
55550aadb33SDmitri Tikhonov        return -1;
55650aadb33SDmitri Tikhonov
55750aadb33SDmitri Tikhonov  err:
55850aadb33SDmitri Tikhonov    uncompressed_size = 1;  /* This triggers return -1 above */
55950aadb33SDmitri Tikhonov    goto cleanup;
56050aadb33SDmitri Tikhonov}
56150aadb33SDmitri Tikhonov
56250aadb33SDmitri Tikhonov
56350aadb33SDmitri Tikhonovvoid
56450aadb33SDmitri Tikhonovlsquic_crt_cleanup (void)
56550aadb33SDmitri Tikhonov{
56650aadb33SDmitri Tikhonov    if (s_ccsbuf)
56750aadb33SDmitri Tikhonov    {
56850aadb33SDmitri Tikhonov        lsquic_str_delete(s_ccsbuf);
56950aadb33SDmitri Tikhonov        s_ccsbuf = NULL;
57050aadb33SDmitri Tikhonov    }
57150aadb33SDmitri Tikhonov}
57250aadb33SDmitri Tikhonov
57350aadb33SDmitri Tikhonov
574