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