OpenCoverage

bs_ber.c

Absolute File Name:/home/opencoverage/opencoverage/guest-scripts/libressl/src/ssl/bs_ber.c
Source codeSwitch to Preprocessed file
LineSourceCount
1/* $OpenBSD: bs_ber.c,v 1.9 2016/12/03 12:34:35 jsing Exp $ */-
2/*-
3 * Copyright (c) 2014, Google Inc.-
4 *-
5 * Permission to use, copy, modify, and/or distribute this software for any-
6 * purpose with or without fee is hereby granted, provided that the above-
7 * copyright notice and this permission notice appear in all copies.-
8 *-
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES-
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF-
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY-
12 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES-
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION-
14 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN-
15 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */-
16-
17#include <string.h>-
18-
19#include <openssl/opensslconf.h>-
20-
21#include "bytestring.h"-
22-
23/*-
24 * kMaxDepth is a just a sanity limit. The code should be such that the length-
25 * of the input being processes always decreases. None the less, a very large-
26 * input could otherwise cause the stack to overflow.-
27 */-
28static const unsigned int kMaxDepth = 2048;-
29-
30/* Non-strict version that allows a relaxed DER with indefinite form. */-
31static int-
32cbs_nonstrict_get_any_asn1_element(CBS *cbs, CBS *out, unsigned int *out_tag,-
33 size_t *out_header_len)-
34{-
35 return cbs_get_any_asn1_element_internal(cbs, out,
executed 31 times by 1 test: return cbs_get_any_asn1_element_internal(cbs, out, out_tag, out_header_len, 0);
Executed by:
  • bytestringtest
31
36 out_tag, out_header_len, 0);
executed 31 times by 1 test: return cbs_get_any_asn1_element_internal(cbs, out, out_tag, out_header_len, 0);
Executed by:
  • bytestringtest
31
37}-
38-
39/*-
40 * cbs_find_indefinite walks an ASN.1 structure in |orig_in| and sets-
41 * |*indefinite_found| depending on whether an indefinite length element was-
42 * found. The value of |orig_in| is not modified.-
43 *-
44 * Returns one on success (i.e. |*indefinite_found| was set) and zero on error.-
45 */-
46static int-
47cbs_find_indefinite(const CBS *orig_in, char *indefinite_found,-
48 unsigned int depth)-
49{-
50 CBS in;-
51-
52 if (depth > kMaxDepth)
depth > kMaxDepthDescription
TRUEnever evaluated
FALSEevaluated 4 times by 1 test
Evaluated by:
  • bytestringtest
0-4
53 return 0;
never executed: return 0;
0
54-
55 CBS_init(&in, CBS_data(orig_in), CBS_len(orig_in));-
56-
57 while (CBS_len(&in) > 0) {
CBS_len(&in) > 0Description
TRUEevaluated 4 times by 1 test
Evaluated by:
  • bytestringtest
FALSEevaluated 1 time by 1 test
Evaluated by:
  • bytestringtest
1-4
58 CBS contents;-
59 unsigned int tag;-
60 size_t header_len;-
61-
62 if (!cbs_nonstrict_get_any_asn1_element(&in, &contents, &tag,
!cbs_nonstrict..., &header_len)Description
TRUEnever evaluated
FALSEevaluated 4 times by 1 test
Evaluated by:
  • bytestringtest
0-4
63 &header_len))
!cbs_nonstrict..., &header_len)Description
TRUEnever evaluated
FALSEevaluated 4 times by 1 test
Evaluated by:
  • bytestringtest
0-4
64 return 0;
never executed: return 0;
0
65-
66 /* Indefinite form not allowed by DER. */-
67 if (CBS_len(&contents) == header_len && header_len > 0 &&
CBS_len(&conte... == header_lenDescription
TRUEevaluated 3 times by 1 test
Evaluated by:
  • bytestringtest
FALSEevaluated 1 time by 1 test
Evaluated by:
  • bytestringtest
header_len > 0Description
TRUEevaluated 3 times by 1 test
Evaluated by:
  • bytestringtest
FALSEnever evaluated
0-3
68 CBS_data(&contents)[header_len - 1] == 0x80) {
CBS_data(&cont...n - 1] == 0x80Description
TRUEevaluated 3 times by 1 test
Evaluated by:
  • bytestringtest
FALSEnever evaluated
0-3
69 *indefinite_found = 1;-
70 return 1;
executed 3 times by 1 test: return 1;
Executed by:
  • bytestringtest
3
71 }-
72 if (tag & CBS_ASN1_CONSTRUCTED) {
tag & 0x20Description
TRUEnever evaluated
FALSEevaluated 1 time by 1 test
Evaluated by:
  • bytestringtest
0-1
73 if (!CBS_skip(&contents, header_len) ||
!CBS_skip(&con...s, header_len)Description
TRUEnever evaluated
FALSEnever evaluated
0
74 !cbs_find_indefinite(&contents, indefinite_found,
!cbs_find_inde...nd, depth + 1)Description
TRUEnever evaluated
FALSEnever evaluated
0
75 depth + 1))
!cbs_find_inde...nd, depth + 1)Description
TRUEnever evaluated
FALSEnever evaluated
0
76 return 0;
never executed: return 0;
0
77 }
never executed: end of block
0
78 }
executed 1 time by 1 test: end of block
Executed by:
  • bytestringtest
