lsquic_crt_compress.c revision a5fa05f9
17d09751dSDmitri Tikhonov/* Copyright (c) 2017 - 2020 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 165a5fa05f9SDmitri Tikhonovstatic int 166a5fa05f9SDmitri Tikhonovmatch_common_cert (lsquic_str_t * cert, lsquic_str_t * common_set_hashes, 167a5fa05f9SDmitri Tikhonov uint64_t* out_hash, uint32_t* out_index); 168a5fa05f9SDmitri Tikhonov 169a5fa05f9SDmitri Tikhonovlsquic_str_t * 170a5fa05f9SDmitri Tikhonovlsquic_get_common_certs_hash() 17150aadb33SDmitri Tikhonov{ 17250aadb33SDmitri Tikhonov int i; 17350aadb33SDmitri Tikhonov if (s_ccsbuf == NULL) 17450aadb33SDmitri Tikhonov { 17550aadb33SDmitri Tikhonov s_ccsbuf = lsquic_str_new(NULL, 0); 17650aadb33SDmitri Tikhonov for (i=0 ;i<common_certs_num; ++i) 17750aadb33SDmitri Tikhonov { 17850aadb33SDmitri Tikhonov lsquic_str_append(s_ccsbuf, (const char *)&common_cert_set[i].hash, 8); 17950aadb33SDmitri Tikhonov } 18050aadb33SDmitri Tikhonov } 18150aadb33SDmitri Tikhonov return s_ccsbuf; 18250aadb33SDmitri Tikhonov} 18350aadb33SDmitri Tikhonov 18450aadb33SDmitri Tikhonov 18550aadb33SDmitri Tikhonov/* return 0 found, -1 not found */ 186a5fa05f9SDmitri Tikhonovint 187a5fa05f9SDmitri Tikhonovlsquic_get_common_cert(uint64_t hash, uint32_t index, lsquic_str_t *buf) 18850aadb33SDmitri Tikhonov{ 18950aadb33SDmitri Tikhonov int i; 19050aadb33SDmitri Tikhonov for (i = 0; i < common_certs_num; i++) 19150aadb33SDmitri Tikhonov { 19250aadb33SDmitri Tikhonov if (common_cert_set[i].hash == hash) 19350aadb33SDmitri Tikhonov { 19450aadb33SDmitri Tikhonov if (index < common_cert_set[i].num_certs) 19550aadb33SDmitri Tikhonov { 19650aadb33SDmitri Tikhonov lsquic_str_setto(buf, (const char *) common_cert_set[i].certs[index], 19750aadb33SDmitri Tikhonov common_cert_set[i].lens[index]); 19850aadb33SDmitri Tikhonov return 0; 19950aadb33SDmitri Tikhonov } 20050aadb33SDmitri Tikhonov break; 20150aadb33SDmitri Tikhonov } 20250aadb33SDmitri Tikhonov } 20350aadb33SDmitri Tikhonov return -1; 20450aadb33SDmitri Tikhonov} 20550aadb33SDmitri Tikhonov 20650aadb33SDmitri Tikhonov 2075392f7a3SLiteSpeed Techstatic int 2085392f7a3SLiteSpeed Techcomp_ls_str (lsquic_str_t * a, const void * b, size_t b_len) 2095392f7a3SLiteSpeed Tech{ 2105392f7a3SLiteSpeed Tech size_t a_len; 2115392f7a3SLiteSpeed Tech int r; 2125392f7a3SLiteSpeed Tech 2135392f7a3SLiteSpeed Tech a_len = lsquic_str_len(a); 2145392f7a3SLiteSpeed Tech r = memcmp(lsquic_str_buf(a), b, a_len < b_len ? a_len : b_len); 2155392f7a3SLiteSpeed Tech if (r) 2165392f7a3SLiteSpeed Tech return r; 2175392f7a3SLiteSpeed Tech else 2185392f7a3SLiteSpeed Tech return (a_len > b_len) - (b_len > a_len); 2195392f7a3SLiteSpeed Tech} 2205392f7a3SLiteSpeed Tech 2215392f7a3SLiteSpeed Tech 2225392f7a3SLiteSpeed Tech/* 0, matched -1, error */ 223a5fa05f9SDmitri Tikhonovstatic int 224a5fa05f9SDmitri Tikhonovmatch_common_cert (lsquic_str_t * cert, lsquic_str_t * common_set_hashes, 2255392f7a3SLiteSpeed Tech uint64_t* out_hash, uint32_t* out_index) 2265392f7a3SLiteSpeed Tech{ 2275392f7a3SLiteSpeed Tech size_t i, j; 2285392f7a3SLiteSpeed Tech int n; 2295392f7a3SLiteSpeed Tech uint64_t hash; 2305392f7a3SLiteSpeed Tech size_t min, max, mid; 2315392f7a3SLiteSpeed Tech 2325392f7a3SLiteSpeed Tech if (lsquic_str_len(common_set_hashes) % sizeof(uint64_t) != 0) 2335392f7a3SLiteSpeed Tech return -1; 2345392f7a3SLiteSpeed Tech 2355392f7a3SLiteSpeed Tech for (i = 0; i < lsquic_str_len(common_set_hashes) / sizeof(uint64_t); i++) 2365392f7a3SLiteSpeed Tech { 2375392f7a3SLiteSpeed Tech memcpy(&hash, lsquic_str_buf(common_set_hashes) + i * sizeof(uint64_t), 2385392f7a3SLiteSpeed Tech sizeof(uint64_t)); 2395392f7a3SLiteSpeed Tech 2405392f7a3SLiteSpeed Tech for (j = 0; j < common_certs_num; j++) 2415392f7a3SLiteSpeed Tech { 2425392f7a3SLiteSpeed Tech if (common_cert_set[j].hash != hash) 2435392f7a3SLiteSpeed Tech continue; 2445392f7a3SLiteSpeed Tech 2455392f7a3SLiteSpeed Tech if (common_cert_set[j].num_certs == 0) 2465392f7a3SLiteSpeed Tech continue; 2475392f7a3SLiteSpeed Tech 2485392f7a3SLiteSpeed Tech min = 0; 2495392f7a3SLiteSpeed Tech max = common_cert_set[j].num_certs - 1; 2505392f7a3SLiteSpeed Tech while (max >= min) 2515392f7a3SLiteSpeed Tech { 2525392f7a3SLiteSpeed Tech mid = min + ((max - min) / 2); 2535392f7a3SLiteSpeed Tech n = comp_ls_str(cert, common_cert_set[j].certs[mid], 2545392f7a3SLiteSpeed Tech common_cert_set[j].lens[mid]); 2555392f7a3SLiteSpeed Tech if (n < 0) 2565392f7a3SLiteSpeed Tech { 2575392f7a3SLiteSpeed Tech if (mid == 0) 2585392f7a3SLiteSpeed Tech break; 2595392f7a3SLiteSpeed Tech max = mid - 1; 2605392f7a3SLiteSpeed Tech } 2615392f7a3SLiteSpeed Tech else if (n > 0) 2625392f7a3SLiteSpeed Tech min = mid + 1; 2635392f7a3SLiteSpeed Tech else 2645392f7a3SLiteSpeed Tech { 2655392f7a3SLiteSpeed Tech *out_hash = hash; 2665392f7a3SLiteSpeed Tech *out_index = mid; 2675392f7a3SLiteSpeed Tech return 0; 2685392f7a3SLiteSpeed Tech } 2695392f7a3SLiteSpeed Tech } 2705392f7a3SLiteSpeed Tech } 2715392f7a3SLiteSpeed Tech } 2725392f7a3SLiteSpeed Tech 2735392f7a3SLiteSpeed Tech return -1; 2745392f7a3SLiteSpeed Tech} 2755392f7a3SLiteSpeed Tech 2765392f7a3SLiteSpeed Tech 27750aadb33SDmitri Tikhonov/* result is written to dict */ 27850aadb33SDmitri Tikhonovstatic void 27950aadb33SDmitri Tikhonovmake_zlib_dict_for_entries(cert_entry_t *entries, 28050aadb33SDmitri Tikhonov lsquic_str_t **certs, size_t certs_count, 28150aadb33SDmitri Tikhonov lsquic_str_t *dict) 28250aadb33SDmitri Tikhonov{ 28350aadb33SDmitri Tikhonov int i; 28450aadb33SDmitri Tikhonov size_t zlib_dict_size = 0; 28550aadb33SDmitri Tikhonov for (i = certs_count - 1; i >= 0; --i) 28650aadb33SDmitri Tikhonov { 28750aadb33SDmitri Tikhonov if (entries[i].type != ENTRY_COMPRESSED) 28850aadb33SDmitri Tikhonov { 28950aadb33SDmitri Tikhonov zlib_dict_size += lsquic_str_len(certs[i]); 29050aadb33SDmitri Tikhonov } 29150aadb33SDmitri Tikhonov } 29250aadb33SDmitri Tikhonov 29350aadb33SDmitri Tikhonov // At the end of the dictionary is a block of common certificate substrings. 29450aadb33SDmitri Tikhonov zlib_dict_size += sizeof(common_cert_sub_strings); 29550aadb33SDmitri Tikhonov 29650aadb33SDmitri Tikhonov for (i = certs_count - 1; i >= 0; --i) 29750aadb33SDmitri Tikhonov { 29850aadb33SDmitri Tikhonov if (entries[i].type != ENTRY_COMPRESSED) 29950aadb33SDmitri Tikhonov { 30050aadb33SDmitri Tikhonov lsquic_str_append(dict, lsquic_str_buf(certs[i]), lsquic_str_len(certs[i])); 30150aadb33SDmitri Tikhonov } 30250aadb33SDmitri Tikhonov } 30350aadb33SDmitri Tikhonov 30450aadb33SDmitri Tikhonov lsquic_str_append(dict, (const char *)common_cert_sub_strings, sizeof(common_cert_sub_strings)); 30550aadb33SDmitri Tikhonov assert((size_t)lsquic_str_len(dict) == zlib_dict_size); 30650aadb33SDmitri Tikhonov} 30750aadb33SDmitri Tikhonov 30850aadb33SDmitri Tikhonov 309a5fa05f9SDmitri Tikhonovstatic 31050aadb33SDmitri Tikhonovvoid get_certs_hash(lsquic_str_t *certs, size_t certs_count, uint64_t *hashs) 31150aadb33SDmitri Tikhonov{ 31250aadb33SDmitri Tikhonov size_t i; 31350aadb33SDmitri Tikhonov for(i = 0; i < certs_count; ++i) 31450aadb33SDmitri Tikhonov { 315a5fa05f9SDmitri Tikhonov hashs[i] = lsquic_fnv1a_64((const uint8_t *)lsquic_str_buf(&certs[i]), lsquic_str_len(&certs[i])); 31650aadb33SDmitri Tikhonov } 31750aadb33SDmitri Tikhonov} 31850aadb33SDmitri Tikhonov 31950aadb33SDmitri Tikhonov 3205392f7a3SLiteSpeed Techstatic void get_certs_entries(lsquic_str_t **certs, size_t certs_count, 3215392f7a3SLiteSpeed Tech lsquic_str_t *client_common_set_hashes, 3225392f7a3SLiteSpeed Tech lsquic_str_t *client_cached_cert_hashes, 3235392f7a3SLiteSpeed Tech cert_entry_t *entries) 3245392f7a3SLiteSpeed Tech{ 3255392f7a3SLiteSpeed Tech size_t i; 3265392f7a3SLiteSpeed Tech int j; 3275392f7a3SLiteSpeed Tech cert_entry_t *entry; 3285392f7a3SLiteSpeed Tech uint64_t hash, cached_hash; 3295392f7a3SLiteSpeed Tech bool cached; 3305392f7a3SLiteSpeed Tech 3315392f7a3SLiteSpeed Tech const bool cached_valid = (lsquic_str_len(client_cached_cert_hashes) % sizeof(uint64_t) == 0) 3325392f7a3SLiteSpeed Tech && (lsquic_str_len(client_cached_cert_hashes) > 0); 3335392f7a3SLiteSpeed Tech 3345392f7a3SLiteSpeed Tech assert(&entries[certs_count - 1]); 3355392f7a3SLiteSpeed Tech 3365392f7a3SLiteSpeed Tech for (i = 0; i<certs_count; ++i) 3375392f7a3SLiteSpeed Tech { 3385392f7a3SLiteSpeed Tech entry = &entries[i]; 3395392f7a3SLiteSpeed Tech if (cached_valid) 3405392f7a3SLiteSpeed Tech { 3415392f7a3SLiteSpeed Tech cached = false; 342a5fa05f9SDmitri Tikhonov hash = lsquic_fnv1a_64((const uint8_t *)lsquic_str_buf(certs[i]), lsquic_str_len(certs[i])); 3435392f7a3SLiteSpeed Tech 3445392f7a3SLiteSpeed Tech for (j = 0; j < (int)lsquic_str_len(client_cached_cert_hashes); 3455392f7a3SLiteSpeed Tech j += sizeof(uint64_t)) 3465392f7a3SLiteSpeed Tech { 3475392f7a3SLiteSpeed Tech memcpy(&cached_hash, lsquic_str_buf(client_cached_cert_hashes) + j, 3485392f7a3SLiteSpeed Tech sizeof(uint64_t)); 3495392f7a3SLiteSpeed Tech if (hash != cached_hash) 3505392f7a3SLiteSpeed Tech continue; 3515392f7a3SLiteSpeed Tech 3525392f7a3SLiteSpeed Tech entry->type = ENTRY_CACHED; 3535392f7a3SLiteSpeed Tech entry->hash = hash; 3545392f7a3SLiteSpeed Tech cached = true; 3555392f7a3SLiteSpeed Tech break; 3565392f7a3SLiteSpeed Tech } 3575392f7a3SLiteSpeed Tech 3585392f7a3SLiteSpeed Tech if (cached) 3595392f7a3SLiteSpeed Tech continue; 3605392f7a3SLiteSpeed Tech } 3615392f7a3SLiteSpeed Tech 3625392f7a3SLiteSpeed Tech if (0 == match_common_cert(certs[i], client_common_set_hashes, 3635392f7a3SLiteSpeed Tech &entry->set_hash, &entry->index)) 3645392f7a3SLiteSpeed Tech { 3655392f7a3SLiteSpeed Tech entry->type = ENTRY_COMMON; 3665392f7a3SLiteSpeed Tech continue; 3675392f7a3SLiteSpeed Tech } 3685392f7a3SLiteSpeed Tech 3695392f7a3SLiteSpeed Tech entry->type = ENTRY_COMPRESSED; 3705392f7a3SLiteSpeed Tech } 3715392f7a3SLiteSpeed Tech} 3725392f7a3SLiteSpeed Tech 373a5fa05f9SDmitri Tikhonovstatic size_t 374a5fa05f9SDmitri Tikhonovget_entries_size(cert_entry_t *entries, size_t entries_count) 37550aadb33SDmitri Tikhonov{ 37650aadb33SDmitri Tikhonov size_t i; 37750aadb33SDmitri Tikhonov size_t entries_size = 0; 37850aadb33SDmitri Tikhonov for(i=0; i<entries_count; ++i) 37950aadb33SDmitri Tikhonov { 38050aadb33SDmitri Tikhonov entries_size++; 38150aadb33SDmitri Tikhonov switch (entries[i].type) 38250aadb33SDmitri Tikhonov { 38350aadb33SDmitri Tikhonov case ENTRY_COMPRESSED: 38450aadb33SDmitri Tikhonov break; 38550aadb33SDmitri Tikhonov case ENTRY_CACHED: 38650aadb33SDmitri Tikhonov entries_size += sizeof(uint64_t); 38750aadb33SDmitri Tikhonov break; 38850aadb33SDmitri Tikhonov case ENTRY_COMMON: 38950aadb33SDmitri Tikhonov entries_size += sizeof(uint64_t) + sizeof(uint32_t); 39050aadb33SDmitri Tikhonov break; 39150aadb33SDmitri Tikhonov default: 39250aadb33SDmitri Tikhonov break; 39350aadb33SDmitri Tikhonov } 39450aadb33SDmitri Tikhonov } 39550aadb33SDmitri Tikhonov entries_size++; /* for end marker */ 39650aadb33SDmitri Tikhonov return entries_size; 39750aadb33SDmitri Tikhonov} 39850aadb33SDmitri Tikhonov 399a5fa05f9SDmitri Tikhonovstatic 40050aadb33SDmitri Tikhonovvoid serialize_cert_entries(uint8_t* out, int *out_len, cert_entry_t *entries, 40150aadb33SDmitri Tikhonov size_t entries_count) 40250aadb33SDmitri Tikhonov{ 40350aadb33SDmitri Tikhonov size_t i; 40450aadb33SDmitri Tikhonov uint8_t *start = out; 40550aadb33SDmitri Tikhonov for(i=0; i<entries_count; ++i) 40650aadb33SDmitri Tikhonov { 40750aadb33SDmitri Tikhonov *out++ = (uint8_t)(entries[i].type); 40850aadb33SDmitri Tikhonov switch (entries[i].type) 40950aadb33SDmitri Tikhonov { 41050aadb33SDmitri Tikhonov case ENTRY_COMPRESSED: 41150aadb33SDmitri Tikhonov break; 41250aadb33SDmitri Tikhonov case ENTRY_CACHED: 41350aadb33SDmitri Tikhonov memcpy(out, &entries[i].hash, sizeof(uint64_t)); 41450aadb33SDmitri Tikhonov out += sizeof(uint64_t); 41550aadb33SDmitri Tikhonov break; 41650aadb33SDmitri Tikhonov case ENTRY_COMMON: 41750aadb33SDmitri Tikhonov memcpy(out, &entries[i].set_hash, sizeof(uint64_t)); 41850aadb33SDmitri Tikhonov out += sizeof(uint64_t); 41950aadb33SDmitri Tikhonov memcpy(out, &entries[i].index, sizeof(uint32_t)); 42050aadb33SDmitri Tikhonov out += sizeof(uint32_t); 42150aadb33SDmitri Tikhonov break; 42250aadb33SDmitri Tikhonov default: 42350aadb33SDmitri Tikhonov break; 42450aadb33SDmitri Tikhonov } 42550aadb33SDmitri Tikhonov } 42650aadb33SDmitri Tikhonov 42750aadb33SDmitri Tikhonov *out++ = 0; // end marker 42850aadb33SDmitri Tikhonov *out_len = out - start; 42950aadb33SDmitri Tikhonov} 43050aadb33SDmitri Tikhonov 43150aadb33SDmitri Tikhonov 432a5fa05f9SDmitri Tikhonovint 433a5fa05f9SDmitri Tikhonovlsquic_get_certs_count(lsquic_str_t *compressed_crt_buf) 43450aadb33SDmitri Tikhonov{ 43550aadb33SDmitri Tikhonov char *in = lsquic_str_buf(compressed_crt_buf); 43650aadb33SDmitri Tikhonov char *in_end = in + lsquic_str_len(compressed_crt_buf); 43750aadb33SDmitri Tikhonov size_t idx = 0; 43850aadb33SDmitri Tikhonov uint8_t type_byte; 43950aadb33SDmitri Tikhonov 44050aadb33SDmitri Tikhonov for (;;) 44150aadb33SDmitri Tikhonov { 44250aadb33SDmitri Tikhonov if (in >= in_end) 44350aadb33SDmitri Tikhonov return -1; 44450aadb33SDmitri Tikhonov 44550aadb33SDmitri Tikhonov type_byte = in[0]; 44650aadb33SDmitri Tikhonov ++in; 44750aadb33SDmitri Tikhonov if (type_byte == 0) 44850aadb33SDmitri Tikhonov break; 44950aadb33SDmitri Tikhonov 45050aadb33SDmitri Tikhonov ++idx; 45150aadb33SDmitri Tikhonov switch(type_byte) 45250aadb33SDmitri Tikhonov { 45350aadb33SDmitri Tikhonov case ENTRY_COMPRESSED: 45450aadb33SDmitri Tikhonov break; 45550aadb33SDmitri Tikhonov case ENTRY_CACHED: 45650aadb33SDmitri Tikhonov { 45750aadb33SDmitri Tikhonov if (in_end - in < (int)sizeof(uint64_t)) 45850aadb33SDmitri Tikhonov return -1; 45950aadb33SDmitri Tikhonov in += sizeof(uint64_t); 46050aadb33SDmitri Tikhonov break; 46150aadb33SDmitri Tikhonov } 46250aadb33SDmitri Tikhonov case ENTRY_COMMON: 46350aadb33SDmitri Tikhonov { 46450aadb33SDmitri Tikhonov if (in_end - in < (int)(sizeof(uint64_t) + sizeof(uint32_t))) 46550aadb33SDmitri Tikhonov return -1; 46650aadb33SDmitri Tikhonov in += sizeof(uint64_t) + sizeof(uint32_t); 46750aadb33SDmitri Tikhonov break; 46850aadb33SDmitri Tikhonov } 46950aadb33SDmitri Tikhonov default: 47050aadb33SDmitri Tikhonov return -1; 47150aadb33SDmitri Tikhonov } 47250aadb33SDmitri Tikhonov } 47350aadb33SDmitri Tikhonov return idx; 47450aadb33SDmitri Tikhonov} 47550aadb33SDmitri Tikhonov 47650aadb33SDmitri Tikhonov 47750aadb33SDmitri Tikhonov/* return 0: OK, -1, error */ 47850aadb33SDmitri Tikhonovstatic int parse_entries(const unsigned char **in_out, const unsigned char *const in_end, 47950aadb33SDmitri Tikhonov lsquic_str_t *cached_certs, size_t cached_certs_count, 48050aadb33SDmitri Tikhonov cert_entry_t *out_entries, 48150aadb33SDmitri Tikhonov lsquic_str_t **out_certs, size_t *out_certs_count) 48250aadb33SDmitri Tikhonov{ 48350aadb33SDmitri Tikhonov const unsigned char *in = *in_out; 48450aadb33SDmitri Tikhonov size_t idx = 0; 48550aadb33SDmitri Tikhonov uint64_t* cached_hashes; 48650aadb33SDmitri Tikhonov cert_entry_t *entry; 48750aadb33SDmitri Tikhonov lsquic_str_t *cert; 48850aadb33SDmitri Tikhonov uint8_t type_byte; 48950aadb33SDmitri Tikhonov int rv; 49050aadb33SDmitri Tikhonov size_t i; 49150aadb33SDmitri Tikhonov 49250aadb33SDmitri Tikhonov cached_hashes = NULL; 49350aadb33SDmitri Tikhonov 49450aadb33SDmitri Tikhonov for (;;) 49550aadb33SDmitri Tikhonov { 49650aadb33SDmitri Tikhonov /* XXX potential invalid read */ 49750aadb33SDmitri Tikhonov type_byte = in[0]; 49850aadb33SDmitri Tikhonov ++in; 49950aadb33SDmitri Tikhonov 50050aadb33SDmitri Tikhonov if (type_byte == 0) 50150aadb33SDmitri Tikhonov break; 50250aadb33SDmitri Tikhonov 50350aadb33SDmitri Tikhonov entry = &out_entries[idx]; 50450aadb33SDmitri Tikhonov cert = out_certs[idx]; 50550aadb33SDmitri Tikhonov /* XXX This seems dangerous -- there is no guard that `idx' does not 50650aadb33SDmitri Tikhonov * exceed `out_certs_count'. 50750aadb33SDmitri Tikhonov */ 50850aadb33SDmitri Tikhonov lsquic_str_d(cert); 50950aadb33SDmitri Tikhonov 51050aadb33SDmitri Tikhonov ++idx; 51150aadb33SDmitri Tikhonov entry->type = type_byte; 51250aadb33SDmitri Tikhonov switch (entry->type) 51350aadb33SDmitri Tikhonov { 51450aadb33SDmitri Tikhonov case ENTRY_COMPRESSED: 51550aadb33SDmitri Tikhonov break; 51650aadb33SDmitri Tikhonov case ENTRY_CACHED: 51750aadb33SDmitri Tikhonov { 51850aadb33SDmitri Tikhonov memcpy(&entry->hash, in, sizeof(uint64_t)); 51950aadb33SDmitri Tikhonov in += sizeof(uint64_t); 52050aadb33SDmitri Tikhonov 52150aadb33SDmitri Tikhonov if (!cached_hashes) 52250aadb33SDmitri Tikhonov { 52350aadb33SDmitri Tikhonov cached_hashes = malloc(cached_certs_count * sizeof(uint64_t));; 52450aadb33SDmitri Tikhonov if (!cached_hashes) 52550aadb33SDmitri Tikhonov goto err; 52650aadb33SDmitri Tikhonov get_certs_hash(cached_certs, cached_certs_count, cached_hashes); 52750aadb33SDmitri Tikhonov } 52850aadb33SDmitri Tikhonov 52950aadb33SDmitri Tikhonov for (i=0; i<cached_certs_count; ++i) 53050aadb33SDmitri Tikhonov { 53150aadb33SDmitri Tikhonov if (cached_hashes[i] == entry->hash) 53250aadb33SDmitri Tikhonov { 53350aadb33SDmitri Tikhonov lsquic_str_append(cert, lsquic_str_buf(&cached_certs[i]), 53450aadb33SDmitri Tikhonov lsquic_str_len(&cached_certs[i])); 53550aadb33SDmitri Tikhonov break; 53650aadb33SDmitri Tikhonov } 53750aadb33SDmitri Tikhonov } 53850aadb33SDmitri Tikhonov /* XXX: return -1 if not found? Logic removed in 53950aadb33SDmitri Tikhonov 4fd7e76bc031ac637e76c7f0930aff53f5b71705 */ 54050aadb33SDmitri Tikhonov break; 54150aadb33SDmitri Tikhonov } 54250aadb33SDmitri Tikhonov case ENTRY_COMMON: 54350aadb33SDmitri Tikhonov { 54450aadb33SDmitri Tikhonov memcpy(&entry->set_hash, in, sizeof(uint64_t)); 54550aadb33SDmitri Tikhonov in += sizeof(uint64_t); 54650aadb33SDmitri Tikhonov memcpy(&entry->index, in, sizeof(uint32_t)); 54750aadb33SDmitri Tikhonov in += sizeof(uint32_t); 54850aadb33SDmitri Tikhonov 549a5fa05f9SDmitri Tikhonov if (0 == lsquic_get_common_cert(entry->set_hash, entry->index, cert)) 55050aadb33SDmitri Tikhonov break; 55150aadb33SDmitri Tikhonov else 55250aadb33SDmitri Tikhonov goto err; 55350aadb33SDmitri Tikhonov } 55450aadb33SDmitri Tikhonov default: 55550aadb33SDmitri Tikhonov goto err; 55650aadb33SDmitri Tikhonov } 55750aadb33SDmitri Tikhonov } 55850aadb33SDmitri Tikhonov 55950aadb33SDmitri Tikhonov rv = 0; 56050aadb33SDmitri Tikhonov *in_out = in; 56150aadb33SDmitri Tikhonov *out_certs_count = idx; 56250aadb33SDmitri Tikhonov 56350aadb33SDmitri Tikhonov cleanup: 56450aadb33SDmitri Tikhonov free(cached_hashes); 56550aadb33SDmitri Tikhonov return rv; 56650aadb33SDmitri Tikhonov 56750aadb33SDmitri Tikhonov err: 56850aadb33SDmitri Tikhonov rv = -1; 56950aadb33SDmitri Tikhonov goto cleanup; 57050aadb33SDmitri Tikhonov} 57150aadb33SDmitri Tikhonov 57250aadb33SDmitri Tikhonov 5735392f7a3SLiteSpeed Tech/* return 0 for OK */ 574a5fa05f9SDmitri Tikhonovint 575a5fa05f9SDmitri Tikhonovlsquic_compress_certs (lsquic_str_t **certs, size_t certs_count, 5765392f7a3SLiteSpeed Tech lsquic_str_t *client_common_set_hashes, 5775392f7a3SLiteSpeed Tech lsquic_str_t *client_cached_cert_hashes, 5785392f7a3SLiteSpeed Tech lsquic_str_t *result) 5795392f7a3SLiteSpeed Tech{ 5805392f7a3SLiteSpeed Tech int rv; 5815392f7a3SLiteSpeed Tech size_t i; 5825392f7a3SLiteSpeed Tech size_t uncompressed_size = 0, compressed_size = 0 ; 5835392f7a3SLiteSpeed Tech z_stream z; 5845392f7a3SLiteSpeed Tech lsquic_str_t *dict; 5855392f7a3SLiteSpeed Tech size_t entries_size, result_length; 5865392f7a3SLiteSpeed Tech int out_len; 5875392f7a3SLiteSpeed Tech uint8_t* out; 5885392f7a3SLiteSpeed Tech uint32_t tmp_size_32; 5895392f7a3SLiteSpeed Tech cert_entry_t *entries; 5905392f7a3SLiteSpeed Tech 5915392f7a3SLiteSpeed Tech entries = malloc(sizeof(cert_entry_t) * certs_count); 5925392f7a3SLiteSpeed Tech if (!entries) 5935392f7a3SLiteSpeed Tech return -1; 5945392f7a3SLiteSpeed Tech 5955392f7a3SLiteSpeed Tech dict = lsquic_str_new(NULL, 0); 5965392f7a3SLiteSpeed Tech if (!dict) 5975392f7a3SLiteSpeed Tech goto err; 5985392f7a3SLiteSpeed Tech 5995392f7a3SLiteSpeed Tech get_certs_entries(certs, certs_count, client_common_set_hashes, 6005392f7a3SLiteSpeed Tech client_cached_cert_hashes, entries); 6015392f7a3SLiteSpeed Tech 6025392f7a3SLiteSpeed Tech for (i = 0; i < certs_count; i++) 6035392f7a3SLiteSpeed Tech { 6045392f7a3SLiteSpeed Tech if (entries[i].type == ENTRY_COMPRESSED) 6055392f7a3SLiteSpeed Tech { 6065392f7a3SLiteSpeed Tech /*uint32_t length + cert content*/ 6075392f7a3SLiteSpeed Tech uncompressed_size += 4 + lsquic_str_len(certs[i]); 6085392f7a3SLiteSpeed Tech } 6095392f7a3SLiteSpeed Tech } 6105392f7a3SLiteSpeed Tech 6115392f7a3SLiteSpeed Tech if (uncompressed_size > 0) 6125392f7a3SLiteSpeed Tech { 6135392f7a3SLiteSpeed Tech memset(&z, 0, sizeof(z)); 6145392f7a3SLiteSpeed Tech if (Z_OK != deflateInit(&z, Z_DEFAULT_COMPRESSION)) 6155392f7a3SLiteSpeed Tech goto err; 6165392f7a3SLiteSpeed Tech 6175392f7a3SLiteSpeed Tech make_zlib_dict_for_entries(entries, certs, certs_count, dict); 6185392f7a3SLiteSpeed Tech if(Z_OK != deflateSetDictionary(&z, (const unsigned char *)lsquic_str_buf(dict), lsquic_str_len(dict))) 6195392f7a3SLiteSpeed Tech goto err; 6205392f7a3SLiteSpeed Tech compressed_size = deflateBound(&z, uncompressed_size); 6215392f7a3SLiteSpeed Tech } 6225392f7a3SLiteSpeed Tech 6235392f7a3SLiteSpeed Tech entries_size = get_entries_size(entries, certs_count); 6245392f7a3SLiteSpeed Tech result_length = entries_size + (uncompressed_size > 0 ? 4 : 0) + 6255392f7a3SLiteSpeed Tech compressed_size; 6265392f7a3SLiteSpeed Tech lsquic_str_prealloc(result, result_length); 6275392f7a3SLiteSpeed Tech 6285392f7a3SLiteSpeed Tech out = (unsigned char *)lsquic_str_buf(result); 6295392f7a3SLiteSpeed Tech serialize_cert_entries(out, &out_len, entries, certs_count); 6305392f7a3SLiteSpeed Tech out += entries_size; 6315392f7a3SLiteSpeed Tech 6325392f7a3SLiteSpeed Tech if (uncompressed_size == 0) 6335392f7a3SLiteSpeed Tech { 6345392f7a3SLiteSpeed Tech lsquic_str_setlen(result, entries_size); 6355392f7a3SLiteSpeed Tech rv = 0; 6365392f7a3SLiteSpeed Tech goto cleanup; 6375392f7a3SLiteSpeed Tech } 6385392f7a3SLiteSpeed Tech 6395392f7a3SLiteSpeed Tech tmp_size_32 = uncompressed_size; 6405392f7a3SLiteSpeed Tech memcpy(out, &tmp_size_32, sizeof(uint32_t)); 6415392f7a3SLiteSpeed Tech out += sizeof(uint32_t); 6425392f7a3SLiteSpeed Tech 6435392f7a3SLiteSpeed Tech z.next_out = out; 6445392f7a3SLiteSpeed Tech z.avail_out = compressed_size; 6455392f7a3SLiteSpeed Tech 6465392f7a3SLiteSpeed Tech for (i = 0; i < certs_count; ++i) 6475392f7a3SLiteSpeed Tech { 6485392f7a3SLiteSpeed Tech if (entries[i].type != ENTRY_COMPRESSED) 6495392f7a3SLiteSpeed Tech continue; 6505392f7a3SLiteSpeed Tech 6515392f7a3SLiteSpeed Tech tmp_size_32 = lsquic_str_len(certs[i]); 6525392f7a3SLiteSpeed Tech z.next_in = (uint8_t*)(&tmp_size_32); 6535392f7a3SLiteSpeed Tech z.avail_in = sizeof(tmp_size_32); 6545392f7a3SLiteSpeed Tech if (Z_OK != deflate(&z, Z_NO_FLUSH) || z.avail_in) 6555392f7a3SLiteSpeed Tech goto err; 6565392f7a3SLiteSpeed Tech z.next_in = (unsigned char *)lsquic_str_buf(certs[i]); 6575392f7a3SLiteSpeed Tech z.avail_in = lsquic_str_len(certs[i]); 6585392f7a3SLiteSpeed Tech if (Z_OK != deflate(&z, Z_NO_FLUSH) || z.avail_in) 6595392f7a3SLiteSpeed Tech goto err; 6605392f7a3SLiteSpeed Tech } 6615392f7a3SLiteSpeed Tech 6625392f7a3SLiteSpeed Tech z.avail_in = 0; 6635392f7a3SLiteSpeed Tech if (Z_STREAM_END != deflate(&z, Z_FINISH)) 6645392f7a3SLiteSpeed Tech goto err; 6655392f7a3SLiteSpeed Tech 6665392f7a3SLiteSpeed Tech rv = 0; 6675392f7a3SLiteSpeed Tech result_length -= z.avail_out; 6685392f7a3SLiteSpeed Tech lsquic_str_setlen(result, result_length); 6695392f7a3SLiteSpeed Tech 6705392f7a3SLiteSpeed Tech cleanup: 6715392f7a3SLiteSpeed Tech free(entries); 6725392f7a3SLiteSpeed Tech if (dict) 6735392f7a3SLiteSpeed Tech lsquic_str_delete(dict); 6745392f7a3SLiteSpeed Tech if (uncompressed_size) 6755392f7a3SLiteSpeed Tech deflateEnd(&z); 6765392f7a3SLiteSpeed Tech return rv; 6775392f7a3SLiteSpeed Tech 6785392f7a3SLiteSpeed Tech err: 6795392f7a3SLiteSpeed Tech rv = -1; 6805392f7a3SLiteSpeed Tech goto cleanup; 6815392f7a3SLiteSpeed Tech} 6825392f7a3SLiteSpeed Tech 6835392f7a3SLiteSpeed Tech 68450aadb33SDmitri Tikhonov/* 0: ok */ 685a5fa05f9SDmitri Tikhonovint 686a5fa05f9SDmitri Tikhonovlsquic_decompress_certs (const unsigned char *in, const unsigned char *in_end, 68750aadb33SDmitri Tikhonov lsquic_str_t *cached_certs, size_t cached_certs_count, 68850aadb33SDmitri Tikhonov lsquic_str_t **out_certs, size_t *out_certs_count) 68950aadb33SDmitri Tikhonov{ 69050aadb33SDmitri Tikhonov int ret; 69150aadb33SDmitri Tikhonov size_t i; 692b93f59beSBob Perper uint8_t* uncompressed_data, *uncompressed_data_buf; 69350aadb33SDmitri Tikhonov lsquic_str_t *dict; 69450aadb33SDmitri Tikhonov uint32_t uncompressed_size; 69550aadb33SDmitri Tikhonov size_t count = *out_certs_count; 69650aadb33SDmitri Tikhonov cert_entry_t *entries; 69750aadb33SDmitri Tikhonov z_stream z; 69850aadb33SDmitri Tikhonov 69950aadb33SDmitri Tikhonov assert(*out_certs_count > 0 && *out_certs_count < 10000 700a5fa05f9SDmitri Tikhonov && "Call lsquic_get_certs_count() to get right certificates count first and make enough room for out_certs_count"); 70150aadb33SDmitri Tikhonov 70250aadb33SDmitri Tikhonov if (count == 0 || count > 10000) 70350aadb33SDmitri Tikhonov return -1; 70450aadb33SDmitri Tikhonov 70550aadb33SDmitri Tikhonov dict = lsquic_str_new(NULL, 0); 70650aadb33SDmitri Tikhonov if (!dict) 70750aadb33SDmitri Tikhonov return -1; 70850aadb33SDmitri Tikhonov 70950aadb33SDmitri Tikhonov uncompressed_data_buf = NULL; 710b93f59beSBob Perper#ifdef WIN32 711b93f59beSBob Perper uncompressed_data = NULL; 712b93f59beSBob Perper#endif 71350aadb33SDmitri Tikhonov entries = malloc(count * sizeof(cert_entry_t)); 71450aadb33SDmitri Tikhonov if (!entries) 71550aadb33SDmitri Tikhonov goto err; 71650aadb33SDmitri Tikhonov 71750aadb33SDmitri Tikhonov ret = parse_entries(&in, in_end, cached_certs, cached_certs_count, 71850aadb33SDmitri Tikhonov entries, out_certs, out_certs_count); 71950aadb33SDmitri Tikhonov if (ret) 72050aadb33SDmitri Tikhonov goto err; 72150aadb33SDmitri Tikhonov 72250aadb33SDmitri Tikhonov /* re-assign count with real valus */ 72350aadb33SDmitri Tikhonov count = *out_certs_count; 72450aadb33SDmitri Tikhonov 72550aadb33SDmitri Tikhonov if (in < in_end) 72650aadb33SDmitri Tikhonov { 72750aadb33SDmitri Tikhonov if (in_end - in < (int)sizeof(uint32_t)) 72850aadb33SDmitri Tikhonov goto err; 72950aadb33SDmitri Tikhonov 73050aadb33SDmitri Tikhonov memcpy(&uncompressed_size, in, sizeof(uncompressed_size)); 73150aadb33SDmitri Tikhonov in += sizeof(uint32_t); 73250aadb33SDmitri Tikhonov /* XXX Is 128 KB an arbitrary limit or is there a reason behind it? */ 73350aadb33SDmitri Tikhonov if (uncompressed_size > 128 * 1024) 73450aadb33SDmitri Tikhonov goto err; 73550aadb33SDmitri Tikhonov 73650aadb33SDmitri Tikhonov uncompressed_data_buf = uncompressed_data = malloc(uncompressed_size); 737b93f59beSBob Perper if (!uncompressed_data) 738b93f59beSBob Perper goto err; 739b93f59beSBob Perper 74050aadb33SDmitri Tikhonov memset(&z, 0, sizeof(z)); 74150aadb33SDmitri Tikhonov z.next_out = uncompressed_data; 74250aadb33SDmitri Tikhonov z.avail_out = uncompressed_size; 74350aadb33SDmitri Tikhonov z.next_in = (unsigned char *) in; 74450aadb33SDmitri Tikhonov z.avail_in = in_end - in; 74550aadb33SDmitri Tikhonov 74650aadb33SDmitri Tikhonov if (Z_OK != inflateInit(&z)) 74750aadb33SDmitri Tikhonov goto err; 74850aadb33SDmitri Tikhonov 74950aadb33SDmitri Tikhonov ret = inflate(&z, Z_FINISH); 75050aadb33SDmitri Tikhonov if (ret == Z_NEED_DICT) 75150aadb33SDmitri Tikhonov { 75250aadb33SDmitri Tikhonov lsquic_str_d(dict); 75350aadb33SDmitri Tikhonov make_zlib_dict_for_entries(entries, out_certs, count, dict); 75450aadb33SDmitri Tikhonov if (Z_OK != inflateSetDictionary(&z, (const unsigned char *)lsquic_str_buf(dict), lsquic_str_len(dict))) 75550aadb33SDmitri Tikhonov goto err; 75650aadb33SDmitri Tikhonov ret = inflate(&z, Z_FINISH); 75750aadb33SDmitri Tikhonov } 75850aadb33SDmitri Tikhonov 75950aadb33SDmitri Tikhonov if (Z_STREAM_END != ret || z.avail_out > 0 || z.avail_in > 0) 76050aadb33SDmitri Tikhonov goto err; 76150aadb33SDmitri Tikhonov } 76250aadb33SDmitri Tikhonov else 76350aadb33SDmitri Tikhonov uncompressed_size = 0; 76450aadb33SDmitri Tikhonov 76550aadb33SDmitri Tikhonov for (i = 0; i < count; i++) 76650aadb33SDmitri Tikhonov { 76750aadb33SDmitri Tikhonov switch (entries[i].type) 76850aadb33SDmitri Tikhonov { 76950aadb33SDmitri Tikhonov case ENTRY_COMPRESSED: 77050aadb33SDmitri Tikhonov if (uncompressed_size < sizeof(uint32_t)) 77150aadb33SDmitri Tikhonov goto err; 77250aadb33SDmitri Tikhonov lsquic_str_d(out_certs[i]); 77350aadb33SDmitri Tikhonov uint32_t cert_len; 77450aadb33SDmitri Tikhonov memcpy(&cert_len, uncompressed_data, sizeof(cert_len)); 77550aadb33SDmitri Tikhonov uncompressed_data += sizeof(uint32_t); 77650aadb33SDmitri Tikhonov uncompressed_size -= sizeof(uint32_t); 77750aadb33SDmitri Tikhonov if (uncompressed_size < cert_len) 77850aadb33SDmitri Tikhonov goto err; 77950aadb33SDmitri Tikhonov lsquic_str_append(out_certs[i], (const char *)uncompressed_data, cert_len); 78050aadb33SDmitri Tikhonov uncompressed_data += cert_len; 78150aadb33SDmitri Tikhonov uncompressed_size -= cert_len; 78250aadb33SDmitri Tikhonov break; 78350aadb33SDmitri Tikhonov case ENTRY_CACHED: 78450aadb33SDmitri Tikhonov case ENTRY_COMMON: 78550aadb33SDmitri Tikhonov default: 78650aadb33SDmitri Tikhonov break; 78750aadb33SDmitri Tikhonov } 78850aadb33SDmitri Tikhonov } 78950aadb33SDmitri Tikhonov 79050aadb33SDmitri Tikhonov cleanup: 79150aadb33SDmitri Tikhonov lsquic_str_delete(dict); 79250aadb33SDmitri Tikhonov free(entries); 79350aadb33SDmitri Tikhonov if (uncompressed_data_buf) 79450aadb33SDmitri Tikhonov inflateEnd(&z); 79550aadb33SDmitri Tikhonov free(uncompressed_data_buf); 79650aadb33SDmitri Tikhonov if (0 == uncompressed_size) 79750aadb33SDmitri Tikhonov return 0; 79850aadb33SDmitri Tikhonov else 79950aadb33SDmitri Tikhonov return -1; 80050aadb33SDmitri Tikhonov 80150aadb33SDmitri Tikhonov err: 80250aadb33SDmitri Tikhonov uncompressed_size = 1; /* This triggers return -1 above */ 80350aadb33SDmitri Tikhonov goto cleanup; 80450aadb33SDmitri Tikhonov} 80550aadb33SDmitri Tikhonov 80650aadb33SDmitri Tikhonov 80750aadb33SDmitri Tikhonovvoid 80850aadb33SDmitri Tikhonovlsquic_crt_cleanup (void) 80950aadb33SDmitri Tikhonov{ 81050aadb33SDmitri Tikhonov if (s_ccsbuf) 81150aadb33SDmitri Tikhonov { 81250aadb33SDmitri Tikhonov lsquic_str_delete(s_ccsbuf); 81350aadb33SDmitri Tikhonov s_ccsbuf = NULL; 81450aadb33SDmitri Tikhonov } 81550aadb33SDmitri Tikhonov} 816