iPXE
pccrc.c
Go to the documentation of this file.
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
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_SECBOOT ( PERMITTED );
26
27#include <errno.h>
28#include <assert.h>
29#include <ipxe/sha256.h>
30#include <ipxe/sha512.h>
31#include <ipxe/hmac.h>
32#include <ipxe/base16.h>
33#include <ipxe/pccrc.h>
34
35/** @file
36 *
37 * Peer Content Caching and Retrieval: Content Identification [MS-PCCRC]
38 *
39 */
40
41/******************************************************************************
42 *
43 * Utility functions
44 *
45 ******************************************************************************
46 */
47
48/**
49 * Transcribe hash value (for debugging)
50 *
51 * @v info Content information
52 * @v hash Hash value
53 * @ret string Hash value string
54 */
55static inline const char *
56peerdist_info_hash_ntoa ( const struct peerdist_info *info, const void *hash ) {
57 static char buf[ ( 2 * PEERDIST_DIGEST_MAX_SIZE ) + 1 /* NUL */ ];
58 size_t digestsize = info->digestsize;
59
60 /* Sanity check */
61 assert ( info != NULL );
62 assert ( digestsize != 0 );
63 assert ( base16_encoded_len ( digestsize ) < sizeof ( buf ) );
64
65 /* Transcribe hash value */
66 base16_encode ( hash, digestsize, buf, sizeof ( buf ) );
67 return buf;
68}
69
70/**
71 * Get raw data
72 *
73 * @v info Content information
74 * @v data Data buffer
75 * @v offset Starting offset
76 * @v len Length
77 * @ret rc Return status code
78 */
79static int peerdist_info_get ( const struct peerdist_info *info, void *data,
80 size_t offset, size_t len ) {
81
82 /* Sanity check */
83 if ( ( offset > info->raw.len ) ||
84 ( len > ( info->raw.len - offset ) ) ) {
85 DBGC ( info, "PCCRC %p data underrun at [%zx,%zx) of %zx\n",
86 info, offset, ( offset + len ), info->raw.len );
87 return -ERANGE;
88 }
89
90 /* Copy data */
91 memcpy ( data, ( info->raw.data + offset ), len );
92
93 return 0;
94}
95
96/**
97 * Populate segment hashes
98 *
99 * @v segment Content information segment to fill in
100 * @v hash Segment hash of data
101 * @v secret Segment secret
102 */
104 const void *hash, const void *secret ){
105 const struct peerdist_info *info = segment->info;
106 struct digest_algorithm *digest = info->digest;
107 uint8_t ctx[ hmac_ctxsize ( digest ) ];
108 size_t digestsize = info->digestsize;
110
111 /* Sanity check */
112 assert ( digestsize <= sizeof ( segment->hash ) );
113 assert ( digestsize <= sizeof ( segment->secret ) );
114 assert ( digestsize <= sizeof ( segment->id ) );
115
116 /* Get segment hash of data */
117 memcpy ( segment->hash, hash, digestsize );
118
119 /* Get segment secret */
120 memcpy ( segment->secret, secret, digestsize );
121
122 /* Calculate segment identifier */
123 hmac_init ( digest, ctx, segment->secret, digestsize );
124 hmac_update ( digest, ctx, segment->hash, digestsize );
125 hmac_update ( digest, ctx, magic, sizeof ( magic ) );
126 hmac_final ( digest, ctx, segment->id );
127}
128
129/******************************************************************************
130 *
131 * Content Information version 1
132 *
133 ******************************************************************************
134 */
135
136/**
137 * Get number of blocks within a block description
138 *
139 * @v info Content information
140 * @v offset Block description offset
141 * @ret blocks Number of blocks, or negative error
142 */
143static int peerdist_info_v1_blocks ( const struct peerdist_info *info,
144 size_t offset ) {
146 unsigned int blocks;
147 int rc;
148
149 /* Get block description header */
150 if ( ( rc = peerdist_info_get ( info, &raw, offset,
151 sizeof ( raw ) ) ) != 0 )
152 return rc;
153
154 /* Calculate number of blocks */
155 blocks = le32_to_cpu ( raw.blocks );
156
157 return blocks;
158}
159
160/**
161 * Locate block description
162 *
163 * @v info Content information
164 * @v index Segment index
165 * @ret offset Block description offset, or negative error
166 */
168 unsigned int index ) {
169 size_t digestsize = info->digestsize;
170 unsigned int i;
171 size_t offset;
172 int blocks;
173 int rc;
174
175 /* Sanity check */
176 assert ( index < info->segments );
177
178 /* Calculate offset of first block description */
179 offset = ( sizeof ( struct peerdist_info_v1 ) +
180 ( info->segments *
181 sizeof ( peerdist_info_v1_segment_t ( digestsize ) ) ) );
182
183 /* Iterate over block descriptions until we find this segment */
184 for ( i = 0 ; i < index ; i++ ) {
185
186 /* Get number of blocks */
187 blocks = peerdist_info_v1_blocks ( info, offset );
188 if ( blocks < 0 ) {
189 rc = blocks;
190 DBGC ( info, "PCCRC %p segment %d could not get number "
191 "of blocks: %s\n", info, i, strerror ( rc ) );
192 return rc;
193 }
194
195 /* Move to next block description */
197 blocks ) );
198 }
199
200 return offset;
201}
202
203/**
204 * Populate content information
205 *
206 * @v info Content information to fill in
207 * @ret rc Return status code
208 */
209static int peerdist_info_v1 ( struct peerdist_info *info ) {
210 struct peerdist_info_v1 raw;
212 struct peerdist_info_segment last;
213 size_t first_skip;
214 size_t last_skip;
215 size_t last_read;
216 int rc;
217
218 /* Get raw header */
219 if ( ( rc = peerdist_info_get ( info, &raw, 0, sizeof ( raw ) ) ) != 0){
220 DBGC ( info, "PCCRC %p could not get V1 content information: "
221 "%s\n", info, strerror ( rc ) );
222 return rc;
223 }
224 assert ( raw.version.raw == cpu_to_le16 ( PEERDIST_INFO_V1 ) );
225
226 /* Determine hash algorithm */
227 switch ( raw.hash ) {
229 info->digest = &sha256_algorithm;
230 break;
232 info->digest = &sha384_algorithm;
233 break;
235 info->digest = &sha512_algorithm;
236 break;
237 default:
238 DBGC ( info, "PCCRC %p unsupported hash algorithm %#08x\n",
239 info, le32_to_cpu ( raw.hash ) );
240 return -ENOTSUP;
241 }
242 info->digestsize = info->digest->digestsize;
243 assert ( info->digest != NULL );
244 DBGC2 ( info, "PCCRC %p using %s[%zd]\n",
245 info, info->digest->name, ( info->digestsize * 8 ) );
246
247 /* Calculate number of segments */
248 info->segments = le32_to_cpu ( raw.segments );
249
250 /* Get first segment */
251 if ( ( rc = peerdist_info_segment ( info, &first, 0 ) ) != 0 )
252 return rc;
253
254 /* Calculate range start offset */
255 info->range.start = first.range.start;
256
257 /* Calculate trimmed range start offset */
258 first_skip = le32_to_cpu ( raw.first );
259 info->trim.start = ( first.range.start + first_skip );
260
261 /* Get last segment */
262 if ( ( rc = peerdist_info_segment ( info, &last,
263 ( info->segments - 1 ) ) ) != 0 )
264 return rc;
265
266 /* Calculate range end offset */
267 info->range.end = last.range.end;
268
269 /* Calculate trimmed range end offset */
270 if ( raw.last ) {
271 /* Explicit length to include from last segment is given */
272 last_read = le32_to_cpu ( raw.last );
273 last_skip = ( last.index ? 0 : first_skip );
274 info->trim.end = ( last.range.start + last_skip + last_read );
275 } else {
276 /* No explicit length given: range extends to end of segment */
277 info->trim.end = last.range.end;
278 }
279
280 return 0;
281}
282
283/**
284 * Populate content information segment
285 *
286 * @v segment Content information segment to fill in
287 * @ret rc Return status code
288 */
290 const struct peerdist_info *info = segment->info;
291 size_t digestsize = info->digestsize;
293 ssize_t raw_offset;
294 int blocks;
295 int rc;
296
297 /* Sanity checks */
298 assert ( segment->index < info->segments );
299
300 /* Get raw description */
301 raw_offset = ( sizeof ( struct peerdist_info_v1 ) +
302 ( segment->index * sizeof ( raw ) ) );
303 if ( ( rc = peerdist_info_get ( info, &raw, raw_offset,
304 sizeof ( raw ) ) ) != 0 ) {
305 DBGC ( info, "PCCRC %p segment %d could not get segment "
306 "description: %s\n", info, segment->index,
307 strerror ( rc ) );
308 return rc;
309 }
310
311 /* Calculate start offset of this segment */
312 segment->range.start = le64_to_cpu ( raw.segment.offset );
313
314 /* Calculate end offset of this segment */
315 segment->range.end = ( segment->range.start +
316 le32_to_cpu ( raw.segment.len ) );
317
318 /* Calculate block size of this segment */
319 segment->blksize = le32_to_cpu ( raw.segment.blksize );
320
321 /* Locate block description for this segment */
322 raw_offset = peerdist_info_v1_block_offset ( info, segment->index );
323 if ( raw_offset < 0 ) {
324 rc = raw_offset;
325 return rc;
326 }
327
328 /* Get number of blocks */
329 blocks = peerdist_info_v1_blocks ( info, raw_offset );
330 if ( blocks < 0 ) {
331 rc = blocks;
332 DBGC ( info, "PCCRC %p segment %d could not get number of "
333 "blocks: %s\n", info, segment->index, strerror ( rc ) );
334 return rc;
335 }
336 segment->blocks = blocks;
337
338 /* Calculate segment hashes */
339 peerdist_info_segment_hash ( segment, raw.hash, raw.secret );
340
341 return 0;
342}
343
344/**
345 * Populate content information block
346 *
347 * @v block Content information block to fill in
348 * @ret rc Return status code
349 */
351 const struct peerdist_info_segment *segment = block->segment;
352 const struct peerdist_info *info = segment->info;
353 size_t digestsize = info->digestsize;
355 ssize_t raw_offset;
356 int rc;
357
358 /* Sanity checks */
359 assert ( block->index < segment->blocks );
360
361 /* Calculate start offset of this block */
362 block->range.start = ( segment->range.start +
363 ( block->index * segment->blksize ) );
364
365 /* Calculate end offset of this block */
366 block->range.end = ( block->range.start + segment->blksize );
367 if ( block->range.end > segment->range.end )
368 block->range.end = segment->range.end;
369
370 /* Locate block description */
371 raw_offset = peerdist_info_v1_block_offset ( info, segment->index );
372 if ( raw_offset < 0 ) {
373 rc = raw_offset;
374 return rc;
375 }
376
377 /* Get block hash */
378 raw_offset += offsetof ( typeof ( raw ), hash[block->index] );
379 if ( ( rc = peerdist_info_get ( info, block->hash, raw_offset,
380 digestsize ) ) != 0 ) {
381 DBGC ( info, "PCCRC %p segment %d block %d could not get "
382 "hash: %s\n", info, segment->index, block->index,
383 strerror ( rc ) );
384 return rc;
385 }
386
387 return 0;
388}
389
390/** Content information version 1 operations */
396
397/******************************************************************************
398 *
399 * Content Information version 2
400 *
401 ******************************************************************************
402 */
403
404/** A segment cursor */
406 /** Raw data offset */
407 size_t offset;
408 /** Number of segments remaining within this chunk */
409 unsigned int remaining;
410 /** Accumulated segment length */
411 size_t len;
412};
413
414/**
415 * Initialise segment cursor
416 *
417 * @v cursor Segment cursor
418 */
419static inline void
421
422 /* Initialise cursor */
423 cursor->offset = ( sizeof ( struct peerdist_info_v2 ) +
424 sizeof ( struct peerdist_info_v2_chunk ) );
425 cursor->remaining = 0;
426 cursor->len = 0;
427}
428
429/**
430 * Update segment cursor to next segment description
431 *
432 * @v info Content information
433 * @v offset Current offset
434 * @v remaining Number of segments remaining within this chunk
435 * @ret rc Return status code
436 */
437static int
439 struct peerdist_info_v2_cursor *cursor ) {
440 size_t digestsize = info->digestsize;
442 struct peerdist_info_v2_chunk chunk;
443 int rc;
444
445 /* Get chunk description if applicable */
446 if ( ! cursor->remaining ) {
447
448 /* Get chunk description */
449 if ( ( rc = peerdist_info_get ( info, &chunk,
450 ( cursor->offset -
451 sizeof ( chunk ) ),
452 sizeof ( chunk ) ) ) != 0 )
453 return rc;
454
455 /* Update number of segments remaining */
456 cursor->remaining = ( be32_to_cpu ( chunk.len ) /
457 sizeof ( raw ) );
458 }
459
460 /* Get segment description header */
461 if ( ( rc = peerdist_info_get ( info, &raw.segment, cursor->offset,
462 sizeof ( raw.segment ) ) ) != 0 )
463 return rc;
464
465 /* Update cursor */
466 cursor->offset += sizeof ( raw );
467 cursor->remaining--;
468 if ( ! cursor->remaining )
469 cursor->offset += sizeof ( chunk );
470 cursor->len += be32_to_cpu ( raw.segment.len );
471
472 return 0;
473}
474
475/**
476 * Get number of segments and total length
477 *
478 * @v info Content information
479 * @v len Length to fill in
480 * @ret rc Number of segments, or negative error
481 */
483 size_t *len ) {
484 struct peerdist_info_v2_cursor cursor;
485 unsigned int segments;
486 int rc;
487
488 /* Iterate over all segments */
489 for ( peerdist_info_v2_cursor_init ( &cursor ), segments = 0 ;
490 cursor.offset < info->raw.len ; segments++ ) {
491
492 /* Update segment cursor */
494 &cursor ) ) != 0 ) {
495 DBGC ( info, "PCCRC %p segment %d could not update "
496 "segment cursor: %s\n",
497 info, segments, strerror ( rc ) );
498 return rc;
499 }
500 }
501
502 /* Record accumulated length */
503 *len = cursor.len;
504
505 return segments;
506}
507
508/**
509 * Populate content information
510 *
511 * @v info Content information to fill in
512 * @ret rc Return status code
513 */
514static int peerdist_info_v2 ( struct peerdist_info *info ) {
515 struct peerdist_info_v2 raw;
516 size_t len = 0;
517 int segments;
518 int rc;
519
520 /* Get raw header */
521 if ( ( rc = peerdist_info_get ( info, &raw, 0, sizeof ( raw ) ) ) != 0){
522 DBGC ( info, "PCCRC %p could not get V2 content information: "
523 "%s\n", info, strerror ( rc ) );
524 return rc;
525 }
526 assert ( raw.version.raw == cpu_to_le16 ( PEERDIST_INFO_V2 ) );
527
528 /* Determine hash algorithm */
529 switch ( raw.hash ) {
531 info->digest = &sha512_algorithm;
532 info->digestsize = ( 256 / 8 );
533 break;
534 default:
535 DBGC ( info, "PCCRC %p unsupported hash algorithm %#02x\n",
536 info, raw.hash );
537 return -ENOTSUP;
538 }
539 assert ( info->digest != NULL );
540 DBGC2 ( info, "PCCRC %p using %s[%zd]\n",
541 info, info->digest->name, ( info->digestsize * 8 ) );
542
543 /* Calculate number of segments and total length */
544 segments = peerdist_info_v2_segments ( info, &len );
545 if ( segments < 0 ) {
546 rc = segments;
547 DBGC ( info, "PCCRC %p could not get segment count and length: "
548 "%s\n", info, strerror ( rc ) );
549 return rc;
550 }
551 info->segments = segments;
552
553 /* Calculate range start offset */
554 info->range.start = be64_to_cpu ( raw.offset );
555
556 /* Calculate trimmed range start offset */
557 info->trim.start = ( info->range.start + be32_to_cpu ( raw.first ) );
558
559 /* Calculate range end offset */
560 info->range.end = ( info->range.start + len );
561
562 /* Calculate trimmed range end offset */
563 info->trim.end = ( raw.len ? be64_to_cpu ( raw.len ) :
564 info->range.end );
565
566 return 0;
567}
568
569/**
570 * Populate content information segment
571 *
572 * @v segment Content information segment to fill in
573 * @ret rc Return status code
574 */
576 const struct peerdist_info *info = segment->info;
577 size_t digestsize = info->digestsize;
579 struct peerdist_info_v2_cursor cursor;
580 unsigned int index;
581 size_t len;
582 int rc;
583
584 /* Sanity checks */
585 assert ( segment->index < info->segments );
586
587 /* Iterate over all segments before the target segment */
588 for ( peerdist_info_v2_cursor_init ( &cursor ), index = 0 ;
589 index < segment->index ; index++ ) {
590
591 /* Update segment cursor */
593 &cursor ) ) != 0 ) {
594 DBGC ( info, "PCCRC %p segment %d could not update "
595 "segment cursor: %s\n",
596 info, index, strerror ( rc ) );
597 return rc;
598 }
599 }
600
601 /* Get raw description */
602 if ( ( rc = peerdist_info_get ( info, &raw, cursor.offset,
603 sizeof ( raw ) ) ) != 0 ) {
604 DBGC ( info, "PCCRC %p segment %d could not get segment "
605 "description: %s\n",
606 info, segment->index, strerror ( rc ) );
607 return rc;
608 }
609
610 /* Calculate start offset of this segment */
611 segment->range.start = ( info->range.start + cursor.len );
612
613 /* Calculate end offset of this segment */
614 len = be32_to_cpu ( raw.segment.len );
615 segment->range.end = ( segment->range.start + len );
616
617 /* Model as a segment containing a single block */
618 segment->blocks = 1;
619 segment->blksize = len;
620
621 /* Calculate segment hashes */
622 peerdist_info_segment_hash ( segment, raw.hash, raw.secret );
623
624 return 0;
625}
626
627/**
628 * Populate content information block
629 *
630 * @v block Content information block to fill in
631 * @ret rc Return status code
632 */
634 const struct peerdist_info_segment *segment = block->segment;
635 const struct peerdist_info *info = segment->info;
636 size_t digestsize = info->digestsize;
637
638 /* Sanity checks */
639 assert ( block->index < segment->blocks );
640
641 /* Model as a block covering the whole segment */
642 memcpy ( &block->range, &segment->range, sizeof ( block->range ) );
643 memcpy ( block->hash, segment->hash, digestsize );
644
645 return 0;
646}
647
648/** Content information version 2 operations */
654
655/******************************************************************************
656 *
657 * Content Information
658 *
659 ******************************************************************************
660 */
661
662/**
663 * Populate content information
664 *
665 * @v data Raw data
666 * @v len Length of raw data
667 * @v info Content information to fill in
668 * @ret rc Return status code
669 */
670int peerdist_info ( const void *data, size_t len,
671 struct peerdist_info *info ) {
673 int rc;
674
675 /* Initialise structure */
676 memset ( info, 0, sizeof ( *info ) );
677 info->raw.data = data;
678 info->raw.len = len;
679
680 /* Get version */
681 if ( ( rc = peerdist_info_get ( info, &version, 0,
682 sizeof ( version ) ) ) != 0 ) {
683 DBGC ( info, "PCCRC %p could not get version: %s\n",
684 info, strerror ( rc ) );
685 return rc;
686 }
687 DBGC2 ( info, "PCCRC %p version %d.%d\n",
688 info, version.major, version.minor );
689
690 /* Determine version */
691 switch ( version.raw ) {
694 break;
697 break;
698 default:
699 DBGC ( info, "PCCRC %p unsupported version %d.%d\n",
700 info, version.major, version.minor );
701 return -ENOTSUP;
702 }
703 assert ( info->op != NULL );
704 assert ( info->op->info != NULL );
705
706 /* Populate content information */
707 if ( ( rc = info->op->info ( info ) ) != 0 )
708 return rc;
709
710 DBGC2 ( info, "PCCRC %p range [%08zx,%08zx) covers [%08zx,%08zx) with "
711 "%d segments\n", info, info->range.start, info->range.end,
712 info->trim.start, info->trim.end, info->segments );
713 return 0;
714}
715
716/**
717 * Populate content information segment
718 *
719 * @v info Content information
720 * @v segment Content information segment to fill in
721 * @v index Segment index
722 * @ret rc Return status code
723 */
726 unsigned int index ) {
727 int rc;
728
729 /* Sanity checks */
730 assert ( info != NULL );
731 assert ( info->op != NULL );
732 assert ( info->op->segment != NULL );
733 if ( index >= info->segments ) {
734 DBGC ( info, "PCCRC %p segment %d of [0,%d) out of range\n",
735 info, index, info->segments );
736 return -ERANGE;
737 }
738
739 /* Initialise structure */
740 memset ( segment, 0, sizeof ( *segment ) );
741 segment->info = info;
742 segment->index = index;
743
744 /* Populate content information segment */
745 if ( ( rc = info->op->segment ( segment ) ) != 0 )
746 return rc;
747
748 DBGC2 ( info, "PCCRC %p segment %d range [%08zx,%08zx) with %d "
749 "blocks\n", info, segment->index, segment->range.start,
750 segment->range.end, segment->blocks );
751 DBGC2 ( info, "PCCRC %p segment %d digest %s\n", info, segment->index,
753 DBGC2 ( info, "PCCRC %p segment %d secret %s\n", info, segment->index,
754 peerdist_info_hash_ntoa ( info, segment->secret ) );
755 DBGC2 ( info, "PCCRC %p segment %d identf %s\n", info, segment->index,
757 return 0;
758}
759
760/**
761 * Populate content information block
762 *
763 * @v segment Content information segment
764 * @v block Content information block to fill in
765 * @v index Block index
766 * @ret rc Return status code
767 */
770 unsigned int index ) {
771 const struct peerdist_info *info = segment->info;
772 size_t start;
773 size_t end;
774 int rc;
775
776 /* Sanity checks */
777 assert ( segment != NULL );
778 assert ( info != NULL );
779 assert ( info->op != NULL );
780 assert ( info->op->block != NULL );
781 if ( index >= segment->blocks ) {
782 DBGC ( info, "PCCRC %p segment %d block %d of [0,%d) out of "
783 "range\n", info, segment->index, index, segment->blocks);
784 return -ERANGE;
785 }
786
787 /* Initialise structure */
788 memset ( block, 0, sizeof ( *block ) );
789 block->segment = segment;
790 block->index = index;
791
792 /* Populate content information block */
793 if ( ( rc = info->op->block ( block ) ) != 0 )
794 return rc;
795
796 /* Calculate trimmed range */
797 start = block->range.start;
799 start = info->trim.start;
800 end = block->range.end;
801 if ( end > info->trim.end )
802 end = info->trim.end;
803 if ( end < start )
804 end = start;
805 block->trim.start = start;
806 block->trim.end = end;
807
808 DBGC2 ( info, "PCCRC %p segment %d block %d hash %s\n",
809 info, segment->index, block->index,
811 DBGC2 ( info, "PCCRC %p segment %d block %d range [%08zx,%08zx) covers "
812 "[%08zx,%08zx)\n", info, segment->index, block->index,
813 block->range.start, block->range.end, block->trim.start,
814 block->trim.end );
815 return 0;
816}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
struct golan_eq_context ctx
Definition CIB_PRM.h:0
__be32 raw[7]
Definition CIB_PRM.h:0
typeof(acpi_finder=acpi_find)
ACPI table finder.
Definition acpi.c:48
u32 info
Definition ar9003_mac.h:0
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
pseudo_bit_t hash[0x00010]
Definition arbel.h:2
unsigned short uint16_t
Definition stdint.h:11
unsigned char uint8_t
Definition stdint.h:10
signed long ssize_t
Definition stdint.h:7
long index
Definition bigint.h:65
Assertions.
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
u32 version
Driver version.
Definition ath9k_hw.c:1985
Base16 encoding.
static size_t base16_encoded_len(size_t raw_len)
Calculate length of base16-encoded data.
Definition base16.h:25
uint16_t magic
Magic signature.
Definition bzimage.h:1
uint16_t offset
Offset to command line.
Definition bzimage.h:3
ring len
Length.
Definition dwmac.h:226
uint8_t data[48]
Additional event data.
Definition ena.h:11
Error codes.
#define DBGC2(...)
Definition compiler.h:522
#define DBGC(...)
Definition compiler.h:505
uint32_t start
Starting offset.
Definition netvsc.h:1
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define ENOTSUP
Operation not supported.
Definition errno.h:590
#define ERANGE
Result too large.
Definition errno.h:640
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
void hmac_init(struct digest_algorithm *digest, void *ctx, const void *key, size_t key_len)
Initialise HMAC.
Definition hmac.c:58
void hmac_final(struct digest_algorithm *digest, void *ctx, void *hmac)
Finalise HMAC.
Definition hmac.c:88
Keyed-Hashing for Message Authentication.
static void hmac_update(struct digest_algorithm *digest, void *ctx, const void *data, size_t len)
Update HMAC.
Definition hmac.h:43
static size_t hmac_ctxsize(struct digest_algorithm *digest)
Calculate HMAC context size.
Definition hmac.h:29
#define be32_to_cpu(value)
Definition byteswap.h:117
#define le64_to_cpu(value)
Definition byteswap.h:115
#define le32_to_cpu(value)
Definition byteswap.h:114
#define cpu_to_le32(value)
Definition byteswap.h:108
#define cpu_to_le16(value)
Definition byteswap.h:107
#define be64_to_cpu(value)
Definition byteswap.h:118
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
uint16_t segment
Code segment.
Definition librm.h:3
uint8_t block[3][8]
DES-encrypted blocks.
Definition mschapv2.h:1
uint32_t end
Ending offset.
Definition netvsc.h:7
static int peerdist_info_v2_cursor_next(const struct peerdist_info *info, struct peerdist_info_v2_cursor *cursor)
Update segment cursor to next segment description.
Definition pccrc.c:438
static int peerdist_info_v1_block(struct peerdist_info_block *block)
Populate content information block.
Definition pccrc.c:350
static const char * peerdist_info_hash_ntoa(const struct peerdist_info *info, const void *hash)
Transcribe hash value (for debugging)
Definition pccrc.c:56
static void peerdist_info_segment_hash(struct peerdist_info_segment *segment, const void *hash, const void *secret)
Populate segment hashes.
Definition pccrc.c:103
static int peerdist_info_v2_segments(const struct peerdist_info *info, size_t *len)
Get number of segments and total length.
Definition pccrc.c:482
int peerdist_info_segment(const struct peerdist_info *info, struct peerdist_info_segment *segment, unsigned int index)
Populate content information segment.
Definition pccrc.c:724
static int peerdist_info_v1_blocks(const struct peerdist_info *info, size_t offset)
Get number of blocks within a block description.
Definition pccrc.c:143
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:768
static int peerdist_info_v2_block(struct peerdist_info_block *block)
Populate content information block.
Definition pccrc.c:633
static void peerdist_info_v2_cursor_init(struct peerdist_info_v2_cursor *cursor)
Initialise segment cursor.
Definition pccrc.c:420
static int peerdist_info_v2_segment(struct peerdist_info_segment *segment)
Populate content information segment.
Definition pccrc.c:575
static ssize_t peerdist_info_v1_block_offset(const struct peerdist_info *info, unsigned int index)
Locate block description.
Definition pccrc.c:167
static struct peerdist_info_operations peerdist_info_v1_operations
Content information version 1 operations.
Definition pccrc.c:391
static struct peerdist_info_operations peerdist_info_v2_operations
Content information version 2 operations.
Definition pccrc.c:649
static int peerdist_info_get(const struct peerdist_info *info, void *data, size_t offset, size_t len)
Get raw data.
Definition pccrc.c:79
static int peerdist_info_v1_segment(struct peerdist_info_segment *segment)
Populate content information segment.
Definition pccrc.c:289
static int peerdist_info_v1(struct peerdist_info *info)
Populate content information.
Definition pccrc.c:209
static int peerdist_info_v2(struct peerdist_info *info)
Populate content information.
Definition pccrc.c:514
int peerdist_info(const void *data, size_t len, struct peerdist_info *info)
Populate content information.
Definition pccrc.c:670
Peer Content Caching and Retrieval: Content Identification [MS-PCCRC].
#define PEERDIST_INFO_V2
Content Information version 2.
Definition pccrc.h:49
#define peerdist_info_v1_block_t(digestsize, blocks)
Content Information version 1 block description.
Definition pccrc.h:179
#define PEERDIST_INFO_V1_HASH_SHA512
SHA-512 hash algorithm.
Definition pccrc.h:103
#define PEERDIST_INFO_V1_HASH_SHA384
SHA-384 hash algorithm.
Definition pccrc.h:100
#define PEERDIST_INFO_V2_HASH_SHA512_TRUNC
SHA-512 hash algorithm with output truncated to first 256 bits.
Definition pccrc.h:225
#define PEERDIST_INFO_V1_HASH_SHA256
SHA-256 hash algorithm.
Definition pccrc.h:97
#define peerdist_info_v2_segment_t(digestsize)
Content Information version 2 segment description.
Definition pccrc.h:280
#define PEERDIST_INFO_V1
Content Information version 1.
Definition pccrc.h:46
#define peerdist_info_v1_segment_t(digestsize)
Content Information version 1 segment description.
Definition pccrc.h:146
#define PEERDIST_DIGEST_MAX_SIZE
Maximum digest size for any supported algorithm.
Definition pccrc.h:298
#define PEERDIST_SEGMENT_ID_MAGIC
Magic string constant used to calculate segment identifier.
Definition pccrc.h:391
uint32_t first
First block in range.
Definition pccrr.h:1
uint32_t digestsize
Digest size (i.e.
Definition pccrr.h:1
struct digest_algorithm sha256_algorithm
SHA-256 algorithm.
Definition sha256.c:265
SHA-256 algorithm.
struct digest_algorithm sha384_algorithm
SHA-384 algorithm.
Definition sha384.c:64
struct digest_algorithm sha512_algorithm
SHA-512 algorithm.
Definition sha512.c:285
SHA-512 algorithm.
#define offsetof(type, field)
Get offset of a field within a structure.
Definition stddef.h:25
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
A message digest algorithm.
Definition crypto.h:19
A content information block.
Definition pccrc.h:394
Content information operations.
Definition pccrc.h:412
A content information segment.
Definition pccrc.h:347
unsigned int index
Segment index.
Definition pccrc.h:351
struct peerdist_range range
Content range.
Definition pccrc.h:357
Content Information version 1 block description header.
Definition pccrc.h:157
uint32_t blocks
Number of blocks within the block description.
Definition pccrc.h:164
Content Information version 1 segment description header.
Definition pccrc.h:109
Content Information version 1 data structure header.
Definition pccrc.h:62
uint32_t segments
Number of segments within the content information.
Definition pccrc.h:84
Content Information version 2 chunk description header.
Definition pccrc.h:231
uint32_t len
Chunk data length.
Definition pccrc.h:235
A segment cursor.
Definition pccrc.c:405
unsigned int remaining
Number of segments remaining within this chunk.
Definition pccrc.c:409
size_t offset
Raw data offset.
Definition pccrc.c:407
size_t len
Accumulated segment length.
Definition pccrc.c:411
Content Information version 2 segment description header.
Definition pccrc.h:263
Content Information version 2 data structure header.
Definition pccrc.h:196
Content information.
Definition pccrc.h:317
struct peerdist_range trim
Trimmed content range.
Definition pccrc.h:341
size_t start
Start offset.
Definition pccrc.h:311
size_t end
End offset.
Definition pccrc.h:313
Content Information version number.
Definition pccrc.h:28