1
79-
80 *indefinite_found = 0;-
81 return 1;
executed 1 time by 1 test: return 1;
Executed by:
  • bytestringtest
1
82}-
83-
84/*-
85 * is_primitive_type returns true if |tag| likely a primitive type. Normally-
86 * one can just test the "constructed" bit in the tag but, in BER, even-
87 * primitive tags can have the constructed bit if they have indefinite-
88 * length.-
89 */-
90static char-
91is_primitive_type(unsigned int tag)-
92{-
93 return (tag & 0xc0) == 0 &&
executed 6 times by 1 test: return (tag & 0xc0) == 0 && (tag & 0x1f) != ((0x00 | 0x20 | 0x10) & 0x1f) && (tag & 0x1f) != ((0x00 | 0x20 | 0x11) & 0x1f);
Executed by:
  • bytestringtest
(tag & 0xc0) == 0Description
TRUEevaluated 5 times by 1 test
Evaluated by:
  • bytestringtest
FALSEevaluated 1 time by 1 test
Evaluated by:
  • bytestringtest
1-6
94 (tag & 0x1f) != (CBS_ASN1_SEQUENCE & 0x1f) &&
executed 6 times by 1 test: return (tag & 0xc0) == 0 && (tag & 0x1f) != ((0x00 | 0x20 | 0x10) & 0x1f) && (tag & 0x1f) != ((0x00 | 0x20 | 0x11) & 0x1f);
Executed by:
  • bytestringtest
(tag & 0x1f) !... 0x10) & 0x1f)Description
TRUEevaluated 2 times by 1 test
Evaluated by:
  • bytestringtest
FALSEevaluated 3 times by 1 test
Evaluated by:
  • bytestringtest
2-6
95 (tag & 0x1f) != (CBS_ASN1_SET & 0x1f);
executed 6 times by 1 test: return (tag & 0xc0) == 0 && (tag & 0x1f) != ((0x00 | 0x20 | 0x10) & 0x1f) && (tag & 0x1f) != ((0x00 | 0x20 | 0x11) & 0x1f);
Executed by:
  • bytestringtest
(tag & 0x1f) !... 0x11) & 0x1f)Description
TRUEevaluated 2 times by 1 test
Evaluated by:
  • bytestringtest
FALSEnever evaluated
0-6
96}-
97-
98/*-
99 * is_eoc returns true if |header_len| and |contents|, as returned by-
100 * |cbs_nonstrict_get_any_asn1_element|, indicate an "end of contents" (EOC)-
101 * value.-
102 */-
103static char-
104is_eoc(size_t header_len, CBS *contents)-
105{-
106 const unsigned char eoc[] = {0x0, 0x0};-
107-
108 return header_len == 2 && CBS_mem_equal(contents, eoc, 2);
executed 13 times by 1 test: return header_len == 2 && CBS_mem_equal(contents, eoc, 2);
Executed by:
  • bytestringtest
header_len == 2Description
TRUEevaluated 13 times by 1 test
Evaluated by:
  • bytestringtest
FALSEnever evaluated
CBS_mem_equal(...tents, eoc, 2)Description
TRUEevaluated 6 times by 1 test
Evaluated by:
  • bytestringtest
FALSEevaluated 7 times by 1 test
Evaluated by:
  • bytestringtest
0-13
109}-
110-
111/*-
112 * cbs_convert_indefinite reads data with DER encoding (but relaxed to allow-
113 * indefinite form) from |in| and writes definite form DER data to |out|. If-
114 * |squash_header| is set then the top-level of elements from |in| will not-
115 * have their headers written. This is used when concatenating the fragments of-
116 * an indefinite length, primitive value. If |looking_for_eoc| is set then any-
117 * EOC elements found will cause the function to return after consuming it.-
118 * It returns one on success and zero on error.-
119 */-
120static int-
121cbs_convert_indefinite(CBS *in, CBB *out, char squash_header,-
122 char looking_for_eoc, unsigned int depth)-
123{-
124 if (depth > kMaxDepth)
depth > kMaxDepthDescription
TRUEnever evaluated
FALSEevaluated 12 times by 1 test
Evaluated by:
  • bytestringtest
0-12
125 return 0;
never executed: return 0;
0
126-
127 while (CBS_len(in) > 0) {
CBS_len(in) > 0Description
TRUEevaluated 26 times by 1 test
Evaluated by:
  • bytestringtest
FALSEevaluated 6 times by 1 test
Evaluated by:
  • bytestringtest
6-26
128 CBS contents;-
129 unsigned int tag;-
130 size_t header_len;-
131 CBB *out_contents, out_contents_storage;-
132-
133 if (!cbs_nonstrict_get_any_asn1_element(in, &contents, &tag,
!cbs_nonstrict..., &header_len)Description
TRUEnever evaluated
FALSEevaluated 26 times by 1 test
Evaluated by:
  • bytestringtest
0-26
134 &header_len))
!cbs_nonstrict..., &header_len)Description
TRUEnever evaluated
FALSEevaluated 26 times by 1 test
Evaluated by:
  • bytestringtest
