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