1 /* $OpenBSD: tasn_enc.c,v 1.25.2.1 2022/10/20 09:47:01 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 #include "asn1_locl.h" 68 69 static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, 70 const ASN1_ITEM *it, int tag, int aclass); 71 static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, 72 int skcontlen, const ASN1_ITEM *item, int do_sort, int iclass); 73 static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out, 74 const ASN1_TEMPLATE *tt, int tag, int aclass); 75 static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out, 76 const ASN1_ITEM *it, int flags); 77 static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype, 78 const ASN1_ITEM *it); 79 80 /* Top level i2d equivalents: the 'ndef' variant instructs the encoder 81 * to use indefinite length constructed encoding, where appropriate 82 */ 83 84 int 85 ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it) 86 { 87 return asn1_item_flags_i2d(val, out, it, ASN1_TFLG_NDEF); 88 } 89 90 int 91 ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it) 92 { 93 return asn1_item_flags_i2d(val, out, it, 0); 94 } 95 96 /* Encode an ASN1 item, this is use by the 97 * standard 'i2d' function. 'out' points to 98 * a buffer to output the data to. 99 * 100 * The new i2d has one additional feature. If the output 101 * buffer is NULL (i.e. *out == NULL) then a buffer is 102 * allocated and populated with the encoding. 103 */ 104 105 static int 106 asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it, 107 int flags) 108 { 109 if (out && !*out) { 110 unsigned char *p, *buf; 111 int len; 112 len = ASN1_item_ex_i2d(&val, NULL, it, -1, flags); 113 if (len <= 0) 114 return len; 115 buf = malloc(len); 116 if (!buf) 117 return -1; 118 p = buf; 119 ASN1_item_ex_i2d(&val, &p, it, -1, flags); 120 *out = buf; 121 return len; 122 } 123 124 return ASN1_item_ex_i2d(&val, out, it, -1, flags); 125 } 126 127 /* Encode an item, taking care of IMPLICIT tagging (if any). 128 * This function performs the normal item handling: it can be 129 * used in external types. 130 */ 131 132 int 133 ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, 134 int tag, int aclass) 135 { 136 const ASN1_TEMPLATE *tt = NULL; 137 int i, seqcontlen, seqlen, ndef = 1; 138 const ASN1_EXTERN_FUNCS *ef; 139 const ASN1_AUX *aux = it->funcs; 140 ASN1_aux_cb *asn1_cb = NULL; 141 142 if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval) 143 return 0; 144 145 if (aux && aux->asn1_cb) 146 asn1_cb = aux->asn1_cb; 147 148 switch (it->itype) { 149 150 case ASN1_ITYPE_PRIMITIVE: 151 if (it->templates) 152 return asn1_template_ex_i2d(pval, out, it->templates, 153 tag, aclass); 154 return asn1_i2d_ex_primitive(pval, out, it, tag, aclass); 155 break; 156 157 case ASN1_ITYPE_MSTRING: 158 /* 159 * It never makes sense for multi-strings to have implicit 160 * tagging, so if tag != -1, then this looks like an error in 161 * the template. 162 */ 163 if (tag != -1) { 164 ASN1error(ASN1_R_BAD_TEMPLATE); 165 return 0; 166 } 167 return asn1_i2d_ex_primitive(pval, out, it, -1, aclass); 168 169 case ASN1_ITYPE_CHOICE: 170 /* 171 * It never makes sense for CHOICE types to have implicit 172 * tagging, so if tag != -1, then this looks like an error in 173 * the template. 174 */ 175 if (tag != -1) { 176 ASN1error(ASN1_R_BAD_TEMPLATE); 177 return 0; 178 } 179 if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL)) 180 return 0; 181 i = asn1_get_choice_selector(pval, it); 182 if ((i >= 0) && (i < it->tcount)) { 183 ASN1_VALUE **pchval; 184 const ASN1_TEMPLATE *chtt; 185 chtt = it->templates + i; 186 pchval = asn1_get_field_ptr(pval, chtt); 187 return asn1_template_ex_i2d(pchval, out, chtt, 188 -1, aclass); 189 } 190 /* Fixme: error condition if selector out of range */ 191 if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL)) 192 return 0; 193 break; 194 195 case ASN1_ITYPE_EXTERN: 196 /* If new style i2d it does all the work */ 197 ef = it->funcs; 198 return ef->asn1_ex_i2d(pval, out, it, tag, aclass); 199 200 case ASN1_ITYPE_NDEF_SEQUENCE: 201 /* Use indefinite length constructed if requested */ 202 if (aclass & ASN1_TFLG_NDEF) 203 ndef = 2; 204 /* fall through */ 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 0; 211 /* We have a valid cached encoding... */ 212 if (i > 0) 213 return seqcontlen; 214 /* Otherwise carry on */ 215 seqcontlen = 0; 216 /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */ 217 if (tag == -1) { 218 tag = V_ASN1_SEQUENCE; 219 /* Retain any other flags in aclass */ 220 aclass = (aclass & ~ASN1_TFLG_TAG_CLASS) | 221 V_ASN1_UNIVERSAL; 222 } 223 if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL)) 224 return 0; 225 /* First work out sequence content length */ 226 for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { 227 const ASN1_TEMPLATE *seqtt; 228 ASN1_VALUE **pseqval; 229 seqtt = asn1_do_adb(pval, tt, 1); 230 if (!seqtt) 231 return 0; 232 pseqval = asn1_get_field_ptr(pval, seqtt); 233 /* FIXME: check for errors in enhanced version */ 234 seqcontlen += asn1_template_ex_i2d(pseqval, NULL, seqtt, 235 -1, aclass); 236 } 237 238 seqlen = ASN1_object_size(ndef, seqcontlen, tag); 239 if (!out) 240 return seqlen; 241 /* Output SEQUENCE header */ 242 ASN1_put_object(out, ndef, seqcontlen, tag, aclass); 243 for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { 244 const ASN1_TEMPLATE *seqtt; 245 ASN1_VALUE **pseqval; 246 seqtt = asn1_do_adb(pval, tt, 1); 247 if (!seqtt) 248 return 0; 249 pseqval = asn1_get_field_ptr(pval, seqtt); 250 /* FIXME: check for errors in enhanced version */ 251 asn1_template_ex_i2d(pseqval, out, seqtt, -1, aclass); 252 } 253 if (ndef == 2) 254 ASN1_put_eoc(out); 255 if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL)) 256 return 0; 257 return seqlen; 258 259 default: 260 return 0; 261 262 } 263 return 0; 264 } 265 266 int 267 ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out, 268 const ASN1_TEMPLATE *tt) 269 { 270 return asn1_template_ex_i2d(pval, out, tt, -1, 0); 271 } 272 273 static int 274 asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out, 275 const ASN1_TEMPLATE *tt, int tag, int iclass) 276 { 277 int i, ret, flags, ttag, tclass, ndef; 278 flags = tt->flags; 279 /* Work out tag and class to use: tagging may come 280 * either from the template or the arguments, not both 281 * because this would create ambiguity. Additionally 282 * the iclass argument may contain some additional flags 283 * which should be noted and passed down to other levels. 284 */ 285 if (flags & ASN1_TFLG_TAG_MASK) { 286 /* Error if argument and template tagging */ 287 if (tag != -1) 288 /* FIXME: error code here */ 289 return -1; 290 /* Get tagging from template */ 291 ttag = tt->tag; 292 tclass = flags & ASN1_TFLG_TAG_CLASS; 293 } else if (tag != -1) { 294 /* No template tagging, get from arguments */ 295 ttag = tag; 296 tclass = iclass & ASN1_TFLG_TAG_CLASS; 297 } else { 298 ttag = -1; 299 tclass = 0; 300 } 301 /* 302 * Remove any class mask from iflag. 303 */ 304 iclass &= ~ASN1_TFLG_TAG_CLASS; 305 306 /* At this point 'ttag' contains the outer tag to use, 307 * 'tclass' is the class and iclass is any flags passed 308 * to this function. 309 */ 310 311 /* if template and arguments require ndef, use it */ 312 if ((flags & ASN1_TFLG_NDEF) && (iclass & ASN1_TFLG_NDEF)) 313 ndef = 2; 314 else 315 ndef = 1; 316 317 if (flags & ASN1_TFLG_SK_MASK) { 318 /* SET OF, SEQUENCE OF */ 319 STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval; 320 int isset, sktag, skaclass; 321 int skcontlen, sklen; 322 ASN1_VALUE *skitem; 323 324 if (!*pval) 325 return 0; 326 327 if (flags & ASN1_TFLG_SET_OF) { 328 isset = 1; 329 /* 2 means we reorder */ 330 if (flags & ASN1_TFLG_SEQUENCE_OF) 331 isset = 2; 332 } else 333 isset = 0; 334 335 /* Work out inner tag value: if EXPLICIT 336 * or no tagging use underlying type. 337 */ 338 if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG)) { 339 sktag = ttag; 340 skaclass = tclass; 341 } else { 342 skaclass = V_ASN1_UNIVERSAL; 343 if (isset) 344 sktag = V_ASN1_SET; 345 else 346 sktag = V_ASN1_SEQUENCE; 347 } 348 349 /* Determine total length of items */ 350 skcontlen = 0; 351 for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) { 352 skitem = sk_ASN1_VALUE_value(sk, i); 353 skcontlen += ASN1_item_ex_i2d(&skitem, NULL, 354 tt->item, -1, iclass); 355 } 356 sklen = ASN1_object_size(ndef, skcontlen, sktag); 357 /* If EXPLICIT need length of surrounding tag */ 358 if (flags & ASN1_TFLG_EXPTAG) 359 ret = ASN1_object_size(ndef, sklen, ttag); 360 else 361 ret = sklen; 362 363 if (!out) 364 return ret; 365 366 /* Now encode this lot... */ 367 /* EXPLICIT tag */ 368 if (flags & ASN1_TFLG_EXPTAG) 369 ASN1_put_object(out, ndef, sklen, ttag, tclass); 370 /* SET or SEQUENCE and IMPLICIT tag */ 371 ASN1_put_object(out, ndef, skcontlen, sktag, skaclass); 372 /* And the stuff itself */ 373 asn1_set_seq_out(sk, out, skcontlen, tt->item, 374 isset, iclass); 375 if (ndef == 2) { 376 ASN1_put_eoc(out); 377 if (flags & ASN1_TFLG_EXPTAG) 378 ASN1_put_eoc(out); 379 } 380 381 return ret; 382 } 383 384 if (flags & ASN1_TFLG_EXPTAG) { 385 /* EXPLICIT tagging */ 386 /* Find length of tagged item */ 387 i = ASN1_item_ex_i2d(pval, NULL, tt->item, 388 -1, iclass); 389 if (!i) 390 return 0; 391 /* Find length of EXPLICIT tag */ 392 ret = ASN1_object_size(ndef, i, ttag); 393 if (out) { 394 /* Output tag and item */ 395 ASN1_put_object(out, ndef, i, ttag, tclass); 396 ASN1_item_ex_i2d(pval, out, tt->item, 397 -1, iclass); 398 if (ndef == 2) 399 ASN1_put_eoc(out); 400 } 401 return ret; 402 } 403 404 /* Either normal or IMPLICIT tagging: combine class and flags */ 405 return ASN1_item_ex_i2d(pval, out, tt->item, 406 ttag, tclass | iclass); 407 } 408 409 /* Temporary structure used to hold DER encoding of items for SET OF */ 410 411 typedef struct { 412 unsigned char *data; 413 int length; 414 ASN1_VALUE *field; 415 } DER_ENC; 416 417 static int 418 der_cmp(const void *a, const void *b) 419 { 420 const DER_ENC *d1 = a, *d2 = b; 421 int cmplen, i; 422 423 cmplen = (d1->length < d2->length) ? d1->length : d2->length; 424 i = memcmp(d1->data, d2->data, cmplen); 425 if (i) 426 return i; 427 return d1->length - d2->length; 428 } 429 430 /* Output the content octets of SET OF or SEQUENCE OF */ 431 432 static int 433 asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, int skcontlen, 434 const ASN1_ITEM *item, int do_sort, int iclass) 435 { 436 int i; 437 ASN1_VALUE *skitem; 438 unsigned char *tmpdat = NULL, *p = NULL; 439 DER_ENC *derlst = NULL, *tder; 440 441 if (do_sort) { 442 /* Don't need to sort less than 2 items */ 443 if (sk_ASN1_VALUE_num(sk) < 2) 444 do_sort = 0; 445 else { 446 derlst = reallocarray(NULL, sk_ASN1_VALUE_num(sk), 447 sizeof(*derlst)); 448 tmpdat = malloc(skcontlen); 449 if (!derlst || !tmpdat) { 450 free(derlst); 451 free(tmpdat); 452 return 0; 453 } 454 } 455 } 456 /* If not sorting just output each item */ 457 if (!do_sort) { 458 for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) { 459 skitem = sk_ASN1_VALUE_value(sk, i); 460 ASN1_item_ex_i2d(&skitem, out, item, -1, iclass); 461 } 462 return 1; 463 } 464 p = tmpdat; 465 466 /* Doing sort: build up a list of each member's DER encoding */ 467 for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) { 468 skitem = sk_ASN1_VALUE_value(sk, i); 469 tder->data = p; 470 tder->length = ASN1_item_ex_i2d(&skitem, &p, item, -1, iclass); 471 tder->field = skitem; 472 } 473 474 /* Now sort them */ 475 qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp); 476 /* Output sorted DER encoding */ 477 p = *out; 478 for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) { 479 memcpy(p, tder->data, tder->length); 480 p += tder->length; 481 } 482 *out = p; 483 /* If do_sort is 2 then reorder the STACK */ 484 if (do_sort == 2) { 485 for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) 486 (void)sk_ASN1_VALUE_set(sk, i, tder->field); 487 } 488 free(derlst); 489 free(tmpdat); 490 return 1; 491 } 492 493 static int 494 asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, 495 const ASN1_ITEM *it, int tag, int aclass) 496 { 497 int olen, len; 498 int utype; 499 int usetag; 500 int ndef = 0; 501 502 utype = it->utype; 503 504 /* Get length of content octets and maybe find 505 * out the underlying type. 506 */ 507 508 olen = len = asn1_ex_i2c(pval, NULL, &utype, it); 509 510 /* If SEQUENCE, SET or OTHER then header is 511 * included in pseudo content octets so don't 512 * include tag+length. We need to check here 513 * because the call to asn1_ex_i2c() could change 514 * utype. 515 */ 516 if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) || 517 (utype == V_ASN1_OTHER)) 518 usetag = 0; 519 else 520 usetag = 1; 521 522 /* -1 means omit type */ 523 if (len == -1) 524 return 0; 525 526 /* -2 return is special meaning use ndef */ 527 if (len == -2) { 528 ndef = 2; 529 len = 0; 530 } 531 532 /* Treat any other negative value as an error. */ 533 if (len < 0) 534 return -1; 535 536 /* If not implicitly tagged get tag from underlying type */ 537 if (tag == -1) 538 tag = utype; 539 540 /* Output tag+length followed by content octets */ 541 if (out) { 542 if (usetag) 543 ASN1_put_object(out, ndef, len, tag, aclass); 544 if (asn1_ex_i2c(pval, *out, &utype, it) != olen) 545 return -1; 546 if (ndef) 547 ASN1_put_eoc(out); 548 else 549 *out += len; 550 } 551 552 if (usetag) 553 return ASN1_object_size(ndef, len, tag); 554 return len; 555 } 556 557 /* Produce content octets from a structure */ 558 559 static int 560 asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype, 561 const ASN1_ITEM *it) 562 { 563 ASN1_BOOLEAN *tbool = NULL; 564 ASN1_STRING *strtmp; 565 ASN1_OBJECT *otmp; 566 int utype; 567 const unsigned char *cont; 568 unsigned char c; 569 int len; 570 571 if (it->funcs != NULL) { 572 const ASN1_PRIMITIVE_FUNCS *pf = it->funcs; 573 574 if (pf->prim_i2c == NULL) 575 return -1; 576 return pf->prim_i2c(pval, cout, putype, it); 577 } 578 579 /* Should type be omitted? */ 580 if ((it->itype != ASN1_ITYPE_PRIMITIVE) || 581 (it->utype != V_ASN1_BOOLEAN)) { 582 if (!*pval) 583 return -1; 584 } 585 586 if (it->itype == ASN1_ITYPE_MSTRING) { 587 /* If MSTRING type set the underlying type */ 588 strtmp = (ASN1_STRING *)*pval; 589 utype = strtmp->type; 590 *putype = utype; 591 } else if (it->utype == V_ASN1_ANY) { 592 /* If ANY set type and pointer to value */ 593 ASN1_TYPE *typ; 594 typ = (ASN1_TYPE *)*pval; 595 utype = typ->type; 596 *putype = utype; 597 pval = &typ->value.asn1_value; 598 } else 599 utype = *putype; 600 601 switch (utype) { 602 case V_ASN1_OBJECT: 603 otmp = (ASN1_OBJECT *)*pval; 604 cont = otmp->data; 605 len = otmp->length; 606 break; 607 608 case V_ASN1_NULL: 609 cont = NULL; 610 len = 0; 611 break; 612 613 case V_ASN1_BOOLEAN: 614 tbool = (ASN1_BOOLEAN *)pval; 615 if (*tbool == -1) 616 return -1; 617 if (it->utype != V_ASN1_ANY) { 618 /* Default handling if value == size field then omit */ 619 if (*tbool && (it->size > 0)) 620 return -1; 621 if (!*tbool && !it->size) 622 return -1; 623 } 624 c = (unsigned char)*tbool; 625 cont = &c; 626 len = 1; 627 break; 628 629 case V_ASN1_BIT_STRING: 630 return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval, 631 cout ? &cout : NULL); 632 break; 633 634 case V_ASN1_INTEGER: 635 case V_ASN1_ENUMERATED: 636 /* These are all have the same content format 637 * as ASN1_INTEGER 638 */ 639 return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, 640 cout ? &cout : NULL); 641 break; 642 643 case V_ASN1_OCTET_STRING: 644 case V_ASN1_NUMERICSTRING: 645 case V_ASN1_PRINTABLESTRING: 646 case V_ASN1_T61STRING: 647 case V_ASN1_VIDEOTEXSTRING: 648 case V_ASN1_IA5STRING: 649 case V_ASN1_UTCTIME: 650 case V_ASN1_GENERALIZEDTIME: 651 case V_ASN1_GRAPHICSTRING: 652 case V_ASN1_VISIBLESTRING: 653 case V_ASN1_GENERALSTRING: 654 case V_ASN1_UNIVERSALSTRING: 655 case V_ASN1_BMPSTRING: 656 case V_ASN1_UTF8STRING: 657 case V_ASN1_SEQUENCE: 658 case V_ASN1_SET: 659 default: 660 /* All based on ASN1_STRING and handled the same */ 661 strtmp = (ASN1_STRING *)*pval; 662 /* Special handling for NDEF */ 663 if ((it->size == ASN1_TFLG_NDEF) && 664 (strtmp->flags & ASN1_STRING_FLAG_NDEF)) { 665 if (cout) { 666 strtmp->data = cout; 667 strtmp->length = 0; 668 } 669 /* Special return code */ 670 return -2; 671 } 672 cont = strtmp->data; 673 len = strtmp->length; 674 675 break; 676 677 } 678 if (cout && len) 679 memcpy(cout, cont, len); 680 return len; 681 } 682