--- pgp/src/armor.c 2018/04/24 16:40:28 1.1.1.4 +++ pgp/src/armor.c 2018/04/24 16:42:36 1.1.1.6 @@ -1,23 +1,25 @@ /* armor.c - ASCII/binary encoding/decoding based partly on PEM RFC1113. PGP: Pretty Good(tm) Privacy - public key cryptography for the masses. - (c) Copyright 1990-1992 by Philip Zimmermann. All rights reserved. - The author assumes no liability for damages resulting from the use - of this software, even if the damage results from defects in this - software. No warranty is expressed or implied. - - All the source code Philip Zimmermann wrote for PGP is available for - free under the "Copyleft" General Public License from the Free - Software Foundation. A copy of that license agreement is included in - the source release package of PGP. Code developed by others for PGP - is also freely available. Other code that has been incorporated into - PGP from other sources was either originally published in the public - domain or was used with permission from the various authors. See the - PGP User's Guide for more complete information about licensing, - patent restrictions on certain algorithms, trademarks, copyrights, - and export controls. + (c) Copyright 1990-1994 by Philip Zimmermann. All rights reserved. + The author assumes no liability for damages resulting from the use + of this software, even if the damage results from defects in this + software. No warranty is expressed or implied. + + Note that while most PGP source modules bear Philip Zimmermann's + copyright notice, many of them have been revised or entirely written + by contributors who frequently failed to put their names in their + code. Code that has been incorporated into PGP from other authors + was either originally published in the public domain or is used with + permission from the various authors. + + PGP is available for free to the public under certain restrictions. + See the PGP User's Guide (included in the release package) for + important information about licensing, patent restrictions on + certain algorithms, trademarks, copyrights, and export controls. */ + #include #include #include @@ -89,26 +91,27 @@ static long infile_line; /* Current lin #define CRCHIBIT ((crcword) (1L<<(CRCBITS-1))) /* 0x8000 if CRCBITS is 16 */ #define CRCSHIFTS (CRCBITS-8) -/* Notes on making a good 24-bit CRC-- - The primitive irreducible polynomial of degree 23 over GF(2), - 040435651 (octal), comes from Appendix C of "Error Correcting Codes, - 2nd edition" by Peterson and Weldon, page 490. This polynomial was - chosen for its uniform density of ones and zeros, which has better - error detection properties than polynomials with a minimal number of - nonzero terms. Multiplying this primitive degree-23 polynomial by - the polynomial x+1 yields the additional property of detecting any - odd number of bits in error, which means it adds parity. This - approach was recommended by Neal Glover. - - To multiply the polynomial 040435651 by x+1, shift it left 1 bit and - bitwise add (xor) the unshifted version back in. Dropping the unused - upper bit (bit 24) produces a CRC-24 generator bitmask of 041446373 - octal, or 0x864cfb hex. - - You can detect spurious leading zeros or framing errors in the - message by initializing the CRC accumulator to some agreed-upon - nonzero "random-like" value, but this is a bit nonstandard. -*/ +/* + * Notes on making a good 24-bit CRC-- + * The primitive irreducible polynomial of degree 23 over GF(2), + * 040435651 (octal), comes from Appendix C of "Error Correcting Codes, + * 2nd edition" by Peterson and Weldon, page 490. This polynomial was + * chosen for its uniform density of ones and zeros, which has better + * error detection properties than polynomials with a minimal number of + * nonzero terms. Multiplying this primitive degree-23 polynomial by + * the polynomial x+1 yields the additional property of detecting any + * odd number of bits in error, which means it adds parity. This + * approach was recommended by Neal Glover. + * + * To multiply the polynomial 040435651 by x+1, shift it left 1 bit and + * bitwise add (xor) the unshifted version back in. Dropping the unused + * upper bit (bit 24) produces a CRC-24 generator bitmask of 041446373 + * octal, or 0x864cfb hex. + * + * You can detect spurious leading zeros or framing errors in the + * message by initializing the CRC accumulator to some agreed-upon + * nonzero "random-like" value, but this is a bit nonstandard. + */ #define CCITTCRC 0x1021 /* CCITT's 16-bit CRC generator polynomial */ #define PRZCRC 0x864cfbL /* PRZ's 24-bit CRC generator polynomial */ @@ -117,31 +120,32 @@ static long infile_line; /* Current lin static crcword crctable[256]; /* Table for speeding up CRC's */ -/* mk_crctbl derives a CRC lookup table from the CRC polynomial. - The table is used later by the crcbytes function given below. - mk_crctbl only needs to be called once at the dawn of time. - - The theory behind mk_crctbl is that table[i] is initialized - with the CRC of i, and this is related to the CRC of i>>1, - so the CRC of i>>1 (pointed to by p) can be used to derive - the CRC of i (pointed to by q). -*/ +/* + * mk_crctbl derives a CRC lookup table from the CRC polynomial. + * The table is used later by the crcbytes function given below. + * mk_crctbl only needs to be called once at the dawn of time. + * + * The theory behind mk_crctbl is that table[i] is initialized + * with the CRC of i, and this is related to the CRC of i>>1, + * so the CRC of i>>1 (pointed to by p) can be used to derive + * the CRC of i (pointed to by q). + */ static void mk_crctbl(crcword poly) -{ int i; +{ + int i; crcword t, *p, *q; p = q = crctable; *q++ = 0; *q++ = poly; - for (i = 1; i < 128; i++) - { t = *++p; - if (t & CRCHIBIT) - { t <<= 1; + for (i = 1; i < 128; i++) { + t = *++p; + if (t & CRCHIBIT) { + t <<= 1; *q++ = t ^ poly; *q++ = t; - } - else - { t <<= 1; + } else { + t <<= 1; *q++ = t; *q++ = t ^ poly; } @@ -163,7 +167,8 @@ crcbytes(byte *buf, unsigned len, regist /* Initialize the CRC table using our codes */ void init_crc(void) -{ mk_crctbl(PRZCRC); +{ + mk_crctbl(PRZCRC); } @@ -188,12 +193,11 @@ static void outdec(char *p, FILE *f, int c4 = p[2] & 077; putc(ENC(c1), f); putc(ENC(c2), f); - if (count == 1) - { putc(PAD, f); + if (count == 1) { putc(PAD, f); - } - else - { putc(ENC(c3), f); + putc(PAD, f); + } else { + putc(ENC(c3), f); if (count == 2) putc(PAD, f); else @@ -204,7 +208,7 @@ static void outdec(char *p, FILE *f, int /* Output the CRC value, MSB first per normal CRC conventions */ static void outcrc (word32 crc, FILE *outFile) -{ /* Output crc */ +{ char crcbuf[4]; crcbuf[0] = (crc>>16) & 0xff; crcbuf[1] = (crc>>8) & 0xff; @@ -222,19 +226,20 @@ static void outcrc (word32 crc, FILE *ou * weird things. */ static char *numFilename( char *fname, int num, int ofnum) -{ static char fnamenum[MAX_PATH]; +{ + static char fnamenum[MAX_PATH]; int len; int offset = 1; strcpy (fnamenum, fname); len = strlen (fnamenum); do { - fnamenum[len-offset] = '0' + (num%10); - num /= 10; - ofnum /= 10; - offset++; + fnamenum[len-offset] = '0' + (num%10); + num /= 10; + ofnum /= 10; + offset++; } while (ofnum >= 1 && offset < 4); - return(fnamenum); + return fnamenum; } /* @@ -252,8 +257,8 @@ skipline(FILE *f) c = getc(f); if (c == '\n') return flag; - if (state) - { ungetc(c, f); + if (state) { + ungetc(c, f); return flag; } if (c == EOF) @@ -280,8 +285,8 @@ copyline(FILE *in, FILE *out) c = getc(in); if (c == '\n') return 1; - if (state) - { ungetc(c, in); + if (state) { + ungetc(c, in); return 1; } if (c == EOF) @@ -312,27 +317,26 @@ getline(char *buf, int n, FILE *f) state = 0; p = buf; - for (;;) - { c = getc(f); - if (c == '\n') - { *p = 0; + for (;;) { + c = getc(f); + if (c == '\n') { + *p = 0; return 1; /* Line terminated with \n or \r\n */ } - if (state) - { ungetc(c, f); + if (state) { + ungetc(c, f); *p = 0; return 1; /* Line terminated with \r */ } - if (c == EOF) - { *p = 0; + if (c == EOF) { + *p = 0; return (p == buf) ? -1 : 0; /* Error */ } if (c == '\r') state = 1; - else if (--n > 0) + else if (--n > 0) { *p++ = c; - else - { + } else { ungetc(c, f); *p = 0; return 0; /* Out of buffer space */ @@ -358,8 +362,8 @@ get_armor_line(char *buf, FILE *f) break; *p++ = c; } while (--n > 0); - if (p == buf && c == EOF) - { *buf = '\0'; + if (p == buf && c == EOF) { + *buf = '\0'; return NULL; } /* skip to end of line */ @@ -431,48 +435,45 @@ int pem_file(char *infilename, char *out /* open input file as binary */ if ((inFile = fopen(infilename,FOPRBIN)) == NULL) - { - return(1); - } + return 1; - if (!outfilename || pem_lines == 0) + if (!outfilename || pem_lines == 0) { noSections = 1; - else - { /* Evaluate how many parts this file will comprise */ + } else { + /* Evaluate how many parts this file will comprise */ fseek(inFile,0L,SEEK_END); fileLen = ftell(inFile); rewind(inFile); noSections = (fileLen + BYTES_PER_SECTION - 1) / BYTES_PER_SECTION; - if (noSections > 99) - { + if (noSections > 99) { pem_lines = ((fileLen+LINE_LEN-1)/LINE_LEN + 98) / 99; noSections = (fileLen + BYTES_PER_SECTION - 1) / BYTES_PER_SECTION; fprintf(pgpout, "value for \"armorlines\" is too low, using %d\n", pem_lines); } } - if (outfilename == NULL) + if (outfilename == NULL) { outFile = stdout; - else - { if (noSections > 1) - { force_extension(outfilename, ASC_EXTENSION); + } else { + if (noSections > 1) { + force_extension(outfilename, ASC_EXTENSION); outFile = fopen (numFilename (outfilename, 1, noSections), FOPWTXT); - } - else + } else { outFile = fopen(outfilename,FOPWTXT); + } } - if (outFile == NULL) - { fclose(inFile); - return(1); + if (outFile == NULL) { + fclose(inFile); + return 1; } - if (clearfilename) - { if ((clearFile = fopen(clearfilename,FOPRTXT)) == NULL) - { fclose (inFile); + if (clearfilename) { + if ((clearFile = fopen(clearfilename,FOPRTXT)) == NULL) { + fclose (inFile); if (outFile != stdout) fclose (outFile); - return(1); + return 1; } fprintf (outFile, "-----BEGIN PGP SIGNED MESSAGE-----\n\n"); while ((i = getline(buffer, sizeof buffer, clearFile)) >= 0) @@ -496,26 +497,27 @@ int pem_file(char *infilename, char *out } - if (noSections == 1) - { + if (noSections == 1) { byte ctb = 0; ctb = getc(inFile); if (is_ctb_type(ctb, CTB_CERT_PUBKEY_TYPE)) blocktype = "PUBLIC KEY BLOCK"; fprintf (outFile, "-----BEGIN PGP %s-----\n",blocktype); rewind(inFile); - } - else + } else { fprintf (outFile, "-----BEGIN PGP MESSAGE, PART %02d/%02d-----\n", 1, noSections); - fprintf (outFile, "Version: %s\n",rel_version); + } + fprintf (outFile, "Version: %s\n",LANG (rel_version)); + if (globalCommentString[0]) + fprintf (outFile, "Comment: %s\n", globalCommentString); fprintf (outFile, "\n"); init_crc(); crc = CRCINIT; - while((bytesRead = fread(buffer,1,LINE_LEN,inFile)) > 0) - { /* Munge up LINE_LEN characters */ + while((bytesRead = fread(buffer,1,LINE_LEN,inFile)) > 0) { + /* Munge up LINE_LEN characters */ if (bytesRead < LINE_LEN) fill0 (buffer+bytesRead, LINE_LEN-bytesRead); @@ -525,20 +527,20 @@ int pem_file(char *infilename, char *out outdec(buffer+i, outFile, bytesRead-i); putc('\n',outFile); - if (++lines == pem_lines && currentSection < noSections) - { lines = 0; + if (++lines == pem_lines && currentSection < noSections) { + lines = 0; outcrc (crc, outFile); fprintf(outFile,"-----END PGP MESSAGE, PART %02d/%02d-----\n\n", currentSection, noSections); - if (write_error(outFile)) - { fclose(outFile); - return(-1); + if (write_error(outFile)) { + fclose(outFile); + return -1; } fclose (outFile); outFile = fopen (numFilename (outfilename, ++currentSection, noSections), FOPWTXT); - if (outFile == NULL) - { fclose(inFile); - return(-1); + if (outFile == NULL) { + fclose(inFile); + return -1; } fprintf(outFile,"-----BEGIN PGP MESSAGE, PART %02d/%02d-----\n", currentSection, noSections); @@ -562,20 +564,19 @@ int pem_file(char *infilename, char *out fclose(outFile); if (rc) - return(-1); + return -1; - if (clearfilename) - fprintf (pgpout, PSTR("\nClear signature file: %s\n"), outfilename); - else if (noSections == 1) - fprintf (pgpout, PSTR("\nTransport armor file: %s\n"), outfilename); - else - { - fprintf (pgpout, PSTR("\nTransport armor files: ")); + if (clearfilename) { + fprintf (pgpout, LANG("\nClear signature file: %s\n"), outfilename); + } else if (noSections == 1) { + fprintf (pgpout, LANG("\nTransport armor file: %s\n"), outfilename); + } else { + fprintf (pgpout, LANG("\nTransport armor files: ")); for (i=1; i<=noSections; ++i) fprintf (pgpout, "%s%s", numFilename(outfilename, i, noSections), i==noSections?"\n":", "); } - return(0); + return 0; } /* pem_file */ /* End PEM encode routines. */ @@ -597,14 +598,14 @@ int dpem_buffer(char *inbuf, char *outbu /* FOUR input characters go into each THREE output charcters */ - while (*bp!='\0') - { if (*bp&0x80 || (c1=asctobin[*bp])&0x80) + while (*bp != '\0') { + if (*bp&0x80 || (c1=asctobin[*bp])&0x80) return -1; ++bp; if (*bp&0x80 || (c2=asctobin[*bp])&0x80) return -1; - if (*++bp == PAD) - { c3 = c4 = 0; + if (*++bp == PAD) { + c3 = c4 = 0; length += 1; if (c2 & 15) return -1; @@ -614,12 +615,11 @@ int dpem_buffer(char *inbuf, char *outbu bp += 5; else return -1; - } - else if (*bp&0x80 || (c3=asctobin[*bp])&0x80) + } else if (*bp&0x80 || (c3=asctobin[*bp])&0x80) { return -1; - else - { if (*++bp == PAD) - { c4 = 0; + } else { + if (*++bp == PAD) { + c4 = 0; length += 2; if (c3 & 3) return -1; @@ -629,11 +629,11 @@ int dpem_buffer(char *inbuf, char *outbu bp += 2; else return -1; - } - else if (*bp&0x80 || (c4=asctobin[*bp])&0x80) + } else if (*bp&0x80 || (c4=asctobin[*bp])&0x80) { return -1; - else + } else { length += 3; + } } ++bp; j = (c1 << 2) | (c2 >> 4); @@ -645,7 +645,7 @@ int dpem_buffer(char *inbuf, char *outbu } *outlength = length; - return(0); /* normal return */ + return 0; /* normal return */ } /* dpem_buffer */ @@ -661,23 +661,21 @@ open_next(void) FILE *fp; p = pemfilename + strlen(pemfilename); - while (--p >= pemfilename && isdigit(*p)) - { - if (*p != '9') - { + while (--p >= pemfilename && isdigit(*p)) { + if (*p != '9') { ++*p; - return(fopen(pemfilename, FOPRPEM)); + return fopen(pemfilename, FOPRPEM); } *p = '0'; } /* need an extra digit */ - if (p >= pemfilename) - { /* try replacing character ( .as0 -> .a10 ) */ + if (p >= pemfilename) { + /* try replacing character ( .as0 -> .a10 ) */ c = *p; *p = '1'; if ((fp = fopen(pemfilename, FOPRPEM)) != NULL) - return(fp); + return fp; *p = c; /* restore original character */ } ++p; @@ -685,7 +683,7 @@ open_next(void) s[1] = *s; *p = '1'; /* insert digit ( fn0 -> fn10 ) */ - return(fopen(pemfilename, FOPRPEM)); + return fopen(pemfilename, FOPRPEM); } /* @@ -695,35 +693,34 @@ open_next(void) static int pemdecode(FILE *in, FILE *out) { -char inbuf[80]; -char outbuf[80]; + char inbuf[80]; + char outbuf[80]; -int i, n, status; -int line; -int section, currentSection = 1; -int noSections = 0; -int gotcrc = 0; -long crc=CRCINIT, chkcrc = -1; -char crcbuf[4]; -int ret_code = 0; -int end_of_message; + int i, n, status; + int line; + int section, currentSection = 1; + int noSections = 0; + int gotcrc = 0; + long crc=CRCINIT, chkcrc = -1; + char crcbuf[4]; + int ret_code = 0; + int end_of_message; init_crc(); - for (line = 1; ; line++) /* for each input line */ - { - if (get_armor_line(inbuf, in) == NULL) + for (line = 1; ; line++) { /* for each input line */ + if (get_armor_line(inbuf, in) == NULL) { end_of_message = 1; - else - { end_of_message = (strncmp(inbuf,"-----END PGP MESSAGE,", 21) == 0); + } else { + end_of_message = (strncmp(inbuf,"-----END PGP MESSAGE,", 21) == 0); ++infile_line; } - if (currentSection!=noSections && end_of_message) - { /* End of this section */ - if (gotcrc) - { if (chkcrc != crc) - { fprintf(pgpout,PSTR("ERROR: Bad ASCII armor checksum in section %d.\n"), currentSection); + if (currentSection!=noSections && end_of_message) { + /* End of this section */ + if (gotcrc) { + if (chkcrc != crc) { + fprintf(pgpout,LANG("ERROR: Bad ASCII armor checksum in section %d.\n"), currentSection); ret_code = -1; /* continue with decoding to see if there are other bad parts */ } } @@ -732,17 +729,16 @@ int end_of_message; section = 0; /* Try and find start of next section */ - do - { if (get_armor_line(inbuf,in) == NULL) - { FILE *nextf; - if ((nextf = open_next()) != NULL) - { + do { + if (get_armor_line(inbuf,in) == NULL) { + FILE *nextf; + if ((nextf = open_next()) != NULL) { fclose(in); in = nextf; continue; } - fprintf(pgpout,PSTR("Can't find section %d.\n"),currentSection + 1); - return(-1); + fprintf(pgpout,LANG("Can't find section %d.\n"),currentSection + 1); + return -1; } ++infile_line; } @@ -751,27 +747,27 @@ int end_of_message; /* Make sure this section is the correct one */ if (2 != sscanf(inbuf,"-----BEGIN PGP MESSAGE, PART %d/%d", §ion,&noSections)) - { fprintf(pgpout,PSTR("Badly formed section header, part %d.\n"), + { + fprintf(pgpout,LANG("Badly formed section header, part %d.\n"), currentSection+1); - return(-1); + return -1; } - if (section != ++currentSection) - { fprintf(pgpout,PSTR("Sections out of order, expected part %d"),currentSection); + if (section != ++currentSection) { + fprintf(pgpout,LANG("Sections out of order, expected part %d"),currentSection); if (section) - fprintf(pgpout,PSTR(", got part %d\n"),section); + fprintf(pgpout,LANG(", got part %d\n"),section); else fputc('\n',pgpout); - return(-1); + return -1; } /* Skip header after BEGIN line */ do { ++infile_line; - if (get_armor_line(inbuf, in) == NULL) - { - fprintf(pgpout,PSTR("ERROR: Hit EOF in header of section %d.\n"), + if (get_armor_line(inbuf, in) == NULL) { + fprintf(pgpout,LANG("ERROR: Hit EOF in header of section %d.\n"), currentSection); - return(-1); + return -1; } } while (inbuf[0] != '\0'); @@ -781,8 +777,7 @@ int end_of_message; /* Quit when hit the -----END PGP MESSAGE----- line or a blank, or handle checksum */ - if (inbuf[0] == PAD) /* Checksum lines start with PAD char */ - { + if (inbuf[0] == PAD) { /* Checksum lines start with PAD char */ /* If the already-armored file is sent through MIME * and gets armored again, '=' will become '=3D'. * To make life easier, we detect and work around this @@ -793,8 +788,8 @@ int end_of_message; status = dpem_buffer(inbuf+3, crcbuf, &n); else status = dpem_buffer(inbuf+1, crcbuf, &n); - if ( status < 0 || n != 3 ) - { fprintf(pgpout,PSTR("ERROR: Badly formed ASCII armor checksum, line %d.\n"),line); + if ( status < 0 || n != 3 ) { + fprintf(pgpout,LANG("ERROR: Badly formed ASCII armor checksum, line %d.\n"),line); return -1; } chkcrc = (((long)crcbuf[0]<<16)&0xff0000L) + @@ -802,8 +797,8 @@ int end_of_message; gotcrc = 1; continue; } - if (inbuf[0] == '\0') - { fprintf(pgpout,PSTR("WARNING: No ASCII armor `END' line.\n")); + if (inbuf[0] == '\0') { + fprintf(pgpout,LANG("WARNING: No ASCII armor `END' line.\n")); break; } if (strncmp(inbuf, "-----END PGP ", 13) == 0) @@ -811,39 +806,39 @@ int end_of_message; status = dpem_buffer(inbuf,outbuf,&n); - if (status == -1) - { fprintf(pgpout,PSTR("ERROR: Bad ASCII armor character, line %d.\n"), line); + if (status == -1) { + fprintf(pgpout,LANG("ERROR: Bad ASCII armor character, line %d.\n"), line); gotcrc = 1; /* this will print part number, continue with next part */ ret_code = -1; } - if (n > sizeof outbuf) - { fprintf(pgpout,PSTR("ERROR: Bad ASCII armor line length %d on line %d.\n"), + if (n > sizeof outbuf) { + fprintf(pgpout,LANG("ERROR: Bad ASCII armor line length %d on line %d.\n"), n, line); return -1; } crc = crcbytes((byte *)outbuf, n, crc); - if (fwrite(outbuf,1,n,out) != n) - { ret_code = -1; + if (fwrite(outbuf,1,n,out) != n) { + ret_code = -1; break; } } /* line */ - if (gotcrc) - { if (chkcrc != crc) - { fprintf(pgpout,PSTR("ERROR: Bad ASCII armor checksum")); + if (gotcrc) { + if (chkcrc != crc) { + fprintf(pgpout,LANG("ERROR: Bad ASCII armor checksum")); if (noSections > 0) - fprintf(pgpout,PSTR(" in section %d"), noSections); + fprintf(pgpout,LANG(" in section %d"), noSections); fputc('\n',pgpout); return -1; } + } else { + fprintf(pgpout,LANG("Warning: Transport armor lacks a checksum.\n")); } - else - fprintf(pgpout,PSTR("Warning: Transport armor lacks a checksum.\n")); - return(ret_code); /* normal return */ + return ret_code; /* normal return */ } /* pemdecode */ @@ -856,40 +851,37 @@ boolean is_pemfile(char *infile) int n, status; long il; - if ((in = fopen(infile, FOPRPEM)) == NULL) - { /* can't open file */ - return(FALSE); + if ((in = fopen(infile, FOPRPEM)) == NULL) { + /* can't open file */ + return FALSE; } /* Read to infile_line before we begin looking */ - for (il=0; il