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