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