Upstream version 9.38.198.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
23 void CBS_init(CBS *cbs, const uint8_t *data, size_t len) {
24   cbs->data = data;
25   cbs->len = len;
26 }
27
28 static int cbs_get(CBS *cbs, const uint8_t **p, size_t n) {
29   if (cbs->len < n) {
30     return 0;
31   }
32
33   *p = cbs->data;
34   cbs->data += n;
35   cbs->len -= n;
36   return 1;
37 }
38
39 int CBS_skip(CBS *cbs, size_t len) {
40   const uint8_t *dummy;
41   return cbs_get(cbs, &dummy, len);
42 }
43
44 const uint8_t *CBS_data(const CBS *cbs) {
45   return cbs->data;
46 }
47
48 size_t CBS_len(const CBS *cbs) {
49   return cbs->len;
50 }
51
52 int CBS_stow(const CBS *cbs, uint8_t **out_ptr, size_t *out_len) {
53   if (*out_ptr != NULL) {
54     OPENSSL_free(*out_ptr);
55     *out_ptr = NULL;
56   }
57   *out_len = 0;
58
59   if (cbs->len == 0) {
60     return 1;
61   }
62   *out_ptr = BUF_memdup(cbs->data, cbs->len);
63   if (*out_ptr == NULL) {
64     return 0;
65   }
66   *out_len = cbs->len;
67   return 1;
68 }
69
70 int CBS_strdup(const CBS *cbs, char **out_ptr) {
71   if (*out_ptr != NULL) {
72     OPENSSL_free(*out_ptr);
73   }
74   *out_ptr = BUF_strndup((const char*)cbs->data, cbs->len);
75   return (*out_ptr != NULL);
76 }
77
78 int CBS_contains_zero_byte(const CBS *cbs) {
79   return memchr(cbs->data, 0, cbs->len) != NULL;
80 }
81
82 int CBS_mem_equal(const CBS *cbs, const uint8_t *data, size_t len) {
83   if (len != cbs->len)
84     return 0;
85   return CRYPTO_memcmp(cbs->data, data, len) == 0;
86 }
87
88 static int cbs_get_u(CBS *cbs, uint32_t *out, size_t len) {
89   uint32_t result = 0;
90   size_t i;
91   const uint8_t *data;
92
93   if (!cbs_get(cbs, &data, len)) {
94     return 0;
95   }
96   for (i = 0; i < len; i++) {
97     result <<= 8;
98     result |= data[i];
99   }
100   *out = result;
101   return 1;
102 }
103
104 int CBS_get_u8(CBS *cbs, uint8_t *out) {
105   const uint8_t *v;
106   if (!cbs_get(cbs, &v, 1)) {
107     return 0;
108   }
109   *out = *v;
110   return 1;
111 }
112
113 int CBS_get_u16(CBS *cbs, uint16_t *out) {
114   uint32_t v;
115   if (!cbs_get_u(cbs, &v, 2)) {
116     return 0;
117   }
118   *out = v;
119   return 1;
120 }
121
122 int CBS_get_u24(CBS *cbs, uint32_t *out) {
123   return cbs_get_u(cbs, out, 3);
124 }
125
126 int CBS_get_u32(CBS *cbs, uint32_t *out) {
127   return cbs_get_u(cbs, out, 4);
128 }
129
130 int CBS_get_bytes(CBS *cbs, CBS *out, size_t len) {
131   const uint8_t *v;
132   if (!cbs_get(cbs, &v, len)) {
133     return 0;
134   }
135   CBS_init(out, v, len);
136   return 1;
137 }
138
139 static int cbs_get_length_prefixed(CBS *cbs, CBS *out, size_t len_len) {
140   uint32_t len;
141   if (!cbs_get_u(cbs, &len, len_len)) {
142     return 0;
143   }
144   return CBS_get_bytes(cbs, out, len);
145 }
146
147 int CBS_get_u8_length_prefixed(CBS *cbs, CBS *out) {
148   return cbs_get_length_prefixed(cbs, out, 1);
149 }
150
151 int CBS_get_u16_length_prefixed(CBS *cbs, CBS *out) {
152   return cbs_get_length_prefixed(cbs, out, 2);
153 }
154
155 int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out) {
156   return cbs_get_length_prefixed(cbs, out, 3);
157 }
158
159 static int cbs_get_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
160                                 size_t *out_header_len, unsigned depth,
161                                 int *was_indefinite_len);
162
163 /* cbs_get_asn1_indefinite_len sets |*out| to be a CBS that covers an
164  * indefinite length element in |cbs| and advances |*in|. On entry, |cbs| will
165  * not have had the tag and length byte removed. On exit, |*out| does not cover
166  * the EOC element, but |*in| is skipped over it.
167  *
168  * The |depth| argument counts the number of times the code has recursed trying
169  * to find an indefinite length. */
170 static int cbs_get_asn1_indefinite_len(CBS *in, CBS *out, unsigned depth) {
171   static const size_t kEOCLength = 2;
172   size_t header_len;
173   unsigned tag;
174   int was_indefinite_len;
175   CBS orig = *in, child;
176
177   if (!CBS_skip(in, 2 /* tag plus 0x80 byte for indefinite len */)) {
178     return 0;
179   }
180
181   for (;;) {
182     if (!cbs_get_asn1_element(in, &child, &tag, &header_len, depth + 1,
183                               &was_indefinite_len)) {
184       return 0;
185     }
186
187     if (!was_indefinite_len && CBS_len(&child) == kEOCLength &&
188         header_len == kEOCLength && tag == 0) {
189       break;
190     }
191   }
192
193   return CBS_get_bytes(&orig, out, CBS_len(&orig) - CBS_len(in) - kEOCLength);
194 }
195
196 /* MAX_DEPTH the maximum number of levels of indefinite lengths that we'll
197  * support. */
198 #define MAX_DEPTH 64
199
200 static int cbs_get_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
201                                 size_t *out_header_len, unsigned depth,
202                                 int *was_indefinite_len) {
203   uint8_t tag, length_byte;
204   CBS header = *cbs;
205   if (!CBS_get_u8(&header, &tag) ||
206       !CBS_get_u8(&header, &length_byte)) {
207     return 0;
208   }
209
210   if ((tag & 0x1f) == 0x1f) {
211     /* Long form tags are not supported. */
212     return 0;
213   }
214
215   *out_tag = tag;
216   if (was_indefinite_len) {
217     *was_indefinite_len = 0;
218   }
219
220   size_t len;
221   if ((length_byte & 0x80) == 0) {
222     /* Short form length. */
223     len = ((size_t) length_byte) + 2;
224     *out_header_len = 2;
225   } else {
226     /* Long form length. */
227     const size_t num_bytes = length_byte & 0x7f;
228     uint32_t len32;
229
230     if (depth < MAX_DEPTH && num_bytes == 0) {
231       /* indefinite length */
232       *out_header_len = 2;
233       if (was_indefinite_len) {
234         *was_indefinite_len = 1;
235       }
236       return cbs_get_asn1_indefinite_len(cbs, out, depth);
237     }
238
239     if (num_bytes == 0 || num_bytes > 4) {
240       return 0;
241     }
242     if (!cbs_get_u(&header, &len32, num_bytes)) {
243       return 0;
244     }
245     if (len32 < 128) {
246       /* Length should have used short-form encoding. */
247       return 0;
248     }
249     if ((len32 >> ((num_bytes-1)*8)) == 0) {
250       /* Length should have been at least one byte shorter. */
251       return 0;
252     }
253     len = len32;
254     if (len + 2 + num_bytes < len) {
255       /* Overflow. */
256       return 0;
257     }
258     len += 2 + num_bytes;
259     *out_header_len = 2 + num_bytes;
260   }
261
262   return CBS_get_bytes(cbs, out, len);
263 }
264
265 static int cbs_get_asn1(CBS *cbs, CBS *out, unsigned tag_value, int ber,
266                         int skip_header) {
267   size_t header_len;
268   unsigned tag;
269   CBS throwaway;
270
271   if (out == NULL) {
272     out = &throwaway;
273   }
274
275   if (!cbs_get_asn1_element(cbs, out, &tag, &header_len, ber ? 0 : MAX_DEPTH,
276                             NULL) ||
277       tag != tag_value) {
278     return 0;
279   }
280
281   if (skip_header && !CBS_skip(out, header_len)) {
282     assert(0);
283     return 0;
284   }
285
286   return 1;
287 }
288
289 int CBS_get_asn1(CBS *cbs, CBS *out, unsigned tag_value) {
290   return cbs_get_asn1(cbs, out, tag_value, 0 /* DER */,
291                       1 /* skip header */);
292 }
293
294 int CBS_get_asn1_ber(CBS *cbs, CBS *out, unsigned tag_value) {
295   return cbs_get_asn1(cbs, out, tag_value, 1 /* BER */,
296                       1 /* skip header */);
297 }
298
299 int CBS_get_asn1_element(CBS *cbs, CBS *out, unsigned tag_value) {
300   return cbs_get_asn1(cbs, out, tag_value, 0 /* DER */,
301                       0 /* include header */);
302 }