1 /*
2 * Copyright (c) 2024 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/net/http/hpack.h>
8 #include <zephyr/net/net_ip.h>
9 #include <zephyr/ztest.h>
10
11 struct huffman_codes {
12 uint32_t code;
13 uint8_t bitlen;
14 };
15
16 /* Copy-paste from RFC7541. */
17 static struct huffman_codes test_huffman_codes[] = {
18 { 0x1ff8, 13, }, { 0x7fffd8, 23, }, { 0xfffffe2, 28, }, { 0xfffffe3, 28, },
19 { 0xfffffe4, 28, }, { 0xfffffe5, 28, }, { 0xfffffe6, 28, }, { 0xfffffe7, 28, },
20 { 0xfffffe8, 28, }, { 0xffffea, 24, }, { 0x3ffffffc, 30, }, { 0xfffffe9, 28, },
21 { 0xfffffea, 28, }, { 0x3ffffffd, 30, }, { 0xfffffeb, 28, }, { 0xfffffec, 28, },
22 { 0xfffffed, 28, }, { 0xfffffee, 28, }, { 0xfffffef, 28, }, { 0xffffff0, 28, },
23 { 0xffffff1, 28, }, { 0xffffff2, 28, }, { 0x3ffffffe, 30, }, { 0xffffff3, 28, },
24 { 0xffffff4, 28, }, { 0xffffff5, 28, }, { 0xffffff6, 28, }, { 0xffffff7, 28, },
25 { 0xffffff8, 28, }, { 0xffffff9, 28, }, { 0xffffffa, 28, }, { 0xffffffb, 28, },
26 { 0x14, 6, }, { 0x3f8, 10, }, { 0x3f9, 10, }, { 0xffa, 12, },
27 { 0x1ff9, 13, }, { 0x15, 6, }, { 0xf8, 8, }, { 0x7fa, 11, },
28 { 0x3fa, 10, }, { 0x3fb, 10, }, { 0xf9, 8, }, { 0x7fb, 11, },
29 { 0xfa, 8, }, { 0x16, 6, }, { 0x17, 6, }, { 0x18, 6, },
30 { 0x0, 5, }, { 0x1, 5, }, { 0x2, 5, }, { 0x19, 6, },
31 { 0x1a, 6, }, { 0x1b, 6, }, { 0x1c, 6, }, { 0x1d, 6, },
32 { 0x1e, 6, }, { 0x1f, 6, }, { 0x5c, 7, }, { 0xfb, 8, },
33 { 0x7ffc, 15, }, { 0x20, 6, }, { 0xffb, 12, }, { 0x3fc, 10, },
34 { 0x1ffa, 13, }, { 0x21, 6, }, { 0x5d, 7, }, { 0x5e, 7, },
35 { 0x5f, 7, }, { 0x60, 7, }, { 0x61, 7, }, { 0x62, 7, },
36 { 0x63, 7, }, { 0x64, 7, }, { 0x65, 7, }, { 0x66, 7, },
37 { 0x67, 7, }, { 0x68, 7, }, { 0x69, 7, }, { 0x6a, 7, },
38 { 0x6b, 7, }, { 0x6c, 7, }, { 0x6d, 7, }, { 0x6e, 7, },
39 { 0x6f, 7, }, { 0x70, 7, }, { 0x71, 7, }, { 0x72, 7, },
40 { 0xfc, 8, }, { 0x73, 7, }, { 0xfd, 8, }, { 0x1ffb, 13, },
41 { 0x7fff0, 19, }, { 0x1ffc, 13, }, { 0x3ffc, 14, }, { 0x22, 6, },
42 { 0x7ffd, 15, }, { 0x3, 5, }, { 0x23, 6, }, { 0x4, 5, },
43 { 0x24, 6, }, { 0x5, 5, }, { 0x25, 6, }, { 0x26, 6, },
44 { 0x27, 6, }, { 0x6, 5, }, { 0x74, 7, }, { 0x75, 7, },
45 { 0x28, 6, }, { 0x29, 6, }, { 0x2a, 6, }, { 0x7, 5, },
46 { 0x2b, 6, }, { 0x76, 7, }, { 0x2c, 6, }, { 0x8, 5, },
47 { 0x9, 5, }, { 0x2d, 6, }, { 0x77, 7, }, { 0x78, 7, },
48 { 0x79, 7, }, { 0x7a, 7, }, { 0x7b, 7, }, { 0x7ffe, 15, },
49 { 0x7fc, 11, }, { 0x3ffd, 14, }, { 0x1ffd, 13, }, { 0xffffffc, 28, },
50 { 0xfffe6, 20, }, { 0x3fffd2, 22, }, { 0xfffe7, 20, }, { 0xfffe8, 20, },
51 { 0x3fffd3, 22, }, { 0x3fffd4, 22, }, { 0x3fffd5, 22, }, { 0x7fffd9, 23, },
52 { 0x3fffd6, 22, }, { 0x7fffda, 23, }, { 0x7fffdb, 23, }, { 0x7fffdc, 23, },
53 { 0x7fffdd, 23, }, { 0x7fffde, 23, }, { 0xffffeb, 24, }, { 0x7fffdf, 23, },
54 { 0xffffec, 24, }, { 0xffffed, 24, }, { 0x3fffd7, 22, }, { 0x7fffe0, 23, },
55 { 0xffffee, 24, }, { 0x7fffe1, 23, }, { 0x7fffe2, 23, }, { 0x7fffe3, 23, },
56 { 0x7fffe4, 23, }, { 0x1fffdc, 21, }, { 0x3fffd8, 22, }, { 0x7fffe5, 23, },
57 { 0x3fffd9, 22, }, { 0x7fffe6, 23, }, { 0x7fffe7, 23, }, { 0xffffef, 24, },
58 { 0x3fffda, 22, }, { 0x1fffdd, 21, }, { 0xfffe9, 20, }, { 0x3fffdb, 22, },
59 { 0x3fffdc, 22, }, { 0x7fffe8, 23, }, { 0x7fffe9, 23, }, { 0x1fffde, 21, },
60 { 0x7fffea, 23, }, { 0x3fffdd, 22, }, { 0x3fffde, 22, }, { 0xfffff0, 24, },
61 { 0x1fffdf, 21, }, { 0x3fffdf, 22, }, { 0x7fffeb, 23, }, { 0x7fffec, 23, },
62 { 0x1fffe0, 21, }, { 0x1fffe1, 21, }, { 0x3fffe0, 22, }, { 0x1fffe2, 21, },
63 { 0x7fffed, 23, }, { 0x3fffe1, 22, }, { 0x7fffee, 23, }, { 0x7fffef, 23, },
64 { 0xfffea, 20, }, { 0x3fffe2, 22, }, { 0x3fffe3, 22, }, { 0x3fffe4, 22, },
65 { 0x7ffff0, 23, }, { 0x3fffe5, 22, }, { 0x3fffe6, 22, }, { 0x7ffff1, 23, },
66 { 0x3ffffe0, 26, }, { 0x3ffffe1, 26, }, { 0xfffeb, 20, }, { 0x7fff1, 19, },
67 { 0x3fffe7, 22, }, { 0x7ffff2, 23, }, { 0x3fffe8, 22, }, { 0x1ffffec, 25, },
68 { 0x3ffffe2, 26, }, { 0x3ffffe3, 26, }, { 0x3ffffe4, 26, }, { 0x7ffffde, 27, },
69 { 0x7ffffdf, 27, }, { 0x3ffffe5, 26, }, { 0xfffff1, 24, }, { 0x1ffffed, 25, },
70 { 0x7fff2, 19, }, { 0x1fffe3, 21, }, { 0x3ffffe6, 26, }, { 0x7ffffe0, 27, },
71 { 0x7ffffe1, 27, }, { 0x3ffffe7, 26, }, { 0x7ffffe2, 27, }, { 0xfffff2, 24, },
72 { 0x1fffe4, 21, }, { 0x1fffe5, 21, }, { 0x3ffffe8, 26, }, { 0x3ffffe9, 26, },
73 { 0xffffffd, 28, }, { 0x7ffffe3, 27, }, { 0x7ffffe4, 27, }, { 0x7ffffe5, 27, },
74 { 0xfffec, 20, }, { 0xfffff3, 24, }, { 0xfffed, 20, }, { 0x1fffe6, 21, },
75 { 0x3fffe9, 22, }, { 0x1fffe7, 21, }, { 0x1fffe8, 21, }, { 0x7ffff3, 23, },
76 { 0x3fffea, 22, }, { 0x3fffeb, 22, }, { 0x1ffffee, 25, }, { 0x1ffffef, 25, },
77 { 0xfffff4, 24, }, { 0xfffff5, 24, }, { 0x3ffffea, 26, }, { 0x7ffff4, 23, },
78 { 0x3ffffeb, 26, }, { 0x7ffffe6, 27, }, { 0x3ffffec, 26, }, { 0x3ffffed, 26, },
79 { 0x7ffffe7, 27, }, { 0x7ffffe8, 27, }, { 0x7ffffe9, 27, }, { 0x7ffffea, 27, },
80 { 0x7ffffeb, 27, }, { 0xffffffe, 28, }, { 0x7ffffec, 27, }, { 0x7ffffed, 27, },
81 { 0x7ffffee, 27, }, { 0x7ffffef, 27, }, { 0x7fffff0, 27, }, { 0x3ffffee, 26, },
82 };
83
84 /* Prepare a MSB aligned Huffman code, with padding. */
test_huffman_code_prepare(uint32_t * buf,int index)85 static void test_huffman_code_prepare(uint32_t *buf, int index)
86 {
87 uint8_t pad_len = 32 - test_huffman_codes[index].bitlen;
88
89 *buf = test_huffman_codes[index].code;
90 /* Prepare buffer - align to MSB, add padding and covert to
91 * network byte order.
92 */
93 *buf <<= pad_len;
94 *buf |= (1UL << pad_len) - 1UL;
95 *buf = htonl(*buf);
96 }
97
ZTEST(http2_hpack,test_huffman_encode_single)98 ZTEST(http2_hpack, test_huffman_encode_single)
99 {
100 ARRAY_FOR_EACH(test_huffman_codes, i) {
101 uint8_t expected_len = DIV_ROUND_UP(test_huffman_codes[i].bitlen, 8);
102 uint32_t expected;
103 uint32_t buf = 0;
104 uint8_t symbol = i;
105 int ret;
106
107 test_huffman_code_prepare(&expected, i);
108
109 ret = http_hpack_huffman_encode(&symbol, 1, (uint8_t *)&buf, sizeof(buf));
110 zassert_equal(ret, expected_len, "Wrong encoding length");
111 zassert_mem_equal(&buf, &expected, expected_len,
112 "Symbol wrongly encoded");
113 }
114 }
115
ZTEST(http2_hpack,test_huffman_decode_single)116 ZTEST(http2_hpack, test_huffman_decode_single)
117 {
118 ARRAY_FOR_EACH(test_huffman_codes, i) {
119 uint8_t buflen = DIV_ROUND_UP(test_huffman_codes[i].bitlen, 8);
120 uint32_t buf;
121 uint8_t symbol;
122 int ret;
123
124 test_huffman_code_prepare(&buf, i);
125
126 ret = http_hpack_huffman_decode((uint8_t *)&buf, buflen, &symbol, 1);
127 zassert_equal(ret, 1, "Expected to decode 1 symbol");
128 zassert_equal(symbol, i, "Wrong symbol decoded");
129 }
130 }
131
132 static uint8_t test_buf[600];
133
ZTEST(http2_hpack,test_huffman_encode_decode_all)134 ZTEST(http2_hpack, test_huffman_encode_decode_all)
135 {
136 uint8_t str[ARRAY_SIZE(test_huffman_codes)];
137 int expected_len = 0;
138 int ret;
139
140 ARRAY_FOR_EACH(str, i) {
141 expected_len += test_huffman_codes[i].bitlen;
142 str[i] = i;
143 }
144
145 expected_len = DIV_ROUND_UP(expected_len, 8);
146
147 ret = http_hpack_huffman_encode(str, sizeof(str), test_buf, sizeof(test_buf));
148 zassert_equal(ret, expected_len, "Wrong encoded length");
149 memset(str, 0, sizeof(str));
150 ret = http_hpack_huffman_decode(test_buf, expected_len, str, sizeof(str));
151 zassert_equal(ret, sizeof(str), "Wrong decoded length");
152
153 ARRAY_FOR_EACH(str, i) {
154 expected_len += test_huffman_codes[i].bitlen;
155 zassert_equal(str[i], i, "Wrong symbol decoded");
156 }
157 }
158
159 struct example_huffman {
160 const char *str;
161 uint8_t encoded[46];
162 uint8_t encoded_len;
163 };
164
165 /* Encoding examples from RFC7541 */
166 static const struct example_huffman test_huffman[] = {
167 { "www.example.com",
168 { 0xf1, 0xe3, 0xc2, 0xe5, 0xf2, 0x3a, 0x6b, 0xa0,
169 0xab, 0x90, 0xf4, 0xff },
170 12 },
171 { "no-cache", { 0xa8, 0xeb, 0x10, 0x64, 0x9c, 0xbf }, 6 },
172 { "custom-key", { 0x25, 0xa8, 0x49, 0xe9, 0x5b, 0xa9, 0x7d, 0x7f }, 8 },
173 { "custom-value",
174 { 0x25, 0xa8, 0x49, 0xe9, 0x5b, 0xb8, 0xe8, 0xb4,
175 0xbf },
176 9 },
177 { "302", { 0x64, 0x02 }, 2 },
178 { "private", { 0xae, 0xc3, 0x77, 0x1a, 0x4b }, 5 },
179 { "Mon, 21 Oct 2013 20:13:21 GMT",
180 { 0xd0, 0x7a, 0xbe, 0x94, 0x10, 0x54, 0xd4, 0x44,
181 0xa8, 0x20, 0x05, 0x95, 0x04, 0x0b, 0x81, 0x66,
182 0xe0, 0x82, 0xa6, 0x2d, 0x1b, 0xff},
183 22 },
184 { "https://www.example.com",
185 { 0x9d, 0x29, 0xad, 0x17, 0x18, 0x63, 0xc7, 0x8f,
186 0x0b, 0x97, 0xc8, 0xe9, 0xae, 0x82, 0xae, 0x43,
187 0xd3},
188 17 },
189 { "307", { 0x64, 0x0e, 0xff }, 3 },
190 { "gzip", { 0x9b, 0xd9, 0xab }, 3 },
191 { "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1",
192 { 0x94, 0xe7, 0x82, 0x1d, 0xd7, 0xf2, 0xe6, 0xc7,
193 0xb3, 0x35, 0xdf, 0xdf, 0xcd, 0x5b, 0x39, 0x60,
194 0xd5, 0xaf, 0x27, 0x08, 0x7f, 0x36, 0x72, 0xc1,
195 0xab, 0x27, 0x0f, 0xb5, 0x29, 0x1f, 0x95, 0x87,
196 0x31, 0x60, 0x65, 0xc0, 0x03, 0xed, 0x4e, 0xe5,
197 0xb1, 0x06, 0x3d, 0x50, 0x07 },
198 45 },
199 };
200
ZTEST(http2_hpack,test_huffman_encode_examples)201 ZTEST(http2_hpack, test_huffman_encode_examples)
202 {
203 ARRAY_FOR_EACH(test_huffman, i) {
204 int ret;
205
206 ret = http_hpack_huffman_encode(test_huffman[i].str,
207 strlen(test_huffman[i].str),
208 test_buf, sizeof(test_buf));
209 zassert_equal(ret, test_huffman[i].encoded_len,
210 "Wrong encoding length");
211 zassert_mem_equal(test_buf, test_huffman[i].encoded, ret,
212 "Symbol wrongly encoded");
213 }
214 }
215
ZTEST(http2_hpack,test_huffman_decode_examples)216 ZTEST(http2_hpack, test_huffman_decode_examples)
217 {
218 ARRAY_FOR_EACH(test_huffman, i) {
219 int ret;
220
221 ret = http_hpack_huffman_decode(test_huffman[i].encoded,
222 test_huffman[i].encoded_len,
223 test_buf, sizeof(test_buf));
224 zassert_equal(ret, strlen(test_huffman[i].str),
225 "Wrong decoded length");
226 zassert_mem_equal(test_buf, test_huffman[i].str, ret,
227 "Symbol wrongly encoded");
228 }
229 }
230
231 struct example_headers {
232 const char *name;
233 const char *value;
234 uint8_t encoded[60];
235 uint8_t encoded_len;
236 };
237
238 /* Examples from RFC7541 */
239 static const struct example_headers test_static_headers[] = {
240 { ":method", "GET", { 0x82 }, 1 },
241 { ":scheme", "http", { 0x86 }, 1 },
242 { ":path", "/", { 0x84 }, 1 },
243 { ":scheme", "https", { 0x87 }, 1 },
244 { ":path", "/index.html", { 0x85 }, 1 },
245 { ":status", "200", { 0x88 }, 1 },
246 };
247
test_hpack_verify_encode(const struct example_headers * example,size_t num_examples)248 static void test_hpack_verify_encode(const struct example_headers *example,
249 size_t num_examples)
250 {
251 for (int i = 0; i < num_examples; i++) {
252 struct http_hpack_header_buf hdr = {
253 .name = example[i].name,
254 .value = example[i].value,
255 .name_len = strlen(example[i].name),
256 .value_len = strlen(example[i].value)
257 };
258 int ret;
259
260 ret = http_hpack_encode_header(test_buf, sizeof(test_buf), &hdr);
261 zassert_equal(ret, example[i].encoded_len, "Wrong encoding length");
262 zassert_mem_equal(test_buf, example[i].encoded, ret,
263 "Header wrongly decoded");
264 }
265 }
266
test_hpack_verify_decode(const struct example_headers * example,size_t num_examples)267 static void test_hpack_verify_decode(const struct example_headers *example,
268 size_t num_examples)
269 {
270 for (int i = 0; i < num_examples; i++) {
271 struct http_hpack_header_buf hdr;
272 int ret;
273
274 ret = http_hpack_decode_header(example[i].encoded, example[i].encoded_len, &hdr);
275 zassert_equal(ret, example[i].encoded_len, "Wrong decoding length");
276 zassert_equal(hdr.name_len, strlen(example[i].name),
277 "Wrong decoded header name length");
278 zassert_equal(hdr.value_len, strlen(example[i].value),
279 "Wrong decoded header value length");
280 zassert_mem_equal(hdr.name, example[i].name, hdr.name_len,
281 "Header name wrongly decoded");
282 zassert_mem_equal(hdr.value, example[i].value, hdr.value_len,
283 "Header value wrongly decoded");
284 }
285 }
286
ZTEST(http2_hpack,test_http2_hpack_static_encode)287 ZTEST(http2_hpack, test_http2_hpack_static_encode)
288 {
289 test_hpack_verify_encode(test_static_headers,
290 ARRAY_SIZE(test_static_headers));
291 }
292
ZTEST(http2_hpack,test_http2_hpack_static_decode)293 ZTEST(http2_hpack, test_http2_hpack_static_decode)
294 {
295 test_hpack_verify_decode(test_static_headers,
296 ARRAY_SIZE(test_static_headers));
297 }
298
299 static const struct example_headers test_dec_literal_indexed_headers[] = {
300 { ":path", "/sample/path",
301 { 0x04, 0x0c, 0x2f, 0x73, 0x61, 0x6d, 0x70, 0x6c,
302 0x65, 0x2f, 0x70, 0x61, 0x74, 0x68 },
303 14 },
304 { ":authority", "www.example.com",
305 { 0x41, 0x0f, 0x77, 0x77, 0x77, 0x2e, 0x65, 0x78,
306 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f,
307 0x6d },
308 17 },
309 { "cache-control", "no-cache",
310 { 0x58, 0x08, 0x6e, 0x6f, 0x2d, 0x63, 0x61, 0x63,
311 0x68, 0x65 },
312 10 },
313 { ":authority", "www.example.com", /* Huffman encoded */
314 { 0x41, 0x8c, 0xf1, 0xe3, 0xc2, 0xe5, 0xf2, 0x3a,
315 0x6b, 0xa0, 0xab, 0x90, 0xf4, 0xff },
316 14 },
317 { "cache-control", "no-cache", /* Huffman encoded */
318 { 0x58, 0x86, 0xa8, 0xeb, 0x10, 0x64, 0x9c, 0xbf },
319 8 },
320 { ":status", "302",
321 { 0x48, 0x03, 0x33, 0x30, 0x32 },
322 5 },
323 { "cache-control", "private",
324 { 0x58, 0x07, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74,
325 0x65 },
326 9 },
327 { "date", "Mon, 21 Oct 2013 20:13:21 GMT",
328 { 0x61, 0x1d, 0x4d, 0x6f, 0x6e, 0x2c, 0x20, 0x32,
329 0x31, 0x20, 0x4f, 0x63, 0x74, 0x20, 0x32, 0x30,
330 0x31, 0x33, 0x20, 0x32, 0x30, 0x3a, 0x31, 0x33,
331 0x3a, 0x32, 0x31, 0x20, 0x47, 0x4d, 0x54 },
332 31 },
333 { "location", "https://www.example.com",
334 { 0x6e, 0x17, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a,
335 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x65, 0x78,
336 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f,
337 0x6d },
338 25 },
339 { ":status", "307",
340 { 0x48, 0x03, 0x33, 0x30, 0x37 },
341 5 },
342 { "content-encoding", "gzip",
343 { 0x5a, 0x04, 0x67, 0x7a, 0x69, 0x70 },
344 6 },
345 { "set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1",
346 { 0x77, 0x38, 0x66, 0x6f, 0x6f, 0x3d, 0x41, 0x53,
347 0x44, 0x4a, 0x4b, 0x48, 0x51, 0x4b, 0x42, 0x5a,
348 0x58, 0x4f, 0x51, 0x57, 0x45, 0x4f, 0x50, 0x49,
349 0x55, 0x41, 0x58, 0x51, 0x57, 0x45, 0x4f, 0x49,
350 0x55, 0x3b, 0x20, 0x6d, 0x61, 0x78, 0x2d, 0x61,
351 0x67, 0x65, 0x3d, 0x33, 0x36, 0x30, 0x30, 0x3b,
352 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
353 0x3d, 0x31 },
354 58 },
355 { ":status", "302", /* Huffman encoded */
356 { 0x48, 0x82, 0x64, 0x02 },
357 4 },
358 { "cache-control", "private", /* Huffman encoded */
359 { 0x58, 0x85, 0xae, 0xc3, 0x77, 0x1a, 0x4b },
360 7 },
361 { "date", "Mon, 21 Oct 2013 20:13:21 GMT", /* Huffman encoded */
362 { 0x61, 0x96, 0xd0, 0x7a, 0xbe, 0x94, 0x10, 0x54,
363 0xd4, 0x44, 0xa8, 0x20, 0x05, 0x95, 0x04, 0x0b,
364 0x81, 0x66, 0xe0, 0x82, 0xa6, 0x2d, 0x1b, 0xff },
365 24 },
366 { "location", "https://www.example.com", /* Huffman encoded */
367 { 0x6e, 0x91, 0x9d, 0x29, 0xad, 0x17, 0x18, 0x63,
368 0xc7, 0x8f, 0x0b, 0x97, 0xc8, 0xe9, 0xae, 0x82,
369 0xae, 0x43, 0xd3 },
370 19 },
371 { ":status", "307", /* Huffman encoded */
372 { 0x48, 0x83, 0x64, 0x0e, 0xff },
373 5 },
374 { "content-encoding", "gzip", /* Huffman encoded */
375 { 0x5a, 0x83, 0x9b, 0xd9, 0xab },
376 5 },
377 { "set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1",
378 /* Huffman encoded */
379 { 0x77, 0xad, 0x94, 0xe7, 0x82, 0x1d, 0xd7, 0xf2,
380 0xe6, 0xc7, 0xb3, 0x35, 0xdf, 0xdf, 0xcd, 0x5b,
381 0x39, 0x60, 0xd5, 0xaf, 0x27, 0x08, 0x7f, 0x36,
382 0x72, 0xc1, 0xab, 0x27, 0x0f, 0xb5, 0x29, 0x1f,
383 0x95, 0x87, 0x31, 0x60, 0x65, 0xc0, 0x03, 0xed,
384 0x4e, 0xe5, 0xb1, 0x06, 0x3d, 0x50, 0x07 },
385 47 },
386 };
387
388 /* For encoding, we always use never indexed and Huffman when applicable. */
389 static const struct example_headers test_enc_literal_indexed_headers[] = {
390 { ":authority", "www.example.com", /* Huffman encoded */
391 { 0x11, 0x8c, 0xf1, 0xe3, 0xc2, 0xe5, 0xf2, 0x3a,
392 0x6b, 0xa0, 0xab, 0x90, 0xf4, 0xff },
393 14 },
394 { "cache-control", "no-cache", /* Huffman encoded */
395 { 0x1f, 0x09, 0x86, 0xa8, 0xeb, 0x10, 0x64, 0x9c, 0xbf },
396 9 },
397 { ":status", "302", /* Huffman encoded */
398 { 0x18, 0x82, 0x64, 0x02 },
399 4 },
400 { "cache-control", "private", /* Huffman encoded */
401 { 0x1f, 0x09, 0x85, 0xae, 0xc3, 0x77, 0x1a, 0x4b },
402 8 },
403 { "date", "Mon, 21 Oct 2013 20:13:21 GMT", /* Huffman encoded */
404 { 0x1f, 0x12, 0x96, 0xd0, 0x7a, 0xbe, 0x94, 0x10,
405 0x54, 0xd4, 0x44, 0xa8, 0x20, 0x05, 0x95, 0x04,
406 0x0b, 0x81, 0x66, 0xe0, 0x82, 0xa6, 0x2d, 0x1b,
407 0xff },
408 25 },
409 { "location", "https://www.example.com", /* Huffman encoded */
410 { 0x1f, 0x1f, 0x91, 0x9d, 0x29, 0xad, 0x17, 0x18,
411 0x63, 0xc7, 0x8f, 0x0b, 0x97, 0xc8, 0xe9, 0xae,
412 0x82, 0xae, 0x43, 0xd3 },
413 20 },
414 { ":status", "307",
415 /* In this case Huffman is not used, as it does not give any size savings. */
416 { 0x18, 0x03, 0x33, 0x30, 0x37 },
417 5 },
418 { "content-encoding", "gzip", /* Huffman encoded */
419 { 0x1f, 0x0b, 0x83, 0x9b, 0xd9, 0xab },
420 6 },
421 { "set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1",
422 /* Huffman encoded */
423 { 0x1f, 0x28, 0xad, 0x94, 0xe7, 0x82, 0x1d, 0xd7,
424 0xf2, 0xe6, 0xc7, 0xb3, 0x35, 0xdf, 0xdf, 0xcd,
425 0x5b, 0x39, 0x60, 0xd5, 0xaf, 0x27, 0x08, 0x7f,
426 0x36, 0x72, 0xc1, 0xab, 0x27, 0x0f, 0xb5, 0x29,
427 0x1f, 0x95, 0x87, 0x31, 0x60, 0x65, 0xc0, 0x03,
428 0xed, 0x4e, 0xe5, 0xb1, 0x06, 0x3d, 0x50, 0x07 },
429 48 },
430 };
431
ZTEST(http2_hpack,test_http2_hpack_literal_indexed_encode)432 ZTEST(http2_hpack, test_http2_hpack_literal_indexed_encode)
433 {
434 test_hpack_verify_encode(test_enc_literal_indexed_headers,
435 ARRAY_SIZE(test_enc_literal_indexed_headers));
436 }
437
ZTEST(http2_hpack,test_http2_hpack_literal_indexed_decode)438 ZTEST(http2_hpack, test_http2_hpack_literal_indexed_decode)
439 {
440 test_hpack_verify_decode(test_dec_literal_indexed_headers,
441 ARRAY_SIZE(test_dec_literal_indexed_headers));
442 /* We should be able to decode encoding test cases as well. */
443 test_hpack_verify_decode(test_enc_literal_indexed_headers,
444 ARRAY_SIZE(test_enc_literal_indexed_headers));
445 }
446
447 static const struct example_headers test_dec_literal_not_indexed_headers[] = {
448 { "custom-key", "custom-header",
449 { 0x40, 0x0a, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d,
450 0x2d, 0x6b, 0x65, 0x79, 0x0d, 0x63, 0x75, 0x73,
451 0x74, 0x6f, 0x6d, 0x2d, 0x68, 0x65, 0x61, 0x64,
452 0x65, 0x72 },
453 26 },
454 { "password", "secret",
455 { 0x10, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f,
456 0x72, 0x64, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65,
457 0x74 },
458 17 },
459 { "custom-key", "custom-value",
460 { 0x40, 0x0a, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d,
461 0x2d, 0x6b, 0x65, 0x79, 0x0c, 0x63, 0x75, 0x73,
462 0x74, 0x6f, 0x6d, 0x2d, 0x76, 0x61, 0x6c, 0x75,
463 0x65 },
464 25 },
465 { "custom-key", "custom-value", /* Huffman encoded */
466 { 0x40, 0x88, 0x25, 0xa8, 0x49, 0xe9, 0x5b, 0xa9,
467 0x7d, 0x7f, 0x89, 0x25, 0xa8, 0x49, 0xe9, 0x5b,
468 0xb8, 0xe8, 0xb4, 0xbf },
469 20 },
470 };
471
472 /* For encoding, we always use never indexed and Huffman. */
473 static const struct example_headers test_enc_literal_not_indexed_headers[] = {
474 { "custom-key", "custom-value", /* Huffman encoded */
475 { 0x10, 0x88, 0x25, 0xa8, 0x49, 0xe9, 0x5b, 0xa9,
476 0x7d, 0x7f, 0x89, 0x25, 0xa8, 0x49, 0xe9, 0x5b,
477 0xb8, 0xe8, 0xb4, 0xbf },
478 20 },
479 };
480
481 /* For encoding, we always use never indexed and Huffman codes. */
ZTEST(http2_hpack,test_http2_hpack_literal_not_indexed_encode)482 ZTEST(http2_hpack, test_http2_hpack_literal_not_indexed_encode)
483 {
484 test_hpack_verify_encode(test_enc_literal_not_indexed_headers,
485 ARRAY_SIZE(test_enc_literal_not_indexed_headers));
486 }
487
ZTEST(http2_hpack,test_http2_hpack_literal_not_indexed_decode)488 ZTEST(http2_hpack, test_http2_hpack_literal_not_indexed_decode)
489 {
490 test_hpack_verify_decode(test_dec_literal_not_indexed_headers,
491 ARRAY_SIZE(test_dec_literal_not_indexed_headers));
492 /* We should be able to decode encoding test cases as well. */
493 test_hpack_verify_decode(test_enc_literal_not_indexed_headers,
494 ARRAY_SIZE(test_enc_literal_not_indexed_headers));
495 }
496
497 ZTEST_SUITE(http2_hpack, NULL, NULL, NULL, NULL, NULL);
498