--- pgp/src/crypto.c 2018/04/24 16:39:34 1.1.1.3 +++ pgp/src/crypto.c 2018/04/24 16:40:26 1.1.1.4 @@ -27,6 +27,9 @@ Modified 25-Feb-93 Colin Plumb Improved security of randseed.bin in strong_pseudorandom. Thoroughly revamped make_random_ideakey. + + Modified 6-May-93 Colin Plumb + Changed to use the entry points in rsaglue.c. */ #include @@ -49,6 +52,7 @@ #include "pgp.h" #include "exitpgp.h" #include "zipup.h" +#include "rsaglue.h" #define ENCRYPT_IT FALSE /* to pass to idea_file */ #define DECRYPT_IT TRUE /* to pass to idea_file */ @@ -320,6 +324,7 @@ version_error(int val, int checkval) /*-------------------------------------------------------------------------*/ #define RAND_PREFIX_LENGTH 8 /* Length of IV for IDEA encryption */ +#define RANDSEED_SIZE 24 /* Size of randseed.bin file */ int seedfile_exists(void) /* @@ -332,7 +337,7 @@ int seedfile_exists(void) buildfilename(seedfile,RANDSEED_FILENAME); if (file_exists(seedfile)) return 1; /* True */ - randaccum_later(8*(IDEAKEYSIZE+RAND_PREFIX_LENGTH)); + randaccum_later(8*RANDSEED_SIZE); return 0; } @@ -344,7 +349,7 @@ void create_seedfile(void) */ { char seedfile[MAX_PATH]; /* Random seed filename */ FILE *f; - byte randbuf[IDEAKEYSIZE+RAND_PREFIX_LENGTH]; + byte randbuf[RANDSEED_SIZE]; int i; buildfilename(seedfile,RANDSEED_FILENAME); @@ -356,17 +361,17 @@ void create_seedfile(void) /* This is not part of the string above because it was changed after the 2.2 release translations were started. It should be cleaned up eventually. */ fputc('\n', pgpout); - for (i=1; idigest, sizeof(MD->digest), n, NULL); -#else /* ! PKCS_COMPAT */ -/* Assume MSB external byte ordering */ - mdpacket[0] = MD5_ALGORITHM_BYTE; - mdbufptr = MD->digest; /* point at actual message digest */ - for (i=1; idigest; - certificate[certificate_length++] = *mdbufptr++; - certificate[certificate_length++] = *mdbufptr++; + certificate[certificate_length++] = md5buf[0]; + certificate[certificate_length++] = md5buf[1];; /* Now append the RSA-signed message digest packet: */ for (i=0; i 93-02-25 */ - if (*password) - memset(password, 0, sizeof(password)); - - if (getsecretkey(0, NULL, NULL, timestamp, NULL, NULL, + if (getsecretkey(GPK_ASKPASS, NULL, NULL, timestamp, NULL, NULL, userid, n, e, d, p, q, u) < 0) { fclose(f); return(-1); /* problem with secret key file. error return. */ } certificate_length = make_signature_certificate(certificate, &MD, - K0_SIGNATURE_BYTE, n, d, p, q, u); + K0_SIGNATURE_BYTE, e, d, p, q, u, n); if (certificate_length < 0) return(-1); /* error return from make_signature_certificate() */ @@ -1317,6 +1305,7 @@ int check_signaturefile(char *infile, ch word32 dummystamp; byte userid[256]; MD5_CTX MD; + byte digest[16]; boolean separate_signature; boolean fixedLiteral = FALSE; /* Whether it's a fixed literal2 packet */ extern char **myArgv; @@ -1557,15 +1546,11 @@ int check_signaturefile(char *infile, ch goto outsig; } /* Can't find public key */ - /* Recover message digest via public key */ - mp_modexp((unitptr)outbuf,(unitptr)inbuf,e,n); + count = rsa_public_decrypt(outbuf, (unitptr)inbuf, e, n); if (!quietmode) fputc('.',pgpout); /* Signal RSA completion. */ - /* Unblock message digest, and convert to external byte order: */ - count = postunblock(outbuf, (unitptr)outbuf, n); - if (count == -1) { fprintf(pgpout,PSTR("\n\007Error: RSA-decrypted block is corrupted.\n\ This may be caused either by corrupted data or by using the wrong RSA key.\n")); @@ -1576,9 +1561,7 @@ This may be caused either by corrupted d /*==================================================================*/ /* Look at nested stuff within RSA block... */ - if (count == -2 || - (count != sizeof(MD.digest) && count != sizeof(MD.digest)+1) || - (count == sizeof(MD.digest)+1 && outbuf[0] != MD5_ALGORITHM_BYTE)) + if (count == -2 || count != sizeof(digest)) { fprintf(pgpout,PSTR("\007\nUnrecognized message digest algorithm.\n")); fprintf(pgpout,PSTR("This may require a newer version of PGP.\n")); fprintf(pgpout,PSTR("Can't check signature integrity.\n")); @@ -1586,7 +1569,7 @@ This may be caused either by corrupted d } /* Distinguish PKCS-compatible from pre-3.3 which has an extra byte */ - outbufoffset = (count==sizeof(MD.digest)) ? 0 : 1; + outbufoffset = (count==sizeof(digest)) ? 0 : 1; if (outbuf[outbufoffset] != mdlow2[0] || outbuf[outbufoffset+1] != mdlow2[1]) @@ -1600,14 +1583,14 @@ This may be caused either by corrupted d MDfile0_len(&MD,f,text_len);/* compute a message digest from rest of file */ - MD_addbuffer (&MD, mdextras, mdlensave, TRUE); /* Finish message digest */ + MD_addbuffer (&MD, mdextras, mdlensave, digest); /* Finish message digest */ convert_byteorder(timestamp,4); /* convert timestamp from external form */ PascalToC((char *)userid); /* for display */ /* now compare computed MD with claimed MD */ /* Assume MSB external byte ordering */ - if (!equal_buffers((byte *)(MD.digest), outbuf+outbufoffset, 16)) + if (!equal_buffers(digest, outbuf+outbufoffset, 16)) { #ifndef CANONICAL_TEXT /* IF the signature is bad, AND this machine does not use MSDOS-style @@ -1633,7 +1616,7 @@ This may be caused either by corrupted d /* Move back to the start of the file and recalculate the MD */ rewind( tempFile ); MDfile0_len( &MD, tempFile, -1L ); - MD_addbuffer( &MD, mdextras, mdlensave, TRUE ); + MD_addbuffer( &MD, mdextras, mdlensave, digest ); /* Clean up behind us */ fclose( tempFile ); @@ -1641,7 +1624,7 @@ This may be caused either by corrupted d /* Check if the signature is OK this time round */ /* Assume MSB external byte ordering */ - if(equal_buffers((byte *)(MD.digest),outbuf+outbufoffset,16)) + if(equal_buffers(digest, outbuf+outbufoffset, 16)) goto goodsig; } } @@ -1788,6 +1771,7 @@ int check_key_sig(FILE *fkey, long fpkey byte outbuf[MAX_BYTE_PRECISION]; byte keyID[KEYFRAGSIZE]; MD5_CTX MD; + byte digest[16]; byte mdlensave; byte *mdextras; word32 tstamp; @@ -1797,7 +1781,6 @@ int check_key_sig(FILE *fkey, long fpkey byte class; byte algorithm; byte mdlow2[2]; - int outbufoffset; fill0( keyID, KEYFRAGSIZE ); @@ -1887,30 +1870,20 @@ int check_key_sig(FILE *fkey, long fpkey ((certificate-certbuf) - (cert_length+3)) */ goto badcert2; /* complain and return bad status */ - /* Recover message digest via public key */ - mp_modexp((unitptr)outbuf,(unitptr)inbuf,e,n); - - /* Unblock message digest, and convert to external byte order: */ - count = postunblock(outbuf, (unitptr)outbuf, n); + count = rsa_public_decrypt(outbuf, (unitptr)inbuf, e, n); if (count == -2) goto err1; /* Unrecognized digest algorithm */ - if (count != sizeof(MD.digest) && count != sizeof(MD.digest)+1) + if (count != sizeof(digest)) goto err2; /* Bad RSA decrypt. Corruption, or wrong key. */ - /* Distinguish PKCS-compatible from pre-3.3 which has an extra byte */ - outbufoffset = (count==sizeof(MD.digest)) ? 0 : 1; - /* outbuf should contain message digest packet */ /*==================================================================*/ /* Look at nested stuff within RSA block... */ /* Assume MSB external byte ordering */ - if (outbufoffset && outbuf[0] != MD5_ALGORITHM_BYTE) - goto err2; /* Bad RSA decrypt. Corruption, or wrong key. */ - if (outbuf[outbufoffset] != mdlow2[0] || - outbuf[outbufoffset+1] != mdlow2[1]) + if (outbuf[0] != mdlow2[0] || outbuf[1] != mdlow2[1]) goto err2; /* Bad RSA decrypt. Corruption, or wrong key. */ /* Position file to where that plaintext begins... */ @@ -1922,11 +1895,11 @@ int check_key_sig(FILE *fkey, long fpkey if (class != KC_SIGNATURE_BYTE) MD5Update(&MD, (unsigned char *) keyuserid+1, (int)(unsigned char)keyuserid[0]); /* Add time and class data */ - MD_addbuffer (&MD, mdextras, mdlensave, TRUE); /* Finish message digest */ + MD_addbuffer (&MD, mdextras, mdlensave, digest); /* Finish message digest */ /* now compare computed MD with claimed MD */ /* Assume MSB external byte ordering */ - if (!equal_buffers((byte *)(MD.digest), outbuf+outbufoffset, 16)) + if (!equal_buffers(digest, outbuf, 16)) goto err2; convert_byteorder(timestamp,4); /* convert timestamp from external form */ @@ -2090,7 +2063,7 @@ int idea_encryptfile(char *infile, char FILE *f; /* input file */ FILE *g; /* output file */ byte ideakey[16]; - byte passphrase[256]; + struct hashedpw *hpw; if (verbose) fprintf(pgpout,"idea_encryptfile: infile = '%s', outfile = '%s'\n", @@ -2112,12 +2085,17 @@ int idea_encryptfile(char *infile, char } /* Get IDEA password, hashed to a key */ - if (*password != '\0') - hashpass(password, strlen(password), ideakey); - else { - if (!quietmode) + if (passwds) + { memcpy(ideakey, passwds->hash, sizeof(ideakey)); + memset(passwds->hash, 0, sizeof(passwds->hash)); + hpw = passwds; + passwds = passwds->next; + free(hpw); + } + else + { if (!quietmode) fprintf(pgpout,PSTR("\nYou need a pass phrase to encrypt the file. ")); - if (batchmode || GetHashedPassPhrase((char *)passphrase,(char *)ideakey,NOECHO2) <= 0) + if (batchmode || GetHashedPassPhrase((char *)ideakey,NOECHO2) <= 0) { fclose(f); fclose(g); return(-1); @@ -2133,7 +2111,6 @@ int idea_encryptfile(char *infile, char squish_and_idea_file( ideakey, f, g, attempt_compression ); burn(ideakey); /* burn sensitive data on stack */ - burn(passphrase); fclose(f); if (write_error(g)) @@ -2210,14 +2187,10 @@ int encryptfile(char **mcguffins, char * MD5Init(&MD); MDfile0_len(&MD, f, 4096); /* Ignore errors - what could be done? */ - MD5Final(&MD); + MD5Final(md5buf, &MD); + already_have_md5 = 1; fseek(f, 0, SEEK_SET); /* Get back to the beginning for encryption */ - - memcpy(md5buf, MD.digest, 16); - - burn(&MD); - already_have_md5 = 1; } ckp_length = make_random_ideakey(ideakey); @@ -2299,7 +2272,6 @@ static int encryptkeyintofile(FILE *g, char *mcguffin, byte *keybuf, char *keyfile, int ckp_length, int keys_used) { int i; - byte randompad[MAX_BYTE_PRECISION]; /* buffer of random pad bytes */ unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION]; byte keyID[KEYFRAGSIZE]; byte inbuf[MAX_BYTE_PRECISION]; @@ -2370,40 +2342,16 @@ This user will not be able to decrypt th continue; } - - /* - ** Messages encrypted with a public key should use - ** random padding, while messages "signed" with a - ** secret key should use constant padding. - */ - - for (i = 0; i < (blocksize - ckp_length); i++) - while (!(randompad[i] = idearand())) - ; /* Allow only nonzero values */ - - /* - ** Note that RSA key must be at least big enough - ** to encipher a complete conventional key packet - ** in a single RSA block. - */ - - /* ckp_length is conventional key packet length. */ - - /* Do the padding here */ - preblock( (unitptr)inbuf, keybuf, ckp_length, n, randompad ); - - /* XXX This is dangerous... This will print out the - * IDEA Key, which is a breach of security! - */ #ifdef MR_DEBUG - fprintf(pgpout, "IdeaKey and Random Pad: "); - for (i = 0; i < blocksize; i++) { - fprintf(pgpout, "%02X ", inbuf[i]); - } + /* XXX This is dangerous... This will print out the + * IDEA Key, which is a breach of security! + */ + fprintf(pgpout, "Idea Key: "); + for (i = 0; i < ckp_length; i++) + fprintf(pgpout, "%02X ", keybuf[i]); fprintf(pgpout, "\n"); #endif - mp_modexp( (unitptr)outbuf, (unitptr)inbuf, e, n ); - /* RSA encrypt */ + rsa_public_encrypt((unitptr)outbuf, keybuf, ckp_length, e, n); /* write out header record to outfile ... */ @@ -2732,7 +2680,7 @@ int decryptfile(char *infile, char *outf byte ctbCKE; /* Cipher Type Byte */ FILE *f; FILE *g; - int count, status, thiskey, gotkey, end_of_pkes; + int count = 0, status, thiskey, gotkey, end_of_pkes; unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION], d[MAX_UNIT_PRECISION]; unit p[MAX_UNIT_PRECISION], q[MAX_UNIT_PRECISION], u[MAX_UNIT_PRECISION]; byte inbuf[MAX_BYTE_PRECISION]; @@ -2824,9 +2772,9 @@ int decryptfile(char *infile, char *outf if (!gotkey) /* Only do this if we havent already */ /* Get and validate secret key from a key file: */ - if (getsecretkey(GPK_GIVEUP|(quietmode?0:GPK_SHOW), NULL, keyID, - timestamp, NULL, NULL,userid, - n, e, d, p, q, u) == 0) + if (getsecretkey(GPK_GIVEUP|(quietmode?0:GPK_SHOW), + NULL, keyID, timestamp, NULL, NULL, + userid, n, e, d, p, q, u) == 0) { thiskey = gotkey = 1; realprecision = global_precision; @@ -2852,15 +2800,20 @@ int decryptfile(char *infile, char *outf read_mpi((unitptr)inbuf, f, FALSE, FALSE); if (thiskey) { - if (!quietmode && thiskey) { + if (!quietmode) { fprintf(pgpout,PSTR("Just a moment...")); /* RSA will take a while. */ fflush(pgpout); } - - rsa_decrypt((unitptr)outbuf, (unitptr)inbuf, d, - p, q, u); - + count = rsa_private_decrypt(outbuf, (unitptr)inbuf, + e, d, p, q, u, n); + if (count < 0) + { fprintf(pgpout, +PSTR("\n\007Error: RSA-decrypted block is corrupted.\n\ +This may be caused either by corrupted data or by using the wrong RSA key.\n")); + fclose(f); + return(-1); + } if (!quietmode) fputc('.',pgpout); /* Signal RSA completion. */ @@ -2910,14 +2863,6 @@ int decryptfile(char *infile, char *outf fclose(f); return(-1); } - - if ((count = postunblock(outbuf, (unitptr)outbuf, n)) < 0) - { fprintf(pgpout,PSTR("\n\007Error: RSA-decrypted block is corrupted.\n\ -This may be caused either by corrupted data or by using the wrong RSA key.\n")); - fclose(f); - return(-1); - } - /* Verify that top of buffer has correct algorithm byte */ --count; /* one less byte to drop algorithm byte */ /* Assume MSB external byte ordering */ @@ -3001,8 +2946,8 @@ int idea_decryptfile(char *infile, char FILE *f; FILE *g; byte ideakey[16]; - byte passphrase[256]; int status, retries = 0; + struct hashedpw *hpw, **hpwp; word32 flen; if (verbose) @@ -3021,8 +2966,10 @@ int idea_decryptfile(char *infile, char goto err1; } - if (*password == '\0') - ++retries; /* no PGPPASS or -z */ + /* First, try all pre-specified passwords */ + hpwp = &passwds; + hpw = *hpwp; + do /* while pass phrase is bad */ { fread(&ctb,1,1,f); /* read Cipher Type Byte, should be CTB_CKE */ @@ -3036,12 +2983,13 @@ int idea_decryptfile(char *infile, char flen = getpastlength(ctb, f); /* read packet length */ /* Get IDEA password, hashed */ - if (retries == 0) - /* first try environment password */ - hashpass(password, strlen(password), ideakey); - else { - fprintf(pgpout,PSTR("\nYou need a pass phrase to decrypt this file. ")); - if (batchmode || GetHashedPassPhrase((char *)passphrase,(char *)ideakey,NOECHO1) <= 0) + if (hpw) + { /* first try environment passwords */ + memcpy(ideakey, hpw->hash, sizeof(ideakey)); + } + else + { fprintf(pgpout,PSTR("\nYou need a pass phrase to decrypt this file. ")); + if (batchmode || GetHashedPassPhrase((char *)ideakey,NOECHO1) <= 0) { fclose(f); fclose(g); return(-1); @@ -3055,15 +3003,29 @@ int idea_decryptfile(char *infile, char status = idea_file( ideakey, DECRYPT_IT, f, g, flen ); if (status == 0) + { if (hpw) + { /* "Use up" password. */ + *hpwp = hpw->next; + memset(hpw->hash, 0, sizeof(hpw->hash)); + free(hpw); + } break; - if (retries) /* first try is PGPPASS */ + } + if (hpw) + { /* Go to next available password */ + hpwp = &hpw->next; + hpw = *hpwp; + } + else + { ++retries; fprintf(pgpout,PSTR("\n\007Error: Bad pass phrase.\n")); + } + rewind(f); rewind(g); - } while (status == -2 && ++retries < 3); + } while (status == -2 && retries < 2); burn(ideakey); /* burn sensitive data on stack */ - burn(passphrase); if (status == 0 && !quietmode) fputc('.',pgpout); /* show progress */