These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / roms / ipxe / src / include / ipxe / pccrc.h
1 #ifndef _IPXE_PCCRC_H
2 #define _IPXE_PCCRC_H
3
4 /** @file
5  *
6  * Peer Content Caching and Retrieval: Content Identification [MS-PCCRC]
7  *
8  */
9
10 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
11
12 #include <stdint.h>
13 #include <byteswap.h>
14 #include <ipxe/uaccess.h>
15 #include <ipxe/crypto.h>
16
17 /******************************************************************************
18  *
19  * Content Information versioning
20  *
21  ******************************************************************************
22  *
23  * Note that version 1 data structures are little-endian, but version
24  * 2 data structures are big-endian.
25  */
26
27 /** Content Information version number */
28 union peerdist_info_version {
29         /** Raw version number
30          *
31          * Always little-endian, regardless of whether the
32          * encompassing structure is version 1 (little-endian) or
33          * version 2 (big-endian).
34          */
35         uint16_t raw;
36         /** Major:minor version number */
37         struct {
38                 /** Minor version number */
39                 uint8_t minor;
40                 /** Major version number */
41                 uint8_t major;
42         } __attribute__ (( packed ));
43 } __attribute__ (( packed ));
44
45 /** Content Information version 1 */
46 #define PEERDIST_INFO_V1 0x0100
47
48 /** Content Information version 2 */
49 #define PEERDIST_INFO_V2 0x0200
50
51 /******************************************************************************
52  *
53  * Content Information version 1
54  *
55  ******************************************************************************
56  */
57
58 /** Content Information version 1 data structure header
59  *
60  * All fields are little-endian.
61  */
62 struct peerdist_info_v1 {
63         /** Version number */
64         union peerdist_info_version version;
65         /** Hash algorithm
66          *
67          * This is a @c PEERDIST_INFO_V1_HASH_XXX constant.
68          */
69         uint32_t hash;
70         /** Length to skip in first segment
71          *
72          * Length at the start of the first segment which is not
73          * included within the content range.
74          */
75         uint32_t first;
76         /** Length to read in last segment, or zero
77          *
78          * Length within the last segment which is included within the
79          * content range.  A zero value indicates that the whole of
80          * the last segment is included within the content range.
81          */
82         uint32_t last;
83         /** Number of segments within the content information */
84         uint32_t segments;
85         /* Followed by a variable-length array of segment descriptions
86          * and a list of variable-length block descriptions:
87          *
88          * peerdist_info_v1_segment_t(digestsize) segment[segments];
89          * peerdist_info_v1_block_t(digestsize, block0.blocks) block0;
90          * peerdist_info_v1_block_t(digestsize, block1.blocks) block1;
91          * ...
92          * peerdist_info_v1_block_t(digestsize, blockN.blocks) blockN;
93          */
94 } __attribute__ (( packed ));
95
96 /** SHA-256 hash algorithm */
97 #define PEERDIST_INFO_V1_HASH_SHA256 0x0000800cUL
98
99 /** SHA-384 hash algorithm */
100 #define PEERDIST_INFO_V1_HASH_SHA384 0x0000800dUL
101
102 /** SHA-512 hash algorithm */
103 #define PEERDIST_INFO_V1_HASH_SHA512 0x0000800eUL
104
105 /** Content Information version 1 segment description header
106  *
107  * All fields are little-endian.
108  */
109 struct peerdist_info_v1_segment {
110         /** Offset of this segment within the content */
111         uint64_t offset;
112         /** Length of this segment
113          *
114          * Should always be 32MB, except for the last segment within
115          * the content.
116          */
117         uint32_t len;
118         /** Block size for this segment
119          *
120          * Should always be 64kB.  Note that the last block within the
121          * last segment may actually be less than 64kB.
122          */
123         uint32_t blksize;
124         /* Followed by two variable-length hashes:
125          *
126          * uint8_t hash[digestsize];
127          * uint8_t secret[digestsize];
128          *
129          * where digestsize is the digest size for the selected hash
130          * algorithm.
131          *
132          * Note that the hash is taken over (the hashes of all blocks
133          * within) the entire segment, even if the blocks do not
134          * intersect the content range (and so do not appear within
135          * the block list).  It therefore functions only as a segment
136          * identifier; it cannot be used to verify the content of the
137          * segment (since we may not download all blocks within the
138          * segment).
139          */
140 } __attribute__ (( packed ));
141
142 /** Content Information version 1 segment description
143  *
144  * @v digestsize        Digest size
145  */
146 #define peerdist_info_v1_segment_t( digestsize )                        \
147         struct {                                                        \
148                 struct peerdist_info_v1_segment segment;                \
149                 uint8_t hash[digestsize];                               \
150                 uint8_t secret[digestsize];                             \
151         } __attribute__ (( packed ))
152
153 /** Content Information version 1 block description header
154  *
155  * All fields are little-endian.
156  */
157 struct peerdist_info_v1_block {
158         /** Number of blocks within the block description
159          *
160          * This is the number of blocks within the segment which
161          * overlap the content range.  It may therefore be less than
162          * the number of blocks within the segment.
163          */
164         uint32_t blocks;
165         /* Followed by an array of variable-length hashes:
166          *
167          * uint8_t hash[blocks][digestsize];
168          *
169          * where digestsize is the digest size for the selected hash
170          * algorithm.
171          */
172  } __attribute__ (( packed ));
173
174 /** Content Information version 1 block description
175  *
176  * @v digestsize        Digest size
177  * @v blocks            Number of blocks
178  */
179 #define peerdist_info_v1_block_t( digestsize, blocks )                  \
180         struct {                                                        \
181                 struct peerdist_info_v1_block block;                    \
182                 uint8_t hash[blocks][digestsize];                       \
183         } __attribute__ (( packed ))
184
185 /******************************************************************************
186  *
187  * Content Information version 2
188  *
189  ******************************************************************************
190  */
191
192 /** Content Information version 2 data structure header
193  *
194  * All fields are big-endian.
195  */
196 struct peerdist_info_v2 {
197         /** Version number */
198         union peerdist_info_version version;
199         /** Hash algorithm
200          *
201          * This is a @c PEERDIST_INFO_V2_HASH_XXX constant.
202          */
203         uint8_t hash;
204         /** Offset of the first segment within the content */
205         uint64_t offset;
206         /** Index of the first segment within the content */
207         uint64_t index;
208         /** Length to skip in first segment
209          *
210          * Length at the start of the first segment which is not
211          * included within the content range.
212          */
213         uint32_t first;
214         /** Length of content range, or zero
215          *
216          * Length of the content range.  A zero indicates that
217          * everything up to the end of the last segment is included in
218          * the content range.
219          */
220         uint64_t len;
221         /* Followed by a list of chunk descriptions */
222 } __attribute__ (( packed ));
223
224 /** SHA-512 hash algorithm with output truncated to first 256 bits */
225 #define PEERDIST_INFO_V2_HASH_SHA512_TRUNC 0x04
226
227 /** Content Information version 2 chunk description header
228  *
229  * All fields are big-endian.
230  */
231 struct peerdist_info_v2_chunk {
232         /** Chunk type */
233         uint8_t type;
234         /** Chunk data length */
235         uint32_t len;
236         /* Followed by an array of segment descriptions:
237          *
238          * peerdist_info_v2_segment_t(digestsize) segment[segments]
239          *
240          * where digestsize is the digest size for the selected hash
241          * algorithm, and segments is equal to @c len divided by the
242          * size of each segment array entry.
243          */
244 } __attribute__ (( packed ));
245
246 /** Content Information version 2 chunk description
247  *
248  * @v digestsize        Digest size
249  */
250 #define peerdist_info_v2_chunk_t( digestsize )                          \
251         struct {                                                        \
252                 struct peerdist_info_v2_chunk chunk;                    \
253                 peerdist_info_v2_segment_t ( digestsize ) segment[0];   \
254         } __attribute__ (( packed ))
255
256 /** Chunk type */
257 #define PEERDIST_INFO_V2_CHUNK_TYPE 0x00
258
259 /** Content Information version 2 segment description header
260  *
261  * All fields are big-endian.
262  */
263 struct peerdist_info_v2_segment {
264         /** Segment length */
265         uint32_t len;
266         /* Followed by two variable-length hashes:
267          *
268          * uint8_t hash[digestsize];
269          * uint8_t secret[digestsize];
270          *
271          * where digestsize is the digest size for the selected hash
272          * algorithm.
273          */
274 } __attribute__ (( packed ));
275
276 /** Content Information version 2 segment description
277  *
278  * @v digestsize        Digest size
279  */
280 #define peerdist_info_v2_segment_t( digestsize )                        \
281         struct {                                                        \
282                 struct peerdist_info_v2_segment segment;                \
283                 uint8_t hash[digestsize];                               \
284                 uint8_t secret[digestsize];                             \
285         } __attribute__ (( packed ))
286
287 /******************************************************************************
288  *
289  * Content Information
290  *
291  ******************************************************************************
292  */
293
294 /** Maximum digest size for any supported algorithm
295  *
296  * The largest digest size that we support is for SHA-512 at 64 bytes
297  */
298 #define PEERDIST_DIGEST_MAX_SIZE 64
299
300 /** Raw content information */
301 struct peerdist_raw {
302         /** Data buffer */
303         userptr_t data;
304         /** Length of data buffer */
305         size_t len;
306 };
307
308 /** A content range */
309 struct peerdist_range {
310         /** Start offset */
311         size_t start;
312         /** End offset */
313         size_t end;
314 };
315
316 /** Content information */
317 struct peerdist_info {
318         /** Raw content information */
319         struct peerdist_raw raw;
320
321         /** Content information operations */
322         struct peerdist_info_operations *op;
323         /** Digest algorithm */
324         struct digest_algorithm *digest;
325         /** Digest size
326          *
327          * Note that this may be shorter than the digest size of the
328          * digest algorithm.  The truncation does not always take
329          * place as soon as a digest is calculated.  For example,
330          * version 2 content information uses SHA-512 with a truncated
331          * digest size of 32 (256 bits), but the segment identifier
332          * ("HoHoDk") is calculated by using HMAC with the full
333          * SHA-512 digest and then truncating the HMAC output, rather
334          * than by simply using HMAC with the truncated SHA-512
335          * digest.  This is, of course, totally undocumented.
336          */
337         size_t digestsize;
338         /** Content range */
339         struct peerdist_range range;
340         /** Trimmed content range */
341         struct peerdist_range trim;
342         /** Number of segments within the content information */
343         unsigned int segments;
344 };
345
346 /** A content information segment */
347 struct peerdist_info_segment {
348         /** Content information */
349         const struct peerdist_info *info;
350         /** Segment index */
351         unsigned int index;
352
353         /** Content range
354          *
355          * Note that this range may exceed the overall content range.
356          */
357         struct peerdist_range range;
358         /** Number of blocks within this segment */
359         unsigned int blocks;
360         /** Block size */
361         size_t blksize;
362         /** Segment hash of data
363          *
364          * This is MS-PCCRC's "HoD".
365          */
366         uint8_t hash[PEERDIST_DIGEST_MAX_SIZE];
367         /** Segment secret
368          *
369          * This is MS-PCCRC's "Ke = Kp".
370          */
371         uint8_t secret[PEERDIST_DIGEST_MAX_SIZE];
372         /** Segment identifier
373          *
374          * This is MS-PCCRC's "HoHoDk".
375          */
376         uint8_t id[PEERDIST_DIGEST_MAX_SIZE];
377 };
378
379 /** Magic string constant used to calculate segment identifier
380  *
381  * Note that the MS-PCCRC specification states that this constant is
382  *
383  *   "the null-terminated ASCII string constant "MS_P2P_CACHING";
384  *    string literals are all ASCII strings with NULL terminators
385  *    unless otherwise noted."
386  *
387  * The specification lies.  This constant is a UTF-16LE string, not an
388  * ASCII string.  The terminating wNUL *is* included within the
389  * constant.
390  */
391 #define PEERDIST_SEGMENT_ID_MAGIC L"MS_P2P_CACHING"
392
393 /** A content information block */
394 struct peerdist_info_block {
395         /** Content information segment */
396         const struct peerdist_info_segment *segment;
397         /** Block index */
398         unsigned int index;
399
400         /** Content range
401          *
402          * Note that this range may exceed the overall content range.
403          */
404         struct peerdist_range range;
405         /** Trimmed content range */
406         struct peerdist_range trim;
407         /** Block hash */
408         uint8_t hash[PEERDIST_DIGEST_MAX_SIZE];
409 };
410
411 /** Content information operations */
412 struct peerdist_info_operations {
413         /**
414          * Populate content information
415          *
416          * @v info              Content information to fill in
417          * @ret rc              Return status code
418          */
419         int ( * info ) ( struct peerdist_info *info );
420         /**
421          * Populate content information segment
422          *
423          * @v segment           Content information segment to fill in
424          * @ret rc              Return status code
425          */
426         int ( * segment ) ( struct peerdist_info_segment *segment );
427         /**
428          * Populate content information block
429          *
430          * @v block             Content information block to fill in
431          * @ret rc              Return status code
432          */
433         int ( * block ) ( struct peerdist_info_block *block );
434 };
435
436 extern struct digest_algorithm sha512_trunc_algorithm;
437
438 extern int peerdist_info ( userptr_t data, size_t len,
439                            struct peerdist_info *info );
440 extern int peerdist_info_segment ( const struct peerdist_info *info,
441                                    struct peerdist_info_segment *segment,
442                                    unsigned int index );
443 extern int peerdist_info_block ( const struct peerdist_info_segment *segment,
444                                  struct peerdist_info_block *block,
445                                  unsigned int index );
446
447 #endif /* _IPXE_PCCRC_H */