X-Git-Url: https://git.distorted.org.uk/~mdw/become/blobdiff_plain/c4f2d992e4a0fc068281376d89ec38de56dc2f58..c758e6541ca05409b178dd9629e9337494c49890:/src/crypt.c diff --git a/src/crypt.c b/src/crypt.c index 86ed605..1c400aa 100644 --- a/src/crypt.c +++ b/src/crypt.c @@ -1,13 +1,13 @@ /* -*-c-*- * - * $Id: crypt.c,v 1.1 1997/07/21 13:47:51 mdw Exp $ + * $Id: crypt.c,v 1.4 1998/01/12 16:45:55 mdw Exp $ * * Cryptographic transfer of `become' requests * - * (c) 1997 EBI + * (c) 1998 EBI */ -/*----- Licencing notice --------------------------------------------------* +/*----- Licensing notice --------------------------------------------------* * * This file is part of `become' * @@ -22,14 +22,28 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with `become'; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * along with `become'; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*----- Revision history --------------------------------------------------* * * $Log: crypt.c,v $ - * Revision 1.1 1997/07/21 13:47:51 mdw + * Revision 1.4 1998/01/12 16:45:55 mdw + * Fix copyright date. + * + * Revision 1.3 1997/09/26 09:14:58 mdw + * Merged blowfish branch into trunk. + * + * Revision 1.2.2.1 1997/09/26 09:08:02 mdw + * Use the Blowfish encryption algorithm instead of IDEA. This is partly + * because I prefer Blowfish (without any particularly strong evidence) but + * mainly because IDEA is patented and Blowfish isn't. + * + * Revision 1.2 1997/08/04 10:24:21 mdw + * Sources placed under CVS control. + * + * Revision 1.1 1997/07/21 13:47:51 mdw * Initial revision * */ @@ -48,73 +62,27 @@ /* --- Unix headers --- */ #include +#include #include #include #include /* --- Local headers --- */ +#include "become.h" +#include "blowfish.h" #include "config.h" #include "crypt.h" #include "icrypt.h" -#include "idea.h" #include "md5.h" +#include "noise.h" +#include "rand.h" #include "tx.h" #include "utils.h" /*----- Magic numbers -----------------------------------------------------*/ -#define crypt__timeError 15 /* Seconds error to permit */ -#define crypt__seedBits 512 /* Number of random seed bits */ - -/*----- Dump a block of data ----------------------------------------------*/ - -/* --- @crypt__dump@ --- * - * - * Arguments: @char *p@ = a string to display at the top of the message - * @unsigned char *buf@ = pointer to a buffer to display - * @size_t sz@ = size of the buffer - * @FILE *fp@ = file to dump on - * - * Returns: -- - * - * Use: Dumps a block of data to the terminal. This allows a - * programmer to examine the traffic between client and server, - * and possibly locate bugs. - */ - -#ifndef NDEBUG - -static void crypt__dump(const char *p, const unsigned char *buf, - int sz, FILE *fp) -{ - int i; - fprintf(stderr,"+++ %s\n",p); - while (sz>0) - { - fprintf(stderr,"+++ "); - for (i=0;i<8;i++) - { - if (i 128) { - unsigned char tb[MD5_HASHSIZE]; - int i; - - memcpy(tb, s + crypt__seedBits / 8 - sizeof(tb), sizeof(tb)); - memmove(s + sizeof(tb), s, crypt__seedBits / 8 - sizeof(tb)); - memcpy(s, tb, sizeof(tb)); - for (i = 0; i < sizeof(sk); i++) - s[i] ^= sk[i]; - burn(tb); - } - - /* --- Take the seed we have and hash it again to get an IV --- */ + /* --- Encrypt the pool using the secret key --- */ { - unsigned char mdv[MD5_HASHSIZE]; - md5 md; - - md5_init(&md); - md5_buffer(&md, b, sizeof(b)); - md5_buffer(&md, k, IDEA_KEYSIZE); - md5_buffer(&md, s, sizeof(s)); - md5_final(&md, mdv); - memcpy(iv, mdv, IDEA_BLKSIZE); - crypt__dump("IV", iv, IDEA_BLKSIZE, stdout); - burn(md); burn(mdv); + icrypt_job j; + icrypt_init(&j, k, BLOWFISH_KEYSIZE, 0); + rand_encrypt(&j); + burn(j); } + /* --- Generate the session key and IV --- */ - /* --- Lock the file again --- * - * - * We're closing the file after we've finished, so we don't need to - * unlock it afterwards. - */ + noise_acquire(); + rand_extract(sk, BLOWFISH_KEYSIZE); + rand_extract(iv, BLOWFISH_BLKSIZE); + + IF_TRACING(TRACE_CRYPTO, + traceblk(TRACE_CRYPTO, "crypto: session key:", sk, BLOWFISH_KEYSIZE); + traceblk(TRACE_CRYPTO, "crypto: initialisation vector:", + iv, BLOWFISH_BLKSIZE); + ); - crypt__dump("Final seed", s, crypt__seedBits / 8, stdout); + /* --- Write the seed back --- */ rewind(fp); - tx_putBits(s, crypt__seedBits, fp); + rand_write(fp); fclose(fp); - /* --- Destroy sensitive data --- */ - - burn(b); burn(s); } /* --- @crypt_packRequest@ --- * @@ -259,12 +182,17 @@ void crypt_packRequest(request *rq, unsigned char *buff, { /* --- First, build the easy stuff in the block --- */ - buff[crq_cryptType] = cryptType_idea; + buff[crq_cryptType] = cryptType_blowfish; store32(buff + crq_time, t); store32(buff + crq_pid, pid); store32(buff + crq_from, rq->from); store32(buff + crq_to, rq->to); + /* --- Now generate session keys and things --- */ + + crypt__sessionKey(file_RANDSEED, k, sk, buff + crq_iv); + memcpy(buff + crq_session, sk, BLOWFISH_KEYSIZE); + /* --- The string causes a few problems --- * * * There's a good chance that the string will be a good deal shorter than @@ -273,54 +201,49 @@ void crypt_packRequest(request *rq, unsigned char *buff, * version of this code used @strncpy@ which is even worse!) * * I'll fill the block with random (from @rand@(3) -- nothing too - * elaborate) and then encrypt it using IDEA in CFB mode, using the first - * few bytes as the key. This should provide a sufficiently unpredictable - * background for the block. + * elaborate) and then encrypt it using Blowfish in CFB mode, using the + * first few bytes as the key. This should provide a sufficiently + * unpredictable background for the block. */ { icrypt_job j; unsigned char *p; unsigned u; + md5 md; + unsigned char qk[BLOWFISH_KEYSIZE]; /* --- Initialise the buffer with junk --- */ srand((unsigned int)(t ^ pid)); /* Seed the (bad) RNG */ for (p = buff + crq_cmd; p < buff + crq_cmd + CMDLEN_MAX; p++) { - u = rand(); - *p = u ^ (u >> 8); + u = rand(); *p = u ^ (u >> 8); } /* --- Now make the junk a whole lot harder to predict --- */ p = buff + crq_cmd; - icrypt_init(&j, p, 0); + md5_init(&md); md5_buffer(&md, p, CMDLEN_MAX); md5_final(&md, qk); + icrypt_init(&j, qk, BLOWFISH_KEYSIZE, 0); icrypt_encrypt(&j, p, p, CMDLEN_MAX); - burn(j); + burn(j); burn(qk); burn(md); /* --- Copy the string into here --- */ strcpy((char *)buff + crq_cmd, rq->cmd); } - /* --- Generate a session key --- */ - - { - crypt__sessionKey(file_RANDSEED, k, t, pid, sk, buff + crq_iv); - memcpy(buff + crq_session, sk, IDEA_KEYSIZE); - } - /* --- Checksum the finished data --- */ { md5 md; - unsigned char mdv[MD5_HASHSIZE]; + unsigned char mdbuf[MD5_HASHSIZE]; md5_init(&md); md5_buffer(&md, buff + crq_cipher, crq_check - crq_cipher); - md5_final(&md, mdv); - memcpy(buff + crq_check, mdv, 4); - burn(md); burn(mdv); + md5_final(&md, mdbuf); + memcpy(buff + crq_check, mdbuf, 4); + burn(md); burn(mdbuf); } /* --- Encrypt the block --- * @@ -334,16 +257,33 @@ void crypt_packRequest(request *rq, unsigned char *buff, { icrypt_job j; - crypt__dump("request, before encryption", buff, crq_size, stdout); + T( traceblk(TRACE_CRYPTO, "crypto: plaintext request:", + buff, crq_size); ) + + T( traceblk(TRACE_CRYPTO, "crypto: master key:", k, BLOWFISH_KEYSIZE); ) + T( traceblk(TRACE_CRYPTO, "crypto: initial iv:", + buff + crq_iv, BLOWFISH_BLKSIZE); ) + T( traceblk(TRACE_CRYPTO, "crypto: session key:", + sk, BLOWFISH_KEYSIZE); ) + + icrypt_init(&j, k, BLOWFISH_KEYSIZE, buff + crq_iv); + + icrypt_encrypt(&j, buff + crq_session, + buff + crq_session, BLOWFISH_KEYSIZE); + T( traceblk(TRACE_CRYPTO, "crypto: encrypted session key:", + buff + crq_session, BLOWFISH_KEYSIZE); ) + + icrypt_reset(&j, sk, BLOWFISH_KEYSIZE, 0); + + T( traceblk(TRACE_CRYPTO, "crypto: partial iv:", + j.iv, BLOWFISH_BLKSIZE); ) - icrypt_init(&j, k, buff + crq_iv); - icrypt_encrypt(&j, buff + crq_session, buff + crq_session, IDEA_KEYSIZE); - icrypt_reset(&j, sk, 0); icrypt_encrypt(&j, buff + crq_cipher, buff + crq_cipher, crq_size - crq_cipher); burn(j); - crypt__dump("request, after encryption", buff, crq_size, stdout); + T( traceblk(TRACE_CRYPTO, "crypto: ciphertext request:", + buff, crq_size); ) } } @@ -367,7 +307,7 @@ int crypt_unpackRequest(request *rq, unsigned char *buff, { /* --- Check the encryption format --- */ - if (buff[crq_cryptType] != cryptType_idea) + if (buff[crq_cryptType] != cryptType_blowfish) return (0); } @@ -376,36 +316,55 @@ int crypt_unpackRequest(request *rq, unsigned char *buff, icrypt_job j; - crypt__dump("request, before decryption", buff, crq_size, stdout); + T( traceblk(TRACE_CRYPTO, "crypto: ciphertext request:", + buff, crq_size); ) + + T( traceblk(TRACE_CRYPTO, "crypto: master key:", k, BLOWFISH_KEYSIZE); ) + T( traceblk(TRACE_CRYPTO, "crypto: initial iv:", + buff + crq_iv, BLOWFISH_BLKSIZE); ) + + icrypt_init(&j, k, BLOWFISH_KEYSIZE, buff + crq_iv); + T( traceblk(TRACE_CRYPTO, "crypto: job block:", &j, sizeof(j)); ) + + T( traceblk(TRACE_CRYPTO, "crypto: encrypted session key:", + buff + crq_session, BLOWFISH_KEYSIZE); ) + icrypt_decrypt(&j, buff + crq_session, + buff + crq_session, BLOWFISH_KEYSIZE); + memcpy(sk, buff + crq_session, BLOWFISH_KEYSIZE); + T( traceblk(TRACE_CRYPTO, "crypto: session key:", + sk, BLOWFISH_KEYSIZE); ) + + icrypt_reset(&j, sk, BLOWFISH_KEYSIZE, 0); + + T( traceblk(TRACE_CRYPTO, "crypto: partial iv:", + j.iv, BLOWFISH_BLKSIZE); ) - icrypt_init(&j, k, buff + crq_iv); - icrypt_decrypt(&j, buff + crq_session, buff + crq_session, IDEA_KEYSIZE); - memcpy(sk, buff + crq_session, IDEA_KEYSIZE); - icrypt_reset(&j, sk, 0); icrypt_decrypt(&j, buff + crq_cipher, buff + crq_cipher, crq_size - crq_cipher); icrypt_saveIV(&j, rpl + crp_iv); - memset(buff + crq_session, 0, IDEA_KEYSIZE); /* Burn, baby, burn */ - burn(j); + T( traceblk(TRACE_CRYPTO, "crypto: plaintext request:", + buff, crq_size); ) - crypt__dump("request, after decryption", buff, crq_size, stdout); + memset(buff + crq_session, 0, BLOWFISH_KEYSIZE); /* Burn, baby, burn */ + burn(j); } { /* --- Check the validity of the data therein --- */ md5 md; - unsigned char mdv[MD5_HASHSIZE]; + unsigned char mdbuf[MD5_HASHSIZE]; md5_init(&md); md5_buffer(&md, buff + crq_cipher, crq_check - crq_cipher); - md5_final(&md, mdv); - if (memcmp(mdv, buff + crq_check, 4) != 0) { + md5_final(&md, mdbuf); + if (memcmp(mdbuf, buff + crq_check, 4) != 0) { syslog(LOG_INFO, "packet rejected: bad checksum"); + T( trace(TRACE_CRYPTO, "crypto: bad checksum on incoming request"); ) return (0); } - burn(md); burn(mdv); + burn(md); burn(mdbuf); } { @@ -424,6 +383,7 @@ int crypt_unpackRequest(request *rq, unsigned char *buff, if (t - u > crypt__timeError || u - t > crypt__timeError) { syslog(LOG_INFO, "packet rejected: bad time"); + T( trace(TRACE_CRYPTO, "crypto: bad time on incoming request"); ) return (0); } memcpy(rpl + crp_time, buff + crq_time, 8); @@ -431,6 +391,7 @@ int crypt_unpackRequest(request *rq, unsigned char *buff, /* --- Done --- */ + T( trace(TRACE_CRYPTO, "crypto: valid request received"); ) return (1); } @@ -457,25 +418,28 @@ void crypt_packReply(unsigned char *buff, unsigned char *sk, int answer) /* --- Build the checksum --- */ md5 md; - unsigned char mdv[MD5_HASHSIZE]; + unsigned char mdbuf[MD5_HASHSIZE]; md5_init(&md); md5_buffer(&md, buff + crp_cipher, crp_check - crp_cipher); - md5_final(&md, mdv); - memcpy(buff + crp_check, mdv, 4); - burn(md); burn(mdv); + md5_final(&md, mdbuf); + memcpy(buff + crp_check, mdbuf, 4); + burn(md); burn(mdbuf); } { /* --- Encrypt the buffer --- */ icrypt_job j; - icrypt_init(&j, sk, buff + crp_iv); - crypt__dump("reply, before encryption", buff, crp_size, stdout); + + T( traceblk(TRACE_CRYPTO, "crypto: plaintext reply:", buff, crp_size); ) + + icrypt_init(&j, sk, BLOWFISH_KEYSIZE, buff + crp_iv); icrypt_encrypt(&j, buff + crp_cipher, buff + crp_cipher, crp_size - crp_cipher); - crypt__dump("reply, after encryption", buff, crp_size, stdout); burn(j); + + T( traceblk(TRACE_CRYPTO, "crypto: ciphertext reply:", buff, crp_size); ) } } @@ -498,28 +462,32 @@ int crypt_unpackReply(unsigned char *buff, unsigned char *sk, /* --- Decrypt my reply block --- */ icrypt_job j; - icrypt_init(&j, sk, buff + crp_iv); - crypt__dump("reply, before decryption", buff, crp_size, stdout); + + T( traceblk(TRACE_CRYPTO, "crypto: ciphertext reply:", buff, crp_size); ) + + icrypt_init(&j, sk, BLOWFISH_KEYSIZE, buff + crp_iv); icrypt_decrypt(&j, buff + crp_cipher, buff + crp_cipher, crp_size - crp_cipher); - crypt__dump("reply, after decryption", buff, crp_size, stdout); burn(j); + + T( traceblk(TRACE_CRYPTO, "crypto: plaintext reply:", buff, crp_size); ) } { /* --- Check validity --- */ md5 md; - unsigned char mdv[MD5_HASHSIZE]; + unsigned char mdbuf[MD5_HASHSIZE]; char b[8]; /* --- Check the checksum --- */ md5_init(&md); md5_buffer(&md, buff + crp_cipher, crp_check - crp_cipher); - md5_final(&md, mdv); - if (memcmp(buff + crp_check, mdv, 4) != 0) { + md5_final(&md, mdbuf); + if (memcmp(buff + crp_check, mdbuf, 4) != 0) { syslog(LOG_INFO, "reply rejected: bad checksum"); + T( trace(TRACE_CRYPTO, "crypto: bad checksum on reply"); ) return (-1); } @@ -528,12 +496,14 @@ int crypt_unpackReply(unsigned char *buff, unsigned char *sk, store32(b + 0, t); store32(b + 4, pid); if (memcmp(b, buff + crp_time, sizeof(b)) != 0) { syslog(LOG_INFO, "reply rejected: bad identification marker"); + T( trace(TRACE_CRYPTO, "crypto: bad id on reply"); ) return (-1); } } /* --- Return the value --- */ + T( trace(TRACE_CRYPTO, "crypto: valid reply received"); ) return (buff[crp_answer]); } @@ -543,13 +513,12 @@ int crypt_unpackReply(unsigned char *buff, unsigned char *sk, int main(int argc, char *argv[]) { - time_t t = time(0); - pid_t pid = getpid(); unsigned char buff[8]; - unsigned char sk[IDEA_KEYSIZE], k[IDEA_KEYSIZE]; + unsigned char sk[BLOWFISH_KEYSIZE], k[BLOWFISH_KEYSIZE]; FILE *fp; ego(argv[0]); + traceon(stdout, TRACE_CRYPTO); if (argc < 3) die("bad args"); fp = fopen(argv[1], "r"); @@ -557,7 +526,7 @@ int main(int argc, char *argv[]) die("fopen: %s", strerror(errno)); tx_getBits(k, 128, fp); fclose(fp); - crypt__sessionKey(argv[2], k, t, pid, sk, buff); + crypt__sessionKey(argv[2], k, sk, buff); return (0); }