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