]>
Commit | Line | Data |
---|---|---|
7e729bb5 | 1 | /* |
846e33c7 | 2 | * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. |
7e729bb5 | 3 | * |
846e33c7 RS |
4 | * Licensed under the OpenSSL license (the "License"). You may not use |
5 | * this file except in compliance with the License. You can obtain a copy | |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
7e729bb5 MC |
8 | */ |
9 | ||
10 | #ifndef HEADER_PACKET_LOCL_H | |
11 | # define HEADER_PACKET_LOCL_H | |
12 | ||
13 | # include <string.h> | |
14 | # include <openssl/bn.h> | |
15 | # include <openssl/buffer.h> | |
31011544 | 16 | # include <openssl/crypto.h> |
80e0ecbf | 17 | # include <openssl/e_os2.h> |
7e729bb5 | 18 | |
1de1d768 RL |
19 | # include "internal/numbers.h" |
20 | ||
7e729bb5 MC |
21 | # ifdef __cplusplus |
22 | extern "C" { | |
23 | # endif | |
24 | ||
25 | typedef struct { | |
7e729bb5 | 26 | /* Pointer to where we are currently reading from */ |
b6981744 | 27 | const unsigned char *curr; |
6a12a574 EK |
28 | /* Number of bytes remaining */ |
29 | size_t remaining; | |
7e729bb5 MC |
30 | } PACKET; |
31 | ||
6a12a574 | 32 | /* Internal unchecked shorthand; don't use outside this file. */ |
80e0ecbf | 33 | static ossl_inline void packet_forward(PACKET *pkt, size_t len) |
6a12a574 EK |
34 | { |
35 | pkt->curr += len; | |
36 | pkt->remaining -= len; | |
37 | } | |
38 | ||
7e729bb5 | 39 | /* |
bc6616a4 | 40 | * Returns the number of bytes remaining to be read in the PACKET |
7e729bb5 | 41 | */ |
80e0ecbf | 42 | static ossl_inline size_t PACKET_remaining(const PACKET *pkt) |
7e729bb5 | 43 | { |
6a12a574 | 44 | return pkt->remaining; |
7e729bb5 MC |
45 | } |
46 | ||
06217867 EK |
47 | /* |
48 | * Returns a pointer to the first byte after the packet data. | |
49 | * Useful for integrating with non-PACKET parsing code. | |
50 | * Specifically, we use PACKET_end() to verify that a d2i_... call | |
51 | * has consumed the entire packet contents. | |
52 | */ | |
53 | static ossl_inline const unsigned char *PACKET_end(const PACKET *pkt) | |
54 | { | |
55 | return pkt->curr + pkt->remaining; | |
56 | } | |
a230b26e | 57 | |
ec30e856 EK |
58 | /* |
59 | * Returns a pointer to the PACKET's current position. | |
60 | * For use in non-PACKETized APIs. | |
ec30e856 | 61 | */ |
b6981744 | 62 | static ossl_inline const unsigned char *PACKET_data(const PACKET *pkt) |
ec30e856 EK |
63 | { |
64 | return pkt->curr; | |
65 | } | |
66 | ||
7e729bb5 MC |
67 | /* |
68 | * Initialise a PACKET with |len| bytes held in |buf|. This does not make a | |
69 | * copy of the data so |buf| must be present for the whole time that the PACKET | |
70 | * is being used. | |
71 | */ | |
b6981744 EK |
72 | __owur static ossl_inline int PACKET_buf_init(PACKET *pkt, |
73 | const unsigned char *buf, | |
80e0ecbf | 74 | size_t len) |
7e729bb5 | 75 | { |
6a12a574 | 76 | /* Sanity check for negative values. */ |
3fde6c92 | 77 | if (len > (size_t)(SIZE_MAX / 2)) |
7e729bb5 | 78 | return 0; |
7e729bb5 | 79 | |
6a12a574 EK |
80 | pkt->curr = buf; |
81 | pkt->remaining = len; | |
7e729bb5 MC |
82 | return 1; |
83 | } | |
84 | ||
b3e2272c | 85 | /* Initialize a PACKET to hold zero bytes. */ |
80e0ecbf | 86 | static ossl_inline void PACKET_null_init(PACKET *pkt) |
b3e2272c EK |
87 | { |
88 | pkt->curr = NULL; | |
89 | pkt->remaining = 0; | |
90 | } | |
91 | ||
31011544 EK |
92 | /* |
93 | * Returns 1 if the packet has length |num| and its contents equal the |num| | |
94 | * bytes read from |ptr|. Returns 0 otherwise (lengths or contents not equal). | |
95 | * If lengths are equal, performs the comparison in constant time. | |
96 | */ | |
80e0ecbf DSH |
97 | __owur static ossl_inline int PACKET_equal(const PACKET *pkt, const void *ptr, |
98 | size_t num) | |
99 | { | |
31011544 EK |
100 | if (PACKET_remaining(pkt) != num) |
101 | return 0; | |
102 | return CRYPTO_memcmp(pkt->curr, ptr, num) == 0; | |
103 | } | |
104 | ||
7e729bb5 MC |
105 | /* |
106 | * Peek ahead and initialize |subpkt| with the next |len| bytes read from |pkt|. | |
107 | * Data is not copied: the |subpkt| packet will share its underlying buffer with | |
108 | * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|. | |
109 | */ | |
80e0ecbf | 110 | __owur static ossl_inline int PACKET_peek_sub_packet(const PACKET *pkt, |
a230b26e | 111 | PACKET *subpkt, size_t len) |
7e729bb5 MC |
112 | { |
113 | if (PACKET_remaining(pkt) < len) | |
114 | return 0; | |
115 | ||
f4f78ff7 | 116 | return PACKET_buf_init(subpkt, pkt->curr, len); |
7e729bb5 MC |
117 | } |
118 | ||
119 | /* | |
120 | * Initialize |subpkt| with the next |len| bytes read from |pkt|. Data is not | |
121 | * copied: the |subpkt| packet will share its underlying buffer with the | |
122 | * original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|. | |
123 | */ | |
80e0ecbf | 124 | __owur static ossl_inline int PACKET_get_sub_packet(PACKET *pkt, |
a230b26e | 125 | PACKET *subpkt, size_t len) |
7e729bb5 MC |
126 | { |
127 | if (!PACKET_peek_sub_packet(pkt, subpkt, len)) | |
128 | return 0; | |
129 | ||
6a12a574 | 130 | packet_forward(pkt, len); |
7e729bb5 MC |
131 | |
132 | return 1; | |
133 | } | |
134 | ||
80e0ecbf DSH |
135 | /* |
136 | * Peek ahead at 2 bytes in network order from |pkt| and store the value in | |
7e729bb5 MC |
137 | * |*data| |
138 | */ | |
80e0ecbf DSH |
139 | __owur static ossl_inline int PACKET_peek_net_2(const PACKET *pkt, |
140 | unsigned int *data) | |
7e729bb5 MC |
141 | { |
142 | if (PACKET_remaining(pkt) < 2) | |
143 | return 0; | |
144 | ||
80e0ecbf | 145 | *data = ((unsigned int)(*pkt->curr)) << 8; |
7e729bb5 MC |
146 | *data |= *(pkt->curr + 1); |
147 | ||
148 | return 1; | |
149 | } | |
150 | ||
151 | /* Equivalent of n2s */ | |
152 | /* Get 2 bytes in network order from |pkt| and store the value in |*data| */ | |
a230b26e | 153 | __owur static ossl_inline int PACKET_get_net_2(PACKET *pkt, unsigned int *data) |
7e729bb5 MC |
154 | { |
155 | if (!PACKET_peek_net_2(pkt, data)) | |
156 | return 0; | |
157 | ||
6a12a574 | 158 | packet_forward(pkt, 2); |
7e729bb5 MC |
159 | |
160 | return 1; | |
161 | } | |
162 | ||
80e0ecbf DSH |
163 | /* |
164 | * Peek ahead at 3 bytes in network order from |pkt| and store the value in | |
7e729bb5 MC |
165 | * |*data| |
166 | */ | |
80e0ecbf DSH |
167 | __owur static ossl_inline int PACKET_peek_net_3(const PACKET *pkt, |
168 | unsigned long *data) | |
7e729bb5 MC |
169 | { |
170 | if (PACKET_remaining(pkt) < 3) | |
171 | return 0; | |
172 | ||
80e0ecbf DSH |
173 | *data = ((unsigned long)(*pkt->curr)) << 16; |
174 | *data |= ((unsigned long)(*(pkt->curr + 1))) << 8; | |
44128847 | 175 | *data |= *(pkt->curr + 2); |
7e729bb5 MC |
176 | |
177 | return 1; | |
178 | } | |
179 | ||
180 | /* Equivalent of n2l3 */ | |
181 | /* Get 3 bytes in network order from |pkt| and store the value in |*data| */ | |
a230b26e | 182 | __owur static ossl_inline int PACKET_get_net_3(PACKET *pkt, unsigned long *data) |
7e729bb5 MC |
183 | { |
184 | if (!PACKET_peek_net_3(pkt, data)) | |
185 | return 0; | |
186 | ||
6a12a574 | 187 | packet_forward(pkt, 3); |
7e729bb5 MC |
188 | |
189 | return 1; | |
190 | } | |
191 | ||
80e0ecbf DSH |
192 | /* |
193 | * Peek ahead at 4 bytes in network order from |pkt| and store the value in | |
7e729bb5 MC |
194 | * |*data| |
195 | */ | |
80e0ecbf DSH |
196 | __owur static ossl_inline int PACKET_peek_net_4(const PACKET *pkt, |
197 | unsigned long *data) | |
7e729bb5 MC |
198 | { |
199 | if (PACKET_remaining(pkt) < 4) | |
200 | return 0; | |
201 | ||
80e0ecbf | 202 | *data = ((unsigned long)(*pkt->curr)) << 24; |
44128847 | 203 | *data |= ((unsigned long)(*(pkt->curr + 1))) << 16; |
80e0ecbf DSH |
204 | *data |= ((unsigned long)(*(pkt->curr + 2))) << 8; |
205 | *data |= *(pkt->curr + 3); | |
7e729bb5 MC |
206 | |
207 | return 1; | |
208 | } | |
209 | ||
210 | /* Equivalent of n2l */ | |
211 | /* Get 4 bytes in network order from |pkt| and store the value in |*data| */ | |
a230b26e | 212 | __owur static ossl_inline int PACKET_get_net_4(PACKET *pkt, unsigned long *data) |
7e729bb5 MC |
213 | { |
214 | if (!PACKET_peek_net_4(pkt, data)) | |
215 | return 0; | |
216 | ||
6a12a574 | 217 | packet_forward(pkt, 4); |
7e729bb5 MC |
218 | |
219 | return 1; | |
220 | } | |
221 | ||
222 | /* Peek ahead at 1 byte from |pkt| and store the value in |*data| */ | |
80e0ecbf DSH |
223 | __owur static ossl_inline int PACKET_peek_1(const PACKET *pkt, |
224 | unsigned int *data) | |
7e729bb5 MC |
225 | { |
226 | if (!PACKET_remaining(pkt)) | |
227 | return 0; | |
228 | ||
229 | *data = *pkt->curr; | |
230 | ||
231 | return 1; | |
232 | } | |
233 | ||
234 | /* Get 1 byte from |pkt| and store the value in |*data| */ | |
80e0ecbf | 235 | __owur static ossl_inline int PACKET_get_1(PACKET *pkt, unsigned int *data) |
7e729bb5 MC |
236 | { |
237 | if (!PACKET_peek_1(pkt, data)) | |
238 | return 0; | |
239 | ||
6a12a574 | 240 | packet_forward(pkt, 1); |
7e729bb5 MC |
241 | |
242 | return 1; | |
243 | } | |
244 | ||
245 | /* | |
246 | * Peek ahead at 4 bytes in reverse network order from |pkt| and store the value | |
247 | * in |*data| | |
248 | */ | |
80e0ecbf DSH |
249 | __owur static ossl_inline int PACKET_peek_4(const PACKET *pkt, |
250 | unsigned long *data) | |
7e729bb5 MC |
251 | { |
252 | if (PACKET_remaining(pkt) < 4) | |
253 | return 0; | |
254 | ||
80e0ecbf DSH |
255 | *data = *pkt->curr; |
256 | *data |= ((unsigned long)(*(pkt->curr + 1))) << 8; | |
44128847 MC |
257 | *data |= ((unsigned long)(*(pkt->curr + 2))) << 16; |
258 | *data |= ((unsigned long)(*(pkt->curr + 3))) << 24; | |
7e729bb5 MC |
259 | |
260 | return 1; | |
261 | } | |
262 | ||
263 | /* Equivalent of c2l */ | |
264 | /* | |
265 | * Get 4 bytes in reverse network order from |pkt| and store the value in | |
266 | * |*data| | |
267 | */ | |
80e0ecbf | 268 | __owur static ossl_inline int PACKET_get_4(PACKET *pkt, unsigned long *data) |
7e729bb5 MC |
269 | { |
270 | if (!PACKET_peek_4(pkt, data)) | |
271 | return 0; | |
272 | ||
6a12a574 | 273 | packet_forward(pkt, 4); |
7e729bb5 MC |
274 | |
275 | return 1; | |
276 | } | |
277 | ||
278 | /* | |
279 | * Peek ahead at |len| bytes from the |pkt| and store a pointer to them in | |
280 | * |*data|. This just points at the underlying buffer that |pkt| is using. The | |
281 | * caller should not free this data directly (it will be freed when the | |
282 | * underlying buffer gets freed | |
283 | */ | |
80e0ecbf | 284 | __owur static ossl_inline int PACKET_peek_bytes(const PACKET *pkt, |
b6981744 | 285 | const unsigned char **data, |
80e0ecbf | 286 | size_t len) |
7e729bb5 MC |
287 | { |
288 | if (PACKET_remaining(pkt) < len) | |
289 | return 0; | |
290 | ||
291 | *data = pkt->curr; | |
292 | ||
293 | return 1; | |
294 | } | |
295 | ||
296 | /* | |
297 | * Read |len| bytes from the |pkt| and store a pointer to them in |*data|. This | |
298 | * just points at the underlying buffer that |pkt| is using. The caller should | |
299 | * not free this data directly (it will be freed when the underlying buffer gets | |
300 | * freed | |
301 | */ | |
80e0ecbf | 302 | __owur static ossl_inline int PACKET_get_bytes(PACKET *pkt, |
b6981744 | 303 | const unsigned char **data, |
80e0ecbf | 304 | size_t len) |
7e729bb5 MC |
305 | { |
306 | if (!PACKET_peek_bytes(pkt, data, len)) | |
307 | return 0; | |
308 | ||
6a12a574 | 309 | packet_forward(pkt, len); |
7e729bb5 MC |
310 | |
311 | return 1; | |
312 | } | |
313 | ||
314 | /* Peek ahead at |len| bytes from |pkt| and copy them to |data| */ | |
80e0ecbf DSH |
315 | __owur static ossl_inline int PACKET_peek_copy_bytes(const PACKET *pkt, |
316 | unsigned char *data, | |
317 | size_t len) | |
7e729bb5 MC |
318 | { |
319 | if (PACKET_remaining(pkt) < len) | |
320 | return 0; | |
321 | ||
322 | memcpy(data, pkt->curr, len); | |
323 | ||
324 | return 1; | |
325 | } | |
326 | ||
6d41fc80 EK |
327 | /* |
328 | * Read |len| bytes from |pkt| and copy them to |data|. | |
329 | * The caller is responsible for ensuring that |data| can hold |len| bytes. | |
330 | */ | |
80e0ecbf | 331 | __owur static ossl_inline int PACKET_copy_bytes(PACKET *pkt, |
a230b26e | 332 | unsigned char *data, size_t len) |
7e729bb5 MC |
333 | { |
334 | if (!PACKET_peek_copy_bytes(pkt, data, len)) | |
335 | return 0; | |
336 | ||
6a12a574 | 337 | packet_forward(pkt, len); |
7e729bb5 MC |
338 | |
339 | return 1; | |
340 | } | |
341 | ||
67202973 EK |
342 | /* |
343 | * Copy packet data to |dest|, and set |len| to the number of copied bytes. | |
344 | * If the packet has more than |dest_len| bytes, nothing is copied. | |
345 | * Returns 1 if the packet data fits in |dest_len| bytes, 0 otherwise. | |
346 | * Does not forward PACKET position (because it is typically the last thing | |
347 | * done with a given PACKET). | |
348 | */ | |
80e0ecbf DSH |
349 | __owur static ossl_inline int PACKET_copy_all(const PACKET *pkt, |
350 | unsigned char *dest, | |
351 | size_t dest_len, size_t *len) | |
352 | { | |
67202973 EK |
353 | if (PACKET_remaining(pkt) > dest_len) { |
354 | *len = 0; | |
355 | return 0; | |
356 | } | |
357 | *len = pkt->remaining; | |
358 | memcpy(dest, pkt->curr, pkt->remaining); | |
359 | return 1; | |
360 | } | |
361 | ||
6d41fc80 EK |
362 | /* |
363 | * Copy |pkt| bytes to a newly allocated buffer and store a pointer to the | |
364 | * result in |*data|, and the length in |len|. | |
365 | * If |*data| is not NULL, the old data is OPENSSL_free'd. | |
366 | * If the packet is empty, or malloc fails, |*data| will be set to NULL. | |
367 | * Returns 1 if the malloc succeeds and 0 otherwise. | |
368 | * Does not forward PACKET position (because it is typically the last thing | |
369 | * done with a given PACKET). | |
370 | */ | |
80e0ecbf DSH |
371 | __owur static ossl_inline int PACKET_memdup(const PACKET *pkt, |
372 | unsigned char **data, size_t *len) | |
6d41fc80 EK |
373 | { |
374 | size_t length; | |
375 | ||
376 | OPENSSL_free(*data); | |
377 | *data = NULL; | |
378 | *len = 0; | |
379 | ||
380 | length = PACKET_remaining(pkt); | |
381 | ||
382 | if (length == 0) | |
383 | return 1; | |
384 | ||
7644a9ae | 385 | *data = OPENSSL_memdup(pkt->curr, length); |
6d41fc80 EK |
386 | if (*data == NULL) |
387 | return 0; | |
388 | ||
389 | *len = length; | |
390 | return 1; | |
391 | } | |
392 | ||
393 | /* | |
394 | * Read a C string from |pkt| and copy to a newly allocated, NUL-terminated | |
395 | * buffer. Store a pointer to the result in |*data|. | |
396 | * If |*data| is not NULL, the old data is OPENSSL_free'd. | |
397 | * If the data in |pkt| does not contain a NUL-byte, the entire data is | |
398 | * copied and NUL-terminated. | |
399 | * Returns 1 if the malloc succeeds and 0 otherwise. | |
400 | * Does not forward PACKET position (because it is typically the last thing done | |
401 | * with a given PACKET). | |
402 | */ | |
80e0ecbf | 403 | __owur static ossl_inline int PACKET_strndup(const PACKET *pkt, char **data) |
6d41fc80 EK |
404 | { |
405 | OPENSSL_free(*data); | |
32942870 EK |
406 | |
407 | /* This will succeed on an empty packet, unless pkt->curr == NULL. */ | |
80e0ecbf | 408 | *data = OPENSSL_strndup((const char *)pkt->curr, PACKET_remaining(pkt)); |
6d41fc80 EK |
409 | return (*data != NULL); |
410 | } | |
411 | ||
06217867 EK |
412 | /* Returns 1 if |pkt| contains at least one 0-byte, 0 otherwise. */ |
413 | static ossl_inline int PACKET_contains_zero_byte(const PACKET *pkt) | |
414 | { | |
a230b26e | 415 | return memchr(pkt->curr, 0, pkt->remaining) != NULL; |
06217867 EK |
416 | } |
417 | ||
7e729bb5 | 418 | /* Move the current reading position forward |len| bytes */ |
80e0ecbf | 419 | __owur static ossl_inline int PACKET_forward(PACKET *pkt, size_t len) |
7e729bb5 MC |
420 | { |
421 | if (PACKET_remaining(pkt) < len) | |
422 | return 0; | |
423 | ||
6a12a574 | 424 | packet_forward(pkt, len); |
7e729bb5 MC |
425 | |
426 | return 1; | |
427 | } | |
428 | ||
ec30e856 EK |
429 | /* |
430 | * Reads a variable-length vector prefixed with a one-byte length, and stores | |
431 | * the contents in |subpkt|. |pkt| can equal |subpkt|. | |
432 | * Data is not copied: the |subpkt| packet will share its underlying buffer with | |
433 | * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|. | |
434 | * Upon failure, the original |pkt| and |subpkt| are not modified. | |
435 | */ | |
80e0ecbf DSH |
436 | __owur static ossl_inline int PACKET_get_length_prefixed_1(PACKET *pkt, |
437 | PACKET *subpkt) | |
ec30e856 | 438 | { |
80e0ecbf | 439 | unsigned int length; |
b6981744 | 440 | const unsigned char *data; |
80e0ecbf DSH |
441 | PACKET tmp = *pkt; |
442 | if (!PACKET_get_1(&tmp, &length) || | |
443 | !PACKET_get_bytes(&tmp, &data, (size_t)length)) { | |
444 | return 0; | |
445 | } | |
446 | ||
447 | *pkt = tmp; | |
448 | subpkt->curr = data; | |
449 | subpkt->remaining = length; | |
450 | ||
451 | return 1; | |
ec30e856 EK |
452 | } |
453 | ||
06217867 EK |
454 | /* |
455 | * Like PACKET_get_length_prefixed_1, but additionally, fails when there are | |
456 | * leftover bytes in |pkt|. | |
457 | */ | |
a230b26e EK |
458 | __owur static ossl_inline int PACKET_as_length_prefixed_1(PACKET *pkt, |
459 | PACKET *subpkt) | |
06217867 | 460 | { |
a230b26e EK |
461 | unsigned int length; |
462 | const unsigned char *data; | |
463 | PACKET tmp = *pkt; | |
464 | if (!PACKET_get_1(&tmp, &length) || | |
465 | !PACKET_get_bytes(&tmp, &data, (size_t)length) || | |
466 | PACKET_remaining(&tmp) != 0) { | |
467 | return 0; | |
468 | } | |
06217867 | 469 | |
a230b26e EK |
470 | *pkt = tmp; |
471 | subpkt->curr = data; | |
472 | subpkt->remaining = length; | |
06217867 | 473 | |
a230b26e | 474 | return 1; |
06217867 EK |
475 | } |
476 | ||
ec30e856 EK |
477 | /* |
478 | * Reads a variable-length vector prefixed with a two-byte length, and stores | |
479 | * the contents in |subpkt|. |pkt| can equal |subpkt|. | |
480 | * Data is not copied: the |subpkt| packet will share its underlying buffer with | |
481 | * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|. | |
482 | * Upon failure, the original |pkt| and |subpkt| are not modified. | |
483 | */ | |
80e0ecbf DSH |
484 | __owur static ossl_inline int PACKET_get_length_prefixed_2(PACKET *pkt, |
485 | PACKET *subpkt) | |
ec30e856 | 486 | { |
80e0ecbf | 487 | unsigned int length; |
b6981744 | 488 | const unsigned char *data; |
80e0ecbf | 489 | PACKET tmp = *pkt; |
06217867 | 490 | |
80e0ecbf DSH |
491 | if (!PACKET_get_net_2(&tmp, &length) || |
492 | !PACKET_get_bytes(&tmp, &data, (size_t)length)) { | |
493 | return 0; | |
494 | } | |
495 | ||
496 | *pkt = tmp; | |
497 | subpkt->curr = data; | |
498 | subpkt->remaining = length; | |
499 | ||
500 | return 1; | |
ec30e856 EK |
501 | } |
502 | ||
06217867 EK |
503 | /* |
504 | * Like PACKET_get_length_prefixed_2, but additionally, fails when there are | |
505 | * leftover bytes in |pkt|. | |
506 | */ | |
507 | __owur static ossl_inline int PACKET_as_length_prefixed_2(PACKET *pkt, | |
508 | PACKET *subpkt) | |
509 | { | |
a230b26e EK |
510 | unsigned int length; |
511 | const unsigned char *data; | |
512 | PACKET tmp = *pkt; | |
06217867 | 513 | |
a230b26e EK |
514 | if (!PACKET_get_net_2(&tmp, &length) || |
515 | !PACKET_get_bytes(&tmp, &data, (size_t)length) || | |
516 | PACKET_remaining(&tmp) != 0) { | |
517 | return 0; | |
518 | } | |
06217867 | 519 | |
a230b26e EK |
520 | *pkt = tmp; |
521 | subpkt->curr = data; | |
522 | subpkt->remaining = length; | |
06217867 | 523 | |
a230b26e | 524 | return 1; |
06217867 EK |
525 | } |
526 | ||
ec30e856 EK |
527 | /* |
528 | * Reads a variable-length vector prefixed with a three-byte length, and stores | |
529 | * the contents in |subpkt|. |pkt| can equal |subpkt|. | |
530 | * Data is not copied: the |subpkt| packet will share its underlying buffer with | |
531 | * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|. | |
532 | * Upon failure, the original |pkt| and |subpkt| are not modified. | |
533 | */ | |
80e0ecbf DSH |
534 | __owur static ossl_inline int PACKET_get_length_prefixed_3(PACKET *pkt, |
535 | PACKET *subpkt) | |
ec30e856 | 536 | { |
80e0ecbf | 537 | unsigned long length; |
b6981744 | 538 | const unsigned char *data; |
80e0ecbf DSH |
539 | PACKET tmp = *pkt; |
540 | if (!PACKET_get_net_3(&tmp, &length) || | |
541 | !PACKET_get_bytes(&tmp, &data, (size_t)length)) { | |
542 | return 0; | |
543 | } | |
544 | ||
545 | *pkt = tmp; | |
546 | subpkt->curr = data; | |
547 | subpkt->remaining = length; | |
548 | ||
549 | return 1; | |
ec30e856 | 550 | } |
b7273855 MC |
551 | |
552 | /* Writeable packets */ | |
553 | ||
0217dd19 MC |
554 | typedef struct wpacket_sub WPACKET_SUB; |
555 | struct wpacket_sub { | |
556 | /* The parent WPACKET_SUB if we have one or NULL otherwise */ | |
557 | WPACKET_SUB *parent; | |
558 | ||
559 | /* | |
de451856 MC |
560 | * Offset into the buffer where the length of this WPACKET goes. We use an |
561 | * offset in case the buffer grows and gets reallocated. | |
0217dd19 | 562 | */ |
de451856 | 563 | size_t packet_len; |
0217dd19 | 564 | |
de451856 | 565 | /* Number of bytes in the packet_len or 0 if we don't write the length */ |
0217dd19 MC |
566 | size_t lenbytes; |
567 | ||
568 | /* Number of bytes written to the buf prior to this packet starting */ | |
569 | size_t pwritten; | |
570 | ||
571 | /* Flags for this sub-packet */ | |
572 | unsigned int flags; | |
573 | }; | |
574 | ||
575 | typedef struct wpacket_st WPACKET; | |
576 | struct wpacket_st { | |
b7273855 MC |
577 | /* The buffer where we store the output data */ |
578 | BUF_MEM *buf; | |
579 | ||
de451856 MC |
580 | /* |
581 | * Offset into the buffer where we are currently writing. We use an offset | |
582 | * in case the buffer grows and gets reallocated. | |
583 | */ | |
584 | size_t curr; | |
b7273855 MC |
585 | |
586 | /* Number of bytes written so far */ | |
587 | size_t written; | |
588 | ||
9bf85bf9 | 589 | /* Maximum number of bytes we will allow to be written to this WPACKET */ |
b7273855 | 590 | size_t maxsize; |
b7273855 | 591 | |
9bf85bf9 | 592 | /* Our sub-packets (always at least one if not finished) */ |
0217dd19 | 593 | WPACKET_SUB *subs; |
b7273855 MC |
594 | }; |
595 | ||
596 | /* Flags */ | |
9bf85bf9 MC |
597 | |
598 | /* Default */ | |
de451856 | 599 | #define WPACKET_FLAGS_NONE 0 |
9bf85bf9 | 600 | |
ae2f7b37 | 601 | /* Error on WPACKET_close() if no data written to the WPACKET */ |
de451856 | 602 | #define WPACKET_FLAGS_NON_ZERO_LENGTH 1 |
9bf85bf9 | 603 | |
b7273855 | 604 | /* |
ae2f7b37 | 605 | * Abandon all changes on WPACKET_close() if no data written to the WPACKET, |
b7273855 MC |
606 | * i.e. this does not write out a zero packet length |
607 | */ | |
de451856 | 608 | #define WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH 2 |
b7273855 | 609 | |
9bf85bf9 MC |
610 | |
611 | /* | |
612 | * Initialise a WPACKET with the buffer in |buf|. The buffer must exist | |
613 | * for the whole time that the WPACKET is being used. Additionally |lenbytes| of | |
614 | * data is preallocated at the start of the buffer to store the length of the | |
615 | * WPACKET once we know it. | |
616 | */ | |
ae2f7b37 | 617 | int WPACKET_init_len(WPACKET *pkt, BUF_MEM *buf, size_t lenbytes); |
9bf85bf9 MC |
618 | |
619 | /* | |
620 | * Same as WPACKET_init_len except there is no preallocation of the WPACKET | |
621 | * length. | |
622 | */ | |
ae2f7b37 | 623 | int WPACKET_init(WPACKET *pkt, BUF_MEM *buf); |
9bf85bf9 MC |
624 | |
625 | /* | |
626 | * Set the flags to be applied to the current sub-packet | |
627 | */ | |
ae2f7b37 | 628 | int WPACKET_set_flags(WPACKET *pkt, unsigned int flags); |
9bf85bf9 | 629 | |
9bf85bf9 MC |
630 | /* |
631 | * Closes the most recent sub-packet. It also writes out the length of the | |
632 | * packet to the required location (normally the start of the WPACKET) if | |
633 | * appropriate. The top level WPACKET should be closed using WPACKET_finish() | |
634 | * instead of this function. | |
635 | */ | |
ae2f7b37 | 636 | int WPACKET_close(WPACKET *pkt); |
9bf85bf9 MC |
637 | |
638 | /* | |
639 | * The same as WPACKET_close() but only for the top most WPACKET. Additionally | |
640 | * frees memory resources for this WPACKET. | |
641 | */ | |
0217dd19 | 642 | int WPACKET_finish(WPACKET *pkt); |
9bf85bf9 MC |
643 | |
644 | /* | |
645 | * Initialise a new sub-packet. Additionally |lenbytes| of data is preallocated | |
869d0a37 MC |
646 | * at the start of the sub-packet to store its length once we know it. Don't |
647 | * call this directly. Use the convenience macros below instead. | |
9bf85bf9 | 648 | */ |
869d0a37 | 649 | int WPACKET_start_sub_packet_len__(WPACKET *pkt, size_t lenbytes); |
9bf85bf9 | 650 | |
de451856 MC |
651 | /* |
652 | * Convenience macros for calling WPACKET_start_sub_packet_len with different | |
653 | * lengths | |
654 | */ | |
655 | #define WPACKET_start_sub_packet_u8(pkt) \ | |
869d0a37 | 656 | WPACKET_start_sub_packet_len__((pkt), 1) |
de451856 | 657 | #define WPACKET_start_sub_packet_u16(pkt) \ |
869d0a37 | 658 | WPACKET_start_sub_packet_len__((pkt), 2) |
de451856 | 659 | #define WPACKET_start_sub_packet_u24(pkt) \ |
869d0a37 | 660 | WPACKET_start_sub_packet_len__((pkt), 3) |
de451856 | 661 | #define WPACKET_start_sub_packet_u32(pkt) \ |
869d0a37 | 662 | WPACKET_start_sub_packet_len__((pkt), 4) |
de451856 | 663 | |
9bf85bf9 | 664 | /* |
869d0a37 MC |
665 | * Same as WPACKET_start_sub_packet_len__() except no bytes are pre-allocated |
666 | * for the sub-packet length. | |
9bf85bf9 | 667 | */ |
0217dd19 | 668 | int WPACKET_start_sub_packet(WPACKET *pkt); |
9bf85bf9 MC |
669 | |
670 | /* | |
671 | * Allocate bytes in the WPACKET for the output. This reserves the bytes | |
672 | * and counts them as "written", but doesn't actually do the writing. A pointer | |
673 | * to the allocated bytes is stored in |*allocbytes|. | |
4b0fc9fc MC |
674 | * WARNING: the allocated bytes must be filled in immediately, without further |
675 | * WPACKET_* calls. If not then the underlying buffer may be realloc'd and | |
676 | * change its location. | |
9bf85bf9 | 677 | */ |
ae2f7b37 | 678 | int WPACKET_allocate_bytes(WPACKET *pkt, size_t bytes, |
b7273855 | 679 | unsigned char **allocbytes); |
9bf85bf9 | 680 | |
b2b3024e MC |
681 | /* |
682 | * The same as WPACKET_allocate_bytes() except additionally a new sub-packet is | |
683 | * started for the allocated bytes, and then closed immediately afterwards. The | |
869d0a37 MC |
684 | * number of length bytes for the sub-packet is in |lenbytes|. Don't call this |
685 | * directly. Use the convenience macros below instead. | |
b2b3024e | 686 | */ |
869d0a37 MC |
687 | int WPACKET_sub_allocate_bytes__(WPACKET *pkt, size_t len, |
688 | unsigned char **allocbytes, size_t lenbytes); | |
b2b3024e MC |
689 | |
690 | /* | |
691 | * Convenience macros for calling WPACKET_sub_allocate_bytes with different | |
692 | * lengths | |
693 | */ | |
694 | #define WPACKET_sub_allocate_bytes_u8(pkt, len, bytes) \ | |
869d0a37 | 695 | WPACKET_sub_allocate_bytes__((pkt), (len), (bytes), 1) |
b2b3024e | 696 | #define WPACKET_sub_allocate_bytes_u16(pkt, len, bytes) \ |
869d0a37 | 697 | WPACKET_sub_allocate_bytes__((pkt), (len), (bytes), 2) |
b2b3024e | 698 | #define WPACKET_sub_allocate_bytes_u24(pkt, len, bytes) \ |
869d0a37 | 699 | WPACKET_sub_allocate_bytes__((pkt), (len), (bytes), 3) |
b2b3024e | 700 | #define WPACKET_sub_allocate_bytes_u32(pkt, len, bytes) \ |
869d0a37 | 701 | WPACKET_sub_allocate_bytes__((pkt), (len), (bytes), 4) |
b2b3024e | 702 | |
9bf85bf9 MC |
703 | /* |
704 | * Write the value stored in |val| into the WPACKET. The value will consume | |
705 | * |bytes| amount of storage. An error will occur if |val| cannot be | |
706 | * accommodated in |bytes| storage, e.g. attempting to write the value 256 into | |
08029dfa MC |
707 | * 1 byte will fail. Don't call this directly. Use the convenience macros below |
708 | * instead. | |
9bf85bf9 | 709 | */ |
08029dfa MC |
710 | int WPACKET_put_bytes__(WPACKET *pkt, unsigned int val, size_t bytes); |
711 | ||
712 | /* | |
713 | * Convenience macros for calling WPACKET_put_bytes with different | |
714 | * lengths | |
715 | */ | |
716 | #define WPACKET_put_bytes_u8(pkt, val) \ | |
717 | WPACKET_put_bytes__((pkt), (val), 1) | |
718 | #define WPACKET_put_bytes_u16(pkt, val) \ | |
719 | WPACKET_put_bytes__((pkt), (val), 2) | |
720 | #define WPACKET_put_bytes_u24(pkt, val) \ | |
4b0fc9fc | 721 | WPACKET_put_bytes__((pkt), (val), 3) |
08029dfa MC |
722 | #define WPACKET_put_bytes_u32(pkt, val) \ |
723 | WPACKET_sub_allocate_bytes__((pkt), (val), 4) | |
9bf85bf9 MC |
724 | |
725 | /* Set a maximum size that we will not allow the WPACKET to grow beyond */ | |
ae2f7b37 | 726 | int WPACKET_set_max_size(WPACKET *pkt, size_t maxsize); |
9bf85bf9 MC |
727 | |
728 | /* Copy |len| bytes of data from |*src| into the WPACKET. */ | |
ae2f7b37 | 729 | int WPACKET_memcpy(WPACKET *pkt, const void *src, size_t len); |
9bf85bf9 MC |
730 | |
731 | /* | |
732 | * Copy |len| bytes of data from |*src| into the WPACKET and prefix with its | |
869d0a37 MC |
733 | * length (consuming |lenbytes| of data for the length). Don't call this |
734 | * directly. Use the convenience macros below instead. | |
9bf85bf9 | 735 | */ |
869d0a37 | 736 | int WPACKET_sub_memcpy__(WPACKET *pkt, const void *src, size_t len, |
fb790f16 | 737 | size_t lenbytes); |
9bf85bf9 | 738 | |
b2b3024e MC |
739 | /* Convenience macros for calling WPACKET_sub_memcpy with different lengths */ |
740 | #define WPACKET_sub_memcpy_u8(pkt, src, len) \ | |
869d0a37 | 741 | WPACKET_sub_memcpy__((pkt), (src), (len), 1) |
b2b3024e | 742 | #define WPACKET_sub_memcpy_u16(pkt, src, len) \ |
869d0a37 | 743 | WPACKET_sub_memcpy__((pkt), (src), (len), 2) |
b2b3024e | 744 | #define WPACKET_sub_memcpy_bytes_u24(pkt, src, len) \ |
869d0a37 | 745 | WPACKET_sub_memcpy__((pkt), (src), (len), 3) |
b2b3024e | 746 | #define WPACKET_sub_memcpy_bytes_u32(pkt, src, len) \ |
869d0a37 | 747 | WPACKET_sub_memcpy__((pkt), (src), (len), 4) |
b2b3024e | 748 | |
9bf85bf9 MC |
749 | /* |
750 | * Return the total number of bytes written so far to the underlying buffer | |
751 | * including any storage allocated for length bytes | |
752 | */ | |
ae2f7b37 | 753 | int WPACKET_get_total_written(WPACKET *pkt, size_t *written); |
9bf85bf9 MC |
754 | |
755 | /* | |
756 | * Returns the length of the current sub-packet. This excludes any bytes | |
757 | * allocated for the length itself. | |
758 | */ | |
ae2f7b37 | 759 | int WPACKET_get_length(WPACKET *pkt, size_t *len); |
9bf85bf9 MC |
760 | |
761 | /* Release resources in a WPACKET if a failure has occurred. */ | |
871bc59b | 762 | void WPACKET_cleanup(WPACKET *pkt); |
b7273855 | 763 | |
7e729bb5 MC |
764 | # ifdef __cplusplus |
765 | } | |
766 | # endif | |
767 | ||
80e0ecbf | 768 | #endif /* HEADER_PACKET_LOCL_H */ |