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/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 */
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  */
36  /** Major:minor version number */
37  struct {
38  /** Minor version number */
40  /** Major version number */
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  */
63  /** Version number */
65  /** Hash algorithm
66  *
67  * This is a @c PEERDIST_INFO_V1_HASH_XXX constant.
68  */
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  */
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  */
83  /** Number of segments within the content information */
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  */
110  /** Offset of this segment within the content */
112  /** Length of this segment
113  *
114  * Should always be 32MB, except for the last segment within
115  * the content.
116  */
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  */
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  */
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  */
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  */
197  /** Version number */
199  /** Hash algorithm
200  *
201  * This is a @c PEERDIST_INFO_V2_HASH_XXX constant.
202  */
204  /** Offset of the first segment within the content */
206  /** Index of the first segment within the content */
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  */
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  */
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  */
232  /** Chunk type */
234  /** Chunk data length */
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  */
264  /** Segment length */
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 */
304  /** Length of data buffer */
305  size_t len;
306 };
307 
308 /** A content range */
310  /** Start offset */
311  size_t start;
312  /** End offset */
313  size_t end;
314 };
315 
316 /** Content information */
318  /** Raw content information */
320 
321  /** Content information operations */
323  /** Digest algorithm */
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 */
340  /** Trimmed content range */
342  /** Number of segments within the content information */
343  unsigned int segments;
344 };
345 
346 /** A content information 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  */
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  */
367  /** Segment secret
368  *
369  * This is MS-PCCRC's "Ke = Kp".
370  */
372  /** Segment identifier
373  *
374  * This is MS-PCCRC's "HoHoDk".
375  */
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 */
395  /** Content information 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  */
405  /** Trimmed content range */
407  /** Block hash */
409 };
410 
411 /** Content information 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 
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,
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 */
uint64_t len
Length of content range, or zero.
Definition: pccrc.h:220
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
size_t blksize
Block size.
Definition: pccrc.h:361
uint16_t segment
Code segment.
Definition: librm.h:252
unsigned short uint16_t
Definition: stdint.h:11
union peerdist_info_version version
Version number.
Definition: pccrc.h:198
u32 info
Definition: ar9003_mac.h:67
A content information segment.
Definition: pccrc.h:347
uint8_t hash
Hash algorithm.
Definition: pccrc.h:203
struct peerdist_raw __attribute__
userptr_t data
Data buffer.
Definition: pccrc.h:303
Content Information version 1 data structure header.
Definition: pccrc.h:62
uint8_t hash[PEERDIST_DIGEST_MAX_SIZE]
Segment hash of data.
Definition: pccrc.h:366
const struct peerdist_info_segment * segment
Content information segment.
Definition: pccrc.h:396
size_t start
Start offset.
Definition: pccrc.h:311
uint32_t blksize
Block size for this segment.
Definition: pccrc.h:123
uint64_t offset
Offset of the first segment within the content.
Definition: pccrc.h:205
struct peerdist_info_operations * op
Content information operations.
Definition: pccrc.h:322
uint32_t segments
Number of segments within the content information.
Definition: pccrc.h:84
unsigned long long uint64_t
Definition: stdint.h:13
Cryptographic API.
uint32_t len
Length of this segment.
Definition: pccrc.h:117
unsigned int index
Segment index.
Definition: pccrc.h:351
uint8_t secret[PEERDIST_DIGEST_MAX_SIZE]
Segment secret.
Definition: pccrc.h:371
unsigned int index
Block index.
Definition: pccrc.h:398
Access to external ("user") memory.
struct digest_algorithm * digest
Digest algorithm.
Definition: pccrc.h:324
int(* segment)(struct peerdist_info_segment *segment)
Populate content information segment.
Definition: pccrc.h:426
A content information block.
Definition: pccrc.h:394
Content Information version 1 block description header.
Definition: pccrc.h:157
size_t len
Length of data buffer.
Definition: pccrc.h:305
struct peerdist_range range
Content range.
Definition: pccrc.h:357
struct peerdist_info_version::@581 __attribute__((packed))
Major:minor version number.
struct peerdist_range trim
Trimmed content range.
Definition: pccrc.h:341
Content Information version 2 segment description header.
Definition: pccrc.h:263
Content Information version 1 segment description header.
Definition: pccrc.h:109
uint32_t len
Chunk data length.
Definition: pccrc.h:235
uint32_t first
Length to skip in first segment.
Definition: pccrc.h:213
uint32_t len
Length of this segment.
Definition: pccrc.h:18
Content information.
Definition: pccrc.h:317
uint32_t last
Length to read in last segment, or zero.
Definition: pccrc.h:82
A content range.
Definition: pccrc.h:309
uint16_t raw
Raw version number.
Definition: pccrc.h:35
struct peerdist_range trim
Trimmed content range.
Definition: pccrc.h:406
unsigned int segments
Number of segments within the content information.
Definition: pccrc.h:343
unsigned char uint8_t
Definition: stdint.h:10
union peerdist_info_version version
Version number.
Definition: pccrc.h:64
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:298
uint8_t major
Major version number.
Definition: pccrc.h:41
struct peerdist_range range
Content range.
Definition: pccrc.h:339
uint32_t hash
Hash algorithm.
Definition: pccrc.h:69
int peerdist_info(userptr_t data, size_t len, struct peerdist_info *info)
Populate content information.
Definition: pccrc.c:670
uint32_t first
Length to skip in first segment.
Definition: pccrc.h:75
uint32_t blocks
Number of blocks within the block description.
Definition: pccrc.h:164
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:359
const struct peerdist_info * info
Content information.
Definition: pccrc.h:349
Raw content information.
Definition: pccrc.h:301
A message digest algorithm.
Definition: crypto.h:17
uint8_t data[48]
Additional event data.
Definition: ena.h:22
size_t digestsize
Digest size.
Definition: pccrc.h:337
struct peerdist_range range
Content range.
Definition: pccrc.h:404
uint32_t len
Segment length.
Definition: pccrc.h:265
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:419
uint64_t index
Index of the first segment within the content.
Definition: pccrc.h:207
struct peerdist_raw raw
Raw content information.
Definition: pccrc.h:319
uint64_t index
Index of the first segment within the content.
Definition: pccrc.h:21
uint8_t type
Chunk type.
Definition: pccrc.h:233
Content Information version 2 data structure header.
Definition: pccrc.h:196
uint64_t offset
Offset of this segment within the content.
Definition: pccrc.h:111
Content Information version 2 chunk description header.
Definition: pccrc.h:231
int(* block)(struct peerdist_info_block *block)
Populate content information block.
Definition: pccrc.h:433
Content information operations.
Definition: pccrc.h:412
uint8_t minor
Minor version number.
Definition: pccrc.h:39
Content Information version number.
Definition: pccrc.h:28
uint8_t hash[PEERDIST_DIGEST_MAX_SIZE]
Block hash.
Definition: pccrc.h:408
unsigned long userptr_t
A pointer to a user buffer.
Definition: uaccess.h:33
size_t end
End offset.
Definition: pccrc.h:313