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