1 /* der-decoder.c - Distinguished Encoding Rules Encoder 2 * Copyright (C) 2001, 2004, 2008, 2012 g10 Code GmbH 3 * 4 * This file is part of KSBA. 5 * 6 * KSBA is free software; you can redistribute it and/or modify 7 * it under the terms of either 8 * 9 * - the GNU Lesser General Public License as published by the Free 10 * Software Foundation; either version 3 of the License, or (at 11 * your option) any later version. 12 * 13 * or 14 * 15 * - the GNU General Public License as published by the Free 16 * Software Foundation; either version 2 of the License, or (at 17 * your option) any later version. 18 * 19 * or both in parallel, as here. 20 * 21 * KSBA is distributed in the hope that it will be useful, but WITHOUT 22 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 23 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 24 * License for more details. 25 * 26 * You should have received a copies of the GNU General Public License 27 * and the GNU Lesser General Public License along with this program; 28 * if not, see <http://www.gnu.org/licenses/>. 29 */ 30 31 #include <config.h> 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <string.h> 35 #include <assert.h> 36 #include "util.h" 37 38 #include "ksba.h" 39 #include "asn1-func.h" 40 #include "ber-help.h" 41 #include "der-encoder.h" 42 #include "convert.h" 43 44 struct der_encoder_s { 45 AsnNode module; /* the ASN.1 structure */ 46 ksba_writer_t writer; 47 const char *last_errdesc; /* string with the error description */ 48 AsnNode root; /* of the expanded parse tree */ 49 int debug; 50 }; 51 52 /* To be useful for the DER encoder we store all data direct as the 53 binary image, so we use the VALTYPE_MEM */ 54 static gpg_error_t 55 store_value (AsnNode node, const void *buffer, size_t length) 56 { 57 _ksba_asn_set_value (node, VALTYPE_MEM, buffer, length); 58 return 0; 59 } 60 61 static void 62 clear_value (AsnNode node) 63 { 64 _ksba_asn_set_value (node, VALTYPE_NULL, NULL, 0); 65 } 66 67 68 69 70 DerEncoder 71 _ksba_der_encoder_new (void) 72 { 73 DerEncoder d; 74 75 d = xtrycalloc (1, sizeof *d); 76 if (!d) 77 return NULL; 78 79 return d; 80 } 81 82 void 83 _ksba_der_encoder_release (DerEncoder d) 84 { 85 xfree (d); 86 } 87 88 89 /** 90 * _ksba_der_encoder_set_module: 91 * @d: Decoder object 92 * @module: ASN.1 Parse tree 93 * 94 * Initialize the decoder with the ASN.1 module. Note, that this is a 95 * shallow copy of the module. Fixme: What about ref-counting of 96 * AsnNodes? 97 * 98 * Return value: 0 on success or an error code 99 **/ 100 gpg_error_t 101 _ksba_der_encoder_set_module (DerEncoder d, ksba_asn_tree_t module) 102 { 103 if (!d || !module) 104 return gpg_error (GPG_ERR_INV_VALUE); 105 if (d->module) 106 return gpg_error (GPG_ERR_CONFLICT); /* module already set */ 107 108 d->module = module->parse_tree; 109 return 0; 110 } 111 112 113 gpg_error_t 114 _ksba_der_encoder_set_writer (DerEncoder d, ksba_writer_t w) 115 { 116 if (!d || !w) 117 return gpg_error (GPG_ERR_INV_VALUE); 118 if (d->writer) 119 return gpg_error (GPG_ERR_CONFLICT); /* reader already set */ 120 121 d->writer = w; 122 return 0; 123 } 124 125 126 127 /* 128 Helpers to construct and write out objects 129 */ 130 131 132 /* Create and write a 133 134 AlgorithmIdentifier ::= SEQUENCE { 135 algorithm OBJECT IDENTIFIER, 136 parameters ANY DEFINED BY algorithm OPTIONAL 137 } 138 139 where parameters will be set to NULL if parm is NULL or to an octet 140 string with the given parm. As a special hack parameter will not be 141 written if PARM is given but parmlen is 0. */ 142 gpg_error_t 143 _ksba_der_write_algorithm_identifier (ksba_writer_t w, const char *oid, 144 const void *parm, size_t parmlen) 145 { 146 gpg_error_t err; 147 unsigned char *buf; 148 size_t len; 149 int no_null = (parm && !parmlen); 150 151 err = ksba_oid_from_str (oid, &buf, &len); 152 if (err) 153 return err; 154 155 /* write the sequence */ 156 /* fixme: the the length to encode the TLV values are actually not 157 just 2 byte each but depend on the length of the values - for 158 our purposes the static values do work. */ 159 err = _ksba_ber_write_tl (w, TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, 160 (no_null? 2:4) + len + (parm? parmlen:0)); 161 if (err) 162 goto leave; 163 164 /* the OBJECT ID header and the value */ 165 err = _ksba_ber_write_tl (w, TYPE_OBJECT_ID, CLASS_UNIVERSAL, 0, len); 166 if (!err) 167 err = ksba_writer_write (w, buf, len); 168 if (err) 169 goto leave; 170 171 /* Write the parameter */ 172 if (no_null) 173 ; 174 else if (parm) 175 { 176 err = _ksba_ber_write_tl (w, TYPE_OCTET_STRING, CLASS_UNIVERSAL, 177 0, parmlen); 178 if (!err) 179 err = ksba_writer_write (w, parm, parmlen); 180 } 181 else 182 { 183 err = _ksba_ber_write_tl (w, TYPE_NULL, CLASS_UNIVERSAL, 0, 0); 184 } 185 186 leave: 187 xfree (buf); 188 return err; 189 } 190 191 192 193 194 195 /************************************************* 196 *** Copy data from a tree image to the tree *** 197 *************************************************/ 198 199 /* Copy all values from the tree SRC (with values store in SRCIMAGE) 200 to the tree DST */ 201 gpg_error_t 202 _ksba_der_copy_tree (AsnNode dst_root, 203 AsnNode src_root, const unsigned char *src_image) 204 { 205 AsnNode s, d; 206 207 s = src_root; 208 d = dst_root; 209 /* note: we use the is_any flags becuase an inserted copy may have 210 already changed the any tag to the actual type */ 211 while (s && d && (s->type == d->type || d->flags.is_any)) 212 { 213 if (d->flags.is_any) 214 d->type = s->type; 215 216 if (s->flags.in_array && s->right) 217 { 218 if (!_ksba_asn_insert_copy (d)) 219 return gpg_error (GPG_ERR_ENOMEM); 220 } 221 222 if ( !_ksba_asn_is_primitive (s->type) ) 223 ; 224 else if (s->off == -1) 225 clear_value (d); 226 else 227 store_value (d, src_image + s->off + s->nhdr, s->len); 228 229 s = _ksba_asn_walk_tree (src_root, s); 230 d = _ksba_asn_walk_tree (dst_root, d); 231 } 232 233 if (s || d) 234 { 235 /* fputs ("ksba_der_copy_tree: trees don't match\nSOURCE TREE:\n", stderr); */ 236 /* _ksba_asn_node_dump_all (src_root, stderr); */ 237 /* fputs ("DESTINATION TREE:\n", stderr); */ 238 /* _ksba_asn_node_dump_all (dst_root, stderr); */ 239 return gpg_error (GPG_ERR_ENCODING_PROBLEM); 240 } 241 return 0; 242 } 243 244 245 246 /********************************************* 247 ********** Store data in a tree ************* 248 *********************************************/ 249 250 251 gpg_error_t 252 _ksba_der_store_time (AsnNode node, const ksba_isotime_t atime) 253 { 254 char buf[50], *p; 255 int need_gen; 256 gpg_error_t err; 257 258 /* First check that ATIME is indeed as formatted as expected. */ 259 err = _ksba_assert_time_format (atime); 260 if (err) 261 return err; 262 263 memcpy (buf, atime, 8); 264 memcpy (buf+8, atime+9, 6); 265 strcpy (buf+14, "Z"); 266 267 /* We need to use generalized time beginning with the year 2050. */ 268 need_gen = (_ksba_cmp_time (atime, "20500101T000000") >= 0); 269 270 if (node->type == TYPE_ANY) 271 node->type = need_gen? TYPE_GENERALIZED_TIME : TYPE_UTC_TIME; 272 else if (node->type == TYPE_CHOICE) 273 { /* find a suitable choice to store the value */ 274 AsnNode n; 275 276 for (n=node->down; n; n=n->right) 277 { 278 if ( (need_gen && n->type == TYPE_GENERALIZED_TIME) 279 || (!need_gen && n->type == TYPE_UTC_TIME)) 280 { 281 node = n; 282 break; 283 } 284 } 285 } 286 287 if (node->type == TYPE_GENERALIZED_TIME 288 || node->type == TYPE_UTC_TIME) 289 { 290 p = node->type == TYPE_UTC_TIME? (buf+2):buf; 291 return store_value (node, p, strlen (p)); 292 } 293 else 294 return gpg_error (GPG_ERR_INV_VALUE); 295 } 296 297 /* Store the utf-8 STRING in NODE. */ 298 gpg_error_t 299 _ksba_der_store_string (AsnNode node, const char *string) 300 { 301 if (node->type == TYPE_CHOICE) 302 { 303 /* find a suitable choice to store the value */ 304 } 305 306 307 if (node->type == TYPE_PRINTABLE_STRING) 308 { 309 return store_value (node, string, strlen (string)); 310 } 311 else 312 return gpg_error (GPG_ERR_INV_VALUE); 313 } 314 315 316 /* Store the integer VALUE in NODE. VALUE is assumed to be a DER 317 encoded integer prefixed with 4 bytes given its length in network 318 byte order. */ 319 gpg_error_t 320 _ksba_der_store_integer (AsnNode node, const unsigned char *value) 321 { 322 if (node->type == TYPE_INTEGER) 323 { 324 size_t len; 325 326 len = (value[0] << 24) | (value[1] << 16) | (value[2] << 8) | value[3]; 327 return store_value (node, value+4, len); 328 } 329 else 330 return gpg_error (GPG_ERR_INV_VALUE); 331 } 332 333 gpg_error_t 334 _ksba_der_store_oid (AsnNode node, const char *oid) 335 { 336 gpg_error_t err; 337 338 if (node->type == TYPE_ANY) 339 node->type = TYPE_OBJECT_ID; 340 341 if (node->type == TYPE_OBJECT_ID) 342 { 343 unsigned char *buf; 344 size_t len; 345 346 err = ksba_oid_from_str (oid, &buf, &len); 347 if (err) 348 return err; 349 err = store_value (node, buf, len); 350 xfree (buf); 351 return err; 352 } 353 else 354 return gpg_error (GPG_ERR_INV_VALUE); 355 } 356 357 358 gpg_error_t 359 _ksba_der_store_octet_string (AsnNode node, const char *buf, size_t len) 360 { 361 if (node->type == TYPE_ANY) 362 node->type = TYPE_OCTET_STRING; 363 364 if (node->type == TYPE_OCTET_STRING) 365 { 366 return store_value (node, buf, len); 367 } 368 else 369 return gpg_error (GPG_ERR_INV_VALUE); 370 } 371 372 373 gpg_error_t 374 _ksba_der_store_sequence (AsnNode node, const unsigned char *buf, size_t len) 375 { 376 if (node->type == TYPE_ANY) 377 node->type = TYPE_PRE_SEQUENCE; 378 379 if (node->type == TYPE_SEQUENCE || node->type == TYPE_PRE_SEQUENCE) 380 { 381 return store_value (node, buf, len); 382 } 383 else 384 return gpg_error (GPG_ERR_INV_VALUE); 385 } 386 387 388 gpg_error_t 389 _ksba_der_store_null (AsnNode node) 390 { 391 if (node->type == TYPE_ANY) 392 node->type = TYPE_NULL; 393 394 if (node->type == TYPE_NULL) 395 { 396 clear_value (node); 397 return 0; 398 } 399 else 400 return gpg_error (GPG_ERR_INV_VALUE); 401 } 402 403 404 /* 405 Actual DER encoder 406 */ 407 408 /* We have a value for this node. Calculate the length of the header 409 and store it in node->nhdr and store the length of the value in 410 node->value. We assume that this is a primitive node and has a 411 value of type VALTYPE_MEM. */ 412 static void 413 set_nhdr_and_len (AsnNode node, unsigned long length) 414 { 415 int buflen = 0; 416 417 if (node->type == TYPE_SET_OF || node->type == TYPE_SEQUENCE_OF) 418 buflen++; 419 else if (node->type == TYPE_TAG) 420 buflen++; 421 else if (node->type < 0x1f || node->type == TYPE_PRE_SEQUENCE) 422 buflen++; 423 else 424 { 425 never_reached (); 426 /* Fixme: tags with values above 31 are not yet implemented */ 427 } 428 429 if (!node->type /*&& !class*/) 430 buflen++; /* end tag */ 431 else if (node->type == TYPE_NULL /*&& !class*/) 432 buflen++; /* NULL tag */ 433 else if (!length) 434 buflen++; /* indefinite length */ 435 else if (length < 128) 436 buflen++; 437 else 438 { 439 buflen += (length <= 0xff ? 2: 440 length <= 0xffff ? 3: 441 length <= 0xffffff ? 4: 5); 442 } 443 444 node->len = length; 445 node->nhdr = buflen; 446 } 447 448 /* Like above but put now put it into buffer. return the number of 449 bytes copied. There is no need to do length checking here */ 450 static size_t 451 copy_nhdr_and_len (unsigned char *buffer, AsnNode node) 452 { 453 unsigned char *p = buffer; 454 int tag, class; 455 unsigned long length; 456 457 tag = node->type; 458 class = CLASS_UNIVERSAL; 459 length = node->len; 460 461 if (tag == TYPE_SET_OF) 462 tag = TYPE_SET; 463 else if (tag == TYPE_SEQUENCE_OF) 464 tag = TYPE_SEQUENCE; 465 else if (tag == TYPE_PRE_SEQUENCE) 466 tag = TYPE_SEQUENCE; 467 else if (tag == TYPE_TAG) 468 { 469 class = CLASS_CONTEXT; /* Hmmm: we no way to handle other classes */ 470 tag = node->value.v_ulong; 471 } 472 if (tag < 0x1f) 473 { 474 *p = (class << 6) | tag; 475 if (!_ksba_asn_is_primitive (tag)) 476 *p |= 0x20; 477 p++; 478 } 479 else 480 { 481 /* fixme: Not_Implemented*/ 482 } 483 484 if (!tag && !class) 485 *p++ = 0; /* end tag */ 486 else if (tag == TYPE_NULL && !class) 487 *p++ = 0; /* NULL tag */ 488 else if (!length) 489 *p++ = 0x80; /* indefinite length - can't happen! */ 490 else if (length < 128) 491 *p++ = length; 492 else 493 { 494 int i; 495 496 /* fixme: if we know the sizeof an ulong we could support larger 497 objects - however this is pretty ridiculous */ 498 i = (length <= 0xff ? 1: 499 length <= 0xffff ? 2: 500 length <= 0xffffff ? 3: 4); 501 502 *p++ = (0x80 | i); 503 if (i > 3) 504 *p++ = length >> 24; 505 if (i > 2) 506 *p++ = length >> 16; 507 if (i > 1) 508 *p++ = length >> 8; 509 *p++ = length; 510 } 511 512 return p - buffer; 513 } 514 515 516 517 static unsigned long 518 sum_up_lengths (AsnNode root) 519 { 520 AsnNode n; 521 unsigned long len = 0; 522 523 if (root->type == TYPE_NULL) 524 return root->nhdr; 525 526 if (!(n=root->down) || _ksba_asn_is_primitive (root->type)) 527 len = root->len; 528 else 529 { 530 for (; n; n = n->right) 531 len += sum_up_lengths (n); 532 } 533 if ( !_ksba_asn_is_primitive (root->type) 534 && root->type != TYPE_CHOICE 535 && len 536 && !root->flags.is_implicit) 537 { /* this is a constructed one */ 538 set_nhdr_and_len (root, len); 539 } 540 541 return len? (len + root->nhdr):0; 542 } 543 544 /* Create a DER encoding from the value tree ROOT and return an 545 allocated image of appropriate length in r_image and r_imagelen. 546 The value tree is modified so that it can be used the same way as a 547 parsed one, i.e the elements off, and len are set to point into 548 image. */ 549 gpg_error_t 550 _ksba_der_encode_tree (AsnNode root, 551 unsigned char **r_image, size_t *r_imagelen) 552 { 553 AsnNode n; 554 unsigned char *image; 555 size_t imagelen, len; 556 557 /* clear out all fields */ 558 for (n=root; n ; n = _ksba_asn_walk_tree (root, n)) 559 { 560 n->off = -1; 561 n->len = 0; 562 n->nhdr = 0; 563 } 564 565 /* Set default values */ 566 /* FIXME */ 567 568 /* calculate the length of the headers. These are the tag and 569 length fields of all primitive elements */ 570 for (n=root; n ; n = _ksba_asn_walk_tree (root, n)) 571 { 572 if (_ksba_asn_is_primitive (n->type) 573 && !n->flags.is_implicit 574 && ((n->valuetype == VALTYPE_MEM && n->value.v_mem.len) 575 || n->type == TYPE_NULL)) 576 set_nhdr_and_len (n, n->value.v_mem.len); 577 } 578 579 /* Now calculate the length of all constructed types */ 580 imagelen = sum_up_lengths (root); 581 582 #if 0 583 /* set off to zero, so that it can be dumped */ 584 for (n=root; n ; n = _ksba_asn_walk_tree (root, n)) 585 n->off = 0; 586 fputs ("DER encoded value Tree:\n", stderr); 587 _ksba_asn_node_dump_all (root, stderr); 588 for (n=root; n ; n = _ksba_asn_walk_tree (root, n)) 589 n->off = -1; 590 #endif 591 592 /* now we can create an encoding in image */ 593 image = xtrymalloc (imagelen); 594 if (!image) 595 return gpg_error (GPG_ERR_ENOMEM); 596 len = 0; 597 for (n=root; n ; n = _ksba_asn_walk_tree (root, n)) 598 { 599 size_t nbytes; 600 601 if (!n->nhdr) 602 continue; 603 assert (n->off == -1); 604 assert (len < imagelen); 605 n->off = len; 606 nbytes = copy_nhdr_and_len (image+len, n); 607 len += nbytes; 608 if ( _ksba_asn_is_primitive (n->type) 609 && n->valuetype == VALTYPE_MEM 610 && n->value.v_mem.len ) 611 { 612 nbytes = n->value.v_mem.len; 613 assert (len + nbytes <= imagelen); 614 memcpy (image+len, n->value.v_mem.buf, nbytes); 615 len += nbytes; 616 } 617 } 618 619 assert (len == imagelen); 620 621 *r_image = image; 622 if (r_imagelen) 623 *r_imagelen = imagelen; 624 return 0; 625 } 626