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 #include "config.h" 50 51 #ifdef HAVE_SYS_CDEFS_H 52 #include <sys/cdefs.h> 53 #endif 54 55 #if defined(__NetBSD__) 56 __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); 57 __RCSID("$NetBSD: reader.c,v 1.29 2010/02/08 17:19:12 agc Exp $"); 58 #endif 59 60 #include <sys/types.h> 61 #include <sys/stat.h> 62 63 #ifdef HAVE_SYS_MMAN_H 64 #include <sys/mman.h> 65 #endif 66 67 #ifdef HAVE_SYS_PARAM_H 68 #include <sys/param.h> 69 #endif 70 71 #ifdef HAVE_FCNTL_H 72 #include <fcntl.h> 73 #endif 74 75 #ifdef HAVE_UNISTD_H 76 #include <unistd.h> 77 #endif 78 79 #ifdef HAVE_DIRECT_H 80 #include <direct.h> 81 #endif 82 83 #ifdef HAVE_INTTYPES_H 84 #include <inttypes.h> 85 #endif 86 87 #ifdef HAVE_OPENSSL_IDEA_H 88 #include <openssl/cast.h> 89 #endif 90 91 #ifdef HAVE_OPENSSL_IDEA_H 92 #include <openssl/idea.h> 93 #endif 94 95 #ifdef HAVE_OPENSSL_AES_H 96 #include <openssl/aes.h> 97 #endif 98 99 #ifdef HAVE_OPENSSL_DES_H 100 #include <openssl/des.h> 101 #endif 102 103 #include <string.h> 104 #include <stdlib.h> 105 #include <stdio.h> 106 107 #ifdef HAVE_TERMIOS_H 108 #include <termios.h> 109 #endif 110 111 #ifdef HAVE_ERRNO_H 112 #include <errno.h> 113 #endif 114 115 #ifdef HAVE_UNISTD_H 116 #include <unistd.h> 117 #endif 118 119 #ifdef HAVE_LIMITS_H 120 #include <limits.h> 121 #endif 122 123 #include "errors.h" 124 #include "crypto.h" 125 #include "create.h" 126 #include "signature.h" 127 #include "packet.h" 128 #include "packet-parse.h" 129 #include "packet-show.h" 130 #include "packet.h" 131 #include "keyring.h" 132 #include "readerwriter.h" 133 #include "netpgpdefs.h" 134 #include "netpgpdigest.h" 135 136 137 /* get a pass phrase from the user */ 138 int 139 __ops_getpassphrase(void *in, char *phrase, size_t size) 140 { 141 char *p; 142 143 if (in == NULL) { 144 while ((p = getpass("netpgp passphrase: ")) == NULL) { 145 } 146 (void) snprintf(phrase, size, "%s", p); 147 } else { 148 if (fgets(phrase, (int)size, in) == NULL) { 149 return 0; 150 } 151 phrase[strlen(phrase) - 1] = 0x0; 152 } 153 return 1; 154 } 155 156 /** 157 * \ingroup Internal_Readers_Generic 158 * \brief Starts reader stack 159 * \param stream Parse settings 160 * \param reader Reader to use 161 * \param destroyer Destroyer to use 162 * \param vp Reader-specific arg 163 */ 164 void 165 __ops_reader_set(__ops_stream_t *stream, 166 __ops_reader_func_t *reader, 167 __ops_reader_destroyer_t *destroyer, 168 void *vp) 169 { 170 stream->readinfo.reader = reader; 171 stream->readinfo.destroyer = destroyer; 172 stream->readinfo.arg = vp; 173 } 174 175 /** 176 * \ingroup Internal_Readers_Generic 177 * \brief Adds to reader stack 178 * \param stream Parse settings 179 * \param reader Reader to use 180 * \param destroyer Reader's destroyer 181 * \param vp Reader-specific arg 182 */ 183 void 184 __ops_reader_push(__ops_stream_t *stream, 185 __ops_reader_func_t *reader, 186 __ops_reader_destroyer_t *destroyer, 187 void *vp) 188 { 189 __ops_reader_t *readinfo; 190 191 if ((readinfo = calloc(1, sizeof(*readinfo))) == NULL) { 192 (void) fprintf(stderr, "__ops_reader_push: bad alloc\n"); 193 } else { 194 *readinfo = stream->readinfo; 195 (void) memset(&stream->readinfo, 0x0, sizeof(stream->readinfo)); 196 stream->readinfo.next = readinfo; 197 stream->readinfo.parent = stream; 198 199 /* should copy accumulate flags from other reader? RW */ 200 stream->readinfo.accumulate = readinfo->accumulate; 201 202 __ops_reader_set(stream, reader, destroyer, vp); 203 } 204 } 205 206 /** 207 * \ingroup Internal_Readers_Generic 208 * \brief Removes from reader stack 209 * \param stream Parse settings 210 */ 211 void 212 __ops_reader_pop(__ops_stream_t *stream) 213 { 214 __ops_reader_t *next = stream->readinfo.next; 215 216 stream->readinfo = *next; 217 free(next); 218 } 219 220 /** 221 * \ingroup Internal_Readers_Generic 222 * \brief Gets arg from reader 223 * \param readinfo Reader info 224 * \return Pointer to reader info's arg 225 */ 226 void * 227 __ops_reader_get_arg(__ops_reader_t *readinfo) 228 { 229 return readinfo->arg; 230 } 231 232 /**************************************************************************/ 233 234 #define CRC24_POLY 0x1864cfbL 235 236 enum { 237 NONE = 0, 238 BEGIN_PGP_MESSAGE, 239 BEGIN_PGP_PUBLIC_KEY_BLOCK, 240 BEGIN_PGP_PRIVATE_KEY_BLOCK, 241 BEGIN_PGP_MULTI, 242 BEGIN_PGP_SIGNATURE, 243 244 END_PGP_MESSAGE, 245 END_PGP_PUBLIC_KEY_BLOCK, 246 END_PGP_PRIVATE_KEY_BLOCK, 247 END_PGP_MULTI, 248 END_PGP_SIGNATURE, 249 250 BEGIN_PGP_SIGNED_MESSAGE 251 }; 252 253 /** 254 * \struct dearmour_t 255 */ 256 typedef struct { 257 enum { 258 OUTSIDE_BLOCK = 0, 259 BASE64, 260 AT_TRAILER_NAME 261 } state; 262 int lastseen; 263 __ops_stream_t *parse_info; 264 unsigned seen_nl:1; 265 unsigned prev_nl:1; 266 unsigned allow_headers_without_gap:1; 267 /* !< allow headers in armoured data that are 268 * not separated from the data by a blank line 269 * */ 270 unsigned allow_no_gap:1; 271 /* !< allow no blank line at the start of 272 * armoured data */ 273 unsigned allow_trailing_whitespace:1; 274 /* !< allow armoured stuff to have trailing 275 * whitespace where we wouldn't strictly expect 276 * it */ 277 /* it is an error to get a cleartext message without a sig */ 278 unsigned expect_sig:1; 279 unsigned got_sig:1; 280 /* base64 stuff */ 281 unsigned buffered; 282 unsigned char buffer[3]; 283 unsigned eof64; 284 unsigned long checksum; 285 unsigned long read_checksum; 286 /* unarmoured text blocks */ 287 unsigned char unarmoured[NETPGP_BUFSIZ]; 288 size_t unarmoredc; 289 /* pushed back data (stored backwards) */ 290 unsigned char *pushback; 291 unsigned pushbackc; 292 /* armoured block headers */ 293 __ops_headers_t headers; 294 } dearmour_t; 295 296 static void 297 push_back(dearmour_t *dearmour, const unsigned char *buf, 298 unsigned length) 299 { 300 unsigned n; 301 302 if (dearmour->pushback) { 303 (void) fprintf(stderr, "push_back: already pushed back\n"); 304 } else if ((dearmour->pushback = calloc(1, length)) == NULL) { 305 (void) fprintf(stderr, "push_back: bad alloc\n"); 306 } else { 307 for (n = 0; n < length; ++n) { 308 dearmour->pushback[n] = buf[(length - n) - 1]; 309 } 310 dearmour->pushbackc = length; 311 } 312 } 313 314 /* this struct holds a textual header line */ 315 typedef struct headerline_t { 316 const char *s; /* the header line */ 317 size_t len; /* its length */ 318 int type; /* the defined type */ 319 } headerline_t; 320 321 static headerline_t headerlines[] = { 322 { "BEGIN PGP MESSAGE", 17, BEGIN_PGP_MESSAGE }, 323 { "BEGIN PGP PUBLIC KEY BLOCK", 26, BEGIN_PGP_PUBLIC_KEY_BLOCK }, 324 { "BEGIN PGP PRIVATE KEY BLOCK",27, BEGIN_PGP_PRIVATE_KEY_BLOCK }, 325 { "BEGIN PGP MESSAGE, PART ", 25, BEGIN_PGP_MULTI }, 326 { "BEGIN PGP SIGNATURE", 19, BEGIN_PGP_SIGNATURE }, 327 328 { "END PGP MESSAGE", 15, END_PGP_MESSAGE }, 329 { "END PGP PUBLIC KEY BLOCK", 24, END_PGP_PUBLIC_KEY_BLOCK }, 330 { "END PGP PRIVATE KEY BLOCK", 25, END_PGP_PRIVATE_KEY_BLOCK }, 331 { "END PGP MESSAGE, PART ", 22, END_PGP_MULTI }, 332 { "END PGP SIGNATURE", 17, END_PGP_SIGNATURE }, 333 334 { "BEGIN PGP SIGNED MESSAGE", 24, BEGIN_PGP_SIGNED_MESSAGE }, 335 336 { NULL, 0, -1 } 337 }; 338 339 /* search through the table of header lines */ 340 static int 341 findheaderline(char *headerline) 342 { 343 headerline_t *hp; 344 345 for (hp = headerlines ; hp->s ; hp++) { 346 if (strncmp(headerline, hp->s, hp->len) == 0) { 347 break; 348 } 349 } 350 return hp->type; 351 } 352 353 static int 354 set_lastseen_headerline(dearmour_t *dearmour, char *hdr, __ops_error_t **errors) 355 { 356 int lastseen; 357 int prev; 358 359 prev = dearmour->lastseen; 360 if ((lastseen = findheaderline(hdr)) == -1) { 361 OPS_ERROR_1(errors, OPS_E_R_BAD_FORMAT, 362 "Unrecognised Header Line %s", hdr); 363 return 0; 364 } 365 dearmour->lastseen = lastseen; 366 if (__ops_get_debug_level(__FILE__)) { 367 printf("set header: hdr=%s, dearmour->lastseen=%d, prev=%d\n", 368 hdr, dearmour->lastseen, prev); 369 } 370 switch (dearmour->lastseen) { 371 case NONE: 372 OPS_ERROR_1(errors, OPS_E_R_BAD_FORMAT, 373 "Unrecognised last seen Header Line %s", hdr); 374 break; 375 376 case END_PGP_MESSAGE: 377 if (prev != BEGIN_PGP_MESSAGE) { 378 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, 379 "Got END PGP MESSAGE, but not after BEGIN"); 380 } 381 break; 382 383 case END_PGP_PUBLIC_KEY_BLOCK: 384 if (prev != BEGIN_PGP_PUBLIC_KEY_BLOCK) { 385 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, 386 "Got END PGP PUBLIC KEY BLOCK, but not after BEGIN"); 387 } 388 break; 389 390 case END_PGP_PRIVATE_KEY_BLOCK: 391 if (prev != BEGIN_PGP_PRIVATE_KEY_BLOCK) { 392 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, 393 "Got END PGP PRIVATE KEY BLOCK, but not after BEGIN"); 394 } 395 break; 396 397 case BEGIN_PGP_MULTI: 398 case END_PGP_MULTI: 399 OPS_ERROR(errors, OPS_E_R_UNSUPPORTED, 400 "Multi-part messages are not yet supported"); 401 break; 402 403 case END_PGP_SIGNATURE: 404 if (prev != BEGIN_PGP_SIGNATURE) { 405 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, 406 "Got END PGP SIGNATURE, but not after BEGIN"); 407 } 408 break; 409 410 case BEGIN_PGP_MESSAGE: 411 case BEGIN_PGP_PUBLIC_KEY_BLOCK: 412 case BEGIN_PGP_PRIVATE_KEY_BLOCK: 413 case BEGIN_PGP_SIGNATURE: 414 case BEGIN_PGP_SIGNED_MESSAGE: 415 break; 416 } 417 return 1; 418 } 419 420 static int 421 read_char(dearmour_t *dearmour, 422 __ops_error_t **errors, 423 __ops_reader_t *readinfo, 424 __ops_cbdata_t *cbinfo, 425 unsigned skip) 426 { 427 unsigned char c; 428 429 do { 430 if (dearmour->pushbackc) { 431 c = dearmour->pushback[--dearmour->pushbackc]; 432 if (dearmour->pushbackc == 0) { 433 free(dearmour->pushback); 434 dearmour->pushback = NULL; 435 } 436 } else if (__ops_stacked_read(&c, 1, errors, readinfo, 437 cbinfo) != 1) { 438 return -1; 439 } 440 } while (skip && c == '\r'); 441 dearmour->prev_nl = dearmour->seen_nl; 442 dearmour->seen_nl = c == '\n'; 443 return c; 444 } 445 446 static int 447 eat_whitespace(int first, 448 dearmour_t *dearmour, 449 __ops_error_t **errors, 450 __ops_reader_t *readinfo, 451 __ops_cbdata_t *cbinfo, 452 unsigned skip) 453 { 454 int c = first; 455 456 while (c == ' ' || c == '\t') { 457 c = read_char(dearmour, errors, readinfo, cbinfo, skip); 458 } 459 return c; 460 } 461 462 static int 463 read_and_eat_whitespace(dearmour_t *dearmour, 464 __ops_error_t **errors, 465 __ops_reader_t *readinfo, 466 __ops_cbdata_t *cbinfo, 467 unsigned skip) 468 { 469 int c; 470 471 do { 472 c = read_char(dearmour, errors, readinfo, cbinfo, skip); 473 } while (c == ' ' || c == '\t'); 474 return c; 475 } 476 477 static void 478 flush(dearmour_t *dearmour, __ops_cbdata_t *cbinfo) 479 { 480 __ops_packet_t content; 481 482 if (dearmour->unarmoredc > 0) { 483 content.u.unarmoured_text.data = dearmour->unarmoured; 484 content.u.unarmoured_text.length = dearmour->unarmoredc; 485 CALLBACK(OPS_PTAG_CT_UNARMOURED_TEXT, cbinfo, &content); 486 dearmour->unarmoredc = 0; 487 } 488 } 489 490 static int 491 unarmoured_read_char(dearmour_t *dearmour, 492 __ops_error_t **errors, 493 __ops_reader_t *readinfo, 494 __ops_cbdata_t *cbinfo, 495 unsigned skip) 496 { 497 int c; 498 499 do { 500 c = read_char(dearmour, errors, readinfo, cbinfo, 0); 501 if (c < 0) { 502 return c; 503 } 504 dearmour->unarmoured[dearmour->unarmoredc++] = c; 505 if (dearmour->unarmoredc == sizeof(dearmour->unarmoured)) { 506 flush(dearmour, cbinfo); 507 } 508 } while (skip && c == '\r'); 509 return c; 510 } 511 512 /** 513 * \param headers 514 * \param key 515 * 516 * \return header value if found, otherwise NULL 517 */ 518 static const char * 519 __ops_find_header(__ops_headers_t *headers, const char *key) 520 { 521 unsigned n; 522 523 for (n = 0; n < headers->headerc; ++n) { 524 if (strcmp(headers->headers[n].key, key) == 0) { 525 return headers->headers[n].value; 526 } 527 } 528 return NULL; 529 } 530 531 /** 532 * \param dest 533 * \param src 534 */ 535 static void 536 __ops_dup_headers(__ops_headers_t *dest, const __ops_headers_t *src) 537 { 538 unsigned n; 539 540 if ((dest->headers = calloc(src->headerc, sizeof(*dest->headers))) == NULL) { 541 (void) fprintf(stderr, "__ops_dup_headers: bad alloc\n"); 542 } else { 543 dest->headerc = src->headerc; 544 for (n = 0; n < src->headerc; ++n) { 545 dest->headers[n].key = strdup(src->headers[n].key); 546 dest->headers[n].value = strdup(src->headers[n].value); 547 } 548 } 549 } 550 551 /* 552 * Note that this skips CRs so implementations always see just straight LFs 553 * as line terminators 554 */ 555 static int 556 process_dash_escaped(dearmour_t *dearmour, 557 __ops_error_t **errors, 558 __ops_reader_t *readinfo, 559 __ops_cbdata_t *cbinfo) 560 { 561 __ops_packet_t content; 562 __ops_packet_t content2; 563 __ops_cleartext_body_t *body = &content.u.cleartext_body; 564 __ops_cleartext_trailer_t *trailer = &content2.u.cleartext_trailer; 565 const char *hashstr; 566 __ops_hash_t *hash; 567 int total; 568 569 if ((hash = calloc(1, sizeof(*hash))) == NULL) { 570 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, 571 "process_dash_escaped: bad alloc"); 572 return -1; 573 } 574 hashstr = __ops_find_header(&dearmour->headers, "Hash"); 575 if (hashstr) { 576 __ops_hash_alg_t alg; 577 578 alg = __ops_str_to_hash_alg(hashstr); 579 if (!__ops_is_hash_alg_supported(&alg)) { 580 free(hash); 581 OPS_ERROR_1(errors, OPS_E_R_BAD_FORMAT, 582 "Unsupported hash algorithm '%s'", hashstr); 583 return -1; 584 } 585 if (alg == OPS_HASH_UNKNOWN) { 586 free(hash); 587 OPS_ERROR_1(errors, OPS_E_R_BAD_FORMAT, 588 "Unknown hash algorithm '%s'", hashstr); 589 return -1; 590 } 591 __ops_hash_any(hash, alg); 592 } else { 593 __ops_hash_md5(hash); 594 } 595 596 if (!hash->init(hash)) { 597 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, 598 "can't initialise hash"); 599 return -1; 600 } 601 602 body->length = 0; 603 total = 0; 604 for (;;) { 605 int c; 606 unsigned count; 607 608 c = read_char(dearmour, errors, readinfo, cbinfo, 1); 609 if (c < 0) { 610 return -1; 611 } 612 if (dearmour->prev_nl && c == '-') { 613 if ((c = read_char(dearmour, errors, readinfo, cbinfo, 614 0)) < 0) { 615 return -1; 616 } 617 if (c != ' ') { 618 /* then this had better be a trailer! */ 619 if (c != '-') { 620 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, 621 "Bad dash-escaping"); 622 } 623 for (count = 2; count < 5; ++count) { 624 if ((c = read_char(dearmour, errors, 625 readinfo, cbinfo, 0)) < 0) { 626 return -1; 627 } 628 if (c != '-') { 629 OPS_ERROR(errors, 630 OPS_E_R_BAD_FORMAT, 631 "Bad dash-escaping (2)"); 632 } 633 } 634 dearmour->state = AT_TRAILER_NAME; 635 break; 636 } 637 /* otherwise we read the next character */ 638 if ((c = read_char(dearmour, errors, readinfo, cbinfo, 639 0)) < 0) { 640 return -1; 641 } 642 } 643 if (c == '\n' && body->length) { 644 if (memchr(body->data + 1, '\n', body->length - 1) 645 != NULL) { 646 (void) fprintf(stderr, 647 "process_dash_escaped: newline found\n"); 648 return -1; 649 } 650 if (body->data[0] == '\n') { 651 hash->add(hash, (const unsigned char *)"\r", 1); 652 } 653 hash->add(hash, body->data, body->length); 654 if (__ops_get_debug_level(__FILE__)) { 655 fprintf(stderr, "Got body:\n%s\n", body->data); 656 } 657 CALLBACK(OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY, cbinfo, 658 &content); 659 body->length = 0; 660 } 661 body->data[body->length++] = c; 662 total += 1; 663 if (body->length == sizeof(body->data)) { 664 if (__ops_get_debug_level(__FILE__)) { 665 (void) fprintf(stderr, "Got body (2):\n%s\n", 666 body->data); 667 } 668 CALLBACK(OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY, cbinfo, 669 &content); 670 body->length = 0; 671 } 672 } 673 if (body->data[0] != '\n') { 674 (void) fprintf(stderr, 675 "process_dash_escaped: no newline in body data\n"); 676 return -1; 677 } 678 if (body->length != 1) { 679 (void) fprintf(stderr, 680 "process_dash_escaped: bad body length\n"); 681 return -1; 682 } 683 684 /* don't send that one character, because it's part of the trailer */ 685 trailer->hash = hash; 686 CALLBACK(OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER, cbinfo, &content2); 687 return total; 688 } 689 690 static int 691 add_header(dearmour_t *dearmour, const char *key, const char *value) 692 { 693 int n; 694 695 /* 696 * Check that the header is valid 697 */ 698 if (strcmp(key, "Version") == 0 || 699 strcmp(key, "Comment") == 0 || 700 strcmp(key, "MessageID") == 0 || 701 strcmp(key, "Hash") == 0 || 702 strcmp(key, "Charset") == 0) { 703 n = dearmour->headers.headerc; 704 dearmour->headers.headers = realloc(dearmour->headers.headers, 705 (n + 1) * sizeof(*dearmour->headers.headers)); 706 if (dearmour->headers.headers == NULL) { 707 (void) fprintf(stderr, "add_header: bad alloc\n"); 708 return 0; 709 } 710 dearmour->headers.headers[n].key = strdup(key); 711 dearmour->headers.headers[n].value = strdup(value); 712 dearmour->headers.headerc = n + 1; 713 return 1; 714 } 715 return 0; 716 } 717 718 /* \todo what does a return value of 0 indicate? 1 is good, -1 is bad */ 719 static int 720 parse_headers(dearmour_t *dearmour, __ops_error_t **errors, 721 __ops_reader_t * readinfo, __ops_cbdata_t * cbinfo) 722 { 723 unsigned nbuf; 724 unsigned size; 725 unsigned first = 1; 726 char *buf; 727 int ret = 1; 728 729 nbuf = 0; 730 size = 80; 731 if ((buf = calloc(1, size)) == NULL) { 732 (void) fprintf(stderr, "parse_headers: bad calloc\n"); 733 return -1; 734 } 735 for (;;) { 736 int c; 737 738 if ((c = read_char(dearmour, errors, readinfo, cbinfo, 1)) < 0) { 739 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Unexpected EOF"); 740 ret = -1; 741 break; 742 } 743 if (c == '\n') { 744 char *s; 745 746 if (nbuf == 0) { 747 break; 748 } 749 750 if (nbuf >= size) { 751 (void) fprintf(stderr, 752 "parse_headers: bad size\n"); 753 return -1; 754 } 755 buf[nbuf] = '\0'; 756 757 if ((s = strchr(buf, ':')) == NULL) { 758 if (!first && !dearmour->allow_headers_without_gap) { 759 /* 760 * then we have seriously malformed 761 * armour 762 */ 763 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "No colon in armour header"); 764 ret = -1; 765 break; 766 } else { 767 if (first && 768 !(dearmour->allow_headers_without_gap || dearmour->allow_no_gap)) { 769 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "No colon in armour header (2)"); 770 /* 771 * then we have a nasty 772 * armoured block with no 773 * headers, not even a blank 774 * line. 775 */ 776 buf[nbuf] = '\n'; 777 push_back(dearmour, (unsigned char *) buf, nbuf + 1); 778 ret = -1; 779 break; 780 } 781 } 782 } else { 783 *s = '\0'; 784 if (s[1] != ' ') { 785 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "No space in armour header"); 786 ret = -1; 787 goto end; 788 } 789 if (!add_header(dearmour, buf, s + 2)) { 790 OPS_ERROR_1(errors, OPS_E_R_BAD_FORMAT, "Invalid header %s", buf); 791 ret = -1; 792 goto end; 793 } 794 nbuf = 0; 795 } 796 first = 0; 797 } else { 798 if (size <= nbuf + 1) { 799 size += size + 80; 800 buf = realloc(buf, size); 801 if (buf == NULL) { 802 (void) fprintf(stderr, "bad alloc\n"); 803 ret = -1; 804 goto end; 805 } 806 } 807 buf[nbuf++] = c; 808 } 809 } 810 811 end: 812 free(buf); 813 814 return ret; 815 } 816 817 static int 818 read4(dearmour_t *dearmour, __ops_error_t **errors, 819 __ops_reader_t *readinfo, __ops_cbdata_t *cbinfo, 820 int *pc, unsigned *pn, unsigned long *pl) 821 { 822 int n, c; 823 unsigned long l = 0; 824 825 for (n = 0; n < 4; ++n) { 826 c = read_char(dearmour, errors, readinfo, cbinfo, 1); 827 if (c < 0) { 828 dearmour->eof64 = 1; 829 return -1; 830 } 831 if (c == '-' || c == '=') { 832 break; 833 } 834 l <<= 6; 835 if (c >= 'A' && c <= 'Z') { 836 l += (unsigned long)(c - 'A'); 837 } else if (c >= 'a' && c <= 'z') { 838 l += (unsigned long)(c - 'a') + 26; 839 } else if (c >= '0' && c <= '9') { 840 l += (unsigned long)(c - '0') + 52; 841 } else if (c == '+') { 842 l += 62; 843 } else if (c == '/') { 844 l += 63; 845 } else { 846 --n; 847 l >>= 6; 848 } 849 } 850 851 *pc = c; 852 *pn = n; 853 *pl = l; 854 855 return 4; 856 } 857 858 unsigned 859 __ops_crc24(unsigned checksum, unsigned char c) 860 { 861 unsigned i; 862 863 checksum ^= c << 16; 864 for (i = 0; i < 8; i++) { 865 checksum <<= 1; 866 if (checksum & 0x1000000) 867 checksum ^= CRC24_POLY; 868 } 869 return checksum & 0xffffffL; 870 } 871 872 static int 873 decode64(dearmour_t *dearmour, __ops_error_t **errors, 874 __ops_reader_t *readinfo, __ops_cbdata_t *cbinfo) 875 { 876 unsigned n; 877 int n2; 878 unsigned long l; 879 int c; 880 int ret; 881 882 if (dearmour->buffered) { 883 (void) fprintf(stderr, "decode64: bad dearmour->buffered\n"); 884 return 0; 885 } 886 887 ret = read4(dearmour, errors, readinfo, cbinfo, &c, &n, &l); 888 if (ret < 0) { 889 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Badly formed base64"); 890 return 0; 891 } 892 if (n == 3) { 893 if (c != '=') { 894 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, 895 "Badly terminated base64 (2)"); 896 return 0; 897 } 898 dearmour->buffered = 2; 899 dearmour->eof64 = 1; 900 l >>= 2; 901 } else if (n == 2) { 902 if (c != '=') { 903 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, 904 "Badly terminated base64 (3)"); 905 return 0; 906 } 907 dearmour->buffered = 1; 908 dearmour->eof64 = 1; 909 l >>= 4; 910 c = read_char(dearmour, errors, readinfo, cbinfo, 0); 911 if (c != '=') { 912 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, 913 "Badly terminated base64"); 914 return 0; 915 } 916 } else if (n == 0) { 917 if (!dearmour->prev_nl || c != '=') { 918 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, 919 "Badly terminated base64 (4)"); 920 return 0; 921 } 922 dearmour->buffered = 0; 923 } else { 924 if (n != 4) { 925 (void) fprintf(stderr, 926 "decode64: bad n (!= 4)\n"); 927 return 0; 928 } 929 dearmour->buffered = 3; 930 if (c == '-' || c == '=') { 931 (void) fprintf(stderr, "decode64: bad c\n"); 932 return 0; 933 } 934 } 935 936 if (dearmour->buffered < 3 && dearmour->buffered > 0) { 937 /* then we saw padding */ 938 if (c != '=') { 939 (void) fprintf(stderr, "decode64: bad c (=)\n"); 940 return 0; 941 } 942 c = read_and_eat_whitespace(dearmour, errors, readinfo, cbinfo, 943 1); 944 if (c != '\n') { 945 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, 946 "No newline at base64 end"); 947 return 0; 948 } 949 c = read_char(dearmour, errors, readinfo, cbinfo, 0); 950 if (c != '=') { 951 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, 952 "No checksum at base64 end"); 953 return 0; 954 } 955 } 956 if (c == '=') { 957 /* now we are at the checksum */ 958 ret = read4(dearmour, errors, readinfo, cbinfo, &c, &n, 959 &dearmour->read_checksum); 960 if (ret < 0 || n != 4) { 961 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, 962 "Error in checksum"); 963 return 0; 964 } 965 c = read_char(dearmour, errors, readinfo, cbinfo, 1); 966 if (dearmour->allow_trailing_whitespace) 967 c = eat_whitespace(c, dearmour, errors, readinfo, cbinfo, 968 1); 969 if (c != '\n') { 970 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, 971 "Badly terminated checksum"); 972 return 0; 973 } 974 c = read_char(dearmour, errors, readinfo, cbinfo, 0); 975 if (c != '-') { 976 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, 977 "Bad base64 trailer (2)"); 978 return 0; 979 } 980 } 981 if (c == '-') { 982 for (n = 0; n < 4; ++n) 983 if (read_char(dearmour, errors, readinfo, cbinfo, 984 0) != '-') { 985 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, 986 "Bad base64 trailer"); 987 return 0; 988 } 989 dearmour->eof64 = 1; 990 } else { 991 if (!dearmour->buffered) { 992 (void) fprintf(stderr, "decode64: not buffered\n"); 993 return 0; 994 } 995 } 996 997 for (n = 0; n < dearmour->buffered; ++n) { 998 dearmour->buffer[n] = (unsigned char)l; 999 l >>= 8; 1000 } 1001 1002 for (n2 = dearmour->buffered - 1; n2 >= 0; --n2) 1003 dearmour->checksum = __ops_crc24((unsigned)dearmour->checksum, 1004 dearmour->buffer[n2]); 1005 1006 if (dearmour->eof64 && dearmour->read_checksum != dearmour->checksum) { 1007 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Checksum mismatch"); 1008 return 0; 1009 } 1010 return 1; 1011 } 1012 1013 static void 1014 base64(dearmour_t *dearmour) 1015 { 1016 dearmour->state = BASE64; 1017 dearmour->checksum = CRC24_INIT; 1018 dearmour->eof64 = 0; 1019 dearmour->buffered = 0; 1020 } 1021 1022 /* This reader is rather strange in that it can generate callbacks for */ 1023 /* content - this is because plaintext is not encapsulated in PGP */ 1024 /* packets... it also calls back for the text between the blocks. */ 1025 1026 static int 1027 armoured_data_reader(void *dest_, size_t length, __ops_error_t **errors, 1028 __ops_reader_t *readinfo, 1029 __ops_cbdata_t *cbinfo) 1030 { 1031 __ops_packet_t content; 1032 unsigned char *dest = dest_; 1033 dearmour_t *dearmour; 1034 unsigned first; 1035 char buf[1024]; 1036 int saved; 1037 int ret; 1038 1039 dearmour = __ops_reader_get_arg(readinfo); 1040 saved = length; 1041 if (dearmour->eof64 && !dearmour->buffered) { 1042 if (dearmour->state != OUTSIDE_BLOCK && 1043 dearmour->state != AT_TRAILER_NAME) { 1044 (void) fprintf(stderr, 1045 "armoured_data_reader: bad dearmour state\n"); 1046 return 0; 1047 } 1048 } 1049 1050 while (length > 0) { 1051 unsigned count; 1052 unsigned n; 1053 int c; 1054 1055 flush(dearmour, cbinfo); 1056 switch (dearmour->state) { 1057 case OUTSIDE_BLOCK: 1058 /* 1059 * This code returns EOF rather than EARLY_EOF 1060 * because if we don't see a header line at all, then 1061 * it is just an EOF (and not a BLOCK_END) 1062 */ 1063 while (!dearmour->seen_nl) { 1064 if ((c = unarmoured_read_char(dearmour, errors, 1065 readinfo, cbinfo, 1)) < 0) { 1066 return 0; 1067 } 1068 } 1069 1070 /* 1071 * flush at this point so we definitely have room for 1072 * the header, and so we can easily erase it from the 1073 * buffer 1074 */ 1075 flush(dearmour, cbinfo); 1076 /* Find and consume the 5 leading '-' */ 1077 for (count = 0; count < 5; ++count) { 1078 if ((c = unarmoured_read_char(dearmour, errors, 1079 readinfo, cbinfo, 0)) < 0) { 1080 return 0; 1081 } 1082 if (c != '-') { 1083 goto reloop; 1084 } 1085 } 1086 1087 /* Now find the block type */ 1088 for (n = 0; n < sizeof(buf) - 1;) { 1089 if ((c = unarmoured_read_char(dearmour, errors, 1090 readinfo, cbinfo, 0)) < 0) { 1091 return 0; 1092 } 1093 if (c == '-') { 1094 goto got_minus; 1095 } 1096 buf[n++] = c; 1097 } 1098 /* then I guess this wasn't a proper header */ 1099 break; 1100 1101 got_minus: 1102 buf[n] = '\0'; 1103 1104 /* Consume trailing '-' */ 1105 for (count = 1; count < 5; ++count) { 1106 if ((c = unarmoured_read_char(dearmour, errors, 1107 readinfo, cbinfo, 0)) < 0) { 1108 return 0; 1109 } 1110 if (c != '-') { 1111 /* wasn't a header after all */ 1112 goto reloop; 1113 } 1114 } 1115 1116 /* Consume final NL */ 1117 if ((c = unarmoured_read_char(dearmour, errors, readinfo, 1118 cbinfo, 1)) < 0) { 1119 return 0; 1120 } 1121 if (dearmour->allow_trailing_whitespace) { 1122 if ((c = eat_whitespace(c, dearmour, errors, 1123 readinfo, cbinfo, 1)) < 0) { 1124 return 0; 1125 } 1126 } 1127 if (c != '\n') { 1128 /* wasn't a header line after all */ 1129 break; 1130 } 1131 1132 /* 1133 * Now we've seen the header, scrub it from the 1134 * buffer 1135 */ 1136 dearmour->unarmoredc = 0; 1137 1138 /* 1139 * But now we've seen a header line, then errors are 1140 * EARLY_EOF 1141 */ 1142 if ((ret = parse_headers(dearmour, errors, readinfo, 1143 cbinfo)) <= 0) { 1144 return -1; 1145 } 1146 1147 if (!set_lastseen_headerline(dearmour, buf, errors)) { 1148 return -1; 1149 } 1150 1151 if (strcmp(buf, "BEGIN PGP SIGNED MESSAGE") == 0) { 1152 __ops_dup_headers( 1153 &content.u.cleartext_head.headers, 1154 &dearmour->headers); 1155 CALLBACK(OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER, 1156 cbinfo, 1157 &content); 1158 ret = process_dash_escaped(dearmour, errors, 1159 readinfo, cbinfo); 1160 if (ret <= 0) { 1161 return ret; 1162 } 1163 } else { 1164 content.u.armour_header.type = buf; 1165 content.u.armour_header.headers = 1166 dearmour->headers; 1167 (void) memset(&dearmour->headers, 0x0, 1168 sizeof(dearmour->headers)); 1169 CALLBACK(OPS_PTAG_CT_ARMOUR_HEADER, cbinfo, 1170 &content); 1171 base64(dearmour); 1172 } 1173 break; 1174 1175 case BASE64: 1176 first = 1; 1177 while (length > 0) { 1178 if (!dearmour->buffered) { 1179 if (!dearmour->eof64) { 1180 ret = decode64(dearmour, 1181 errors, readinfo, cbinfo); 1182 if (ret <= 0) { 1183 return ret; 1184 } 1185 } 1186 if (!dearmour->buffered) { 1187 if (!dearmour->eof64) { 1188 (void) fprintf(stderr, 1189 "armoured_data_reader: bad dearmour eof64\n"); 1190 return 0; 1191 } 1192 if (first) { 1193 dearmour->state = 1194 AT_TRAILER_NAME; 1195 goto reloop; 1196 } 1197 return -1; 1198 } 1199 } 1200 if (!dearmour->buffered) { 1201 (void) fprintf(stderr, 1202 "armoured_data_reader: bad dearmour buffered\n"); 1203 return 0; 1204 } 1205 *dest = dearmour->buffer[--dearmour->buffered]; 1206 ++dest; 1207 --length; 1208 first = 0; 1209 } 1210 if (dearmour->eof64 && !dearmour->buffered) { 1211 dearmour->state = AT_TRAILER_NAME; 1212 } 1213 break; 1214 1215 case AT_TRAILER_NAME: 1216 for (n = 0; n < sizeof(buf) - 1;) { 1217 if ((c = read_char(dearmour, errors, readinfo, 1218 cbinfo, 0)) < 0) { 1219 return -1; 1220 } 1221 if (c == '-') { 1222 goto got_minus2; 1223 } 1224 buf[n++] = c; 1225 } 1226 /* then I guess this wasn't a proper trailer */ 1227 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, 1228 "Bad ASCII armour trailer"); 1229 break; 1230 1231 got_minus2: 1232 buf[n] = '\0'; 1233 1234 if (!set_lastseen_headerline(dearmour, buf, errors)) { 1235 return -1; 1236 } 1237 1238 /* Consume trailing '-' */ 1239 for (count = 1; count < 5; ++count) { 1240 if ((c = read_char(dearmour, errors, readinfo, 1241 cbinfo, 0)) < 0) { 1242 return -1; 1243 } 1244 if (c != '-') { 1245 /* wasn't a trailer after all */ 1246 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, 1247 "Bad ASCII armour trailer (2)"); 1248 } 1249 } 1250 1251 /* Consume final NL */ 1252 if ((c = read_char(dearmour, errors, readinfo, cbinfo, 1253 1)) < 0) { 1254 return -1; 1255 } 1256 if (dearmour->allow_trailing_whitespace) { 1257 if ((c = eat_whitespace(c, dearmour, errors, 1258 readinfo, cbinfo, 1)) < 0) { 1259 return 0; 1260 } 1261 } 1262 if (c != '\n') { 1263 /* wasn't a trailer line after all */ 1264 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, 1265 "Bad ASCII armour trailer (3)"); 1266 } 1267 1268 if (strncmp(buf, "BEGIN ", 6) == 0) { 1269 if (!set_lastseen_headerline(dearmour, buf, 1270 errors)) { 1271 return -1; 1272 } 1273 if ((ret = parse_headers(dearmour, errors, 1274 readinfo, cbinfo)) <= 0) { 1275 return ret; 1276 } 1277 content.u.armour_header.type = buf; 1278 content.u.armour_header.headers = 1279 dearmour->headers; 1280 (void) memset(&dearmour->headers, 0x0, 1281 sizeof(dearmour->headers)); 1282 CALLBACK(OPS_PTAG_CT_ARMOUR_HEADER, cbinfo, 1283 &content); 1284 base64(dearmour); 1285 } else { 1286 content.u.armour_trailer.type = buf; 1287 CALLBACK(OPS_PTAG_CT_ARMOUR_TRAILER, cbinfo, 1288 &content); 1289 dearmour->state = OUTSIDE_BLOCK; 1290 } 1291 break; 1292 } 1293 reloop: 1294 continue; 1295 } 1296 1297 return saved; 1298 } 1299 1300 static void 1301 armoured_data_destroyer(__ops_reader_t *readinfo) 1302 { 1303 free(__ops_reader_get_arg(readinfo)); 1304 } 1305 1306 /** 1307 * \ingroup Core_Readers_Armour 1308 * \brief Pushes dearmouring reader onto stack 1309 * \param parse_info Usual structure containing information about to how to do the parse 1310 * \sa __ops_reader_pop_dearmour() 1311 */ 1312 void 1313 __ops_reader_push_dearmour(__ops_stream_t *parse_info) 1314 /* 1315 * This function originally had these params to cater for packets which 1316 * didn't strictly match the RFC. The initial 0.5 release is only going to 1317 * support strict checking. If it becomes desirable to support loose checking 1318 * of armoured packets and these params are reinstated, parse_headers() must 1319 * be fixed so that these flags work correctly. 1320 * 1321 * // Allow headers in armoured data that are not separated from the data by a 1322 * blank line unsigned without_gap, 1323 * 1324 * // Allow no blank line at the start of armoured data unsigned no_gap, 1325 * 1326 * //Allow armoured data to have trailing whitespace where we strictly would not 1327 * expect it unsigned trailing_whitespace 1328 */ 1329 { 1330 dearmour_t *dearmour; 1331 1332 if ((dearmour = calloc(1, sizeof(*dearmour))) == NULL) { 1333 (void) fprintf(stderr, "__ops_reader_push_dearmour: bad alloc\n"); 1334 } else { 1335 dearmour->seen_nl = 1; 1336 /* 1337 dearmour->allow_headers_without_gap=without_gap; 1338 dearmour->allow_no_gap=no_gap; 1339 dearmour->allow_trailing_whitespace=trailing_whitespace; 1340 */ 1341 dearmour->expect_sig = 0; 1342 dearmour->got_sig = 0; 1343 1344 __ops_reader_push(parse_info, armoured_data_reader, 1345 armoured_data_destroyer, dearmour); 1346 } 1347 } 1348 1349 /** 1350 * \ingroup Core_Readers_Armour 1351 * \brief Pops dearmour reader from stock 1352 * \param stream 1353 * \sa __ops_reader_push_dearmour() 1354 */ 1355 void 1356 __ops_reader_pop_dearmour(__ops_stream_t *stream) 1357 { 1358 dearmour_t *dearmour; 1359 1360 dearmour = __ops_reader_get_arg(__ops_readinfo(stream)); 1361 free(dearmour); 1362 __ops_reader_pop(stream); 1363 } 1364 1365 /**************************************************************************/ 1366 1367 /* this is actually used for *decrypting* */ 1368 typedef struct { 1369 unsigned char decrypted[1024 * 15]; 1370 size_t c; 1371 size_t off; 1372 __ops_crypt_t *decrypt; 1373 __ops_region_t *region; 1374 unsigned prevplain:1; 1375 } encrypted_t; 1376 1377 static int 1378 encrypted_data_reader(void *dest, 1379 size_t length, 1380 __ops_error_t **errors, 1381 __ops_reader_t *readinfo, 1382 __ops_cbdata_t *cbinfo) 1383 { 1384 encrypted_t *encrypted; 1385 char *cdest; 1386 int saved; 1387 1388 encrypted = __ops_reader_get_arg(readinfo); 1389 saved = length; 1390 /* 1391 * V3 MPIs have the count plain and the cipher is reset after each 1392 * count 1393 */ 1394 if (encrypted->prevplain && !readinfo->parent->reading_mpi_len) { 1395 if (!readinfo->parent->reading_v3_secret) { 1396 (void) fprintf(stderr, 1397 "encrypted_data_reader: bad v3 secret\n"); 1398 return -1; 1399 } 1400 encrypted->decrypt->decrypt_resync(encrypted->decrypt); 1401 encrypted->prevplain = 0; 1402 } else if (readinfo->parent->reading_v3_secret && 1403 readinfo->parent->reading_mpi_len) { 1404 encrypted->prevplain = 1; 1405 } 1406 while (length > 0) { 1407 if (encrypted->c) { 1408 unsigned n; 1409 1410 /* 1411 * if we are reading v3 we should never read 1412 * more than we're asked for */ 1413 if (length < encrypted->c && 1414 (readinfo->parent->reading_v3_secret || 1415 readinfo->parent->exact_read)) { 1416 (void) fprintf(stderr, 1417 "encrypted_data_reader: bad v3 read\n"); 1418 return 0; 1419 } 1420 n = MIN(length, encrypted->c); 1421 (void) memcpy(dest, 1422 encrypted->decrypted + encrypted->off, n); 1423 encrypted->c -= n; 1424 encrypted->off += n; 1425 length -= n; 1426 cdest = dest; 1427 cdest += n; 1428 dest = cdest; 1429 } else { 1430 unsigned n = encrypted->region->length; 1431 unsigned char buffer[1024]; 1432 1433 if (!n) { 1434 return -1; 1435 } 1436 if (!encrypted->region->indeterminate) { 1437 n -= encrypted->region->readc; 1438 if (n == 0) { 1439 return saved - length; 1440 } 1441 if (n > sizeof(buffer)) { 1442 n = sizeof(buffer); 1443 } 1444 } else { 1445 n = sizeof(buffer); 1446 } 1447 1448 /* 1449 * we can only read as much as we're asked for 1450 * in v3 keys because they're partially 1451 * unencrypted! */ 1452 if ((readinfo->parent->reading_v3_secret || 1453 readinfo->parent->exact_read) && n > length) { 1454 n = length; 1455 } 1456 1457 if (!__ops_stacked_limited_read(buffer, n, 1458 encrypted->region, errors, readinfo, cbinfo)) { 1459 return -1; 1460 } 1461 if (!readinfo->parent->reading_v3_secret || 1462 !readinfo->parent->reading_mpi_len) { 1463 encrypted->c = 1464 __ops_decrypt_se_ip(encrypted->decrypt, 1465 encrypted->decrypted, buffer, n); 1466 1467 if (__ops_get_debug_level(__FILE__)) { 1468 int i; 1469 1470 (void) fprintf(stderr, 1471 "READING:\nencrypted: "); 1472 for (i = 0; i < 16; i++) { 1473 (void) fprintf(stderr, 1474 "%2x ", buffer[i]); 1475 } 1476 (void) fprintf(stderr, "\ndecrypted: "); 1477 for (i = 0; i < 16; i++) { 1478 (void) fprintf(stderr, "%2x ", 1479 encrypted->decrypted[i]); 1480 } 1481 (void) fprintf(stderr, "\n"); 1482 } 1483 } else { 1484 (void) memcpy( 1485 &encrypted->decrypted[encrypted->off], buffer, n); 1486 encrypted->c = n; 1487 } 1488 1489 if (encrypted->c == 0) { 1490 (void) fprintf(stderr, 1491 "encrypted_data_reader: 0 decrypted count\n"); 1492 return 0; 1493 } 1494 1495 encrypted->off = 0; 1496 } 1497 } 1498 1499 return saved; 1500 } 1501 1502 static void 1503 encrypted_data_destroyer(__ops_reader_t *readinfo) 1504 { 1505 free(__ops_reader_get_arg(readinfo)); 1506 } 1507 1508 /** 1509 * \ingroup Core_Readers_SE 1510 * \brief Pushes decryption reader onto stack 1511 * \sa __ops_reader_pop_decrypt() 1512 */ 1513 void 1514 __ops_reader_push_decrypt(__ops_stream_t *stream, __ops_crypt_t *decrypt, 1515 __ops_region_t *region) 1516 { 1517 encrypted_t *encrypted; 1518 1519 if ((encrypted = calloc(1, sizeof(*encrypted))) == NULL) { 1520 (void) fprintf(stderr, "__ops_reader_push_decrypted: bad alloc\n"); 1521 } else { 1522 encrypted->decrypt = decrypt; 1523 encrypted->region = region; 1524 __ops_decrypt_init(encrypted->decrypt); 1525 __ops_reader_push(stream, encrypted_data_reader, 1526 encrypted_data_destroyer, encrypted); 1527 } 1528 } 1529 1530 /** 1531 * \ingroup Core_Readers_Encrypted 1532 * \brief Pops decryption reader from stack 1533 * \sa __ops_reader_push_decrypt() 1534 */ 1535 void 1536 __ops_reader_pop_decrypt(__ops_stream_t *stream) 1537 { 1538 encrypted_t *encrypted; 1539 1540 encrypted = __ops_reader_get_arg(__ops_readinfo(stream)); 1541 encrypted->decrypt->decrypt_finish(encrypted->decrypt); 1542 free(encrypted); 1543 __ops_reader_pop(stream); 1544 } 1545 1546 /**************************************************************************/ 1547 1548 typedef struct { 1549 /* boolean: 0 once we've done the preamble/MDC checks */ 1550 /* and are reading from the plaintext */ 1551 int passed_checks; 1552 unsigned char *plaintext; 1553 size_t plaintext_available; 1554 size_t plaintext_offset; 1555 __ops_region_t *region; 1556 __ops_crypt_t *decrypt; 1557 } decrypt_se_ip_t; 1558 1559 /* 1560 Gets entire SE_IP data packet. 1561 Verifies leading preamble 1562 Verifies trailing MDC packet 1563 Then passes up plaintext as requested 1564 */ 1565 static int 1566 se_ip_data_reader(void *dest_, 1567 size_t len, 1568 __ops_error_t **errors, 1569 __ops_reader_t *readinfo, 1570 __ops_cbdata_t *cbinfo) 1571 { 1572 decrypt_se_ip_t *se_ip; 1573 __ops_region_t decrypted_region; 1574 unsigned int n = 0; 1575 1576 se_ip = __ops_reader_get_arg(readinfo); 1577 if (!se_ip->passed_checks) { 1578 unsigned char *buf = NULL; 1579 unsigned char hashed[OPS_SHA1_HASH_SIZE]; 1580 unsigned char *preamble; 1581 unsigned char *plaintext; 1582 unsigned char *mdc; 1583 unsigned char *mdc_hash; 1584 __ops_hash_t hash; 1585 size_t b; 1586 size_t sz_preamble; 1587 size_t sz_mdc_hash; 1588 size_t sz_mdc; 1589 size_t sz_plaintext; 1590 1591 __ops_hash_any(&hash, OPS_HASH_SHA1); 1592 if (!hash.init(&hash)) { 1593 (void) fprintf(stderr, 1594 "se_ip_data_reader: can't init hash\n"); 1595 return -1; 1596 } 1597 1598 __ops_init_subregion(&decrypted_region, NULL); 1599 decrypted_region.length = 1600 se_ip->region->length - se_ip->region->readc; 1601 if ((buf = calloc(1, decrypted_region.length)) == NULL) { 1602 (void) fprintf(stderr, "se_ip_data_reader: bad alloc\n"); 1603 return -1; 1604 } 1605 1606 /* read entire SE IP packet */ 1607 if (!__ops_stacked_limited_read(buf, decrypted_region.length, 1608 &decrypted_region, errors, readinfo, cbinfo)) { 1609 free(buf); 1610 return -1; 1611 } 1612 if (__ops_get_debug_level(__FILE__)) { 1613 unsigned i; 1614 1615 fprintf(stderr, "\n\nentire SE IP packet (len=%d):\n", 1616 decrypted_region.length); 1617 for (i = 0; i < decrypted_region.length; i++) { 1618 fprintf(stderr, "0x%02x ", buf[i]); 1619 if (!((i + 1) % 8)) 1620 fprintf(stderr, "\n"); 1621 } 1622 fprintf(stderr, "\n\n"); 1623 } 1624 /* verify leading preamble */ 1625 1626 if (__ops_get_debug_level(__FILE__)) { 1627 unsigned i; 1628 1629 fprintf(stderr, "\npreamble: "); 1630 for (i = 0; i < se_ip->decrypt->blocksize + 2; i++) 1631 fprintf(stderr, " 0x%02x", buf[i]); 1632 fprintf(stderr, "\n"); 1633 } 1634 b = se_ip->decrypt->blocksize; 1635 if (buf[b - 2] != buf[b] || buf[b - 1] != buf[b + 1]) { 1636 fprintf(stderr, 1637 "Bad symmetric decrypt (%02x%02x vs %02x%02x)\n", 1638 buf[b - 2], buf[b - 1], buf[b], buf[b + 1]); 1639 OPS_ERROR(errors, OPS_E_PROTO_BAD_SYMMETRIC_DECRYPT, 1640 "Bad symmetric decrypt when parsing SE IP packet"); 1641 free(buf); 1642 return -1; 1643 } 1644 /* Verify trailing MDC hash */ 1645 1646 sz_preamble = se_ip->decrypt->blocksize + 2; 1647 sz_mdc_hash = OPS_SHA1_HASH_SIZE; 1648 sz_mdc = 1 + 1 + sz_mdc_hash; 1649 sz_plaintext = (decrypted_region.length - sz_preamble) - sz_mdc; 1650 1651 preamble = buf; 1652 plaintext = buf + sz_preamble; 1653 mdc = plaintext + sz_plaintext; 1654 mdc_hash = mdc + 2; 1655 1656 if (__ops_get_debug_level(__FILE__)) { 1657 unsigned i; 1658 1659 fprintf(stderr, "\nplaintext (len=%" PRIsize "u): ", 1660 sz_plaintext); 1661 for (i = 0; i < sz_plaintext; i++) 1662 fprintf(stderr, " 0x%02x", plaintext[i]); 1663 fprintf(stderr, "\n"); 1664 1665 fprintf(stderr, "\nmdc (len=%" PRIsize "u): ", sz_mdc); 1666 for (i = 0; i < sz_mdc; i++) 1667 fprintf(stderr, " 0x%02x", mdc[i]); 1668 fprintf(stderr, "\n"); 1669 } 1670 __ops_calc_mdc_hash(preamble, sz_preamble, plaintext, 1671 sz_plaintext, hashed); 1672 1673 if (memcmp(mdc_hash, hashed, OPS_SHA1_HASH_SIZE) != 0) { 1674 OPS_ERROR(errors, OPS_E_V_BAD_HASH, 1675 "Bad hash in MDC packet"); 1676 free(buf); 1677 return 0; 1678 } 1679 /* all done with the checks */ 1680 /* now can start reading from the plaintext */ 1681 if (se_ip->plaintext) { 1682 (void) fprintf(stderr, 1683 "se_ip_data_reader: bad plaintext\n"); 1684 return 0; 1685 } 1686 if ((se_ip->plaintext = calloc(1, sz_plaintext)) == NULL) { 1687 (void) fprintf(stderr, 1688 "se_ip_data_reader: bad alloc\n"); 1689 return 0; 1690 } 1691 memcpy(se_ip->plaintext, plaintext, sz_plaintext); 1692 se_ip->plaintext_available = sz_plaintext; 1693 1694 se_ip->passed_checks = 1; 1695 1696 free(buf); 1697 } 1698 n = len; 1699 if (n > se_ip->plaintext_available) { 1700 n = se_ip->plaintext_available; 1701 } 1702 1703 memcpy(dest_, se_ip->plaintext + se_ip->plaintext_offset, n); 1704 se_ip->plaintext_available -= n; 1705 se_ip->plaintext_offset += n; 1706 /* len -= n; - not used at all, for info only */ 1707 1708 return n; 1709 } 1710 1711 static void 1712 se_ip_data_destroyer(__ops_reader_t *readinfo) 1713 { 1714 decrypt_se_ip_t *se_ip; 1715 1716 se_ip = __ops_reader_get_arg(readinfo); 1717 free(se_ip->plaintext); 1718 free(se_ip); 1719 } 1720 1721 /** 1722 \ingroup Internal_Readers_SEIP 1723 */ 1724 void 1725 __ops_reader_push_se_ip_data(__ops_stream_t *stream, __ops_crypt_t *decrypt, 1726 __ops_region_t * region) 1727 { 1728 decrypt_se_ip_t *se_ip; 1729 1730 if ((se_ip = calloc(1, sizeof(*se_ip))) == NULL) { 1731 (void) fprintf(stderr, "__ops_reader_push_se_ip_data: bad alloc\n"); 1732 } else { 1733 se_ip->region = region; 1734 se_ip->decrypt = decrypt; 1735 __ops_reader_push(stream, se_ip_data_reader, se_ip_data_destroyer, 1736 se_ip); 1737 } 1738 } 1739 1740 /** 1741 \ingroup Internal_Readers_SEIP 1742 */ 1743 void 1744 __ops_reader_pop_se_ip_data(__ops_stream_t *stream) 1745 { 1746 /* 1747 * decrypt_se_ip_t 1748 * *se_ip=__ops_reader_get_arg(__ops_readinfo(stream)); 1749 */ 1750 /* free(se_ip); */ 1751 __ops_reader_pop(stream); 1752 } 1753 1754 /**************************************************************************/ 1755 1756 /** Arguments for reader_fd 1757 */ 1758 typedef struct mmap_reader_t { 1759 void *mem; /* memory mapped file */ 1760 uint64_t size; /* size of file */ 1761 uint64_t offset; /* current offset in file */ 1762 int fd; /* file descriptor */ 1763 } mmap_reader_t; 1764 1765 1766 /** 1767 * \ingroup Core_Readers 1768 * 1769 * __ops_reader_fd() attempts to read up to "plength" bytes from the file 1770 * descriptor in "parse_info" into the buffer starting at "dest" using the 1771 * rules contained in "flags" 1772 * 1773 * \param dest Pointer to previously allocated buffer 1774 * \param plength Number of bytes to try to read 1775 * \param flags Rules about reading to use 1776 * \param readinfo Reader info 1777 * \param cbinfo Callback info 1778 * 1779 * \return n Number of bytes read 1780 * 1781 * OPS_R_EARLY_EOF and OPS_R_ERROR push errors on the stack 1782 */ 1783 static int 1784 fd_reader(void *dest, size_t length, __ops_error_t **errors, 1785 __ops_reader_t *readinfo, __ops_cbdata_t *cbinfo) 1786 { 1787 mmap_reader_t *reader = __ops_reader_get_arg(readinfo); 1788 int n = read(reader->fd, dest, length); 1789 1790 __OPS_USED(cbinfo); 1791 if (n == 0) 1792 return 0; 1793 if (n < 0) { 1794 OPS_SYSTEM_ERROR_1(errors, OPS_E_R_READ_FAILED, "read", 1795 "file descriptor %d", reader->fd); 1796 return -1; 1797 } 1798 return n; 1799 } 1800 1801 static void 1802 reader_fd_destroyer(__ops_reader_t *readinfo) 1803 { 1804 free(__ops_reader_get_arg(readinfo)); 1805 } 1806 1807 /** 1808 \ingroup Core_Readers_First 1809 \brief Starts stack with file reader 1810 */ 1811 1812 void 1813 __ops_reader_set_fd(__ops_stream_t *stream, int fd) 1814 { 1815 mmap_reader_t *reader; 1816 1817 if ((reader = calloc(1, sizeof(*reader))) == NULL) { 1818 (void) fprintf(stderr, "__ops_reader_set_fd: bad alloc\n"); 1819 } else { 1820 reader->fd = fd; 1821 __ops_reader_set(stream, fd_reader, reader_fd_destroyer, reader); 1822 } 1823 } 1824 1825 /**************************************************************************/ 1826 1827 typedef struct { 1828 const unsigned char *buffer; 1829 size_t length; 1830 size_t offset; 1831 } reader_mem_t; 1832 1833 static int 1834 mem_reader(void *dest, size_t length, __ops_error_t **errors, 1835 __ops_reader_t *readinfo, __ops_cbdata_t *cbinfo) 1836 { 1837 reader_mem_t *reader = __ops_reader_get_arg(readinfo); 1838 unsigned n; 1839 1840 __OPS_USED(cbinfo); 1841 __OPS_USED(errors); 1842 1843 if (reader->offset + length > reader->length) 1844 n = reader->length - reader->offset; 1845 else 1846 n = length; 1847 1848 if (n == 0) 1849 return 0; 1850 1851 memcpy(dest, reader->buffer + reader->offset, n); 1852 reader->offset += n; 1853 1854 return n; 1855 } 1856 1857 static void 1858 mem_destroyer(__ops_reader_t *readinfo) 1859 { 1860 free(__ops_reader_get_arg(readinfo)); 1861 } 1862 1863 /** 1864 \ingroup Core_Readers_First 1865 \brief Starts stack with memory reader 1866 */ 1867 1868 void 1869 __ops_reader_set_memory(__ops_stream_t *stream, const void *buffer, 1870 size_t length) 1871 { 1872 reader_mem_t *mem; 1873 1874 if ((mem = calloc(1, sizeof(*mem))) == NULL) { 1875 (void) fprintf(stderr, "__ops_reader_set_memory: bad alloc\n"); 1876 } else { 1877 mem->buffer = buffer; 1878 mem->length = length; 1879 mem->offset = 0; 1880 __ops_reader_set(stream, mem_reader, mem_destroyer, mem); 1881 } 1882 } 1883 1884 /**************************************************************************/ 1885 1886 /** 1887 \ingroup Core_Writers 1888 \brief Create and initialise output and mem; Set for writing to mem 1889 \param output Address where new output pointer will be set 1890 \param mem Address when new mem pointer will be set 1891 \param bufsz Initial buffer size (will automatically be increased when necessary) 1892 \note It is the caller's responsiblity to free output and mem. 1893 \sa __ops_teardown_memory_write() 1894 */ 1895 void 1896 __ops_setup_memory_write(__ops_output_t **output, __ops_memory_t **mem, size_t bufsz) 1897 { 1898 /* 1899 * initialise needed structures for writing to memory 1900 */ 1901 1902 *output = __ops_output_new(); 1903 *mem = __ops_memory_new(); 1904 1905 __ops_memory_init(*mem, bufsz); 1906 1907 __ops_writer_set_memory(*output, *mem); 1908 } 1909 1910 /** 1911 \ingroup Core_Writers 1912 \brief Closes writer and frees output and mem 1913 \param output 1914 \param mem 1915 \sa __ops_setup_memory_write() 1916 */ 1917 void 1918 __ops_teardown_memory_write(__ops_output_t *output, __ops_memory_t *mem) 1919 { 1920 __ops_writer_close(output);/* new */ 1921 __ops_output_delete(output); 1922 __ops_memory_free(mem); 1923 } 1924 1925 /** 1926 \ingroup Core_Readers 1927 \brief Create parse_info and sets to read from memory 1928 \param stream Address where new parse_info will be set 1929 \param mem Memory to read from 1930 \param arg Reader-specific arg 1931 \param callback Callback to use with reader 1932 \param accumulate Set if we need to accumulate as we read. (Usually 0 unless doing signature verification) 1933 \note It is the caller's responsiblity to free parse_info 1934 \sa __ops_teardown_memory_read() 1935 */ 1936 void 1937 __ops_setup_memory_read(__ops_io_t *io, 1938 __ops_stream_t **stream, 1939 __ops_memory_t *mem, 1940 void *vp, 1941 __ops_cb_ret_t callback(const __ops_packet_t *, 1942 __ops_cbdata_t *), 1943 unsigned accumulate) 1944 { 1945 *stream = __ops_new(sizeof(**stream)); 1946 (*stream)->io = (*stream)->cbinfo.io = io; 1947 __ops_set_callback(*stream, callback, vp); 1948 __ops_reader_set_memory(*stream, 1949 __ops_mem_data(mem), 1950 __ops_mem_len(mem)); 1951 if (accumulate) { 1952 (*stream)->readinfo.accumulate = 1; 1953 } 1954 } 1955 1956 /** 1957 \ingroup Core_Readers 1958 \brief Frees stream and mem 1959 \param stream 1960 \param mem 1961 \sa __ops_setup_memory_read() 1962 */ 1963 void 1964 __ops_teardown_memory_read(__ops_stream_t *stream, __ops_memory_t *mem) 1965 { 1966 __ops_stream_delete(stream); 1967 __ops_memory_free(mem); 1968 } 1969 1970 /** 1971 \ingroup Core_Writers 1972 \brief Create and initialise output and mem; Set for writing to file 1973 \param output Address where new output pointer will be set 1974 \param filename File to write to 1975 \param allow_overwrite Allows file to be overwritten, if set. 1976 \return Newly-opened file descriptor 1977 \note It is the caller's responsiblity to free output and to close fd. 1978 \sa __ops_teardown_file_write() 1979 */ 1980 int 1981 __ops_setup_file_write(__ops_output_t **output, const char *filename, 1982 unsigned allow_overwrite) 1983 { 1984 int fd = 0; 1985 int flags = 0; 1986 1987 /* 1988 * initialise needed structures for writing to file 1989 */ 1990 if (filename == NULL) { 1991 /* write to stdout */ 1992 fd = STDOUT_FILENO; 1993 } else { 1994 flags = O_WRONLY | O_CREAT; 1995 if (allow_overwrite) 1996 flags |= O_TRUNC; 1997 else 1998 flags |= O_EXCL; 1999 #ifdef O_BINARY 2000 flags |= O_BINARY; 2001 #endif 2002 fd = open(filename, flags, 0600); 2003 if (fd < 0) { 2004 perror(filename); 2005 return fd; 2006 } 2007 } 2008 *output = __ops_output_new(); 2009 __ops_writer_set_fd(*output, fd); 2010 return fd; 2011 } 2012 2013 /** 2014 \ingroup Core_Writers 2015 \brief Closes writer, frees info, closes fd 2016 \param output 2017 \param fd 2018 */ 2019 void 2020 __ops_teardown_file_write(__ops_output_t *output, int fd) 2021 { 2022 __ops_writer_close(output); 2023 close(fd); 2024 __ops_output_delete(output); 2025 } 2026 2027 /** 2028 \ingroup Core_Writers 2029 \brief As __ops_setup_file_write, but appends to file 2030 */ 2031 int 2032 __ops_setup_file_append(__ops_output_t **output, const char *filename) 2033 { 2034 int fd; 2035 /* 2036 * initialise needed structures for writing to file 2037 */ 2038 2039 #ifdef O_BINARY 2040 fd = open(filename, O_WRONLY | O_APPEND | O_BINARY, 0600); 2041 #else 2042 fd = open(filename, O_WRONLY | O_APPEND, 0600); 2043 #endif 2044 if (fd < 0) { 2045 perror(filename); 2046 return fd; 2047 } 2048 *output = __ops_output_new(); 2049 2050 __ops_writer_set_fd(*output, fd); 2051 2052 return fd; 2053 } 2054 2055 /** 2056 \ingroup Core_Writers 2057 \brief As __ops_teardown_file_write() 2058 */ 2059 void 2060 __ops_teardown_file_append(__ops_output_t *output, int fd) 2061 { 2062 __ops_teardown_file_write(output, fd); 2063 } 2064 2065 /** 2066 \ingroup Core_Readers 2067 \brief Creates parse_info, opens file, and sets to read from file 2068 \param stream Address where new parse_info will be set 2069 \param filename Name of file to read 2070 \param vp Reader-specific arg 2071 \param callback Callback to use when reading 2072 \param accumulate Set if we need to accumulate as we read. (Usually 0 unless doing signature verification) 2073 \note It is the caller's responsiblity to free parse_info and to close fd 2074 \sa __ops_teardown_file_read() 2075 */ 2076 int 2077 __ops_setup_file_read(__ops_io_t *io, 2078 __ops_stream_t **stream, 2079 const char *filename, 2080 void *vp, 2081 __ops_cb_ret_t callback(const __ops_packet_t *, 2082 __ops_cbdata_t *), 2083 unsigned accumulate) 2084 { 2085 int fd; 2086 2087 #ifdef O_BINARY 2088 fd = open(filename, O_RDONLY | O_BINARY); 2089 #else 2090 fd = open(filename, O_RDONLY); 2091 #endif 2092 if (fd < 0) { 2093 (void) fprintf(io->errs, "can't open \"%s\"\n", filename); 2094 return fd; 2095 } 2096 *stream = __ops_new(sizeof(**stream)); 2097 (*stream)->io = (*stream)->cbinfo.io = io; 2098 __ops_set_callback(*stream, callback, vp); 2099 #ifdef USE_MMAP_FOR_FILES 2100 __ops_reader_set_mmap(*stream, fd); 2101 #else 2102 __ops_reader_set_fd(*stream, fd); 2103 #endif 2104 if (accumulate) { 2105 (*stream)->readinfo.accumulate = 1; 2106 } 2107 return fd; 2108 } 2109 2110 /** 2111 \ingroup Core_Readers 2112 \brief Frees stream and closes fd 2113 \param stream 2114 \param fd 2115 \sa __ops_setup_file_read() 2116 */ 2117 void 2118 __ops_teardown_file_read(__ops_stream_t *stream, int fd) 2119 { 2120 close(fd); 2121 __ops_stream_delete(stream); 2122 } 2123 2124 __ops_cb_ret_t 2125 litdata_cb(const __ops_packet_t *pkt, __ops_cbdata_t *cbinfo) 2126 { 2127 const __ops_contents_t *content = &pkt->u; 2128 2129 if (__ops_get_debug_level(__FILE__)) { 2130 printf("litdata_cb: "); 2131 __ops_print_packet(&cbinfo->printstate, pkt); 2132 } 2133 /* Read data from packet into static buffer */ 2134 switch (pkt->tag) { 2135 case OPS_PTAG_CT_LITDATA_BODY: 2136 /* if writer enabled, use it */ 2137 if (cbinfo->output) { 2138 if (__ops_get_debug_level(__FILE__)) { 2139 printf("litdata_cb: length is %u\n", 2140 content->litdata_body.length); 2141 } 2142 __ops_write(cbinfo->output, 2143 content->litdata_body.data, 2144 content->litdata_body.length); 2145 } 2146 break; 2147 2148 case OPS_PTAG_CT_LITDATA_HEADER: 2149 /* ignore */ 2150 break; 2151 2152 default: 2153 break; 2154 } 2155 2156 return OPS_RELEASE_MEMORY; 2157 } 2158 2159 __ops_cb_ret_t 2160 pk_sesskey_cb(const __ops_packet_t *pkt, __ops_cbdata_t *cbinfo) 2161 { 2162 const __ops_contents_t *content = &pkt->u; 2163 unsigned from; 2164 __ops_io_t *io; 2165 2166 io = cbinfo->io; 2167 if (__ops_get_debug_level(__FILE__)) { 2168 __ops_print_packet(&cbinfo->printstate, pkt); 2169 } 2170 /* Read data from packet into static buffer */ 2171 switch (pkt->tag) { 2172 case OPS_PTAG_CT_PK_SESSION_KEY: 2173 if (__ops_get_debug_level(__FILE__)) { 2174 printf("OPS_PTAG_CT_PK_SESSION_KEY\n"); 2175 } 2176 if (!cbinfo->cryptinfo.keyring) { 2177 (void) fprintf(io->errs, 2178 "pk_sesskey_cb: bad keyring\n"); 2179 return (__ops_cb_ret_t)0; 2180 } 2181 from = 0; 2182 cbinfo->cryptinfo.keydata = 2183 __ops_getkeybyid(io, cbinfo->cryptinfo.keyring, 2184 content->pk_sesskey.key_id, &from); 2185 if (!cbinfo->cryptinfo.keydata) { 2186 break; 2187 } 2188 break; 2189 2190 default: 2191 break; 2192 } 2193 2194 return OPS_RELEASE_MEMORY; 2195 } 2196 2197 /** 2198 \ingroup Core_Callbacks 2199 2200 \brief Callback to get secret key, decrypting if necessary. 2201 2202 @verbatim 2203 This callback does the following: 2204 * finds the session key in the keyring 2205 * gets a passphrase if required 2206 * decrypts the secret key, if necessary 2207 * sets the seckey in the content struct 2208 @endverbatim 2209 */ 2210 2211 __ops_cb_ret_t 2212 get_seckey_cb(const __ops_packet_t *pkt, __ops_cbdata_t *cbinfo) 2213 { 2214 const __ops_contents_t *content = &pkt->u; 2215 const __ops_seckey_t *secret; 2216 const __ops_key_t *keypair; 2217 unsigned from; 2218 __ops_io_t *io; 2219 2220 io = cbinfo->io; 2221 if (__ops_get_debug_level(__FILE__)) { 2222 __ops_print_packet(&cbinfo->printstate, pkt); 2223 } 2224 switch (pkt->tag) { 2225 case OPS_GET_SECKEY: 2226 from = 0; 2227 cbinfo->cryptinfo.keydata = 2228 __ops_getkeybyid(io, cbinfo->cryptinfo.keyring, 2229 content->get_seckey.pk_sesskey->key_id, 2230 &from); 2231 if (!cbinfo->cryptinfo.keydata || 2232 !__ops_is_key_secret(cbinfo->cryptinfo.keydata)) { 2233 return (__ops_cb_ret_t)0; 2234 } 2235 2236 keypair = cbinfo->cryptinfo.keydata; 2237 do { 2238 /* print out the user id */ 2239 __ops_print_keydata(io, keypair, "pub", &keypair->key.pubkey); 2240 /* now decrypt key */ 2241 secret = __ops_decrypt_seckey(keypair, NULL); /* XXX - agc */ 2242 if (secret == NULL) { 2243 (void) fprintf(io->errs, "Bad passphrase\n"); 2244 } 2245 } while (secret == NULL); 2246 *content->get_seckey.seckey = secret; 2247 break; 2248 2249 default: 2250 break; 2251 } 2252 2253 return OPS_RELEASE_MEMORY; 2254 } 2255 2256 /** 2257 \ingroup HighLevel_Callbacks 2258 \brief Callback to use when you need to prompt user for passphrase 2259 \param contents 2260 \param cbinfo 2261 */ 2262 __ops_cb_ret_t 2263 get_passphrase_cb(const __ops_packet_t *pkt, __ops_cbdata_t *cbinfo) 2264 { 2265 const __ops_contents_t *content = &pkt->u; 2266 __ops_io_t *io; 2267 2268 io = cbinfo->io; 2269 if (__ops_get_debug_level(__FILE__)) { 2270 __ops_print_packet(&cbinfo->printstate, pkt); 2271 } 2272 if (cbinfo->cryptinfo.keydata == NULL) { 2273 (void) fprintf(io->errs, "get_passphrase_cb: NULL keydata\n"); 2274 } else { 2275 __ops_print_keydata(io, cbinfo->cryptinfo.keydata, "pub", 2276 &cbinfo->cryptinfo.keydata->key.pubkey); 2277 } 2278 switch (pkt->tag) { 2279 case OPS_GET_PASSPHRASE: 2280 *(content->skey_passphrase.passphrase) = 2281 strdup(getpass("netpgp passphrase: ")); 2282 return OPS_KEEP_MEMORY; 2283 default: 2284 break; 2285 } 2286 return OPS_RELEASE_MEMORY; 2287 } 2288 2289 unsigned 2290 __ops_reader_set_accumulate(__ops_stream_t *stream, unsigned state) 2291 { 2292 return stream->readinfo.accumulate = state; 2293 } 2294 2295 /**************************************************************************/ 2296 2297 static int 2298 hash_reader(void *dest, 2299 size_t length, 2300 __ops_error_t **errors, 2301 __ops_reader_t *readinfo, 2302 __ops_cbdata_t *cbinfo) 2303 { 2304 __ops_hash_t *hash = __ops_reader_get_arg(readinfo); 2305 int r; 2306 2307 r = __ops_stacked_read(dest, length, errors, readinfo, cbinfo); 2308 if (r <= 0) { 2309 return r; 2310 } 2311 hash->add(hash, dest, (unsigned)r); 2312 return r; 2313 } 2314 2315 /** 2316 \ingroup Internal_Readers_Hash 2317 \brief Push hashed data reader on stack 2318 */ 2319 void 2320 __ops_reader_push_hash(__ops_stream_t *stream, __ops_hash_t *hash) 2321 { 2322 if (!hash->init(hash)) { 2323 (void) fprintf(stderr, "__ops_reader_push_hash: can't init hash\n"); 2324 /* just continue and die */ 2325 /* XXX - agc - no way to return failure */ 2326 } 2327 __ops_reader_push(stream, hash_reader, NULL, hash); 2328 } 2329 2330 /** 2331 \ingroup Internal_Readers_Hash 2332 \brief Pop hashed data reader from stack 2333 */ 2334 void 2335 __ops_reader_pop_hash(__ops_stream_t *stream) 2336 { 2337 __ops_reader_pop(stream); 2338 } 2339 2340 /* read memory from the previously mmap-ed file */ 2341 static int 2342 mmap_reader(void *dest, size_t length, __ops_error_t **errors, 2343 __ops_reader_t *readinfo, __ops_cbdata_t *cbinfo) 2344 { 2345 mmap_reader_t *mem = __ops_reader_get_arg(readinfo); 2346 unsigned n; 2347 char *cmem = mem->mem; 2348 2349 __OPS_USED(errors); 2350 __OPS_USED(cbinfo); 2351 n = MIN(length, (unsigned)(mem->size - mem->offset)); 2352 if (n > 0) { 2353 (void) memcpy(dest, &cmem[(int)mem->offset], (unsigned)n); 2354 mem->offset += n; 2355 } 2356 return n; 2357 } 2358 2359 /* tear down the mmap, close the fd */ 2360 static void 2361 mmap_destroyer(__ops_reader_t *readinfo) 2362 { 2363 mmap_reader_t *mem = __ops_reader_get_arg(readinfo); 2364 2365 (void) munmap(mem->mem, (unsigned)mem->size); 2366 (void) close(mem->fd); 2367 free(__ops_reader_get_arg(readinfo)); 2368 } 2369 2370 /* set up the file to use mmap-ed memory if available, file IO otherwise */ 2371 void 2372 __ops_reader_set_mmap(__ops_stream_t *stream, int fd) 2373 { 2374 mmap_reader_t *mem; 2375 struct stat st; 2376 2377 if (fstat(fd, &st) != 0) { 2378 (void) fprintf(stderr, "__ops_reader_set_mmap: can't fstat\n"); 2379 } else if ((mem = calloc(1, sizeof(*mem))) == NULL) { 2380 (void) fprintf(stderr, "__ops_reader_set_mmap: bad alloc\n"); 2381 } else { 2382 mem->size = (uint64_t)st.st_size; 2383 mem->offset = 0; 2384 mem->fd = fd; 2385 mem->mem = mmap(NULL, (size_t)st.st_size, PROT_READ, 2386 MAP_PRIVATE | MAP_FILE, fd, 0); 2387 if (mem->mem == MAP_FAILED) { 2388 __ops_reader_set(stream, fd_reader, reader_fd_destroyer, 2389 mem); 2390 } else { 2391 __ops_reader_set(stream, mmap_reader, mmap_destroyer, 2392 mem); 2393 } 2394 } 2395 } 2396