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