1 // Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <openssl/asn1.h>
16 
17 #include <assert.h>
18 #include <limits.h>
19 #include <string.h>
20 
21 #include <openssl/asn1t.h>
22 #include <openssl/mem.h>
23 
24 #include "../internal.h"
25 #include "internal.h"
26 
27 
28 static int asn1_item_ex_i2d_opt(ASN1_VALUE **pval, unsigned char **out,
29                                 const ASN1_ITEM *it, int tag, int aclass,
30                                 int optional);
31 static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
32                                  const ASN1_ITEM *it, int tag, int aclass,
33                                  int optional);
34 static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cont, int *out_omit,
35                        int *putype, const ASN1_ITEM *it);
36 static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
37                             int skcontlen, const ASN1_ITEM *item, int do_sort);
38 static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
39                                 const ASN1_TEMPLATE *tt, int tag, int aclass,
40                                 int optional);
41 
42 // Top level i2d equivalents
43 
ASN1_item_i2d(ASN1_VALUE * val,unsigned char ** out,const ASN1_ITEM * it)44 int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it) {
45   if (out && !*out) {
46     unsigned char *p, *buf;
47     int len = ASN1_item_ex_i2d(&val, NULL, it, /*tag=*/-1, /*aclass=*/0);
48     if (len <= 0) {
49       return len;
50     }
51     buf = reinterpret_cast<uint8_t *>(OPENSSL_malloc(len));
52     if (!buf) {
53       return -1;
54     }
55     p = buf;
56     int len2 = ASN1_item_ex_i2d(&val, &p, it, /*tag=*/-1, /*aclass=*/0);
57     if (len2 <= 0) {
58       OPENSSL_free(buf);
59       return len2;
60     }
61     assert(len == len2);
62     *out = buf;
63     return len;
64   }
65 
66   return ASN1_item_ex_i2d(&val, out, it, /*tag=*/-1, /*aclass=*/0);
67 }
68 
69 // Encode an item, taking care of IMPLICIT tagging (if any). This function
70 // performs the normal item handling: it can be used in external types.
71 
ASN1_item_ex_i2d(ASN1_VALUE ** pval,unsigned char ** out,const ASN1_ITEM * it,int tag,int aclass)72 int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
73                      const ASN1_ITEM *it, int tag, int aclass) {
74   int ret = asn1_item_ex_i2d_opt(pval, out, it, tag, aclass, /*optional=*/0);
75   assert(ret != 0);
76   return ret;
77 }
78 
79 // asn1_item_ex_i2d_opt behaves like |ASN1_item_ex_i2d| but, if |optional| is
80 // 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)81 int asn1_item_ex_i2d_opt(ASN1_VALUE **pval, unsigned char **out,
82                          const ASN1_ITEM *it, int tag, int aclass,
83                          int optional) {
84   const ASN1_TEMPLATE *tt = NULL;
85   int i, seqcontlen, seqlen;
86 
87   // Historically, |aclass| was repurposed to pass additional flags into the
88   // encoding process.
89   assert((aclass & ASN1_TFLG_TAG_CLASS) == aclass);
90   // If not overridding the tag, |aclass| is ignored and should be zero.
91   assert(tag != -1 || aclass == 0);
92 
93   // All fields are pointers, except for boolean |ASN1_ITYPE_PRIMITIVE|s.
94   // Optional primitives are handled later.
95   if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval) {
96     if (optional) {
97       return 0;
98     }
99     OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE);
100     return -1;
101   }
102 
103   switch (it->itype) {
104     case ASN1_ITYPE_PRIMITIVE:
105       if (it->templates) {
106         // This is an |ASN1_ITEM_TEMPLATE|.
107         if (it->templates->flags & ASN1_TFLG_OPTIONAL) {
108           OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE);
109           return -1;
110         }
111         return asn1_template_ex_i2d(pval, out, it->templates, tag, aclass,
112                                     optional);
113       }
114       return asn1_i2d_ex_primitive(pval, out, it, tag, aclass, optional);
115 
116     case ASN1_ITYPE_MSTRING:
117       // It never makes sense for multi-strings to have implicit tagging, so
118       // if tag != -1, then this looks like an error in the template.
119       if (tag != -1) {
120         OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE);
121         return -1;
122       }
123       return asn1_i2d_ex_primitive(pval, out, it, -1, 0, optional);
124 
125     case ASN1_ITYPE_CHOICE: {
126       // It never makes sense for CHOICE types to have implicit tagging, so if
127       // tag != -1, then this looks like an error in the template.
128       if (tag != -1) {
129         OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE);
130         return -1;
131       }
132       i = asn1_get_choice_selector(pval, it);
133       if (i < 0 || i >= it->tcount) {
134         OPENSSL_PUT_ERROR(ASN1, ASN1_R_NO_MATCHING_CHOICE_TYPE);
135         return -1;
136       }
137       const ASN1_TEMPLATE *chtt = it->templates + i;
138       if (chtt->flags & ASN1_TFLG_OPTIONAL) {
139         OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE);
140         return -1;
141       }
142       ASN1_VALUE **pchval = asn1_get_field_ptr(pval, chtt);
143       return asn1_template_ex_i2d(pchval, out, chtt, -1, 0, /*optional=*/0);
144     }
145 
146     case ASN1_ITYPE_EXTERN: {
147       // We don't support implicit tagging with external types.
148       if (tag != -1) {
149         OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE);
150         return -1;
151       }
152       const ASN1_EXTERN_FUNCS *ef =
153           reinterpret_cast<const ASN1_EXTERN_FUNCS *>(it->funcs);
154       int ret = ef->asn1_ex_i2d(pval, out, it);
155       if (ret == 0) {
156         // |asn1_ex_i2d| should never return zero. We have already checked
157         // for optional values generically, and |ASN1_ITYPE_EXTERN| fields
158         // must be pointers.
159         OPENSSL_PUT_ERROR(ASN1, ERR_R_INTERNAL_ERROR);
160         return -1;
161       }
162       return ret;
163     }
164 
165     case ASN1_ITYPE_SEQUENCE: {
166       i = asn1_enc_restore(&seqcontlen, out, pval, it);
167       // An error occurred
168       if (i < 0) {
169         return -1;
170       }
171       // We have a valid cached encoding...
172       if (i > 0) {
173         return seqcontlen;
174       }
175       // Otherwise carry on
176       seqcontlen = 0;
177       // If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL
178       if (tag == -1) {
179         tag = V_ASN1_SEQUENCE;
180         aclass = V_ASN1_UNIVERSAL;
181       }
182       // First work out sequence content length
183       for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
184         const ASN1_TEMPLATE *seqtt;
185         ASN1_VALUE **pseqval;
186         int tmplen;
187         seqtt = asn1_do_adb(pval, tt, 1);
188         if (!seqtt) {
189           return -1;
190         }
191         pseqval = asn1_get_field_ptr(pval, seqtt);
192         tmplen =
193             asn1_template_ex_i2d(pseqval, NULL, seqtt, -1, 0, /*optional=*/0);
194         if (tmplen == -1 || (tmplen > INT_MAX - seqcontlen)) {
195           return -1;
196         }
197         seqcontlen += tmplen;
198       }
199 
200       seqlen = ASN1_object_size(/*constructed=*/1, seqcontlen, tag);
201       if (!out || seqlen == -1) {
202         return seqlen;
203       }
204       // Output SEQUENCE header
205       ASN1_put_object(out, /*constructed=*/1, seqcontlen, tag, aclass);
206       for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
207         const ASN1_TEMPLATE *seqtt;
208         ASN1_VALUE **pseqval;
209         seqtt = asn1_do_adb(pval, tt, 1);
210         if (!seqtt) {
211           return -1;
212         }
213         pseqval = asn1_get_field_ptr(pval, seqtt);
214         if (asn1_template_ex_i2d(pseqval, out, seqtt, -1, 0, /*optional=*/0) <
215             0) {
216           return -1;
217         }
218       }
219       return seqlen;
220     }
221 
222     default:
223       OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE);
224       return -1;
225   }
226 }
227 
228 // asn1_template_ex_i2d behaves like |asn1_item_ex_i2d_opt| but uses an
229 // |ASN1_TEMPLATE| instead of an |ASN1_ITEM|. An |ASN1_TEMPLATE| wraps an
230 // |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)231 static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
232                                 const ASN1_TEMPLATE *tt, int tag, int iclass,
233                                 int optional) {
234   int i, ret, ttag, tclass;
235   size_t j;
236   uint32_t flags = tt->flags;
237 
238   // Historically, |iclass| was repurposed to pass additional flags into the
239   // encoding process.
240   assert((iclass & ASN1_TFLG_TAG_CLASS) == iclass);
241   // If not overridding the tag, |iclass| is ignored and should be zero.
242   assert(tag != -1 || iclass == 0);
243 
244   // Work out tag and class to use: tagging may come either from the
245   // template or the arguments, not both because this would create
246   // ambiguity.
247   if (flags & ASN1_TFLG_TAG_MASK) {
248     // Error if argument and template tagging
249     if (tag != -1) {
250       OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE);
251       return -1;
252     }
253     // Get tagging from template
254     ttag = tt->tag;
255     tclass = flags & ASN1_TFLG_TAG_CLASS;
256   } else if (tag != -1) {
257     // No template tagging, get from arguments
258     ttag = tag;
259     tclass = iclass & ASN1_TFLG_TAG_CLASS;
260   } else {
261     ttag = -1;
262     tclass = 0;
263   }
264 
265   // The template may itself by marked as optional, or this may be the template
266   // of an |ASN1_ITEM_TEMPLATE| type which was contained inside an outer
267   // optional template. (They cannot both be true because the
268   // |ASN1_ITEM_TEMPLATE| codepath rejects optional templates.)
269   assert(!optional || (flags & ASN1_TFLG_OPTIONAL) == 0);
270   optional = optional || (flags & ASN1_TFLG_OPTIONAL) != 0;
271 
272   // At this point 'ttag' contains the outer tag to use, and 'tclass' is the
273   // class.
274 
275   if (flags & ASN1_TFLG_SK_MASK) {
276     // SET OF, SEQUENCE OF
277     STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
278     int isset, sktag, skaclass;
279     int skcontlen, sklen;
280     ASN1_VALUE *skitem;
281 
282     if (!*pval) {
283       if (optional) {
284         return 0;
285       }
286       OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE);
287       return -1;
288     }
289 
290     if (flags & ASN1_TFLG_SET_OF) {
291       isset = 1;
292       // Historically, types with both bits set were mutated when
293       // serialized to apply the sort. We no longer support this.
294       assert((flags & ASN1_TFLG_SEQUENCE_OF) == 0);
295     } else {
296       isset = 0;
297     }
298 
299     // Work out inner tag value: if EXPLICIT or no tagging use underlying
300     // type.
301     if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG)) {
302       sktag = ttag;
303       skaclass = tclass;
304     } else {
305       skaclass = V_ASN1_UNIVERSAL;
306       if (isset) {
307         sktag = V_ASN1_SET;
308       } else {
309         sktag = V_ASN1_SEQUENCE;
310       }
311     }
312 
313     // Determine total length of items
314     skcontlen = 0;
315     for (j = 0; j < sk_ASN1_VALUE_num(sk); j++) {
316       int tmplen;
317       skitem = sk_ASN1_VALUE_value(sk, j);
318       tmplen = ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item), -1, 0);
319       if (tmplen == -1 || (skcontlen > INT_MAX - tmplen)) {
320         return -1;
321       }
322       skcontlen += tmplen;
323     }
324     sklen = ASN1_object_size(/*constructed=*/1, skcontlen, sktag);
325     if (sklen == -1) {
326       return -1;
327     }
328     // If EXPLICIT need length of surrounding tag
329     if (flags & ASN1_TFLG_EXPTAG) {
330       ret = ASN1_object_size(/*constructed=*/1, sklen, ttag);
331     } else {
332       ret = sklen;
333     }
334 
335     if (!out || ret == -1) {
336       return ret;
337     }
338 
339     // Now encode this lot...
340     // EXPLICIT tag
341     if (flags & ASN1_TFLG_EXPTAG) {
342       ASN1_put_object(out, /*constructed=*/1, sklen, ttag, tclass);
343     }
344     // SET or SEQUENCE and IMPLICIT tag
345     ASN1_put_object(out, /*constructed=*/1, skcontlen, sktag, skaclass);
346     // And the stuff itself
347     if (!asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item), isset)) {
348       return -1;
349     }
350     return ret;
351   }
352 
353   if (flags & ASN1_TFLG_EXPTAG) {
354     // EXPLICIT tagging
355     // Find length of tagged item
356     i = asn1_item_ex_i2d_opt(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, 0,
357                              optional);
358     if (i <= 0) {
359       return i;
360     }
361     // Find length of EXPLICIT tag
362     ret = ASN1_object_size(/*constructed=*/1, i, ttag);
363     if (out && ret != -1) {
364       // Output tag and item
365       ASN1_put_object(out, /*constructed=*/1, i, ttag, tclass);
366       if (ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, 0) < 0) {
367         return -1;
368       }
369     }
370     return ret;
371   }
372 
373   // Either normal or IMPLICIT tagging
374   return asn1_item_ex_i2d_opt(pval, out, ASN1_ITEM_ptr(tt->item), ttag, tclass,
375                               optional);
376 }
377 
378 // Temporary structure used to hold DER encoding of items for SET OF
379 
380 typedef struct {
381   unsigned char *data;
382   int length;
383 } DER_ENC;
384 
der_cmp(const void * a,const void * b)385 static int der_cmp(const void *a, const void *b) {
386   const DER_ENC *d1 = reinterpret_cast<const DER_ENC *>(a),
387                 *d2 = reinterpret_cast<const DER_ENC *>(b);
388   int cmplen, i;
389   cmplen = (d1->length < d2->length) ? d1->length : d2->length;
390   i = OPENSSL_memcmp(d1->data, d2->data, cmplen);
391   if (i) {
392     return i;
393   }
394   return d1->length - d2->length;
395 }
396 
397 // asn1_set_seq_out writes |sk| to |out| under the i2d output convention,
398 // excluding the tag and length. It returns one on success and zero on error.
399 // |skcontlen| must be the total encoded size. If |do_sort| is non-zero, the
400 // elements are sorted for a SET OF type. Each element of |sk| has type
401 // |item|.
asn1_set_seq_out(STACK_OF (ASN1_VALUE)* sk,unsigned char ** out,int skcontlen,const ASN1_ITEM * item,int do_sort)402 static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
403                             int skcontlen, const ASN1_ITEM *item, int do_sort) {
404   // No need to sort if there are fewer than two items.
405   if (!do_sort || sk_ASN1_VALUE_num(sk) < 2) {
406     for (size_t i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
407       ASN1_VALUE *skitem = sk_ASN1_VALUE_value(sk, i);
408       if (ASN1_item_ex_i2d(&skitem, out, item, -1, 0) < 0) {
409         return 0;
410       }
411     }
412     return 1;
413   }
414 
415   int ret = 0;
416   uint8_t *const buf = reinterpret_cast<uint8_t *>(OPENSSL_malloc(skcontlen));
417   DER_ENC *encoded = reinterpret_cast<DER_ENC *>(
418       OPENSSL_calloc(sk_ASN1_VALUE_num(sk), sizeof(*encoded)));
419   uint8_t *p = buf;
420   if (encoded == NULL || buf == NULL) {
421     goto err;
422   }
423 
424   // Encode all the elements into |buf| and populate |encoded|.
425   for (size_t i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
426     ASN1_VALUE *skitem = sk_ASN1_VALUE_value(sk, i);
427     encoded[i].data = p;
428     encoded[i].length = ASN1_item_ex_i2d(&skitem, &p, item, -1, 0);
429     if (encoded[i].length < 0) {
430       goto err;
431     }
432     assert(p - buf <= skcontlen);
433   }
434 
435   qsort(encoded, sk_ASN1_VALUE_num(sk), sizeof(*encoded), der_cmp);
436 
437   // Output the elements in sorted order.
438   p = *out;
439   for (size_t i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
440     OPENSSL_memcpy(p, encoded[i].data, encoded[i].length);
441     p += encoded[i].length;
442   }
443   *out = p;
444 
445   ret = 1;
446 
447 err:
448   OPENSSL_free(encoded);
449   OPENSSL_free(buf);
450   return ret;
451 }
452 
453 // asn1_i2d_ex_primitive behaves like |ASN1_item_ex_i2d| but |item| must be a
454 // 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)455 static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
456                                  const ASN1_ITEM *it, int tag, int aclass,
457                                  int optional) {
458   // Get length of content octets and maybe find out the underlying type.
459   int omit;
460   int utype = it->utype;
461   int len = asn1_ex_i2c(pval, NULL, &omit, &utype, it);
462   if (len < 0) {
463     return -1;
464   }
465   if (omit) {
466     if (optional) {
467       return 0;
468     }
469     OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE);
470     return -1;
471   }
472 
473   // If SEQUENCE, SET or OTHER then header is included in pseudo content
474   // octets so don't include tag+length. We need to check here because the
475   // call to asn1_ex_i2c() could change utype.
476   int usetag =
477       utype != V_ASN1_SEQUENCE && utype != V_ASN1_SET && utype != V_ASN1_OTHER;
478 
479   // If not implicitly tagged get tag from underlying type
480   if (tag == -1) {
481     tag = utype;
482   }
483 
484   // Output tag+length followed by content octets
485   if (out) {
486     if (usetag) {
487       ASN1_put_object(out, /*constructed=*/0, len, tag, aclass);
488     }
489     int len2 = asn1_ex_i2c(pval, *out, &omit, &utype, it);
490     if (len2 < 0) {
491       return -1;
492     }
493     assert(len == len2);
494     assert(!omit);
495     *out += len;
496   }
497 
498   if (usetag) {
499     return ASN1_object_size(/*constructed=*/0, len, tag);
500   }
501   return len;
502 }
503 
504 // asn1_ex_i2c writes the |*pval| to |cout| under the i2d output convention,
505 // excluding the tag and length. It returns the number of bytes written,
506 // possibly zero, on success or -1 on error. If |*pval| should be omitted, it
507 // returns zero and sets |*out_omit| to true.
508 //
509 // If |it| is an MSTRING or ANY type, it gets the underlying type from |*pval|,
510 // which must be an |ASN1_STRING| or |ASN1_TYPE|, respectively. It then updates
511 // |*putype| with the tag number of type used, or |V_ASN1_OTHER| if it was not a
512 // universal type. If |*putype| is set to |V_ASN1_SEQUENCE|, |V_ASN1_SET|, or
513 // |V_ASN1_OTHER|, it additionally outputs the tag and length, so the caller
514 // must not do so.
515 //
516 // Otherwise, |*putype| must contain |it->utype|.
517 //
518 // WARNING: Unlike most functions in this file, |asn1_ex_i2c| can return zero
519 // 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)520 static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *out_omit,
521                        int *putype, const ASN1_ITEM *it) {
522   ASN1_BOOLEAN *tbool = NULL;
523   ASN1_STRING *strtmp;
524   ASN1_OBJECT *otmp;
525   int utype;
526   const unsigned char *cont;
527   unsigned char c;
528   int len;
529 
530   assert(it->itype == ASN1_ITYPE_PRIMITIVE || it->itype == ASN1_ITYPE_MSTRING);
531   // Historically, |it->funcs| for primitive types contained an
532   // |ASN1_PRIMITIVE_FUNCS| table of callbacks.
533   assert(it->funcs == NULL);
534 
535   *out_omit = 0;
536 
537   // Handle omitted optional values for all but BOOLEAN, which uses a
538   // non-pointer representation.
539   if (it->itype != ASN1_ITYPE_PRIMITIVE || it->utype != V_ASN1_BOOLEAN) {
540     if (!*pval) {
541       *out_omit = 1;
542       return 0;
543     }
544   }
545 
546   if (it->itype == ASN1_ITYPE_MSTRING || it->utype == V_ASN1_ANY_AS_STRING) {
547     // If MSTRING type set the underlying type
548     strtmp = (ASN1_STRING *)*pval;
549     utype = strtmp->type;
550     if (utype < 0 && utype != V_ASN1_OTHER) {
551       // MSTRINGs can have type -1 when default-constructed.
552       OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TYPE);
553       return -1;
554     }
555     // Negative INTEGER and ENUMERATED values use |ASN1_STRING| type values that
556     // do not match their corresponding utype values.
557     if (utype == V_ASN1_NEG_INTEGER) {
558       utype = V_ASN1_INTEGER;
559     } else if (utype == V_ASN1_NEG_ENUMERATED) {
560       utype = V_ASN1_ENUMERATED;
561     }
562     *putype = utype;
563   } else if (it->utype == V_ASN1_ANY) {
564     // If ANY set type and pointer to value
565     ASN1_TYPE *typ;
566     typ = (ASN1_TYPE *)*pval;
567     utype = typ->type;
568     if (utype < 0 && utype != V_ASN1_OTHER) {
569       // |ASN1_TYPE|s can have type -1 when default-constructed.
570       OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TYPE);
571       return -1;
572     }
573     *putype = utype;
574     pval = &typ->value.asn1_value;
575   } else {
576     utype = *putype;
577   }
578 
579   switch (utype) {
580     case V_ASN1_OBJECT:
581       otmp = (ASN1_OBJECT *)*pval;
582       cont = otmp->data;
583       len = otmp->length;
584       if (len == 0) {
585         // Some |ASN1_OBJECT|s do not have OIDs and cannot be serialized.
586         OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OBJECT);
587         return -1;
588       }
589       break;
590 
591     case V_ASN1_NULL:
592       cont = NULL;
593       len = 0;
594       break;
595 
596     case V_ASN1_BOOLEAN:
597       tbool = (ASN1_BOOLEAN *)pval;
598       if (*tbool == ASN1_BOOLEAN_NONE) {
599         *out_omit = 1;
600         return 0;
601       }
602       if (it->utype != V_ASN1_ANY) {
603         // Default handling if value == size field then omit
604         if ((*tbool && (it->size > 0)) || (!*tbool && !it->size)) {
605           *out_omit = 1;
606           return 0;
607         }
608       }
609       c = *tbool ? 0xff : 0x00;
610       cont = &c;
611       len = 1;
612       break;
613 
614     case V_ASN1_BIT_STRING: {
615       int ret =
616           i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval, cout ? &cout : NULL);
617       // |i2c_ASN1_BIT_STRING| returns zero on error instead of -1.
618       return ret <= 0 ? -1 : ret;
619     }
620 
621     case V_ASN1_INTEGER:
622     case V_ASN1_ENUMERATED: {
623       // |i2c_ASN1_INTEGER| also handles ENUMERATED.
624       int ret = i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL);
625       // |i2c_ASN1_INTEGER| returns zero on error instead of -1.
626       return ret <= 0 ? -1 : ret;
627     }
628 
629     case V_ASN1_OCTET_STRING:
630     case V_ASN1_NUMERICSTRING:
631     case V_ASN1_PRINTABLESTRING:
632     case V_ASN1_T61STRING:
633     case V_ASN1_VIDEOTEXSTRING:
634     case V_ASN1_IA5STRING:
635     case V_ASN1_UTCTIME:
636     case V_ASN1_GENERALIZEDTIME:
637     case V_ASN1_GRAPHICSTRING:
638     case V_ASN1_VISIBLESTRING:
639     case V_ASN1_GENERALSTRING:
640     case V_ASN1_UNIVERSALSTRING:
641     case V_ASN1_BMPSTRING:
642     case V_ASN1_UTF8STRING:
643     case V_ASN1_SEQUENCE:
644     case V_ASN1_SET:
645     // This is not a valid |ASN1_ITEM| type, but it appears in |ASN1_TYPE|.
646     case V_ASN1_OTHER:
647       // All based on ASN1_STRING and handled the same
648       strtmp = (ASN1_STRING *)*pval;
649       cont = strtmp->data;
650       len = strtmp->length;
651       break;
652 
653     default:
654       OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE);
655       return -1;
656   }
657   if (cout && len) {
658     OPENSSL_memcpy(cout, cont, len);
659   }
660   return len;
661 }
662