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