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