1 /* $OpenBSD: tasn_enc.c,v 1.23 2020/12/08 15:06:42 tb Exp $ */
2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 * project 2000.
4 */
5 /* ====================================================================
6 * Copyright (c) 2000-2004 The OpenSSL Project. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgment:
22 * "This product includes software developed by the OpenSSL Project
23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 * endorse or promote products derived from this software without
27 * prior written permission. For written permission, please contact
28 * licensing@OpenSSL.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 * nor may "OpenSSL" appear in their names without prior written
32 * permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 * acknowledgment:
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com). This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58
59 #include <stddef.h>
60 #include <string.h>
61
62 #include <openssl/asn1.h>
63 #include <openssl/asn1t.h>
64 #include <openssl/err.h>
65 #include <openssl/objects.h>
66
67 static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
68 const ASN1_ITEM *it, int tag, int aclass);
69 static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
70 int skcontlen, const ASN1_ITEM *item, int do_sort, int iclass);
71 static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
72 const ASN1_TEMPLATE *tt, int tag, int aclass);
73 static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
74 const ASN1_ITEM *it, int flags);
75 static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
76 const ASN1_ITEM *it);
77
78 /* Top level i2d equivalents: the 'ndef' variant instructs the encoder
79 * to use indefinite length constructed encoding, where appropriate
80 */
81
82 int
ASN1_item_ndef_i2d(ASN1_VALUE * val,unsigned char ** out,const ASN1_ITEM * it)83 ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it)
84 {
85 return asn1_item_flags_i2d(val, out, it, ASN1_TFLG_NDEF);
86 }
87
88 int
ASN1_item_i2d(ASN1_VALUE * val,unsigned char ** out,const ASN1_ITEM * it)89 ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it)
90 {
91 return asn1_item_flags_i2d(val, out, it, 0);
92 }
93
94 /* Encode an ASN1 item, this is use by the
95 * standard 'i2d' function. 'out' points to
96 * a buffer to output the data to.
97 *
98 * The new i2d has one additional feature. If the output
99 * buffer is NULL (i.e. *out == NULL) then a buffer is
100 * allocated and populated with the encoding.
101 */
102
103 static int
asn1_item_flags_i2d(ASN1_VALUE * val,unsigned char ** out,const ASN1_ITEM * it,int flags)104 asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it,
105 int flags)
106 {
107 if (out && !*out) {
108 unsigned char *p, *buf;
109 int len;
110 len = ASN1_item_ex_i2d(&val, NULL, it, -1, flags);
111 if (len <= 0)
112 return len;
113 buf = malloc(len);
114 if (!buf)
115 return -1;
116 p = buf;
117 ASN1_item_ex_i2d(&val, &p, it, -1, flags);
118 *out = buf;
119 return len;
120 }
121
122 return ASN1_item_ex_i2d(&val, out, it, -1, flags);
123 }
124
125 /* Encode an item, taking care of IMPLICIT tagging (if any).
126 * This function performs the normal item handling: it can be
127 * used in external types.
128 */
129
130 int
ASN1_item_ex_i2d(ASN1_VALUE ** pval,unsigned char ** out,const ASN1_ITEM * it,int tag,int aclass)131 ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it,
132 int tag, int aclass)
133 {
134 const ASN1_TEMPLATE *tt = NULL;
135 int i, seqcontlen, seqlen, ndef = 1;
136 const ASN1_EXTERN_FUNCS *ef;
137 const ASN1_AUX *aux = it->funcs;
138 ASN1_aux_cb *asn1_cb = NULL;
139
140 if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
141 return 0;
142
143 if (aux && aux->asn1_cb)
144 asn1_cb = aux->asn1_cb;
145
146 switch (it->itype) {
147
148 case ASN1_ITYPE_PRIMITIVE:
149 if (it->templates)
150 return asn1_template_ex_i2d(pval, out, it->templates,
151 tag, aclass);
152 return asn1_i2d_ex_primitive(pval, out, it, tag, aclass);
153 break;
154
155 case ASN1_ITYPE_MSTRING:
156 /*
157 * It never makes sense for multi-strings to have implicit
158 * tagging, so if tag != -1, then this looks like an error in
159 * the template.
160 */
161 if (tag != -1) {
162 ASN1error(ASN1_R_BAD_TEMPLATE);
163 return 0;
164 }
165 return asn1_i2d_ex_primitive(pval, out, it, -1, aclass);
166
167 case ASN1_ITYPE_CHOICE:
168 /*
169 * It never makes sense for CHOICE types to have implicit
170 * tagging, so if tag != -1, then this looks like an error in
171 * the template.
172 */
173 if (tag != -1) {
174 ASN1error(ASN1_R_BAD_TEMPLATE);
175 return 0;
176 }
177 if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
178 return 0;
179 i = asn1_get_choice_selector(pval, it);
180 if ((i >= 0) && (i < it->tcount)) {
181 ASN1_VALUE **pchval;
182 const ASN1_TEMPLATE *chtt;
183 chtt = it->templates + i;
184 pchval = asn1_get_field_ptr(pval, chtt);
185 return asn1_template_ex_i2d(pchval, out, chtt,
186 -1, aclass);
187 }
188 /* Fixme: error condition if selector out of range */
189 if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
190 return 0;
191 break;
192
193 case ASN1_ITYPE_EXTERN:
194 /* If new style i2d it does all the work */
195 ef = it->funcs;
196 return ef->asn1_ex_i2d(pval, out, it, tag, aclass);
197
198 case ASN1_ITYPE_NDEF_SEQUENCE:
199 /* Use indefinite length constructed if requested */
200 if (aclass & ASN1_TFLG_NDEF)
201 ndef = 2;
202 /* fall through */
203
204 case ASN1_ITYPE_SEQUENCE:
205 i = asn1_enc_restore(&seqcontlen, out, pval, it);
206 /* An error occurred */
207 if (i < 0)
208 return 0;
209 /* We have a valid cached encoding... */
210 if (i > 0)
211 return seqcontlen;
212 /* Otherwise carry on */
213 seqcontlen = 0;
214 /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */
215 if (tag == -1) {
216 tag = V_ASN1_SEQUENCE;
217 /* Retain any other flags in aclass */
218 aclass = (aclass & ~ASN1_TFLG_TAG_CLASS) |
219 V_ASN1_UNIVERSAL;
220 }
221 if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
222 return 0;
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 seqtt = asn1_do_adb(pval, tt, 1);
228 if (!seqtt)
229 return 0;
230 pseqval = asn1_get_field_ptr(pval, seqtt);
231 /* FIXME: check for errors in enhanced version */
232 seqcontlen += asn1_template_ex_i2d(pseqval, NULL, seqtt,
233 -1, aclass);
234 }
235
236 seqlen = ASN1_object_size(ndef, seqcontlen, tag);
237 if (!out)
238 return seqlen;
239 /* Output SEQUENCE header */
240 ASN1_put_object(out, ndef, seqcontlen, tag, aclass);
241 for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
242 const ASN1_TEMPLATE *seqtt;
243 ASN1_VALUE **pseqval;
244 seqtt = asn1_do_adb(pval, tt, 1);
245 if (!seqtt)
246 return 0;
247 pseqval = asn1_get_field_ptr(pval, seqtt);
248 /* FIXME: check for errors in enhanced version */
249 asn1_template_ex_i2d(pseqval, out, seqtt, -1, aclass);
250 }
251 if (ndef == 2)
252 ASN1_put_eoc(out);
253 if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
254 return 0;
255 return seqlen;
256
257 default:
258 return 0;
259
260 }
261 return 0;
262 }
263
264 int
ASN1_template_i2d(ASN1_VALUE ** pval,unsigned char ** out,const ASN1_TEMPLATE * tt)265 ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out,
266 const ASN1_TEMPLATE *tt)
267 {
268 return asn1_template_ex_i2d(pval, out, tt, -1, 0);
269 }
270
271 static int
asn1_template_ex_i2d(ASN1_VALUE ** pval,unsigned char ** out,const ASN1_TEMPLATE * tt,int tag,int iclass)272 asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
273 const ASN1_TEMPLATE *tt, int tag, int iclass)
274 {
275 int i, ret, flags, ttag, tclass, ndef;
276 flags = tt->flags;
277 /* Work out tag and class to use: tagging may come
278 * either from the template or the arguments, not both
279 * because this would create ambiguity. Additionally
280 * the iclass argument may contain some additional flags
281 * which should be noted and passed down to other levels.
282 */
283 if (flags & ASN1_TFLG_TAG_MASK) {
284 /* Error if argument and template tagging */
285 if (tag != -1)
286 /* FIXME: error code here */
287 return -1;
288 /* Get tagging from template */
289 ttag = tt->tag;
290 tclass = flags & ASN1_TFLG_TAG_CLASS;
291 } else if (tag != -1) {
292 /* No template tagging, get from arguments */
293 ttag = tag;
294 tclass = iclass & ASN1_TFLG_TAG_CLASS;
295 } else {
296 ttag = -1;
297 tclass = 0;
298 }
299 /*
300 * Remove any class mask from iflag.
301 */
302 iclass &= ~ASN1_TFLG_TAG_CLASS;
303
304 /* At this point 'ttag' contains the outer tag to use,
305 * 'tclass' is the class and iclass is any flags passed
306 * to this function.
307 */
308
309 /* if template and arguments require ndef, use it */
310 if ((flags & ASN1_TFLG_NDEF) && (iclass & ASN1_TFLG_NDEF))
311 ndef = 2;
312 else
313 ndef = 1;
314
315 if (flags & ASN1_TFLG_SK_MASK) {
316 /* SET OF, SEQUENCE OF */
317 STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
318 int isset, sktag, skaclass;
319 int skcontlen, sklen;
320 ASN1_VALUE *skitem;
321
322 if (!*pval)
323 return 0;
324
325 if (flags & ASN1_TFLG_SET_OF) {
326 isset = 1;
327 /* 2 means we reorder */
328 if (flags & ASN1_TFLG_SEQUENCE_OF)
329 isset = 2;
330 } else
331 isset = 0;
332
333 /* Work out inner tag value: if EXPLICIT
334 * or no tagging use underlying type.
335 */
336 if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG)) {
337 sktag = ttag;
338 skaclass = tclass;
339 } else {
340 skaclass = V_ASN1_UNIVERSAL;
341 if (isset)
342 sktag = V_ASN1_SET;
343 else
344 sktag = V_ASN1_SEQUENCE;
345 }
346
347 /* Determine total length of items */
348 skcontlen = 0;
349 for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
350 skitem = sk_ASN1_VALUE_value(sk, i);
351 skcontlen += ASN1_item_ex_i2d(&skitem, NULL,
352 tt->item, -1, iclass);
353 }
354 sklen = ASN1_object_size(ndef, skcontlen, sktag);
355 /* If EXPLICIT need length of surrounding tag */
356 if (flags & ASN1_TFLG_EXPTAG)
357 ret = ASN1_object_size(ndef, sklen, ttag);
358 else
359 ret = sklen;
360
361 if (!out)
362 return ret;
363
364 /* Now encode this lot... */
365 /* EXPLICIT tag */
366 if (flags & ASN1_TFLG_EXPTAG)
367 ASN1_put_object(out, ndef, sklen, ttag, tclass);
368 /* SET or SEQUENCE and IMPLICIT tag */
369 ASN1_put_object(out, ndef, skcontlen, sktag, skaclass);
370 /* And the stuff itself */
371 asn1_set_seq_out(sk, out, skcontlen, tt->item,
372 isset, iclass);
373 if (ndef == 2) {
374 ASN1_put_eoc(out);
375 if (flags & ASN1_TFLG_EXPTAG)
376 ASN1_put_eoc(out);
377 }
378
379 return ret;
380 }
381
382 if (flags & ASN1_TFLG_EXPTAG) {
383 /* EXPLICIT tagging */
384 /* Find length of tagged item */
385 i = ASN1_item_ex_i2d(pval, NULL, tt->item,
386 -1, iclass);
387 if (!i)
388 return 0;
389 /* Find length of EXPLICIT tag */
390 ret = ASN1_object_size(ndef, i, ttag);
391 if (out) {
392 /* Output tag and item */
393 ASN1_put_object(out, ndef, i, ttag, tclass);
394 ASN1_item_ex_i2d(pval, out, tt->item,
395 -1, iclass);
396 if (ndef == 2)
397 ASN1_put_eoc(out);
398 }
399 return ret;
400 }
401
402 /* Either normal or IMPLICIT tagging: combine class and flags */
403 return ASN1_item_ex_i2d(pval, out, tt->item,
404 ttag, tclass | iclass);
405 }
406
407 /* Temporary structure used to hold DER encoding of items for SET OF */
408
409 typedef struct {
410 unsigned char *data;
411 int length;
412 ASN1_VALUE *field;
413 } DER_ENC;
414
415 static int
der_cmp(const void * a,const void * b)416 der_cmp(const void *a, const void *b)
417 {
418 const DER_ENC *d1 = a, *d2 = b;
419 int cmplen, i;
420
421 cmplen = (d1->length < d2->length) ? d1->length : d2->length;
422 i = memcmp(d1->data, d2->data, cmplen);
423 if (i)
424 return i;
425 return d1->length - d2->length;
426 }
427
428 /* Output the content octets of SET OF or SEQUENCE OF */
429
430 static int
asn1_set_seq_out(STACK_OF (ASN1_VALUE)* sk,unsigned char ** out,int skcontlen,const ASN1_ITEM * item,int do_sort,int iclass)431 asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, int skcontlen,
432 const ASN1_ITEM *item, int do_sort, int iclass)
433 {
434 int i;
435 ASN1_VALUE *skitem;
436 unsigned char *tmpdat = NULL, *p = NULL;
437 DER_ENC *derlst = NULL, *tder;
438
439 if (do_sort) {
440 /* Don't need to sort less than 2 items */
441 if (sk_ASN1_VALUE_num(sk) < 2)
442 do_sort = 0;
443 else {
444 derlst = reallocarray(NULL, sk_ASN1_VALUE_num(sk),
445 sizeof(*derlst));
446 tmpdat = malloc(skcontlen);
447 if (!derlst || !tmpdat) {
448 free(derlst);
449 free(tmpdat);
450 return 0;
451 }
452 }
453 }
454 /* If not sorting just output each item */
455 if (!do_sort) {
456 for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
457 skitem = sk_ASN1_VALUE_value(sk, i);
458 ASN1_item_ex_i2d(&skitem, out, item, -1, iclass);
459 }
460 return 1;
461 }
462 p = tmpdat;
463
464 /* Doing sort: build up a list of each member's DER encoding */
465 for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
466 skitem = sk_ASN1_VALUE_value(sk, i);
467 tder->data = p;
468 tder->length = ASN1_item_ex_i2d(&skitem, &p, item, -1, iclass);
469 tder->field = skitem;
470 }
471
472 /* Now sort them */
473 qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp);
474 /* Output sorted DER encoding */
475 p = *out;
476 for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
477 memcpy(p, tder->data, tder->length);
478 p += tder->length;
479 }
480 *out = p;
481 /* If do_sort is 2 then reorder the STACK */
482 if (do_sort == 2) {
483 for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++)
484 (void)sk_ASN1_VALUE_set(sk, i, tder->field);
485 }
486 free(derlst);
487 free(tmpdat);
488 return 1;
489 }
490
491 static int
asn1_i2d_ex_primitive(ASN1_VALUE ** pval,unsigned char ** out,const ASN1_ITEM * it,int tag,int aclass)492 asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
493 const ASN1_ITEM *it, int tag, int aclass)
494 {
495 int len;
496 int utype;
497 int usetag;
498 int ndef = 0;
499
500 utype = it->utype;
501
502 /* Get length of content octets and maybe find
503 * out the underlying type.
504 */
505
506 len = asn1_ex_i2c(pval, NULL, &utype, it);
507
508 /* If SEQUENCE, SET or OTHER then header is
509 * included in pseudo content octets so don't
510 * include tag+length. We need to check here
511 * because the call to asn1_ex_i2c() could change
512 * utype.
513 */
514 if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) ||
515 (utype == V_ASN1_OTHER))
516 usetag = 0;
517 else
518 usetag = 1;
519
520 /* -1 means omit type */
521 if (len == -1)
522 return 0;
523
524 /* -2 return is special meaning use ndef */
525 if (len == -2) {
526 ndef = 2;
527 len = 0;
528 }
529
530 /* If not implicitly tagged get tag from underlying type */
531 if (tag == -1)
532 tag = utype;
533
534 /* Output tag+length followed by content octets */
535 if (out) {
536 if (usetag)
537 ASN1_put_object(out, ndef, len, tag, aclass);
538 asn1_ex_i2c(pval, *out, &utype, it);
539 if (ndef)
540 ASN1_put_eoc(out);
541 else
542 *out += len;
543 }
544
545 if (usetag)
546 return ASN1_object_size(ndef, len, tag);
547 return len;
548 }
549
550 /* Produce content octets from a structure */
551
552 static int
asn1_ex_i2c(ASN1_VALUE ** pval,unsigned char * cout,int * putype,const ASN1_ITEM * it)553 asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
554 const ASN1_ITEM *it)
555 {
556 ASN1_BOOLEAN *tbool = NULL;
557 ASN1_STRING *strtmp;
558 ASN1_OBJECT *otmp;
559 int utype;
560 const unsigned char *cont;
561 unsigned char c;
562 int len;
563
564 if (it->funcs != NULL) {
565 const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
566
567 if (pf->prim_i2c == NULL)
568 return -1;
569 return pf->prim_i2c(pval, cout, putype, it);
570 }
571
572 /* Should type be omitted? */
573 if ((it->itype != ASN1_ITYPE_PRIMITIVE) ||
574 (it->utype != V_ASN1_BOOLEAN)) {
575 if (!*pval)
576 return -1;
577 }
578
579 if (it->itype == ASN1_ITYPE_MSTRING) {
580 /* If MSTRING type set the underlying type */
581 strtmp = (ASN1_STRING *)*pval;
582 utype = strtmp->type;
583 *putype = utype;
584 } else if (it->utype == V_ASN1_ANY) {
585 /* If ANY set type and pointer to value */
586 ASN1_TYPE *typ;
587 typ = (ASN1_TYPE *)*pval;
588 utype = typ->type;
589 *putype = utype;
590 pval = &typ->value.asn1_value;
591 } else
592 utype = *putype;
593
594 switch (utype) {
595 case V_ASN1_OBJECT:
596 otmp = (ASN1_OBJECT *)*pval;
597 cont = otmp->data;
598 len = otmp->length;
599 break;
600
601 case V_ASN1_NULL:
602 cont = NULL;
603 len = 0;
604 break;
605
606 case V_ASN1_BOOLEAN:
607 tbool = (ASN1_BOOLEAN *)pval;
608 if (*tbool == -1)
609 return -1;
610 if (it->utype != V_ASN1_ANY) {
611 /* Default handling if value == size field then omit */
612 if (*tbool && (it->size > 0))
613 return -1;
614 if (!*tbool && !it->size)
615 return -1;
616 }
617 c = (unsigned char)*tbool;
618 cont = &c;
619 len = 1;
620 break;
621
622 case V_ASN1_BIT_STRING:
623 return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval,
624 cout ? &cout : NULL);
625 break;
626
627 case V_ASN1_INTEGER:
628 case V_ASN1_ENUMERATED:
629 /* These are all have the same content format
630 * as ASN1_INTEGER
631 */
632 return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval,
633 cout ? &cout : NULL);
634 break;
635
636 case V_ASN1_OCTET_STRING:
637 case V_ASN1_NUMERICSTRING:
638 case V_ASN1_PRINTABLESTRING:
639 case V_ASN1_T61STRING:
640 case V_ASN1_VIDEOTEXSTRING:
641 case V_ASN1_IA5STRING:
642 case V_ASN1_UTCTIME:
643 case V_ASN1_GENERALIZEDTIME:
644 case V_ASN1_GRAPHICSTRING:
645 case V_ASN1_VISIBLESTRING:
646 case V_ASN1_GENERALSTRING:
647 case V_ASN1_UNIVERSALSTRING:
648 case V_ASN1_BMPSTRING:
649 case V_ASN1_UTF8STRING:
650 case V_ASN1_SEQUENCE:
651 case V_ASN1_SET:
652 default:
653 /* All based on ASN1_STRING and handled the same */
654 strtmp = (ASN1_STRING *)*pval;
655 /* Special handling for NDEF */
656 if ((it->size == ASN1_TFLG_NDEF) &&
657 (strtmp->flags & ASN1_STRING_FLAG_NDEF)) {
658 if (cout) {
659 strtmp->data = cout;
660 strtmp->length = 0;
661 }
662 /* Special return code */
663 return -2;
664 }
665 cont = strtmp->data;
666 len = strtmp->length;
667
668 break;
669
670 }
671 if (cout && len)
672 memcpy(cout, cont, len);
673 return len;
674 }
675