1 /*- 2 * Copyright (c) 2009 The NetBSD Foundation, Inc. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to The NetBSD Foundation 6 * by Alistair Crooks (agc@NetBSD.org) 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 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 */ 29 /* 30 * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) 31 * All rights reserved. 32 * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted 33 * their moral rights under the UK Copyright Design and Patents Act 1988 to 34 * be recorded as the authors of this copyright work. 35 * 36 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 37 * use this file except in compliance with the License. 38 * 39 * You may obtain a copy of the License at 40 * http://www.apache.org/licenses/LICENSE-2.0 41 * 42 * Unless required by applicable law or agreed to in writing, software 43 * distributed under the License is distributed on an "AS IS" BASIS, 44 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 45 * 46 * See the License for the specific language governing permissions and 47 * limitations under the License. 48 */ 49 50 /** \file 51 * This file contains the base functions used by the writers. 52 */ 53 #include "config.h" 54 55 #ifdef HAVE_SYS_CDEFS_H 56 #include <sys/cdefs.h> 57 #endif 58 59 #if defined(__NetBSD__) 60 __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); 61 __RCSID("$NetBSD: writer.c,v 1.13 2009/06/13 05:25:09 agc Exp $"); 62 #endif 63 64 #include <sys/types.h> 65 66 #ifdef HAVE_SYS_UIO_H 67 #include <sys/uio.h> 68 #endif 69 70 #ifdef HAVE_FCNTL_H 71 #include <fcntl.h> 72 #endif 73 74 #include <stdlib.h> 75 #include <string.h> 76 77 #ifdef HAVE_UNISTD_H 78 #include <unistd.h> 79 #endif 80 81 #ifdef HAVE_OPENSSL_CAST_H 82 #include <openssl/cast.h> 83 #endif 84 85 #include "create.h" 86 #include "writer.h" 87 #include "keyring.h" 88 #include "signature.h" 89 #include "packet.h" 90 #include "packet-parse.h" 91 #include "readerwriter.h" 92 #include "memory.h" 93 #include "netpgpdefs.h" 94 #include "version.h" 95 #include "netpgpdigest.h" 96 97 98 /* 99 * return 1 if OK, otherwise 0 100 */ 101 static unsigned 102 base_write(const void *src, unsigned len, __ops_output_t *out) 103 { 104 return out->writer.writer(src, len, &out->errors, &out->writer); 105 } 106 107 /** 108 * \ingroup Core_WritePackets 109 * 110 * \param src 111 * \param len 112 * \param output 113 * \return 1 if OK, otherwise 0 114 */ 115 116 unsigned 117 __ops_write(__ops_output_t *output, const void *src, unsigned len) 118 { 119 return base_write(src, len, output); 120 } 121 122 /** 123 * \ingroup Core_WritePackets 124 * \param n 125 * \param len 126 * \param output 127 * \return 1 if OK, otherwise 0 128 */ 129 130 unsigned 131 __ops_write_scalar(__ops_output_t *output, unsigned n, unsigned len) 132 { 133 unsigned char c; 134 135 while (len-- > 0) { 136 c = n >> (len * 8); 137 if (!base_write(&c, 1, output)) { 138 return 0; 139 } 140 } 141 return 1; 142 } 143 144 /** 145 * \ingroup Core_WritePackets 146 * \param bn 147 * \param output 148 * \return 1 if OK, otherwise 0 149 */ 150 151 unsigned 152 __ops_write_mpi(__ops_output_t *output, const BIGNUM *bn) 153 { 154 unsigned char buf[NETPGP_BUFSIZ]; 155 unsigned bits = (unsigned)BN_num_bits(bn); 156 157 if (bits > 65535) { 158 (void) fprintf(stderr, "__ops_write_mpi: too large %u\n", bits); 159 return 0; 160 } 161 BN_bn2bin(bn, buf); 162 return __ops_write_scalar(output, bits, 2) && 163 __ops_write(output, buf, (bits + 7) / 8); 164 } 165 166 /** 167 * \ingroup Core_WritePackets 168 * \param tag 169 * \param output 170 * \return 1 if OK, otherwise 0 171 */ 172 173 unsigned 174 __ops_write_ptag(__ops_output_t *output, __ops_content_tag_t tag) 175 { 176 unsigned char c; 177 178 c = tag | OPS_PTAG_ALWAYS_SET | OPS_PTAG_NEW_FORMAT; 179 return base_write(&c, 1, output); 180 } 181 182 /** 183 * \ingroup Core_WritePackets 184 * \param len 185 * \param output 186 * \return 1 if OK, otherwise 0 187 */ 188 189 unsigned 190 __ops_write_length(__ops_output_t *output, unsigned len) 191 { 192 unsigned char c[2]; 193 194 if (len < 192) { 195 c[0] = len; 196 return base_write(c, 1, output); 197 } 198 if (len < 8192 + 192) { 199 c[0] = ((len - 192) >> 8) + 192; 200 c[1] = (len - 192) % 256; 201 return base_write(c, 2, output); 202 } 203 return __ops_write_scalar(output, 0xff, 1) && 204 __ops_write_scalar(output, len, 4); 205 } 206 207 /* 208 * Note that we finalise from the top down, so we don't use writers below 209 * that have already been finalised 210 */ 211 unsigned 212 writer_info_finalise(__ops_error_t **errors, __ops_writer_t *writer) 213 { 214 unsigned ret = 1; 215 216 if (writer->finaliser) { 217 ret = writer->finaliser(errors, writer); 218 writer->finaliser = NULL; 219 } 220 if (writer->next && !writer_info_finalise(errors, writer->next)) { 221 writer->finaliser = NULL; 222 return 0; 223 } 224 return ret; 225 } 226 227 void 228 writer_info_delete(__ops_writer_t *writer) 229 { 230 /* we should have finalised before deleting */ 231 if (writer->finaliser) { 232 (void) fprintf(stderr, "writer_info_delete: not finalised\n"); 233 return; 234 } 235 if (writer->next) { 236 writer_info_delete(writer->next); 237 free(writer->next); 238 writer->next = NULL; 239 } 240 if (writer->destroyer) { 241 writer->destroyer(writer); 242 writer->destroyer = NULL; 243 } 244 writer->writer = NULL; 245 } 246 247 /** 248 * \ingroup Core_Writers 249 * 250 * Set a writer in output. There should not be another writer set. 251 * 252 * \param output The output structure 253 * \param writer 254 * \param finaliser 255 * \param destroyer 256 * \param arg The argument for the writer and destroyer 257 */ 258 void 259 __ops_writer_set(__ops_output_t *output, 260 __ops_writer_func_t *writer, 261 __ops_writer_finaliser_t *finaliser, 262 __ops_writer_destroyer_t *destroyer, 263 void *arg) 264 { 265 if (output->writer.writer) { 266 (void) fprintf(stderr, "__ops_writer_set: already set\n"); 267 } else { 268 output->writer.writer = writer; 269 output->writer.finaliser = finaliser; 270 output->writer.destroyer = destroyer; 271 output->writer.arg = arg; 272 } 273 } 274 275 /** 276 * \ingroup Core_Writers 277 * 278 * Push a writer in output. There must already be another writer set. 279 * 280 * \param output The output structure 281 * \param writer 282 * \param finaliser 283 * \param destroyer 284 * \param arg The argument for the writer and destroyer 285 */ 286 void 287 __ops_writer_push(__ops_output_t *output, 288 __ops_writer_func_t *writer, 289 __ops_writer_finaliser_t *finaliser, 290 __ops_writer_destroyer_t *destroyer, 291 void *arg) 292 { 293 __ops_writer_t *copy = calloc(1, sizeof(*copy)); 294 295 if (output->writer.writer == NULL) { 296 (void) fprintf(stderr, "__ops_writer_push: no orig writer\n"); 297 } else { 298 *copy = output->writer; 299 output->writer.next = copy; 300 301 output->writer.writer = writer; 302 output->writer.finaliser = finaliser; 303 output->writer.destroyer = destroyer; 304 output->writer.arg = arg; 305 } 306 } 307 308 void 309 __ops_writer_pop(__ops_output_t *output) 310 { 311 __ops_writer_t *next; 312 313 /* Make sure the finaliser has been called. */ 314 if (output->writer.finaliser) { 315 (void) fprintf(stderr, 316 "__ops_writer_pop: finaliser not called\n"); 317 } else if (output->writer.next == NULL) { 318 (void) fprintf(stderr, 319 "__ops_writer_pop: not a stacked writer\n"); 320 } else { 321 if (output->writer.destroyer) { 322 output->writer.destroyer(&output->writer); 323 } 324 next = output->writer.next; 325 output->writer = *next; 326 free(next); 327 } 328 } 329 330 /** 331 * \ingroup Core_Writers 332 * 333 * Close the writer currently set in output. 334 * 335 * \param output The output structure 336 */ 337 unsigned 338 __ops_writer_close(__ops_output_t *output) 339 { 340 unsigned ret = writer_info_finalise(&output->errors, &output->writer); 341 342 writer_info_delete(&output->writer); 343 return ret; 344 } 345 346 /** 347 * \ingroup Core_Writers 348 * 349 * Get the arg supplied to __ops_createinfo_set_writer(). 350 * 351 * \param writer The writer_info structure 352 * \return The arg 353 */ 354 void * 355 __ops_writer_get_arg(__ops_writer_t *writer) 356 { 357 return writer->arg; 358 } 359 360 /** 361 * \ingroup Core_Writers 362 * 363 * Write to the next writer down in the stack. 364 * 365 * \param src The data to write. 366 * \param len The length of src. 367 * \param errors A place to store errors. 368 * \param writer The writer_info structure. 369 * \return Success - if 0, then errors should contain the error. 370 */ 371 unsigned 372 __ops_stacked_write(const void *src, unsigned len, 373 __ops_error_t ** errors, __ops_writer_t *writer) 374 { 375 return writer->next->writer(src, len, errors, writer->next); 376 } 377 378 /** 379 * \ingroup Core_Writers 380 * 381 * Free the arg. Many writers just have a calloc()ed lump of storage, this 382 * function releases it. 383 * 384 * \param writer the info structure. 385 */ 386 static void 387 generic_destroyer(__ops_writer_t *writer) 388 { 389 (void) free(__ops_writer_get_arg(writer)); 390 } 391 392 /** 393 * \ingroup Core_Writers 394 * 395 * A writer that just writes to the next one down. Useful for when you 396 * want to insert just a finaliser into the stack. 397 */ 398 unsigned 399 __ops_writer_passthrough(const unsigned char *src, 400 unsigned len, 401 __ops_error_t **errors, 402 __ops_writer_t *writer) 403 { 404 return __ops_stacked_write(src, len, errors, writer); 405 } 406 407 /**************************************************************************/ 408 409 /** 410 * \struct dashesc_t 411 */ 412 typedef struct { 413 unsigned seen_nl:1; 414 unsigned seen_cr:1; 415 __ops_create_sig_t *sig; 416 __ops_memory_t *trailing; 417 } dashesc_t; 418 419 static unsigned 420 dash_esc_writer(const unsigned char *src, 421 unsigned len, 422 __ops_error_t **errors, 423 __ops_writer_t *writer) 424 { 425 dashesc_t *dash = __ops_writer_get_arg(writer); 426 unsigned n; 427 428 if (__ops_get_debug_level(__FILE__)) { 429 unsigned int i = 0; 430 431 (void) fprintf(stderr, "dash_esc_writer writing %d:\n", len); 432 for (i = 0; i < len; i++) { 433 fprintf(stderr, "0x%02x ", src[i]); 434 if (((i + 1) % 16) == 0) { 435 (void) fprintf(stderr, "\n"); 436 } else if (((i + 1) % 8) == 0) { 437 (void) fprintf(stderr, " "); 438 } 439 } 440 (void) fprintf(stderr, "\n"); 441 } 442 /* XXX: make this efficient */ 443 for (n = 0; n < len; ++n) { 444 unsigned l; 445 446 if (dash->seen_nl) { 447 if (src[n] == '-' && 448 !__ops_stacked_write("- ", 2, errors, writer)) { 449 return 0; 450 } 451 dash->seen_nl = 0; 452 } 453 dash->seen_nl = src[n] == '\n'; 454 455 if (dash->seen_nl && !dash->seen_cr) { 456 if (!__ops_stacked_write("\r", 1, errors, writer)) { 457 return 0; 458 } 459 __ops_sig_add_data(dash->sig, "\r", 1); 460 } 461 dash->seen_cr = src[n] == '\r'; 462 463 if (!__ops_stacked_write(&src[n], 1, errors, writer)) { 464 return 0; 465 } 466 467 /* trailing whitespace isn't included in the signature */ 468 if (src[n] == ' ' || src[n] == '\t') { 469 __ops_memory_add(dash->trailing, &src[n], 1); 470 } else { 471 if ((l = __ops_mem_len(dash->trailing)) != 0) { 472 if (!dash->seen_nl && !dash->seen_cr) { 473 __ops_sig_add_data(dash->sig, 474 __ops_mem_data(dash->trailing), l); 475 } 476 __ops_memory_clear(dash->trailing); 477 } 478 __ops_sig_add_data(dash->sig, &src[n], 1); 479 } 480 } 481 return 1; 482 } 483 484 /** 485 * \param writer 486 */ 487 static void 488 dash_escaped_destroyer(__ops_writer_t *writer) 489 { 490 dashesc_t *dash; 491 492 dash = __ops_writer_get_arg(writer); 493 __ops_memory_free(dash->trailing); 494 (void) free(dash); 495 } 496 497 /** 498 * \ingroup Core_WritersNext 499 * \brief Push Clearsigned Writer onto stack 500 * \param output 501 * \param sig 502 */ 503 unsigned 504 __ops_writer_push_clearsigned(__ops_output_t *output, __ops_create_sig_t *sig) 505 { 506 static const char header[] = 507 "-----BEGIN PGP SIGNED MESSAGE-----\r\nHash: "; 508 const char *hash = __ops_text_from_hash(__ops_sig_get_hash(sig)); 509 dashesc_t *dash = calloc(1, sizeof(*dash)); 510 unsigned ret; 511 512 ret = (__ops_write(output, header, sizeof(header) - 1) && 513 __ops_write(output, hash, strlen(hash)) && 514 __ops_write(output, "\r\n\r\n", 4)); 515 516 if (ret == 0) { 517 OPS_ERROR(&output->errors, OPS_E_W, 518 "Error pushing clearsigned header"); 519 free(dash); 520 return ret; 521 } 522 dash->seen_nl = 1; 523 dash->sig = sig; 524 dash->trailing = __ops_memory_new(); 525 __ops_writer_push(output, dash_esc_writer, NULL, 526 dash_escaped_destroyer, dash); 527 return ret; 528 } 529 530 531 /** 532 * \struct base64_t 533 */ 534 typedef struct { 535 unsigned pos; 536 unsigned char t; 537 unsigned checksum; 538 } base64_t; 539 540 static const char b64map[] = 541 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 542 543 static unsigned 544 base64_writer(const unsigned char *src, 545 unsigned len, 546 __ops_error_t **errors, 547 __ops_writer_t *writer) 548 { 549 base64_t *base64 = __ops_writer_get_arg(writer); 550 unsigned n; 551 552 for (n = 0; n < len;) { 553 base64->checksum = __ops_crc24(base64->checksum, src[n]); 554 if (base64->pos == 0) { 555 /* XXXXXX00 00000000 00000000 */ 556 if (!__ops_stacked_write(&b64map[(unsigned)src[n] >> 2], 557 1, errors, writer)) { 558 return 0; 559 } 560 561 /* 000000XX xxxx0000 00000000 */ 562 base64->t = (src[n++] & 3) << 4; 563 base64->pos = 1; 564 } else if (base64->pos == 1) { 565 /* 000000xx XXXX0000 00000000 */ 566 base64->t += (unsigned)src[n] >> 4; 567 if (!__ops_stacked_write(&b64map[base64->t], 1, 568 errors, writer)) { 569 return 0; 570 } 571 572 /* 00000000 0000XXXX xx000000 */ 573 base64->t = (src[n++] & 0xf) << 2; 574 base64->pos = 2; 575 } else if (base64->pos == 2) { 576 /* 00000000 0000xxxx XX000000 */ 577 base64->t += (unsigned)src[n] >> 6; 578 if (!__ops_stacked_write(&b64map[base64->t], 1, 579 errors, writer)) { 580 return 0; 581 } 582 583 /* 00000000 00000000 00XXXXXX */ 584 if (!__ops_stacked_write(&b64map[src[n++] & 0x3f], 1, 585 errors, writer)) { 586 return 0; 587 } 588 589 base64->pos = 0; 590 } 591 } 592 593 return 1; 594 } 595 596 static unsigned 597 sig_finaliser(__ops_error_t **errors, __ops_writer_t *writer) 598 { 599 static const char trail[] = "\r\n-----END PGP SIGNATURE-----\r\n"; 600 unsigned char c[3]; 601 base64_t *base64; 602 603 base64 = __ops_writer_get_arg(writer); 604 if (base64->pos) { 605 if (!__ops_stacked_write(&b64map[base64->t], 1, errors, 606 writer)) { 607 return 0; 608 } 609 if (base64->pos == 1 && 610 !__ops_stacked_write("==", 2, errors, writer)) { 611 return 0; 612 } 613 if (base64->pos == 2 && 614 !__ops_stacked_write("=", 1, errors, writer)) { 615 return 0; 616 } 617 } 618 /* Ready for the checksum */ 619 if (!__ops_stacked_write("\r\n=", 3, errors, writer)) { 620 return 0; 621 } 622 623 base64->pos = 0; /* get ready to write the checksum */ 624 625 c[0] = base64->checksum >> 16; 626 c[1] = base64->checksum >> 8; 627 c[2] = base64->checksum; 628 /* push the checksum through our own writer */ 629 if (!base64_writer(c, 3, errors, writer)) { 630 return 0; 631 } 632 633 return __ops_stacked_write(trail, sizeof(trail) - 1, errors, writer); 634 } 635 636 /** 637 * \struct linebreak_t 638 */ 639 typedef struct { 640 unsigned pos; 641 } linebreak_t; 642 643 #define BREAKPOS 76 644 645 static unsigned 646 linebreak_writer(const unsigned char *src, 647 unsigned len, 648 __ops_error_t ** errors, 649 __ops_writer_t * writer) 650 { 651 linebreak_t *linebreak = __ops_writer_get_arg(writer); 652 unsigned n; 653 654 for (n = 0; n < len; ++n, ++linebreak->pos) { 655 if (src[n] == '\r' || src[n] == '\n') { 656 linebreak->pos = 0; 657 } 658 659 if (linebreak->pos == BREAKPOS) { 660 if (!__ops_stacked_write("\r\n", 2, errors, writer)) { 661 return 0; 662 } 663 linebreak->pos = 0; 664 } 665 if (!__ops_stacked_write(&src[n], 1, errors, writer)) { 666 return 0; 667 } 668 } 669 670 return 1; 671 } 672 673 /** 674 * \ingroup Core_WritersNext 675 * \brief Push armoured signature on stack 676 * \param output 677 */ 678 unsigned 679 __ops_writer_use_armored_sig(__ops_output_t *output) 680 { 681 static const char header[] = 682 "\r\n-----BEGIN PGP SIGNATURE-----\r\nVersion: " 683 NETPGP_VERSION_STRING 684 "\r\n\r\n"; 685 base64_t *base64; 686 687 __ops_writer_pop(output); 688 if (__ops_write(output, header, sizeof(header) - 1) == 0) { 689 OPS_ERROR(&output->errors, OPS_E_W, 690 "Error switching to armoured signature"); 691 return 0; 692 } 693 __ops_writer_push(output, linebreak_writer, NULL, 694 generic_destroyer, 695 calloc(1, sizeof(linebreak_t))); 696 base64 = calloc(1, sizeof(*base64)); 697 if (!base64) { 698 OPS_MEMORY_ERROR(&output->errors); 699 return 0; 700 } 701 base64->checksum = CRC24_INIT; 702 __ops_writer_push(output, base64_writer, sig_finaliser, 703 generic_destroyer, base64); 704 return 1; 705 } 706 707 static unsigned 708 armoured_message_finaliser(__ops_error_t **errors, __ops_writer_t *writer) 709 { 710 /* TODO: This is same as sig_finaliser apart from trailer. */ 711 static const char *trailer = "\r\n-----END PGP MESSAGE-----\r\n"; 712 unsigned char c[3]; 713 base64_t *base64; 714 715 base64 = __ops_writer_get_arg(writer); 716 if (base64->pos) { 717 if (!__ops_stacked_write(&b64map[base64->t], 1, errors, 718 writer)) { 719 return 0; 720 } 721 if (base64->pos == 1 && 722 !__ops_stacked_write("==", 2, errors, writer)) { 723 return 0; 724 } 725 if (base64->pos == 2 && 726 !__ops_stacked_write("=", 1, errors, writer)) { 727 return 0; 728 } 729 } 730 /* Ready for the checksum */ 731 if (!__ops_stacked_write("\r\n=", 3, errors, writer)) { 732 return 0; 733 } 734 735 base64->pos = 0; /* get ready to write the checksum */ 736 737 c[0] = base64->checksum >> 16; 738 c[1] = base64->checksum >> 8; 739 c[2] = base64->checksum; 740 /* push the checksum through our own writer */ 741 if (!base64_writer(c, 3, errors, writer)) { 742 return 0; 743 } 744 745 return __ops_stacked_write(trailer, sizeof(trailer)-1, errors, writer); 746 } 747 748 /** 749 \ingroup Core_WritersNext 750 \brief Write a PGP MESSAGE 751 \todo replace with generic function 752 */ 753 void 754 __ops_writer_push_armor_msg(__ops_output_t *output) 755 { 756 static const char header[] = "-----BEGIN PGP MESSAGE-----\r\n"; 757 base64_t *base64; 758 759 __ops_write(output, header, sizeof(header) - 1); 760 __ops_write(output, "\r\n", 2); 761 base64 = calloc(1, sizeof(*base64)); 762 base64->checksum = CRC24_INIT; 763 __ops_writer_push(output, base64_writer, armoured_message_finaliser, 764 generic_destroyer, base64); 765 } 766 767 static unsigned 768 armoured_finaliser(__ops_armor_type_t type, 769 __ops_error_t **errors, 770 __ops_writer_t *writer) 771 { 772 static const char tail_pubkey[] = 773 "\r\n-----END PGP PUBLIC KEY BLOCK-----\r\n"; 774 static const char tail_private_key[] = 775 "\r\n-----END PGP PRIVATE KEY BLOCK-----\r\n"; 776 unsigned char c[3]; 777 unsigned int sz_tail = 0; 778 const char *tail = NULL; 779 base64_t *base64; 780 781 switch (type) { 782 case OPS_PGP_PUBLIC_KEY_BLOCK: 783 tail = tail_pubkey; 784 sz_tail = sizeof(tail_pubkey) - 1; 785 break; 786 787 case OPS_PGP_PRIVATE_KEY_BLOCK: 788 tail = tail_private_key; 789 sz_tail = sizeof(tail_private_key) - 1; 790 break; 791 792 default: 793 (void) fprintf(stderr, "armoured_finaliser: unusual type\n"); 794 return 0; 795 } 796 base64 = __ops_writer_get_arg(writer); 797 if (base64->pos) { 798 if (!__ops_stacked_write(&b64map[base64->t], 1, errors, 799 writer)) { 800 return 0; 801 } 802 if (base64->pos == 1 && !__ops_stacked_write("==", 2, errors, 803 writer)) { 804 return 0; 805 } 806 if (base64->pos == 2 && !__ops_stacked_write("=", 1, errors, 807 writer)) { 808 return 0; 809 } 810 } 811 /* Ready for the checksum */ 812 if (!__ops_stacked_write("\r\n=", 3, errors, writer)) { 813 return 0; 814 } 815 base64->pos = 0; /* get ready to write the checksum */ 816 c[0] = base64->checksum >> 16; 817 c[1] = base64->checksum >> 8; 818 c[2] = base64->checksum; 819 /* push the checksum through our own writer */ 820 if (!base64_writer(c, 3, errors, writer)) { 821 return 0; 822 } 823 return __ops_stacked_write(tail, sz_tail, errors, writer); 824 } 825 826 static unsigned 827 armored_pubkey_fini(__ops_error_t **errors, __ops_writer_t *writer) 828 { 829 return armoured_finaliser(OPS_PGP_PUBLIC_KEY_BLOCK, errors, writer); 830 } 831 832 static unsigned 833 armored_privkey_fini(__ops_error_t **errors, __ops_writer_t *writer) 834 { 835 return armoured_finaliser(OPS_PGP_PRIVATE_KEY_BLOCK, errors, writer); 836 } 837 838 /* \todo use this for other armoured types */ 839 /** 840 \ingroup Core_WritersNext 841 \brief Push Armoured Writer on stack (generic) 842 */ 843 void 844 __ops_writer_push_armoured(__ops_output_t *output, __ops_armor_type_t type) 845 { 846 static char hdr_pubkey[] = 847 "-----BEGIN PGP PUBLIC KEY BLOCK-----\r\nVersion: " 848 NETPGP_VERSION_STRING 849 "\r\n\r\n"; 850 static char hdr_private_key[] = 851 "-----BEGIN PGP PRIVATE KEY BLOCK-----\r\nVersion: " 852 NETPGP_VERSION_STRING 853 "\r\n\r\n"; 854 unsigned int sz_hdr = 0; 855 unsigned (*finaliser) (__ops_error_t **, __ops_writer_t *); 856 base64_t *base64; 857 char *header = NULL; 858 859 finaliser = NULL; 860 switch (type) { 861 case OPS_PGP_PUBLIC_KEY_BLOCK: 862 header = hdr_pubkey; 863 sz_hdr = sizeof(hdr_pubkey) - 1; 864 finaliser = armored_pubkey_fini; 865 break; 866 867 case OPS_PGP_PRIVATE_KEY_BLOCK: 868 header = hdr_private_key; 869 sz_hdr = sizeof(hdr_private_key) - 1; 870 finaliser = armored_privkey_fini; 871 break; 872 873 default: 874 (void) fprintf(stderr, 875 "__ops_writer_push_armoured: unusual type\n"); 876 return; 877 } 878 __ops_write(output, header, sz_hdr); 879 __ops_writer_push(output, linebreak_writer, NULL, 880 generic_destroyer, 881 calloc(1, sizeof(linebreak_t))); 882 base64 = calloc(1, sizeof(*base64)); 883 base64->checksum = CRC24_INIT; 884 __ops_writer_push(output, base64_writer, finaliser, 885 generic_destroyer, base64); 886 } 887 888 /**************************************************************************/ 889 890 typedef struct { 891 __ops_crypt_t *crypt; 892 int free_crypt; 893 } crypt_t; 894 895 /* 896 * This writer simply takes plaintext as input, 897 * encrypts it with the given key 898 * and outputs the resulting encrypted text 899 */ 900 static unsigned 901 encrypt_writer(const unsigned char *src, 902 unsigned len, 903 __ops_error_t **errors, 904 __ops_writer_t *writer) 905 { 906 #define BUFSZ 1024 /* arbitrary number */ 907 unsigned char encbuf[BUFSZ]; 908 unsigned remaining; 909 unsigned done = 0; 910 crypt_t *pgp_encrypt; 911 912 remaining = len; 913 pgp_encrypt = (crypt_t *) __ops_writer_get_arg(writer); 914 if (!__ops_is_sa_supported(pgp_encrypt->crypt->alg)) { 915 (void) fprintf(stderr, "encrypt_writer: not supported\n"); 916 return 0; 917 } 918 while (remaining > 0) { 919 unsigned size = (remaining < BUFSZ) ? remaining : BUFSZ; 920 921 /* memcpy(buf,src,size); // \todo copy needed here? */ 922 pgp_encrypt->crypt->cfb_encrypt(pgp_encrypt->crypt, encbuf, 923 src + done, size); 924 925 if (__ops_get_debug_level(__FILE__)) { 926 int i = 0; 927 928 (void) fprintf(stderr, "WRITING:\nunencrypted: "); 929 for (i = 0; i < 16; i++) { 930 (void) fprintf(stderr, "%2x ", src[done + i]); 931 } 932 (void) fprintf(stderr, "\nencrypted: "); 933 for (i = 0; i < 16; i++) { 934 (void) fprintf(stderr, "%2x ", encbuf[i]); 935 } 936 (void) fprintf(stderr, "\n"); 937 } 938 if (!__ops_stacked_write(encbuf, size, errors, writer)) { 939 if (__ops_get_debug_level(__FILE__)) { 940 fprintf(stderr, 941 "encrypted_writer: stacked write\n"); 942 } 943 return 0; 944 } 945 remaining -= size; 946 done += size; 947 } 948 949 return 1; 950 } 951 952 static void 953 encrypt_destroyer(__ops_writer_t *writer) 954 { 955 crypt_t *pgp_encrypt = (crypt_t *) __ops_writer_get_arg(writer); 956 957 if (pgp_encrypt->free_crypt) { 958 (void) free(pgp_encrypt->crypt); 959 } 960 (void) free(pgp_encrypt); 961 } 962 963 /** 964 \ingroup Core_WritersNext 965 \brief Push Encrypted Writer onto stack (create SE packets) 966 */ 967 void 968 __ops_push_enc_crypt(__ops_output_t *output, __ops_crypt_t *pgp_crypt) 969 { 970 /* Create encrypt to be used with this writer */ 971 /* Remember to free this in the destroyer */ 972 crypt_t *pgp_encrypt; 973 974 pgp_encrypt = calloc(1, sizeof(*pgp_encrypt)); 975 /* Setup the encrypt */ 976 pgp_encrypt->crypt = pgp_crypt; 977 pgp_encrypt->free_crypt = 0; 978 /* And push writer on stack */ 979 __ops_writer_push(output, encrypt_writer, NULL, encrypt_destroyer, 980 pgp_encrypt); 981 } 982 983 /**************************************************************************/ 984 985 typedef struct { 986 __ops_crypt_t *crypt; 987 } encrypt_se_ip_t; 988 989 static unsigned encrypt_se_ip_writer(const unsigned char *, 990 unsigned, 991 __ops_error_t **, 992 __ops_writer_t *); 993 static void encrypt_se_ip_destroyer(__ops_writer_t *); 994 995 /* */ 996 997 /** 998 \ingroup Core_WritersNext 999 \brief Push Encrypted SE IP Writer onto stack 1000 */ 1001 void 1002 __ops_push_enc_se_ip(__ops_output_t *output, const __ops_key_t *pubkey) 1003 { 1004 unsigned char *iv = NULL; 1005 __ops_crypt_t *encrypted; 1006 1007 /* Create se_ip to be used with this writer */ 1008 /* Remember to free this in the destroyer */ 1009 encrypt_se_ip_t *se_ip = calloc(1, sizeof(*se_ip)); 1010 1011 __ops_pk_sesskey_t *encrypted_pk_sesskey; 1012 1013 /* Create and write encrypted PK session key */ 1014 encrypted_pk_sesskey = __ops_create_pk_sesskey(pubkey); 1015 __ops_write_pk_sesskey(output, encrypted_pk_sesskey); 1016 1017 /* Setup the se_ip */ 1018 encrypted = calloc(1, sizeof(*encrypted)); 1019 __ops_crypt_any(encrypted, encrypted_pk_sesskey->symm_alg); 1020 iv = calloc(1, encrypted->blocksize); 1021 encrypted->set_iv(encrypted, iv); 1022 encrypted->set_crypt_key(encrypted, &encrypted_pk_sesskey->key[0]); 1023 __ops_encrypt_init(encrypted); 1024 1025 se_ip->crypt = encrypted; 1026 1027 /* And push writer on stack */ 1028 __ops_writer_push(output, encrypt_se_ip_writer, NULL, 1029 encrypt_se_ip_destroyer, se_ip); 1030 /* tidy up */ 1031 (void) free(encrypted_pk_sesskey); 1032 (void) free(iv); 1033 } 1034 1035 static unsigned 1036 encrypt_se_ip_writer(const unsigned char *src, 1037 unsigned len, 1038 __ops_error_t **errors, 1039 __ops_writer_t *writer) 1040 { 1041 const unsigned int bufsz = 128; 1042 encrypt_se_ip_t *se_ip = __ops_writer_get_arg(writer); 1043 __ops_output_t *litoutput; 1044 __ops_output_t *zoutput; 1045 __ops_output_t *output; 1046 __ops_memory_t *litmem; 1047 __ops_memory_t *zmem; 1048 __ops_memory_t *localmem; 1049 unsigned ret = 1; 1050 1051 __ops_setup_memory_write(&litoutput, &litmem, bufsz); 1052 __ops_setup_memory_write(&zoutput, &zmem, bufsz); 1053 __ops_setup_memory_write(&output, &localmem, bufsz); 1054 1055 /* create literal data packet from source data */ 1056 __ops_write_litdata(litoutput, src, (const int)len, OPS_LDT_BINARY); 1057 if (__ops_mem_len(litmem) <= len) { 1058 (void) fprintf(stderr, "encrypt_se_ip_writer: bad len\n"); 1059 return 0; 1060 } 1061 1062 /* create compressed packet from literal data packet */ 1063 __ops_writez(__ops_mem_data(litmem), __ops_mem_len(litmem), zoutput); 1064 1065 /* create SE IP packet set from this compressed literal data */ 1066 __ops_write_se_ip_pktset(__ops_mem_data(zmem), 1067 __ops_mem_len(zmem), 1068 se_ip->crypt, output); 1069 if (__ops_mem_len(localmem) <= __ops_mem_len(zmem)) { 1070 (void) fprintf(stderr, 1071 "encrypt_se_ip_writer: bad comp len\n"); 1072 return 0; 1073 } 1074 1075 /* now write memory to next writer */ 1076 ret = __ops_stacked_write(__ops_mem_data(localmem), 1077 __ops_mem_len(localmem), 1078 errors, writer); 1079 1080 __ops_memory_free(localmem); 1081 __ops_memory_free(zmem); 1082 __ops_memory_free(litmem); 1083 1084 return ret; 1085 } 1086 1087 static void 1088 encrypt_se_ip_destroyer(__ops_writer_t *writer) 1089 { 1090 encrypt_se_ip_t *se_ip; 1091 1092 se_ip = __ops_writer_get_arg(writer); 1093 (void) free(se_ip->crypt); 1094 (void) free(se_ip); 1095 } 1096 1097 unsigned 1098 __ops_write_se_ip_pktset(const unsigned char *data, 1099 const unsigned int len, 1100 __ops_crypt_t *crypted, 1101 __ops_output_t *output) 1102 { 1103 __ops_output_t *mdcoutput; 1104 __ops_memory_t *mdc; 1105 unsigned char hashed[OPS_SHA1_HASH_SIZE]; 1106 unsigned char *preamble; 1107 const size_t sz_mdc = 1 + 1 + OPS_SHA1_HASH_SIZE; 1108 size_t sz_preamble; 1109 size_t sz_buf; 1110 1111 sz_preamble = crypted->blocksize + 2; 1112 preamble = calloc(1, sz_preamble); 1113 sz_buf = sz_preamble + len + sz_mdc; 1114 1115 if (!__ops_write_ptag(output, OPS_PTAG_CT_SE_IP_DATA) || 1116 !__ops_write_length(output, 1 + sz_buf) || 1117 !__ops_write_scalar(output, SE_IP_DATA_VERSION, 1)) { 1118 free(preamble); 1119 return 0; 1120 } 1121 __ops_random(preamble, crypted->blocksize); 1122 preamble[crypted->blocksize] = preamble[crypted->blocksize - 2]; 1123 preamble[crypted->blocksize + 1] = preamble[crypted->blocksize - 1]; 1124 1125 if (__ops_get_debug_level(__FILE__)) { 1126 unsigned int i = 0; 1127 1128 fprintf(stderr, "\npreamble: "); 1129 for (i = 0; i < sz_preamble; i++) { 1130 fprintf(stderr, " 0x%02x", preamble[i]); 1131 } 1132 fprintf(stderr, "\n"); 1133 } 1134 1135 /* now construct MDC packet and add to the end of the buffer */ 1136 __ops_setup_memory_write(&mdcoutput, &mdc, sz_mdc); 1137 __ops_calc_mdc_hash(preamble, sz_preamble, data, len, &hashed[0]); 1138 __ops_write_mdc(hashed, mdcoutput); 1139 1140 if (__ops_get_debug_level(__FILE__)) { 1141 unsigned int i = 0; 1142 size_t sz_plaintext = len; 1143 size_t sz_mdc2 = 1 + 1 + OPS_SHA1_HASH_SIZE; 1144 unsigned char *digest = NULL; 1145 1146 (void) fprintf(stderr, "\nplaintext: "); 1147 for (i = 0; i < sz_plaintext; i++) { 1148 (void) fprintf(stderr, " 0x%02x", data[i]); 1149 } 1150 (void) fprintf(stderr, "\n"); 1151 1152 (void) fprintf(stderr, "\nmdc: "); 1153 digest = __ops_mem_data(mdc); 1154 for (i = 0; i < sz_mdc2; i++) { 1155 (void) fprintf(stderr, " 0x%02x", digest[i]); 1156 } 1157 (void) fprintf(stderr, "\n"); 1158 } 1159 1160 /* and write it out */ 1161 __ops_push_enc_crypt(output, crypted); 1162 if (__ops_get_debug_level(__FILE__)) { 1163 (void) fprintf(stderr, 1164 "writing %" PRIsize "u + %d + %" PRIsize "u\n", 1165 sz_preamble, len, __ops_mem_len(mdc)); 1166 } 1167 if (!__ops_write(output, preamble, sz_preamble) || 1168 !__ops_write(output, data, len) || 1169 !__ops_write(output, __ops_mem_data(mdc), __ops_mem_len(mdc))) { 1170 /* \todo fix cleanup here and in old code functions */ 1171 return 0; 1172 } 1173 1174 __ops_writer_pop(output); 1175 1176 /* cleanup */ 1177 __ops_teardown_memory_write(mdcoutput, mdc); 1178 (void) free(preamble); 1179 1180 return 1; 1181 } 1182 1183 typedef struct { 1184 int fd; 1185 } writer_fd_t; 1186 1187 static unsigned 1188 fd_writer(const unsigned char *src, unsigned len, 1189 __ops_error_t **errors, 1190 __ops_writer_t *writer) 1191 { 1192 writer_fd_t *writerfd; 1193 int n; 1194 1195 writerfd = __ops_writer_get_arg(writer); 1196 n = write(writerfd->fd, src, len); 1197 if (n == -1) { 1198 OPS_SYSTEM_ERROR_1(errors, OPS_E_W_WRITE_FAILED, "write", 1199 "file descriptor %d", writerfd->fd); 1200 return 0; 1201 } 1202 if ((unsigned) n != len) { 1203 OPS_ERROR_1(errors, OPS_E_W_WRITE_TOO_SHORT, 1204 "file descriptor %d", writerfd->fd); 1205 return 0; 1206 } 1207 return 1; 1208 } 1209 1210 static void 1211 writer_fd_destroyer(__ops_writer_t *writer) 1212 { 1213 (void) free(__ops_writer_get_arg(writer)); 1214 } 1215 1216 /** 1217 * \ingroup Core_WritersFirst 1218 * \brief Write to a File 1219 * 1220 * Set the writer in output to be a stock writer that writes to a file 1221 * descriptor. If another writer has already been set, then that is 1222 * first destroyed. 1223 * 1224 * \param output The output structure 1225 * \param fd The file descriptor 1226 * 1227 */ 1228 1229 void 1230 __ops_writer_set_fd(__ops_output_t *output, int fd) 1231 { 1232 writer_fd_t *writer; 1233 1234 writer = calloc(1, sizeof(*writer)); 1235 writer->fd = fd; 1236 __ops_writer_set(output, fd_writer, NULL, writer_fd_destroyer, writer); 1237 } 1238 1239 static unsigned 1240 memory_writer(const unsigned char *src, 1241 unsigned len, 1242 __ops_error_t **errors, 1243 __ops_writer_t *writer) 1244 { 1245 __ops_memory_t *mem; 1246 1247 __OPS_USED(errors); 1248 mem = __ops_writer_get_arg(writer); 1249 __ops_memory_add(mem, src, len); 1250 return 1; 1251 } 1252 1253 /** 1254 * \ingroup Core_WritersFirst 1255 * \brief Write to memory 1256 * 1257 * Set a memory writer. 1258 * 1259 * \param output The output structure 1260 * \param mem The memory structure 1261 * \note It is the caller's responsiblity to call __ops_memory_free(mem) 1262 * \sa __ops_memory_free() 1263 */ 1264 1265 void 1266 __ops_writer_set_memory(__ops_output_t *output, __ops_memory_t *mem) 1267 { 1268 __ops_writer_set(output, memory_writer, NULL, NULL, mem); 1269 } 1270 1271 /**************************************************************************/ 1272 1273 typedef struct { 1274 __ops_hash_alg_t hash_alg; 1275 __ops_hash_t hash; 1276 unsigned char *hashed; 1277 } skey_checksum_t; 1278 1279 static unsigned 1280 skey_checksum_writer(const unsigned char *src, 1281 const unsigned len, 1282 __ops_error_t **errors, 1283 __ops_writer_t *writer) 1284 { 1285 skey_checksum_t *sum; 1286 unsigned ret = 1; 1287 1288 sum = __ops_writer_get_arg(writer); 1289 /* add contents to hash */ 1290 sum->hash.add(&sum->hash, src, len); 1291 /* write to next stacked writer */ 1292 ret = __ops_stacked_write(src, len, errors, writer); 1293 /* tidy up and return */ 1294 return ret; 1295 } 1296 1297 static unsigned 1298 skey_checksum_finaliser(__ops_error_t **errors, __ops_writer_t *writer) 1299 { 1300 skey_checksum_t *sum; 1301 1302 sum = __ops_writer_get_arg(writer); 1303 if (errors) { 1304 printf("errors in skey_checksum_finaliser\n"); 1305 } 1306 sum->hash.finish(&sum->hash, sum->hashed); 1307 return 1; 1308 } 1309 1310 static void 1311 skey_checksum_destroyer(__ops_writer_t *writer) 1312 { 1313 skey_checksum_t *sum; 1314 1315 sum = __ops_writer_get_arg(writer); 1316 (void) free(sum); 1317 } 1318 1319 /** 1320 \ingroup Core_WritersNext 1321 \param output 1322 \param seckey 1323 */ 1324 void 1325 __ops_push_checksum_writer(__ops_output_t *output, __ops_seckey_t *seckey) 1326 { 1327 /* XXX: push a SHA-1 checksum writer (and change s2k to 254). */ 1328 skey_checksum_t *sum; 1329 1330 sum = calloc(1, sizeof(*sum)); 1331 /* configure the arg */ 1332 sum->hash_alg = seckey->hash_alg; 1333 sum->hashed = seckey->checkhash; 1334 /* init the hash */ 1335 __ops_hash_any(&sum->hash, sum->hash_alg); 1336 sum->hash.init(&sum->hash); 1337 __ops_writer_push(output, skey_checksum_writer, 1338 skey_checksum_finaliser, skey_checksum_destroyer, sum); 1339 } 1340 1341 /**************************************************************************/ 1342 1343 #define MAX_PARTIAL_DATA_LENGTH 1073741824 1344 1345 typedef struct { 1346 __ops_crypt_t *crypt; 1347 __ops_memory_t *mem_data; 1348 __ops_memory_t *litmem; 1349 __ops_output_t *litoutput; 1350 __ops_memory_t *se_ip_mem; 1351 __ops_output_t *se_ip_out; 1352 __ops_hash_t hash; 1353 } str_enc_se_ip_t; 1354 1355 1356 static unsigned 1357 str_enc_se_ip_writer(const unsigned char *src, 1358 unsigned len, 1359 __ops_error_t **errors, 1360 __ops_writer_t *writer); 1361 1362 static unsigned 1363 str_enc_se_ip_finaliser(__ops_error_t **errors, 1364 __ops_writer_t * writer); 1365 1366 static void str_enc_se_ip_destroyer(__ops_writer_t *writer); 1367 1368 /* */ 1369 1370 /** 1371 \ingroup Core_WritersNext 1372 \param output 1373 \param pubkey 1374 */ 1375 void 1376 __ops_push_stream_enc_se_ip(__ops_output_t *output, const __ops_key_t *pubkey) 1377 { 1378 __ops_pk_sesskey_t *encrypted_pk_sesskey; 1379 const unsigned int bufsz = 1024; 1380 str_enc_se_ip_t *se_ip = calloc(1, sizeof(*se_ip)); 1381 __ops_crypt_t *encrypted; 1382 unsigned char *iv = NULL; 1383 1384 encrypted_pk_sesskey = __ops_create_pk_sesskey(pubkey); 1385 __ops_write_pk_sesskey(output, encrypted_pk_sesskey); 1386 1387 /* Setup the se_ip */ 1388 encrypted = calloc(1, sizeof(*encrypted)); 1389 __ops_crypt_any(encrypted, encrypted_pk_sesskey->symm_alg); 1390 iv = calloc(1, encrypted->blocksize); 1391 encrypted->set_iv(encrypted, iv); 1392 encrypted->set_crypt_key(encrypted, &encrypted_pk_sesskey->key[0]); 1393 __ops_encrypt_init(encrypted); 1394 1395 se_ip->crypt = encrypted; 1396 1397 se_ip->mem_data = __ops_memory_new(); 1398 __ops_memory_init(se_ip->mem_data, bufsz); 1399 1400 se_ip->litmem = NULL; 1401 se_ip->litoutput = NULL; 1402 1403 __ops_setup_memory_write(&se_ip->se_ip_out, &se_ip->se_ip_mem, bufsz); 1404 1405 /* And push writer on stack */ 1406 __ops_writer_push(output, 1407 str_enc_se_ip_writer, 1408 str_enc_se_ip_finaliser, 1409 str_enc_se_ip_destroyer, se_ip); 1410 /* tidy up */ 1411 (void) free(encrypted_pk_sesskey); 1412 (void) free(iv); 1413 } 1414 1415 1416 /* calculate the partial data length */ 1417 static unsigned int 1418 __ops_partial_data_len(unsigned int len) 1419 { 1420 unsigned int mask = MAX_PARTIAL_DATA_LENGTH; 1421 int i; 1422 1423 if (len == 0) { 1424 (void) fprintf(stderr, "__ops_partial_data_len: 0 len\n"); 1425 return 0; 1426 } 1427 if (len > MAX_PARTIAL_DATA_LENGTH) { 1428 return MAX_PARTIAL_DATA_LENGTH; 1429 } 1430 for (i = 0; i <= 30; i++) { 1431 if (mask & len) { 1432 break; 1433 } 1434 mask >>= 1; 1435 } 1436 return mask; 1437 } 1438 1439 static unsigned 1440 __ops_write_partial_len(unsigned int len, __ops_output_t *output) 1441 { 1442 /* len must be a power of 2 from 0 to 30 */ 1443 unsigned char c; 1444 int i; 1445 1446 for (i = 0; i <= 30; i++) { 1447 if ((len >> i) & 1) { 1448 break; 1449 } 1450 } 1451 c = 224 + i; 1452 return __ops_write(output, &c, 1); 1453 } 1454 1455 static unsigned 1456 stream_write_litdata(__ops_output_t *output, 1457 const unsigned char *data, 1458 unsigned len) 1459 { 1460 while (len > 0) { 1461 size_t pdlen = __ops_partial_data_len(len); 1462 1463 __ops_write_partial_len(pdlen, output); 1464 __ops_write(output, data, pdlen); 1465 data += pdlen; 1466 len -= pdlen; 1467 } 1468 return 1; 1469 } 1470 1471 static unsigned 1472 stream_write_litdata_first(__ops_output_t *output, 1473 const unsigned char *data, 1474 unsigned int len, 1475 const __ops_litdata_type_t type) 1476 { 1477 /* \todo add filename */ 1478 /* \todo add date */ 1479 /* \todo do we need to check text data for <cr><lf> line endings ? */ 1480 1481 size_t sz_towrite; 1482 size_t sz_pd; 1483 1484 sz_towrite = 1 + 1 + 4 + len; 1485 sz_pd = __ops_partial_data_len(sz_towrite); 1486 if (sz_pd < 512) { 1487 (void) fprintf(stderr, 1488 "stream_write_litdata_first: bad sz_pd\n"); 1489 return 0; 1490 } 1491 __ops_write_ptag(output, OPS_PTAG_CT_LITDATA); 1492 __ops_write_partial_len(sz_pd, output); 1493 __ops_write_scalar(output, (unsigned)type, 1); 1494 __ops_write_scalar(output, 0, 1); 1495 __ops_write_scalar(output, 0, 4); 1496 __ops_write(output, data, sz_pd - 6); 1497 1498 data += (sz_pd - 6); 1499 sz_towrite -= sz_pd; 1500 1501 return stream_write_litdata(output, data, sz_towrite); 1502 } 1503 1504 static unsigned 1505 stream_write_litdata_last(__ops_output_t *output, 1506 const unsigned char *data, 1507 unsigned int len) 1508 { 1509 __ops_write_length(output, len); 1510 return __ops_write(output, data, len); 1511 } 1512 1513 static unsigned 1514 stream_write_se_ip(__ops_output_t *output, 1515 const unsigned char *data, 1516 unsigned int len, 1517 str_enc_se_ip_t *se_ip) 1518 { 1519 size_t pdlen; 1520 1521 while (len > 0) { 1522 pdlen = __ops_partial_data_len(len); 1523 __ops_write_partial_len(pdlen, output); 1524 1525 __ops_push_enc_crypt(output, se_ip->crypt); 1526 __ops_write(output, data, pdlen); 1527 __ops_writer_pop(output); 1528 1529 se_ip->hash.add(&se_ip->hash, data, pdlen); 1530 1531 data += pdlen; 1532 len -= pdlen; 1533 } 1534 return 1; 1535 } 1536 1537 static unsigned 1538 stream_write_se_ip_first(__ops_output_t *output, 1539 const unsigned char *data, 1540 unsigned int len, 1541 str_enc_se_ip_t *se_ip) 1542 { 1543 unsigned char *preamble; 1544 size_t blocksize; 1545 size_t sz_preamble; 1546 size_t sz_towrite; 1547 size_t sz_pd; 1548 1549 blocksize = se_ip->crypt->blocksize; 1550 sz_preamble = blocksize + 2; 1551 sz_towrite = sz_preamble + 1 + len; 1552 preamble = calloc(1, sz_preamble); 1553 sz_pd = __ops_partial_data_len(sz_towrite); 1554 if (sz_pd < 512) { 1555 (void) fprintf(stderr, 1556 "stream_write_se_ip_first: bad sz_pd\n"); 1557 return 0; 1558 } 1559 __ops_write_ptag(output, OPS_PTAG_CT_SE_IP_DATA); 1560 __ops_write_partial_len(sz_pd, output); 1561 __ops_write_scalar(output, SE_IP_DATA_VERSION, 1); 1562 __ops_push_enc_crypt(output, se_ip->crypt); 1563 1564 __ops_random(preamble, blocksize); 1565 preamble[blocksize] = preamble[blocksize - 2]; 1566 preamble[blocksize + 1] = preamble[blocksize - 1]; 1567 __ops_hash_any(&se_ip->hash, OPS_HASH_SHA1); 1568 se_ip->hash.init(&se_ip->hash); 1569 __ops_write(output, preamble, sz_preamble); 1570 se_ip->hash.add(&se_ip->hash, preamble, sz_preamble); 1571 __ops_write(output, data, sz_pd - sz_preamble - 1); 1572 se_ip->hash.add(&se_ip->hash, data, sz_pd - sz_preamble - 1); 1573 data += (sz_pd - sz_preamble - 1); 1574 sz_towrite -= sz_pd; 1575 __ops_writer_pop(output); 1576 stream_write_se_ip(output, data, sz_towrite, se_ip); 1577 (void) free(preamble); 1578 return 1; 1579 } 1580 1581 static unsigned 1582 stream_write_se_ip_last(__ops_output_t *output, 1583 const unsigned char *data, 1584 unsigned int len, 1585 str_enc_se_ip_t *se_ip) 1586 { 1587 __ops_output_t *mdcoutput; 1588 __ops_memory_t *mdcmem; 1589 unsigned char c; 1590 unsigned char hashed[OPS_SHA1_HASH_SIZE]; 1591 const size_t sz_mdc = 1 + 1 + OPS_SHA1_HASH_SIZE; 1592 size_t sz_buf = len + sz_mdc; 1593 1594 se_ip->hash.add(&se_ip->hash, data, len); 1595 1596 /* MDC packet tag */ 1597 c = MDC_PKT_TAG; 1598 se_ip->hash.add(&se_ip->hash, &c, 1); 1599 1600 /* MDC packet len */ 1601 c = OPS_SHA1_HASH_SIZE; 1602 se_ip->hash.add(&se_ip->hash, &c, 1); 1603 1604 /* finish */ 1605 se_ip->hash.finish(&se_ip->hash, hashed); 1606 1607 __ops_setup_memory_write(&mdcoutput, &mdcmem, sz_mdc); 1608 __ops_write_mdc(hashed, mdcoutput); 1609 1610 /* write length of last se_ip chunk */ 1611 __ops_write_length(output, sz_buf); 1612 1613 /* encode everting */ 1614 __ops_push_enc_crypt(output, se_ip->crypt); 1615 1616 __ops_write(output, data, len); 1617 __ops_write(output, __ops_mem_data(mdcmem), __ops_mem_len(mdcmem)); 1618 1619 __ops_writer_pop(output); 1620 1621 __ops_teardown_memory_write(mdcoutput, mdcmem); 1622 1623 return 1; 1624 } 1625 1626 static unsigned 1627 str_enc_se_ip_writer(const unsigned char *src, 1628 unsigned len, 1629 __ops_error_t **errors, 1630 __ops_writer_t *writer) 1631 { 1632 str_enc_se_ip_t *se_ip = __ops_writer_get_arg(writer); 1633 unsigned ret = 1; 1634 1635 if (se_ip->litoutput == NULL) { /* first literal data chunk 1636 * is not yet written */ 1637 size_t datalength; 1638 1639 __ops_memory_add(se_ip->mem_data, src, len); 1640 datalength = __ops_mem_len(se_ip->mem_data); 1641 1642 /* 4.2.2.4. Partial Body Lengths */ 1643 /* The first partial length MUST be at least 512 octets long. */ 1644 if (datalength < 512) { 1645 return 1; /* will wait for more data or 1646 * end of stream */ 1647 } 1648 __ops_setup_memory_write(&se_ip->litoutput, 1649 &se_ip->litmem, datalength + 32); 1650 stream_write_litdata_first(se_ip->litoutput, 1651 __ops_mem_data(se_ip->mem_data), 1652 datalength, 1653 OPS_LDT_BINARY); 1654 1655 stream_write_se_ip_first(se_ip->se_ip_out, 1656 __ops_mem_data(se_ip->litmem), 1657 __ops_mem_len(se_ip->litmem), se_ip); 1658 } else { 1659 stream_write_litdata(se_ip->litoutput, src, len); 1660 stream_write_se_ip(se_ip->se_ip_out, 1661 __ops_mem_data(se_ip->litmem), 1662 __ops_mem_len(se_ip->litmem), se_ip); 1663 } 1664 1665 /* now write memory to next writer */ 1666 ret = __ops_stacked_write(__ops_mem_data(se_ip->se_ip_mem), 1667 __ops_mem_len(se_ip->se_ip_mem), 1668 errors, writer); 1669 1670 __ops_memory_clear(se_ip->litmem); 1671 __ops_memory_clear(se_ip->se_ip_mem); 1672 1673 return ret; 1674 } 1675 1676 static unsigned 1677 str_enc_se_ip_finaliser(__ops_error_t **errors, __ops_writer_t *writer) 1678 { 1679 str_enc_se_ip_t *se_ip = __ops_writer_get_arg(writer); 1680 /* write last chunk of data */ 1681 1682 if (se_ip->litoutput == NULL) { 1683 /* first literal data chunk was not written */ 1684 /* so we know the total length of data, write a simple packet */ 1685 1686 /* create literal data packet from buffered data */ 1687 __ops_setup_memory_write(&se_ip->litoutput, &se_ip->litmem, 1688 __ops_mem_len(se_ip->mem_data) + 32); 1689 1690 __ops_write_litdata(se_ip->litoutput, 1691 __ops_mem_data(se_ip->mem_data), 1692 (const int)__ops_mem_len(se_ip->mem_data), 1693 OPS_LDT_BINARY); 1694 1695 /* create SE IP packet set from this literal data */ 1696 __ops_write_se_ip_pktset( 1697 __ops_mem_data(se_ip->litmem), 1698 __ops_mem_len(se_ip->litmem), 1699 se_ip->crypt, se_ip->se_ip_out); 1700 1701 } else { 1702 /* finish writing */ 1703 stream_write_litdata_last(se_ip->litoutput, NULL, 0); 1704 stream_write_se_ip_last(se_ip->se_ip_out, 1705 __ops_mem_data(se_ip->litmem), 1706 __ops_mem_len(se_ip->litmem), se_ip); 1707 } 1708 1709 /* now write memory to next writer */ 1710 return __ops_stacked_write(__ops_mem_data(se_ip->se_ip_mem), 1711 __ops_mem_len(se_ip->se_ip_mem), 1712 errors, writer); 1713 } 1714 1715 static void 1716 str_enc_se_ip_destroyer(__ops_writer_t *writer) 1717 { 1718 str_enc_se_ip_t *se_ip = __ops_writer_get_arg(writer); 1719 1720 __ops_memory_free(se_ip->mem_data); 1721 __ops_teardown_memory_write(se_ip->litoutput, se_ip->litmem); 1722 __ops_teardown_memory_write(se_ip->se_ip_out, se_ip->se_ip_mem); 1723 1724 se_ip->crypt->decrypt_finish(se_ip->crypt); 1725 1726 (void) free(se_ip->crypt); 1727 (void) free(se_ip); 1728 } 1729