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