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.15 2009/10/07 16:19:51 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 658 if (linebreak->pos == BREAKPOS) { 659 if (!__ops_stacked_write("\r\n", 2, errors, writer)) { 660 return 0; 661 } 662 linebreak->pos = 0; 663 } 664 if (!__ops_stacked_write(&src[n], 1, errors, writer)) { 665 return 0; 666 } 667 } 668 669 return 1; 670 } 671 672 /** 673 * \ingroup Core_WritersNext 674 * \brief Push armoured signature on stack 675 * \param output 676 */ 677 unsigned 678 __ops_writer_use_armored_sig(__ops_output_t *output) 679 { 680 static const char header[] = 681 "\r\n-----BEGIN PGP SIGNATURE-----\r\nVersion: " 682 NETPGP_VERSION_STRING 683 "\r\n\r\n"; 684 linebreak_t *linebreak; 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 if ((linebreak = calloc(1, sizeof(*linebreak))) == NULL) { 694 OPS_ERROR(&output->errors, OPS_E_W, 695 "__ops_writer_use_armored_sig: Bad alloc"); 696 return 0; 697 } 698 __ops_writer_push(output, linebreak_writer, NULL, 699 generic_destroyer, 700 linebreak); 701 base64 = calloc(1, sizeof(*base64)); 702 if (!base64) { 703 OPS_MEMORY_ERROR(&output->errors); 704 return 0; 705 } 706 base64->checksum = CRC24_INIT; 707 __ops_writer_push(output, base64_writer, sig_finaliser, 708 generic_destroyer, base64); 709 return 1; 710 } 711 712 static unsigned 713 armoured_message_finaliser(__ops_error_t **errors, __ops_writer_t *writer) 714 { 715 /* TODO: This is same as sig_finaliser apart from trailer. */ 716 static const char *trailer = "\r\n-----END PGP MESSAGE-----\r\n"; 717 unsigned char c[3]; 718 base64_t *base64; 719 720 base64 = __ops_writer_get_arg(writer); 721 if (base64->pos) { 722 if (!__ops_stacked_write(&b64map[base64->t], 1, errors, 723 writer)) { 724 return 0; 725 } 726 if (base64->pos == 1 && 727 !__ops_stacked_write("==", 2, errors, writer)) { 728 return 0; 729 } 730 if (base64->pos == 2 && 731 !__ops_stacked_write("=", 1, errors, writer)) { 732 return 0; 733 } 734 } 735 /* Ready for the checksum */ 736 if (!__ops_stacked_write("\r\n=", 3, errors, writer)) { 737 return 0; 738 } 739 740 base64->pos = 0; /* get ready to write the checksum */ 741 742 c[0] = base64->checksum >> 16; 743 c[1] = base64->checksum >> 8; 744 c[2] = base64->checksum; 745 /* push the checksum through our own writer */ 746 if (!base64_writer(c, 3, errors, writer)) { 747 return 0; 748 } 749 750 return __ops_stacked_write(trailer, sizeof(trailer)-1, errors, writer); 751 } 752 753 /** 754 \ingroup Core_WritersNext 755 \brief Write a PGP MESSAGE 756 \todo replace with generic function 757 */ 758 void 759 __ops_writer_push_armor_msg(__ops_output_t *output) 760 { 761 static const char header[] = "-----BEGIN PGP MESSAGE-----\r\n"; 762 base64_t *base64; 763 764 __ops_write(output, header, sizeof(header) - 1); 765 __ops_write(output, "\r\n", 2); 766 if ((base64 = calloc(1, sizeof(*base64))) == NULL) { 767 (void) fprintf(stderr, "__ops_writer_push_armor_msg: bad alloc\n"); 768 } else { 769 base64->checksum = CRC24_INIT; 770 __ops_writer_push(output, base64_writer, 771 armoured_message_finaliser, generic_destroyer, 772 base64); 773 } 774 } 775 776 static unsigned 777 armoured_finaliser(__ops_armor_type_t type, 778 __ops_error_t **errors, 779 __ops_writer_t *writer) 780 { 781 static const char tail_pubkey[] = 782 "\r\n-----END PGP PUBLIC KEY BLOCK-----\r\n"; 783 static const char tail_private_key[] = 784 "\r\n-----END PGP PRIVATE KEY BLOCK-----\r\n"; 785 unsigned char c[3]; 786 unsigned int sz_tail = 0; 787 const char *tail = NULL; 788 base64_t *base64; 789 790 switch (type) { 791 case OPS_PGP_PUBLIC_KEY_BLOCK: 792 tail = tail_pubkey; 793 sz_tail = sizeof(tail_pubkey) - 1; 794 break; 795 796 case OPS_PGP_PRIVATE_KEY_BLOCK: 797 tail = tail_private_key; 798 sz_tail = sizeof(tail_private_key) - 1; 799 break; 800 801 default: 802 (void) fprintf(stderr, "armoured_finaliser: unusual type\n"); 803 return 0; 804 } 805 base64 = __ops_writer_get_arg(writer); 806 if (base64->pos) { 807 if (!__ops_stacked_write(&b64map[base64->t], 1, errors, 808 writer)) { 809 return 0; 810 } 811 if (base64->pos == 1 && !__ops_stacked_write("==", 2, errors, 812 writer)) { 813 return 0; 814 } 815 if (base64->pos == 2 && !__ops_stacked_write("=", 1, errors, 816 writer)) { 817 return 0; 818 } 819 } 820 /* Ready for the checksum */ 821 if (!__ops_stacked_write("\r\n=", 3, errors, writer)) { 822 return 0; 823 } 824 base64->pos = 0; /* get ready to write the checksum */ 825 c[0] = base64->checksum >> 16; 826 c[1] = base64->checksum >> 8; 827 c[2] = base64->checksum; 828 /* push the checksum through our own writer */ 829 if (!base64_writer(c, 3, errors, writer)) { 830 return 0; 831 } 832 return __ops_stacked_write(tail, sz_tail, errors, writer); 833 } 834 835 static unsigned 836 armored_pubkey_fini(__ops_error_t **errors, __ops_writer_t *writer) 837 { 838 return armoured_finaliser(OPS_PGP_PUBLIC_KEY_BLOCK, errors, writer); 839 } 840 841 static unsigned 842 armored_privkey_fini(__ops_error_t **errors, __ops_writer_t *writer) 843 { 844 return armoured_finaliser(OPS_PGP_PRIVATE_KEY_BLOCK, errors, writer); 845 } 846 847 /* \todo use this for other armoured types */ 848 /** 849 \ingroup Core_WritersNext 850 \brief Push Armoured Writer on stack (generic) 851 */ 852 void 853 __ops_writer_push_armoured(__ops_output_t *output, __ops_armor_type_t type) 854 { 855 static char hdr_pubkey[] = 856 "-----BEGIN PGP PUBLIC KEY BLOCK-----\r\nVersion: " 857 NETPGP_VERSION_STRING 858 "\r\n\r\n"; 859 static char hdr_private_key[] = 860 "-----BEGIN PGP PRIVATE KEY BLOCK-----\r\nVersion: " 861 NETPGP_VERSION_STRING 862 "\r\n\r\n"; 863 unsigned int sz_hdr = 0; 864 unsigned (*finaliser) (__ops_error_t **, __ops_writer_t *); 865 base64_t *base64; 866 linebreak_t *linebreak; 867 char *header = NULL; 868 869 finaliser = NULL; 870 switch (type) { 871 case OPS_PGP_PUBLIC_KEY_BLOCK: 872 header = hdr_pubkey; 873 sz_hdr = sizeof(hdr_pubkey) - 1; 874 finaliser = armored_pubkey_fini; 875 break; 876 877 case OPS_PGP_PRIVATE_KEY_BLOCK: 878 header = hdr_private_key; 879 sz_hdr = sizeof(hdr_private_key) - 1; 880 finaliser = armored_privkey_fini; 881 break; 882 883 default: 884 (void) fprintf(stderr, 885 "__ops_writer_push_armoured: unusual type\n"); 886 return; 887 } 888 if ((linebreak = calloc(1, sizeof(*linebreak))) == NULL) { 889 (void) fprintf(stderr, 890 "__ops_writer_push_armoured: bad alloc\n"); 891 return; 892 } 893 __ops_write(output, header, sz_hdr); 894 __ops_writer_push(output, linebreak_writer, NULL, 895 generic_destroyer, 896 linebreak); 897 if ((base64 = calloc(1, sizeof(*base64))) == NULL) { 898 (void) fprintf(stderr, 899 "__ops_writer_push_armoured: bad alloc\n"); 900 return; 901 } 902 base64->checksum = CRC24_INIT; 903 __ops_writer_push(output, base64_writer, finaliser, 904 generic_destroyer, base64); 905 } 906 907 /**************************************************************************/ 908 909 typedef struct { 910 __ops_crypt_t *crypt; 911 int free_crypt; 912 } crypt_t; 913 914 /* 915 * This writer simply takes plaintext as input, 916 * encrypts it with the given key 917 * and outputs the resulting encrypted text 918 */ 919 static unsigned 920 encrypt_writer(const unsigned char *src, 921 unsigned len, 922 __ops_error_t **errors, 923 __ops_writer_t *writer) 924 { 925 #define BUFSZ 1024 /* arbitrary number */ 926 unsigned char encbuf[BUFSZ]; 927 unsigned remaining; 928 unsigned done = 0; 929 crypt_t *pgp_encrypt; 930 931 remaining = len; 932 pgp_encrypt = (crypt_t *) __ops_writer_get_arg(writer); 933 if (!__ops_is_sa_supported(pgp_encrypt->crypt->alg)) { 934 (void) fprintf(stderr, "encrypt_writer: not supported\n"); 935 return 0; 936 } 937 while (remaining > 0) { 938 unsigned size = (remaining < BUFSZ) ? remaining : BUFSZ; 939 940 /* memcpy(buf,src,size); // \todo copy needed here? */ 941 pgp_encrypt->crypt->cfb_encrypt(pgp_encrypt->crypt, encbuf, 942 src + done, size); 943 944 if (__ops_get_debug_level(__FILE__)) { 945 int i = 0; 946 947 (void) fprintf(stderr, "WRITING:\nunencrypted: "); 948 for (i = 0; i < 16; i++) { 949 (void) fprintf(stderr, "%2x ", src[done + i]); 950 } 951 (void) fprintf(stderr, "\nencrypted: "); 952 for (i = 0; i < 16; i++) { 953 (void) fprintf(stderr, "%2x ", encbuf[i]); 954 } 955 (void) fprintf(stderr, "\n"); 956 } 957 if (!__ops_stacked_write(encbuf, size, errors, writer)) { 958 if (__ops_get_debug_level(__FILE__)) { 959 fprintf(stderr, 960 "encrypted_writer: stacked write\n"); 961 } 962 return 0; 963 } 964 remaining -= size; 965 done += size; 966 } 967 968 return 1; 969 } 970 971 static void 972 encrypt_destroyer(__ops_writer_t *writer) 973 { 974 crypt_t *pgp_encrypt = (crypt_t *) __ops_writer_get_arg(writer); 975 976 if (pgp_encrypt->free_crypt) { 977 free(pgp_encrypt->crypt); 978 } 979 free(pgp_encrypt); 980 } 981 982 /** 983 \ingroup Core_WritersNext 984 \brief Push Encrypted Writer onto stack (create SE packets) 985 */ 986 void 987 __ops_push_enc_crypt(__ops_output_t *output, __ops_crypt_t *pgp_crypt) 988 { 989 /* Create encrypt to be used with this writer */ 990 /* Remember to free this in the destroyer */ 991 crypt_t *pgp_encrypt; 992 993 if ((pgp_encrypt = calloc(1, sizeof(*pgp_encrypt))) == NULL) { 994 (void) fprintf(stderr, "__ops_push_enc_crypt: bad alloc\n"); 995 } else { 996 /* Setup the encrypt */ 997 pgp_encrypt->crypt = pgp_crypt; 998 pgp_encrypt->free_crypt = 0; 999 /* And push writer on stack */ 1000 __ops_writer_push(output, encrypt_writer, NULL, 1001 encrypt_destroyer, pgp_encrypt); 1002 } 1003 } 1004 1005 /**************************************************************************/ 1006 1007 typedef struct { 1008 __ops_crypt_t *crypt; 1009 } encrypt_se_ip_t; 1010 1011 static unsigned encrypt_se_ip_writer(const unsigned char *, 1012 unsigned, 1013 __ops_error_t **, 1014 __ops_writer_t *); 1015 static void encrypt_se_ip_destroyer(__ops_writer_t *); 1016 1017 /* */ 1018 1019 /** 1020 \ingroup Core_WritersNext 1021 \brief Push Encrypted SE IP Writer onto stack 1022 */ 1023 void 1024 __ops_push_enc_se_ip(__ops_output_t *output, const __ops_key_t *pubkey) 1025 { 1026 unsigned char *iv; 1027 __ops_crypt_t *encrypted; 1028 /* Create se_ip to be used with this writer */ 1029 /* Remember to free this in the destroyer */ 1030 encrypt_se_ip_t *se_ip; 1031 __ops_pk_sesskey_t *encrypted_pk_sesskey; 1032 1033 if ((se_ip = calloc(1, sizeof(*se_ip))) == NULL) { 1034 (void) fprintf(stderr, "__ops_push_enc_se_ip: bad alloc\n"); 1035 return; 1036 } 1037 1038 /* Create and write encrypted PK session key */ 1039 encrypted_pk_sesskey = __ops_create_pk_sesskey(pubkey); 1040 __ops_write_pk_sesskey(output, encrypted_pk_sesskey); 1041 1042 /* Setup the se_ip */ 1043 if ((encrypted = calloc(1, sizeof(*encrypted))) == NULL) { 1044 free(se_ip); 1045 (void) fprintf(stderr, "__ops_push_enc_se_ip: bad alloc\n"); 1046 return; 1047 } 1048 __ops_crypt_any(encrypted, encrypted_pk_sesskey->symm_alg); 1049 if ((iv = calloc(1, encrypted->blocksize)) == NULL) { 1050 free(se_ip); 1051 free(encrypted); 1052 (void) fprintf(stderr, "__ops_push_enc_se_ip: bad alloc\n"); 1053 return; 1054 } 1055 encrypted->set_iv(encrypted, iv); 1056 encrypted->set_crypt_key(encrypted, &encrypted_pk_sesskey->key[0]); 1057 __ops_encrypt_init(encrypted); 1058 1059 se_ip->crypt = encrypted; 1060 1061 /* And push writer on stack */ 1062 __ops_writer_push(output, encrypt_se_ip_writer, NULL, 1063 encrypt_se_ip_destroyer, se_ip); 1064 /* tidy up */ 1065 free(encrypted_pk_sesskey); 1066 free(iv); 1067 } 1068 1069 static unsigned 1070 encrypt_se_ip_writer(const unsigned char *src, 1071 unsigned len, 1072 __ops_error_t **errors, 1073 __ops_writer_t *writer) 1074 { 1075 const unsigned int bufsz = 128; 1076 encrypt_se_ip_t *se_ip = __ops_writer_get_arg(writer); 1077 __ops_output_t *litoutput; 1078 __ops_output_t *zoutput; 1079 __ops_output_t *output; 1080 __ops_memory_t *litmem; 1081 __ops_memory_t *zmem; 1082 __ops_memory_t *localmem; 1083 unsigned ret = 1; 1084 1085 __ops_setup_memory_write(&litoutput, &litmem, bufsz); 1086 __ops_setup_memory_write(&zoutput, &zmem, bufsz); 1087 __ops_setup_memory_write(&output, &localmem, bufsz); 1088 1089 /* create literal data packet from source data */ 1090 __ops_write_litdata(litoutput, src, (const int)len, OPS_LDT_BINARY); 1091 if (__ops_mem_len(litmem) <= len) { 1092 (void) fprintf(stderr, "encrypt_se_ip_writer: bad len\n"); 1093 return 0; 1094 } 1095 1096 /* create compressed packet from literal data packet */ 1097 __ops_writez(__ops_mem_data(litmem), __ops_mem_len(litmem), zoutput); 1098 1099 /* create SE IP packet set from this compressed literal data */ 1100 __ops_write_se_ip_pktset(__ops_mem_data(zmem), 1101 __ops_mem_len(zmem), 1102 se_ip->crypt, output); 1103 if (__ops_mem_len(localmem) <= __ops_mem_len(zmem)) { 1104 (void) fprintf(stderr, 1105 "encrypt_se_ip_writer: bad comp len\n"); 1106 return 0; 1107 } 1108 1109 /* now write memory to next writer */ 1110 ret = __ops_stacked_write(__ops_mem_data(localmem), 1111 __ops_mem_len(localmem), 1112 errors, writer); 1113 1114 __ops_memory_free(localmem); 1115 __ops_memory_free(zmem); 1116 __ops_memory_free(litmem); 1117 1118 return ret; 1119 } 1120 1121 static void 1122 encrypt_se_ip_destroyer(__ops_writer_t *writer) 1123 { 1124 encrypt_se_ip_t *se_ip; 1125 1126 se_ip = __ops_writer_get_arg(writer); 1127 free(se_ip->crypt); 1128 free(se_ip); 1129 } 1130 1131 unsigned 1132 __ops_write_se_ip_pktset(const unsigned char *data, 1133 const unsigned int len, 1134 __ops_crypt_t *crypted, 1135 __ops_output_t *output) 1136 { 1137 __ops_output_t *mdcoutput; 1138 __ops_memory_t *mdc; 1139 unsigned char hashed[OPS_SHA1_HASH_SIZE]; 1140 unsigned char *preamble; 1141 const size_t sz_mdc = 1 + 1 + OPS_SHA1_HASH_SIZE; 1142 size_t sz_preamble; 1143 size_t sz_buf; 1144 1145 sz_preamble = crypted->blocksize + 2; 1146 if ((preamble = calloc(1, sz_preamble)) == NULL) { 1147 (void) fprintf(stderr, "__ops_write_se_ip_pktset: bad alloc\n"); 1148 return 0; 1149 } 1150 sz_buf = sz_preamble + len + sz_mdc; 1151 1152 if (!__ops_write_ptag(output, OPS_PTAG_CT_SE_IP_DATA) || 1153 !__ops_write_length(output, 1 + sz_buf) || 1154 !__ops_write_scalar(output, SE_IP_DATA_VERSION, 1)) { 1155 free(preamble); 1156 return 0; 1157 } 1158 __ops_random(preamble, crypted->blocksize); 1159 preamble[crypted->blocksize] = preamble[crypted->blocksize - 2]; 1160 preamble[crypted->blocksize + 1] = preamble[crypted->blocksize - 1]; 1161 1162 if (__ops_get_debug_level(__FILE__)) { 1163 unsigned int i; 1164 1165 fprintf(stderr, "\npreamble: "); 1166 for (i = 0; i < sz_preamble; i++) { 1167 fprintf(stderr, " 0x%02x", preamble[i]); 1168 } 1169 fprintf(stderr, "\n"); 1170 } 1171 1172 /* now construct MDC packet and add to the end of the buffer */ 1173 __ops_setup_memory_write(&mdcoutput, &mdc, sz_mdc); 1174 __ops_calc_mdc_hash(preamble, sz_preamble, data, len, &hashed[0]); 1175 __ops_write_mdc(hashed, mdcoutput); 1176 1177 if (__ops_get_debug_level(__FILE__)) { 1178 unsigned int i; 1179 size_t sz_plaintext = len; 1180 size_t sz_mdc2 = 1 + 1 + OPS_SHA1_HASH_SIZE; 1181 unsigned char *digest; 1182 1183 (void) fprintf(stderr, "\nplaintext: "); 1184 for (i = 0; i < sz_plaintext; i++) { 1185 (void) fprintf(stderr, " 0x%02x", data[i]); 1186 } 1187 (void) fprintf(stderr, "\n"); 1188 1189 (void) fprintf(stderr, "\nmdc: "); 1190 digest = __ops_mem_data(mdc); 1191 for (i = 0; i < sz_mdc2; i++) { 1192 (void) fprintf(stderr, " 0x%02x", digest[i]); 1193 } 1194 (void) fprintf(stderr, "\n"); 1195 } 1196 1197 /* and write it out */ 1198 __ops_push_enc_crypt(output, crypted); 1199 if (__ops_get_debug_level(__FILE__)) { 1200 (void) fprintf(stderr, 1201 "writing %" PRIsize "u + %u + %" PRIsize "u\n", 1202 sz_preamble, len, __ops_mem_len(mdc)); 1203 } 1204 if (!__ops_write(output, preamble, sz_preamble) || 1205 !__ops_write(output, data, len) || 1206 !__ops_write(output, __ops_mem_data(mdc), __ops_mem_len(mdc))) { 1207 /* \todo fix cleanup here and in old code functions */ 1208 return 0; 1209 } 1210 1211 __ops_writer_pop(output); 1212 1213 /* cleanup */ 1214 __ops_teardown_memory_write(mdcoutput, mdc); 1215 free(preamble); 1216 1217 return 1; 1218 } 1219 1220 typedef struct { 1221 int fd; 1222 } writer_fd_t; 1223 1224 static unsigned 1225 fd_writer(const unsigned char *src, unsigned len, 1226 __ops_error_t **errors, 1227 __ops_writer_t *writer) 1228 { 1229 writer_fd_t *writerfd; 1230 int n; 1231 1232 writerfd = __ops_writer_get_arg(writer); 1233 n = write(writerfd->fd, src, len); 1234 if (n == -1) { 1235 OPS_SYSTEM_ERROR_1(errors, OPS_E_W_WRITE_FAILED, "write", 1236 "file descriptor %d", writerfd->fd); 1237 return 0; 1238 } 1239 if ((unsigned) n != len) { 1240 OPS_ERROR_1(errors, OPS_E_W_WRITE_TOO_SHORT, 1241 "file descriptor %d", writerfd->fd); 1242 return 0; 1243 } 1244 return 1; 1245 } 1246 1247 static void 1248 writer_fd_destroyer(__ops_writer_t *writer) 1249 { 1250 free(__ops_writer_get_arg(writer)); 1251 } 1252 1253 /** 1254 * \ingroup Core_WritersFirst 1255 * \brief Write to a File 1256 * 1257 * Set the writer in output to be a stock writer that writes to a file 1258 * descriptor. If another writer has already been set, then that is 1259 * first destroyed. 1260 * 1261 * \param output The output structure 1262 * \param fd The file descriptor 1263 * 1264 */ 1265 1266 void 1267 __ops_writer_set_fd(__ops_output_t *output, int fd) 1268 { 1269 writer_fd_t *writer; 1270 1271 if ((writer = calloc(1, sizeof(*writer))) == NULL) { 1272 (void) fprintf(stderr, "__ops_writer_set_fd: bad alloc\n"); 1273 } else { 1274 writer->fd = fd; 1275 __ops_writer_set(output, fd_writer, NULL, writer_fd_destroyer, writer); 1276 } 1277 } 1278 1279 static unsigned 1280 memory_writer(const unsigned char *src, 1281 unsigned len, 1282 __ops_error_t **errors, 1283 __ops_writer_t *writer) 1284 { 1285 __ops_memory_t *mem; 1286 1287 __OPS_USED(errors); 1288 mem = __ops_writer_get_arg(writer); 1289 __ops_memory_add(mem, src, len); 1290 return 1; 1291 } 1292 1293 /** 1294 * \ingroup Core_WritersFirst 1295 * \brief Write to memory 1296 * 1297 * Set a memory writer. 1298 * 1299 * \param output The output structure 1300 * \param mem The memory structure 1301 * \note It is the caller's responsiblity to call __ops_memory_free(mem) 1302 * \sa __ops_memory_free() 1303 */ 1304 1305 void 1306 __ops_writer_set_memory(__ops_output_t *output, __ops_memory_t *mem) 1307 { 1308 __ops_writer_set(output, memory_writer, NULL, NULL, mem); 1309 } 1310 1311 /**************************************************************************/ 1312 1313 typedef struct { 1314 __ops_hash_alg_t hash_alg; 1315 __ops_hash_t hash; 1316 unsigned char *hashed; 1317 } skey_checksum_t; 1318 1319 static unsigned 1320 skey_checksum_writer(const unsigned char *src, 1321 const unsigned len, 1322 __ops_error_t **errors, 1323 __ops_writer_t *writer) 1324 { 1325 skey_checksum_t *sum; 1326 unsigned ret = 1; 1327 1328 sum = __ops_writer_get_arg(writer); 1329 /* add contents to hash */ 1330 sum->hash.add(&sum->hash, src, len); 1331 /* write to next stacked writer */ 1332 ret = __ops_stacked_write(src, len, errors, writer); 1333 /* tidy up and return */ 1334 return ret; 1335 } 1336 1337 static unsigned 1338 skey_checksum_finaliser(__ops_error_t **errors, __ops_writer_t *writer) 1339 { 1340 skey_checksum_t *sum; 1341 1342 sum = __ops_writer_get_arg(writer); 1343 if (errors) { 1344 printf("errors in skey_checksum_finaliser\n"); 1345 } 1346 sum->hash.finish(&sum->hash, sum->hashed); 1347 return 1; 1348 } 1349 1350 static void 1351 skey_checksum_destroyer(__ops_writer_t *writer) 1352 { 1353 skey_checksum_t *sum; 1354 1355 sum = __ops_writer_get_arg(writer); 1356 free(sum); 1357 } 1358 1359 /** 1360 \ingroup Core_WritersNext 1361 \param output 1362 \param seckey 1363 */ 1364 void 1365 __ops_push_checksum_writer(__ops_output_t *output, __ops_seckey_t *seckey) 1366 { 1367 /* XXX: push a SHA-1 checksum writer (and change s2k to 254). */ 1368 skey_checksum_t *sum; 1369 1370 if ((sum = calloc(1, sizeof(*sum))) == NULL) { 1371 (void) fprintf(stderr, "__ops_push_checksum_writer: bad alloc\n"); 1372 } else { 1373 /* configure the arg */ 1374 sum->hash_alg = seckey->hash_alg; 1375 sum->hashed = seckey->checkhash; 1376 /* init the hash */ 1377 __ops_hash_any(&sum->hash, sum->hash_alg); 1378 if (!sum->hash.init(&sum->hash)) { 1379 (void) fprintf(stderr, 1380 "__ops_push_checksum_writer: bad hash init\n"); 1381 /* just continue and die */ 1382 /* XXX - agc - no way to return failure */ 1383 } 1384 __ops_writer_push(output, skey_checksum_writer, 1385 skey_checksum_finaliser, skey_checksum_destroyer, sum); 1386 } 1387 } 1388 1389 /**************************************************************************/ 1390 1391 #define MAX_PARTIAL_DATA_LENGTH 1073741824 1392 1393 typedef struct { 1394 __ops_crypt_t *crypt; 1395 __ops_memory_t *mem_data; 1396 __ops_memory_t *litmem; 1397 __ops_output_t *litoutput; 1398 __ops_memory_t *se_ip_mem; 1399 __ops_output_t *se_ip_out; 1400 __ops_hash_t hash; 1401 } str_enc_se_ip_t; 1402 1403 1404 static unsigned 1405 str_enc_se_ip_writer(const unsigned char *src, 1406 unsigned len, 1407 __ops_error_t **errors, 1408 __ops_writer_t *writer); 1409 1410 static unsigned 1411 str_enc_se_ip_finaliser(__ops_error_t **errors, 1412 __ops_writer_t * writer); 1413 1414 static void str_enc_se_ip_destroyer(__ops_writer_t *writer); 1415 1416 /* */ 1417 1418 /** 1419 \ingroup Core_WritersNext 1420 \param output 1421 \param pubkey 1422 */ 1423 void 1424 __ops_push_stream_enc_se_ip(__ops_output_t *output, const __ops_key_t *pubkey) 1425 { 1426 __ops_pk_sesskey_t *encrypted_pk_sesskey; 1427 const unsigned int bufsz = 1024; 1428 str_enc_se_ip_t *se_ip; 1429 __ops_crypt_t *encrypted; 1430 unsigned char *iv; 1431 1432 if ((se_ip = calloc(1, sizeof(*se_ip))) == NULL) { 1433 (void) fprintf(stderr, 1434 "__ops_push_stream_enc_se_ip: bad alloc\n"); 1435 return; 1436 } 1437 encrypted_pk_sesskey = __ops_create_pk_sesskey(pubkey); 1438 __ops_write_pk_sesskey(output, encrypted_pk_sesskey); 1439 1440 /* Setup the se_ip */ 1441 if ((encrypted = calloc(1, sizeof(*encrypted))) == NULL) { 1442 free(se_ip); 1443 (void) fprintf(stderr, 1444 "__ops_push_stream_enc_se_ip: bad alloc\n"); 1445 return; 1446 } 1447 __ops_crypt_any(encrypted, encrypted_pk_sesskey->symm_alg); 1448 if ((iv = calloc(1, encrypted->blocksize)) == NULL) { 1449 free(encrypted); 1450 free(se_ip); 1451 (void) fprintf(stderr, 1452 "__ops_push_stream_enc_se_ip: bad alloc\n"); 1453 return; 1454 } 1455 encrypted->set_iv(encrypted, iv); 1456 encrypted->set_crypt_key(encrypted, &encrypted_pk_sesskey->key[0]); 1457 __ops_encrypt_init(encrypted); 1458 1459 se_ip->crypt = encrypted; 1460 1461 se_ip->mem_data = __ops_memory_new(); 1462 __ops_memory_init(se_ip->mem_data, bufsz); 1463 1464 se_ip->litmem = NULL; 1465 se_ip->litoutput = NULL; 1466 1467 __ops_setup_memory_write(&se_ip->se_ip_out, &se_ip->se_ip_mem, bufsz); 1468 1469 /* And push writer on stack */ 1470 __ops_writer_push(output, 1471 str_enc_se_ip_writer, 1472 str_enc_se_ip_finaliser, 1473 str_enc_se_ip_destroyer, se_ip); 1474 /* tidy up */ 1475 free(encrypted_pk_sesskey); 1476 free(iv); 1477 } 1478 1479 1480 /* calculate the partial data length */ 1481 static unsigned int 1482 __ops_partial_data_len(unsigned int len) 1483 { 1484 unsigned int mask = MAX_PARTIAL_DATA_LENGTH; 1485 int i; 1486 1487 if (len == 0) { 1488 (void) fprintf(stderr, "__ops_partial_data_len: 0 len\n"); 1489 return 0; 1490 } 1491 if (len > MAX_PARTIAL_DATA_LENGTH) { 1492 return MAX_PARTIAL_DATA_LENGTH; 1493 } 1494 for (i = 0; i <= 30; i++) { 1495 if (mask & len) { 1496 break; 1497 } 1498 mask >>= 1; 1499 } 1500 return mask; 1501 } 1502 1503 static unsigned 1504 __ops_write_partial_len(unsigned int len, __ops_output_t *output) 1505 { 1506 /* len must be a power of 2 from 0 to 30 */ 1507 unsigned char c; 1508 int i; 1509 1510 for (i = 0; i <= 30; i++) { 1511 if ((len >> i) & 1) { 1512 break; 1513 } 1514 } 1515 c = 224 + i; 1516 return __ops_write(output, &c, 1); 1517 } 1518 1519 static unsigned 1520 stream_write_litdata(__ops_output_t *output, 1521 const unsigned char *data, 1522 unsigned len) 1523 { 1524 while (len > 0) { 1525 size_t pdlen = __ops_partial_data_len(len); 1526 1527 __ops_write_partial_len(pdlen, output); 1528 __ops_write(output, data, pdlen); 1529 data += pdlen; 1530 len -= pdlen; 1531 } 1532 return 1; 1533 } 1534 1535 static unsigned 1536 stream_write_litdata_first(__ops_output_t *output, 1537 const unsigned char *data, 1538 unsigned int len, 1539 const __ops_litdata_type_t type) 1540 { 1541 /* \todo add filename */ 1542 /* \todo add date */ 1543 /* \todo do we need to check text data for <cr><lf> line endings ? */ 1544 1545 size_t sz_towrite; 1546 size_t sz_pd; 1547 1548 sz_towrite = 1 + 1 + 4 + len; 1549 sz_pd = __ops_partial_data_len(sz_towrite); 1550 if (sz_pd < 512) { 1551 (void) fprintf(stderr, 1552 "stream_write_litdata_first: bad sz_pd\n"); 1553 return 0; 1554 } 1555 __ops_write_ptag(output, OPS_PTAG_CT_LITDATA); 1556 __ops_write_partial_len(sz_pd, output); 1557 __ops_write_scalar(output, (unsigned)type, 1); 1558 __ops_write_scalar(output, 0, 1); 1559 __ops_write_scalar(output, 0, 4); 1560 __ops_write(output, data, sz_pd - 6); 1561 1562 data += (sz_pd - 6); 1563 sz_towrite -= sz_pd; 1564 1565 return stream_write_litdata(output, data, sz_towrite); 1566 } 1567 1568 static unsigned 1569 stream_write_litdata_last(__ops_output_t *output, 1570 const unsigned char *data, 1571 unsigned int len) 1572 { 1573 __ops_write_length(output, len); 1574 return __ops_write(output, data, len); 1575 } 1576 1577 static unsigned 1578 stream_write_se_ip(__ops_output_t *output, 1579 const unsigned char *data, 1580 unsigned int len, 1581 str_enc_se_ip_t *se_ip) 1582 { 1583 size_t pdlen; 1584 1585 while (len > 0) { 1586 pdlen = __ops_partial_data_len(len); 1587 __ops_write_partial_len(pdlen, output); 1588 1589 __ops_push_enc_crypt(output, se_ip->crypt); 1590 __ops_write(output, data, pdlen); 1591 __ops_writer_pop(output); 1592 1593 se_ip->hash.add(&se_ip->hash, data, pdlen); 1594 1595 data += pdlen; 1596 len -= pdlen; 1597 } 1598 return 1; 1599 } 1600 1601 static unsigned 1602 stream_write_se_ip_first(__ops_output_t *output, 1603 const unsigned char *data, 1604 unsigned int len, 1605 str_enc_se_ip_t *se_ip) 1606 { 1607 unsigned char *preamble; 1608 size_t blocksize; 1609 size_t sz_preamble; 1610 size_t sz_towrite; 1611 size_t sz_pd; 1612 1613 blocksize = se_ip->crypt->blocksize; 1614 sz_preamble = blocksize + 2; 1615 sz_towrite = sz_preamble + 1 + len; 1616 if ((preamble = calloc(1, sz_preamble)) == NULL) { 1617 (void) fprintf(stderr, 1618 "stream_write_se_ip_first: bad alloc\n"); 1619 return 0; 1620 } 1621 sz_pd = __ops_partial_data_len(sz_towrite); 1622 if (sz_pd < 512) { 1623 free(preamble); 1624 (void) fprintf(stderr, 1625 "stream_write_se_ip_first: bad sz_pd\n"); 1626 return 0; 1627 } 1628 __ops_write_ptag(output, OPS_PTAG_CT_SE_IP_DATA); 1629 __ops_write_partial_len(sz_pd, output); 1630 __ops_write_scalar(output, SE_IP_DATA_VERSION, 1); 1631 __ops_push_enc_crypt(output, se_ip->crypt); 1632 1633 __ops_random(preamble, blocksize); 1634 preamble[blocksize] = preamble[blocksize - 2]; 1635 preamble[blocksize + 1] = preamble[blocksize - 1]; 1636 __ops_hash_any(&se_ip->hash, OPS_HASH_SHA1); 1637 if (!se_ip->hash.init(&se_ip->hash)) { 1638 free(preamble); 1639 (void) fprintf(stderr, 1640 "stream_write_se_ip_first: bad hash init\n"); 1641 return 0; 1642 } 1643 __ops_write(output, preamble, sz_preamble); 1644 se_ip->hash.add(&se_ip->hash, preamble, sz_preamble); 1645 __ops_write(output, data, sz_pd - sz_preamble - 1); 1646 se_ip->hash.add(&se_ip->hash, data, sz_pd - sz_preamble - 1); 1647 data += (sz_pd - sz_preamble - 1); 1648 sz_towrite -= sz_pd; 1649 __ops_writer_pop(output); 1650 stream_write_se_ip(output, data, sz_towrite, se_ip); 1651 free(preamble); 1652 return 1; 1653 } 1654 1655 static unsigned 1656 stream_write_se_ip_last(__ops_output_t *output, 1657 const unsigned char *data, 1658 unsigned int len, 1659 str_enc_se_ip_t *se_ip) 1660 { 1661 __ops_output_t *mdcoutput; 1662 __ops_memory_t *mdcmem; 1663 unsigned char c; 1664 unsigned char hashed[OPS_SHA1_HASH_SIZE]; 1665 const size_t sz_mdc = 1 + 1 + OPS_SHA1_HASH_SIZE; 1666 size_t sz_buf = len + sz_mdc; 1667 1668 se_ip->hash.add(&se_ip->hash, data, len); 1669 1670 /* MDC packet tag */ 1671 c = MDC_PKT_TAG; 1672 se_ip->hash.add(&se_ip->hash, &c, 1); 1673 1674 /* MDC packet len */ 1675 c = OPS_SHA1_HASH_SIZE; 1676 se_ip->hash.add(&se_ip->hash, &c, 1); 1677 1678 /* finish */ 1679 se_ip->hash.finish(&se_ip->hash, hashed); 1680 1681 __ops_setup_memory_write(&mdcoutput, &mdcmem, sz_mdc); 1682 __ops_write_mdc(hashed, mdcoutput); 1683 1684 /* write length of last se_ip chunk */ 1685 __ops_write_length(output, sz_buf); 1686 1687 /* encode everting */ 1688 __ops_push_enc_crypt(output, se_ip->crypt); 1689 1690 __ops_write(output, data, len); 1691 __ops_write(output, __ops_mem_data(mdcmem), __ops_mem_len(mdcmem)); 1692 1693 __ops_writer_pop(output); 1694 1695 __ops_teardown_memory_write(mdcoutput, mdcmem); 1696 1697 return 1; 1698 } 1699 1700 static unsigned 1701 str_enc_se_ip_writer(const unsigned char *src, 1702 unsigned len, 1703 __ops_error_t **errors, 1704 __ops_writer_t *writer) 1705 { 1706 str_enc_se_ip_t *se_ip = __ops_writer_get_arg(writer); 1707 unsigned ret = 1; 1708 1709 if (se_ip->litoutput == NULL) { /* first literal data chunk 1710 * is not yet written */ 1711 size_t datalength; 1712 1713 __ops_memory_add(se_ip->mem_data, src, len); 1714 datalength = __ops_mem_len(se_ip->mem_data); 1715 1716 /* 4.2.2.4. Partial Body Lengths */ 1717 /* The first partial length MUST be at least 512 octets long. */ 1718 if (datalength < 512) { 1719 return 1; /* will wait for more data or 1720 * end of stream */ 1721 } 1722 __ops_setup_memory_write(&se_ip->litoutput, 1723 &se_ip->litmem, datalength + 32); 1724 stream_write_litdata_first(se_ip->litoutput, 1725 __ops_mem_data(se_ip->mem_data), 1726 datalength, 1727 OPS_LDT_BINARY); 1728 1729 stream_write_se_ip_first(se_ip->se_ip_out, 1730 __ops_mem_data(se_ip->litmem), 1731 __ops_mem_len(se_ip->litmem), se_ip); 1732 } else { 1733 stream_write_litdata(se_ip->litoutput, src, len); 1734 stream_write_se_ip(se_ip->se_ip_out, 1735 __ops_mem_data(se_ip->litmem), 1736 __ops_mem_len(se_ip->litmem), se_ip); 1737 } 1738 1739 /* now write memory to next writer */ 1740 ret = __ops_stacked_write(__ops_mem_data(se_ip->se_ip_mem), 1741 __ops_mem_len(se_ip->se_ip_mem), 1742 errors, writer); 1743 1744 __ops_memory_clear(se_ip->litmem); 1745 __ops_memory_clear(se_ip->se_ip_mem); 1746 1747 return ret; 1748 } 1749 1750 static unsigned 1751 str_enc_se_ip_finaliser(__ops_error_t **errors, __ops_writer_t *writer) 1752 { 1753 str_enc_se_ip_t *se_ip = __ops_writer_get_arg(writer); 1754 /* write last chunk of data */ 1755 1756 if (se_ip->litoutput == NULL) { 1757 /* first literal data chunk was not written */ 1758 /* so we know the total length of data, write a simple packet */ 1759 1760 /* create literal data packet from buffered data */ 1761 __ops_setup_memory_write(&se_ip->litoutput, &se_ip->litmem, 1762 __ops_mem_len(se_ip->mem_data) + 32); 1763 1764 __ops_write_litdata(se_ip->litoutput, 1765 __ops_mem_data(se_ip->mem_data), 1766 (const int)__ops_mem_len(se_ip->mem_data), 1767 OPS_LDT_BINARY); 1768 1769 /* create SE IP packet set from this literal data */ 1770 __ops_write_se_ip_pktset( 1771 __ops_mem_data(se_ip->litmem), 1772 __ops_mem_len(se_ip->litmem), 1773 se_ip->crypt, se_ip->se_ip_out); 1774 1775 } else { 1776 /* finish writing */ 1777 stream_write_litdata_last(se_ip->litoutput, NULL, 0); 1778 stream_write_se_ip_last(se_ip->se_ip_out, 1779 __ops_mem_data(se_ip->litmem), 1780 __ops_mem_len(se_ip->litmem), se_ip); 1781 } 1782 1783 /* now write memory to next writer */ 1784 return __ops_stacked_write(__ops_mem_data(se_ip->se_ip_mem), 1785 __ops_mem_len(se_ip->se_ip_mem), 1786 errors, writer); 1787 } 1788 1789 static void 1790 str_enc_se_ip_destroyer(__ops_writer_t *writer) 1791 { 1792 str_enc_se_ip_t *se_ip = __ops_writer_get_arg(writer); 1793 1794 __ops_memory_free(se_ip->mem_data); 1795 __ops_teardown_memory_write(se_ip->litoutput, se_ip->litmem); 1796 __ops_teardown_memory_write(se_ip->se_ip_out, se_ip->se_ip_mem); 1797 1798 se_ip->crypt->decrypt_finish(se_ip->crypt); 1799 1800 free(se_ip->crypt); 1801 free(se_ip); 1802 } 1803