1 /* 2 * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the OpenSSL license (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #include <stddef.h> 11 #include <string.h> 12 #include "internal/cryptlib.h" 13 #include <openssl/asn1.h> 14 #include <openssl/asn1t.h> 15 #include <openssl/objects.h> 16 #include "crypto/asn1.h" 17 #include "asn1_local.h" 18 19 static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, 20 const ASN1_ITEM *it, int tag, int aclass); 21 static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, 22 int skcontlen, const ASN1_ITEM *item, 23 int do_sort, int iclass); 24 static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out, 25 const ASN1_TEMPLATE *tt, int tag, int aclass); 26 static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out, 27 const ASN1_ITEM *it, int flags); 28 static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype, 29 const ASN1_ITEM *it); 30 31 /* 32 * Top level i2d equivalents: the 'ndef' variant instructs the encoder to use 33 * indefinite length constructed encoding, where appropriate 34 */ 35 36 int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out, 37 const ASN1_ITEM *it) 38 { 39 return asn1_item_flags_i2d(val, out, it, ASN1_TFLG_NDEF); 40 } 41 42 int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it) 43 { 44 return asn1_item_flags_i2d(val, out, it, 0); 45 } 46 47 /* 48 * Encode an ASN1 item, this is use by the standard 'i2d' function. 'out' 49 * points to a buffer to output the data to. The new i2d has one additional 50 * feature. If the output buffer is NULL (i.e. *out == NULL) then a buffer is 51 * allocated and populated with the encoding. 52 */ 53 54 static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out, 55 const ASN1_ITEM *it, int flags) 56 { 57 if (out && !*out) { 58 unsigned char *p, *buf; 59 int len; 60 61 len = ASN1_item_ex_i2d(&val, NULL, it, -1, flags); 62 if (len <= 0) 63 return len; 64 if ((buf = OPENSSL_malloc(len)) == NULL) { 65 ASN1err(ASN1_F_ASN1_ITEM_FLAGS_I2D, ERR_R_MALLOC_FAILURE); 66 return -1; 67 } 68 p = buf; 69 ASN1_item_ex_i2d(&val, &p, it, -1, flags); 70 *out = buf; 71 return len; 72 } 73 74 return ASN1_item_ex_i2d(&val, out, it, -1, flags); 75 } 76 77 /* 78 * Encode an item, taking care of IMPLICIT tagging (if any). This function 79 * performs the normal item handling: it can be used in external types. 80 */ 81 82 int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, 83 const ASN1_ITEM *it, int tag, int aclass) 84 { 85 const ASN1_TEMPLATE *tt = NULL; 86 int i, seqcontlen, seqlen, ndef = 1; 87 const ASN1_EXTERN_FUNCS *ef; 88 const ASN1_AUX *aux = it->funcs; 89 ASN1_aux_cb *asn1_cb = 0; 90 91 if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval) 92 return 0; 93 94 if (aux && aux->asn1_cb) 95 asn1_cb = aux->asn1_cb; 96 97 switch (it->itype) { 98 99 case ASN1_ITYPE_PRIMITIVE: 100 if (it->templates) 101 return asn1_template_ex_i2d(pval, out, it->templates, 102 tag, aclass); 103 return asn1_i2d_ex_primitive(pval, out, it, tag, aclass); 104 105 case ASN1_ITYPE_MSTRING: 106 return asn1_i2d_ex_primitive(pval, out, it, -1, aclass); 107 108 case ASN1_ITYPE_CHOICE: 109 if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL)) 110 return 0; 111 i = asn1_get_choice_selector(pval, it); 112 if ((i >= 0) && (i < it->tcount)) { 113 ASN1_VALUE **pchval; 114 const ASN1_TEMPLATE *chtt; 115 chtt = it->templates + i; 116 pchval = asn1_get_field_ptr(pval, chtt); 117 return asn1_template_ex_i2d(pchval, out, chtt, -1, aclass); 118 } 119 /* Fixme: error condition if selector out of range */ 120 if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL)) 121 return 0; 122 break; 123 124 case ASN1_ITYPE_EXTERN: 125 /* If new style i2d it does all the work */ 126 ef = it->funcs; 127 return ef->asn1_ex_i2d(pval, out, it, tag, aclass); 128 129 case ASN1_ITYPE_NDEF_SEQUENCE: 130 /* Use indefinite length constructed if requested */ 131 if (aclass & ASN1_TFLG_NDEF) 132 ndef = 2; 133 /* fall through */ 134 135 case ASN1_ITYPE_SEQUENCE: 136 i = asn1_enc_restore(&seqcontlen, out, pval, it); 137 /* An error occurred */ 138 if (i < 0) 139 return 0; 140 /* We have a valid cached encoding... */ 141 if (i > 0) 142 return seqcontlen; 143 /* Otherwise carry on */ 144 seqcontlen = 0; 145 /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */ 146 if (tag == -1) { 147 tag = V_ASN1_SEQUENCE; 148 /* Retain any other flags in aclass */ 149 aclass = (aclass & ~ASN1_TFLG_TAG_CLASS) 150 | V_ASN1_UNIVERSAL; 151 } 152 if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL)) 153 return 0; 154 /* First work out sequence content length */ 155 for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { 156 const ASN1_TEMPLATE *seqtt; 157 ASN1_VALUE **pseqval; 158 int tmplen; 159 seqtt = asn1_do_adb(pval, tt, 1); 160 if (!seqtt) 161 return 0; 162 pseqval = asn1_get_field_ptr(pval, seqtt); 163 tmplen = asn1_template_ex_i2d(pseqval, NULL, seqtt, -1, aclass); 164 if (tmplen == -1 || (tmplen > INT_MAX - seqcontlen)) 165 return -1; 166 seqcontlen += tmplen; 167 } 168 169 seqlen = ASN1_object_size(ndef, seqcontlen, tag); 170 if (!out || seqlen == -1) 171 return seqlen; 172 /* Output SEQUENCE header */ 173 ASN1_put_object(out, ndef, seqcontlen, tag, aclass); 174 for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { 175 const ASN1_TEMPLATE *seqtt; 176 ASN1_VALUE **pseqval; 177 seqtt = asn1_do_adb(pval, tt, 1); 178 if (!seqtt) 179 return 0; 180 pseqval = asn1_get_field_ptr(pval, seqtt); 181 /* FIXME: check for errors in enhanced version */ 182 asn1_template_ex_i2d(pseqval, out, seqtt, -1, aclass); 183 } 184 if (ndef == 2) 185 ASN1_put_eoc(out); 186 if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL)) 187 return 0; 188 return seqlen; 189 190 default: 191 return 0; 192 193 } 194 return 0; 195 } 196 197 static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out, 198 const ASN1_TEMPLATE *tt, int tag, int iclass) 199 { 200 int i, ret, flags, ttag, tclass, ndef; 201 ASN1_VALUE *tval; 202 flags = tt->flags; 203 204 /* 205 * If field is embedded then val needs fixing so it is a pointer to 206 * a pointer to a field. 207 */ 208 if (flags & ASN1_TFLG_EMBED) { 209 tval = (ASN1_VALUE *)pval; 210 pval = &tval; 211 } 212 /* 213 * Work out tag and class to use: tagging may come either from the 214 * template or the arguments, not both because this would create 215 * ambiguity. Additionally the iclass argument may contain some 216 * additional flags which should be noted and passed down to other 217 * levels. 218 */ 219 if (flags & ASN1_TFLG_TAG_MASK) { 220 /* Error if argument and template tagging */ 221 if (tag != -1) 222 /* FIXME: error code here */ 223 return -1; 224 /* Get tagging from template */ 225 ttag = tt->tag; 226 tclass = flags & ASN1_TFLG_TAG_CLASS; 227 } else if (tag != -1) { 228 /* No template tagging, get from arguments */ 229 ttag = tag; 230 tclass = iclass & ASN1_TFLG_TAG_CLASS; 231 } else { 232 ttag = -1; 233 tclass = 0; 234 } 235 /* 236 * Remove any class mask from iflag. 237 */ 238 iclass &= ~ASN1_TFLG_TAG_CLASS; 239 240 /* 241 * At this point 'ttag' contains the outer tag to use, 'tclass' is the 242 * class and iclass is any flags passed to this function. 243 */ 244 245 /* if template and arguments require ndef, use it */ 246 if ((flags & ASN1_TFLG_NDEF) && (iclass & ASN1_TFLG_NDEF)) 247 ndef = 2; 248 else 249 ndef = 1; 250 251 if (flags & ASN1_TFLG_SK_MASK) { 252 /* SET OF, SEQUENCE OF */ 253 STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval; 254 int isset, sktag, skaclass; 255 int skcontlen, sklen; 256 ASN1_VALUE *skitem; 257 258 if (!*pval) 259 return 0; 260 261 if (flags & ASN1_TFLG_SET_OF) { 262 isset = 1; 263 /* 2 means we reorder */ 264 if (flags & ASN1_TFLG_SEQUENCE_OF) 265 isset = 2; 266 } else 267 isset = 0; 268 269 /* 270 * Work out inner tag value: if EXPLICIT or no tagging use underlying 271 * type. 272 */ 273 if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG)) { 274 sktag = ttag; 275 skaclass = tclass; 276 } else { 277 skaclass = V_ASN1_UNIVERSAL; 278 if (isset) 279 sktag = V_ASN1_SET; 280 else 281 sktag = V_ASN1_SEQUENCE; 282 } 283 284 /* Determine total length of items */ 285 skcontlen = 0; 286 for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) { 287 int tmplen; 288 skitem = sk_ASN1_VALUE_value(sk, i); 289 tmplen = ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item), 290 -1, iclass); 291 if (tmplen == -1 || (skcontlen > INT_MAX - tmplen)) 292 return -1; 293 skcontlen += tmplen; 294 } 295 sklen = ASN1_object_size(ndef, skcontlen, sktag); 296 if (sklen == -1) 297 return -1; 298 /* If EXPLICIT need length of surrounding tag */ 299 if (flags & ASN1_TFLG_EXPTAG) 300 ret = ASN1_object_size(ndef, sklen, ttag); 301 else 302 ret = sklen; 303 304 if (!out || ret == -1) 305 return ret; 306 307 /* Now encode this lot... */ 308 /* EXPLICIT tag */ 309 if (flags & ASN1_TFLG_EXPTAG) 310 ASN1_put_object(out, ndef, sklen, ttag, tclass); 311 /* SET or SEQUENCE and IMPLICIT tag */ 312 ASN1_put_object(out, ndef, skcontlen, sktag, skaclass); 313 /* And the stuff itself */ 314 asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item), 315 isset, iclass); 316 if (ndef == 2) { 317 ASN1_put_eoc(out); 318 if (flags & ASN1_TFLG_EXPTAG) 319 ASN1_put_eoc(out); 320 } 321 322 return ret; 323 } 324 325 if (flags & ASN1_TFLG_EXPTAG) { 326 /* EXPLICIT tagging */ 327 /* Find length of tagged item */ 328 i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, iclass); 329 if (!i) 330 return 0; 331 /* Find length of EXPLICIT tag */ 332 ret = ASN1_object_size(ndef, i, ttag); 333 if (out && ret != -1) { 334 /* Output tag and item */ 335 ASN1_put_object(out, ndef, i, ttag, tclass); 336 ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, iclass); 337 if (ndef == 2) 338 ASN1_put_eoc(out); 339 } 340 return ret; 341 } 342 343 /* Either normal or IMPLICIT tagging: combine class and flags */ 344 return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), 345 ttag, tclass | iclass); 346 347 } 348 349 /* Temporary structure used to hold DER encoding of items for SET OF */ 350 351 typedef struct { 352 unsigned char *data; 353 int length; 354 ASN1_VALUE *field; 355 } DER_ENC; 356 357 static int der_cmp(const void *a, const void *b) 358 { 359 const DER_ENC *d1 = a, *d2 = b; 360 int cmplen, i; 361 cmplen = (d1->length < d2->length) ? d1->length : d2->length; 362 i = memcmp(d1->data, d2->data, cmplen); 363 if (i) 364 return i; 365 return d1->length - d2->length; 366 } 367 368 /* Output the content octets of SET OF or SEQUENCE OF */ 369 370 static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, 371 int skcontlen, const ASN1_ITEM *item, 372 int do_sort, int iclass) 373 { 374 int i; 375 ASN1_VALUE *skitem; 376 unsigned char *tmpdat = NULL, *p = NULL; 377 DER_ENC *derlst = NULL, *tder; 378 if (do_sort) { 379 /* Don't need to sort less than 2 items */ 380 if (sk_ASN1_VALUE_num(sk) < 2) 381 do_sort = 0; 382 else { 383 derlst = OPENSSL_malloc(sk_ASN1_VALUE_num(sk) 384 * sizeof(*derlst)); 385 if (derlst == NULL) 386 return 0; 387 tmpdat = OPENSSL_malloc(skcontlen); 388 if (tmpdat == NULL) { 389 OPENSSL_free(derlst); 390 return 0; 391 } 392 } 393 } 394 /* If not sorting just output each item */ 395 if (!do_sort) { 396 for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) { 397 skitem = sk_ASN1_VALUE_value(sk, i); 398 ASN1_item_ex_i2d(&skitem, out, item, -1, iclass); 399 } 400 return 1; 401 } 402 p = tmpdat; 403 404 /* Doing sort: build up a list of each member's DER encoding */ 405 for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) { 406 skitem = sk_ASN1_VALUE_value(sk, i); 407 tder->data = p; 408 tder->length = ASN1_item_ex_i2d(&skitem, &p, item, -1, iclass); 409 tder->field = skitem; 410 } 411 412 /* Now sort them */ 413 qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp); 414 /* Output sorted DER encoding */ 415 p = *out; 416 for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) { 417 memcpy(p, tder->data, tder->length); 418 p += tder->length; 419 } 420 *out = p; 421 /* If do_sort is 2 then reorder the STACK */ 422 if (do_sort == 2) { 423 for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) 424 (void)sk_ASN1_VALUE_set(sk, i, tder->field); 425 } 426 OPENSSL_free(derlst); 427 OPENSSL_free(tmpdat); 428 return 1; 429 } 430 431 static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, 432 const ASN1_ITEM *it, int tag, int aclass) 433 { 434 int len; 435 int utype; 436 int usetag; 437 int ndef = 0; 438 439 utype = it->utype; 440 441 /* 442 * Get length of content octets and maybe find out the underlying type. 443 */ 444 445 len = asn1_ex_i2c(pval, NULL, &utype, it); 446 447 /* 448 * If SEQUENCE, SET or OTHER then header is included in pseudo content 449 * octets so don't include tag+length. We need to check here because the 450 * call to asn1_ex_i2c() could change utype. 451 */ 452 if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) || 453 (utype == V_ASN1_OTHER)) 454 usetag = 0; 455 else 456 usetag = 1; 457 458 /* -1 means omit type */ 459 460 if (len == -1) 461 return 0; 462 463 /* -2 return is special meaning use ndef */ 464 if (len == -2) { 465 ndef = 2; 466 len = 0; 467 } 468 469 /* If not implicitly tagged get tag from underlying type */ 470 if (tag == -1) 471 tag = utype; 472 473 /* Output tag+length followed by content octets */ 474 if (out) { 475 if (usetag) 476 ASN1_put_object(out, ndef, len, tag, aclass); 477 asn1_ex_i2c(pval, *out, &utype, it); 478 if (ndef) 479 ASN1_put_eoc(out); 480 else 481 *out += len; 482 } 483 484 if (usetag) 485 return ASN1_object_size(ndef, len, tag); 486 return len; 487 } 488 489 /* Produce content octets from a structure */ 490 491 static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype, 492 const ASN1_ITEM *it) 493 { 494 ASN1_BOOLEAN *tbool = NULL; 495 ASN1_STRING *strtmp; 496 ASN1_OBJECT *otmp; 497 int utype; 498 const unsigned char *cont; 499 unsigned char c; 500 int len; 501 const ASN1_PRIMITIVE_FUNCS *pf; 502 pf = it->funcs; 503 if (pf && pf->prim_i2c) 504 return pf->prim_i2c(pval, cout, putype, it); 505 506 /* Should type be omitted? */ 507 if ((it->itype != ASN1_ITYPE_PRIMITIVE) 508 || (it->utype != V_ASN1_BOOLEAN)) { 509 if (!*pval) 510 return -1; 511 } 512 513 if (it->itype == ASN1_ITYPE_MSTRING) { 514 /* If MSTRING type set the underlying type */ 515 strtmp = (ASN1_STRING *)*pval; 516 utype = strtmp->type; 517 *putype = utype; 518 } else if (it->utype == V_ASN1_ANY) { 519 /* If ANY set type and pointer to value */ 520 ASN1_TYPE *typ; 521 typ = (ASN1_TYPE *)*pval; 522 utype = typ->type; 523 *putype = utype; 524 pval = &typ->value.asn1_value; 525 } else 526 utype = *putype; 527 528 switch (utype) { 529 case V_ASN1_OBJECT: 530 otmp = (ASN1_OBJECT *)*pval; 531 cont = otmp->data; 532 len = otmp->length; 533 if (cont == NULL || len == 0) 534 return -1; 535 break; 536 537 case V_ASN1_NULL: 538 cont = NULL; 539 len = 0; 540 break; 541 542 case V_ASN1_BOOLEAN: 543 tbool = (ASN1_BOOLEAN *)pval; 544 if (*tbool == -1) 545 return -1; 546 if (it->utype != V_ASN1_ANY) { 547 /* 548 * Default handling if value == size field then omit 549 */ 550 if (*tbool && (it->size > 0)) 551 return -1; 552 if (!*tbool && !it->size) 553 return -1; 554 } 555 c = (unsigned char)*tbool; 556 cont = &c; 557 len = 1; 558 break; 559 560 case V_ASN1_BIT_STRING: 561 return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval, 562 cout ? &cout : NULL); 563 564 case V_ASN1_INTEGER: 565 case V_ASN1_ENUMERATED: 566 /* 567 * These are all have the same content format as ASN1_INTEGER 568 */ 569 return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL); 570 571 case V_ASN1_OCTET_STRING: 572 case V_ASN1_NUMERICSTRING: 573 case V_ASN1_PRINTABLESTRING: 574 case V_ASN1_T61STRING: 575 case V_ASN1_VIDEOTEXSTRING: 576 case V_ASN1_IA5STRING: 577 case V_ASN1_UTCTIME: 578 case V_ASN1_GENERALIZEDTIME: 579 case V_ASN1_GRAPHICSTRING: 580 case V_ASN1_VISIBLESTRING: 581 case V_ASN1_GENERALSTRING: 582 case V_ASN1_UNIVERSALSTRING: 583 case V_ASN1_BMPSTRING: 584 case V_ASN1_UTF8STRING: 585 case V_ASN1_SEQUENCE: 586 case V_ASN1_SET: 587 default: 588 /* All based on ASN1_STRING and handled the same */ 589 strtmp = (ASN1_STRING *)*pval; 590 /* Special handling for NDEF */ 591 if ((it->size == ASN1_TFLG_NDEF) 592 && (strtmp->flags & ASN1_STRING_FLAG_NDEF)) { 593 if (cout) { 594 strtmp->data = cout; 595 strtmp->length = 0; 596 } 597 /* Special return code */ 598 return -2; 599 } 600 cont = strtmp->data; 601 len = strtmp->length; 602 603 break; 604 605 } 606 if (cout && len) 607 memcpy(cout, cont, len); 608 return len; 609 } 610