Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / third_party / boringssl / src / crypto / bytestring / cbs.c
1 /* Copyright (c) 2014, Google Inc.
2  *
3  * Permission to use, copy, modify, and/or distribute this software for any
4  * purpose with or without fee is hereby granted, provided that the above
5  * copyright notice and this permission notice appear in all copies.
6  *
7  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14
15 #include <openssl/buf.h>
16 #include <openssl/mem.h>
17 #include <openssl/bytestring.h>
18
19 #include <assert.h>
20 #include <string.h>
21
22 #include "internal.h"
23
24
25 void CBS_init(CBS *cbs, const uint8_t *data, size_t len) {
26   cbs->data = data;
27   cbs->len = len;
28 }
29
30 static int cbs_get(CBS *cbs, const uint8_t **p, size_t n) {
31   if (cbs->len < n) {
32     return 0;
33   }
34
35   *p = cbs->data;
36   cbs->data += n;
37   cbs->len -= n;
38   return 1;
39 }
40
41 int CBS_skip(CBS *cbs, size_t len) {
42   const uint8_t *dummy;
43   return cbs_get(cbs, &dummy, len);
44 }
45
46 const uint8_t *CBS_data(const CBS *cbs) {
47   return cbs->data;
48 }
49
50 size_t CBS_len(const CBS *cbs) {
51   return cbs->len;
52 }
53
54 int CBS_stow(const CBS *cbs, uint8_t **out_ptr, size_t *out_len) {
55   if (*out_ptr != NULL) {
56     OPENSSL_free(*out_ptr);
57     *out_ptr = NULL;
58   }
59   *out_len = 0;
60
61   if (cbs->len == 0) {
62     return 1;
63   }
64   *out_ptr = BUF_memdup(cbs->data, cbs->len);
65   if (*out_ptr == NULL) {
66     return 0;
67   }
68   *out_len = cbs->len;
69   return 1;
70 }
71
72 int CBS_strdup(const CBS *cbs, char **out_ptr) {
73   if (*out_ptr != NULL) {
74     OPENSSL_free(*out_ptr);
75   }
76   *out_ptr = BUF_strndup((const char*)cbs->data, cbs->len);
77   return (*out_ptr != NULL);
78 }
79
80 int CBS_contains_zero_byte(const CBS *cbs) {
81   return memchr(cbs->data, 0, cbs->len) != NULL;
82 }
83
84 int CBS_mem_equal(const CBS *cbs, const uint8_t *data, size_t len) {
85   if (len != cbs->len)
86     return 0;
87   return CRYPTO_memcmp(cbs->data, data, len) == 0;
88 }
89
90 static int cbs_get_u(CBS *cbs, uint32_t *out, size_t len) {
91   uint32_t result = 0;
92   size_t i;
93   const uint8_t *data;
94
95   if (!cbs_get(cbs, &data, len)) {
96     return 0;
97   }
98   for (i = 0; i < len; i++) {
99     result <<= 8;
100     result |= data[i];
101   }
102   *out = result;
103   return 1;
104 }
105
106 int CBS_get_u8(CBS *cbs, uint8_t *out) {
107   const uint8_t *v;
108   if (!cbs_get(cbs, &v, 1)) {
109     return 0;
110   }
111   *out = *v;
112   return 1;
113 }
114
115 int CBS_get_u16(CBS *cbs, uint16_t *out) {
116   uint32_t v;
117   if (!cbs_get_u(cbs, &v, 2)) {
118     return 0;
119   }
120   *out = v;
121   return 1;
122 }
123
124 int CBS_get_u24(CBS *cbs, uint32_t *out) {
125   return cbs_get_u(cbs, out, 3);
126 }
127
128 int CBS_get_u32(CBS *cbs, uint32_t *out) {
129   return cbs_get_u(cbs, out, 4);
130 }
131
132 int CBS_get_bytes(CBS *cbs, CBS *out, size_t len) {
133   const uint8_t *v;
134   if (!cbs_get(cbs, &v, len)) {
135     return 0;
136   }
137   CBS_init(out, v, len);
138   return 1;
139 }
140
141 static int cbs_get_length_prefixed(CBS *cbs, CBS *out, size_t len_len) {
142   uint32_t len;
143   if (!cbs_get_u(cbs, &len, len_len)) {
144     return 0;
145   }
146   return CBS_get_bytes(cbs, out, len);
147 }
148
149 int CBS_get_u8_length_prefixed(CBS *cbs, CBS *out) {
150   return cbs_get_length_prefixed(cbs, out, 1);
151 }
152
153 int CBS_get_u16_length_prefixed(CBS *cbs, CBS *out) {
154   return cbs_get_length_prefixed(cbs, out, 2);
155 }
156
157 int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out) {
158   return cbs_get_length_prefixed(cbs, out, 3);
159 }
160
161 int CBS_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
162                              size_t *out_header_len) {
163   uint8_t tag, length_byte;
164   CBS header = *cbs;
165   CBS throwaway;
166
167   if (out == NULL) {
168     out = &throwaway;
169   }
170
171   if (!CBS_get_u8(&header, &tag) ||
172       !CBS_get_u8(&header, &length_byte)) {
173     return 0;
174   }
175
176   if ((tag & 0x1f) == 0x1f) {
177     /* Long form tags are not supported. */
178     return 0;
179   }
180
181   if (out_tag != NULL) {
182     *out_tag = tag;
183   }
184
185   size_t len;
186   if ((length_byte & 0x80) == 0) {
187     /* Short form length. */
188     len = ((size_t) length_byte) + 2;
189     if (out_header_len != NULL) {
190       *out_header_len = 2;
191     }
192   } else {
193     /* Long form length. */
194     const size_t num_bytes = length_byte & 0x7f;
195     uint32_t len32;
196
197     if ((tag & CBS_ASN1_CONSTRUCTED) != 0 && num_bytes == 0) {
198       /* indefinite length */
199       *out_header_len = 2;
200       return CBS_get_bytes(cbs, out, 2);
201     }
202
203     if (num_bytes == 0 || num_bytes > 4) {
204       return 0;
205     }
206     if (!cbs_get_u(&header, &len32, num_bytes)) {
207       return 0;
208     }
209     if (len32 < 128) {
210       /* Length should have used short-form encoding. */
211       return 0;
212     }
213     if ((len32 >> ((num_bytes-1)*8)) == 0) {
214       /* Length should have been at least one byte shorter. */
215       return 0;
216     }
217     len = len32;
218     if (len + 2 + num_bytes < len) {
219       /* Overflow. */
220       return 0;
221     }
222     len += 2 + num_bytes;
223     if (out_header_len != NULL) {
224       *out_header_len = 2 + num_bytes;
225     }
226   }
227
228   return CBS_get_bytes(cbs, out, len);
229 }
230
231 static int cbs_get_asn1(CBS *cbs, CBS *out, unsigned tag_value,
232                         int skip_header) {
233   size_t header_len;
234   unsigned tag;
235   CBS throwaway;
236
237   if (out == NULL) {
238     out = &throwaway;
239   }
240
241   if (!CBS_get_any_asn1_element(cbs, out, &tag, &header_len) ||
242       tag != tag_value ||
243       (header_len > 0 &&
244        /* This ensures that the tag is either zero length or
245         * indefinite-length. */
246        CBS_len(out) == header_len &&
247        CBS_data(out)[header_len - 1] == 0x80)) {
248     return 0;
249   }
250
251   if (skip_header && !CBS_skip(out, header_len)) {
252     assert(0);
253     return 0;
254   }
255
256   return 1;
257 }
258
259 int CBS_get_asn1(CBS *cbs, CBS *out, unsigned tag_value) {
260   return cbs_get_asn1(cbs, out, tag_value, 1 /* skip header */);
261 }
262
263 int CBS_get_asn1_element(CBS *cbs, CBS *out, unsigned tag_value) {
264   return cbs_get_asn1(cbs, out, tag_value, 0 /* include header */);
265 }
266
267 int CBS_peek_asn1_tag(const CBS *cbs, unsigned tag_value) {
268   if (CBS_len(cbs) < 1) {
269     return 0;
270   }
271   return CBS_data(cbs)[0] == tag_value;
272 }
273
274 int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out) {
275   CBS bytes;
276   const uint8_t *data;
277   size_t i, len;
278
279   if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_INTEGER)) {
280     return 0;
281   }
282
283   *out = 0;
284   data = CBS_data(&bytes);
285   len = CBS_len(&bytes);
286
287   if (len == 0) {
288     /* An INTEGER is encoded with at least one octet. */
289     return 0;
290   }
291
292   if ((data[0] & 0x80) != 0) {
293     /* negative number */
294     return 0;
295   }
296
297   for (i = 0; i < len; i++) {
298     if ((*out >> 56) != 0) {
299       /* Too large to represent as a uint64_t. */
300       return 0;
301     }
302     *out <<= 8;
303     *out |= data[i];
304   }
305
306   return 1;
307 }
308
309 int CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present, unsigned tag) {
310   if (CBS_peek_asn1_tag(cbs, tag)) {
311     if (!CBS_get_asn1(cbs, out, tag)) {
312       return 0;
313     }
314     *out_present = 1;
315   } else {
316     *out_present = 0;
317   }
318   return 1;
319 }
320
321 int CBS_get_optional_asn1_octet_string(CBS *cbs, CBS *out, int *out_present,
322                                        unsigned tag) {
323   CBS child;
324   int present;
325   if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) {
326     return 0;
327   }
328   if (present) {
329     if (!CBS_get_asn1(&child, out, CBS_ASN1_OCTETSTRING) ||
330         CBS_len(&child) != 0) {
331       return 0;
332     }
333   } else {
334     CBS_init(out, NULL, 0);
335   }
336   if (out_present) {
337     *out_present = present;
338   }
339   return 1;
340 }
341
342 int CBS_get_optional_asn1_uint64(CBS *cbs, uint64_t *out, unsigned tag,
343                                  uint64_t default_value) {
344   CBS child;
345   int present;
346   if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) {
347     return 0;
348   }
349   if (present) {
350     if (!CBS_get_asn1_uint64(&child, out) ||
351         CBS_len(&child) != 0) {
352       return 0;
353     }
354   } else {
355     *out = default_value;
356   }
357   return 1;
358 }
359
360 int CBS_get_optional_asn1_bool(CBS *cbs, int *out, unsigned tag,
361                                int default_value) {
362   CBS child, child2;
363   int present;
364   if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) {
365     return 0;
366   }
367   if (present) {
368     uint8_t boolean;
369
370     if (!CBS_get_asn1(&child, &child2, CBS_ASN1_BOOLEAN) ||
371         CBS_len(&child2) != 1 ||
372         CBS_len(&child) != 0) {
373       return 0;
374     }
375
376     boolean = CBS_data(&child2)[0];
377     if (boolean == 0) {
378       *out = 0;
379     } else if (boolean == 0xff) {
380       *out = 1;
381     } else {
382       return 0;
383     }
384   } else {
385     *out = default_value;
386   }
387   return 1;
388 }