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