• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "../internal.h"
24 
25 
CBS_init(CBS * cbs,const uint8_t * data,size_t len)26 void CBS_init(CBS *cbs, const uint8_t *data, size_t len) {
27   cbs->data = data;
28   cbs->len = len;
29 }
30 
cbs_get(CBS * cbs,const uint8_t ** p,size_t n)31 static int cbs_get(CBS *cbs, const uint8_t **p, size_t n) {
32   if (cbs->len < n) {
33     return 0;
34   }
35 
36   *p = cbs->data;
37   cbs->data += n;
38   cbs->len -= n;
39   return 1;
40 }
41 
CBS_skip(CBS * cbs,size_t len)42 int CBS_skip(CBS *cbs, size_t len) {
43   const uint8_t *dummy;
44   return cbs_get(cbs, &dummy, len);
45 }
46 
CBS_data(const CBS * cbs)47 const uint8_t *CBS_data(const CBS *cbs) {
48   return cbs->data;
49 }
50 
CBS_len(const CBS * cbs)51 size_t CBS_len(const CBS *cbs) {
52   return cbs->len;
53 }
54 
CBS_stow(const CBS * cbs,uint8_t ** out_ptr,size_t * out_len)55 int CBS_stow(const CBS *cbs, uint8_t **out_ptr, size_t *out_len) {
56   OPENSSL_free(*out_ptr);
57   *out_ptr = NULL;
58   *out_len = 0;
59 
60   if (cbs->len == 0) {
61     return 1;
62   }
63   *out_ptr = BUF_memdup(cbs->data, cbs->len);
64   if (*out_ptr == NULL) {
65     return 0;
66   }
67   *out_len = cbs->len;
68   return 1;
69 }
70 
CBS_strdup(const CBS * cbs,char ** out_ptr)71 int CBS_strdup(const CBS *cbs, char **out_ptr) {
72   if (*out_ptr != NULL) {
73     OPENSSL_free(*out_ptr);
74   }
75   *out_ptr = BUF_strndup((const char*)cbs->data, cbs->len);
76   return (*out_ptr != NULL);
77 }
78 
CBS_contains_zero_byte(const CBS * cbs)79 int CBS_contains_zero_byte(const CBS *cbs) {
80   return OPENSSL_memchr(cbs->data, 0, cbs->len) != NULL;
81 }
82 
CBS_mem_equal(const CBS * cbs,const uint8_t * data,size_t len)83 int CBS_mem_equal(const CBS *cbs, const uint8_t *data, size_t len) {
84   if (len != cbs->len) {
85     return 0;
86   }
87   return CRYPTO_memcmp(cbs->data, data, len) == 0;
88 }
89 
cbs_get_u(CBS * cbs,uint32_t * out,size_t len)90 static int cbs_get_u(CBS *cbs, uint32_t *out, size_t len) {
91   uint32_t result = 0;
92   const uint8_t *data;
93 
94   if (!cbs_get(cbs, &data, len)) {
95     return 0;
96   }
97   for (size_t i = 0; i < len; i++) {
98     result <<= 8;
99     result |= data[i];
100   }
101   *out = result;
102   return 1;
103 }
104 
CBS_get_u8(CBS * cbs,uint8_t * out)105 int CBS_get_u8(CBS *cbs, uint8_t *out) {
106   const uint8_t *v;
107   if (!cbs_get(cbs, &v, 1)) {
108     return 0;
109   }
110   *out = *v;
111   return 1;
112 }
113 
CBS_get_u16(CBS * cbs,uint16_t * out)114 int CBS_get_u16(CBS *cbs, uint16_t *out) {
115   uint32_t v;
116   if (!cbs_get_u(cbs, &v, 2)) {
117     return 0;
118   }
119   *out = v;
120   return 1;
121 }
122 
CBS_get_u24(CBS * cbs,uint32_t * out)123 int CBS_get_u24(CBS *cbs, uint32_t *out) {
124   return cbs_get_u(cbs, out, 3);
125 }
126 
CBS_get_u32(CBS * cbs,uint32_t * out)127 int CBS_get_u32(CBS *cbs, uint32_t *out) {
128   return cbs_get_u(cbs, out, 4);
129 }
130 
CBS_get_last_u8(CBS * cbs,uint8_t * out)131 int CBS_get_last_u8(CBS *cbs, uint8_t *out) {
132   if (cbs->len == 0) {
133     return 0;
134   }
135   *out = cbs->data[cbs->len - 1];
136   cbs->len--;
137   return 1;
138 }
139 
CBS_get_bytes(CBS * cbs,CBS * out,size_t len)140 int CBS_get_bytes(CBS *cbs, CBS *out, size_t len) {
141   const uint8_t *v;
142   if (!cbs_get(cbs, &v, len)) {
143     return 0;
144   }
145   CBS_init(out, v, len);
146   return 1;
147 }
148 
CBS_copy_bytes(CBS * cbs,uint8_t * out,size_t len)149 int CBS_copy_bytes(CBS *cbs, uint8_t *out, size_t len) {
150   const uint8_t *v;
151   if (!cbs_get(cbs, &v, len)) {
152     return 0;
153   }
154   OPENSSL_memcpy(out, v, len);
155   return 1;
156 }
157 
cbs_get_length_prefixed(CBS * cbs,CBS * out,size_t len_len)158 static int cbs_get_length_prefixed(CBS *cbs, CBS *out, size_t len_len) {
159   uint32_t len;
160   if (!cbs_get_u(cbs, &len, len_len)) {
161     return 0;
162   }
163   return CBS_get_bytes(cbs, out, len);
164 }
165 
CBS_get_u8_length_prefixed(CBS * cbs,CBS * out)166 int CBS_get_u8_length_prefixed(CBS *cbs, CBS *out) {
167   return cbs_get_length_prefixed(cbs, out, 1);
168 }
169 
CBS_get_u16_length_prefixed(CBS * cbs,CBS * out)170 int CBS_get_u16_length_prefixed(CBS *cbs, CBS *out) {
171   return cbs_get_length_prefixed(cbs, out, 2);
172 }
173 
CBS_get_u24_length_prefixed(CBS * cbs,CBS * out)174 int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out) {
175   return cbs_get_length_prefixed(cbs, out, 3);
176 }
177 
cbs_get_any_asn1_element(CBS * cbs,CBS * out,unsigned * out_tag,size_t * out_header_len,int ber_ok)178 static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
179                                     size_t *out_header_len, int ber_ok) {
180   uint8_t tag, length_byte;
181   CBS header = *cbs;
182   CBS throwaway;
183 
184   if (out == NULL) {
185     out = &throwaway;
186   }
187 
188   if (!CBS_get_u8(&header, &tag) ||
189       !CBS_get_u8(&header, &length_byte)) {
190     return 0;
191   }
192 
193   /* ITU-T X.690 section 8.1.2.3 specifies the format for identifiers with a tag
194    * number no greater than 30.
195    *
196    * If the number portion is 31 (0x1f, the largest value that fits in the
197    * allotted bits), then the tag is more than one byte long and the
198    * continuation bytes contain the tag number. This parser only supports tag
199    * numbers less than 31 (and thus single-byte tags). */
200   if ((tag & 0x1f) == 0x1f) {
201     return 0;
202   }
203 
204   if (out_tag != NULL) {
205     *out_tag = tag;
206   }
207 
208   size_t len;
209   /* The format for the length encoding is specified in ITU-T X.690 section
210    * 8.1.3. */
211   if ((length_byte & 0x80) == 0) {
212     /* Short form length. */
213     len = ((size_t) length_byte) + 2;
214     if (out_header_len != NULL) {
215       *out_header_len = 2;
216     }
217   } else {
218     /* The high bit indicate that this is the long form, while the next 7 bits
219      * encode the number of subsequent octets used to encode the length (ITU-T
220      * X.690 clause 8.1.3.5.b). */
221     const size_t num_bytes = length_byte & 0x7f;
222     uint32_t len32;
223 
224     if (ber_ok && (tag & CBS_ASN1_CONSTRUCTED) != 0 && num_bytes == 0) {
225       /* indefinite length */
226       if (out_header_len != NULL) {
227         *out_header_len = 2;
228       }
229       return CBS_get_bytes(cbs, out, 2);
230     }
231 
232     /* ITU-T X.690 clause 8.1.3.5.c specifies that the value 0xff shall not be
233      * used as the first byte of the length. If this parser encounters that
234      * value, num_bytes will be parsed as 127, which will fail the check below.
235      */
236     if (num_bytes == 0 || num_bytes > 4) {
237       return 0;
238     }
239     if (!cbs_get_u(&header, &len32, num_bytes)) {
240       return 0;
241     }
242     /* ITU-T X.690 section 10.1 (DER length forms) requires encoding the length
243      * with the minimum number of octets. */
244     if (len32 < 128) {
245       /* Length should have used short-form encoding. */
246       return 0;
247     }
248     if ((len32 >> ((num_bytes-1)*8)) == 0) {
249       /* Length should have been at least one byte shorter. */
250       return 0;
251     }
252     len = len32;
253     if (len + 2 + num_bytes < len) {
254       /* Overflow. */
255       return 0;
256     }
257     len += 2 + num_bytes;
258     if (out_header_len != NULL) {
259       *out_header_len = 2 + num_bytes;
260     }
261   }
262 
263   return CBS_get_bytes(cbs, out, len);
264 }
265 
CBS_get_any_asn1(CBS * cbs,CBS * out,unsigned * out_tag)266 int CBS_get_any_asn1(CBS *cbs, CBS *out, unsigned *out_tag) {
267   size_t header_len;
268   if (!CBS_get_any_asn1_element(cbs, out, out_tag, &header_len)) {
269     return 0;
270   }
271 
272   if (!CBS_skip(out, header_len)) {
273     assert(0);
274     return 0;
275   }
276 
277   return 1;
278 }
279 
CBS_get_any_asn1_element(CBS * cbs,CBS * out,unsigned * out_tag,size_t * out_header_len)280 int CBS_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
281                                     size_t *out_header_len) {
282   return cbs_get_any_asn1_element(cbs, out, out_tag, out_header_len,
283                                   0 /* DER only */);
284 }
285 
CBS_get_any_ber_asn1_element(CBS * cbs,CBS * out,unsigned * out_tag,size_t * out_header_len)286 int CBS_get_any_ber_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
287                                  size_t *out_header_len) {
288   return cbs_get_any_asn1_element(cbs, out, out_tag, out_header_len,
289                                   1 /* BER allowed */);
290 }
291 
cbs_get_asn1(CBS * cbs,CBS * out,unsigned tag_value,int skip_header)292 static int cbs_get_asn1(CBS *cbs, CBS *out, unsigned tag_value,
293                         int skip_header) {
294   size_t header_len;
295   unsigned tag;
296   CBS throwaway;
297 
298   if (out == NULL) {
299     out = &throwaway;
300   }
301 
302   if (!CBS_get_any_asn1_element(cbs, out, &tag, &header_len) ||
303       tag != tag_value) {
304     return 0;
305   }
306 
307   if (skip_header && !CBS_skip(out, header_len)) {
308     assert(0);
309     return 0;
310   }
311 
312   return 1;
313 }
314 
CBS_get_asn1(CBS * cbs,CBS * out,unsigned tag_value)315 int CBS_get_asn1(CBS *cbs, CBS *out, unsigned tag_value) {
316   return cbs_get_asn1(cbs, out, tag_value, 1 /* skip header */);
317 }
318 
CBS_get_asn1_element(CBS * cbs,CBS * out,unsigned tag_value)319 int CBS_get_asn1_element(CBS *cbs, CBS *out, unsigned tag_value) {
320   return cbs_get_asn1(cbs, out, tag_value, 0 /* include header */);
321 }
322 
CBS_peek_asn1_tag(const CBS * cbs,unsigned tag_value)323 int CBS_peek_asn1_tag(const CBS *cbs, unsigned tag_value) {
324   if (CBS_len(cbs) < 1) {
325     return 0;
326   }
327   return CBS_data(cbs)[0] == tag_value;
328 }
329 
CBS_get_asn1_uint64(CBS * cbs,uint64_t * out)330 int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out) {
331   CBS bytes;
332   if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_INTEGER)) {
333     return 0;
334   }
335 
336   *out = 0;
337   const uint8_t *data = CBS_data(&bytes);
338   size_t len = CBS_len(&bytes);
339 
340   if (len == 0) {
341     /* An INTEGER is encoded with at least one octet. */
342     return 0;
343   }
344 
345   if ((data[0] & 0x80) != 0) {
346     /* Negative number. */
347     return 0;
348   }
349 
350   if (data[0] == 0 && len > 1 && (data[1] & 0x80) == 0) {
351     /* Extra leading zeros. */
352     return 0;
353   }
354 
355   for (size_t i = 0; i < len; i++) {
356     if ((*out >> 56) != 0) {
357       /* Too large to represent as a uint64_t. */
358       return 0;
359     }
360     *out <<= 8;
361     *out |= data[i];
362   }
363 
364   return 1;
365 }
366 
CBS_get_optional_asn1(CBS * cbs,CBS * out,int * out_present,unsigned tag)367 int CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present, unsigned tag) {
368   int present = 0;
369 
370   if (CBS_peek_asn1_tag(cbs, tag)) {
371     if (!CBS_get_asn1(cbs, out, tag)) {
372       return 0;
373     }
374     present = 1;
375   }
376 
377   if (out_present != NULL) {
378     *out_present = present;
379   }
380 
381   return 1;
382 }
383 
CBS_get_optional_asn1_octet_string(CBS * cbs,CBS * out,int * out_present,unsigned tag)384 int CBS_get_optional_asn1_octet_string(CBS *cbs, CBS *out, int *out_present,
385                                        unsigned tag) {
386   CBS child;
387   int present;
388   if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) {
389     return 0;
390   }
391   if (present) {
392     if (!CBS_get_asn1(&child, out, CBS_ASN1_OCTETSTRING) ||
393         CBS_len(&child) != 0) {
394       return 0;
395     }
396   } else {
397     CBS_init(out, NULL, 0);
398   }
399   if (out_present) {
400     *out_present = present;
401   }
402   return 1;
403 }
404 
CBS_get_optional_asn1_uint64(CBS * cbs,uint64_t * out,unsigned tag,uint64_t default_value)405 int CBS_get_optional_asn1_uint64(CBS *cbs, uint64_t *out, unsigned tag,
406                                  uint64_t default_value) {
407   CBS child;
408   int present;
409   if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) {
410     return 0;
411   }
412   if (present) {
413     if (!CBS_get_asn1_uint64(&child, out) ||
414         CBS_len(&child) != 0) {
415       return 0;
416     }
417   } else {
418     *out = default_value;
419   }
420   return 1;
421 }
422 
CBS_get_optional_asn1_bool(CBS * cbs,int * out,unsigned tag,int default_value)423 int CBS_get_optional_asn1_bool(CBS *cbs, int *out, unsigned tag,
424                                int default_value) {
425   CBS child, child2;
426   int present;
427   if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) {
428     return 0;
429   }
430   if (present) {
431     uint8_t boolean;
432 
433     if (!CBS_get_asn1(&child, &child2, CBS_ASN1_BOOLEAN) ||
434         CBS_len(&child2) != 1 ||
435         CBS_len(&child) != 0) {
436       return 0;
437     }
438 
439     boolean = CBS_data(&child2)[0];
440     if (boolean == 0) {
441       *out = 0;
442     } else if (boolean == 0xff) {
443       *out = 1;
444     } else {
445       return 0;
446     }
447   } else {
448     *out = default_value;
449   }
450   return 1;
451 }
452 
CBS_is_valid_asn1_bitstring(const CBS * cbs)453 int CBS_is_valid_asn1_bitstring(const CBS *cbs) {
454   CBS in = *cbs;
455   uint8_t num_unused_bits;
456   if (!CBS_get_u8(&in, &num_unused_bits) ||
457       num_unused_bits > 7) {
458     return 0;
459   }
460 
461   if (num_unused_bits == 0) {
462     return 1;
463   }
464 
465   /* All num_unused_bits bits must exist and be zeros. */
466   uint8_t last;
467   if (!CBS_get_last_u8(&in, &last) ||
468       (last & ((1 << num_unused_bits) - 1)) != 0) {
469     return 0;
470   }
471 
472   return 1;
473 }
474 
CBS_asn1_bitstring_has_bit(const CBS * cbs,unsigned bit)475 int CBS_asn1_bitstring_has_bit(const CBS *cbs, unsigned bit) {
476   if (!CBS_is_valid_asn1_bitstring(cbs)) {
477     return 0;
478   }
479 
480   const unsigned byte_num = (bit >> 3) + 1;
481   const unsigned bit_num = 7 - (bit & 7);
482 
483   /* Unused bits are zero, and this function does not distinguish between
484    * missing and unset bits. Thus it is sufficient to do a byte-level length
485    * check. */
486   return byte_num < CBS_len(cbs) &&
487          (CBS_data(cbs)[byte_num] & (1 << bit_num)) != 0;
488 }
489