1 #ifndef _IPXE_PCCRR_H 2 #define _IPXE_PCCRR_H 3 4 /** @file 5 * 6 * Peer Content Caching and Retrieval: Retrieval Protocol [MS-PCCRR] 7 * 8 * All fields are in network byte order. 9 * 10 */ 11 12 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); 13 14 #include <stdint.h> 15 #include <ipxe/uaccess.h> 16 17 /** Magic retrieval URI path */ 18 #define PEERDIST_MAGIC_PATH "/116B50EB-ECE2-41ac-8429-9F9E963361B7/" 19 20 /** Retrieval protocol version */ 21 union peerdist_msg_version { 22 /** Raw version number */ 23 uint32_t raw; 24 /** Major:minor version number */ 25 struct { 26 /** Minor version number */ 27 uint16_t minor; 28 /** Major version number */ 29 uint16_t major; 30 } __attribute__ (( packed )); 31 } __attribute__ (( packed )); 32 33 /** Retrieval protocol version 1.0 */ 34 #define PEERDIST_MSG_VERSION_1_0 0x00000001UL 35 36 /** Retrieval protocol version 2.0 */ 37 #define PEERDIST_MSG_VERSION_2_0 0x00000002UL 38 39 /** Retrieval protocol supported versions */ 40 struct peerdist_msg_versions { 41 /** Minimum supported protocol version */ 42 union peerdist_msg_version min; 43 /** Maximum supported protocol version */ 44 union peerdist_msg_version max; 45 } __attribute__ (( packed )); 46 47 /** Retrieval protocol block range */ 48 struct peerdist_msg_range { 49 /** First block in range */ 50 uint32_t first; 51 /** Number of blocks in range */ 52 uint32_t count; 53 } __attribute__ (( packed )); 54 55 /** Retrieval protocol segment ID header */ 56 struct peerdist_msg_segment { 57 /** Digest size (i.e. length of segment ID) */ 58 uint32_t digestsize; 59 /* Followed by a single variable-length ID and padding: 60 * 61 * uint8_t id[digestsize]; 62 * uint8_t pad[ (-digestsize) & 0x3 ]; 63 */ 64 } __attribute__ (( packed )); 65 66 /** Retrieval protocol segment ID 67 * 68 * @v digestsize Digest size 69 */ 70 #define peerdist_msg_segment_t( digestsize ) \ 71 struct { \ 72 struct peerdist_msg_segment segment; \ 73 uint8_t id[digestsize]; \ 74 uint8_t pad[ ( -(digestsize) ) & 0x3 ]; \ 75 } __attribute__ (( packed )) 76 77 /** Retrieval protocol block range list header */ 78 struct peerdist_msg_ranges { 79 /** Number of ranges */ 80 uint32_t count; 81 /* Followed by an array of block ranges: 82 * 83 * struct peerdist_msg_range range[count]; 84 */ 85 } __attribute__ (( packed )); 86 87 /** Retrieval protocol block range list 88 * 89 * @v count Number of ranges 90 */ 91 #define peerdist_msg_ranges_t( count ) \ 92 struct { \ 93 struct peerdist_msg_ranges ranges; \ 94 struct peerdist_msg_range range[count]; \ 95 } __attribute__ (( packed )) 96 97 /** Retrieval protocol data block header */ 98 struct peerdist_msg_block { 99 /** Length of data block */ 100 uint32_t len; 101 /* Followed by the (encrypted) data block: 102 * 103 * uint8_t data[len]; 104 */ 105 } __attribute__ (( packed )); 106 107 /** Retrieval protocol data block */ 108 #define peerdist_msg_block_t( len ) \ 109 struct { \ 110 struct peerdist_msg_block block; \ 111 uint8_t data[len]; \ 112 } __attribute__ (( packed )) 113 114 /** Retrieval protocol initialisation vector header */ 115 struct peerdist_msg_iv { 116 /** Cipher block size */ 117 uint32_t blksize; 118 /* Followed by the initialisation vector: 119 * 120 * uint8_t data[blksize]; 121 */ 122 } __attribute__ (( packed )); 123 124 /** Retrieval protocol initialisation vector */ 125 #define peerdist_msg_iv_t( blksize ) \ 126 struct { \ 127 struct peerdist_msg_iv iv; \ 128 uint8_t data[blksize]; \ 129 } __attribute__ (( packed )) 130 131 /** Retrieval protocol useless VRF data header */ 132 struct peerdist_msg_useless_vrf { 133 /** Length of useless VRF data */ 134 uint32_t len; 135 /* Followed by a variable-length useless VRF data block and 136 * padding: 137 * 138 * uint8_t data[len]; 139 * uint8_t pad[ (-len) & 0x3 ]; 140 */ 141 } __attribute__ (( packed )); 142 143 /** Retrieval protocol useless VRF data */ 144 #define peerdist_msg_useless_vrf_t( vrf_len ) \ 145 struct { \ 146 struct peerdist_msg_useless_vrf vrf; \ 147 uint8_t data[vrf_len]; \ 148 uint8_t pad[ ( -(vrf_len) ) & 0x3 ]; \ 149 } __attribute__ (( packed )) 150 151 /** Retrieval protocol message header */ 152 struct peerdist_msg_header { 153 /** Protocol version 154 * 155 * This is the protocol version in which the message type was 156 * first defined. 157 */ 158 union peerdist_msg_version version; 159 /** Message type */ 160 uint32_t type; 161 /** Message size (including this header) */ 162 uint32_t len; 163 /** Cryptographic algorithm ID */ 164 uint32_t algorithm; 165 } __attribute__ (( packed )); 166 167 /** Retrieval protocol cryptographic algorithm IDs */ 168 enum peerdist_msg_algorithm { 169 /** No encryption */ 170 PEERDIST_MSG_PLAINTEXT = 0x00000000UL, 171 /** AES-128 in CBC mode */ 172 PEERDIST_MSG_AES_128_CBC = 0x00000001UL, 173 /** AES-192 in CBC mode */ 174 PEERDIST_MSG_AES_192_CBC = 0x00000002UL, 175 /** AES-256 in CBC mode */ 176 PEERDIST_MSG_AES_256_CBC = 0x00000003UL, 177 }; 178 179 /** Retrieval protocol transport response header */ 180 struct peerdist_msg_transport_header { 181 /** Length (excluding this header) 182 * 183 * This seems to be identical in both purpose and value to the 184 * length found within the message header, and therefore 185 * serves no useful purpose. 186 */ 187 uint32_t len; 188 } __attribute__ (( packed )); 189 190 /** Retrieval protocol negotiation request */ 191 struct peerdist_msg_nego_req { 192 /** Message header */ 193 struct peerdist_msg_header hdr; 194 /** Supported versions */ 195 struct peerdist_msg_versions versions; 196 } __attribute__ (( packed )); 197 198 /** Retrieval protocol negotiation request version */ 199 #define PEERDIST_MSG_NEGO_REQ_VERSION PEERDIST_MSG_VERSION_1_0 200 201 /** Retrieval protocol negotiation request type */ 202 #define PEERDIST_MSG_NEGO_REQ_TYPE 0x00000000UL 203 204 /** Retrieval protocol negotiation response */ 205 struct peerdist_msg_nego_resp { 206 /** Message header */ 207 struct peerdist_msg_header hdr; 208 /** Supported versions */ 209 struct peerdist_msg_versions versions; 210 } __attribute__ (( packed )); 211 212 /** Retrieval protocol negotiation response version */ 213 #define PEERDIST_MSG_NEGO_RESP_VERSION PEERDIST_MSG_VERSION_1_0 214 215 /** Retrieval protocol negotiation response type */ 216 #define PEERDIST_MSG_NEGO_RESP_TYPE 0x00000001UL 217 218 /** Retrieval protocol block list request header */ 219 struct peerdist_msg_getblklist { 220 /** Message header */ 221 struct peerdist_msg_header hdr; 222 /* Followed by a segment ID and a block range list: 223 * 224 * peerdist_msg_segment_t(digestsize) segment; 225 * peerdist_msg_ranges_t(count) ranges; 226 */ 227 } __attribute__ (( packed )); 228 229 /** Retrieval protocol block list request 230 * 231 * @v digestsize Digest size 232 * @v count Block range count 233 */ 234 #define peerdist_msg_getblklist_t( digestsize, count ) \ 235 struct { \ 236 struct peerdist_msg_getblklist getblklist; \ 237 peerdist_msg_segment_t ( digestsize ) segment; \ 238 peerdist_msg_ranges_t ( count ) ranges; \ 239 } __attribute__ (( packed )) 240 241 /** Retrieval protocol block list request version */ 242 #define PEERDIST_MSG_GETBLKLIST_VERSION PEERDIST_MSG_VERSION_1_0 243 244 /** Retrieval protocol block list request type */ 245 #define PEERDIST_MSG_GETBLKLIST_TYPE 0x00000002UL 246 247 /** Retrieval protocol block fetch request header */ 248 struct peerdist_msg_getblks { 249 /** Message header */ 250 struct peerdist_msg_header hdr; 251 /* Followed by a segment ID, a block range list, and a useless 252 * VRF block: 253 * 254 * peerdist_msg_segment_t(digestsize) segment; 255 * peerdist_msg_ranges_t(count) ranges; 256 * peerdist_msg_vrf_t(vrf_len) vrf; 257 */ 258 } __attribute__ (( packed )); 259 260 /** Retrieval protocol block fetch request 261 * 262 * @v digestsize Digest size 263 * @v count Block range count 264 * @v vrf_len Length of uselessness 265 */ 266 #define peerdist_msg_getblks_t( digestsize, count, vrf_len ) \ 267 struct { \ 268 struct peerdist_msg_getblks getblks; \ 269 peerdist_msg_segment_t ( digestsize ) segment; \ 270 peerdist_msg_ranges_t ( count ) ranges; \ 271 peerdist_msg_useless_vrf_t ( vrf_len ); \ 272 } __attribute__ (( packed )) 273 274 /** Retrieval protocol block fetch request version */ 275 #define PEERDIST_MSG_GETBLKS_VERSION PEERDIST_MSG_VERSION_1_0 276 277 /** Retrieval protocol block fetch request type */ 278 #define PEERDIST_MSG_GETBLKS_TYPE 0x00000003UL 279 280 /** Retrieval protocol block list response header */ 281 struct peerdist_msg_blklist { 282 /** Message header */ 283 struct peerdist_msg_header hdr; 284 /* Followed by a segment ID, a block range list, and a next 285 * block index: 286 * 287 * peerdist_msg_segment_t(digestsize) segment; 288 * peerdist_msg_ranges_t(count) ranges; 289 * uint32_t next; 290 */ 291 } __attribute__ (( packed )); 292 293 /** Retrieval protocol block list response 294 * 295 * @v digestsize Digest size 296 * @v count Block range count 297 */ 298 #define peerdist_msg_blklist_t( digestsize, count ) \ 299 struct { \ 300 struct peerdist_msg_blklist blklist; \ 301 peerdist_msg_segment_t ( digestsize ) segment; \ 302 peerdist_msg_ranges_t ( count ) ranges; \ 303 uint32_t next; \ 304 } __attribute__ (( packed )) 305 306 /** Retrieval protocol block list response version */ 307 #define PEERDIST_MSG_BLKLIST_VERSION PEERDIST_MSG_VERSION_1_0 308 309 /** Retrieval protocol block list response type */ 310 #define PEERDIST_MSG_BLKLIST_TYPE 0x00000004UL 311 312 /** Retrieval protocol block fetch response header */ 313 struct peerdist_msg_blk { 314 /** Message header */ 315 struct peerdist_msg_header hdr; 316 /* Followed by a segment ID, a block index, a next block 317 * index, a data block, a useless VRF block, and an 318 * initialisation vector: 319 * 320 * peerdist_msg_segment_t(digestsize) segment; 321 * uint32_t index; 322 * uint32_t next; 323 * peerdist_msg_block_t(len) data; 324 * peerdist_msg_useless_vrf_t(vrf_len) vrf; 325 * peerdist_msg_iv_t(blksize) iv; 326 */ 327 } __attribute__ (( packed )); 328 329 /** Retrieval protocol block fetch response 330 * 331 * @v digestsize Digest size 332 * @v len Data block length 333 * @v vrf_len Length of uselessness 334 * @v blksize Cipher block size 335 */ 336 #define peerdist_msg_blk_t( digestsize, len, vrf_len, blksize ) \ 337 struct { \ 338 struct peerdist_msg_blk blk; \ 339 peerdist_msg_segment_t ( digestsize ) segment; \ 340 uint32_t index; \ 341 uint32_t next; \ 342 peerdist_msg_block_t ( len ) block; \ 343 peerdist_msg_useless_vrf_t ( vrf_len ) vrf; \ 344 peerdist_msg_iv_t ( blksize ) iv; \ 345 } __attribute__ (( packed )) 346 347 /** Retrieval protocol block fetch response version */ 348 #define PEERDIST_MSG_BLK_VERSION PEERDIST_MSG_VERSION_1_0 349 350 /** Retrieval protocol block fetch response type */ 351 #define PEERDIST_MSG_BLK_TYPE 0x00000005UL 352 353 /** 354 * Parse retrieval protocol block fetch response 355 * 356 * @v raw Raw data 357 * @v raw_len Length of raw data 358 * @v digestsize Digest size 359 * @v blksize Cipher block size 360 * @v blk Structure to fill in 361 * @ret rc Return status code 362 */ 363 #define peerdist_msg_blk( raw, raw_len, digestsize, blksize, blk ) ( { \ 364 assert ( sizeof ( (blk)->segment.id ) == (digestsize) ); \ 365 assert ( sizeof ( (blk)->block.data ) == 0 ); \ 366 assert ( sizeof ( (blk)->vrf.data ) == 0 ); \ 367 assert ( sizeof ( (blk)->iv.data ) == blksize ); \ 368 peerdist_msg_blk_untyped ( (raw), (raw_len), (digestsize), \ 369 (blksize), blk ); \ 370 } ) 371 372 extern int peerdist_msg_blk_untyped ( userptr_t raw, size_t raw_len, 373 size_t digestsize, size_t blksize, 374 void *out ); 375 376 #endif /* _IPXE_PCCRR_H */ 377