/src/boringssl/crypto/asn1/tasn_enc.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
2 | | * All rights reserved. |
3 | | * |
4 | | * This package is an SSL implementation written |
5 | | * by Eric Young (eay@cryptsoft.com). |
6 | | * The implementation was written so as to conform with Netscapes SSL. |
7 | | * |
8 | | * This library is free for commercial and non-commercial use as long as |
9 | | * the following conditions are aheared to. The following conditions |
10 | | * apply to all code found in this distribution, be it the RC4, RSA, |
11 | | * lhash, DES, etc., code; not just the SSL code. The SSL documentation |
12 | | * included with this distribution is covered by the same copyright terms |
13 | | * except that the holder is Tim Hudson (tjh@cryptsoft.com). |
14 | | * |
15 | | * Copyright remains Eric Young's, and as such any Copyright notices in |
16 | | * the code are not to be removed. |
17 | | * If this package is used in a product, Eric Young should be given attribution |
18 | | * as the author of the parts of the library used. |
19 | | * This can be in the form of a textual message at program startup or |
20 | | * in documentation (online or textual) provided with the package. |
21 | | * |
22 | | * Redistribution and use in source and binary forms, with or without |
23 | | * modification, are permitted provided that the following conditions |
24 | | * are met: |
25 | | * 1. Redistributions of source code must retain the copyright |
26 | | * notice, this list of conditions and the following disclaimer. |
27 | | * 2. Redistributions in binary form must reproduce the above copyright |
28 | | * notice, this list of conditions and the following disclaimer in the |
29 | | * documentation and/or other materials provided with the distribution. |
30 | | * 3. All advertising materials mentioning features or use of this software |
31 | | * must display the following acknowledgement: |
32 | | * "This product includes cryptographic software written by |
33 | | * Eric Young (eay@cryptsoft.com)" |
34 | | * The word 'cryptographic' can be left out if the rouines from the library |
35 | | * being used are not cryptographic related :-). |
36 | | * 4. If you include any Windows specific code (or a derivative thereof) from |
37 | | * the apps directory (application code) you must include an acknowledgement: |
38 | | * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
39 | | * |
40 | | * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
41 | | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
42 | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
43 | | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
44 | | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
45 | | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
46 | | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
47 | | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
48 | | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
49 | | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
50 | | * SUCH DAMAGE. |
51 | | * |
52 | | * The licence and distribution terms for any publically available version or |
53 | | * derivative of this code cannot be changed. i.e. this code cannot simply be |
54 | | * copied and put under another distribution licence |
55 | | * [including the GNU Public Licence.] */ |
56 | | |
57 | | #include <openssl/asn1.h> |
58 | | |
59 | | #include <assert.h> |
60 | | #include <limits.h> |
61 | | #include <string.h> |
62 | | |
63 | | #include <openssl/asn1t.h> |
64 | | #include <openssl/mem.h> |
65 | | |
66 | | #include "../internal.h" |
67 | | #include "internal.h" |
68 | | |
69 | | |
70 | | static int asn1_item_ex_i2d_opt(ASN1_VALUE **pval, unsigned char **out, |
71 | | const ASN1_ITEM *it, int tag, int aclass, |
72 | | int optional); |
73 | | static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, |
74 | | const ASN1_ITEM *it, int tag, int aclass, |
75 | | int optional); |
76 | | static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cont, int *out_omit, |
77 | | int *putype, const ASN1_ITEM *it); |
78 | | static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, |
79 | | int skcontlen, const ASN1_ITEM *item, int do_sort); |
80 | | static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out, |
81 | | const ASN1_TEMPLATE *tt, int tag, int aclass, |
82 | | int optional); |
83 | | |
84 | | // Top level i2d equivalents |
85 | | |
86 | 502k | int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it) { |
87 | 502k | if (out && !*out) { |
88 | 328k | unsigned char *p, *buf; |
89 | 328k | int len = ASN1_item_ex_i2d(&val, NULL, it, /*tag=*/-1, /*aclass=*/0); |
90 | 328k | if (len <= 0) { |
91 | 211 | return len; |
92 | 211 | } |
93 | 327k | buf = OPENSSL_malloc(len); |
94 | 327k | if (!buf) { |
95 | 0 | return -1; |
96 | 0 | } |
97 | 327k | p = buf; |
98 | 327k | int len2 = ASN1_item_ex_i2d(&val, &p, it, /*tag=*/-1, /*aclass=*/0); |
99 | 327k | if (len2 <= 0) { |
100 | 0 | OPENSSL_free(buf); |
101 | 0 | return len2; |
102 | 0 | } |
103 | 327k | assert(len == len2); |
104 | 327k | *out = buf; |
105 | 327k | return len; |
106 | 327k | } |
107 | | |
108 | 174k | return ASN1_item_ex_i2d(&val, out, it, /*tag=*/-1, /*aclass=*/0); |
109 | 502k | } |
110 | | |
111 | | // Encode an item, taking care of IMPLICIT tagging (if any). This function |
112 | | // performs the normal item handling: it can be used in external types. |
113 | | |
114 | | int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, |
115 | 8.71M | const ASN1_ITEM *it, int tag, int aclass) { |
116 | 8.71M | int ret = asn1_item_ex_i2d_opt(pval, out, it, tag, aclass, /*optional=*/0); |
117 | 8.71M | assert(ret != 0); |
118 | 8.71M | return ret; |
119 | 8.71M | } |
120 | | |
121 | | // asn1_item_ex_i2d_opt behaves like |ASN1_item_ex_i2d| but, if |optional| is |
122 | | // non-zero and |*pval| is omitted, it returns zero and writes no bytes. |
123 | | int asn1_item_ex_i2d_opt(ASN1_VALUE **pval, unsigned char **out, |
124 | | const ASN1_ITEM *it, int tag, int aclass, |
125 | 23.1M | int optional) { |
126 | 23.1M | const ASN1_TEMPLATE *tt = NULL; |
127 | 23.1M | int i, seqcontlen, seqlen; |
128 | | |
129 | | // Historically, |aclass| was repurposed to pass additional flags into the |
130 | | // encoding process. |
131 | 23.1M | assert((aclass & ASN1_TFLG_TAG_CLASS) == aclass); |
132 | | // If not overridding the tag, |aclass| is ignored and should be zero. |
133 | 23.1M | assert(tag != -1 || aclass == 0); |
134 | | |
135 | | // All fields are pointers, except for boolean |ASN1_ITYPE_PRIMITIVE|s. |
136 | | // Optional primitives are handled later. |
137 | 23.1M | if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval) { |
138 | 95.1k | if (optional) { |
139 | 95.1k | return 0; |
140 | 95.1k | } |
141 | 0 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE); |
142 | 0 | return -1; |
143 | 95.1k | } |
144 | | |
145 | 23.1M | switch (it->itype) { |
146 | 9.86M | case ASN1_ITYPE_PRIMITIVE: |
147 | 9.86M | if (it->templates) { |
148 | | // This is an |ASN1_ITEM_TEMPLATE|. |
149 | 2.17M | if (it->templates->flags & ASN1_TFLG_OPTIONAL) { |
150 | 0 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); |
151 | 0 | return -1; |
152 | 0 | } |
153 | 2.17M | return asn1_template_ex_i2d(pval, out, it->templates, tag, aclass, |
154 | 2.17M | optional); |
155 | 2.17M | } |
156 | 7.68M | return asn1_i2d_ex_primitive(pval, out, it, tag, aclass, optional); |
157 | | |
158 | 6.13M | case ASN1_ITYPE_MSTRING: |
159 | | // It never makes sense for multi-strings to have implicit tagging, so |
160 | | // if tag != -1, then this looks like an error in the template. |
161 | 6.13M | if (tag != -1) { |
162 | 0 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); |
163 | 0 | return -1; |
164 | 0 | } |
165 | 6.13M | return asn1_i2d_ex_primitive(pval, out, it, -1, 0, optional); |
166 | | |
167 | 1.52M | case ASN1_ITYPE_CHOICE: { |
168 | | // It never makes sense for CHOICE types to have implicit tagging, so if |
169 | | // tag != -1, then this looks like an error in the template. |
170 | 1.52M | if (tag != -1) { |
171 | 0 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); |
172 | 0 | return -1; |
173 | 0 | } |
174 | 1.52M | i = asn1_get_choice_selector(pval, it); |
175 | 1.52M | if (i < 0 || i >= it->tcount) { |
176 | 0 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_NO_MATCHING_CHOICE_TYPE); |
177 | 0 | return -1; |
178 | 0 | } |
179 | 1.52M | const ASN1_TEMPLATE *chtt = it->templates + i; |
180 | 1.52M | if (chtt->flags & ASN1_TFLG_OPTIONAL) { |
181 | 0 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); |
182 | 0 | return -1; |
183 | 0 | } |
184 | 1.52M | ASN1_VALUE **pchval = asn1_get_field_ptr(pval, chtt); |
185 | 1.52M | return asn1_template_ex_i2d(pchval, out, chtt, -1, 0, /*optional=*/0); |
186 | 1.52M | } |
187 | | |
188 | 677k | case ASN1_ITYPE_EXTERN: { |
189 | | // We don't support implicit tagging with external types. |
190 | 677k | if (tag != -1) { |
191 | 0 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); |
192 | 0 | return -1; |
193 | 0 | } |
194 | 677k | const ASN1_EXTERN_FUNCS *ef = it->funcs; |
195 | 677k | int ret = ef->asn1_ex_i2d(pval, out, it); |
196 | 677k | if (ret == 0) { |
197 | | // |asn1_ex_i2d| should never return zero. We have already checked |
198 | | // for optional values generically, and |ASN1_ITYPE_EXTERN| fields |
199 | | // must be pointers. |
200 | 0 | OPENSSL_PUT_ERROR(ASN1, ERR_R_INTERNAL_ERROR); |
201 | 0 | return -1; |
202 | 0 | } |
203 | 677k | return ret; |
204 | 677k | } |
205 | | |
206 | 4.90M | case ASN1_ITYPE_SEQUENCE: { |
207 | 4.90M | i = asn1_enc_restore(&seqcontlen, out, pval, it); |
208 | | // An error occurred |
209 | 4.90M | if (i < 0) { |
210 | 0 | return -1; |
211 | 0 | } |
212 | | // We have a valid cached encoding... |
213 | 4.90M | if (i > 0) { |
214 | 58.1k | return seqcontlen; |
215 | 58.1k | } |
216 | | // Otherwise carry on |
217 | 4.84M | seqcontlen = 0; |
218 | | // If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL |
219 | 4.84M | if (tag == -1) { |
220 | 4.79M | tag = V_ASN1_SEQUENCE; |
221 | 4.79M | aclass = V_ASN1_UNIVERSAL; |
222 | 4.79M | } |
223 | | // First work out sequence content length |
224 | 14.6M | for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { |
225 | 9.79M | const ASN1_TEMPLATE *seqtt; |
226 | 9.79M | ASN1_VALUE **pseqval; |
227 | 9.79M | int tmplen; |
228 | 9.79M | seqtt = asn1_do_adb(pval, tt, 1); |
229 | 9.79M | if (!seqtt) { |
230 | 0 | return -1; |
231 | 0 | } |
232 | 9.79M | pseqval = asn1_get_field_ptr(pval, seqtt); |
233 | 9.79M | tmplen = |
234 | 9.79M | asn1_template_ex_i2d(pseqval, NULL, seqtt, -1, 0, /*optional=*/0); |
235 | 9.79M | if (tmplen == -1 || (tmplen > INT_MAX - seqcontlen)) { |
236 | 208 | return -1; |
237 | 208 | } |
238 | 9.79M | seqcontlen += tmplen; |
239 | 9.79M | } |
240 | | |
241 | 4.84M | seqlen = ASN1_object_size(/*constructed=*/1, seqcontlen, tag); |
242 | 4.84M | if (!out || seqlen == -1) { |
243 | 3.22M | return seqlen; |
244 | 3.22M | } |
245 | | // Output SEQUENCE header |
246 | 1.62M | ASN1_put_object(out, /*constructed=*/1, seqcontlen, tag, aclass); |
247 | 4.91M | for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { |
248 | 3.28M | const ASN1_TEMPLATE *seqtt; |
249 | 3.28M | ASN1_VALUE **pseqval; |
250 | 3.28M | seqtt = asn1_do_adb(pval, tt, 1); |
251 | 3.28M | if (!seqtt) { |
252 | 0 | return -1; |
253 | 0 | } |
254 | 3.28M | pseqval = asn1_get_field_ptr(pval, seqtt); |
255 | 3.28M | if (asn1_template_ex_i2d(pseqval, out, seqtt, -1, 0, /*optional=*/0) < |
256 | 3.28M | 0) { |
257 | 0 | return -1; |
258 | 0 | } |
259 | 3.28M | } |
260 | 1.62M | return seqlen; |
261 | 1.62M | } |
262 | | |
263 | 0 | default: |
264 | 0 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); |
265 | 0 | return -1; |
266 | 23.1M | } |
267 | 23.1M | } |
268 | | |
269 | | // asn1_template_ex_i2d behaves like |asn1_item_ex_i2d_opt| but uses an |
270 | | // |ASN1_TEMPLATE| instead of an |ASN1_ITEM|. An |ASN1_TEMPLATE| wraps an |
271 | | // |ASN1_ITEM| with modifiers such as tagging, SEQUENCE or SET, etc. |
272 | | static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out, |
273 | | const ASN1_TEMPLATE *tt, int tag, int iclass, |
274 | 16.7M | int optional) { |
275 | 16.7M | int i, ret, ttag, tclass; |
276 | 16.7M | size_t j; |
277 | 16.7M | uint32_t flags = tt->flags; |
278 | | |
279 | | // Historically, |iclass| was repurposed to pass additional flags into the |
280 | | // encoding process. |
281 | 16.7M | assert((iclass & ASN1_TFLG_TAG_CLASS) == iclass); |
282 | | // If not overridding the tag, |iclass| is ignored and should be zero. |
283 | 16.7M | assert(tag != -1 || iclass == 0); |
284 | | |
285 | | // Work out tag and class to use: tagging may come either from the |
286 | | // template or the arguments, not both because this would create |
287 | | // ambiguity. |
288 | 16.7M | if (flags & ASN1_TFLG_TAG_MASK) { |
289 | | // Error if argument and template tagging |
290 | 1.92M | if (tag != -1) { |
291 | 0 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); |
292 | 0 | return -1; |
293 | 0 | } |
294 | | // Get tagging from template |
295 | 1.92M | ttag = tt->tag; |
296 | 1.92M | tclass = flags & ASN1_TFLG_TAG_CLASS; |
297 | 14.8M | } else if (tag != -1) { |
298 | | // No template tagging, get from arguments |
299 | 0 | ttag = tag; |
300 | 0 | tclass = iclass & ASN1_TFLG_TAG_CLASS; |
301 | 14.8M | } else { |
302 | 14.8M | ttag = -1; |
303 | 14.8M | tclass = 0; |
304 | 14.8M | } |
305 | | |
306 | | // The template may itself by marked as optional, or this may be the template |
307 | | // of an |ASN1_ITEM_TEMPLATE| type which was contained inside an outer |
308 | | // optional template. (They cannot both be true because the |
309 | | // |ASN1_ITEM_TEMPLATE| codepath rejects optional templates.) |
310 | 16.7M | assert(!optional || (flags & ASN1_TFLG_OPTIONAL) == 0); |
311 | 16.7M | optional = optional || (flags & ASN1_TFLG_OPTIONAL) != 0; |
312 | | |
313 | | // At this point 'ttag' contains the outer tag to use, and 'tclass' is the |
314 | | // class. |
315 | | |
316 | 16.7M | if (flags & ASN1_TFLG_SK_MASK) { |
317 | | // SET OF, SEQUENCE OF |
318 | 2.30M | STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval; |
319 | 2.30M | int isset, sktag, skaclass; |
320 | 2.30M | int skcontlen, sklen; |
321 | 2.30M | ASN1_VALUE *skitem; |
322 | | |
323 | 2.30M | if (!*pval) { |
324 | 32.8k | if (optional) { |
325 | 32.8k | return 0; |
326 | 32.8k | } |
327 | 0 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE); |
328 | 0 | return -1; |
329 | 32.8k | } |
330 | | |
331 | 2.27M | if (flags & ASN1_TFLG_SET_OF) { |
332 | 1.94M | isset = 1; |
333 | | // Historically, types with both bits set were mutated when |
334 | | // serialized to apply the sort. We no longer support this. |
335 | 1.94M | assert((flags & ASN1_TFLG_SEQUENCE_OF) == 0); |
336 | 1.94M | } else { |
337 | 323k | isset = 0; |
338 | 323k | } |
339 | | |
340 | | // Work out inner tag value: if EXPLICIT or no tagging use underlying |
341 | | // type. |
342 | 2.27M | if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG)) { |
343 | 99.5k | sktag = ttag; |
344 | 99.5k | skaclass = tclass; |
345 | 2.17M | } else { |
346 | 2.17M | skaclass = V_ASN1_UNIVERSAL; |
347 | 2.17M | if (isset) { |
348 | 1.94M | sktag = V_ASN1_SET; |
349 | 1.94M | } else { |
350 | 227k | sktag = V_ASN1_SEQUENCE; |
351 | 227k | } |
352 | 2.17M | } |
353 | | |
354 | | // Determine total length of items |
355 | 2.27M | skcontlen = 0; |
356 | 6.56M | for (j = 0; j < sk_ASN1_VALUE_num(sk); j++) { |
357 | 4.28M | int tmplen; |
358 | 4.28M | skitem = sk_ASN1_VALUE_value(sk, j); |
359 | 4.28M | tmplen = ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item), -1, 0); |
360 | 4.28M | if (tmplen == -1 || (skcontlen > INT_MAX - tmplen)) { |
361 | 243 | return -1; |
362 | 243 | } |
363 | 4.28M | skcontlen += tmplen; |
364 | 4.28M | } |
365 | 2.27M | sklen = ASN1_object_size(/*constructed=*/1, skcontlen, sktag); |
366 | 2.27M | if (sklen == -1) { |
367 | 0 | return -1; |
368 | 0 | } |
369 | | // If EXPLICIT need length of surrounding tag |
370 | 2.27M | if (flags & ASN1_TFLG_EXPTAG) { |
371 | 0 | ret = ASN1_object_size(/*constructed=*/1, sklen, ttag); |
372 | 2.27M | } else { |
373 | 2.27M | ret = sklen; |
374 | 2.27M | } |
375 | | |
376 | 2.27M | if (!out || ret == -1) { |
377 | 1.23M | return ret; |
378 | 1.23M | } |
379 | | |
380 | | // Now encode this lot... |
381 | | // EXPLICIT tag |
382 | 1.03M | if (flags & ASN1_TFLG_EXPTAG) { |
383 | 0 | ASN1_put_object(out, /*constructed=*/1, sklen, ttag, tclass); |
384 | 0 | } |
385 | | // SET or SEQUENCE and IMPLICIT tag |
386 | 1.03M | ASN1_put_object(out, /*constructed=*/1, skcontlen, sktag, skaclass); |
387 | | // And the stuff itself |
388 | 1.03M | if (!asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item), isset)) { |
389 | 0 | return -1; |
390 | 0 | } |
391 | 1.03M | return ret; |
392 | 1.03M | } |
393 | | |
394 | 14.4M | if (flags & ASN1_TFLG_EXPTAG) { |
395 | | // EXPLICIT tagging |
396 | | // Find length of tagged item |
397 | 727k | i = asn1_item_ex_i2d_opt(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, 0, |
398 | 727k | optional); |
399 | 727k | if (i <= 0) { |
400 | 95.1k | return i; |
401 | 95.1k | } |
402 | | // Find length of EXPLICIT tag |
403 | 632k | ret = ASN1_object_size(/*constructed=*/1, i, ttag); |
404 | 632k | if (out && ret != -1) { |
405 | | // Output tag and item |
406 | 125k | ASN1_put_object(out, /*constructed=*/1, i, ttag, tclass); |
407 | 125k | if (ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, 0) < 0) { |
408 | 0 | return -1; |
409 | 0 | } |
410 | 125k | } |
411 | 632k | return ret; |
412 | 632k | } |
413 | | |
414 | | // Either normal or IMPLICIT tagging |
415 | 13.7M | return asn1_item_ex_i2d_opt(pval, out, ASN1_ITEM_ptr(tt->item), ttag, tclass, |
416 | 13.7M | optional); |
417 | 14.4M | } |
418 | | |
419 | | // Temporary structure used to hold DER encoding of items for SET OF |
420 | | |
421 | | typedef struct { |
422 | | unsigned char *data; |
423 | | int length; |
424 | | } DER_ENC; |
425 | | |
426 | 500k | static int der_cmp(const void *a, const void *b) { |
427 | 500k | const DER_ENC *d1 = a, *d2 = b; |
428 | 500k | int cmplen, i; |
429 | 500k | cmplen = (d1->length < d2->length) ? d1->length : d2->length; |
430 | 500k | i = OPENSSL_memcmp(d1->data, d2->data, cmplen); |
431 | 500k | if (i) { |
432 | 450k | return i; |
433 | 450k | } |
434 | 50.0k | return d1->length - d2->length; |
435 | 500k | } |
436 | | |
437 | | // asn1_set_seq_out writes |sk| to |out| under the i2d output convention, |
438 | | // excluding the tag and length. It returns one on success and zero on error. |
439 | | // |skcontlen| must be the total encoded size. If |do_sort| is non-zero, the |
440 | | // elements are sorted for a SET OF type. Each element of |sk| has type |
441 | | // |item|. |
442 | | static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, |
443 | 1.03M | int skcontlen, const ASN1_ITEM *item, int do_sort) { |
444 | | // No need to sort if there are fewer than two items. |
445 | 1.03M | if (!do_sort || sk_ASN1_VALUE_num(sk) < 2) { |
446 | 2.13M | for (size_t i = 0; i < sk_ASN1_VALUE_num(sk); i++) { |
447 | 1.25M | ASN1_VALUE *skitem = sk_ASN1_VALUE_value(sk, i); |
448 | 1.25M | if (ASN1_item_ex_i2d(&skitem, out, item, -1, 0) < 0) { |
449 | 0 | return 0; |
450 | 0 | } |
451 | 1.25M | } |
452 | 882k | return 1; |
453 | 882k | } |
454 | | |
455 | 155k | if (sk_ASN1_VALUE_num(sk) > ((size_t)-1) / sizeof(DER_ENC)) { |
456 | 0 | OPENSSL_PUT_ERROR(ASN1, ERR_R_OVERFLOW); |
457 | 0 | return 0; |
458 | 0 | } |
459 | | |
460 | 155k | int ret = 0; |
461 | 155k | unsigned char *const buf = OPENSSL_malloc(skcontlen); |
462 | 155k | DER_ENC *encoded = OPENSSL_malloc(sk_ASN1_VALUE_num(sk) * sizeof(*encoded)); |
463 | 155k | if (encoded == NULL || buf == NULL) { |
464 | 0 | goto err; |
465 | 0 | } |
466 | | |
467 | | // Encode all the elements into |buf| and populate |encoded|. |
468 | 155k | unsigned char *p = buf; |
469 | 642k | for (size_t i = 0; i < sk_ASN1_VALUE_num(sk); i++) { |
470 | 486k | ASN1_VALUE *skitem = sk_ASN1_VALUE_value(sk, i); |
471 | 486k | encoded[i].data = p; |
472 | 486k | encoded[i].length = ASN1_item_ex_i2d(&skitem, &p, item, -1, 0); |
473 | 486k | if (encoded[i].length < 0) { |
474 | 0 | goto err; |
475 | 0 | } |
476 | 486k | assert(p - buf <= skcontlen); |
477 | 486k | } |
478 | | |
479 | 155k | qsort(encoded, sk_ASN1_VALUE_num(sk), sizeof(*encoded), der_cmp); |
480 | | |
481 | | // Output the elements in sorted order. |
482 | 155k | p = *out; |
483 | 642k | for (size_t i = 0; i < sk_ASN1_VALUE_num(sk); i++) { |
484 | 486k | OPENSSL_memcpy(p, encoded[i].data, encoded[i].length); |
485 | 486k | p += encoded[i].length; |
486 | 486k | } |
487 | 155k | *out = p; |
488 | | |
489 | 155k | ret = 1; |
490 | | |
491 | 155k | err: |
492 | 155k | OPENSSL_free(encoded); |
493 | 155k | OPENSSL_free(buf); |
494 | 155k | return ret; |
495 | 155k | } |
496 | | |
497 | | // asn1_i2d_ex_primitive behaves like |ASN1_item_ex_i2d| but |item| must be a |
498 | | // a PRIMITIVE or MSTRING type that is not an |ASN1_ITEM_TEMPLATE|. |
499 | | static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, |
500 | | const ASN1_ITEM *it, int tag, int aclass, |
501 | 13.8M | int optional) { |
502 | | // Get length of content octets and maybe find out the underlying type. |
503 | 13.8M | int omit; |
504 | 13.8M | int utype = it->utype; |
505 | 13.8M | int len = asn1_ex_i2c(pval, NULL, &omit, &utype, it); |
506 | 13.8M | if (len < 0) { |
507 | 211 | return -1; |
508 | 211 | } |
509 | 13.8M | if (omit) { |
510 | 160k | if (optional) { |
511 | 160k | return 0; |
512 | 160k | } |
513 | 0 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE); |
514 | 0 | return -1; |
515 | 160k | } |
516 | | |
517 | | // If SEQUENCE, SET or OTHER then header is included in pseudo content |
518 | | // octets so don't include tag+length. We need to check here because the |
519 | | // call to asn1_ex_i2c() could change utype. |
520 | 13.6M | int usetag = |
521 | 13.6M | utype != V_ASN1_SEQUENCE && utype != V_ASN1_SET && utype != V_ASN1_OTHER; |
522 | | |
523 | | // If not implicitly tagged get tag from underlying type |
524 | 13.6M | if (tag == -1) { |
525 | 12.7M | tag = utype; |
526 | 12.7M | } |
527 | | |
528 | | // Output tag+length followed by content octets |
529 | 13.6M | if (out) { |
530 | 3.42M | if (usetag) { |
531 | 3.39M | ASN1_put_object(out, /*constructed=*/0, len, tag, aclass); |
532 | 3.39M | } |
533 | 3.42M | int len2 = asn1_ex_i2c(pval, *out, &omit, &utype, it); |
534 | 3.42M | if (len2 < 0) { |
535 | 0 | return -1; |
536 | 0 | } |
537 | 3.42M | assert(len == len2); |
538 | 3.42M | assert(!omit); |
539 | 3.42M | *out += len; |
540 | 3.42M | } |
541 | | |
542 | 13.6M | if (usetag) { |
543 | 13.5M | return ASN1_object_size(/*constructed=*/0, len, tag); |
544 | 13.5M | } |
545 | 111k | return len; |
546 | 13.6M | } |
547 | | |
548 | | // asn1_ex_i2c writes the |*pval| to |cout| under the i2d output convention, |
549 | | // excluding the tag and length. It returns the number of bytes written, |
550 | | // possibly zero, on success or -1 on error. If |*pval| should be omitted, it |
551 | | // returns zero and sets |*out_omit| to true. |
552 | | // |
553 | | // If |it| is an MSTRING or ANY type, it gets the underlying type from |*pval|, |
554 | | // which must be an |ASN1_STRING| or |ASN1_TYPE|, respectively. It then updates |
555 | | // |*putype| with the tag number of type used, or |V_ASN1_OTHER| if it was not a |
556 | | // universal type. If |*putype| is set to |V_ASN1_SEQUENCE|, |V_ASN1_SET|, or |
557 | | // |V_ASN1_OTHER|, it additionally outputs the tag and length, so the caller |
558 | | // must not do so. |
559 | | // |
560 | | // Otherwise, |*putype| must contain |it->utype|. |
561 | | // |
562 | | // WARNING: Unlike most functions in this file, |asn1_ex_i2c| can return zero |
563 | | // without omitting the element. ASN.1 values may have empty contents. |
564 | | static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *out_omit, |
565 | 17.2M | int *putype, const ASN1_ITEM *it) { |
566 | 17.2M | ASN1_BOOLEAN *tbool = NULL; |
567 | 17.2M | ASN1_STRING *strtmp; |
568 | 17.2M | ASN1_OBJECT *otmp; |
569 | 17.2M | int utype; |
570 | 17.2M | const unsigned char *cont; |
571 | 17.2M | unsigned char c; |
572 | 17.2M | int len; |
573 | | |
574 | | // Historically, |it->funcs| for primitive types contained an |
575 | | // |ASN1_PRIMITIVE_FUNCS| table of callbacks. |
576 | 17.2M | assert(it->funcs == NULL); |
577 | | |
578 | 17.2M | *out_omit = 0; |
579 | | |
580 | | // Should type be omitted? |
581 | 17.2M | if ((it->itype != ASN1_ITYPE_PRIMITIVE) || (it->utype != V_ASN1_BOOLEAN)) { |
582 | 17.2M | if (!*pval) { |
583 | 133k | *out_omit = 1; |
584 | 133k | return 0; |
585 | 133k | } |
586 | 17.2M | } |
587 | | |
588 | 17.1M | if (it->itype == ASN1_ITYPE_MSTRING) { |
589 | | // If MSTRING type set the underlying type |
590 | 7.66M | strtmp = (ASN1_STRING *)*pval; |
591 | 7.66M | utype = strtmp->type; |
592 | 7.66M | if (utype < 0 && utype != V_ASN1_OTHER) { |
593 | | // MSTRINGs can have type -1 when default-constructed. |
594 | 1 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TYPE); |
595 | 1 | return -1; |
596 | 1 | } |
597 | | // Negative INTEGER and ENUMERATED values use |ASN1_STRING| type values |
598 | | // that do not match their corresponding utype values. INTEGERs cannot |
599 | | // participate in MSTRING types, but ENUMERATEDs can. |
600 | | // |
601 | | // TODO(davidben): Is this a bug? Although arguably one of the MSTRING |
602 | | // types should contain more values, rather than less. See |
603 | | // https://crbug.com/boringssl/412. But it is not possible to fit all |
604 | | // possible ANY values into an |ASN1_STRING|, so matching the spec here |
605 | | // is somewhat hopeless. |
606 | 7.66M | if (utype == V_ASN1_NEG_INTEGER) { |
607 | 0 | utype = V_ASN1_INTEGER; |
608 | 7.66M | } else if (utype == V_ASN1_NEG_ENUMERATED) { |
609 | 139k | utype = V_ASN1_ENUMERATED; |
610 | 139k | } |
611 | 7.66M | *putype = utype; |
612 | 9.44M | } else if (it->utype == V_ASN1_ANY) { |
613 | | // If ANY set type and pointer to value |
614 | 224k | ASN1_TYPE *typ; |
615 | 224k | typ = (ASN1_TYPE *)*pval; |
616 | 224k | utype = typ->type; |
617 | 224k | if (utype < 0 && utype != V_ASN1_OTHER) { |
618 | | // |ASN1_TYPE|s can have type -1 when default-constructed. |
619 | 0 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TYPE); |
620 | 0 | return -1; |
621 | 0 | } |
622 | 224k | *putype = utype; |
623 | 224k | pval = &typ->value.asn1_value; |
624 | 9.22M | } else { |
625 | 9.22M | utype = *putype; |
626 | 9.22M | } |
627 | | |
628 | 17.1M | switch (utype) { |
629 | 7.94M | case V_ASN1_OBJECT: |
630 | 7.94M | otmp = (ASN1_OBJECT *)*pval; |
631 | 7.94M | cont = otmp->data; |
632 | 7.94M | len = otmp->length; |
633 | 7.94M | if (len == 0) { |
634 | | // Some |ASN1_OBJECT|s do not have OIDs and cannot be serialized. |
635 | 210 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OBJECT); |
636 | 210 | return -1; |
637 | 210 | } |
638 | 7.94M | break; |
639 | | |
640 | 7.94M | case V_ASN1_NULL: |
641 | 105k | cont = NULL; |
642 | 105k | len = 0; |
643 | 105k | break; |
644 | | |
645 | 30.3k | case V_ASN1_BOOLEAN: |
646 | 30.3k | tbool = (ASN1_BOOLEAN *)pval; |
647 | 30.3k | if (*tbool == ASN1_BOOLEAN_NONE) { |
648 | 27.2k | *out_omit = 1; |
649 | 27.2k | return 0; |
650 | 27.2k | } |
651 | 3.17k | if (it->utype != V_ASN1_ANY) { |
652 | | // Default handling if value == size field then omit |
653 | 655 | if ((*tbool && (it->size > 0)) || (!*tbool && !it->size)) { |
654 | 387 | *out_omit = 1; |
655 | 387 | return 0; |
656 | 387 | } |
657 | 655 | } |
658 | 2.79k | c = *tbool ? 0xff : 0x00; |
659 | 2.79k | cont = &c; |
660 | 2.79k | len = 1; |
661 | 2.79k | break; |
662 | | |
663 | 177k | case V_ASN1_BIT_STRING: { |
664 | 177k | int ret = |
665 | 177k | i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval, cout ? &cout : NULL); |
666 | | // |i2c_ASN1_BIT_STRING| returns zero on error instead of -1. |
667 | 177k | return ret <= 0 ? -1 : ret; |
668 | 3.17k | } |
669 | | |
670 | 26.5k | case V_ASN1_INTEGER: |
671 | 278k | case V_ASN1_ENUMERATED: { |
672 | | // |i2c_ASN1_INTEGER| also handles ENUMERATED. |
673 | 278k | int ret = i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL); |
674 | | // |i2c_ASN1_INTEGER| returns zero on error instead of -1. |
675 | 278k | return ret <= 0 ? -1 : ret; |
676 | 26.5k | } |
677 | | |
678 | 78.7k | case V_ASN1_OCTET_STRING: |
679 | 85.3k | case V_ASN1_NUMERICSTRING: |
680 | 93.5k | case V_ASN1_PRINTABLESTRING: |
681 | 97.4k | case V_ASN1_T61STRING: |
682 | 99.1k | case V_ASN1_VIDEOTEXSTRING: |
683 | 1.17M | case V_ASN1_IA5STRING: |
684 | 1.17M | case V_ASN1_UTCTIME: |
685 | 1.17M | case V_ASN1_GENERALIZEDTIME: |
686 | 1.17M | case V_ASN1_GRAPHICSTRING: |
687 | 1.17M | case V_ASN1_VISIBLESTRING: |
688 | 1.17M | case V_ASN1_GENERALSTRING: |
689 | 1.18M | case V_ASN1_UNIVERSALSTRING: |
690 | 1.19M | case V_ASN1_BMPSTRING: |
691 | 8.42M | case V_ASN1_UTF8STRING: |
692 | 8.54M | case V_ASN1_SEQUENCE: |
693 | 8.55M | case V_ASN1_SET: |
694 | | // This is not a valid |ASN1_ITEM| type, but it appears in |ASN1_TYPE|. |
695 | 8.56M | case V_ASN1_OTHER: |
696 | | // TODO(crbug.com/boringssl/412): This default case should be removed, now |
697 | | // that we've resolved https://crbug.com/boringssl/561. However, it is still |
698 | | // needed to support some edge cases in |ASN1_PRINTABLE|. |ASN1_PRINTABLE| |
699 | | // broadly doesn't tolerate unrecognized universal tags, but except for |
700 | | // eight values that map to |B_ASN1_UNKNOWN| instead of zero. See the |
701 | | // X509Test.NameAttributeValues test. |
702 | 8.57M | default: |
703 | | // All based on ASN1_STRING and handled the same |
704 | 8.57M | strtmp = (ASN1_STRING *)*pval; |
705 | 8.57M | cont = strtmp->data; |
706 | 8.57M | len = strtmp->length; |
707 | 8.57M | break; |
708 | 17.1M | } |
709 | 16.6M | if (cout && len) { |
710 | 3.28M | OPENSSL_memcpy(cout, cont, len); |
711 | 3.28M | } |
712 | 16.6M | return len; |
713 | 17.1M | } |