tasn_enc.c revision 368530
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 /* 155 * It never makes sense for multi-strings to have implicit tagging, so 156 * if tag != -1, then this looks like an error in the template. 157 */ 158 if (tag != -1) { 159 ASN1err(ASN1_F_ASN1_ITEM_EX_I2D, ASN1_R_BAD_TEMPLATE); 160 return -1; 161 } 162 return asn1_i2d_ex_primitive(pval, out, it, -1, aclass); 163 164 case ASN1_ITYPE_CHOICE: 165 /* 166 * It never makes sense for CHOICE types to have implicit tagging, so 167 * if tag != -1, then this looks like an error in the template. 168 */ 169 if (tag != -1) { 170 ASN1err(ASN1_F_ASN1_ITEM_EX_I2D, ASN1_R_BAD_TEMPLATE); 171 return -1; 172 } 173 if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL)) 174 return 0; 175 i = asn1_get_choice_selector(pval, it); 176 if ((i >= 0) && (i < it->tcount)) { 177 ASN1_VALUE **pchval; 178 const ASN1_TEMPLATE *chtt; 179 chtt = it->templates + i; 180 pchval = asn1_get_field_ptr(pval, chtt); 181 return asn1_template_ex_i2d(pchval, out, chtt, -1, aclass); 182 } 183 /* Fixme: error condition if selector out of range */ 184 if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL)) 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 /* 200 * Fixup for IMPLICIT tag: note this messes up for tags > 30, but so 201 * did the old code. Tags > 30 are very rare anyway. 202 */ 203 if (out && (tag != -1)) 204 *p = aclass | tag | (*p & V_ASN1_CONSTRUCTED); 205 return i; 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 int tmplen; 237 seqtt = asn1_do_adb(pval, tt, 1); 238 if (!seqtt) 239 return 0; 240 pseqval = asn1_get_field_ptr(pval, seqtt); 241 tmplen = asn1_template_ex_i2d(pseqval, NULL, seqtt, -1, aclass); 242 if (tmplen == -1 || (tmplen > INT_MAX - seqcontlen)) 243 return -1; 244 seqcontlen += tmplen; 245 } 246 247 seqlen = ASN1_object_size(ndef, seqcontlen, tag); 248 if (!out || seqlen == -1) 249 return seqlen; 250 /* Output SEQUENCE header */ 251 ASN1_put_object(out, ndef, seqcontlen, tag, aclass); 252 for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { 253 const ASN1_TEMPLATE *seqtt; 254 ASN1_VALUE **pseqval; 255 seqtt = asn1_do_adb(pval, tt, 1); 256 if (!seqtt) 257 return 0; 258 pseqval = asn1_get_field_ptr(pval, seqtt); 259 /* FIXME: check for errors in enhanced version */ 260 asn1_template_ex_i2d(pseqval, out, seqtt, -1, aclass); 261 } 262 if (ndef == 2) 263 ASN1_put_eoc(out); 264 if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL)) 265 return 0; 266 return seqlen; 267 268 default: 269 return 0; 270 271 } 272 return 0; 273} 274 275int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out, 276 const ASN1_TEMPLATE *tt) 277{ 278 return asn1_template_ex_i2d(pval, out, tt, -1, 0); 279} 280 281static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out, 282 const ASN1_TEMPLATE *tt, int tag, int iclass) 283{ 284 int i, ret, flags, ttag, tclass, ndef; 285 flags = tt->flags; 286 /* 287 * Work out tag and class to use: tagging may come either from the 288 * template or the arguments, not both because this would create 289 * ambiguity. Additionally the iclass argument may contain some 290 * additional flags which should be noted and passed down to other 291 * levels. 292 */ 293 if (flags & ASN1_TFLG_TAG_MASK) { 294 /* Error if argument and template tagging */ 295 if (tag != -1) 296 /* FIXME: error code here */ 297 return -1; 298 /* Get tagging from template */ 299 ttag = tt->tag; 300 tclass = flags & ASN1_TFLG_TAG_CLASS; 301 } else if (tag != -1) { 302 /* No template tagging, get from arguments */ 303 ttag = tag; 304 tclass = iclass & ASN1_TFLG_TAG_CLASS; 305 } else { 306 ttag = -1; 307 tclass = 0; 308 } 309 /* 310 * Remove any class mask from iflag. 311 */ 312 iclass &= ~ASN1_TFLG_TAG_CLASS; 313 314 /* 315 * At this point 'ttag' contains the outer tag to use, 'tclass' is the 316 * class and iclass is any flags passed to this function. 317 */ 318 319 /* if template and arguments require ndef, use it */ 320 if ((flags & ASN1_TFLG_NDEF) && (iclass & ASN1_TFLG_NDEF)) 321 ndef = 2; 322 else 323 ndef = 1; 324 325 if (flags & ASN1_TFLG_SK_MASK) { 326 /* SET OF, SEQUENCE OF */ 327 STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval; 328 int isset, sktag, skaclass; 329 int skcontlen, sklen; 330 ASN1_VALUE *skitem; 331 332 if (!*pval) 333 return 0; 334 335 if (flags & ASN1_TFLG_SET_OF) { 336 isset = 1; 337 /* 2 means we reorder */ 338 if (flags & ASN1_TFLG_SEQUENCE_OF) 339 isset = 2; 340 } else 341 isset = 0; 342 343 /* 344 * Work out inner tag value: if EXPLICIT or no tagging use underlying 345 * type. 346 */ 347 if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG)) { 348 sktag = ttag; 349 skaclass = tclass; 350 } else { 351 skaclass = V_ASN1_UNIVERSAL; 352 if (isset) 353 sktag = V_ASN1_SET; 354 else 355 sktag = V_ASN1_SEQUENCE; 356 } 357 358 /* Determine total length of items */ 359 skcontlen = 0; 360 for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) { 361 int tmplen; 362 skitem = sk_ASN1_VALUE_value(sk, i); 363 tmplen = ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item), 364 -1, iclass); 365 if (tmplen == -1 || (skcontlen > INT_MAX - tmplen)) 366 return -1; 367 skcontlen += tmplen; 368 } 369 sklen = ASN1_object_size(ndef, skcontlen, sktag); 370 if (sklen == -1) 371 return -1; 372 /* If EXPLICIT need length of surrounding tag */ 373 if (flags & ASN1_TFLG_EXPTAG) 374 ret = ASN1_object_size(ndef, sklen, ttag); 375 else 376 ret = sklen; 377 378 if (!out || ret == -1) 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 ASN1_put_eoc(out); 392 if (flags & ASN1_TFLG_EXPTAG) 393 ASN1_put_eoc(out); 394 } 395 396 return ret; 397 } 398 399 if (flags & ASN1_TFLG_EXPTAG) { 400 /* EXPLICIT tagging */ 401 /* Find length of tagged item */ 402 i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, iclass); 403 if (!i) 404 return 0; 405 /* Find length of EXPLICIT tag */ 406 ret = ASN1_object_size(ndef, i, ttag); 407 if (out && ret != -1) { 408 /* Output tag and item */ 409 ASN1_put_object(out, ndef, i, ttag, tclass); 410 ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, iclass); 411 if (ndef == 2) 412 ASN1_put_eoc(out); 413 } 414 return ret; 415 } 416 417 /* Either normal or IMPLICIT tagging: combine class and flags */ 418 return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), 419 ttag, tclass | iclass); 420 421} 422 423/* Temporary structure used to hold DER encoding of items for SET OF */ 424 425typedef struct { 426 unsigned char *data; 427 int length; 428 ASN1_VALUE *field; 429} DER_ENC; 430 431static int der_cmp(const void *a, const void *b) 432{ 433 const DER_ENC *d1 = a, *d2 = b; 434 int cmplen, i; 435 cmplen = (d1->length < d2->length) ? d1->length : d2->length; 436 i = memcmp(d1->data, d2->data, cmplen); 437 if (i) 438 return i; 439 return d1->length - d2->length; 440} 441 442/* Output the content octets of SET OF or SEQUENCE OF */ 443 444static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, 445 int skcontlen, const ASN1_ITEM *item, 446 int do_sort, int iclass) 447{ 448 int i; 449 ASN1_VALUE *skitem; 450 unsigned char *tmpdat = NULL, *p = NULL; 451 DER_ENC *derlst = NULL, *tder; 452 if (do_sort) { 453 /* Don't need to sort less than 2 items */ 454 if (sk_ASN1_VALUE_num(sk) < 2) 455 do_sort = 0; 456 else { 457 derlst = OPENSSL_malloc(sk_ASN1_VALUE_num(sk) 458 * sizeof(*derlst)); 459 if (!derlst) 460 return 0; 461 tmpdat = OPENSSL_malloc(skcontlen); 462 if (!tmpdat) { 463 OPENSSL_free(derlst); 464 return 0; 465 } 466 } 467 } 468 /* If not sorting just output each item */ 469 if (!do_sort) { 470 for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) { 471 skitem = sk_ASN1_VALUE_value(sk, i); 472 ASN1_item_ex_i2d(&skitem, out, item, -1, iclass); 473 } 474 return 1; 475 } 476 p = tmpdat; 477 478 /* Doing sort: build up a list of each member's DER encoding */ 479 for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) { 480 skitem = sk_ASN1_VALUE_value(sk, i); 481 tder->data = p; 482 tder->length = ASN1_item_ex_i2d(&skitem, &p, item, -1, iclass); 483 tder->field = skitem; 484 } 485 486 /* Now sort them */ 487 qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp); 488 /* Output sorted DER encoding */ 489 p = *out; 490 for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) { 491 memcpy(p, tder->data, tder->length); 492 p += tder->length; 493 } 494 *out = p; 495 /* If do_sort is 2 then reorder the STACK */ 496 if (do_sort == 2) { 497 for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) 498 (void)sk_ASN1_VALUE_set(sk, i, tder->field); 499 } 500 OPENSSL_free(derlst); 501 OPENSSL_free(tmpdat); 502 return 1; 503} 504 505static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, 506 const ASN1_ITEM *it, int tag, int aclass) 507{ 508 int len; 509 int utype; 510 int usetag; 511 int ndef = 0; 512 513 utype = it->utype; 514 515 /* 516 * Get length of content octets and maybe find out the underlying type. 517 */ 518 519 len = asn1_ex_i2c(pval, NULL, &utype, it); 520 521 /* 522 * If SEQUENCE, SET or OTHER then header is included in pseudo content 523 * octets so don't include tag+length. We need to check here because the 524 * call to asn1_ex_i2c() could change utype. 525 */ 526 if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) || 527 (utype == V_ASN1_OTHER)) 528 usetag = 0; 529 else 530 usetag = 1; 531 532 /* -1 means omit type */ 533 534 if (len == -1) 535 return 0; 536 537 /* -2 return is special meaning use ndef */ 538 if (len == -2) { 539 ndef = 2; 540 len = 0; 541 } 542 543 /* If not implicitly tagged get tag from underlying type */ 544 if (tag == -1) 545 tag = utype; 546 547 /* Output tag+length followed by content octets */ 548 if (out) { 549 if (usetag) 550 ASN1_put_object(out, ndef, len, tag, aclass); 551 asn1_ex_i2c(pval, *out, &utype, it); 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 565int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype, 566 const ASN1_ITEM *it) 567{ 568 ASN1_BOOLEAN *tbool = NULL; 569 ASN1_STRING *strtmp; 570 ASN1_OBJECT *otmp; 571 int utype; 572 const unsigned char *cont; 573 unsigned char c; 574 int len; 575 const ASN1_PRIMITIVE_FUNCS *pf; 576 pf = it->funcs; 577 if (pf && pf->prim_i2c) 578 return pf->prim_i2c(pval, cout, putype, it); 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 if (cont == NULL || len == 0) 608 return -1; 609 break; 610 611 case V_ASN1_NULL: 612 cont = NULL; 613 len = 0; 614 break; 615 616 case V_ASN1_BOOLEAN: 617 tbool = (ASN1_BOOLEAN *)pval; 618 if (*tbool == -1) 619 return -1; 620 if (it->utype != V_ASN1_ANY) { 621 /* 622 * Default handling if value == size field then omit 623 */ 624 if (*tbool && (it->size > 0)) 625 return -1; 626 if (!*tbool && !it->size) 627 return -1; 628 } 629 c = (unsigned char)*tbool; 630 cont = &c; 631 len = 1; 632 break; 633 634 case V_ASN1_BIT_STRING: 635 return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval, 636 cout ? &cout : NULL); 637 break; 638 639 case V_ASN1_INTEGER: 640 case V_ASN1_ENUMERATED: 641 /* 642 * These are all have the same content format as ASN1_INTEGER 643 */ 644 return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL); 645 break; 646 647 case V_ASN1_OCTET_STRING: 648 case V_ASN1_NUMERICSTRING: 649 case V_ASN1_PRINTABLESTRING: 650 case V_ASN1_T61STRING: 651 case V_ASN1_VIDEOTEXSTRING: 652 case V_ASN1_IA5STRING: 653 case V_ASN1_UTCTIME: 654 case V_ASN1_GENERALIZEDTIME: 655 case V_ASN1_GRAPHICSTRING: 656 case V_ASN1_VISIBLESTRING: 657 case V_ASN1_GENERALSTRING: 658 case V_ASN1_UNIVERSALSTRING: 659 case V_ASN1_BMPSTRING: 660 case V_ASN1_UTF8STRING: 661 case V_ASN1_SEQUENCE: 662 case V_ASN1_SET: 663 default: 664 /* All based on ASN1_STRING and handled the same */ 665 strtmp = (ASN1_STRING *)*pval; 666 /* Special handling for NDEF */ 667 if ((it->size == ASN1_TFLG_NDEF) 668 && (strtmp->flags & ASN1_STRING_FLAG_NDEF)) { 669 if (cout) { 670 strtmp->data = cout; 671 strtmp->length = 0; 672 } 673 /* Special return code */ 674 return -2; 675 } 676 cont = strtmp->data; 677 len = strtmp->length; 678 679 break; 680 681 } 682 if (cout && len) 683 memcpy(cout, cont, len); 684 return len; 685} 686