Major overhaul. Now uses DSA signatures rather than the bogus symmetric
[become] / src / crypt.c
diff --git a/src/crypt.c b/src/crypt.c
deleted file mode 100644 (file)
index 549e94b..0000000
+++ /dev/null
@@ -1,542 +0,0 @@
-/* -*-c-*-
- *
- * $Id: crypt.c,v 1.5 1998/06/18 15:08:49 mdw Exp $
- *
- * Cryptographic transfer of `become' requests
- *
- * (c) 1998 EBI
- */
-
-/*----- Licensing notice --------------------------------------------------*
- *
- * This file is part of `become'
- *
- * `Become' is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * `Become' is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/*----- Revision history --------------------------------------------------*
- *
- * $Log: crypt.c,v $
- * Revision 1.5  1998/06/18 15:08:49  mdw
- * Paranoia: set close-on-exec flag for seed file.
- *
- * 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
- *
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-/* --- ANSI headers --- */
-
-#include <ctype.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-/* --- Unix headers --- */
-
-#include <sys/types.h>
-#include <sys/time.h>
-#include <unistd.h>
-#include <syslog.h>
-#include <fcntl.h>
-
-/* --- Local headers --- */
-
-#include "become.h"
-#include "blowfish.h"
-#include "config.h"
-#include "crypt.h"
-#include "icrypt.h"
-#include "md5.h"
-#include "noise.h"
-#include "rand.h"
-#include "tx.h"
-#include "utils.h"
-
-/*----- Magic numbers -----------------------------------------------------*/
-
-#define crypt__timeError 60            /* Seconds error to permit */
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @crypt__sessionKey@ --- *
- *
- * Arguments:  @const char *seedfile@ = pointer to name of seed file
- *             @unsigned char *k@ = our secret key
- *             @unsigned *sk@ = where to store the session key
- *             @unsigned char *iv@ = where to store the IV
- *
- * Returns:    ---
- *
- * Use:                Decides on a random session key and initialisation vector.
- */
-
-static void crypt__sessionKey(const char *seedfile, unsigned char *k,
-                             unsigned char *sk, unsigned char *iv)
-{
-  FILE *fp;                            /* File handle for reading */
-  struct flock l;
-  int ok = 1;
-
-  /* --- Open the random seed file --- *
-   *
-   * If I can't manage that, create a new one.
-   */
-
-  if ((fp = fopen(seedfile, "r+")) == 0) {
-    ok = 0;
-    if ((fp = fopen(seedfile, "w+")) == 0)
-      die("can't create random number file: %s", strerror(errno));
-    rand_clear();
-  }
-  if (fcntl(fileno(fp), F_SETFD, 1) < 0) {
-    die("can't set close-on-exec for random number file: %s",
-       strerror(errno));
-  }
-
-  /* --- Lock the seed file against concurrency problems --- */
-
-  l.l_type = F_WRLCK;
-  l.l_whence = SEEK_SET;
-  l.l_start = 0;
-  l.l_len = 0;
-  if (fcntl(fileno(fp), F_SETLKW, &l) < 0)
-    die("can't lock random number file: %s", strerror(errno));
-
-    /* --- Now read the file, and launder the seed --- */
-
-  if (ok)
-    rand_read(fp);
-
-  /* --- Encrypt the pool using the secret key --- */
-
-  {
-    icrypt_job j;
-    icrypt_init(&j, k, BLOWFISH_KEYSIZE, 0);
-    rand_encrypt(&j);
-    burn(j);
-  }
-
-  /* --- Generate the session key and IV --- */
-
-  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);
-  );
-
-  /* --- Write the seed back --- */
-
-  rewind(fp);
-  rand_write(fp);
-  fclose(fp);
-
-}
-
-/* --- @crypt_packRequest@ --- *
- *
- * Arguments:  @request *rq@ = pointer to request block
- *             @unsigned char *buff@ = pointer to a buffer
- *             @time_t t@ = the current time
- *             @pid_t pid@ = my process ID
- *             @unsigned char *k@ = pointer to 128-bit key
- *             @unsigned char *sk@ = where to put the session key
- *
- * Returns:    ---
- *
- * Use:                Packs a request block into a buffer.  The buffer should have
- *             space for at least @crq_size@ bytes.  The buffer comes back
- *             encrypted and ready to send.
- */
-
-void crypt_packRequest(request *rq, unsigned char *buff,
-                      time_t t, pid_t pid,
-                      unsigned char *k, unsigned char *sk)
-{
-  /* --- First, build the easy stuff in the block --- */
-
-  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
-   * the space allowed for it.  This will probably mean lots of zeroes, and a
-   * very easy known-plaintext job for a potential attacker.  (An early
-   * 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 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);
-    }
-
-    /* --- Now make the junk a whole lot harder to predict --- */
-
-    p = buff + crq_cmd;
-    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(qk); burn(md);
-
-    /* --- Copy the string into here --- */
-
-    strcpy((char *)buff + crq_cmd, rq->cmd);
-  }
-
-  /* --- Checksum the finished data --- */
-
-  {
-    md5 md;
-    unsigned char mdbuf[MD5_HASHSIZE];
-
-    md5_init(&md);
-    md5_buffer(&md, buff + crq_cipher, crq_check - crq_cipher);
-    md5_final(&md, mdbuf);
-    memcpy(buff + crq_check, mdbuf, 4);
-    burn(md); burn(mdbuf);
-  }
-
-  /* --- Encrypt the block --- *
-   *
-   * First, encrypt the session key using the master key.  Since the session
-   * key is effectively random, this makes cracking the master key much
-   * harder.  The rest of the block is then encrypted with the session key,
-   * using the IV left over from encrypting the session key.
-   */
-
-  {
-    icrypt_job j;
-
-    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_encrypt(&j, buff + crq_cipher,
-                  buff + crq_cipher, crq_size - crq_cipher);
-    burn(j);
-
-    T( traceblk(TRACE_CRYPTO, "crypto: ciphertext request:",
-               buff, crq_size); )
-  }
-}
-
-/* --- @crypt_unpackRequest@ --- *
- *
- * Arguments:  @reqest *rq@ = pointer to destination request block
- *             @unsigned char *buff@ = pointer to source buffer
- *             @unsigned char *k@ = pointer to encryption key
- *             @unsigned char *sk@ = pointer to where to store session key
- *             @unsigned char *rpl@ = where to start building reply
- *
- * Returns:    Nonzero if it was decrypted OK
- *
- * Use:                Decrypts and unpacks a request buffer.
- */
-
-int crypt_unpackRequest(request *rq, unsigned char *buff,
-                       unsigned char *k, unsigned char *sk,
-                       unsigned char *rpl)
-{
-  {
-    /* --- Check the encryption format --- */
-
-    if (buff[crq_cryptType] != cryptType_blowfish)
-      return (0);
-  }
-
-  {
-    /* --- First things first: decrypt the block --- */
-
-    icrypt_job j;
-
-    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_decrypt(&j, buff + crq_cipher,
-                  buff + crq_cipher, crq_size - crq_cipher);
-    icrypt_saveIV(&j, rpl + crp_iv);
-
-    T( traceblk(TRACE_CRYPTO, "crypto: plaintext request:",
-               buff, crq_size); )
-
-    memset(buff + crq_session, 0, BLOWFISH_KEYSIZE); /* Burn, baby, burn */
-    burn(j);
-  }
-
-  {
-    /* --- Check the validity of the data therein --- */
-
-    md5 md;
-    unsigned char mdbuf[MD5_HASHSIZE];
-
-    md5_init(&md);
-    md5_buffer(&md, buff + crq_cipher, crq_check - crq_cipher);
-    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(mdbuf);
-  }
-
-  {
-    /* --- Extract fields from the block --- */
-
-    rq->from = load32(buff + crq_from);
-    rq->to = load32(buff + crq_to);
-    memcpy(rq->cmd, buff + crq_cmd, CMDLEN_MAX);
-  }
-
-  {
-    /* --- Fill in bits of the reply block --- */
-
-    long t = (long)time(0);
-    long u = (long)load32(buff + crq_time);
-
-    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);
-  }
-
-  /* --- Done --- */
-
-  T( trace(TRACE_CRYPTO, "crypto: valid request received"); )
-  return (1);
-}
-
-/* --- @crypt_packReply@ --- *
- *
- * Arguments:  @char *buff@ = pointer to reply block
- *             @unsigned char *sk@ = pointer to session key
- *             @int answer@ = yes or no
- *
- * Returns:    ---
- *
- * Use:                Packs and encrypts a reply block.
- */
-
-void crypt_packReply(unsigned char *buff, unsigned char *sk, int answer)
-{
-  {
-    /* --- Store the answer --- */
-
-    buff[crp_answer] = (answer != 0);
-  }
-
-  {
-    /* --- Build the checksum --- */
-
-    md5 md;
-    unsigned char mdbuf[MD5_HASHSIZE];
-
-    md5_init(&md);
-    md5_buffer(&md, buff + crp_cipher, crp_check - crp_cipher);
-    md5_final(&md, mdbuf);
-    memcpy(buff + crp_check, mdbuf, 4);
-    burn(md); burn(mdbuf);
-  }
-
-  {
-    /* --- Encrypt the buffer --- */
-
-    icrypt_job j;
-
-    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);
-    burn(j);
-
-    T( traceblk(TRACE_CRYPTO, "crypto: ciphertext reply:", buff, crp_size); )
-  }
-}
-
-/* --- @crypt_unpackReply@ --- *
- *
- * Arguments:  @unsigned char *buff@ = pointer to reply buffer
- *             @unsigned char *sk@ = pointer to session key
- *             @time_t t@ = time at which request was sent
- *             @pid_t pid@ = my process ID
- *
- * Returns:    >0 if request granted, zero if denied, <0 if reply rejected
- *
- * Use:                Unpacks a reply block, and informs the caller of the outcome.
- */
-
-int crypt_unpackReply(unsigned char *buff, unsigned char *sk,
-                     time_t t, pid_t pid)
-{
-  {
-    /* --- Decrypt my reply block --- */
-
-    icrypt_job j;
-
-    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);
-    burn(j);
-
-    T( traceblk(TRACE_CRYPTO, "crypto: plaintext reply:", buff, crp_size); )
-  }
-
-  {
-    /* --- Check validity --- */
-
-    md5 md;
-    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, 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);
-    }
-
-    /* --- Check the identifier --- */
-
-    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]);
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-int main(int argc, char *argv[])
-{
-  unsigned char buff[8];
-  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");
-  if (!fp)
-    die("fopen: %s", strerror(errno));
-  tx_getBits(k, 128, fp);
-  fclose(fp);
-  crypt__sessionKey(argv[2], k, sk, buff);
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/