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