0-26
135 return 0;
never executed: return 0;
0
136-
137 out_contents = out;-
138-
139 if (CBS_len(&contents) == header_len) {
CBS_len(&conte... == header_lenDescription
TRUEevaluated 13 times by 1 test
Evaluated by:
  • bytestringtest
FALSEevaluated 13 times by 1 test
Evaluated by:
  • bytestringtest
13
140 if (is_eoc(header_len, &contents))
is_eoc(header_len, &contents)Description
TRUEevaluated 6 times by 1 test
Evaluated by:
  • bytestringtest
FALSEevaluated 7 times by 1 test
Evaluated by:
  • bytestringtest
6-7
141 return looking_for_eoc;
executed 6 times by 1 test: return looking_for_eoc;
Executed by:
  • bytestringtest
6
142-
143 if (header_len > 0 &&
header_len > 0Description
TRUEevaluated 7 times by 1 test
Evaluated by:
  • bytestringtest
FALSEnever evaluated
0-7
144 CBS_data(&contents)[header_len - 1] == 0x80) {
CBS_data(&cont...n - 1] == 0x80Description
TRUEevaluated 6 times by 1 test
Evaluated by:
  • bytestringtest
FALSEevaluated 1 time by 1 test
Evaluated by:
  • bytestringtest
1-6
145 /*-
146 * This is an indefinite length element. If-
147 * it's a SEQUENCE or SET then we just need to-
148 * write the out the contents as normal, but-
149 * with a concrete length prefix.-
150 *-
151 * If it's a something else then the contents-
152 * will be a series of DER elements of the same-
153 * type which need to be concatenated.-
154 */-
155 const char context_specific = (tag & 0xc0)-
156 == 0x80;-
157 char squash_child_headers =-
158 is_primitive_type(tag);-
159-
160 /*-
161 * This is a hack, but it sufficies to handle-
162 * NSS's output. If we find an indefinite-
163 * length, context-specific tag with a definite,-
164 * primtive tag inside it, then we assume that-
165 * the context-specific tag is implicit and the-
166 * tags within are fragments of a primitive type-
167 * that need to be concatenated.-
168 */-
169 if (context_specific &&
context_specificDescription
TRUEevaluated 1 time by 1 test
Evaluated by:
  • bytestringtest
FALSEevaluated 5 times by 1 test
Evaluated by:
  • bytestringtest
1-5
170 (tag & CBS_ASN1_CONSTRUCTED)) {
(tag & 0x20)Description
TRUEevaluated 1 time by 1 test
Evaluated by:
  • bytestringtest
FALSEnever evaluated
0-1
171 CBS in_copy, inner_contents;-
172 unsigned int inner_tag;-
173 size_t inner_header_len;-
174-
175 CBS_init(&in_copy, CBS_data(in),-
176 CBS_len(in));-
177 if (!cbs_nonstrict_get_any_asn1_element(
!cbs_nonstrict...er_header_len)Description
TRUEnever evaluated
FALSEevaluated 1 time by 1 test
Evaluated by:
  • bytestringtest
0-1
178 &in_copy, &inner_contents,
!cbs_nonstrict...er_header_len)Description
TRUEnever evaluated
FALSEevaluated 1 time by 1 test
Evaluated by:
  • bytestringtest
0-1
179 &inner_tag, &inner_header_len))
!cbs_nonstrict...er_header_len)Description
TRUEnever evaluated
FALSEevaluated 1 time by 1 test
Evaluated by:
  • bytestringtest
0-1
180 return 0;
never executed: return 0;
0
181-
182 if (CBS_len(&inner_contents) >
CBS_len(&inner...ner_header_lenDescription
TRUEnever evaluated
FALSEevaluated 1 time by 1 test
Evaluated by:
  • bytestringtest
0-1
183 inner_header_len &&
CBS_len(&inner...ner_header_lenDescription
TRUEnever evaluated
FALSEevaluated 1 time by 1 test
Evaluated by:
  • bytestringtest
0-1
184 is_primitive_type(inner_tag))
is_primitive_type(inner_tag)Description
TRUEnever evaluated
FALSEnever evaluated
0
185 squash_child_headers = 1;
never executed: squash_child_headers = 1;
0
186 }
executed 1 time by 1 test: end of block
Executed by:
  • bytestringtest
1
187-
188 if (!squash_header) {
!squash_headerDescription
TRUEevaluated 6 times by 1 test
Evaluated by:
  • bytestringtest
FALSEnever evaluated
0-6
189 unsigned int out_tag = tag;-
190-
191 if (squash_child_headers)
squash_child_headersDescription
TRUEevaluated 2 times by 1 test
Evaluated by:
  • bytestringtest
FALSEevaluated 4 times by 1 test
Evaluated by:
  • bytestringtest
2-4
192 out_tag &=
executed 2 times by 1 test: out_tag &= ~0x20;
Executed by:
  • bytestringtest
2
193 ~CBS_ASN1_CONSTRUCTED;
executed 2 times by 1 test: out_tag &= ~0x20;
Executed by:
  • bytestringtest
2
194-
195 if (!CBB_add_asn1(out,
!CBB_add_asn1(...rage, out_tag)Description
TRUEnever evaluated
FALSEevaluated 6 times by 1 test
Evaluated by:
  • bytestringtest
0-6
196 &out_contents_storage, out_tag))
!CBB_add_asn1(...rage, out_tag)Description
TRUEnever evaluated
FALSEevaluated 6 times by 1 test
Evaluated by:
  • bytestringtest
0-6
197 return 0;
never executed: return 0;
0
198-
199 out_contents = &out_contents_storage;-
200 }
executed 6 times by 1 test: end of block
Executed by:
  • bytestringtest
6
201-
202 if (!cbs_convert_indefinite(in, out_contents,
!cbs_convert_i...1 , depth + 1)Description
TRUEnever evaluated
FALSEevaluated 6 times by 1 test
Evaluated by:
  • bytestringtest
0-6
203 squash_child_headers,
!cbs_convert_i...1 , depth + 1)Description
TRUEnever evaluated
FALSEevaluated 6 times by 1 test
Evaluated by:
  • bytestringtest
0-6
204 1 /* looking for eoc */, depth + 1))
!cbs_convert_i...1 , depth + 1)Description
TRUEnever evaluated
FALSEevaluated 6 times by 1 test
Evaluated by:
  • bytestringtest
