1 /*
2 * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26 /** @file
27 *
28 * Peer Content Caching and Retrieval: Content Identification [MS-PCCRC] tests
29 *
30 */
31
32 /* Forcibly enable assertions */
33 #undef NDEBUG
34
35 #include <stdint.h>
36 #include <string.h>
37 #include <assert.h>
38 #include <ipxe/uaccess.h>
39 #include <ipxe/pccrc.h>
40 #include <ipxe/sha256.h>
41 #include <ipxe/sha512.h>
42 #include <ipxe/hmac.h>
43 #include <ipxe/test.h>
44
45 /** Define inline raw data */
46 #define DATA(...) { __VA_ARGS__ }
47
48 /**
49 * Define an inline content range
50 *
51 * @v START Start offset
52 * @v END End offset
53 * @ret range Content range
54 */
55 #define RANGE( START, END ) { .start = START, .end = END }
56
57 /**
58 * Define an inline trimmed content range
59 *
60 * @v START Start offset
61 * @v END End offset
62 * @ret trim Trimmed content range
63 */
64 #define TRIM( START, END ) { .start = START, .end = END }
65
66 /** A content information test */
67 struct peerdist_info_test {
68 /** Raw content information */
69 const void *data;
70 /** Length of raw content information */
71 size_t len;
72 /** Expected digest algorithm */
73 struct digest_algorithm *expected_digest;
74 /** Expected digest size */
75 size_t expected_digestsize;
76 /** Expected content range */
77 struct peerdist_range expected_range;
78 /** Expected trimmed content range */
79 struct peerdist_range expected_trim;
80 /** Expected number of segments */
81 unsigned int expected_segments;
82 };
83
84 /**
85 * Define a content information test
86 *
87 * @v name Test name
88 * @v DATA Raw content information
89 * @v DIGEST Expected digest algorithm
90 * @v DIGESTSIZE Expected digest size
91 * @v RANGE Expected content range
92 * @v TRIM Expected trimmer content range
93 * @v SEGMENTS Expected number of segments
94 * @ret test Content information test
95 *
96 * Raw content information can be obtained from PeerDist-capable web
97 * servers using wget's "--header" option to inject the relevant
98 * PeerDist headers. For example:
99 *
100 * wget --header "Accept-Encoding: peerdist" \
101 * --header "X-P2P-PeerDist: Version=1.0" \
102 * http://peerdist.server.address/test.url -O - | xxd -i -c 11
103 *
104 * Version 1 content information can be retrieved using the headers:
105 *
106 * Accept-Encoding: peerdist
107 * X-P2P-PeerDist: Version=1.0
108 *
109 * Version 2 content information can be retrieved (from compatible
110 * servers) using the headers:
111 *
112 * Accept-Encoding: peerdist
113 * X-P2P-PeerDist: Version=1.1
114 * X-P2P-PeerDistEx: MinContentInformation=2.0, MaxContentInformation=2.0
115 */
116 #define PEERDIST_INFO_TEST( name, DATA, DIGEST, DIGESTSIZE, RANGE, \
117 TRIM, SEGMENTS ) \
118 static const uint8_t name ## _data[] = DATA; \
119 static struct peerdist_info_test name = { \
120 .data = name ## _data, \
121 .len = sizeof ( name ## _data ), \
122 .expected_digest = DIGEST, \
123 .expected_digestsize = DIGESTSIZE, \
124 .expected_range = RANGE, \
125 .expected_trim = TRIM, \
126 .expected_segments = SEGMENTS, \
127 }
128
129 /** A content information segment test */
130 struct peerdist_info_segment_test {
131 /** Segment index */
132 unsigned int index;
133 /** Expected content range */
134 struct peerdist_range expected_range;
135 /** Expected number of blocks */
136 unsigned int expected_blocks;
137 /** Expected block size */
138 size_t expected_blksize;
139 /** Expected segment hash of data */
140 uint8_t expected_hash[PEERDIST_DIGEST_MAX_SIZE];
141 /** Expected segment secret */
142 uint8_t expected_secret[PEERDIST_DIGEST_MAX_SIZE];
143 /** Expected segment identifier */
144 uint8_t expected_id[PEERDIST_DIGEST_MAX_SIZE];
145 };
146
147 /**
148 * Define a content information segment test
149 *
150 * @v name Test name
151 * @v INDEX Segment index
152 * @v RANGE Expected content range
153 * @v BLOCKS Expected number of blocks
154 * @v BLKSIZE Expected block size
155 * @v HASH Expected segment hash of data
156 * @v SECRET Expected segment secret
157 * @v ID Expected segment identifier
158 * @ret test Content information segment test
159 */
160 #define PEERDIST_INFO_SEGMENT_TEST( name, INDEX, RANGE, BLOCKS, \
161 BLKSIZE, HASH, SECRET, ID ) \
162 static struct peerdist_info_segment_test name = { \
163 .index = INDEX, \
164 .expected_range = RANGE, \
165 .expected_blocks = BLOCKS, \
166 .expected_blksize = BLKSIZE, \
167 .expected_hash = HASH, \
168 .expected_secret = SECRET, \
169 .expected_id = ID, \
170 }
171
172 /** A content information block test */
173 struct peerdist_info_block_test {
174 /** Block index */
175 unsigned int index;
176 /** Expected content range */
177 struct peerdist_range expected_range;
178 /** Expected trimmed content range */
179 struct peerdist_range expected_trim;
180 /** Expected hash of data */
181 uint8_t expected_hash[PEERDIST_DIGEST_MAX_SIZE];
182 };
183
184 /**
185 * Define a content information block test
186 *
187 * @v name Test name
188 * @v INDEX Block index
189 * @v RANGE Expected content range
190 * @v TRIM Expected trimmed content range
191 * @v HASH Expected hash of data
192 * @ret test Content information block test
193 */
194 #define PEERDIST_INFO_BLOCK_TEST( name, INDEX, RANGE, TRIM, HASH ) \
195 static struct peerdist_info_block_test name = { \
196 .index = INDEX, \
197 .expected_range = RANGE, \
198 .expected_trim = TRIM, \
199 .expected_hash = HASH, \
200 }
201
202 /**
203 * Define a server passphrase
204 *
205 * @v name Server passphrase name
206 * @v DATA Raw server passphrase
207 *
208 * The server passphrase can be exported from a Windows BranchCache
209 * server using the command:
210 *
211 * netsh branchcache exportkey exported.key somepassword
212 *
213 * and this encrypted exported key can be decrypted using the
214 * oSSL_key_dx or mcrypt_key_dx utilities found in the (prototype)
215 * Prequel project at https://fedorahosted.org/prequel/ :
216 *
217 * oSSL_key_dx exported.key somepassword
218 * or
219 * mcrypt_key_dx exported.key somepassword
220 *
221 * Either command will display both the server passphrase and the
222 * "Server Secret". Note that this latter is the version 1 server
223 * secret (i.e. the SHA-256 of the server passphrase); the
224 * corresponding version 2 server secret can be obtained by
225 * calculating the truncated SHA-512 of the server passphrase.
226 *
227 * We do not know the server passphrase during normal operation. We
228 * use it in the self-tests only to check for typos and other errors
229 * in the test vectors, by checking that the segment secret defined in
230 * a content information segment test is as expected.
231 */
232 #define SERVER_PASSPHRASE( name, DATA ) \
233 static uint8_t name[] = DATA
234
235 /** Server passphrase used for these test vectors */
236 SERVER_PASSPHRASE ( passphrase,
237 DATA ( 0x2a, 0x3d, 0x73, 0xeb, 0x43, 0x5e, 0x9f, 0x2b, 0x8a, 0x34, 0x42,
238 0x67, 0xe7, 0x46, 0x7a, 0x3c, 0x73, 0x85, 0xc6, 0xe0, 0x55, 0xe2,
239 0xb4, 0xd3, 0x0d, 0xfe, 0xc7, 0xc3, 0x8b, 0x0e, 0xd7, 0x2c ) );
240
241 /** IIS logo (iis-85.png) content information version 1 */
242 PEERDIST_INFO_TEST ( iis_85_png_v1,
243 DATA ( 0x00, 0x01, 0x0c, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
244 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
245 0x00, 0x00, 0x00, 0x00, 0x7e, 0x85, 0x01, 0x00, 0x00, 0x00, 0x01,
246 0x00, 0xd8, 0xd9, 0x76, 0x35, 0x4a, 0x48, 0x72, 0xe9, 0x25, 0x76,
247 0x18, 0x03, 0xf4, 0x58, 0xd9, 0xda, 0xaa, 0x67, 0xf8, 0xe3, 0x1c,
248 0x63, 0x0f, 0xb7, 0x4e, 0x6a, 0x31, 0x2e, 0xf8, 0xa2, 0x5a, 0xba,
249 0x11, 0xaf, 0xc0, 0xd7, 0x94, 0x92, 0x43, 0xf9, 0x4f, 0x9c, 0x1f,
250 0xab, 0x35, 0xd9, 0xfd, 0x1e, 0x33, 0x1f, 0xcf, 0x78, 0x11, 0xa2,
251 0xe0, 0x1d, 0x35, 0x87, 0xb3, 0x8d, 0x77, 0x0a, 0x29, 0xe2, 0x02,
252 0x00, 0x00, 0x00, 0x73, 0xc1, 0x8a, 0xb8, 0x54, 0x91, 0x10, 0xf8,
253 0xe9, 0x0e, 0x71, 0xbb, 0xc3, 0xab, 0x2a, 0xa8, 0xc4, 0x4d, 0x13,
254 0xf4, 0x92, 0x94, 0x99, 0x25, 0x5b, 0x66, 0x0f, 0x24, 0xec, 0x77,
255 0x80, 0x0b, 0x97, 0x4b, 0xdd, 0x65, 0x56, 0x7f, 0xde, 0xec, 0xcd,
256 0xaf, 0xe4, 0x57, 0xa9, 0x50, 0x3b, 0x45, 0x48, 0xf6, 0x6e, 0xd3,
257 0xb1, 0x88, 0xdc, 0xfd, 0xa0, 0xac, 0x38, 0x2b, 0x09, 0x71, 0x1a,
258 0xcc ),
259 &sha256_algorithm, 32, RANGE ( 0, 99710 ), TRIM ( 0, 99710 ), 1 );
260
261 /** IIS logo (iis-85.png) content information version 1 segment 0 */
262 PEERDIST_INFO_SEGMENT_TEST ( iis_85_png_v1_s0, 0,
263 RANGE ( 0, 99710 ), 2, 65536,
264 DATA ( 0xd8, 0xd9, 0x76, 0x35, 0x4a, 0x48, 0x72, 0xe9, 0x25, 0x76, 0x18,
265 0x03, 0xf4, 0x58, 0xd9, 0xda, 0xaa, 0x67, 0xf8, 0xe3, 0x1c, 0x63,
266 0x0f, 0xb7, 0x4e, 0x6a, 0x31, 0x2e, 0xf8, 0xa2, 0x5a, 0xba ),
267 DATA ( 0x11, 0xaf, 0xc0, 0xd7, 0x94, 0x92, 0x43, 0xf9, 0x4f, 0x9c, 0x1f,
268 0xab, 0x35, 0xd9, 0xfd, 0x1e, 0x33, 0x1f, 0xcf, 0x78, 0x11, 0xa2,
269 0xe0, 0x1d, 0x35, 0x87, 0xb3, 0x8d, 0x77, 0x0a, 0x29, 0xe2 ),
270 DATA ( 0x49, 0x1b, 0x21, 0x7d, 0xbe, 0xe2, 0xb5, 0xf1, 0x2c, 0xa7, 0x9b,
271 0x01, 0x5e, 0x06, 0xf4, 0xbb, 0xe6, 0x4f, 0x97, 0x45, 0xba, 0xd7,
272 0x86, 0x7a, 0xef, 0x17, 0xde, 0x59, 0x92, 0x7e, 0xdc, 0xe9 ) );
273
274 /** IIS logo (iis-85.png) content information version 1 segment 0 block 0 */
275 PEERDIST_INFO_BLOCK_TEST ( iis_85_png_v1_s0_b0, 0,
276 RANGE ( 0, 65536 ),
277 TRIM ( 0, 65536 ),
278 DATA ( 0x73, 0xc1, 0x8a, 0xb8, 0x54, 0x91, 0x10, 0xf8, 0xe9, 0x0e, 0x71,
279 0xbb, 0xc3, 0xab, 0x2a, 0xa8, 0xc4, 0x4d, 0x13, 0xf4, 0x92, 0x94,
280 0x99, 0x25, 0x5b, 0x66, 0x0f, 0x24, 0xec, 0x77, 0x80, 0x0b ) );
281
282 /** IIS logo (iis-85.png) content information version 1 segment 0 block 1 */
283 PEERDIST_INFO_BLOCK_TEST ( iis_85_png_v1_s0_b1, 1,
284 RANGE ( 65536, 99710 ),
285 TRIM ( 65536, 99710 ),
286 DATA ( 0x97, 0x4b, 0xdd, 0x65, 0x56, 0x7f, 0xde, 0xec, 0xcd, 0xaf, 0xe4,
287 0x57, 0xa9, 0x50, 0x3b, 0x45, 0x48, 0xf6, 0x6e, 0xd3, 0xb1, 0x88,
288 0xdc, 0xfd, 0xa0, 0xac, 0x38, 0x2b, 0x09, 0x71, 0x1a, 0xcc ) );
289
290 /** IIS logo (iis-85.png) content information version 2 */
291 PEERDIST_INFO_TEST ( iis_85_png_v2,
292 DATA ( 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
293 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
294 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
295 0x00, 0x00, 0x88, 0x00, 0x00, 0x99, 0xde, 0xe0, 0xd0, 0xc3, 0x58,
296 0xe2, 0x68, 0x4b, 0x62, 0x33, 0x0d, 0x32, 0xb5, 0xf1, 0x97, 0x87,
297 0x24, 0xa0, 0xd0, 0xa5, 0x2b, 0xdc, 0x5e, 0x78, 0x1f, 0xae, 0x71,
298 0xff, 0x57, 0xa8, 0xbe, 0x3d, 0xd4, 0x58, 0x03, 0x7e, 0xd4, 0x04,
299 0x11, 0x6b, 0xb6, 0x16, 0xd9, 0xb1, 0x41, 0x16, 0x08, 0x85, 0x20,
300 0xc4, 0x7c, 0xdc, 0x50, 0xab, 0xce, 0xa3, 0xfa, 0xe1, 0x88, 0xa9,
301 0x8e, 0xa2, 0x2d, 0xf3, 0xc0, 0x00, 0x00, 0xeb, 0xa0, 0x33, 0x81,
302 0xd0, 0xd0, 0xcb, 0x74, 0xf4, 0xb6, 0x13, 0xd8, 0x21, 0x0f, 0x37,
303 0xf0, 0x02, 0xa0, 0x6f, 0x39, 0x10, 0x58, 0x60, 0x96, 0xa1, 0x30,
304 0xd3, 0x43, 0x98, 0xc0, 0x8e, 0x66, 0xd7, 0xbc, 0xb8, 0xb6, 0xeb,
305 0x77, 0x83, 0xe4, 0xf8, 0x07, 0x64, 0x7b, 0x63, 0xf1, 0x46, 0xb5,
306 0x2f, 0x4a, 0xc8, 0x9c, 0xcc, 0x7a, 0xbf, 0x5f, 0xa1, 0x1a, 0xca,
307 0xfc, 0x2a, 0xcf, 0x50, 0x28, 0x58, 0x6c ),
308 &sha512_algorithm, 32, RANGE ( 0, 99710 ), TRIM ( 0, 99710 ), 2 );
309
310 /** IIS logo (iis-85.png) content information version 2 segment 0 */
311 PEERDIST_INFO_SEGMENT_TEST ( iis_85_png_v2_s0, 0,
312 RANGE ( 0, 39390 ), 1, 39390,
313 DATA ( 0xe0, 0xd0, 0xc3, 0x58, 0xe2, 0x68, 0x4b, 0x62, 0x33, 0x0d, 0x32,
314 0xb5, 0xf1, 0x97, 0x87, 0x24, 0xa0, 0xd0, 0xa5, 0x2b, 0xdc, 0x5e,
315 0x78, 0x1f, 0xae, 0x71, 0xff, 0x57, 0xa8, 0xbe, 0x3d, 0xd4 ),
316 DATA ( 0x58, 0x03, 0x7e, 0xd4, 0x04, 0x11, 0x6b, 0xb6, 0x16, 0xd9, 0xb1,
317 0x41, 0x16, 0x08, 0x85, 0x20, 0xc4, 0x7c, 0xdc, 0x50, 0xab, 0xce,
318 0xa3, 0xfa, 0xe1, 0x88, 0xa9, 0x8e, 0xa2, 0x2d, 0xf3, 0xc0 ),
319 DATA ( 0x33, 0x71, 0xbb, 0xea, 0xdd, 0xb6, 0x23, 0x53, 0xad, 0xce, 0xf9,
320 0x70, 0xa0, 0x6f, 0xdf, 0x65, 0x00, 0x1e, 0x04, 0x21, 0xf4, 0xc7,
321 0x10, 0x82, 0x76, 0xb0, 0xc3, 0x7a, 0x9f, 0x9e, 0xc1, 0x0f ) );
322
323 /** IIS logo (iis-85.png) content information version 2 segment 0 block 0 */
324 PEERDIST_INFO_BLOCK_TEST ( iis_85_png_v2_s0_b0, 0,
325 RANGE ( 0, 39390 ),
326 TRIM ( 0, 39390 ),
327 DATA ( 0xe0, 0xd0, 0xc3, 0x58, 0xe2, 0x68, 0x4b, 0x62, 0x33, 0x0d, 0x32,
328 0xb5, 0xf1, 0x97, 0x87, 0x24, 0xa0, 0xd0, 0xa5, 0x2b, 0xdc, 0x5e,
329 0x78, 0x1f, 0xae, 0x71, 0xff, 0x57, 0xa8, 0xbe, 0x3d, 0xd4 ) );
330
331 /** IIS logo (iis-85.png) content information version 2 segment 1 */
332 PEERDIST_INFO_SEGMENT_TEST ( iis_85_png_v2_s1, 1,
333 RANGE ( 39390, 99710 ), 1, 60320,
334 DATA ( 0x33, 0x81, 0xd0, 0xd0, 0xcb, 0x74, 0xf4, 0xb6, 0x13, 0xd8, 0x21,
335 0x0f, 0x37, 0xf0, 0x02, 0xa0, 0x6f, 0x39, 0x10, 0x58, 0x60, 0x96,
336 0xa1, 0x30, 0xd3, 0x43, 0x98, 0xc0, 0x8e, 0x66, 0xd7, 0xbc ),
337 DATA ( 0xb8, 0xb6, 0xeb, 0x77, 0x83, 0xe4, 0xf8, 0x07, 0x64, 0x7b, 0x63,
338 0xf1, 0x46, 0xb5, 0x2f, 0x4a, 0xc8, 0x9c, 0xcc, 0x7a, 0xbf, 0x5f,
339 0xa1, 0x1a, 0xca, 0xfc, 0x2a, 0xcf, 0x50, 0x28, 0x58, 0x6c ),
340 DATA ( 0xd7, 0xe9, 0x24, 0x42, 0x5e, 0x8f, 0x4f, 0x88, 0xf0, 0x1d, 0xc6,
341 0xa9, 0xbb, 0x1b, 0xc3, 0x7b, 0xe1, 0x13, 0xec, 0x79, 0x17, 0xc7,
342 0x45, 0xd4, 0x96, 0x5c, 0x2b, 0x55, 0xfa, 0x16, 0x3a, 0x6e ) );
343
344 /** IIS logo (iis-85.png) content information version 2 segment 1 block 0 */
345 PEERDIST_INFO_BLOCK_TEST ( iis_85_png_v2_s1_b0, 0,
346 RANGE ( 39390, 99710 ),
347 TRIM ( 39390, 99710 ),
348 DATA ( 0x33, 0x81, 0xd0, 0xd0, 0xcb, 0x74, 0xf4, 0xb6, 0x13, 0xd8, 0x21,
349 0x0f, 0x37, 0xf0, 0x02, 0xa0, 0x6f, 0x39, 0x10, 0x58, 0x60, 0x96,
350 0xa1, 0x30, 0xd3, 0x43, 0x98, 0xc0, 0x8e, 0x66, 0xd7, 0xbc ) );
351
352 /**
353 * Report content information test result
354 *
355 * @v test Content information test
356 * @v info Content information to fill in
357 * @v file Test code file
358 * @v line Test code line
359 */
peerdist_info_okx(struct peerdist_info_test * test,struct peerdist_info * info,const char * file,unsigned int line)360 static void peerdist_info_okx ( struct peerdist_info_test *test,
361 struct peerdist_info *info,
362 const char *file, unsigned int line ) {
363
364 /* Parse content information */
365 okx ( peerdist_info ( virt_to_user ( test->data ), test->len,
366 info ) == 0, file, line );
367
368 /* Verify content information */
369 okx ( info->raw.data == virt_to_user ( test->data ), file, line );
370 okx ( info->raw.len == test->len, file, line );
371 okx ( info->digest == test->expected_digest, file, line );
372 okx ( info->digestsize == test->expected_digestsize, file, line );
373 okx ( info->range.start == test->expected_range.start, file, line );
374 okx ( info->range.end == test->expected_range.end, file, line );
375 okx ( info->trim.start == test->expected_trim.start, file, line );
376 okx ( info->trim.end == test->expected_trim.end, file, line );
377 okx ( info->trim.start >= info->range.start, file, line );
378 okx ( info->trim.end <= info->range.end, file, line );
379 okx ( info->segments == test->expected_segments, file, line );
380 }
381 #define peerdist_info_ok( test, info ) \
382 peerdist_info_okx ( test, info, __FILE__, __LINE__ )
383
384 /**
385 * Report content information segment test result
386 *
387 * @v test Content information segment test
388 * @v info Content information
389 * @v segment Segment information to fill in
390 * @v file Test code file
391 * @v line Test code line
392 */
peerdist_info_segment_okx(struct peerdist_info_segment_test * test,const struct peerdist_info * info,struct peerdist_info_segment * segment,const char * file,unsigned int line)393 static void peerdist_info_segment_okx ( struct peerdist_info_segment_test *test,
394 const struct peerdist_info *info,
395 struct peerdist_info_segment *segment,
396 const char *file, unsigned int line ) {
397 size_t digestsize = info->digestsize;
398
399 /* Parse content information segment */
400 okx ( peerdist_info_segment ( info, segment, test->index ) == 0,
401 file, line );
402
403 /* Verify content information segment */
404 okx ( segment->info == info, file, line );
405 okx ( segment->index == test->index, file, line );
406 okx ( segment->range.start == test->expected_range.start, file, line );
407 okx ( segment->range.end == test->expected_range.end, file, line );
408 okx ( segment->blocks == test->expected_blocks, file, line );
409 okx ( segment->blksize == test->expected_blksize, file, line );
410 okx ( memcmp ( segment->hash, test->expected_hash,
411 digestsize ) == 0, file, line );
412 okx ( memcmp ( segment->secret, test->expected_secret,
413 digestsize ) == 0, file, line );
414 okx ( memcmp ( segment->id, test->expected_id,
415 digestsize ) == 0, file, line );
416 }
417 #define peerdist_info_segment_ok( test, info, segment ) \
418 peerdist_info_segment_okx ( test, info, segment, __FILE__, __LINE__ )
419
420 /**
421 * Report content information block test result
422 *
423 * @v test Content information block test
424 * @v segment Segment information
425 * @v block Block information to fill in
426 * @v file Test code file
427 * @v line Test code line
428 */
429 static void
peerdist_info_block_okx(struct peerdist_info_block_test * test,const struct peerdist_info_segment * segment,struct peerdist_info_block * block,const char * file,unsigned int line)430 peerdist_info_block_okx ( struct peerdist_info_block_test *test,
431 const struct peerdist_info_segment *segment,
432 struct peerdist_info_block *block,
433 const char *file, unsigned int line ) {
434 const struct peerdist_info *info = segment->info;
435 size_t digestsize = info->digestsize;
436
437 /* Parse content information block */
438 okx ( peerdist_info_block ( segment, block, test->index ) == 0,
439 file, line );
440
441 /* Verify content information block */
442 okx ( block->segment == segment, file, line );
443 okx ( block->index == test->index, file, line );
444 okx ( block->range.start == test->expected_range.start, file, line );
445 okx ( block->range.end == test->expected_range.end, file, line );
446 okx ( block->trim.start == test->expected_trim.start, file, line );
447 okx ( block->trim.end == test->expected_trim.end, file, line );
448 okx ( memcmp ( block->hash, test->expected_hash,
449 digestsize ) == 0, file, line );
450 }
451 #define peerdist_info_block_ok( test, segment, block ) \
452 peerdist_info_block_okx ( test, segment, block, __FILE__, __LINE__ )
453
454 /**
455 * Report server passphrase test result
456 *
457 * @v test Content information segment test
458 * @v info Content information
459 * @v pass Server passphrase
460 * @v pass_len Length of server passphrase
461 * @v file Test code file
462 * @v line Test code line
463 */
464 static void
peerdist_info_passphrase_okx(struct peerdist_info_segment_test * test,const struct peerdist_info * info,uint8_t * pass,size_t pass_len,const char * file,unsigned int line)465 peerdist_info_passphrase_okx ( struct peerdist_info_segment_test *test,
466 const struct peerdist_info *info,
467 uint8_t *pass, size_t pass_len,
468 const char *file, unsigned int line ) {
469 struct digest_algorithm *digest = info->digest;
470 uint8_t ctx[digest->ctxsize];
471 uint8_t secret[digest->digestsize];
472 uint8_t expected[digest->digestsize];
473 size_t digestsize = info->digestsize;
474 size_t secretsize = digestsize;
475
476 /* Calculate server secret */
477 digest_init ( digest, ctx );
478 digest_update ( digest, ctx, pass, pass_len );
479 digest_final ( digest, ctx, secret );
480
481 /* Calculate expected segment secret */
482 hmac_init ( digest, ctx, secret, &secretsize );
483 assert ( secretsize == digestsize );
484 hmac_update ( digest, ctx, test->expected_hash, digestsize );
485 hmac_final ( digest, ctx, secret, &secretsize, expected );
486 assert ( secretsize == digestsize );
487
488 /* Verify segment secret */
489 okx ( memcmp ( test->expected_secret, expected, digestsize ) == 0,
490 file, line );
491 }
492 #define peerdist_info_passphrase_ok( test, info, pass, pass_len ) \
493 peerdist_info_passphrase_okx ( test, info, pass, pass_len, \
494 __FILE__, __LINE__ )
495
496 /**
497 * Perform content information self-tests
498 *
499 */
peerdist_info_test_exec(void)500 static void peerdist_info_test_exec ( void ) {
501 struct peerdist_info info;
502 struct peerdist_info_segment segment;
503 struct peerdist_info_block block;
504
505 /* IIS logo (iis-85.png) content information version 1 */
506 peerdist_info_ok ( &iis_85_png_v1, &info );
507 peerdist_info_passphrase_ok ( &iis_85_png_v1_s0, &info,
508 passphrase, sizeof ( passphrase ) );
509 peerdist_info_segment_ok ( &iis_85_png_v1_s0, &info, &segment );
510 peerdist_info_block_ok ( &iis_85_png_v1_s0_b0, &segment, &block );
511 peerdist_info_block_ok ( &iis_85_png_v1_s0_b1, &segment, &block );
512
513 /* IIS logo (iis-85.png) content information version 2 */
514 peerdist_info_ok ( &iis_85_png_v2, &info );
515 peerdist_info_passphrase_ok ( &iis_85_png_v2_s0, &info,
516 passphrase, sizeof ( passphrase ) );
517 peerdist_info_segment_ok ( &iis_85_png_v2_s0, &info, &segment );
518 peerdist_info_block_ok ( &iis_85_png_v2_s0_b0, &segment, &block );
519 peerdist_info_passphrase_ok ( &iis_85_png_v2_s1, &info,
520 passphrase, sizeof ( passphrase ) );
521 peerdist_info_segment_ok ( &iis_85_png_v2_s1, &info, &segment );
522 peerdist_info_block_ok ( &iis_85_png_v2_s1_b0, &segment, &block );
523 }
524
525 /** Content information self-test */
526 struct self_test peerdist_info_test __self_test = {
527 .name = "pccrc",
528 .exec = peerdist_info_test_exec,
529 };
530