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