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