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