lsquic_crt_compress.c revision 355db7c6
1/* Copyright (c) 2017 - 2018 LiteSpeed Technologies Inc.  See LICENSE. */
2#include <assert.h>
3#include <stdbool.h>
4#include <string.h>
5#include <time.h>
6#include <zlib.h>
7
8#include <openssl/ssl.h>
9#ifndef WIN32
10#else
11#include <stdlib.h>
12#include <vc_compat.h>
13#endif
14
15#include "lsquic_int_types.h"
16#include "lsquic_crypto.h"
17#include "lsquic_crt_compress.h"
18#include "lsquic_util.h"
19
20#include "lsquic_str.h"
21
22#include "common_cert_set_2.c"
23#include "common_cert_set_3.c"
24
25/*
26 * common_cert_sub_strings contains ~1500 bytes of common certificate substrings
27 * as a dictionary of zlib from the Alexa Top 5000 set.
28 */
29static const unsigned char common_cert_sub_strings[] = {
30    0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04,
31    0x16, 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03,
32    0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30,
33    0x5f, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x04, 0x01,
34    0x06, 0x06, 0x0b, 0x60, 0x86, 0x48, 0x01, 0x86, 0xfd, 0x6d, 0x01, 0x07,
35    0x17, 0x01, 0x30, 0x33, 0x20, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65,
36    0x64, 0x20, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e,
37    0x20, 0x53, 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x31, 0x34,
38    0x20, 0x53, 0x53, 0x4c, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31,
39    0x32, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x53, 0x65, 0x72,
40    0x76, 0x65, 0x72, 0x20, 0x43, 0x41, 0x30, 0x2d, 0x61, 0x69, 0x61, 0x2e,
41    0x76, 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d,
42    0x2f, 0x45, 0x2d, 0x63, 0x72, 0x6c, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x73,
43    0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x45, 0x2e, 0x63, 0x65,
44    0x72, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
45    0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x4a, 0x2e, 0x63,
46    0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
47    0x2f, 0x63, 0x70, 0x73, 0x20, 0x28, 0x63, 0x29, 0x30, 0x30, 0x09, 0x06,
48    0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x30, 0x0d,
49    0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05,
50    0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x7b, 0x30, 0x1d, 0x06, 0x03, 0x55,
51    0x1d, 0x0e, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
52    0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01,
53    0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xd2,
54    0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x2e,
55    0x63, 0x72, 0x6c, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16,
56    0x04, 0x14, 0xb4, 0x2e, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x69,
57    0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x30, 0x0b, 0x06, 0x03,
58    0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x01, 0x30, 0x0d, 0x06, 0x09,
59    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30,
60    0x81, 0xca, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
61    0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x08,
62    0x13, 0x07, 0x41, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x61, 0x31, 0x13, 0x30,
63    0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0a, 0x53, 0x63, 0x6f, 0x74,
64    0x74, 0x73, 0x64, 0x61, 0x6c, 0x65, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03,
65    0x55, 0x04, 0x0a, 0x13, 0x11, 0x47, 0x6f, 0x44, 0x61, 0x64, 0x64, 0x79,
66    0x2e, 0x63, 0x6f, 0x6d, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x33,
67    0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x68, 0x74, 0x74,
68    0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
69    0x61, 0x74, 0x65, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79,
70    0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74,
71    0x6f, 0x72, 0x79, 0x31, 0x30, 0x30, 0x2e, 0x06, 0x03, 0x55, 0x04, 0x03,
72    0x13, 0x27, 0x47, 0x6f, 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, 0x20, 0x53,
73    0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66,
74    0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68,
75    0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55,
76    0x04, 0x05, 0x13, 0x08, 0x30, 0x37, 0x39, 0x36, 0x39, 0x32, 0x38, 0x37,
77    0x30, 0x1e, 0x17, 0x0d, 0x31, 0x31, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d,
78    0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0c,
79    0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00,
80    0x30, 0x1d, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
81    0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55,
82    0x1d, 0x25, 0x04, 0x16, 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05,
83    0x05, 0x07, 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
84    0x03, 0x02, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff,
85    0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x33, 0x06, 0x03, 0x55, 0x1d,
86    0x1f, 0x04, 0x2c, 0x30, 0x2a, 0x30, 0x28, 0xa0, 0x26, 0xa0, 0x24, 0x86,
87    0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e,
88    0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
89    0x67, 0x64, 0x73, 0x31, 0x2d, 0x32, 0x30, 0x2a, 0x30, 0x28, 0x06, 0x08,
90    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x1c, 0x68, 0x74,
91    0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x65,
92    0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63,
93    0x70, 0x73, 0x30, 0x34, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17,
94    0x0d, 0x31, 0x33, 0x30, 0x35, 0x30, 0x39, 0x06, 0x08, 0x2b, 0x06, 0x01,
95    0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x2d, 0x68, 0x74, 0x74, 0x70, 0x3a,
96    0x2f, 0x2f, 0x73, 0x30, 0x39, 0x30, 0x37, 0x06, 0x08, 0x2b, 0x06, 0x01,
97    0x05, 0x05, 0x07, 0x02, 0x30, 0x44, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04,
98    0x3d, 0x30, 0x3b, 0x30, 0x39, 0x06, 0x0b, 0x60, 0x86, 0x48, 0x01, 0x86,
99    0xf8, 0x45, 0x01, 0x07, 0x17, 0x06, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
100    0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x1b, 0x53, 0x31, 0x17,
101    0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56, 0x65, 0x72,
102    0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31,
103    0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x16, 0x56, 0x65,
104    0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74,
105    0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x31, 0x3b, 0x30, 0x39,
106    0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x32, 0x54, 0x65, 0x72, 0x6d, 0x73,
107    0x20, 0x6f, 0x66, 0x20, 0x75, 0x73, 0x65, 0x20, 0x61, 0x74, 0x20, 0x68,
108    0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76,
109    0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
110    0x72, 0x70, 0x61, 0x20, 0x28, 0x63, 0x29, 0x30, 0x31, 0x10, 0x30, 0x0e,
111    0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x31, 0x13, 0x30, 0x11,
112    0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0a, 0x47, 0x31, 0x13, 0x30, 0x11,
113    0x06, 0x0b, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x3c, 0x02, 0x01,
114    0x03, 0x13, 0x02, 0x55, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04,
115    0x03, 0x14, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
116    0x31, 0x1d, 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x0f, 0x13, 0x14, 0x50,
117    0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x20, 0x4f, 0x72, 0x67, 0x61, 0x6e,
118    0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x12, 0x31, 0x21, 0x30,
119    0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x18, 0x44, 0x6f, 0x6d, 0x61,
120    0x69, 0x6e, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x20, 0x56,
121    0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x64, 0x31, 0x14, 0x31, 0x31,
122    0x30, 0x2f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x28, 0x53, 0x65, 0x65,
123    0x20, 0x77, 0x77, 0x77, 0x2e, 0x72, 0x3a, 0x2f, 0x2f, 0x73, 0x65, 0x63,
124    0x75, 0x72, 0x65, 0x2e, 0x67, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53,
125    0x69, 0x67, 0x6e, 0x31, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x41,
126    0x2e, 0x63, 0x72, 0x6c, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e,
127    0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x45, 0x63, 0x72,
128    0x6c, 0x2e, 0x67, 0x65, 0x6f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63,
129    0x6f, 0x6d, 0x2f, 0x63, 0x72, 0x6c, 0x73, 0x2f, 0x73, 0x64, 0x31, 0x1a,
130    0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x68, 0x74, 0x74, 0x70, 0x3a,
131    0x2f, 0x2f, 0x45, 0x56, 0x49, 0x6e, 0x74, 0x6c, 0x2d, 0x63, 0x63, 0x72,
132    0x74, 0x2e, 0x67, 0x77, 0x77, 0x77, 0x2e, 0x67, 0x69, 0x63, 0x65, 0x72,
133    0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x31, 0x6f, 0x63, 0x73, 0x70, 0x2e,
134    0x76, 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d,
135    0x30, 0x39, 0x72, 0x61, 0x70, 0x69, 0x64, 0x73, 0x73, 0x6c, 0x2e, 0x63,
136    0x6f, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79, 0x2e, 0x63,
137    0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72,
138    0x79, 0x2f, 0x30, 0x81, 0x80, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
139    0x07, 0x01, 0x01, 0x04, 0x74, 0x30, 0x72, 0x30, 0x24, 0x06, 0x08, 0x2b,
140    0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x18, 0x68, 0x74, 0x74,
141    0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x67, 0x6f, 0x64,
142    0x61, 0x64, 0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x30, 0x4a, 0x06,
143    0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x3e, 0x68,
144    0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66,
145    0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64,
146    0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73,
147    0x69, 0x74, 0x6f, 0x72, 0x79, 0x2f, 0x67, 0x64, 0x5f, 0x69, 0x6e, 0x74,
148    0x65, 0x72, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x63, 0x72,
149    0x74, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16,
150    0x80, 0x14, 0xfd, 0xac, 0x61, 0x32, 0x93, 0x6c, 0x45, 0xd6, 0xe2, 0xee,
151    0x85, 0x5f, 0x9a, 0xba, 0xe7, 0x76, 0x99, 0x68, 0xcc, 0xe7, 0x30, 0x27,
152    0x86, 0x29, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x86, 0x30,
153    0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x73,
154};
155
156#define common_certs_num 2
157const common_cert_t common_cert_set[common_certs_num] = {
158    {common_certs2_num, common_certs2, common_certs2_lens, common_certs2_hash},
159    {common_certs3_num, common_certs3, common_certs3_lens, common_certs3_hash},
160};
161
162
163static lsquic_str_t *s_ccsbuf;
164
165lsquic_str_t * get_common_certs_hash()
166{
167    int i;
168    if (s_ccsbuf == NULL)
169    {
170        s_ccsbuf = lsquic_str_new(NULL, 0);
171        for (i=0 ;i<common_certs_num; ++i)
172        {
173            lsquic_str_append(s_ccsbuf, (const char *)&common_cert_set[i].hash, 8);
174        }
175    }
176    return s_ccsbuf;
177}
178
179
180/* return 0 found, -1 not found */
181int get_common_cert(uint64_t hash, uint32_t index, lsquic_str_t *buf)
182{
183    int i;
184    for (i = 0; i < common_certs_num; i++)
185    {
186        if (common_cert_set[i].hash == hash)
187        {
188            if (index < common_cert_set[i].num_certs)
189            {
190                lsquic_str_setto(buf, (const char *) common_cert_set[i].certs[index],
191                         common_cert_set[i].lens[index]);
192                return 0;
193            }
194            break;
195        }
196    }
197    return -1;
198}
199
200
201/* result is written to dict */
202static void
203make_zlib_dict_for_entries(cert_entry_t *entries,
204                                lsquic_str_t **certs, size_t certs_count,
205                                lsquic_str_t *dict)
206{
207    int i;
208    size_t zlib_dict_size = 0;
209    for (i = certs_count - 1; i >= 0; --i)
210    {
211        if (entries[i].type != ENTRY_COMPRESSED)
212        {
213            zlib_dict_size += lsquic_str_len(certs[i]);
214        }
215    }
216
217    // At the end of the dictionary is a block of common certificate substrings.
218    zlib_dict_size += sizeof(common_cert_sub_strings);
219
220    for (i = certs_count - 1; i >= 0; --i)
221    {
222        if (entries[i].type != ENTRY_COMPRESSED)
223        {
224            lsquic_str_append(dict, lsquic_str_buf(certs[i]), lsquic_str_len(certs[i]));
225        }
226    }
227
228    lsquic_str_append(dict, (const char *)common_cert_sub_strings, sizeof(common_cert_sub_strings));
229    assert((size_t)lsquic_str_len(dict) == zlib_dict_size);
230}
231
232
233void get_certs_hash(lsquic_str_t *certs, size_t certs_count, uint64_t *hashs)
234{
235    size_t i;
236    for(i = 0; i < certs_count; ++i)
237    {
238        hashs[i] = fnv1a_64((const uint8_t *)lsquic_str_buf(&certs[i]), lsquic_str_len(&certs[i]));
239    }
240}
241
242
243size_t get_entries_size(cert_entry_t *entries, size_t entries_count)
244{
245    size_t i;
246    size_t entries_size = 0;
247    for(i=0; i<entries_count; ++i)
248    {
249        entries_size++;
250        switch (entries[i].type)
251        {
252        case ENTRY_COMPRESSED:
253            break;
254        case ENTRY_CACHED:
255            entries_size += sizeof(uint64_t);
256            break;
257        case ENTRY_COMMON:
258            entries_size += sizeof(uint64_t) + sizeof(uint32_t);
259            break;
260        default:
261            break;
262        }
263    }
264    entries_size++;  /* for end marker */
265    return entries_size;
266}
267
268
269void serialize_cert_entries(uint8_t* out, int *out_len, cert_entry_t *entries,
270                            size_t entries_count)
271{
272    size_t i;
273    uint8_t *start = out;
274    for(i=0; i<entries_count; ++i)
275    {
276        *out++ = (uint8_t)(entries[i].type);
277        switch (entries[i].type)
278        {
279        case ENTRY_COMPRESSED:
280            break;
281        case ENTRY_CACHED:
282            memcpy(out, &entries[i].hash, sizeof(uint64_t));
283            out += sizeof(uint64_t);
284            break;
285        case ENTRY_COMMON:
286            memcpy(out, &entries[i].set_hash, sizeof(uint64_t));
287            out += sizeof(uint64_t);
288            memcpy(out, &entries[i].index, sizeof(uint32_t));
289            out += sizeof(uint32_t);
290            break;
291        default:
292            break;
293        }
294    }
295
296    *out++ = 0;  // end marker
297    *out_len = out - start;
298}
299
300
301int get_certs_count(lsquic_str_t *compressed_crt_buf)
302{
303    char *in = lsquic_str_buf(compressed_crt_buf);
304    char *in_end = in + lsquic_str_len(compressed_crt_buf);
305    size_t idx = 0;
306    uint8_t type_byte;
307
308    for (;;)
309    {
310        if (in >= in_end)
311            return -1;
312
313        type_byte = in[0];
314        ++in;
315        if (type_byte == 0)
316            break;
317
318        ++idx;
319        switch(type_byte)
320        {
321        case ENTRY_COMPRESSED:
322            break;
323        case ENTRY_CACHED:
324        {
325            if (in_end - in < (int)sizeof(uint64_t))
326                return -1;
327            in += sizeof(uint64_t);
328            break;
329        }
330        case ENTRY_COMMON:
331        {
332            if (in_end - in < (int)(sizeof(uint64_t) + sizeof(uint32_t)))
333                return -1;
334            in += sizeof(uint64_t) + sizeof(uint32_t);
335            break;
336        }
337        default:
338            return -1;
339        }
340    }
341    return idx;
342}
343
344
345/* return 0: OK, -1, error */
346static int parse_entries(const unsigned char **in_out, const unsigned char *const in_end,
347                         lsquic_str_t *cached_certs, size_t cached_certs_count,
348                         cert_entry_t *out_entries,
349                         lsquic_str_t **out_certs, size_t *out_certs_count)
350{
351    const unsigned char *in = *in_out;
352    size_t idx = 0;
353    uint64_t* cached_hashes;
354    cert_entry_t *entry;
355    lsquic_str_t *cert;
356    uint8_t type_byte;
357    int rv;
358    size_t i;
359
360    cached_hashes = NULL;
361
362    for (;;)
363    {
364        /* XXX potential invalid read */
365        type_byte = in[0];
366        ++in;
367
368        if (type_byte == 0)
369            break;
370
371        entry = &out_entries[idx];
372        cert = out_certs[idx];
373        /* XXX This seems dangerous -- there is no guard that `idx' does not
374         * exceed `out_certs_count'.
375         */
376        lsquic_str_d(cert);
377
378        ++idx;
379        entry->type = type_byte;
380        switch (entry->type)
381        {
382        case ENTRY_COMPRESSED:
383            break;
384        case ENTRY_CACHED:
385        {
386            memcpy(&entry->hash, in, sizeof(uint64_t));
387            in += sizeof(uint64_t);
388
389            if (!cached_hashes)
390            {
391                cached_hashes = malloc(cached_certs_count * sizeof(uint64_t));;
392                if (!cached_hashes)
393                    goto err;
394                get_certs_hash(cached_certs, cached_certs_count, cached_hashes);
395            }
396
397            for (i=0; i<cached_certs_count; ++i)
398            {
399                if (cached_hashes[i] == entry->hash)
400                {
401                    lsquic_str_append(cert, lsquic_str_buf(&cached_certs[i]),
402                                  lsquic_str_len(&cached_certs[i]));
403                    break;
404                }
405            }
406            /* XXX: return -1 if not found?  Logic removed in
407                                4fd7e76bc031ac637e76c7f0930aff53f5b71705 */
408            break;
409        }
410        case ENTRY_COMMON:
411        {
412            memcpy(&entry->set_hash, in, sizeof(uint64_t));
413            in += sizeof(uint64_t);
414            memcpy(&entry->index, in, sizeof(uint32_t));
415            in += sizeof(uint32_t);
416
417            if (0 == get_common_cert(entry->set_hash, entry->index, cert))
418                break;
419            else
420                goto err;
421        }
422        default:
423            goto err;
424        }
425    }
426
427    rv = 0;
428    *in_out = in;
429    *out_certs_count = idx;
430
431  cleanup:
432    free(cached_hashes);
433    return rv;
434
435  err:
436    rv = -1;
437    goto cleanup;
438}
439
440
441/* 0: ok */
442int decompress_certs(const unsigned char *in, const unsigned char *in_end,
443                     lsquic_str_t *cached_certs, size_t cached_certs_count,
444                     lsquic_str_t **out_certs, size_t *out_certs_count)
445{
446    int ret;
447    size_t i;
448    uint8_t* uncompressed_data, *uncompressed_data_buf;
449    lsquic_str_t *dict;
450    uint32_t uncompressed_size;
451    size_t count = *out_certs_count;
452    cert_entry_t *entries;
453    z_stream z;
454
455    assert(*out_certs_count > 0 && *out_certs_count < 10000
456            && "Call get_certs_count() to get right certificates count first and make enough room for out_certs_count");
457
458    if (count == 0 || count > 10000)
459        return -1;
460
461    dict = lsquic_str_new(NULL, 0);
462    if (!dict)
463        return -1;
464
465    uncompressed_data_buf = NULL;
466#ifdef WIN32
467    uncompressed_data = NULL;
468#endif
469    entries = malloc(count * sizeof(cert_entry_t));
470    if (!entries)
471        goto err;
472
473    ret = parse_entries(&in, in_end, cached_certs, cached_certs_count,
474                  entries, out_certs, out_certs_count);
475    if (ret)
476        goto err;
477
478    /* re-assign count with real valus */
479    count = *out_certs_count;
480
481    if (in < in_end)
482    {
483        if (in_end - in < (int)sizeof(uint32_t))
484            goto err;
485
486        memcpy(&uncompressed_size, in, sizeof(uncompressed_size));
487        in += sizeof(uint32_t);
488        /* XXX Is 128 KB an arbitrary limit or is there a reason behind it? */
489        if (uncompressed_size > 128 * 1024)
490            goto err;
491
492        uncompressed_data_buf = uncompressed_data = malloc(uncompressed_size);
493        if (!uncompressed_data)
494            goto err;
495
496        memset(&z, 0, sizeof(z));
497        z.next_out  = uncompressed_data;
498        z.avail_out = uncompressed_size;
499        z.next_in   = (unsigned char *) in;
500        z.avail_in  = in_end - in;
501
502        if (Z_OK != inflateInit(&z))
503            goto err;
504
505        ret = inflate(&z, Z_FINISH);
506        if (ret == Z_NEED_DICT)
507        {
508            lsquic_str_d(dict);
509            make_zlib_dict_for_entries(entries, out_certs, count, dict);
510            if (Z_OK != inflateSetDictionary(&z, (const unsigned char *)lsquic_str_buf(dict), lsquic_str_len(dict)))
511                goto err;
512            ret = inflate(&z, Z_FINISH);
513        }
514
515        if (Z_STREAM_END != ret || z.avail_out > 0 || z.avail_in > 0)
516            goto err;
517    }
518    else
519        uncompressed_size = 0;
520
521    for (i = 0; i < count; i++)
522    {
523        switch (entries[i].type)
524        {
525          case ENTRY_COMPRESSED:
526              if (uncompressed_size < sizeof(uint32_t))
527                  goto err;
528              lsquic_str_d(out_certs[i]);
529              uint32_t cert_len;
530              memcpy(&cert_len, uncompressed_data, sizeof(cert_len));
531              uncompressed_data += sizeof(uint32_t);
532              uncompressed_size -= sizeof(uint32_t);
533              if (uncompressed_size < cert_len)
534                  goto err;
535              lsquic_str_append(out_certs[i], (const char *)uncompressed_data, cert_len);
536              uncompressed_data += cert_len;
537              uncompressed_size -= cert_len;
538              break;
539          case ENTRY_CACHED:
540          case ENTRY_COMMON:
541          default:
542            break;
543        }
544    }
545
546  cleanup:
547    lsquic_str_delete(dict);
548    free(entries);
549    if (uncompressed_data_buf)
550        inflateEnd(&z);
551    free(uncompressed_data_buf);
552    if (0 == uncompressed_size)
553        return 0;
554    else
555        return -1;
556
557  err:
558    uncompressed_size = 1;  /* This triggers return -1 above */
559    goto cleanup;
560}
561
562
563void
564lsquic_crt_cleanup (void)
565{
566    if (s_ccsbuf)
567    {
568        lsquic_str_delete(s_ccsbuf);
569        s_ccsbuf = NULL;
570    }
571}
572