1 /* armor.c - ASCII/binary encoding/decoding based partly on 2 PEM RFC1113 and MIME standards. 3 PGP: Pretty Good(tm) Privacy - public key cryptography for the masses. 4 5 (c) Copyright 1990-1996 by Philip Zimmermann. All rights reserved. 6 The author assumes no liability for damages resulting from the use 7 of this software, even if the damage results from defects in this 8 software. No warranty is expressed or implied. 9 10 Note that while most PGP source modules bear Philip Zimmermann's 11 copyright notice, many of them have been revised or entirely written 12 by contributors who frequently failed to put their names in their 13 code. Code that has been incorporated into PGP from other authors 14 was either originally published in the public domain or is used with 15 permission from the various authors. 16 17 PGP is available for free to the public under certain restrictions. 18 See the PGP User's Guide (included in the release package) for 19 important information about licensing, patent restrictions on 20 certain algorithms, trademarks, copyrights, and export controls. 21 */ 22 #include <ctype.h> 23 #include <stdio.h> 24 #include <string.h> 25 #include "mpilib.h" 26 #include "fileio.h" 27 #include "mpiio.h" 28 #include "language.h" 29 #include "pgp.h" 30 #include "charset.h" 31 #include "crypto.h" 32 #include "armor.h" 33 #include "keymgmt.h" 34 #ifdef MACTC5 35 #include "Macutil2.h" 36 #include "Macutil3.h" 37 #endif 38 39 static int darmor_file(char *infile, char *outfile); 40 static crcword crchware(byte ch, crcword poly, crcword accum); 41 static int armordecode(FILE * in, FILE * out, int *warned); 42 static void mk_crctbl(crcword poly); 43 static boolean is_armorfile(char *infile); 44 45 /* Begin ASCII armor routines. 46 This converts a binary file into printable ASCII characters, in a 47 radix-64 form mostly compatible with the MIME format. 48 This makes it easier to send encrypted files over a 7-bit channel. 49 */ 50 51 /* Index this array by a 6 bit value to get the character corresponding 52 * to that value. 53 */ 54 static 55 unsigned char bintoasc[] = 56 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 57 58 /* Index this array by a 7 bit value to get the 6-bit binary field 59 * corresponding to that value. Any illegal characters return high bit set. 60 */ 61 static 62 unsigned char asctobin[] = 63 { 64 #ifdef EBCDIC 65 128,128,128,128,128,128,128,128, 128,128,128,128,128,128,128,128, 66 128,128,128,128,128,128,128,128, 128,128,128,128,128,128,128,128, 67 128,128,128,128,128,128,128,128, 128,128,128,128,128,128,128,128, 68 128,128,128,128,128,128,128,128, 128,128,128,128,128,128,128,128, 69 128,128,128,128,128,128,128,128, 128,128,128,128,128,128, 62,128, 70 128,128,128,128,128,128,128,128, 128,128,128,128,128,128,128,128, 71 128, 63,128,128,128,128,128,128, 128,128,128,128,128,128,128,128, 72 128,128,128,128,128,128,128,128, 128,128,128,128,128,128,128,128, 73 128, 26, 27, 28, 29, 30, 31, 32, 33, 34,128,128,128,128,128,128, 74 128, 35, 36, 37, 38, 39, 40, 41, 42, 43,128,128,128,128,128,128, 75 128,128, 44, 45, 46, 47, 48, 49, 50, 51,128,128,128,128,128,128, 76 128,128,128,128,128,128,128,128, 128,128,128,128,128,128,128,128, 77 128, 0, 1, 2, 3, 4, 5, 6, 7, 8,128,128,128,128,128,128, 78 128, 9, 10, 11, 12, 13, 14, 15, 16, 17,128,128,128,128,128,128, 79 128,128, 18, 19, 20, 21, 22, 23, 24, 25,128,128,128,128,128,128, 80 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,128,128,128,128,128,128 81 #else 82 0200, 0200, 0200, 0200, 0200, 0200, 0200, 0200, 83 0200, 0200, 0200, 0200, 0200, 0200, 0200, 0200, 84 0200, 0200, 0200, 0200, 0200, 0200, 0200, 0200, 85 0200, 0200, 0200, 0200, 0200, 0200, 0200, 0200, 86 0200, 0200, 0200, 0200, 0200, 0200, 0200, 0200, 87 0200, 0200, 0200, 0076, 0200, 0200, 0200, 0077, 88 0064, 0065, 0066, 0067, 0070, 0071, 0072, 0073, 89 0074, 0075, 0200, 0200, 0200, 0200, 0200, 0200, 90 0200, 0000, 0001, 0002, 0003, 0004, 0005, 0006, 91 0007, 0010, 0011, 0012, 0013, 0014, 0015, 0016, 92 0017, 0020, 0021, 0022, 0023, 0024, 0025, 0026, 93 0027, 0030, 0031, 0200, 0200, 0200, 0200, 0200, 94 0200, 0032, 0033, 0034, 0035, 0036, 0037, 0040, 95 0041, 0042, 0043, 0044, 0045, 0046, 0047, 0050, 96 0051, 0052, 0053, 0054, 0055, 0056, 0057, 0060, 97 0061, 0062, 0063, 0200, 0200, 0200, 0200, 0200 98 #endif 99 }; 100 101 /* Current line number for mult decodes */ 102 #ifdef MACTC5 103 long infile_line; /* Current line number for mult decodes */ 104 #else 105 static long infile_line; 106 #endif 107 108 /************************************************************************/ 109 110 /* CRC Routines. */ 111 /* These CRC functions are derived from code in chapter 19 of the book 112 * "C Programmer's Guide to Serial Communications", by Joe Campbell. 113 * Generalized to any CRC width by Philip Zimmermann. 114 */ 115 116 #define byte unsigned char 117 118 #define CRCBITS 24 /* may be 16, 24, or 32 */ 119 /* #define maskcrc(crc) ((crcword)(crc)) *//* if CRCBITS is 16 or 32 */ 120 #define maskcrc(crc) ((crc) & 0xffffffL) /* if CRCBITS is 24 */ 121 #define CRCHIBIT ((crcword) (1L<<(CRCBITS-1))) /* 0x8000 if CRCBITS is 16 */ 122 #define CRCSHIFTS (CRCBITS-8) 123 124 /* 125 * Notes on making a good 24-bit CRC-- 126 * The primitive irreducible polynomial of degree 23 over GF(2), 127 * 040435651 (octal), comes from Appendix C of "Error Correcting Codes, 128 * 2nd edition" by Peterson and Weldon, page 490. This polynomial was 129 * chosen for its uniform density of ones and zeros, which has better 130 * error detection properties than polynomials with a minimal number of 131 * nonzero terms. Multiplying this primitive degree-23 polynomial by 132 * the polynomial x+1 yields the additional property of detecting any 133 * odd number of bits in error, which means it adds parity. This 134 * approach was recommended by Neal Glover. 135 * 136 * To multiply the polynomial 040435651 by x+1, shift it left 1 bit and 137 * bitwise add (xor) the unshifted version back in. Dropping the unused 138 * upper bit (bit 24) produces a CRC-24 generator bitmask of 041446373 139 * octal, or 0x864cfb hex. 140 * 141 * You can detect spurious leading zeros or framing errors in the 142 * message by initializing the CRC accumulator to some agreed-upon 143 * nonzero value, but the value used is a bit nonstandard. 144 */ 145 146 #define CCITTCRC 0x1021 /* CCITT's 16-bit CRC generator polynomial */ 147 #define PRZCRC 0x864cfbL /* PRZ's 24-bit CRC generator polynomial */ 148 #define CRCINIT 0xB704CEL /* Init value for CRC accumulator */ 149 150 static crcword crctable[256]; /* Table for speeding up CRC's */ 151 152 /* 153 * mk_crctbl derives a CRC lookup table from the CRC polynomial. 154 * The table is used later by the crcbytes function given below. 155 * mk_crctbl only needs to be called once at the dawn of time. 156 * 157 * The theory behind mk_crctbl is that table[i] is initialized 158 * with the CRC of i, and this is related to the CRC of i>>1, 159 * so the CRC of i>>1 (pointed to by p) can be used to derive 160 * the CRC of i (pointed to by q). 161 */ 162 static void 163 mk_crctbl(crcword poly) 164 { 165 int i; 166 crcword t, *p, *q; 167 p = q = crctable; 168 *q++ = 0; 169 *q++ = poly; 170 for (i = 1; i < 128; i++) { 171 t = *++p; 172 if (t & CRCHIBIT) { 173 t <<= 1; 174 *q++ = t ^ poly; 175 *q++ = t; 176 } else { 177 t <<= 1; 178 *q++ = t; 179 *q++ = t ^ poly; 180 } 181 } 182 } 183 184 /* 185 * Accumulate a buffer's worth of bytes into a CRC accumulator, 186 * returning the new CRC value. 187 */ 188 crcword 189 crcbytes(byte * buf, unsigned len, register crcword accum) 190 { 191 do { 192 accum = accum << 8 ^ crctable[(byte) (accum >> CRCSHIFTS) ^ *buf++]; 193 } while (--len); 194 return maskcrc(accum); 195 } /* crcbytes */ 196 197 /* Initialize the CRC table using our codes */ 198 void 199 init_crc(void) 200 { 201 mk_crctbl(PRZCRC); 202 } 203 204 205 /************************************************************************/ 206 207 208 /* ENC is the basic 1 character encoding function to make a char printing */ 209 #define ENC(c) ((int)bintoasc[((c) & 077)]) 210 #define PAD '=' 211 212 /* 213 * output one group of up to 3 bytes, pointed at by p, on file f. 214 * if fewer than 3 are present, the 1 or two extras must be zeros. 215 */ 216 static void 217 outdec(char *p, FILE *f, int count) 218 { 219 int c1, c2, c3, c4; 220 221 c1 = *p >> 2; 222 c2 = ((*p << 4) & 060) | ((p[1] >> 4) & 017); 223 c3 = ((p[1] << 2) & 074) | ((p[2] >> 6) & 03); 224 c4 = p[2] & 077; 225 putc(ENC(c1), f); 226 putc(ENC(c2), f); 227 if (count == 1) { 228 putc(PAD, f); 229 putc(PAD, f); 230 } else { 231 putc(ENC(c3), f); 232 if (count == 2) 233 putc(PAD, f); 234 else 235 putc(ENC(c4), f); 236 } 237 } /* outdec */ 238 239 240 /* Output the CRC value, MSB first per normal CRC conventions */ 241 static void 242 outcrc(word32 crc, FILE *outFile) 243 { 244 char crcbuf[4]; 245 crcbuf[0] = (crc >> 16) & 0xff; 246 crcbuf[1] = (crc >> 8) & 0xff; 247 crcbuf[2] = (crc >> 0) & 0xff; 248 putc(PAD, outFile); 249 outdec(crcbuf, outFile, 3); 250 putc('\n', outFile); 251 } /* outcrc */ 252 253 /* Return filename for output (text mode), but replace last letter(s) of 254 * filename with the ascii for num. It will use the appropriate number 255 * of digits for ofnum when converting num, so if ofnum < 10, use 1 digit, 256 * >= 10 and < 100 use 2 digits, >= 100 and < 1000 use 3 digits. If its 257 * >= 1000, then we have other problems to worry about, and this might do 258 * weird things. 259 */ 260 static char * 261 numFilename(char *fname, int num, int ofnum) 262 { 263 static char fnamenum[MAX_PATH]; 264 int len; 265 int offset = 1; 266 267 strcpy(fnamenum, fname); 268 len = strlen(fnamenum); 269 do { 270 fnamenum[len - offset] = '0' + (num % 10); 271 num /= 10; 272 ofnum /= 10; 273 offset++; 274 } while (ofnum >= 1 && offset < 4); 275 return fnamenum; 276 } 277 278 /* 279 * Reads and discards a line from the given file. Returns -1 on error or 280 * EOF, 0 if the line is blank, and 1 if the line is not blank. 281 */ 282 static int 283 skipline(FILE * f) 284 { 285 int state, flag, c; 286 287 state = 0; 288 flag = 0; 289 for (;;) { 290 c = getc(f); 291 if (c == '\n') 292 return flag; 293 if (state) { 294 ungetc(c, f); 295 return flag; 296 } 297 if (c == EOF) 298 return -1; 299 if (c == '\r') 300 state = 1; 301 else if (c != ' ') 302 flag = 1; 303 } 304 } /* skipline */ 305 306 307 /* 308 * Copies a line from the input file to the output. Does NOT copy the 309 * trailing newline. Returns -1 on EOF or error, 0 if the line was terminated 310 * by EOF, and 1 if the line was terminated with a newline sequence. 311 */ 312 static int 313 copyline(FILE * in, FILE * out) 314 { 315 int state, flag, c; 316 317 state = 0; 318 for (;;) { 319 c = getc(in); 320 if (c == '\n') 321 return 1; 322 if (state) { 323 ungetc(c, in); 324 return 1; 325 } 326 if (c == EOF) 327 return 0; 328 if (c == '\r') 329 state = 1; 330 else 331 putc(c, out); 332 } 333 } /* copyline */ 334 335 /* 336 * Reads a line from file f, up to the size of the buffer. The line in the 337 * buffer will NOT include line termination, although any of (CR, LF, CRLF) 338 * is accepted on input. The return value is -1 on error, 0 if the line 339 * was terminated abnormally (EOF, error, or out of buffer space), and 340 * 1 if the line was terminated normally. 341 * 342 * Passing in a buffer less than 2 characters long is not a terribly bright 343 * idea. 344 */ 345 static int 346 get_line(char *buf, int n, FILE * f) 347 { 348 int state; 349 char *p; 350 int c; 351 352 state = 0; 353 p = buf; 354 for (;;) { 355 c = getc(f); 356 if (c == '\n') { 357 *p = 0; 358 return 1; /* Line terminated with \n or \r\n */ 359 } 360 if (state) { 361 ungetc(c, f); 362 *p = 0; 363 return 1; /* Line terminated with \r */ 364 } 365 if (c == EOF) { 366 *p = 0; 367 return (p == buf) ? -1 : 0; /* Error */ 368 } 369 if (c == '\r') 370 state = 1; 371 else if (--n > 0) { 372 *p++ = c; 373 } else { 374 ungetc(c, f); 375 *p = 0; 376 return 0; /* Out of buffer space */ 377 } 378 } /* for (;;) */ 379 } /* get_line */ 380 381 #if 1 382 /* This limit is advisory only; longer lines are handled properly. 383 * The only requirement is that this be at least as long as the longest 384 * delimiter string used by PGP 385 * (e.g. "-----BEGIN PGP MESSAGE, PART %02d/%02d-----\n") 386 */ 387 #define MAX_LINE_SIZE 80 388 #else 389 #ifdef MSDOS /* limited stack space */ 390 #define MAX_LINE_SIZE 256 391 #else 392 #define MAX_LINE_SIZE 1024 393 #endif 394 #endif 395 396 /* 397 * Read a line from file f, buf must be able to hold at least MAX_LINE_SIZE 398 * characters. Anything after that is ignored. Strips trailing spaces and 399 * line terminator, can read LF, CRLF and CR textfiles. It can't be ASCII 400 * armor anyway. 401 */ 402 static char * 403 get_armor_line(char *buf, FILE * f) 404 { 405 int c, n = MAX_LINE_SIZE-1; 406 char *p = buf; 407 408 do { 409 c = getc(f); 410 if (c == '\n' || c == '\r' || c == EOF) 411 break; 412 *p++ = c; 413 } while (--n > 0); 414 if (p == buf && c == EOF) { 415 *buf = '\0'; 416 return NULL; 417 } 418 /* 419 * Skip to end of line, setting n to non-zero if anything trailing is 420 * not a space (meaning that any trailing whitespace in the buffer is 421 * not trailing whitespace on the line and should not be stripped). 422 */ 423 n = 0; 424 while (c != '\n' && c != '\r' && c != EOF) { 425 n |= c ^ ' '; 426 c = getc(f); 427 } 428 if (c == '\r' && (c = getc(f)) != '\n') 429 ungetc(c, f); 430 if (!n) { /* Skip trailing whitespace, as described above */ 431 while (p > buf && p[-1] == ' ') 432 --p; 433 } 434 *p = '\0'; 435 return buf; 436 } 437 438 439 /* 440 * Encode a file in sections. 64 ASCII bytes * 720 lines = 46K, 441 * recommended max. Usenet message size is 50K so this leaves a nice 442 * margin for .signature. In the interests of orthogonality and 443 * programmer laziness no check is made for a message containing only 444 * a few lines (or even just an 'end') after a section break. 445 */ 446 #define LINE_LEN 48L 447 int pem_lines = 720; 448 #define BYTES_PER_SECTION (LINE_LEN * pem_lines) 449 450 #if defined(VMS) || defined(C370) 451 #define FOPRARMOR FOPRTXT 452 #else 453 /* armored files are opened in binary mode so that CRLF/LF/CR files 454 can be handled by all systems */ 455 #define FOPRARMOR FOPRBIN 456 #endif 457 458 extern boolean verbose; /* Undocumented command mode in PGP.C */ 459 extern boolean filter_mode; 460 461 /* 462 * Copy from infilename to outfilename, ASCII armoring as you go along, 463 * and with breaks every pem_lines lines. 464 * If clearfilename is non-NULL, first output that file preceded by a 465 * special delimiter line. filename is the original filename, used 466 * only for debugging. 467 */ 468 int 469 armor_file(char *infilename, char *outfilename, char *filename, 470 char *clearfilename, boolean kv_label) 471 { 472 char buffer[MAX_LINE_SIZE]; 473 int i, rc, bytesRead, lines = 0; 474 int noSections, currentSection = 1; 475 long fileLen; 476 crcword crc; 477 FILE *inFile, *outFile, *clearFile; 478 char *tempf; 479 char *blocktype = "MESSAGE"; 480 #ifdef MACTC5 481 char curOutFile[256]=""; 482 #endif 483 484 if (verbose) 485 fprintf(pgpout, 486 "armor_file: infile = %s, outfile = %s, filename = %s, clearname = %s\n", 487 infilename, outfilename, filename, 488 clearfilename == NULL ? "" : clearfilename); 489 490 /* open input file as binary */ 491 if ((inFile = fopen(infilename, FOPRBIN)) == NULL) 492 return 1; 493 494 if (!outfilename || pem_lines == 0) { 495 noSections = 1; 496 } else { 497 /* Evaluate how many parts this file will comprise */ 498 fseek(inFile, 0L, SEEK_END); 499 fileLen = ftell(inFile); 500 rewind(inFile); 501 noSections = (fileLen + BYTES_PER_SECTION - 1) / 502 BYTES_PER_SECTION; 503 if (noSections > 99) { 504 pem_lines = ((fileLen + LINE_LEN - 1) / LINE_LEN + 98) / 99; 505 noSections = (fileLen + BYTES_PER_SECTION - 1) / 506 BYTES_PER_SECTION; 507 fprintf(pgpout, 508 "value for \"armorlines\" is too low, using %d\n", pem_lines); 509 } 510 } 511 512 if (clearfilename) 513 tempf = tempfile(TMP_WIPE); 514 else 515 tempf = outfilename; 516 517 if (outfilename == NULL) { 518 outFile = stdout; 519 } else { 520 if (noSections > 1) { 521 do { 522 char *t; 523 force_extension(outfilename, ASC_EXTENSION); 524 strcpy(outfilename, numFilename(outfilename, 1, noSections)); 525 if (!file_exists(outfilename)) break; 526 t = ck_dup_output(outfilename, TRUE, TRUE); 527 if (t==NULL) user_error(); 528 strcpy(outfilename,t); 529 } while (TRUE); 530 outFile = fopen(tempf, FOPWTXT); 531 } else 532 outFile = fopen(tempf, FOPWTXT); 533 #ifdef MACTC5 534 strcpy(curOutFile,outfilename); 535 #endif 536 } 537 538 if (outFile == NULL) { 539 fclose(inFile); 540 return 1; 541 } 542 if (clearfilename) { 543 if ((clearFile = fopen(clearfilename, FOPRTXT)) == NULL) { 544 fclose(inFile); 545 if (outFile != stdout) 546 fclose(outFile); 547 return 1; 548 } 549 fprintf(outFile, "-----BEGIN PGP SIGNED MESSAGE-----\n\n"); 550 while ((i = get_line(buffer, sizeof buffer, clearFile)) >= 0) { 551 /* Quote lines beginning with '-' as per RFC1113; 552 * Also quote lines beginning with "From "; this is 553 * for Unix mailers which add ">" to such lines. 554 */ 555 if (buffer[0] == '-' || strncmp(buffer, "From ", 5) == 0) 556 fputs("- ", outFile); 557 fputs(buffer, outFile); 558 /* If there is more on this line, copy it */ 559 if (i == 0) 560 if (copyline(clearFile, outFile) <= 0) 561 break; 562 fputc('\n', outFile); 563 } 564 fclose(clearFile); 565 putc('\n', outFile); 566 blocktype = "SIGNATURE"; 567 } 568 if (noSections == 1) { 569 byte ctb = 0; 570 int keycounter = 0; 571 int status; 572 ctb = getc(inFile); 573 if (is_ctb_type(ctb, CTB_CERT_PUBKEY_TYPE)) { 574 blocktype = "PUBLIC KEY BLOCK"; 575 if (kv_label) { 576 kv_title(outFile); /* Title line */ 577 rewind(inFile); /* Back over CTB */ 578 status = kvformat_keypacket(inFile, outFile, TRUE, "", infilename, 579 FALSE, FALSE, &keycounter); 580 fprintf(outFile, "\n"); 581 } 582 } else if (is_ctb_type(ctb, CTB_CERT_SECKEY_TYPE)) { 583 blocktype = "SECRET KEY BLOCK"; 584 if (kv_label) { 585 kv_title(outFile); /* Title line */ 586 rewind(inFile); /* Back over CTB */ 587 status = kvformat_keypacket(inFile, outFile, TRUE, "", infilename, 588 FALSE, FALSE, &keycounter); 589 fprintf(outFile, "\n"); 590 } 591 } 592 fprintf(outFile, "-----BEGIN PGP %s-----\n", blocktype); 593 rewind(inFile); 594 } else { 595 fprintf(outFile, 596 "-----BEGIN PGP MESSAGE, PART %02d/%02d-----\n", 597 1, noSections); 598 } 599 fprintf(outFile, "Version: %s\n", LANG(rel_version)); 600 if (clearfilename) 601 fprintf(outFile, "Charset: %s\n", charset); 602 if (globalCommentString[0]) 603 fprintf(outFile, "Comment: %s\n", globalCommentString); 604 fprintf(outFile, "\n"); 605 606 init_crc(); 607 crc = CRCINIT; 608 609 while ((bytesRead = fread(buffer, 1, LINE_LEN, inFile)) > 0) { 610 /* Munge up LINE_LEN characters */ 611 if (bytesRead < LINE_LEN) 612 fill0(buffer + bytesRead, LINE_LEN - bytesRead); 613 614 crc = crcbytes((byte *) buffer, bytesRead, crc); 615 for (i = 0; i < bytesRead - 3; i += 3) 616 outdec(buffer + i, outFile, 3); 617 outdec(buffer + i, outFile, bytesRead - i); 618 putc('\n', outFile); 619 #ifdef MACTC5 620 mac_poll_for_break(); 621 #endif 622 623 if (++lines == pem_lines && currentSection < noSections) { 624 lines = 0; 625 outcrc(crc, outFile); 626 fprintf(outFile, 627 "-----END PGP MESSAGE, PART %02d/%02d-----\n\n", 628 currentSection, noSections); 629 if (write_error(outFile)) { 630 fclose(outFile); 631 return -1; 632 } 633 fclose(outFile); 634 #ifdef MACTC5 635 PGPSetFinfo(curOutFile,'TEXT','MPGP'); 636 #endif 637 outFile = fopen(numFilename(outfilename, 638 ++currentSection, 639 noSections), FOPWTXT); 640 #ifdef MACTC5 641 strcpy(curOutFile,numFilename (outfilename,currentSection,noSections)); 642 #endif 643 if (outFile == NULL) { 644 fclose(inFile); 645 return -1; 646 } 647 fprintf(outFile, 648 "-----BEGIN PGP MESSAGE, PART %02d/%02d-----\n", 649 currentSection, noSections); 650 fprintf(outFile, "\n"); 651 crc = CRCINIT; 652 } 653 } 654 outcrc(crc, outFile); 655 656 if (noSections == 1) 657 fprintf(outFile, "-----END PGP %s-----\n", blocktype); 658 else 659 fprintf(outFile, "-----END PGP MESSAGE, PART %02d/%02d-----\n", 660 noSections, noSections); 661 662 /* Done */ 663 fclose(inFile); 664 rc = write_error(outFile); 665 if (outFile == stdout) 666 return rc; 667 #ifdef MACTC5 668 PGPSetFinfo(curOutFile,'TEXT','MPGP'); 669 #endif 670 fclose(outFile); 671 if (clearfilename) { 672 remove(outfilename); 673 savetemp(tempf,outfilename); 674 } 675 676 if (rc) 677 return -1; 678 679 if (clearfilename) { 680 fprintf(pgpout, 681 LANG("\nClear signature file: %s\n"), outfilename); 682 } else if (noSections == 1) { 683 fprintf(pgpout, 684 LANG("\nTransport armor file: %s\n"), outfilename); 685 } else { 686 fprintf(pgpout, LANG("\nTransport armor files: ")); 687 for (i = 1; i <= noSections; ++i) 688 fprintf(pgpout, "%s%s", 689 numFilename(outfilename, i, noSections), 690 i == noSections ? "\n" : ", "); 691 } 692 return 0; 693 } /* armor_file */ 694 695 /* End ASCII armor encode routines. */ 696 697 698 /* 699 * ASCII armor decode routines. 700 */ 701 static int 702 darmor_buffer(char *inbuf, char *outbuf, int *outlength) 703 { 704 unsigned char *bp; 705 int length; 706 unsigned int c1, c2, c3, c4; 707 register int j; 708 709 length = 0; 710 bp = (unsigned char *) inbuf; 711 712 /* FOUR input characters go into each THREE output charcters */ 713 714 while (*bp != '\0') { 715 #ifdef EBCDIC 716 if ((c1 = asctobin[*bp]) & 0x80) 717 return -1; 718 ++bp; 719 if ((c2 = asctobin[*bp]) & 0x80) 720 return -1; 721 #else 722 if (*bp & 0x80 || (c1 = asctobin[*bp]) & 0x80) 723 return -1; 724 ++bp; 725 if (*bp & 0x80 || (c2 = asctobin[*bp]) & 0x80) 726 return -1; 727 #endif 728 if (*++bp == PAD) { 729 c3 = c4 = 0; 730 length += 1; 731 if (c2 & 15) 732 return -1; 733 if (strcmp((char *) bp, "==") == 0) 734 bp += 1; 735 else if (strcmp((char *) bp, "=3D=3D") == 0) 736 bp += 5; 737 else 738 return -1; 739 #ifdef EBCDIC 740 } else if ((c3 = asctobin[*bp]) & 0x80) { 741 #else 742 } else if (*bp & 0x80 || (c3 = asctobin[*bp]) & 0x80) { 743 #endif 744 return -1; 745 } else { 746 if (*++bp == PAD) { 747 c4 = 0; 748 length += 2; 749 if (c3 & 3) 750 return -1; 751 if (strcmp((char *) bp, "=") == 0); /* All is well */ 752 else if (strcmp((char *) bp, "=3D") == 0) 753 bp += 2; 754 else 755 return -1; 756 #ifdef EBCDIC 757 } else if ((c4 = asctobin[*bp]) & 0x80) { 758 #else 759 } else if (*bp & 0x80 || (c4 = asctobin[*bp]) & 0x80) { 760 #endif 761 return -1; 762 } else { 763 length += 3; 764 } 765 } 766 ++bp; 767 j = (c1 << 2) | (c2 >> 4); 768 *outbuf++ = j; 769 j = (c2 << 4) | (c3 >> 2); 770 *outbuf++ = j; 771 j = (c3 << 6) | c4; 772 *outbuf++ = j; 773 } 774 775 *outlength = length; 776 return 0; /* normal return */ 777 778 } /* darmor_buffer */ 779 780 static char armorfilename[MAX_PATH]; 781 /* 782 * try to open the next file of a multi-part armored file 783 * the sequence number is expected at the end of the file name 784 */ 785 static FILE * 786 open_next(void) 787 { 788 char *p, *s, c; 789 FILE *fp; 790 791 p = armorfilename + strlen(armorfilename); 792 while (--p >= armorfilename && isdigit(*p)) { 793 if (*p != '9') { 794 ++*p; 795 return fopen(armorfilename, FOPRARMOR); 796 } 797 *p = '0'; 798 } 799 800 /* need an extra digit */ 801 if (p >= armorfilename) { 802 /* try replacing character ( .as0 -> .a10 ) */ 803 c = *p; 804 *p = '1'; 805 if ((fp = fopen(armorfilename, FOPRARMOR)) != NULL) 806 return fp; 807 *p = c; /* restore original character */ 808 } 809 ++p; 810 for (s = p + strlen(p); s >= p; --s) 811 s[1] = *s; 812 *p = '1'; /* insert digit ( fn0 -> fn10 ) */ 813 814 #if defined(MSDOS) && !defined(BUG) 815 /* if the resulting filename has more than three 816 characters after the first dot, don't even try to open it */ 817 s = strchr(armorfilename, '.'); 818 if (s != NULL) 819 if (strlen(s) > 3) 820 return NULL; 821 #endif /* MSDOS */ 822 823 return fopen(armorfilename, FOPRARMOR); 824 } 825 826 /* 827 * Returns -1 if the line given is does not begin as a valid ASCII 828 * armor header line (something of the form "Label: ", where "Label" 829 * must begin with a letter followed by letters, numbers, or hyphens, 830 * followed immediately by a colon and a space), 0 if it is a familiar 831 * label, and the length of the label if it is an unfamiliar label 832 * (E.g. not "Version" or "Comment"); 833 */ 834 static int 835 isheaderline(char const *buf) 836 { 837 int i; 838 839 if (!isalpha(*buf)) 840 return -1; /* Not a label */ 841 842 for (i = 1; isalnum(buf[i]) || i == '-'; i++) 843 ; 844 if (buf[i] != ':' || buf[i+1] != ' ') 845 return -1; /* Not a label */ 846 847 if (memcmp(buf, "Charset", i) == 0) { 848 if (use_charset_header) strcpy(charset_header,buf+9); 849 return 0; 850 } 851 if (memcmp(buf, "Version", i) == 0 || 852 memcmp(buf, "Comment", i) == 0) 853 return 0; /* Familiar label */ 854 return i; /* Unfamiliar label */ 855 } 856 857 /* 858 * Skips a bunch of headers, either returning 0, or printing 859 * an error message and returning -1. 860 * If it encounters an unfamiliar label and *warned is not set, 861 * prints a warning and sets *warned. 862 * NOTE that file read errors are NOT printed or reported in the 863 * return code. It is assumed that the following read will 864 * notice the error and do something appropriate. 865 */ 866 static int 867 skipheaders(FILE *in, char *buf, int *warned, int armorfollows) 868 { 869 int label_seen = 0; 870 int i; 871 #ifndef STRICT_ARMOR /* Allow no space */ 872 long fpos; 873 char outbuf[(MAX_LINE_SIZE*3+3)/4]; 874 int n; 875 #endif 876 877 for (;;) { 878 ++infile_line; 879 #ifndef STRICT_ARMOR 880 fpos = ftell(in); 881 #endif 882 if (get_armor_line(buf, in) == NULL) /* Error */ 883 return 0; /* See comment above */ 884 if (buf[0] == '\0') /* Blank line */ 885 return 0; /* Success */ 886 if (label_seen && (buf[0] == ' ' || buf[0] == '\t')) 887 continue; /* RFC-822-style continuation line */ 888 i = isheaderline(buf); 889 if (i < 0) { /* Not a legal header line */ 890 #ifndef STRICT_ARMOR /* If it's as ASCII armor line, accept it */ 891 if (armorfollows && darmor_buffer(buf, outbuf, &n) == 0 && n == 48) 892 { 893 fseek(in, fpos, SEEK_SET); 894 --infile_line; 895 return 0; /* Consider this acceptable */ 896 } 897 #else 898 (void)armorfollows; /* Stop compiler complaints */ 899 #endif 900 fprintf(pgpout, 901 LANG("Invalid ASCII armor header line: \"%.40s\"\n\ 902 ASCII armor corrupted.\n"), buf); 903 return -1; 904 } 905 if (i > 0 && !*warned) { 906 fprintf(pgpout, 907 LANG("Warning: Unrecognized ASCII armor header label \"%.*s:\" ignored.\n"), 908 i, buf); 909 *warned = 1; 910 } 911 label_seen = 1; /* Continuation lines are now legal */ 912 } 913 } 914 915 /* 916 * Copy from in to out, decoding as you go, with handling for multiple 917 * 500-line blocks of encoded data. This function also knows how to 918 * go past the end of one part to the beginning of the next in a multi-part 919 * file. (As you can see from some ugliness below, this is not the best 920 * place to do it, since the caller is responsible for closing the 921 * "original_in" file.) 922 */ 923 static int 924 armordecode(FILE *original_in, FILE *out, int *warned) 925 { 926 char inbuf[MAX_LINE_SIZE]; 927 char outbuf[MAX_LINE_SIZE]; 928 929 int i, n, status; 930 int line; 931 int section, currentSection = 1; 932 int noSections = 0; 933 int gotcrc = 0; 934 long crc = CRCINIT, chkcrc = -1; 935 char crcbuf[4]; 936 int ret_code = 0; 937 int end_of_message; 938 FILE *in = original_in; 939 940 init_crc(); 941 942 for (line = 1;; line++) { /* for each input line */ 943 if (get_armor_line(inbuf, in) == NULL) { 944 end_of_message = 1; 945 } else { 946 end_of_message = 947 (strncmp(inbuf, "-----END PGP MESSAGE,", 21) == 0); 948 ++infile_line; 949 } 950 951 if (currentSection != noSections && end_of_message) { 952 /* End of this section */ 953 if (gotcrc) { 954 if (chkcrc != crc) { 955 fprintf(pgpout, 956 LANG("ERROR: Bad ASCII armor checksum in section %d.\n"), currentSection); 957 /* continue with decoding to see if there are other bad parts */ 958 ret_code = -1; 959 } 960 } 961 gotcrc = 0; 962 crc = CRCINIT; 963 section = 0; 964 965 /* Try and find start of next section */ 966 do { 967 if (get_armor_line(inbuf, in) == NULL) { 968 if (in != original_in) 969 fclose(in); 970 if ((in = open_next()) != NULL) 971 continue; /* Keep working on new in */ 972 fprintf(pgpout, 973 LANG("Can't find section %d.\n"), currentSection + 1); 974 return -1; 975 } 976 ++infile_line; 977 } 978 while (strncmp(inbuf, "-----BEGIN PGP MESSAGE", 22)); 979 980 /* Make sure this section is the correct one */ 981 if (2 != sscanf(inbuf, 982 "-----BEGIN PGP MESSAGE, PART %d/%d", 983 §ion, &noSections)) { 984 fprintf(pgpout, 985 LANG("Badly formed section delimiter, part %d.\n"), 986 currentSection + 1); 987 goto error; 988 } 989 if (section != ++currentSection) { 990 fprintf(pgpout, 991 LANG("Sections out of order, expected part %d"), currentSection); 992 if (section) 993 fprintf(pgpout, 994 LANG(", got part %d\n"), section); 995 else 996 fputc('\n', pgpout); 997 goto error; 998 } 999 /* Skip header after BEGIN line */ 1000 if (skipheaders(in, inbuf, warned, 1) < 0) 1001 goto error; 1002 if (feof(in)) { 1003 fprintf(pgpout, 1004 LANG("ERROR: Hit EOF in header of section %d.\n"), 1005 currentSection); 1006 goto error; 1007 } 1008 1009 /* Continue decoding */ 1010 continue; 1011 } 1012 #ifdef MACTC5 1013 mac_poll_for_break(); 1014 #endif 1015 1016 /* Quit when hit the -----END PGP MESSAGE----- line or a blank, 1017 * or handle checksum 1018 */ 1019 if (inbuf[0] == PAD) { /* Checksum lines start 1020 with PAD char */ 1021 /* If the already-armored file is sent through MIME 1022 * and gets armored again, '=' will become '=3D'. 1023 * To make life easier, we detect and work around this 1024 * idiosyncracy. 1025 */ 1026 if (strlen(inbuf) == 7 && 1027 inbuf[1] == '3' && inbuf[2] == 'D') 1028 status = darmor_buffer(inbuf + 3, crcbuf, &n); 1029 else 1030 status = darmor_buffer(inbuf + 1, crcbuf, &n); 1031 if (status < 0 || n != 3) { 1032 fprintf(pgpout, 1033 LANG("ERROR: Badly formed ASCII armor checksum, line %d.\n"), line); 1034 goto error; 1035 } 1036 chkcrc = (((long) crcbuf[0] << 16) & 0xff0000L) + 1037 ((crcbuf[1] << 8) & 0xff00L) + (crcbuf[2] & 0xffL); 1038 gotcrc = 1; 1039 continue; 1040 } 1041 if (inbuf[0] == '\0') { 1042 fprintf(pgpout, 1043 LANG("WARNING: No ASCII armor `END' line.\n")); 1044 break; 1045 } 1046 if (strncmp(inbuf, "-----END PGP ", 13) == 0) 1047 break; 1048 1049 status = darmor_buffer(inbuf, outbuf, &n); 1050 1051 if (status == -1) { 1052 fprintf(pgpout, 1053 LANG("ERROR: Bad ASCII armor character, line %d.\n"), line); 1054 gotcrc = 1; /* this will print part number, 1055 continue with next part */ 1056 ret_code = -1; 1057 } 1058 if (n > sizeof outbuf) { 1059 fprintf(pgpout, 1060 LANG("ERROR: Bad ASCII armor line length %d on line %d.\n"), 1061 n, line); 1062 goto error; 1063 } 1064 crc = crcbytes((byte *) outbuf, n, crc); 1065 if (fwrite(outbuf, 1, n, out) != n) { 1066 ret_code = -1; 1067 break; 1068 } 1069 } /* line */ 1070 1071 if (gotcrc) { 1072 if (chkcrc != crc) { 1073 fprintf(pgpout, 1074 LANG("ERROR: Bad ASCII armor checksum")); 1075 if (noSections > 0) 1076 fprintf(pgpout, 1077 LANG(" in section %d"), noSections); 1078 fputc('\n', pgpout); 1079 goto error; 1080 } 1081 } else { 1082 fprintf(pgpout, 1083 LANG("Warning: Transport armor lacks a checksum.\n")); 1084 } 1085 1086 if (in != original_in) 1087 fclose(in); 1088 return ret_code; /* normal return */ 1089 error: 1090 if (in != original_in) 1091 fclose(in); 1092 return -1; /* error return */ 1093 } /* armordecode */ 1094 1095 static boolean 1096 is_armorfile(char *infile) 1097 { 1098 FILE *in; 1099 char inbuf[MAX_LINE_SIZE]; 1100 char outbuf[MAX_LINE_SIZE]; 1101 int n; 1102 long il; 1103 1104 in = fopen(infile, FOPRARMOR); 1105 if (in == NULL) 1106 return FALSE; /* can't open file */ 1107 1108 /* Read to infile_line before we begin looking */ 1109 for (il = 0; il < infile_line; ++il) { 1110 if (get_armor_line(inbuf, in) == NULL) { 1111 fclose(in); 1112 return FALSE; 1113 } 1114 } 1115 1116 /* search file for delimiter line */ 1117 for (;;) { 1118 if (get_armor_line(inbuf, in) == NULL) 1119 break; 1120 if (strncmp(inbuf, "-----BEGIN PGP ", 15) == 0) { 1121 if (strncmp(inbuf, 1122 "-----BEGIN PGP SIGNED MESSAGE-----", 34) == 0) { 1123 fclose(in); 1124 return TRUE; 1125 } 1126 n = 1; /* Don't print warnings yet */ 1127 if (skipheaders(in, inbuf, &n, 1) < 0 || 1128 get_armor_line(inbuf, in) == NULL || 1129 darmor_buffer(inbuf, outbuf, &n) < 0) 1130 break; 1131 fclose(in); 1132 return TRUE; 1133 } 1134 } 1135 1136 fclose(in); 1137 return FALSE; 1138 } /* is_armorfile */ 1139 1140 static int 1141 darmor_file(char *infile, char *outfile) 1142 { 1143 FILE *in, *out; 1144 char buf[MAX_LINE_SIZE]; 1145 char outbuf[(MAX_LINE_SIZE*3+3)/4]; 1146 int status, n; 1147 long il, fpos; 1148 char *litfile = NULL; 1149 int header_warned = 0; /* Complained about unknown header */ 1150 1151 if ((in = fopen(infile, FOPRARMOR)) == NULL) { 1152 fprintf(pgpout, LANG("ERROR: Can't find file %s\n"), infile); 1153 return 10; 1154 } 1155 strcpy(armorfilename, infile); /* store filename for multi-parts */ 1156 1157 /* Skip to infile_line */ 1158 for (il = 0; il < infile_line; ++il) { 1159 if (get_armor_line(buf, in) == NULL) { 1160 fclose(in); 1161 return -1; 1162 } 1163 } 1164 1165 /* Loop through file, searching for delimiter. Decode anything with a 1166 delimiter, complain if there were no delimiter. */ 1167 1168 /* search file for delimiter line */ 1169 for (;;) { 1170 ++infile_line; 1171 if (get_armor_line(buf, in) == NULL) { 1172 fprintf(pgpout, 1173 LANG("ERROR: No ASCII armor `BEGIN' line!\n")); 1174 fclose(in); 1175 return 12; 1176 } 1177 if (strncmp(buf, "-----BEGIN PGP ", 15) == 0) 1178 break; 1179 } 1180 if (strncmp(buf, "-----BEGIN PGP SIGNED MESSAGE-----", 34) == 0) { 1181 FILE *litout; 1182 char *p; 1183 int nline; 1184 1185 /* 1186 * It would be nice to allow headers here, as we could add 1187 * additional information to PGP messages, but it appears to 1188 * be too easy to spoof, given standard text viewers. So, 1189 * forbid it outright until we sit down and figure out how to 1190 * thwart all the ways of faking an end-of-headers. The 1191 * possibilities are: 1192 * - Enough trailing whitespace on a valid-looking line to force a 1193 * line wrap. The 80 column case is tricky, as the classical 1194 * Big Iron IBM mainframe pads to 80 columns, and some terminal 1195 * and text viewer combinations cause a blank line, while others 1196 * don't. A line that is exactly 80 columns wide but ends in 1197 * a non-blank would do, too. 1198 * - A big pile of whitespace within a line, enough to 1199 * produce something that looks like a blank line between 1200 * the beginning and end parts. 1201 * - Various cursor-control sequences. 1202 * Basically, it's a nasty problem. A very strong case can be made 1203 * for the argument that it's the text viewer's problem, and outside 1204 * PGP's jurisdiction, but that has a few conflicts with reality. 1205 */ 1206 charset_header[0] = '\0'; 1207 if (get_armor_line(buf, in) == NULL) { 1208 fprintf(pgpout, 1209 LANG("ERROR: ASCII armor decode input ended unexpectedly!\n")); 1210 fclose(in); 1211 return 12; 1212 } 1213 if (buf[0] != '\0') { 1214 fprintf(pgpout, 1215 LANG("ERROR: Header line added to ASCII armor: \"%s\"\n\ 1216 ASCII armor corrupted.\n"), buf); 1217 fclose(in); 1218 return -1; 1219 1220 } 1221 1222 litfile = tempfile(TMP_WIPE | TMP_TMPDIR); 1223 if ((litout = fopen(litfile, FOPWTXT)) == NULL) { 1224 fprintf(pgpout, 1225 LANG("\n\007Unable to write ciphertext output file '%s'.\n"), litfile); 1226 fclose(in); 1227 return -1; 1228 } 1229 1230 status = 0; 1231 for (;;) { 1232 ++infile_line; 1233 nline = status; 1234 status = get_line(buf, sizeof buf, in); 1235 if (status < 0) { 1236 fprintf(pgpout, 1237 LANG("ERROR: ASCII armor decode input ended unexpectedly!\n")); 1238 fclose(in); 1239 fclose(litout); 1240 rmtemp(litfile); 1241 return 12; 1242 } 1243 if (strncmp(buf, "-----BEGIN PGP ", 15) == 0) 1244 break; 1245 if (nline) 1246 putc('\n', litout); 1247 /* De-quote lines starting with '- ' */ 1248 fputs(buf + ((buf[0] == '-' && buf[1] == ' ') ? 2 : 0), litout); 1249 /* Copy trailing part of line, if any. */ 1250 if (!status) 1251 status = copyline(in, litout); 1252 /* Ignore error; get_line will discover it again */ 1253 } 1254 fflush(litout); 1255 if (ferror(litout)) { 1256 fclose(litout); 1257 fclose(in); 1258 rmtemp(litfile); 1259 return -1; 1260 } 1261 fclose(litout); 1262 } 1263 /* Skip header after BEGIN line */ 1264 if (skipheaders(in, buf, &header_warned, 1) < 0) { 1265 fclose(in); 1266 return -1; 1267 } 1268 if (feof(in)) { 1269 fprintf(pgpout, LANG("ERROR: Hit EOF in header.\n")); 1270 fclose(in); 1271 return 13; 1272 } 1273 1274 if ((out = fopen(outfile, FOPWBIN)) == NULL) { 1275 fprintf(pgpout, 1276 LANG("\n\007Unable to write ciphertext output file '%s'.\n"), outfile); 1277 fclose(in); 1278 return -1; 1279 } 1280 status = armordecode(in, out, &header_warned); 1281 1282 if (litfile) { 1283 char *canonfile, hold_charset[16]; 1284 char lit_mode = MODE_TEXT; 1285 word32 dummystamp = 0; 1286 FILE *f; 1287 1288 /* Convert clearsigned message to internal character set */ 1289 canonfile = tempfile(TMP_WIPE | TMP_TMPDIR); 1290 strip_spaces = TRUE; 1291 if (charset_header[0]) { 1292 strcpy(hold_charset, charset); 1293 strcpy(charset, charset_header); 1294 init_charset(); 1295 } 1296 make_canonical(litfile, canonfile); 1297 rmtemp(litfile); 1298 litfile = canonfile; 1299 if (charset_header[0]) { 1300 strcpy(charset, hold_charset); 1301 init_charset(); 1302 } 1303 /* Glue the literal file read above to the signature */ 1304 f = fopen(litfile, FOPRBIN); 1305 1306 write_ctb_len(out, CTB_LITERAL2_TYPE, fsize(f) + 6, FALSE); 1307 fwrite(&lit_mode, 1, 1, out); /* write lit_mode */ 1308 fputc('\0', out); /* No filename */ 1309 fwrite(&dummystamp, 1, sizeof(dummystamp), out); 1310 /* dummy timestamp */ 1311 copyfile(f, out, -1L); /* Append literal file */ 1312 fclose(f); 1313 rmtemp(litfile); 1314 } 1315 if (write_error(out)) 1316 status = -1; 1317 fclose(out); 1318 fclose(in); 1319 return status; 1320 } /* darmor_file */ 1321 1322 /* Entry points for generic interface names */ 1323 1324 int de_armor_file(char *infile, char *outfile, long *curline) 1325 { 1326 int status; 1327 1328 if (verbose) 1329 fprintf(pgpout, 1330 "de_armor_file: infile = %s, outfile = %s, curline = %ld\n", 1331 infile, outfile, *curline); 1332 infile_line = (curline ? *curline : 0); 1333 status = darmor_file(infile, outfile); 1334 if (curline) 1335 *curline = infile_line; 1336 return status; 1337 } 1338 1339 boolean 1340 is_armor_file(char *infile, long startline) 1341 { 1342 infile_line = startline; 1343 return is_armorfile(infile); 1344 } 1345