From a8d9cd9485c5cda7b99df3aff9b09b74d74b9d3a Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 28 Jul 2015 15:59:43 +0100 Subject: [peerdist] Add support for constructing and decoding retrieval messages Signed-off-by: Michael Brown --- src/include/ipxe/pccrr.h | 376 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 376 insertions(+) create mode 100644 src/include/ipxe/pccrr.h diff --git a/src/include/ipxe/pccrr.h b/src/include/ipxe/pccrr.h new file mode 100644 index 0000000..1ea86c4 --- /dev/null +++ b/src/include/ipxe/pccrr.h @@ -0,0 +1,376 @@ +#ifndef _IPXE_PCCRR_H +#define _IPXE_PCCRR_H + +/** @file + * + * Peer Content Caching and Retrieval: Retrieval Protocol [MS-PCCRR] + * + * All fields are in network byte order. + * + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +#include +#include + +/** Magic retrieval URI path */ +#define PEERDIST_MAGIC_PATH "/116B50EB-ECE2-41ac-8429-9F9E963361B7/" + +/** Retrieval protocol version */ +union peerdist_msg_version { + /** Raw version number */ + uint32_t raw; + /** Major:minor version number */ + struct { + /** Minor version number */ + uint16_t minor; + /** Major version number */ + uint16_t major; + } __attribute__ (( packed )); +} __attribute__ (( packed )); + +/** Retrieval protocol version 1.0 */ +#define PEERDIST_MSG_VERSION_1_0 0x00000001UL + +/** Retrieval protocol version 2.0 */ +#define PEERDIST_MSG_VERSION_2_0 0x00000002UL + +/** Retrieval protocol supported versions */ +struct peerdist_msg_versions { + /** Minimum supported protocol version */ + union peerdist_msg_version min; + /** Maximum supported protocol version */ + union peerdist_msg_version max; +} __attribute__ (( packed )); + +/** Retrieval protocol block range */ +struct peerdist_msg_range { + /** First block in range */ + uint32_t first; + /** Number of blocks in range */ + uint32_t count; +} __attribute__ (( packed )); + +/** Retrieval protocol segment ID header */ +struct peerdist_msg_segment { + /** Digest size (i.e. length of segment ID) */ + uint32_t digestsize; + /* Followed by a single variable-length ID and padding: + * + * uint8_t id[digestsize]; + * uint8_t pad[ (-digestsize) & 0x3 ]; + */ +} __attribute__ (( packed )); + +/** Retrieval protocol segment ID + * + * @v digestsize Digest size + */ +#define peerdist_msg_segment_t( digestsize ) \ + struct { \ + struct peerdist_msg_segment segment; \ + uint8_t id[digestsize]; \ + uint8_t pad[ ( -(digestsize) ) & 0x3 ]; \ + } __attribute__ (( packed )) + +/** Retrieval protocol block range list header */ +struct peerdist_msg_ranges { + /** Number of ranges */ + uint32_t count; + /* Followed by an array of block ranges: + * + * struct peerdist_msg_range range[count]; + */ +} __attribute__ (( packed )); + +/** Retrieval protocol block range list + * + * @v count Number of ranges + */ +#define peerdist_msg_ranges_t( count ) \ + struct { \ + struct peerdist_msg_ranges ranges; \ + struct peerdist_msg_range range[count]; \ + } __attribute__ (( packed )) + +/** Retrieval protocol data block header */ +struct peerdist_msg_block { + /** Length of data block */ + uint32_t len; + /* Followed by the (encrypted) data block: + * + * uint8_t data[len]; + */ +} __attribute__ (( packed )); + +/** Retrieval protocol data block */ +#define peerdist_msg_block_t( len ) \ + struct { \ + struct peerdist_msg_block block; \ + uint8_t data[len]; \ + } __attribute__ (( packed )) + +/** Retrieval protocol initialisation vector header */ +struct peerdist_msg_iv { + /** Cipher block size */ + uint32_t blksize; + /* Followed by the initialisation vector: + * + * uint8_t data[blksize]; + */ +} __attribute__ (( packed )); + +/** Retrieval protocol initialisation vector */ +#define peerdist_msg_iv_t( blksize ) \ + struct { \ + struct peerdist_msg_iv iv; \ + uint8_t data[blksize]; \ + } __attribute__ (( packed )) + +/** Retrieval protocol useless VRF data header */ +struct peerdist_msg_useless_vrf { + /** Length of useless VRF data */ + uint32_t len; + /* Followed by a variable-length useless VRF data block and + * padding: + * + * uint8_t data[len]; + * uint8_t pad[ (-len) & 0x3 ]; + */ +} __attribute__ (( packed )); + +/** Retrieval protocol useless VRF data */ +#define peerdist_msg_useless_vrf_t( vrf_len ) \ + struct { \ + struct peerdist_msg_useless_vrf vrf; \ + uint8_t data[vrf_len]; \ + uint8_t pad[ ( -(vrf_len) ) & 0x3 ]; \ + } __attribute__ (( packed )) + +/** Retrieval protocol message header */ +struct peerdist_msg_header { + /** Protocol version + * + * This is the protocol version in which the message type was + * first defined. + */ + union peerdist_msg_version version; + /** Message type */ + uint32_t type; + /** Message size (including this header) */ + uint32_t len; + /** Cryptographic algorithm ID */ + uint32_t algorithm; +} __attribute__ (( packed )); + +/** Retrieval protocol cryptographic algorithm IDs */ +enum peerdist_msg_algorithm { + /** No encryption */ + PEERDIST_MSG_PLAINTEXT = 0x00000000UL, + /** AES-128 in CBC mode */ + PEERDIST_MSG_AES_128_CBC = 0x00000001UL, + /** AES-192 in CBC mode */ + PEERDIST_MSG_AES_192_CBC = 0x00000002UL, + /** AES-256 in CBC mode */ + PEERDIST_MSG_AES_256_CBC = 0x00000003UL, +}; + +/** Retrieval protocol transport response header */ +struct peerdist_msg_transport_header { + /** Length (excluding this header) + * + * This seems to be identical in both purpose and value to the + * length found within the message header, and therefore + * serves no useful purpose. + */ + uint32_t len; +} __attribute__ (( packed )); + +/** Retrieval protocol negotiation request */ +struct peerdist_msg_nego_req { + /** Message header */ + struct peerdist_msg_header hdr; + /** Supported versions */ + struct peerdist_msg_versions versions; +} __attribute__ (( packed )); + +/** Retrieval protocol negotiation request version */ +#define PEERDIST_MSG_NEGO_REQ_VERSION PEERDIST_MSG_VERSION_1_0 + +/** Retrieval protocol negotiation request type */ +#define PEERDIST_MSG_NEGO_REQ_TYPE 0x00000000UL + +/** Retrieval protocol negotiation response */ +struct peerdist_msg_nego_resp { + /** Message header */ + struct peerdist_msg_header hdr; + /** Supported versions */ + struct peerdist_msg_versions versions; +} __attribute__ (( packed )); + +/** Retrieval protocol negotiation response version */ +#define PEERDIST_MSG_NEGO_RESP_VERSION PEERDIST_MSG_VERSION_1_0 + +/** Retrieval protocol negotiation response type */ +#define PEERDIST_MSG_NEGO_RESP_TYPE 0x00000001UL + +/** Retrieval protocol block list request header */ +struct peerdist_msg_getblklist { + /** Message header */ + struct peerdist_msg_header hdr; + /* Followed by a segment ID and a block range list: + * + * peerdist_msg_segment_t(digestsize) segment; + * peerdist_msg_ranges_t(count) ranges; + */ +} __attribute__ (( packed )); + +/** Retrieval protocol block list request + * + * @v digestsize Digest size + * @v count Block range count + */ +#define peerdist_msg_getblklist_t( digestsize, count ) \ + struct { \ + struct peerdist_msg_getblklist getblklist; \ + peerdist_msg_segment_t ( digestsize ) segment; \ + peerdist_msg_ranges_t ( count ) ranges; \ + } __attribute__ (( packed )) + +/** Retrieval protocol block list request version */ +#define PEERDIST_MSG_GETBLKLIST_VERSION PEERDIST_MSG_VERSION_1_0 + +/** Retrieval protocol block list request type */ +#define PEERDIST_MSG_GETBLKLIST_TYPE 0x00000002UL + +/** Retrieval protocol block fetch request header */ +struct peerdist_msg_getblks { + /** Message header */ + struct peerdist_msg_header hdr; + /* Followed by a segment ID, a block range list, and a useless + * VRF block: + * + * peerdist_msg_segment_t(digestsize) segment; + * peerdist_msg_ranges_t(count) ranges; + * peerdist_msg_vrf_t(vrf_len) vrf; + */ +} __attribute__ (( packed )); + +/** Retrieval protocol block fetch request + * + * @v digestsize Digest size + * @v count Block range count + * @v vrf_len Length of uselessness + */ +#define peerdist_msg_getblks_t( digestsize, count, vrf_len ) \ + struct { \ + struct peerdist_msg_getblks getblks; \ + peerdist_msg_segment_t ( digestsize ) segment; \ + peerdist_msg_ranges_t ( count ) ranges; \ + peerdist_msg_useless_vrf_t ( vrf_len ); \ + } __attribute__ (( packed )) + +/** Retrieval protocol block fetch request version */ +#define PEERDIST_MSG_GETBLKS_VERSION PEERDIST_MSG_VERSION_1_0 + +/** Retrieval protocol block fetch request type */ +#define PEERDIST_MSG_GETBLKS_TYPE 0x00000003UL + +/** Retrieval protocol block list response header */ +struct peerdist_msg_blklist { + /** Message header */ + struct peerdist_msg_header hdr; + /* Followed by a segment ID, a block range list, and a next + * block index: + * + * peerdist_msg_segment_t(digestsize) segment; + * peerdist_msg_ranges_t(count) ranges; + * uint32_t next; + */ +} __attribute__ (( packed )); + +/** Retrieval protocol block list response + * + * @v digestsize Digest size + * @v count Block range count + */ +#define peerdist_msg_blklist_t( digestsize, count ) \ + struct { \ + struct peerdist_msg_blklist blklist; \ + peerdist_msg_segment_t ( digestsize ) segment; \ + peerdist_msg_ranges_t ( count ) ranges; \ + uint32_t next; \ + } __attribute__ (( packed )) + +/** Retrieval protocol block list response version */ +#define PEERDIST_MSG_BLKLIST_VERSION PEERDIST_MSG_VERSION_1_0 + +/** Retrieval protocol block list response type */ +#define PEERDIST_MSG_BLKLIST_TYPE 0x00000004UL + +/** Retrieval protocol block fetch response header */ +struct peerdist_msg_blk { + /** Message header */ + struct peerdist_msg_header hdr; + /* Followed by a segment ID, a block index, a next block + * index, a data block, a useless VRF block, and an + * initialisation vector: + * + * peerdist_msg_segment_t(digestsize) segment; + * uint32_t index; + * uint32_t next; + * peerdist_msg_block_t(len) data; + * peerdist_msg_useless_vrf_t(vrf_len) vrf; + * peerdist_msg_iv_t(blksize) iv; + */ +} __attribute__ (( packed )); + +/** Retrieval protocol block fetch response + * + * @v digestsize Digest size + * @v len Data block length + * @v vrf_len Length of uselessness + * @v blksize Cipher block size + */ +#define peerdist_msg_blk_t( digestsize, len, vrf_len, blksize ) \ + struct { \ + struct peerdist_msg_blk blk; \ + peerdist_msg_segment_t ( digestsize ) segment; \ + uint32_t index; \ + uint32_t next; \ + peerdist_msg_block_t ( len ) block; \ + peerdist_msg_useless_vrf_t ( vrf_len ) vrf; \ + peerdist_msg_iv_t ( blksize ) iv; \ + } __attribute__ (( packed )) + +/** Retrieval protocol block fetch response version */ +#define PEERDIST_MSG_BLK_VERSION PEERDIST_MSG_VERSION_1_0 + +/** Retrieval protocol block fetch response type */ +#define PEERDIST_MSG_BLK_TYPE 0x00000005UL + +/** + * Parse retrieval protocol block fetch response + * + * @v raw Raw data + * @v raw_len Length of raw data + * @v digestsize Digest size + * @v blksize Cipher block size + * @v blk Structure to fill in + * @ret rc Return status code + */ +#define peerdist_msg_blk( raw, raw_len, digestsize, blksize, blk ) ( { \ + assert ( sizeof ( (blk)->segment.id ) == (digestsize) ); \ + assert ( sizeof ( (blk)->block.data ) == 0 ); \ + assert ( sizeof ( (blk)->vrf.data ) == 0 ); \ + assert ( sizeof ( (blk)->iv.data ) == blksize ); \ + peerdist_msg_blk_untyped ( (raw), (raw_len), (digestsize), \ + (blksize), blk ); \ + } ) + +extern int peerdist_msg_blk_untyped ( userptr_t raw, size_t raw_len, + size_t digestsize, size_t blksize, + void *out ); + +#endif /* _IPXE_PCCRR_H */ -- cgit v1.1