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