0-6
205 return 0;
never executed: return 0;
0
206-
207 if (out_contents != out && !CBB_flush(out))
out_contents != outDescription
TRUEevaluated 6 times by 1 test
Evaluated by:
  • bytestringtest
FALSEnever evaluated
!CBB_flush(out)Description
TRUEnever evaluated
FALSEevaluated 6 times by 1 test
Evaluated by:
  • bytestringtest
0-6
208 return 0;
never executed: return 0;
0
209-
210 continue;
executed 6 times by 1 test: continue;
Executed by:
  • bytestringtest
6
211 }-
212 }
executed 1 time by 1 test: end of block
Executed by:
  • bytestringtest
1
213-
214 if (!squash_header) {
!squash_headerDescription
TRUEevaluated 11 times by 1 test
Evaluated by:
  • bytestringtest
FALSEevaluated 3 times by 1 test
Evaluated by:
  • bytestringtest
3-11
215 if (!CBB_add_asn1(out, &out_contents_storage, tag))
!CBB_add_asn1(..._storage, tag)Description
TRUEnever evaluated
FALSEevaluated 11 times by 1 test
Evaluated by:
  • bytestringtest
0-11
216 return 0;
never executed: return 0;
0
217-
218 out_contents = &out_contents_storage;-
219 }
executed 11 times by 1 test: end of block
Executed by:
  • bytestringtest
11
220-
221 if (!CBS_skip(&contents, header_len))
!CBS_skip(&con...s, header_len)Description
TRUEnever evaluated
FALSEevaluated 14 times by 1 test
Evaluated by:
  • bytestringtest
