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