48a5f3d7dc9c7cbd796b9b419bb0b66d07e29224
[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 <openssl/crypto.h>
66 # include <openssl/e_os2.h>
67
68 # ifdef __cplusplus
69 extern "C" {
70 # endif
71
72 typedef struct {
73     /* Pointer to where we are currently reading from */
74     unsigned char *curr;
75     /* Number of bytes remaining */
76     size_t remaining;
77 } PACKET;
78
79 /* Internal unchecked shorthand; don't use outside this file. */
80 static ossl_inline void packet_forward(PACKET *pkt, size_t len)
81 {
82     pkt->curr += len;
83     pkt->remaining -= len;
84 }
85
86 /*
87  * Returns the number of bytes remaining to be read in the PACKET
88  */
89 static ossl_inline size_t PACKET_remaining(const PACKET *pkt)
90 {
91     return pkt->remaining;
92 }
93
94 /*
95  * Returns a pointer to the PACKET's current position.
96  * For use in non-PACKETized APIs.
97  * TODO(openssl-team): this should return 'const unsigned char*' but can't
98  * currently because legacy code passes 'unsigned char*'s around.
99  */
100 static ossl_inline unsigned char *PACKET_data(const PACKET *pkt)
101 {
102     return pkt->curr;
103 }
104
105 /*
106  * Initialise a PACKET with |len| bytes held in |buf|. This does not make a
107  * copy of the data so |buf| must be present for the whole time that the PACKET
108  * is being used.
109  */
110 __owur static ossl_inline int PACKET_buf_init(PACKET *pkt, unsigned char *buf,
111                                               size_t len)
112 {
113     /* Sanity check for negative values. */
114 #ifdef SIZE_MAX
115     if (len > (size_t)(SIZE_MAX / 2))
116         return 0;
117 #else
118     if (len > ((size_t)2 << (sizeof(size_t) * 8 - 1)))
119         return 0;
120 #endif
121
122     pkt->curr = buf;
123     pkt->remaining = len;
124     return 1;
125 }
126
127 /* Initialize a PACKET to hold zero bytes. */
128 static ossl_inline void PACKET_null_init(PACKET *pkt)
129 {
130     pkt->curr = NULL;
131     pkt->remaining = 0;
132 }
133
134 /*
135  * Returns 1 if the packet has length |num| and its contents equal the |num|
136  * bytes read from |ptr|. Returns 0 otherwise (lengths or contents not equal).
137  * If lengths are equal, performs the comparison in constant time.
138  */
139 __owur static ossl_inline int PACKET_equal(const PACKET *pkt, const void *ptr,
140                                            size_t num)
141 {
142     if (PACKET_remaining(pkt) != num)
143         return 0;
144     return CRYPTO_memcmp(pkt->curr, ptr, num) == 0;
145 }
146
147 /*
148  * Peek ahead and initialize |subpkt| with the next |len| bytes read from |pkt|.
149  * Data is not copied: the |subpkt| packet will share its underlying buffer with
150  * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|.
151  */
152 __owur static ossl_inline int PACKET_peek_sub_packet(const PACKET *pkt,
153                                                      PACKET *subpkt,
154                                                      size_t len)
155 {
156     if (PACKET_remaining(pkt) < len)
157         return 0;
158
159     return PACKET_buf_init(subpkt, pkt->curr, len);
160 }
161
162 /*
163  * Initialize |subpkt| with the next |len| bytes read from |pkt|. Data is not
164  * copied: the |subpkt| packet will share its underlying buffer with the
165  * original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|.
166  */
167 __owur static ossl_inline int PACKET_get_sub_packet(PACKET *pkt,
168                                                     PACKET *subpkt,
169                                                     size_t len)
170 {
171     if (!PACKET_peek_sub_packet(pkt, subpkt, len))
172         return 0;
173
174     packet_forward(pkt, len);
175
176     return 1;
177 }
178
179 /*
180  * Peek ahead at 2 bytes in network order from |pkt| and store the value in
181  * |*data|
182  */
183 __owur static ossl_inline int PACKET_peek_net_2(const PACKET *pkt,
184                                                 unsigned int *data)
185 {
186     if (PACKET_remaining(pkt) < 2)
187         return 0;
188
189     *data = ((unsigned int)(*pkt->curr)) << 8;
190     *data |= *(pkt->curr + 1);
191
192     return 1;
193 }
194
195 /* Equivalent of n2s */
196 /* Get 2 bytes in network order from |pkt| and store the value in |*data| */
197 __owur static ossl_inline int PACKET_get_net_2(PACKET *pkt,
198                                                unsigned int *data)
199 {
200     if (!PACKET_peek_net_2(pkt, data))
201         return 0;
202
203     packet_forward(pkt, 2);
204
205     return 1;
206 }
207
208 /*
209  * Peek ahead at 3 bytes in network order from |pkt| and store the value in
210  * |*data|
211  */
212 __owur static ossl_inline int PACKET_peek_net_3(const PACKET *pkt,
213                                                 unsigned long *data)
214 {
215     if (PACKET_remaining(pkt) < 3)
216         return 0;
217
218     *data = ((unsigned long)(*pkt->curr)) << 16;
219     *data |= ((unsigned long)(*(pkt->curr + 1))) << 8;
220     *data |= *(pkt->curr + 2);
221
222     return 1;
223 }
224
225 /* Equivalent of n2l3 */
226 /* Get 3 bytes in network order from |pkt| and store the value in |*data| */
227 __owur static ossl_inline int PACKET_get_net_3(PACKET *pkt,
228                                                unsigned long *data)
229 {
230     if (!PACKET_peek_net_3(pkt, data))
231         return 0;
232
233     packet_forward(pkt, 3);
234
235     return 1;
236 }
237
238 /*
239  * Peek ahead at 4 bytes in network order from |pkt| and store the value in
240  * |*data|
241  */
242 __owur static ossl_inline int PACKET_peek_net_4(const PACKET *pkt,
243                                                 unsigned long *data)
244 {
245     if (PACKET_remaining(pkt) < 4)
246         return 0;
247
248     *data = ((unsigned long)(*pkt->curr)) << 24;
249     *data |= ((unsigned long)(*(pkt->curr + 1))) << 16;
250     *data |= ((unsigned long)(*(pkt->curr + 2))) << 8;
251     *data |= *(pkt->curr + 3);
252
253     return 1;
254 }
255
256 /* Equivalent of n2l */
257 /* Get 4 bytes in network order from |pkt| and store the value in |*data| */
258 __owur static ossl_inline int PACKET_get_net_4(PACKET *pkt,
259                                                unsigned long *data)
260 {
261     if (!PACKET_peek_net_4(pkt, data))
262         return 0;
263
264     packet_forward(pkt, 4);
265
266     return 1;
267 }
268
269 /* Peek ahead at 1 byte from |pkt| and store the value in |*data| */
270 __owur static ossl_inline int PACKET_peek_1(const PACKET *pkt,
271                                             unsigned int *data)
272 {
273     if (!PACKET_remaining(pkt))
274         return 0;
275
276     *data = *pkt->curr;
277
278     return 1;
279 }
280
281 /* Get 1 byte from |pkt| and store the value in |*data| */
282 __owur static ossl_inline int PACKET_get_1(PACKET *pkt, unsigned int *data)
283 {
284     if (!PACKET_peek_1(pkt, data))
285         return 0;
286
287     packet_forward(pkt, 1);
288
289     return 1;
290 }
291
292 /*
293  * Peek ahead at 4 bytes in reverse network order from |pkt| and store the value
294  * in |*data|
295  */
296 __owur static ossl_inline int PACKET_peek_4(const PACKET *pkt,
297                                             unsigned long *data)
298 {
299     if (PACKET_remaining(pkt) < 4)
300         return 0;
301
302     *data = *pkt->curr;
303     *data |= ((unsigned long)(*(pkt->curr + 1))) << 8;
304     *data |= ((unsigned long)(*(pkt->curr + 2))) << 16;
305     *data |= ((unsigned long)(*(pkt->curr + 3))) << 24;
306
307     return 1;
308 }
309
310 /* Equivalent of c2l */
311 /*
312  * Get 4 bytes in reverse network order from |pkt| and store the value in
313  * |*data|
314  */
315 __owur static ossl_inline int PACKET_get_4(PACKET *pkt, unsigned long *data)
316 {
317     if (!PACKET_peek_4(pkt, data))
318         return 0;
319
320     packet_forward(pkt, 4);
321
322     return 1;
323 }
324
325 /*
326  * Peek ahead at |len| bytes from the |pkt| and store a pointer to them in
327  * |*data|. This just points at the underlying buffer that |pkt| is using. The
328  * caller should not free this data directly (it will be freed when the
329  * underlying buffer gets freed
330  */
331 __owur static ossl_inline int PACKET_peek_bytes(const PACKET *pkt,
332                                                 unsigned char **data,
333                                                 size_t len)
334 {
335     if (PACKET_remaining(pkt) < len)
336         return 0;
337
338     *data = pkt->curr;
339
340     return 1;
341 }
342
343 /*
344  * Read |len| bytes from the |pkt| and store a pointer to them in |*data|. This
345  * just points at the underlying buffer that |pkt| is using. The caller should
346  * not free this data directly (it will be freed when the underlying buffer gets
347  * freed
348  */
349 __owur static ossl_inline int PACKET_get_bytes(PACKET *pkt,
350                                                unsigned char **data,
351                                                size_t len)
352 {
353     if (!PACKET_peek_bytes(pkt, data, len))
354         return 0;
355
356     packet_forward(pkt, len);
357
358     return 1;
359 }
360
361 /* Peek ahead at |len| bytes from |pkt| and copy them to |data| */
362 __owur static ossl_inline int PACKET_peek_copy_bytes(const PACKET *pkt,
363                                                      unsigned char *data,
364                                                      size_t len)
365 {
366     if (PACKET_remaining(pkt) < len)
367         return 0;
368
369     memcpy(data, pkt->curr, len);
370
371     return 1;
372 }
373
374 /*
375  * Read |len| bytes from |pkt| and copy them to |data|.
376  * The caller is responsible for ensuring that |data| can hold |len| bytes.
377  */
378 __owur static ossl_inline int PACKET_copy_bytes(PACKET *pkt,
379                                                 unsigned char *data,
380                                                 size_t len)
381 {
382     if (!PACKET_peek_copy_bytes(pkt, data, len))
383         return 0;
384
385     packet_forward(pkt, len);
386
387     return 1;
388 }
389
390 /*
391  * Copy packet data to |dest|, and set |len| to the number of copied bytes.
392  * If the packet has more than |dest_len| bytes, nothing is copied.
393  * Returns 1 if the packet data fits in |dest_len| bytes, 0 otherwise.
394  * Does not forward PACKET position (because it is typically the last thing
395  * done with a given PACKET).
396  */
397 __owur static ossl_inline int PACKET_copy_all(const PACKET *pkt,
398                                               unsigned char *dest,
399                                               size_t dest_len, size_t *len)
400 {
401     if (PACKET_remaining(pkt) > dest_len) {
402         *len = 0;
403         return 0;
404     }
405     *len = pkt->remaining;
406     memcpy(dest, pkt->curr, pkt->remaining);
407     return 1;
408 }
409
410 /*
411  * Copy |pkt| bytes to a newly allocated buffer and store a pointer to the
412  * result in |*data|, and the length in |len|.
413  * If |*data| is not NULL, the old data is OPENSSL_free'd.
414  * If the packet is empty, or malloc fails, |*data| will be set to NULL.
415  * Returns 1 if the malloc succeeds and 0 otherwise.
416  * Does not forward PACKET position (because it is typically the last thing
417  * done with a given PACKET).
418  */
419 __owur static ossl_inline int PACKET_memdup(const PACKET *pkt,
420                                             unsigned char **data, size_t *len)
421 {
422     size_t length;
423
424     OPENSSL_free(*data);
425     *data = NULL;
426     *len = 0;
427
428     length = PACKET_remaining(pkt);
429
430     if (length == 0)
431         return 1;
432
433     *data = OPENSSL_memdup(pkt->curr, length);
434     if (*data == NULL)
435         return 0;
436
437     *len = length;
438     return 1;
439 }
440
441 /*
442  * Read a C string from |pkt| and copy to a newly allocated, NUL-terminated
443  * buffer. Store a pointer to the result in |*data|.
444  * If |*data| is not NULL, the old data is OPENSSL_free'd.
445  * If the data in |pkt| does not contain a NUL-byte, the entire data is
446  * copied and NUL-terminated.
447  * Returns 1 if the malloc succeeds and 0 otherwise.
448  * Does not forward PACKET position (because it is typically the last thing done
449  * with a given PACKET).
450  */
451 __owur static ossl_inline int PACKET_strndup(const PACKET *pkt, char **data)
452 {
453     OPENSSL_free(*data);
454
455     /* This will succeed on an empty packet, unless pkt->curr == NULL. */
456     *data = OPENSSL_strndup((const char *)pkt->curr, PACKET_remaining(pkt));
457     return (*data != NULL);
458 }
459
460 /* Move the current reading position forward |len| bytes */
461 __owur static ossl_inline int PACKET_forward(PACKET *pkt, size_t len)
462 {
463     if (PACKET_remaining(pkt) < len)
464         return 0;
465
466     packet_forward(pkt, len);
467
468     return 1;
469 }
470
471 /*
472  * Reads a variable-length vector prefixed with a one-byte length, and stores
473  * the contents in |subpkt|. |pkt| can equal |subpkt|.
474  * Data is not copied: the |subpkt| packet will share its underlying buffer with
475  * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|.
476  * Upon failure, the original |pkt| and |subpkt| are not modified.
477  */
478 __owur static ossl_inline int PACKET_get_length_prefixed_1(PACKET *pkt,
479                                                            PACKET *subpkt)
480 {
481     unsigned int length;
482     unsigned char *data;
483     PACKET tmp = *pkt;
484     if (!PACKET_get_1(&tmp, &length) ||
485         !PACKET_get_bytes(&tmp, &data, (size_t)length)) {
486         return 0;
487     }
488
489     *pkt = tmp;
490     subpkt->curr = data;
491     subpkt->remaining = length;
492
493     return 1;
494 }
495
496 /*
497  * Reads a variable-length vector prefixed with a two-byte length, and stores
498  * the contents in |subpkt|. |pkt| can equal |subpkt|.
499  * Data is not copied: the |subpkt| packet will share its underlying buffer with
500  * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|.
501  * Upon failure, the original |pkt| and |subpkt| are not modified.
502  */
503 __owur static ossl_inline int PACKET_get_length_prefixed_2(PACKET *pkt,
504                                                            PACKET *subpkt)
505 {
506     unsigned int length;
507     unsigned char *data;
508     PACKET tmp = *pkt;
509     if (!PACKET_get_net_2(&tmp, &length) ||
510         !PACKET_get_bytes(&tmp, &data, (size_t)length)) {
511         return 0;
512     }
513
514     *pkt = tmp;
515     subpkt->curr = data;
516     subpkt->remaining = length;
517
518     return 1;
519 }
520
521 /*
522  * Reads a variable-length vector prefixed with a three-byte length, and stores
523  * the contents in |subpkt|. |pkt| can equal |subpkt|.
524  * Data is not copied: the |subpkt| packet will share its underlying buffer with
525  * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|.
526  * Upon failure, the original |pkt| and |subpkt| are not modified.
527  */
528 __owur static ossl_inline int PACKET_get_length_prefixed_3(PACKET *pkt,
529                                                            PACKET *subpkt)
530 {
531     unsigned long length;
532     unsigned char *data;
533     PACKET tmp = *pkt;
534     if (!PACKET_get_net_3(&tmp, &length) ||
535         !PACKET_get_bytes(&tmp, &data, (size_t)length)) {
536         return 0;
537     }
538
539     *pkt = tmp;
540     subpkt->curr = data;
541     subpkt->remaining = length;
542
543     return 1;
544 }
545 # ifdef __cplusplus
546 }
547 # endif
548
549 #endif                          /* HEADER_PACKET_LOCL_H */