These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / roms / ipxe / src / tests / pccrc_test.c
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  */
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  */
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
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
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  */
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 };