PACKET: simplify
[openssl.git] / ssl / packet_locl.h
1 /* ssl/packet_locl.h */
2 /*
3  * Written by Matt Caswell for the OpenSSL project.
4  */
5 /* ====================================================================
6  * Copyright (c) 2015 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    openssl-core@openssl.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * (eay@cryptsoft.com).  This product includes software written by Tim
55  * Hudson (tjh@cryptsoft.com).
56  *
57  */
58
59 #ifndef HEADER_PACKET_LOCL_H
60 # define HEADER_PACKET_LOCL_H
61
62 # include <string.h>
63 # include <openssl/bn.h>
64 # include <openssl/buffer.h>
65 # include "e_os.h"
66
67 # ifdef __cplusplus
68 extern "C" {
69 # endif
70
71 typedef struct {
72     /* Pointer to where we are currently reading from */
73     unsigned char *curr;
74     /* Number of bytes remaining */
75     size_t remaining;
76 } PACKET;
77
78 /* Internal unchecked shorthand; don't use outside this file. */
79 static inline void packet_forward(PACKET *pkt, size_t len)
80 {
81     pkt->curr += len;
82     pkt->remaining -= len;
83 }
84
85 /*
86  * Returns the number of bytes remaining to be read in the PACKET
87  */
88 __owur static inline size_t PACKET_remaining(const PACKET *pkt)
89 {
90     return pkt->remaining;
91 }
92
93 /*
94  * Returns a pointer to the PACKET's current position.
95  * For use in non-PACKETized APIs.
96  * TODO(openssl-team): this should return 'const unsigned char*' but can't
97  * currently because legacy code passes 'unsigned char*'s around.
98  */
99 static inline unsigned char *PACKET_data(const PACKET *pkt)
100 {
101     return pkt->curr;
102 }
103
104 /*
105  * Initialise a PACKET with |len| bytes held in |buf|. This does not make a
106  * copy of the data so |buf| must be present for the whole time that the PACKET
107  * is being used.
108  */
109 static inline int PACKET_buf_init(PACKET *pkt, unsigned char *buf, size_t len)
110 {
111     /* Sanity check for negative values. */
112     if (buf + len < buf)
113         return 0;
114
115     pkt->curr = buf;
116     pkt->remaining = len;
117     return 1;
118 }
119
120 /*
121  * Peek ahead and initialize |subpkt| with the next |len| bytes read from |pkt|.
122  * Data is not copied: the |subpkt| packet will share its underlying buffer with
123  * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|.
124  */
125 __owur static inline int PACKET_peek_sub_packet(const PACKET *pkt,
126                                                 PACKET *subpkt, size_t len)
127 {
128     if (PACKET_remaining(pkt) < len)
129         return 0;
130
131     PACKET_buf_init(subpkt, pkt->curr, len);
132
133     return 1;
134 }
135
136 /*
137  * Initialize |subpkt| with the next |len| bytes read from |pkt|. Data is not
138  * copied: the |subpkt| packet will share its underlying buffer with the
139  * original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|.
140  */
141 __owur static inline int PACKET_get_sub_packet(PACKET *pkt, PACKET *subpkt,
142                                                size_t len)
143 {
144     if (!PACKET_peek_sub_packet(pkt, subpkt, len))
145         return 0;
146
147     packet_forward(pkt, len);
148
149     return 1;
150 }
151
152 /* Peek ahead at 2 bytes in network order from |pkt| and store the value in
153  * |*data|
154  */
155 __owur static inline int PACKET_peek_net_2(const PACKET *pkt,
156                                            unsigned int *data)
157 {
158     if (PACKET_remaining(pkt) < 2)
159         return 0;
160
161     *data  = ((unsigned int)(*pkt->curr)) <<  8;
162     *data |= *(pkt->curr + 1);
163
164     return 1;
165 }
166
167 /* Equivalent of n2s */
168 /* Get 2 bytes in network order from |pkt| and store the value in |*data| */
169 __owur static inline int PACKET_get_net_2(PACKET *pkt, unsigned int *data)
170 {
171     if (!PACKET_peek_net_2(pkt, data))
172         return 0;
173
174     packet_forward(pkt, 2);
175
176     return 1;
177 }
178
179 /* Peek ahead at 3 bytes in network order from |pkt| and store the value in
180  * |*data|
181  */
182 __owur static inline int PACKET_peek_net_3(const PACKET *pkt,
183                                            unsigned long *data)
184 {
185     if (PACKET_remaining(pkt) < 3)
186         return 0;
187
188     *data  = ((unsigned long)(*pkt->curr)) << 16;
189     *data |= ((unsigned long)(*(pkt->curr + 1))) <<  8;
190     *data |= *(pkt->curr + 2);
191
192     return 1;
193 }
194
195 /* Equivalent of n2l3 */
196 /* Get 3 bytes in network order from |pkt| and store the value in |*data| */
197 __owur static inline int PACKET_get_net_3(PACKET *pkt, unsigned long *data)
198 {
199     if (!PACKET_peek_net_3(pkt, data))
200         return 0;
201
202     packet_forward(pkt, 3);
203
204     return 1;
205 }
206
207 /* Peek ahead at 4 bytes in network order from |pkt| and store the value in
208  * |*data|
209  */
210 __owur static inline int PACKET_peek_net_4(const PACKET *pkt,
211                                            unsigned long *data)
212 {
213     if (PACKET_remaining(pkt) < 4)
214         return 0;
215
216     *data  = ((unsigned long)(*pkt->curr)) << 24;
217     *data |= ((unsigned long)(*(pkt->curr + 1))) << 16;
218     *data |= ((unsigned long)(*(pkt->curr + 2))) <<  8;
219     *data |= *(pkt->curr+3);
220
221     return 1;
222 }
223
224 /* Equivalent of n2l */
225 /* Get 4 bytes in network order from |pkt| and store the value in |*data| */
226 __owur static inline int PACKET_get_net_4(PACKET *pkt, unsigned long *data)
227 {
228     if (!PACKET_peek_net_4(pkt, data))
229         return 0;
230
231     packet_forward(pkt, 4);
232
233     return 1;
234 }
235
236 /* Peek ahead at 1 byte from |pkt| and store the value in |*data| */
237 __owur static inline int PACKET_peek_1(const PACKET *pkt, unsigned int *data)
238 {
239     if (!PACKET_remaining(pkt))
240         return 0;
241
242     *data = *pkt->curr;
243
244     return 1;
245 }
246
247 /* Get 1 byte from |pkt| and store the value in |*data| */
248 __owur static inline int PACKET_get_1(PACKET *pkt, unsigned int *data)
249 {
250     if (!PACKET_peek_1(pkt, data))
251         return 0;
252
253     packet_forward(pkt, 1);
254
255     return 1;
256 }
257
258 /*
259  * Peek ahead at 4 bytes in reverse network order from |pkt| and store the value
260  * in |*data|
261  */
262 __owur static inline int PACKET_peek_4(const PACKET *pkt, unsigned long *data)
263 {
264     if (PACKET_remaining(pkt) < 4)
265         return 0;
266
267     *data  = *pkt->curr;
268     *data |= ((unsigned long)(*(pkt->curr + 1))) <<  8;
269     *data |= ((unsigned long)(*(pkt->curr + 2))) << 16;
270     *data |= ((unsigned long)(*(pkt->curr + 3))) << 24;
271
272     return 1;
273 }
274
275 /* Equivalent of c2l */
276 /*
277  * Get 4 bytes in reverse network order from |pkt| and store the value in
278  * |*data|
279  */
280 __owur static inline int PACKET_get_4(PACKET *pkt, unsigned long *data)
281 {
282     if (!PACKET_peek_4(pkt, data))
283         return 0;
284
285     packet_forward(pkt, 4);
286
287     return 1;
288 }
289
290 /*
291  * Peek ahead at |len| bytes from the |pkt| and store a pointer to them in
292  * |*data|. This just points at the underlying buffer that |pkt| is using. The
293  * caller should not free this data directly (it will be freed when the
294  * underlying buffer gets freed
295  */
296 __owur static inline int PACKET_peek_bytes(const PACKET *pkt, unsigned char **data,
297                                           size_t len)
298 {
299     if (PACKET_remaining(pkt) < len)
300         return 0;
301
302     *data = pkt->curr;
303
304     return 1;
305 }
306
307 /*
308  * Read |len| bytes from the |pkt| and store a pointer to them in |*data|. This
309  * just points at the underlying buffer that |pkt| is using. The caller should
310  * not free this data directly (it will be freed when the underlying buffer gets
311  * freed
312  */
313 __owur static inline int PACKET_get_bytes(PACKET *pkt, unsigned char **data,
314                                           size_t len)
315 {
316     if (!PACKET_peek_bytes(pkt, data, len))
317         return 0;
318
319     packet_forward(pkt, len);
320
321     return 1;
322 }
323
324 /* Peek ahead at |len| bytes from |pkt| and copy them to |data| */
325 __owur static inline int PACKET_peek_copy_bytes(const PACKET *pkt,
326                                                 unsigned char *data, size_t len)
327 {
328     if (PACKET_remaining(pkt) < len)
329         return 0;
330
331     memcpy(data, pkt->curr, len);
332
333     return 1;
334 }
335
336 /*
337  * Read |len| bytes from |pkt| and copy them to |data|.
338  * The caller is responsible for ensuring that |data| can hold |len| bytes.
339  */
340 __owur static inline int PACKET_copy_bytes(PACKET *pkt, unsigned char *data,
341                                            size_t len)
342 {
343     if (!PACKET_peek_copy_bytes(pkt, data, len))
344         return 0;
345
346     packet_forward(pkt, len);
347
348     return 1;
349 }
350
351 /*
352  * Copy |pkt| bytes to a newly allocated buffer and store a pointer to the
353  * result in |*data|, and the length in |len|.
354  * If |*data| is not NULL, the old data is OPENSSL_free'd.
355  * If the packet is empty, or malloc fails, |*data| will be set to NULL.
356  * Returns 1 if the malloc succeeds and 0 otherwise.
357  * Does not forward PACKET position (because it is typically the last thing
358  * done with a given PACKET).
359  */
360 __owur static inline int PACKET_memdup(const PACKET *pkt, unsigned char **data,
361                                        size_t *len)
362 {
363     size_t length;
364
365     OPENSSL_free(*data);
366     *data = NULL;
367     *len = 0;
368
369     length = PACKET_remaining(pkt);
370
371     if (length == 0)
372         return 1;
373
374     *data = BUF_memdup(pkt->curr, length);
375
376     if (*data == NULL)
377         return 0;
378
379     *len = length;
380     return 1;
381 }
382
383 /*
384  * Read a C string from |pkt| and copy to a newly allocated, NUL-terminated
385  * buffer. Store a pointer to the result in |*data|.
386  * If |*data| is not NULL, the old data is OPENSSL_free'd.
387  * If the data in |pkt| does not contain a NUL-byte, the entire data is
388  * copied and NUL-terminated.
389  * Returns 1 if the malloc succeeds and 0 otherwise.
390  * Does not forward PACKET position (because it is typically the last thing done
391  * with a given PACKET).
392  */
393 __owur static inline int PACKET_strndup(const PACKET *pkt, char **data)
394 {
395     OPENSSL_free(*data);
396     *data = BUF_strndup((const char*)pkt->curr, PACKET_remaining(pkt));
397     return (*data != NULL);
398 }
399
400 /* Move the current reading position forward |len| bytes */
401 __owur static inline int PACKET_forward(PACKET *pkt, size_t len)
402 {
403     if (PACKET_remaining(pkt) < len)
404         return 0;
405
406     packet_forward(pkt, len);
407
408     return 1;
409 }
410
411 /*
412  * Reads a variable-length vector prefixed with a one-byte length, and stores
413  * the contents in |subpkt|. |pkt| can equal |subpkt|.
414  * Data is not copied: the |subpkt| packet will share its underlying buffer with
415  * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|.
416  * Upon failure, the original |pkt| and |subpkt| are not modified.
417  */
418 __owur static inline int PACKET_get_length_prefixed_1(PACKET *pkt, PACKET *subpkt)
419 {
420   unsigned int length;
421   unsigned char *data;
422   PACKET tmp = *pkt;
423   if (!PACKET_get_1(&tmp, &length) ||
424       !PACKET_get_bytes(&tmp, &data, (size_t)length)) {
425       return 0;
426   }
427
428   *pkt = tmp;
429   subpkt->curr = data;
430   subpkt->remaining = length;
431
432   return 1;
433 }
434
435 /*
436  * Reads a variable-length vector prefixed with a two-byte length, and stores
437  * the contents in |subpkt|. |pkt| can equal |subpkt|.
438  * Data is not copied: the |subpkt| packet will share its underlying buffer with
439  * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|.
440  * Upon failure, the original |pkt| and |subpkt| are not modified.
441  */
442 __owur static inline int PACKET_get_length_prefixed_2(PACKET *pkt, PACKET *subpkt)
443 {
444   unsigned int length;
445   unsigned char *data;
446   PACKET tmp = *pkt;
447   if (!PACKET_get_net_2(&tmp, &length) ||
448       !PACKET_get_bytes(&tmp, &data, (size_t)length)) {
449       return 0;
450   }
451
452   *pkt = tmp;
453   subpkt->curr = data;
454   subpkt->remaining = length;
455
456   return 1;
457 }
458
459 /*
460  * Reads a variable-length vector prefixed with a three-byte length, and stores
461  * the contents in |subpkt|. |pkt| can equal |subpkt|.
462  * Data is not copied: the |subpkt| packet will share its underlying buffer with
463  * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|.
464  * Upon failure, the original |pkt| and |subpkt| are not modified.
465  */
466 __owur static inline int PACKET_get_length_prefixed_3(PACKET *pkt, PACKET *subpkt)
467 {
468   unsigned long length;
469   unsigned char *data;
470   PACKET tmp = *pkt;
471   if (!PACKET_get_net_3(&tmp, &length) ||
472       !PACKET_get_bytes(&tmp, &data, (size_t)length)) {
473       return 0;
474   }
475
476   *pkt = tmp;
477   subpkt->curr = data;
478   subpkt->remaining = length;
479
480   return 1;
481 }
482 # ifdef __cplusplus
483 }
484 # endif
485
486 #endif /* HEADER_PACKET_LOCL_H */