1 /* Copyright (C) 1995-1998 Eric Young ([email protected])
2 * All rights reserved.
3 *
4 * This package is an SSL implementation written
5 * by Eric Young ([email protected]).
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 ([email protected]).
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 ([email protected])"
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 ([email protected])"
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
ASN1_item_i2d(ASN1_VALUE * val,unsigned char ** out,const ASN1_ITEM * it)86 int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it) {
87 if (out && !*out) {
88 unsigned char *p, *buf;
89 int len = ASN1_item_ex_i2d(&val, NULL, it, /*tag=*/-1, /*aclass=*/0);
90 if (len <= 0) {
91 return len;
92 }
93 buf = OPENSSL_malloc(len);
94 if (!buf) {
95 return -1;
96 }
97 p = buf;
98 int len2 = ASN1_item_ex_i2d(&val, &p, it, /*tag=*/-1, /*aclass=*/0);
99 if (len2 <= 0) {
100 OPENSSL_free(buf);
101 return len2;
102 }
103 assert(len == len2);
104 *out = buf;
105 return len;
106 }
107
108 return ASN1_item_ex_i2d(&val, out, it, /*tag=*/-1, /*aclass=*/0);
109 }
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
ASN1_item_ex_i2d(ASN1_VALUE ** pval,unsigned char ** out,const ASN1_ITEM * it,int tag,int aclass)114 int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
115 const ASN1_ITEM *it, int tag, int aclass) {
116 int ret = asn1_item_ex_i2d_opt(pval, out, it, tag, aclass, /*optional=*/0);
117 assert(ret != 0);
118 return ret;
119 }
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.
asn1_item_ex_i2d_opt(ASN1_VALUE ** pval,unsigned char ** out,const ASN1_ITEM * it,int tag,int aclass,int optional)123 int asn1_item_ex_i2d_opt(ASN1_VALUE **pval, unsigned char **out,
124 const ASN1_ITEM *it, int tag, int aclass,
125 int optional) {
126 const ASN1_TEMPLATE *tt = NULL;
127 int i, seqcontlen, seqlen;
128
129 // Historically, |aclass| was repurposed to pass additional flags into the
130 // encoding process.
131 assert((aclass & ASN1_TFLG_TAG_CLASS) == aclass);
132 // If not overridding the tag, |aclass| is ignored and should be zero.
133 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 if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval) {
138 if (optional) {
139 return 0;
140 }
141 OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE);
142 return -1;
143 }
144
145 switch (it->itype) {
146 case ASN1_ITYPE_PRIMITIVE:
147 if (it->templates) {
148 // This is an |ASN1_ITEM_TEMPLATE|.
149 if (it->templates->flags & ASN1_TFLG_OPTIONAL) {
150 OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE);
151 return -1;
152 }
153 return asn1_template_ex_i2d(pval, out, it->templates, tag, aclass,
154 optional);
155 }
156 return asn1_i2d_ex_primitive(pval, out, it, tag, aclass, optional);
157
158 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 if (tag != -1) {
162 OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE);
163 return -1;
164 }
165 return asn1_i2d_ex_primitive(pval, out, it, -1, 0, optional);
166
167 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 if (tag != -1) {
171 OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE);
172 return -1;
173 }
174 i = asn1_get_choice_selector(pval, it);
175 if (i < 0 || i >= it->tcount) {
176 OPENSSL_PUT_ERROR(ASN1, ASN1_R_NO_MATCHING_CHOICE_TYPE);
177 return -1;
178 }
179 const ASN1_TEMPLATE *chtt = it->templates + i;
180 if (chtt->flags & ASN1_TFLG_OPTIONAL) {
181 OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE);
182 return -1;
183 }
184 ASN1_VALUE **pchval = asn1_get_field_ptr(pval, chtt);
185 return asn1_template_ex_i2d(pchval, out, chtt, -1, 0, /*optional=*/0);
186 }
187
188 case ASN1_ITYPE_EXTERN: {
189 // We don't support implicit tagging with external types.
190 if (tag != -1) {
191 OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE);
192 return -1;
193 }
194 const ASN1_EXTERN_FUNCS *ef = it->funcs;
195 int ret = ef->asn1_ex_i2d(pval, out, it);
196 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 OPENSSL_PUT_ERROR(ASN1, ERR_R_INTERNAL_ERROR);
201 return -1;
202 }
203 return ret;
204 }
205
206 case ASN1_ITYPE_SEQUENCE: {
207 i = asn1_enc_restore(&seqcontlen, out, pval, it);
208 // An error occurred
209 if (i < 0) {
210 return -1;
211 }
212 // We have a valid cached encoding...
213 if (i > 0) {
214 return seqcontlen;
215 }
216 // Otherwise carry on
217 seqcontlen = 0;
218 // If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL
219 if (tag == -1) {
220 tag = V_ASN1_SEQUENCE;
221 aclass = V_ASN1_UNIVERSAL;
222 }
223 // First work out sequence content length
224 for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
225 const ASN1_TEMPLATE *seqtt;
226 ASN1_VALUE **pseqval;
227 int tmplen;
228 seqtt = asn1_do_adb(pval, tt, 1);
229 if (!seqtt) {
230 return -1;
231 }
232 pseqval = asn1_get_field_ptr(pval, seqtt);
233 tmplen =
234 asn1_template_ex_i2d(pseqval, NULL, seqtt, -1, 0, /*optional=*/0);
235 if (tmplen == -1 || (tmplen > INT_MAX - seqcontlen)) {
236 return -1;
237 }
238 seqcontlen += tmplen;
239 }
240
241 seqlen = ASN1_object_size(/*constructed=*/1, seqcontlen, tag);
242 if (!out || seqlen == -1) {
243 return seqlen;
244 }
245 // Output SEQUENCE header
246 ASN1_put_object(out, /*constructed=*/1, seqcontlen, tag, aclass);
247 for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
248 const ASN1_TEMPLATE *seqtt;
249 ASN1_VALUE **pseqval;
250 seqtt = asn1_do_adb(pval, tt, 1);
251 if (!seqtt) {
252 return -1;
253 }
254 pseqval = asn1_get_field_ptr(pval, seqtt);
255 if (asn1_template_ex_i2d(pseqval, out, seqtt, -1, 0, /*optional=*/0) <
256 0) {
257 return -1;
258 }
259 }
260 return seqlen;
261 }
262
263 default:
264 OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE);
265 return -1;
266 }
267 }
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.
asn1_template_ex_i2d(ASN1_VALUE ** pval,unsigned char ** out,const ASN1_TEMPLATE * tt,int tag,int iclass,int optional)272 static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
273 const ASN1_TEMPLATE *tt, int tag, int iclass,
274 int optional) {
275 int i, ret, ttag, tclass;
276 size_t j;
277 uint32_t flags = tt->flags;
278
279 // Historically, |iclass| was repurposed to pass additional flags into the
280 // encoding process.
281 assert((iclass & ASN1_TFLG_TAG_CLASS) == iclass);
282 // If not overridding the tag, |iclass| is ignored and should be zero.
283 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 if (flags & ASN1_TFLG_TAG_MASK) {
289 // Error if argument and template tagging
290 if (tag != -1) {
291 OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE);
292 return -1;
293 }
294 // Get tagging from template
295 ttag = tt->tag;
296 tclass = flags & ASN1_TFLG_TAG_CLASS;
297 } else if (tag != -1) {
298 // No template tagging, get from arguments
299 ttag = tag;
300 tclass = iclass & ASN1_TFLG_TAG_CLASS;
301 } else {
302 ttag = -1;
303 tclass = 0;
304 }
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 assert(!optional || (flags & ASN1_TFLG_OPTIONAL) == 0);
311 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 if (flags & ASN1_TFLG_SK_MASK) {
317 // SET OF, SEQUENCE OF
318 STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
319 int isset, sktag, skaclass;
320 int skcontlen, sklen;
321 ASN1_VALUE *skitem;
322
323 if (!*pval) {
324 if (optional) {
325 return 0;
326 }
327 OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE);
328 return -1;
329 }
330
331 if (flags & ASN1_TFLG_SET_OF) {
332 isset = 1;
333 // Historically, types with both bits set were mutated when
334 // serialized to apply the sort. We no longer support this.
335 assert((flags & ASN1_TFLG_SEQUENCE_OF) == 0);
336 } else {
337 isset = 0;
338 }
339
340 // Work out inner tag value: if EXPLICIT or no tagging use underlying
341 // type.
342 if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG)) {
343 sktag = ttag;
344 skaclass = tclass;
345 } else {
346 skaclass = V_ASN1_UNIVERSAL;
347 if (isset) {
348 sktag = V_ASN1_SET;
349 } else {
350 sktag = V_ASN1_SEQUENCE;
351 }
352 }
353
354 // Determine total length of items
355 skcontlen = 0;
356 for (j = 0; j < sk_ASN1_VALUE_num(sk); j++) {
357 int tmplen;
358 skitem = sk_ASN1_VALUE_value(sk, j);
359 tmplen = ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item), -1, 0);
360 if (tmplen == -1 || (skcontlen > INT_MAX - tmplen)) {
361 return -1;
362 }
363 skcontlen += tmplen;
364 }
365 sklen = ASN1_object_size(/*constructed=*/1, skcontlen, sktag);
366 if (sklen == -1) {
367 return -1;
368 }
369 // If EXPLICIT need length of surrounding tag
370 if (flags & ASN1_TFLG_EXPTAG) {
371 ret = ASN1_object_size(/*constructed=*/1, sklen, ttag);
372 } else {
373 ret = sklen;
374 }
375
376 if (!out || ret == -1) {
377 return ret;
378 }
379
380 // Now encode this lot...
381 // EXPLICIT tag
382 if (flags & ASN1_TFLG_EXPTAG) {
383 ASN1_put_object(out, /*constructed=*/1, sklen, ttag, tclass);
384 }
385 // SET or SEQUENCE and IMPLICIT tag
386 ASN1_put_object(out, /*constructed=*/1, skcontlen, sktag, skaclass);
387 // And the stuff itself
388 if (!asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item), isset)) {
389 return -1;
390 }
391 return ret;
392 }
393
394 if (flags & ASN1_TFLG_EXPTAG) {
395 // EXPLICIT tagging
396 // Find length of tagged item
397 i = asn1_item_ex_i2d_opt(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, 0,
398 optional);
399 if (i <= 0) {
400 return i;
401 }
402 // Find length of EXPLICIT tag
403 ret = ASN1_object_size(/*constructed=*/1, i, ttag);
404 if (out && ret != -1) {
405 // Output tag and item
406 ASN1_put_object(out, /*constructed=*/1, i, ttag, tclass);
407 if (ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, 0) < 0) {
408 return -1;
409 }
410 }
411 return ret;
412 }
413
414 // Either normal or IMPLICIT tagging
415 return asn1_item_ex_i2d_opt(pval, out, ASN1_ITEM_ptr(tt->item), ttag, tclass,
416 optional);
417 }
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
der_cmp(const void * a,const void * b)426 static int der_cmp(const void *a, const void *b) {
427 const DER_ENC *d1 = a, *d2 = b;
428 int cmplen, i;
429 cmplen = (d1->length < d2->length) ? d1->length : d2->length;
430 i = OPENSSL_memcmp(d1->data, d2->data, cmplen);
431 if (i) {
432 return i;
433 }
434 return d1->length - d2->length;
435 }
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|.
asn1_set_seq_out(STACK_OF (ASN1_VALUE)* sk,unsigned char ** out,int skcontlen,const ASN1_ITEM * item,int do_sort)442 static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
443 int skcontlen, const ASN1_ITEM *item, int do_sort) {
444 // No need to sort if there are fewer than two items.
445 if (!do_sort || sk_ASN1_VALUE_num(sk) < 2) {
446 for (size_t i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
447 ASN1_VALUE *skitem = sk_ASN1_VALUE_value(sk, i);
448 if (ASN1_item_ex_i2d(&skitem, out, item, -1, 0) < 0) {
449 return 0;
450 }
451 }
452 return 1;
453 }
454
455 int ret = 0;
456 unsigned char *const buf = OPENSSL_malloc(skcontlen);
457 DER_ENC *encoded = OPENSSL_calloc(sk_ASN1_VALUE_num(sk), sizeof(*encoded));
458 if (encoded == NULL || buf == NULL) {
459 goto err;
460 }
461
462 // Encode all the elements into |buf| and populate |encoded|.
463 unsigned char *p = buf;
464 for (size_t i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
465 ASN1_VALUE *skitem = sk_ASN1_VALUE_value(sk, i);
466 encoded[i].data = p;
467 encoded[i].length = ASN1_item_ex_i2d(&skitem, &p, item, -1, 0);
468 if (encoded[i].length < 0) {
469 goto err;
470 }
471 assert(p - buf <= skcontlen);
472 }
473
474 qsort(encoded, sk_ASN1_VALUE_num(sk), sizeof(*encoded), der_cmp);
475
476 // Output the elements in sorted order.
477 p = *out;
478 for (size_t i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
479 OPENSSL_memcpy(p, encoded[i].data, encoded[i].length);
480 p += encoded[i].length;
481 }
482 *out = p;
483
484 ret = 1;
485
486 err:
487 OPENSSL_free(encoded);
488 OPENSSL_free(buf);
489 return ret;
490 }
491
492 // asn1_i2d_ex_primitive behaves like |ASN1_item_ex_i2d| but |item| must be a
493 // a PRIMITIVE or MSTRING type that is not an |ASN1_ITEM_TEMPLATE|.
asn1_i2d_ex_primitive(ASN1_VALUE ** pval,unsigned char ** out,const ASN1_ITEM * it,int tag,int aclass,int optional)494 static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
495 const ASN1_ITEM *it, int tag, int aclass,
496 int optional) {
497 // Get length of content octets and maybe find out the underlying type.
498 int omit;
499 int utype = it->utype;
500 int len = asn1_ex_i2c(pval, NULL, &omit, &utype, it);
501 if (len < 0) {
502 return -1;
503 }
504 if (omit) {
505 if (optional) {
506 return 0;
507 }
508 OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE);
509 return -1;
510 }
511
512 // If SEQUENCE, SET or OTHER then header is included in pseudo content
513 // octets so don't include tag+length. We need to check here because the
514 // call to asn1_ex_i2c() could change utype.
515 int usetag =
516 utype != V_ASN1_SEQUENCE && utype != V_ASN1_SET && utype != V_ASN1_OTHER;
517
518 // If not implicitly tagged get tag from underlying type
519 if (tag == -1) {
520 tag = utype;
521 }
522
523 // Output tag+length followed by content octets
524 if (out) {
525 if (usetag) {
526 ASN1_put_object(out, /*constructed=*/0, len, tag, aclass);
527 }
528 int len2 = asn1_ex_i2c(pval, *out, &omit, &utype, it);
529 if (len2 < 0) {
530 return -1;
531 }
532 assert(len == len2);
533 assert(!omit);
534 *out += len;
535 }
536
537 if (usetag) {
538 return ASN1_object_size(/*constructed=*/0, len, tag);
539 }
540 return len;
541 }
542
543 // asn1_ex_i2c writes the |*pval| to |cout| under the i2d output convention,
544 // excluding the tag and length. It returns the number of bytes written,
545 // possibly zero, on success or -1 on error. If |*pval| should be omitted, it
546 // returns zero and sets |*out_omit| to true.
547 //
548 // If |it| is an MSTRING or ANY type, it gets the underlying type from |*pval|,
549 // which must be an |ASN1_STRING| or |ASN1_TYPE|, respectively. It then updates
550 // |*putype| with the tag number of type used, or |V_ASN1_OTHER| if it was not a
551 // universal type. If |*putype| is set to |V_ASN1_SEQUENCE|, |V_ASN1_SET|, or
552 // |V_ASN1_OTHER|, it additionally outputs the tag and length, so the caller
553 // must not do so.
554 //
555 // Otherwise, |*putype| must contain |it->utype|.
556 //
557 // WARNING: Unlike most functions in this file, |asn1_ex_i2c| can return zero
558 // without omitting the element. ASN.1 values may have empty contents.
asn1_ex_i2c(ASN1_VALUE ** pval,unsigned char * cout,int * out_omit,int * putype,const ASN1_ITEM * it)559 static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *out_omit,
560 int *putype, const ASN1_ITEM *it) {
561 ASN1_BOOLEAN *tbool = NULL;
562 ASN1_STRING *strtmp;
563 ASN1_OBJECT *otmp;
564 int utype;
565 const unsigned char *cont;
566 unsigned char c;
567 int len;
568
569 // Historically, |it->funcs| for primitive types contained an
570 // |ASN1_PRIMITIVE_FUNCS| table of callbacks.
571 assert(it->funcs == NULL);
572
573 *out_omit = 0;
574
575 // Should type be omitted?
576 if ((it->itype != ASN1_ITYPE_PRIMITIVE) || (it->utype != V_ASN1_BOOLEAN)) {
577 if (!*pval) {
578 *out_omit = 1;
579 return 0;
580 }
581 }
582
583 if (it->itype == ASN1_ITYPE_MSTRING) {
584 // If MSTRING type set the underlying type
585 strtmp = (ASN1_STRING *)*pval;
586 utype = strtmp->type;
587 if (utype < 0 && utype != V_ASN1_OTHER) {
588 // MSTRINGs can have type -1 when default-constructed.
589 OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TYPE);
590 return -1;
591 }
592 // Negative INTEGER and ENUMERATED values use |ASN1_STRING| type values
593 // that do not match their corresponding utype values. INTEGERs cannot
594 // participate in MSTRING types, but ENUMERATEDs can.
595 //
596 // TODO(davidben): Is this a bug? Although arguably one of the MSTRING
597 // types should contain more values, rather than less. See
598 // https://crbug.com/boringssl/412. But it is not possible to fit all
599 // possible ANY values into an |ASN1_STRING|, so matching the spec here
600 // is somewhat hopeless.
601 if (utype == V_ASN1_NEG_INTEGER) {
602 utype = V_ASN1_INTEGER;
603 } else if (utype == V_ASN1_NEG_ENUMERATED) {
604 utype = V_ASN1_ENUMERATED;
605 }
606 *putype = utype;
607 } else if (it->utype == V_ASN1_ANY) {
608 // If ANY set type and pointer to value
609 ASN1_TYPE *typ;
610 typ = (ASN1_TYPE *)*pval;
611 utype = typ->type;
612 if (utype < 0 && utype != V_ASN1_OTHER) {
613 // |ASN1_TYPE|s can have type -1 when default-constructed.
614 OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TYPE);
615 return -1;
616 }
617 *putype = utype;
618 pval = &typ->value.asn1_value;
619 } else {
620 utype = *putype;
621 }
622
623 switch (utype) {
624 case V_ASN1_OBJECT:
625 otmp = (ASN1_OBJECT *)*pval;
626 cont = otmp->data;
627 len = otmp->length;
628 if (len == 0) {
629 // Some |ASN1_OBJECT|s do not have OIDs and cannot be serialized.
630 OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OBJECT);
631 return -1;
632 }
633 break;
634
635 case V_ASN1_NULL:
636 cont = NULL;
637 len = 0;
638 break;
639
640 case V_ASN1_BOOLEAN:
641 tbool = (ASN1_BOOLEAN *)pval;
642 if (*tbool == ASN1_BOOLEAN_NONE) {
643 *out_omit = 1;
644 return 0;
645 }
646 if (it->utype != V_ASN1_ANY) {
647 // Default handling if value == size field then omit
648 if ((*tbool && (it->size > 0)) || (!*tbool && !it->size)) {
649 *out_omit = 1;
650 return 0;
651 }
652 }
653 c = *tbool ? 0xff : 0x00;
654 cont = &c;
655 len = 1;
656 break;
657
658 case V_ASN1_BIT_STRING: {
659 int ret =
660 i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval, cout ? &cout : NULL);
661 // |i2c_ASN1_BIT_STRING| returns zero on error instead of -1.
662 return ret <= 0 ? -1 : ret;
663 }
664
665 case V_ASN1_INTEGER:
666 case V_ASN1_ENUMERATED: {
667 // |i2c_ASN1_INTEGER| also handles ENUMERATED.
668 int ret = i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL);
669 // |i2c_ASN1_INTEGER| returns zero on error instead of -1.
670 return ret <= 0 ? -1 : ret;
671 }
672
673 case V_ASN1_OCTET_STRING:
674 case V_ASN1_NUMERICSTRING:
675 case V_ASN1_PRINTABLESTRING:
676 case V_ASN1_T61STRING:
677 case V_ASN1_VIDEOTEXSTRING:
678 case V_ASN1_IA5STRING:
679 case V_ASN1_UTCTIME:
680 case V_ASN1_GENERALIZEDTIME:
681 case V_ASN1_GRAPHICSTRING:
682 case V_ASN1_VISIBLESTRING:
683 case V_ASN1_GENERALSTRING:
684 case V_ASN1_UNIVERSALSTRING:
685 case V_ASN1_BMPSTRING:
686 case V_ASN1_UTF8STRING:
687 case V_ASN1_SEQUENCE:
688 case V_ASN1_SET:
689 // This is not a valid |ASN1_ITEM| type, but it appears in |ASN1_TYPE|.
690 case V_ASN1_OTHER:
691 // TODO(crbug.com/boringssl/412): This default case should be removed, now
692 // that we've resolved https://crbug.com/boringssl/561. However, it is still
693 // needed to support some edge cases in |ASN1_PRINTABLE|. |ASN1_PRINTABLE|
694 // broadly doesn't tolerate unrecognized universal tags, but except for
695 // eight values that map to |B_ASN1_UNKNOWN| instead of zero. See the
696 // X509Test.NameAttributeValues test.
697 default:
698 // All based on ASN1_STRING and handled the same
699 strtmp = (ASN1_STRING *)*pval;
700 cont = strtmp->data;
701 len = strtmp->length;
702 break;
703 }
704 if (cout && len) {
705 OPENSSL_memcpy(cout, cont, len);
706 }
707 return len;
708 }
709