]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. | |
3 | * | |
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 | |
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> | |
16 | # include <openssl/crypto.h> | |
17 | # include <openssl/e_os2.h> | |
18 | ||
19 | # include "internal/numbers.h" | |
20 | ||
21 | # ifdef __cplusplus | |
22 | extern "C" { | |
23 | # endif | |
24 | ||
25 | typedef struct { | |
26 | /* Pointer to where we are currently reading from */ | |
27 | const unsigned char *curr; | |
28 | /* Number of bytes remaining */ | |
29 | size_t remaining; | |
30 | } PACKET; | |
31 | ||
32 | /* Internal unchecked shorthand; don't use outside this file. */ | |
33 | static ossl_inline void packet_forward(PACKET *pkt, size_t len) | |
34 | { | |
35 | pkt->curr += len; | |
36 | pkt->remaining -= len; | |
37 | } | |
38 | ||
39 | /* | |
40 | * Returns the number of bytes remaining to be read in the PACKET | |
41 | */ | |
42 | static ossl_inline size_t PACKET_remaining(const PACKET *pkt) | |
43 | { | |
44 | return pkt->remaining; | |
45 | } | |
46 | ||
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 | } | |
57 | ||
58 | /* | |
59 | * Returns a pointer to the PACKET's current position. | |
60 | * For use in non-PACKETized APIs. | |
61 | */ | |
62 | static ossl_inline const unsigned char *PACKET_data(const PACKET *pkt) | |
63 | { | |
64 | return pkt->curr; | |
65 | } | |
66 | ||
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 | */ | |
72 | __owur static ossl_inline int PACKET_buf_init(PACKET *pkt, | |
73 | const unsigned char *buf, | |
74 | size_t len) | |
75 | { | |
76 | /* Sanity check for negative values. */ | |
77 | if (len > (size_t)(SIZE_MAX / 2)) | |
78 | return 0; | |
79 | ||
80 | pkt->curr = buf; | |
81 | pkt->remaining = len; | |
82 | return 1; | |
83 | } | |
84 | ||
85 | /* Initialize a PACKET to hold zero bytes. */ | |
86 | static ossl_inline void PACKET_null_init(PACKET *pkt) | |
87 | { | |
88 | pkt->curr = NULL; | |
89 | pkt->remaining = 0; | |
90 | } | |
91 | ||
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 | */ | |
97 | __owur static ossl_inline int PACKET_equal(const PACKET *pkt, const void *ptr, | |
98 | size_t num) | |
99 | { | |
100 | if (PACKET_remaining(pkt) != num) | |
101 | return 0; | |
102 | return CRYPTO_memcmp(pkt->curr, ptr, num) == 0; | |
103 | } | |
104 | ||
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 | */ | |
110 | __owur static ossl_inline int PACKET_peek_sub_packet(const PACKET *pkt, | |
111 | PACKET *subpkt, size_t len) | |
112 | { | |
113 | if (PACKET_remaining(pkt) < len) | |
114 | return 0; | |
115 | ||
116 | return PACKET_buf_init(subpkt, pkt->curr, len); | |
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 | */ | |
124 | __owur static ossl_inline int PACKET_get_sub_packet(PACKET *pkt, | |
125 | PACKET *subpkt, size_t len) | |
126 | { | |
127 | if (!PACKET_peek_sub_packet(pkt, subpkt, len)) | |
128 | return 0; | |
129 | ||
130 | packet_forward(pkt, len); | |
131 | ||
132 | return 1; | |
133 | } | |
134 | ||
135 | /* | |
136 | * Peek ahead at 2 bytes in network order from |pkt| and store the value in | |
137 | * |*data| | |
138 | */ | |
139 | __owur static ossl_inline int PACKET_peek_net_2(const PACKET *pkt, | |
140 | unsigned int *data) | |
141 | { | |
142 | if (PACKET_remaining(pkt) < 2) | |
143 | return 0; | |
144 | ||
145 | *data = ((unsigned int)(*pkt->curr)) << 8; | |
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| */ | |
153 | __owur static ossl_inline int PACKET_get_net_2(PACKET *pkt, unsigned int *data) | |
154 | { | |
155 | if (!PACKET_peek_net_2(pkt, data)) | |
156 | return 0; | |
157 | ||
158 | packet_forward(pkt, 2); | |
159 | ||
160 | return 1; | |
161 | } | |
162 | ||
163 | /* Same as PACKET_get_net_2() but for a size_t */ | |
164 | __owur static ossl_inline int PACKET_get_net_2_len(PACKET *pkt, size_t *data) | |
165 | { | |
166 | unsigned int i; | |
167 | int ret = PACKET_get_net_2(pkt, &i); | |
168 | ||
169 | if (ret) | |
170 | *data = (size_t)i; | |
171 | ||
172 | return ret; | |
173 | } | |
174 | ||
175 | /* | |
176 | * Peek ahead at 3 bytes in network order from |pkt| and store the value in | |
177 | * |*data| | |
178 | */ | |
179 | __owur static ossl_inline int PACKET_peek_net_3(const PACKET *pkt, | |
180 | unsigned long *data) | |
181 | { | |
182 | if (PACKET_remaining(pkt) < 3) | |
183 | return 0; | |
184 | ||
185 | *data = ((unsigned long)(*pkt->curr)) << 16; | |
186 | *data |= ((unsigned long)(*(pkt->curr + 1))) << 8; | |
187 | *data |= *(pkt->curr + 2); | |
188 | ||
189 | return 1; | |
190 | } | |
191 | ||
192 | /* Equivalent of n2l3 */ | |
193 | /* Get 3 bytes in network order from |pkt| and store the value in |*data| */ | |
194 | __owur static ossl_inline int PACKET_get_net_3(PACKET *pkt, unsigned long *data) | |
195 | { | |
196 | if (!PACKET_peek_net_3(pkt, data)) | |
197 | return 0; | |
198 | ||
199 | packet_forward(pkt, 3); | |
200 | ||
201 | return 1; | |
202 | } | |
203 | ||
204 | /* Same as PACKET_get_net_3() but for a size_t */ | |
205 | __owur static ossl_inline int PACKET_get_net_3_len(PACKET *pkt, size_t *data) | |
206 | { | |
207 | unsigned long i; | |
208 | int ret = PACKET_get_net_3(pkt, &i); | |
209 | ||
210 | if (ret) | |
211 | *data = (size_t)i; | |
212 | ||
213 | return ret; | |
214 | } | |
215 | ||
216 | /* | |
217 | * Peek ahead at 4 bytes in network order from |pkt| and store the value in | |
218 | * |*data| | |
219 | */ | |
220 | __owur static ossl_inline int PACKET_peek_net_4(const PACKET *pkt, | |
221 | unsigned long *data) | |
222 | { | |
223 | if (PACKET_remaining(pkt) < 4) | |
224 | return 0; | |
225 | ||
226 | *data = ((unsigned long)(*pkt->curr)) << 24; | |
227 | *data |= ((unsigned long)(*(pkt->curr + 1))) << 16; | |
228 | *data |= ((unsigned long)(*(pkt->curr + 2))) << 8; | |
229 | *data |= *(pkt->curr + 3); | |
230 | ||
231 | return 1; | |
232 | } | |
233 | ||
234 | /* Equivalent of n2l */ | |
235 | /* Get 4 bytes in network order from |pkt| and store the value in |*data| */ | |
236 | __owur static ossl_inline int PACKET_get_net_4(PACKET *pkt, unsigned long *data) | |
237 | { | |
238 | if (!PACKET_peek_net_4(pkt, data)) | |
239 | return 0; | |
240 | ||
241 | packet_forward(pkt, 4); | |
242 | ||
243 | return 1; | |
244 | } | |
245 | ||
246 | /* Same as PACKET_get_net_4() but for a size_t */ | |
247 | __owur static ossl_inline int PACKET_get_net_4_len(PACKET *pkt, size_t *data) | |
248 | { | |
249 | unsigned long i; | |
250 | int ret = PACKET_get_net_4(pkt, &i); | |
251 | ||
252 | if (ret) | |
253 | *data = (size_t)i; | |
254 | ||
255 | return ret; | |
256 | } | |
257 | ||
258 | /* Peek ahead at 1 byte from |pkt| and store the value in |*data| */ | |
259 | __owur static ossl_inline int PACKET_peek_1(const PACKET *pkt, | |
260 | unsigned int *data) | |
261 | { | |
262 | if (!PACKET_remaining(pkt)) | |
263 | return 0; | |
264 | ||
265 | *data = *pkt->curr; | |
266 | ||
267 | return 1; | |
268 | } | |
269 | ||
270 | /* Get 1 byte from |pkt| and store the value in |*data| */ | |
271 | __owur static ossl_inline int PACKET_get_1(PACKET *pkt, unsigned int *data) | |
272 | { | |
273 | if (!PACKET_peek_1(pkt, data)) | |
274 | return 0; | |
275 | ||
276 | packet_forward(pkt, 1); | |
277 | ||
278 | return 1; | |
279 | } | |
280 | ||
281 | /* Same as PACKET_get_1() but for a size_t */ | |
282 | __owur static ossl_inline int PACKET_get_1_len(PACKET *pkt, size_t *data) | |
283 | { | |
284 | unsigned int i; | |
285 | int ret = PACKET_get_1(pkt, &i); | |
286 | ||
287 | if (ret) | |
288 | *data = (size_t)i; | |
289 | ||
290 | return ret; | |
291 | } | |
292 | ||
293 | /* | |
294 | * Peek ahead at 4 bytes in reverse network order from |pkt| and store the value | |
295 | * in |*data| | |
296 | */ | |
297 | __owur static ossl_inline int PACKET_peek_4(const PACKET *pkt, | |
298 | unsigned long *data) | |
299 | { | |
300 | if (PACKET_remaining(pkt) < 4) | |
301 | return 0; | |
302 | ||
303 | *data = *pkt->curr; | |
304 | *data |= ((unsigned long)(*(pkt->curr + 1))) << 8; | |
305 | *data |= ((unsigned long)(*(pkt->curr + 2))) << 16; | |
306 | *data |= ((unsigned long)(*(pkt->curr + 3))) << 24; | |
307 | ||
308 | return 1; | |
309 | } | |
310 | ||
311 | /* Equivalent of c2l */ | |
312 | /* | |
313 | * Get 4 bytes in reverse network order from |pkt| and store the value in | |
314 | * |*data| | |
315 | */ | |
316 | __owur static ossl_inline int PACKET_get_4(PACKET *pkt, unsigned long *data) | |
317 | { | |
318 | if (!PACKET_peek_4(pkt, data)) | |
319 | return 0; | |
320 | ||
321 | packet_forward(pkt, 4); | |
322 | ||
323 | return 1; | |
324 | } | |
325 | ||
326 | /* | |
327 | * Peek ahead at |len| bytes from the |pkt| and store a pointer to them in | |
328 | * |*data|. This just points at the underlying buffer that |pkt| is using. The | |
329 | * caller should not free this data directly (it will be freed when the | |
330 | * underlying buffer gets freed | |
331 | */ | |
332 | __owur static ossl_inline int PACKET_peek_bytes(const PACKET *pkt, | |
333 | const unsigned char **data, | |
334 | size_t len) | |
335 | { | |
336 | if (PACKET_remaining(pkt) < len) | |
337 | return 0; | |
338 | ||
339 | *data = pkt->curr; | |
340 | ||
341 | return 1; | |
342 | } | |
343 | ||
344 | /* | |
345 | * Read |len| bytes from the |pkt| and store a pointer to them in |*data|. This | |
346 | * just points at the underlying buffer that |pkt| is using. The caller should | |
347 | * not free this data directly (it will be freed when the underlying buffer gets | |
348 | * freed | |
349 | */ | |
350 | __owur static ossl_inline int PACKET_get_bytes(PACKET *pkt, | |
351 | const unsigned char **data, | |
352 | size_t len) | |
353 | { | |
354 | if (!PACKET_peek_bytes(pkt, data, len)) | |
355 | return 0; | |
356 | ||
357 | packet_forward(pkt, len); | |
358 | ||
359 | return 1; | |
360 | } | |
361 | ||
362 | /* Peek ahead at |len| bytes from |pkt| and copy them to |data| */ | |
363 | __owur static ossl_inline int PACKET_peek_copy_bytes(const PACKET *pkt, | |
364 | unsigned char *data, | |
365 | size_t len) | |
366 | { | |
367 | if (PACKET_remaining(pkt) < len) | |
368 | return 0; | |
369 | ||
370 | memcpy(data, pkt->curr, len); | |
371 | ||
372 | return 1; | |
373 | } | |
374 | ||
375 | /* | |
376 | * Read |len| bytes from |pkt| and copy them to |data|. | |
377 | * The caller is responsible for ensuring that |data| can hold |len| bytes. | |
378 | */ | |
379 | __owur static ossl_inline int PACKET_copy_bytes(PACKET *pkt, | |
380 | unsigned char *data, size_t len) | |
381 | { | |
382 | if (!PACKET_peek_copy_bytes(pkt, data, len)) | |
383 | return 0; | |
384 | ||
385 | packet_forward(pkt, len); | |
386 | ||
387 | return 1; | |
388 | } | |
389 | ||
390 | /* | |
391 | * Copy packet data to |dest|, and set |len| to the number of copied bytes. | |
392 | * If the packet has more than |dest_len| bytes, nothing is copied. | |
393 | * Returns 1 if the packet data fits in |dest_len| bytes, 0 otherwise. | |
394 | * Does not forward PACKET position (because it is typically the last thing | |
395 | * done with a given PACKET). | |
396 | */ | |
397 | __owur static ossl_inline int PACKET_copy_all(const PACKET *pkt, | |
398 | unsigned char *dest, | |
399 | size_t dest_len, size_t *len) | |
400 | { | |
401 | if (PACKET_remaining(pkt) > dest_len) { | |
402 | *len = 0; | |
403 | return 0; | |
404 | } | |
405 | *len = pkt->remaining; | |
406 | memcpy(dest, pkt->curr, pkt->remaining); | |
407 | return 1; | |
408 | } | |
409 | ||
410 | /* | |
411 | * Copy |pkt| bytes to a newly allocated buffer and store a pointer to the | |
412 | * result in |*data|, and the length in |len|. | |
413 | * If |*data| is not NULL, the old data is OPENSSL_free'd. | |
414 | * If the packet is empty, or malloc fails, |*data| will be set to NULL. | |
415 | * Returns 1 if the malloc succeeds and 0 otherwise. | |
416 | * Does not forward PACKET position (because it is typically the last thing | |
417 | * done with a given PACKET). | |
418 | */ | |
419 | __owur static ossl_inline int PACKET_memdup(const PACKET *pkt, | |
420 | unsigned char **data, size_t *len) | |
421 | { | |
422 | size_t length; | |
423 | ||
424 | OPENSSL_free(*data); | |
425 | *data = NULL; | |
426 | *len = 0; | |
427 | ||
428 | length = PACKET_remaining(pkt); | |
429 | ||
430 | if (length == 0) | |
431 | return 1; | |
432 | ||
433 | *data = OPENSSL_memdup(pkt->curr, length); | |
434 | if (*data == NULL) | |
435 | return 0; | |
436 | ||
437 | *len = length; | |
438 | return 1; | |
439 | } | |
440 | ||
441 | /* | |
442 | * Read a C string from |pkt| and copy to a newly allocated, NUL-terminated | |
443 | * buffer. Store a pointer to the result in |*data|. | |
444 | * If |*data| is not NULL, the old data is OPENSSL_free'd. | |
445 | * If the data in |pkt| does not contain a NUL-byte, the entire data is | |
446 | * copied and NUL-terminated. | |
447 | * Returns 1 if the malloc succeeds and 0 otherwise. | |
448 | * Does not forward PACKET position (because it is typically the last thing done | |
449 | * with a given PACKET). | |
450 | */ | |
451 | __owur static ossl_inline int PACKET_strndup(const PACKET *pkt, char **data) | |
452 | { | |
453 | OPENSSL_free(*data); | |
454 | ||
455 | /* This will succeed on an empty packet, unless pkt->curr == NULL. */ | |
456 | *data = OPENSSL_strndup((const char *)pkt->curr, PACKET_remaining(pkt)); | |
457 | return (*data != NULL); | |
458 | } | |
459 | ||
460 | /* Returns 1 if |pkt| contains at least one 0-byte, 0 otherwise. */ | |
461 | static ossl_inline int PACKET_contains_zero_byte(const PACKET *pkt) | |
462 | { | |
463 | return memchr(pkt->curr, 0, pkt->remaining) != NULL; | |
464 | } | |
465 | ||
466 | /* Move the current reading position forward |len| bytes */ | |
467 | __owur static ossl_inline int PACKET_forward(PACKET *pkt, size_t len) | |
468 | { | |
469 | if (PACKET_remaining(pkt) < len) | |
470 | return 0; | |
471 | ||
472 | packet_forward(pkt, len); | |
473 | ||
474 | return 1; | |
475 | } | |
476 | ||
477 | /* | |
478 | * Reads a variable-length vector prefixed with a one-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 | */ | |
484 | __owur static ossl_inline int PACKET_get_length_prefixed_1(PACKET *pkt, | |
485 | PACKET *subpkt) | |
486 | { | |
487 | unsigned int length; | |
488 | const unsigned char *data; | |
489 | PACKET tmp = *pkt; | |
490 | if (!PACKET_get_1(&tmp, &length) || | |
491 | !PACKET_get_bytes(&tmp, &data, (size_t)length)) { | |
492 | return 0; | |
493 | } | |
494 | ||
495 | *pkt = tmp; | |
496 | subpkt->curr = data; | |
497 | subpkt->remaining = length; | |
498 | ||
499 | return 1; | |
500 | } | |
501 | ||
502 | /* | |
503 | * Like PACKET_get_length_prefixed_1, but additionally, fails when there are | |
504 | * leftover bytes in |pkt|. | |
505 | */ | |
506 | __owur static ossl_inline int PACKET_as_length_prefixed_1(PACKET *pkt, | |
507 | PACKET *subpkt) | |
508 | { | |
509 | unsigned int length; | |
510 | const unsigned char *data; | |
511 | PACKET tmp = *pkt; | |
512 | if (!PACKET_get_1(&tmp, &length) || | |
513 | !PACKET_get_bytes(&tmp, &data, (size_t)length) || | |
514 | PACKET_remaining(&tmp) != 0) { | |
515 | return 0; | |
516 | } | |
517 | ||
518 | *pkt = tmp; | |
519 | subpkt->curr = data; | |
520 | subpkt->remaining = length; | |
521 | ||
522 | return 1; | |
523 | } | |
524 | ||
525 | /* | |
526 | * Reads a variable-length vector prefixed with a two-byte length, and stores | |
527 | * the contents in |subpkt|. |pkt| can equal |subpkt|. | |
528 | * Data is not copied: the |subpkt| packet will share its underlying buffer with | |
529 | * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|. | |
530 | * Upon failure, the original |pkt| and |subpkt| are not modified. | |
531 | */ | |
532 | __owur static ossl_inline int PACKET_get_length_prefixed_2(PACKET *pkt, | |
533 | PACKET *subpkt) | |
534 | { | |
535 | unsigned int length; | |
536 | const unsigned char *data; | |
537 | PACKET tmp = *pkt; | |
538 | ||
539 | if (!PACKET_get_net_2(&tmp, &length) || | |
540 | !PACKET_get_bytes(&tmp, &data, (size_t)length)) { | |
541 | return 0; | |
542 | } | |
543 | ||
544 | *pkt = tmp; | |
545 | subpkt->curr = data; | |
546 | subpkt->remaining = length; | |
547 | ||
548 | return 1; | |
549 | } | |
550 | ||
551 | /* | |
552 | * Like PACKET_get_length_prefixed_2, but additionally, fails when there are | |
553 | * leftover bytes in |pkt|. | |
554 | */ | |
555 | __owur static ossl_inline int PACKET_as_length_prefixed_2(PACKET *pkt, | |
556 | PACKET *subpkt) | |
557 | { | |
558 | unsigned int length; | |
559 | const unsigned char *data; | |
560 | PACKET tmp = *pkt; | |
561 | ||
562 | if (!PACKET_get_net_2(&tmp, &length) || | |
563 | !PACKET_get_bytes(&tmp, &data, (size_t)length) || | |
564 | PACKET_remaining(&tmp) != 0) { | |
565 | return 0; | |
566 | } | |
567 | ||
568 | *pkt = tmp; | |
569 | subpkt->curr = data; | |
570 | subpkt->remaining = length; | |
571 | ||
572 | return 1; | |
573 | } | |
574 | ||
575 | /* | |
576 | * Reads a variable-length vector prefixed with a three-byte length, and stores | |
577 | * the contents in |subpkt|. |pkt| can equal |subpkt|. | |
578 | * Data is not copied: the |subpkt| packet will share its underlying buffer with | |
579 | * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|. | |
580 | * Upon failure, the original |pkt| and |subpkt| are not modified. | |
581 | */ | |
582 | __owur static ossl_inline int PACKET_get_length_prefixed_3(PACKET *pkt, | |
583 | PACKET *subpkt) | |
584 | { | |
585 | unsigned long length; | |
586 | const unsigned char *data; | |
587 | PACKET tmp = *pkt; | |
588 | if (!PACKET_get_net_3(&tmp, &length) || | |
589 | !PACKET_get_bytes(&tmp, &data, (size_t)length)) { | |
590 | return 0; | |
591 | } | |
592 | ||
593 | *pkt = tmp; | |
594 | subpkt->curr = data; | |
595 | subpkt->remaining = length; | |
596 | ||
597 | return 1; | |
598 | } | |
599 | ||
600 | /* Writeable packets */ | |
601 | ||
602 | typedef struct wpacket_sub WPACKET_SUB; | |
603 | struct wpacket_sub { | |
604 | /* The parent WPACKET_SUB if we have one or NULL otherwise */ | |
605 | WPACKET_SUB *parent; | |
606 | ||
607 | /* | |
608 | * Offset into the buffer where the length of this WPACKET goes. We use an | |
609 | * offset in case the buffer grows and gets reallocated. | |
610 | */ | |
611 | size_t packet_len; | |
612 | ||
613 | /* Number of bytes in the packet_len or 0 if we don't write the length */ | |
614 | size_t lenbytes; | |
615 | ||
616 | /* Number of bytes written to the buf prior to this packet starting */ | |
617 | size_t pwritten; | |
618 | ||
619 | /* Flags for this sub-packet */ | |
620 | unsigned int flags; | |
621 | }; | |
622 | ||
623 | typedef struct wpacket_st WPACKET; | |
624 | struct wpacket_st { | |
625 | /* The buffer where we store the output data */ | |
626 | BUF_MEM *buf; | |
627 | ||
628 | /* Fixed sized buffer which can be used as an alternative to buf */ | |
629 | unsigned char *staticbuf; | |
630 | ||
631 | /* | |
632 | * Offset into the buffer where we are currently writing. We use an offset | |
633 | * in case the buffer grows and gets reallocated. | |
634 | */ | |
635 | size_t curr; | |
636 | ||
637 | /* Number of bytes written so far */ | |
638 | size_t written; | |
639 | ||
640 | /* Maximum number of bytes we will allow to be written to this WPACKET */ | |
641 | size_t maxsize; | |
642 | ||
643 | /* Our sub-packets (always at least one if not finished) */ | |
644 | WPACKET_SUB *subs; | |
645 | }; | |
646 | ||
647 | /* Flags */ | |
648 | ||
649 | /* Default */ | |
650 | #define WPACKET_FLAGS_NONE 0 | |
651 | ||
652 | /* Error on WPACKET_close() if no data written to the WPACKET */ | |
653 | #define WPACKET_FLAGS_NON_ZERO_LENGTH 1 | |
654 | ||
655 | /* | |
656 | * Abandon all changes on WPACKET_close() if no data written to the WPACKET, | |
657 | * i.e. this does not write out a zero packet length | |
658 | */ | |
659 | #define WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH 2 | |
660 | ||
661 | ||
662 | /* | |
663 | * Initialise a WPACKET with the buffer in |buf|. The buffer must exist | |
664 | * for the whole time that the WPACKET is being used. Additionally |lenbytes| of | |
665 | * data is preallocated at the start of the buffer to store the length of the | |
666 | * WPACKET once we know it. | |
667 | */ | |
668 | int WPACKET_init_len(WPACKET *pkt, BUF_MEM *buf, size_t lenbytes); | |
669 | ||
670 | /* | |
671 | * Same as WPACKET_init_len except there is no preallocation of the WPACKET | |
672 | * length. | |
673 | */ | |
674 | int WPACKET_init(WPACKET *pkt, BUF_MEM *buf); | |
675 | ||
676 | /* | |
677 | * Same as WPACKET_init_len except we do not use a growable BUF_MEM structure. | |
678 | * A fixed buffer of memory |buf| of size |len| is used instead. A failure will | |
679 | * occur if you attempt to write beyond the end of the buffer | |
680 | */ | |
681 | int WPACKET_init_static_len(WPACKET *pkt, unsigned char *buf, size_t len, | |
682 | size_t lenbytes); | |
683 | /* | |
684 | * Set the flags to be applied to the current sub-packet | |
685 | */ | |
686 | int WPACKET_set_flags(WPACKET *pkt, unsigned int flags); | |
687 | ||
688 | /* | |
689 | * Closes the most recent sub-packet. It also writes out the length of the | |
690 | * packet to the required location (normally the start of the WPACKET) if | |
691 | * appropriate. The top level WPACKET should be closed using WPACKET_finish() | |
692 | * instead of this function. | |
693 | */ | |
694 | int WPACKET_close(WPACKET *pkt); | |
695 | ||
696 | /* | |
697 | * The same as WPACKET_close() but only for the top most WPACKET. Additionally | |
698 | * frees memory resources for this WPACKET. | |
699 | */ | |
700 | int WPACKET_finish(WPACKET *pkt); | |
701 | ||
702 | /* | |
703 | * Iterate through all the sub-packets and write out their lengths as if they | |
704 | * were being closed. The lengths will be overwritten with the final lengths | |
705 | * when the sub-packets are eventually closed (which may be different if more | |
706 | * data is added to the WPACKET). This function fails if a sub-packet is of 0 | |
707 | * length and WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH is set. | |
708 | */ | |
709 | int WPACKET_fill_lengths(WPACKET *pkt); | |
710 | ||
711 | /* | |
712 | * Initialise a new sub-packet. Additionally |lenbytes| of data is preallocated | |
713 | * at the start of the sub-packet to store its length once we know it. Don't | |
714 | * call this directly. Use the convenience macros below instead. | |
715 | */ | |
716 | int WPACKET_start_sub_packet_len__(WPACKET *pkt, size_t lenbytes); | |
717 | ||
718 | /* | |
719 | * Convenience macros for calling WPACKET_start_sub_packet_len with different | |
720 | * lengths | |
721 | */ | |
722 | #define WPACKET_start_sub_packet_u8(pkt) \ | |
723 | WPACKET_start_sub_packet_len__((pkt), 1) | |
724 | #define WPACKET_start_sub_packet_u16(pkt) \ | |
725 | WPACKET_start_sub_packet_len__((pkt), 2) | |
726 | #define WPACKET_start_sub_packet_u24(pkt) \ | |
727 | WPACKET_start_sub_packet_len__((pkt), 3) | |
728 | #define WPACKET_start_sub_packet_u32(pkt) \ | |
729 | WPACKET_start_sub_packet_len__((pkt), 4) | |
730 | ||
731 | /* | |
732 | * Same as WPACKET_start_sub_packet_len__() except no bytes are pre-allocated | |
733 | * for the sub-packet length. | |
734 | */ | |
735 | int WPACKET_start_sub_packet(WPACKET *pkt); | |
736 | ||
737 | /* | |
738 | * Allocate bytes in the WPACKET for the output. This reserves the bytes | |
739 | * and counts them as "written", but doesn't actually do the writing. A pointer | |
740 | * to the allocated bytes is stored in |*allocbytes|. |allocbytes| may be NULL. | |
741 | * WARNING: the allocated bytes must be filled in immediately, without further | |
742 | * WPACKET_* calls. If not then the underlying buffer may be realloc'd and | |
743 | * change its location. | |
744 | */ | |
745 | int WPACKET_allocate_bytes(WPACKET *pkt, size_t len, | |
746 | unsigned char **allocbytes); | |
747 | ||
748 | /* | |
749 | * The same as WPACKET_allocate_bytes() except additionally a new sub-packet is | |
750 | * started for the allocated bytes, and then closed immediately afterwards. The | |
751 | * number of length bytes for the sub-packet is in |lenbytes|. Don't call this | |
752 | * directly. Use the convenience macros below instead. | |
753 | */ | |
754 | int WPACKET_sub_allocate_bytes__(WPACKET *pkt, size_t len, | |
755 | unsigned char **allocbytes, size_t lenbytes); | |
756 | ||
757 | /* | |
758 | * Convenience macros for calling WPACKET_sub_allocate_bytes with different | |
759 | * lengths | |
760 | */ | |
761 | #define WPACKET_sub_allocate_bytes_u8(pkt, len, bytes) \ | |
762 | WPACKET_sub_allocate_bytes__((pkt), (len), (bytes), 1) | |
763 | #define WPACKET_sub_allocate_bytes_u16(pkt, len, bytes) \ | |
764 | WPACKET_sub_allocate_bytes__((pkt), (len), (bytes), 2) | |
765 | #define WPACKET_sub_allocate_bytes_u24(pkt, len, bytes) \ | |
766 | WPACKET_sub_allocate_bytes__((pkt), (len), (bytes), 3) | |
767 | #define WPACKET_sub_allocate_bytes_u32(pkt, len, bytes) \ | |
768 | WPACKET_sub_allocate_bytes__((pkt), (len), (bytes), 4) | |
769 | ||
770 | /* | |
771 | * The same as WPACKET_allocate_bytes() except the reserved bytes are not | |
772 | * actually counted as written. Typically this will be for when we don't know | |
773 | * how big arbitrary data is going to be up front, but we do know what the | |
774 | * maximum size will be. If this function is used, then it should be immediately | |
775 | * followed by a WPACKET_allocate_bytes() call before any other WPACKET | |
776 | * functions are called (unless the write to the allocated bytes is abandoned). | |
777 | * | |
778 | * For example: If we are generating a signature, then the size of that | |
779 | * signature may not be known in advance. We can use WPACKET_reserve_bytes() to | |
780 | * handle this: | |
781 | * | |
782 | * if (!WPACKET_sub_reserve_bytes_u16(&pkt, EVP_PKEY_size(pkey), &sigbytes1) | |
783 | * || EVP_SignFinal(md_ctx, sigbytes1, &siglen, pkey) <= 0 | |
784 | * || !WPACKET_sub_allocate_bytes_u16(&pkt, siglen, &sigbytes2) | |
785 | * || sigbytes1 != sigbytes2) | |
786 | * goto err; | |
787 | */ | |
788 | int WPACKET_reserve_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes); | |
789 | ||
790 | /* | |
791 | * The "reserve_bytes" equivalent of WPACKET_sub_allocate_bytes__() | |
792 | */ | |
793 | int WPACKET_sub_reserve_bytes__(WPACKET *pkt, size_t len, | |
794 | unsigned char **allocbytes, size_t lenbytes); | |
795 | ||
796 | /* | |
797 | * Convenience macros for WPACKET_sub_reserve_bytes with different lengths | |
798 | */ | |
799 | #define WPACKET_sub_reserve_bytes_u8(pkt, len, bytes) \ | |
800 | WPACKET_reserve_bytes__((pkt), (len), (bytes), 1) | |
801 | #define WPACKET_sub_reserve_bytes_u16(pkt, len, bytes) \ | |
802 | WPACKET_sub_reserve_bytes__((pkt), (len), (bytes), 2) | |
803 | #define WPACKET_sub_reserve_bytes_u24(pkt, len, bytes) \ | |
804 | WPACKET_sub_reserve_bytes__((pkt), (len), (bytes), 3) | |
805 | #define WPACKET_sub_reserve_bytes_u32(pkt, len, bytes) \ | |
806 | WPACKET_sub_reserve_bytes__((pkt), (len), (bytes), 4) | |
807 | ||
808 | /* | |
809 | * Write the value stored in |val| into the WPACKET. The value will consume | |
810 | * |bytes| amount of storage. An error will occur if |val| cannot be | |
811 | * accommodated in |bytes| storage, e.g. attempting to write the value 256 into | |
812 | * 1 byte will fail. Don't call this directly. Use the convenience macros below | |
813 | * instead. | |
814 | */ | |
815 | int WPACKET_put_bytes__(WPACKET *pkt, unsigned int val, size_t bytes); | |
816 | ||
817 | /* | |
818 | * Convenience macros for calling WPACKET_put_bytes with different | |
819 | * lengths | |
820 | */ | |
821 | #define WPACKET_put_bytes_u8(pkt, val) \ | |
822 | WPACKET_put_bytes__((pkt), (val), 1) | |
823 | #define WPACKET_put_bytes_u16(pkt, val) \ | |
824 | WPACKET_put_bytes__((pkt), (val), 2) | |
825 | #define WPACKET_put_bytes_u24(pkt, val) \ | |
826 | WPACKET_put_bytes__((pkt), (val), 3) | |
827 | #define WPACKET_put_bytes_u32(pkt, val) \ | |
828 | WPACKET_put_bytes__((pkt), (val), 4) | |
829 | ||
830 | /* Set a maximum size that we will not allow the WPACKET to grow beyond */ | |
831 | int WPACKET_set_max_size(WPACKET *pkt, size_t maxsize); | |
832 | ||
833 | /* Copy |len| bytes of data from |*src| into the WPACKET. */ | |
834 | int WPACKET_memcpy(WPACKET *pkt, const void *src, size_t len); | |
835 | ||
836 | /* Set |len| bytes of data to |ch| into the WPACKET. */ | |
837 | int WPACKET_memset(WPACKET *pkt, int ch, size_t len); | |
838 | ||
839 | /* | |
840 | * Copy |len| bytes of data from |*src| into the WPACKET and prefix with its | |
841 | * length (consuming |lenbytes| of data for the length). Don't call this | |
842 | * directly. Use the convenience macros below instead. | |
843 | */ | |
844 | int WPACKET_sub_memcpy__(WPACKET *pkt, const void *src, size_t len, | |
845 | size_t lenbytes); | |
846 | ||
847 | /* Convenience macros for calling WPACKET_sub_memcpy with different lengths */ | |
848 | #define WPACKET_sub_memcpy_u8(pkt, src, len) \ | |
849 | WPACKET_sub_memcpy__((pkt), (src), (len), 1) | |
850 | #define WPACKET_sub_memcpy_u16(pkt, src, len) \ | |
851 | WPACKET_sub_memcpy__((pkt), (src), (len), 2) | |
852 | #define WPACKET_sub_memcpy_u24(pkt, src, len) \ | |
853 | WPACKET_sub_memcpy__((pkt), (src), (len), 3) | |
854 | #define WPACKET_sub_memcpy_u32(pkt, src, len) \ | |
855 | WPACKET_sub_memcpy__((pkt), (src), (len), 4) | |
856 | ||
857 | /* | |
858 | * Return the total number of bytes written so far to the underlying buffer | |
859 | * including any storage allocated for length bytes | |
860 | */ | |
861 | int WPACKET_get_total_written(WPACKET *pkt, size_t *written); | |
862 | ||
863 | /* | |
864 | * Returns the length of the current sub-packet. This excludes any bytes | |
865 | * allocated for the length itself. | |
866 | */ | |
867 | int WPACKET_get_length(WPACKET *pkt, size_t *len); | |
868 | ||
869 | /* | |
870 | * Returns a pointer to the current write location, but does not allocate any | |
871 | * bytes. | |
872 | */ | |
873 | unsigned char *WPACKET_get_curr(WPACKET *pkt); | |
874 | ||
875 | /* Release resources in a WPACKET if a failure has occurred. */ | |
876 | void WPACKET_cleanup(WPACKET *pkt); | |
877 | ||
878 | # ifdef __cplusplus | |
879 | } | |
880 | # endif | |
881 | ||
882 | #endif /* HEADER_PACKET_LOCL_H */ |