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