0-14
222 return 0;
never executed: return 0;
0
223-
224 if (tag & CBS_ASN1_CONSTRUCTED) {
tag & 0x20Description
TRUEevaluated 3 times by 1 test
Evaluated by:
  • bytestringtest
FALSEevaluated 11 times by 1 test
Evaluated by:
  • bytestringtest
3-11
225 if (!cbs_convert_indefinite(&contents, out_contents,
!cbs_convert_i...0 , depth + 1)Description
TRUEnever evaluated
FALSEevaluated 3 times by 1 test
Evaluated by:
  • bytestringtest
0-3
226 0 /* don't squash header */,
!cbs_convert_i...0 , depth + 1)Description
TRUEnever evaluated
FALSEevaluated 3 times by 1 test
Evaluated by:
  • bytestringtest
0-3
227 0 /* not looking for eoc */, depth + 1))
!cbs_convert_i...0 , depth + 1)Description
TRUEnever evaluated
FALSEevaluated 3 times by 1 test
Evaluated by:
  • bytestringtest
0-3
228 return 0;
never executed: return 0;
0
229 } else {
executed 3 times by 1 test: end of block
Executed by:
  • bytestringtest
3
230 if (!CBB_add_bytes(out_contents, CBS_data(&contents),
!CBB_add_bytes...en(&contents))Description
TRUEnever evaluated
FALSEevaluated 11 times by 1 test
Evaluated by:
  • bytestringtest
0-11
231 CBS_len(&contents)))
!CBB_add_bytes...en(&contents))Description
TRUEnever evaluated
FALSEevaluated 11 times by 1 test
Evaluated by:
  • bytestringtest
0-11
232 return 0;
never executed: return 0;
0
233 }
executed 11 times by 1 test: end of block
Executed by:
  • bytestringtest
11
234-
235 if (out_contents != out && !CBB_flush(out))
out_contents != outDescription
TRUEevaluated 11 times by 1 test
Evaluated by:
  • bytestringtest
FALSEevaluated 3 times by 1 test
Evaluated by:
  • bytestringtest
!CBB_flush(out)Description
TRUEnever evaluated
FALSEevaluated 11 times by 1 test
Evaluated by:
  • bytestringtest
0-11
236 return 0;
never executed: return 0;
0
237 }
executed 14 times by 1 test: end of block
Executed by:
  • bytestringtest
14
238-
239 return looking_for_eoc == 0;
executed 6 times by 1 test: return looking_for_eoc == 0;
Executed by:
  • bytestringtest
6
240}-
241-
242int-
243CBS_asn1_indefinite_to_definite(CBS *in, uint8_t **out, size_t *out_len)-
244{-
245 CBB cbb;-
246-
247 /*-
248 * First, do a quick walk to find any indefinite-length elements. Most-
249 * of the time we hope that there aren't any and thus we can quickly-
250 * return.-
251 */-
252 char conversion_needed;-
253 if (!cbs_find_indefinite(in, &conversion_needed, 0))
!cbs_find_inde...ion_needed, 0)Description
TRUEnever evaluated
FALSEevaluated 4 times by 1 test
Evaluated by:
  • bytestringtest
0-4
254 return 0;
never executed: return 0;
0
255-
256 if (!conversion_needed) {
!conversion_neededDescription
TRUEevaluated 1 time by 1 test
Evaluated by:
  • bytestringtest
FALSEevaluated 3 times by 1 test
Evaluated by:
  • bytestringtest
1-3
257 *out = NULL;-
258 *out_len = 0;-
259 return 1;
executed 1 time by 1 test: return 1;
Executed by:
  • bytestringtest
1
260 }-
261-
262 if (!CBB_init(&cbb, CBS_len(in)))
!CBB_init(&cbb, CBS_len(in))Description
TRUEnever evaluated
FALSEevaluated 3 times by 1 test
Evaluated by:
  • bytestringtest
0-3
263 return 0;
never executed: return 0;
0
264 if (!cbs_convert_indefinite(in, &cbb, 0, 0, 0)) {
!cbs_convert_i...&cbb, 0, 0, 0)Description
TRUEnever evaluated
FALSEevaluated 3 times by 1 test
Evaluated by:
  • bytestringtest
0-3
265 CBB_cleanup(&cbb);-
266 return 0;
never executed: return 0;
0
267 }-
268-
269 return CBB_finish(&cbb, out, out_len);
executed 3 times by 1 test: return CBB_finish(&cbb, out, out_len);
Executed by:
  • bytestringtest
3
270}-
Source codeSwitch to Preprocessed file

Generated by Squish Coco 4.2.2