chiark / gitweb /
Allow user-specified symmetric crypto algorithms.
authormdw <mdw>
Sun, 18 Apr 2004 18:08:11 +0000 (18:08 +0000)
committermdw <mdw>
Sun, 18 Apr 2004 18:08:11 +0000 (18:08 +0000)
doc/tripe.8
ethereal/packet-tripe.c
keyexch.c
keymgmt.c
keyset.c
tripe.c
tripe.h

index b6da8d814a32d3bfbca123203f0cf0932eaccca6..929f01910788c52fcbdbcfe68aa030880eedde6d 100644 (file)
@@ -444,6 +444,34 @@ Now start
 with the
 .B \-ttripe\-ec
 option, and all should be well.
+.SS "Using other symmetric algorithms"
+The default symmetric algorithms
+.B tripe
+uses are Blowfish (by Schneier) for symmetric encryption, and RIPEMD-160
+(by Dobbertin, Bosselaers and Preneel) for hashing and as a MAC (in HMAC
+mode, designed by Bellare, Canetti and Krawczyk).  These can all be
+overridden by setting attributes on your private key, as follows.
+.TP
+.B cipher
+Names the symmetric encryption scheme to use.  The default is
+.BR blowfish\-cbc .
+.TP
+.B hash
+Names the hash function to use.  The default is
+.BR rmd160 .
+.TP
+.B mac
+Names the message authentication code to use.  The name of the MAC may
+be followed by a
+.RB ` / '
+and the desired tag length in bits.  The default is
+.IB hash \-hmac
+at half the underlying hash function's output length.
+.TP
+.B mgf
+A `mask-generation function', used in the key-exchange.  The default is
+.IB hash \-mgf
+and there's no good reason to change it.
 .SS "About the name"
 The program's name is
 .BR tripe ,
index 4b4e0aceb6e60c67e3561be50a7300a805f01d48..afeb1bcc3435e0dea8960942169ef4e783d56e5a 100644 (file)
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: packet-tripe.c,v 1.3 2004/04/08 01:36:17 mdw Exp $
+ * $Id: packet-tripe.c,v 1.4 2004/04/18 18:08:11 mdw Exp $
  *
  * TrIPE protocol dissector for Ethereal
  *
@@ -39,6 +39,7 @@
 #include <glib.h>
 #include <gmodule.h>
 #include <epan/packet.h>
+#include <prefs.h>
 
 #ifdef ETHEREAL_BUGGERED
 #  define plugin_address_table_t void
@@ -53,6 +54,8 @@
 
 static int proto_tripe = -1;
 
+static guint hashsz = 20, tagsz = 10, ivsz = 8;
+
 typedef struct hfmp {
   int hf, hf_len, hf_val, tt;
 } hfmp;
@@ -65,8 +68,8 @@ static int hf_tripe_packet_type = -1;
 static int hf_tripe_ct = -1;
 static int hf_tripe_ct_seq = -1;
 static int hf_tripe_ct_iv = -1;
-static int hf_tripe_ct_cbc = -1;
-static int hf_tripe_ct_mac = -1;
+static int hf_tripe_ct_ct = -1;
+static int hf_tripe_ct_tag = -1;
 static int hf_tripe_kx_type = -1;
 static hfge hf_tripe_kx_mychal = { -1, -1, -1, -1, -1, -1, -1, -1 };
 static int hf_tripe_kx_mycookie = -1;
@@ -81,10 +84,12 @@ G_MODULE_EXPORT const gchar version[] = VERSION;
 
 /*----- Main code ---------------------------------------------------------*/
 
+static void prefcb(void) { }
+
 static gint gethash(proto_tree *tt, int hf, tvbuff_t *b, gint off)
 {
-  proto_tree_add_item(tt, hf, b, off, 20, FALSE);
-  return (off + 20); 
+  proto_tree_add_item(tt, hf, b, off, hashsz, FALSE);
+  return (off + hashsz); 
 }
 
 static gint getmp(proto_tree *tt, const hfmp *hf, tvbuff_t *b, gint off)
@@ -246,17 +251,21 @@ static void dissect_tripe(tvbuff_t *b, packet_info *p, proto_tree *t)
     goto done;
   ct:
     ti = proto_tree_add_item(tt, hf_tripe_ct, b, off, -1, FALSE);
-    seq = tvb_get_ntohl(b, off + 10);
+    seq = tvb_get_ntohl(b, off + tagsz);
     proto_item_set_text(ti, "Encrypted ciphertext (sequence number %lu)",
                        (unsigned long)seq);
     tt = proto_item_add_subtree(ti, tt_tripe_ct);
-    proto_tree_add_item(tt, hf_tripe_ct_mac, b, off, 10, FALSE);
-    off += 10;
+    if (tagsz) {
+      proto_tree_add_item(tt, hf_tripe_ct_tag, b, off, tagsz, FALSE);
+      off += tagsz;
+    }
     proto_tree_add_item(tt, hf_tripe_ct_seq, b, off, 4, FALSE);
     off += 4;
-    proto_tree_add_item(tt, hf_tripe_ct_iv, b, off, 8, FALSE);
-    off += 8;
-    proto_tree_add_item(ti, hf_tripe_ct_cbc, b, off, -1, FALSE);
+    if (ivsz) {
+      proto_tree_add_item(tt, hf_tripe_ct_iv, b, off, ivsz, FALSE);
+      off += ivsz;
+    }
+    proto_tree_add_item(ti, hf_tripe_ct_ct, b, off, -1, FALSE);
     goto done;
   done:;
   }  
@@ -264,6 +273,8 @@ static void dissect_tripe(tvbuff_t *b, packet_info *p, proto_tree *t)
 
 void proto_register_tripe(void)
 {
+  module_t *mod;
+
   static value_string vs_kxtype[] = {
     { KX_PRECHAL,      "KX_PRECHAL (prechallenge)" },
     { KX_COOKIE,       "KX_COOKIE (cookie)" },
@@ -299,15 +310,15 @@ void proto_register_tripe(void)
       FT_BYTES, BASE_NONE, 0, 0,
       "This is the initialization vector used for the actual encryption."
     },
-    &hf_tripe_ct_cbc, {
-      "CBC-encrypted data", "tripe.ct.cbc",
+    &hf_tripe_ct_ct, {
+      "Actual encrypted data", "tripe.ct.ct",
       FT_BYTES, BASE_NONE, 0, 0,
-      "This is the CBC-encrypted message.  Reading it ought to be hard."
+      "This is the encrypted message.  Reading it ought to be hard."
     },
-    &hf_tripe_ct_mac, {
-      "Message authentication code", "tripe.ct.mac",
+    &hf_tripe_ct_tag, {
+      "Message authentication code", "tripe.ct.tag",
       FT_BYTES, BASE_NONE, 0, 0,
-      "This is the message authentication code for the ciphertext."
+      "This is the message authentication code tag for the ciphertext."
     },
     &hf_tripe_kx_type, {
       "Key-exchange message type", "tripe.kx.type",
@@ -392,6 +403,17 @@ void proto_register_tripe(void)
   proto_tripe = proto_register_protocol("TrIPE", "TrIPE", "tripe");
   proto_register_field_array(proto_tripe, hfs, array_length(hfs));
   proto_register_subtree_array(tts, array_length(tts));
+
+  mod = prefs_register_protocol(proto_tripe, prefcb);
+  prefs_register_uint_preference(mod, "hashsz", "Hash length",
+                                "hash function output length (in octets)",
+                                10, &hashsz);
+  prefs_register_uint_preference(mod, "tagsz", "MAC tag length",
+                                "MAC tag length (in octets)", 10, &tagsz);
+  prefs_register_uint_preference(mod, "ivsz", "IV length",
+                                "block cipher initialization vector length"
+                                " (in octets)",
+                                10, &ivsz);
 }
 
 void proto_reg_handoff_tripe(void)
index 97965c85394adf3f63c3ff98d6ab699a9d64f184..18594cf31414447f1b37e4de6be9ae2e0a6d8a07 100644 (file)
--- a/keyexch.c
+++ b/keyexch.c
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: keyexch.c,v 1.12 2004/04/08 01:36:17 mdw Exp $
+ * $Id: keyexch.c,v 1.13 2004/04/18 18:08:11 mdw Exp $
  *
  * Key exchange protocol
  *
@@ -91,7 +91,7 @@
 
 /* --- @hashge@ --- *
  *
- * Arguments:  @HASH_CTX *r@ = pointer to hash context
+ * Arguments:  @ghash *h@ = pointer to hash context
  *             @ge *x@ = pointer to group element
  *
  * Returns:    ---
  *             @buf_t@.
  */
 
-static void hashge(HASH_CTX *r, ge *x)
+static void hashge(ghash *h, ge *x)
 {
   buf b;
   buf_init(&b, buf_t, sizeof(buf_t));
   G_TOBUF(gg, &b, x);
   assert(BOK(&b));
-  HASH(r, BBASE(&b), BLEN(&b));
+  GH_HASH(h, BBASE(&b), BLEN(&b));
 }
 
-/* --- @mpcrypt@ --- *
+/* --- @mpencrypt@, @mpdecrypt@ --- *
  *
  * Arguments:  @mp *d@ = the destination integer
  *             @mp *x@ = the plaintext/ciphertext integer
  *             @size_t sz@ = the expected size of the plaintext
  *             @const octet *k@ = pointer to key material
- *             @size_t ksz@ = size of the key
  *
  * Returns:    The encrypted/decrypted integer.
  *
@@ -125,13 +124,25 @@ static void hashge(HASH_CTX *r, ge *x)
  *             encryption thing.
  */
 
-static mp *mpcrypt(mp *d, mp *x, size_t sz, const octet *k, size_t ksz)
+static mp *mpencrypt(mp *d, mp *x, size_t sz, const octet *k)
 {
-  MGF_CTX m;
+  gcipher *mgf;
 
-  MGF_INIT(&m, k, ksz, 0);
+  mgf = GC_INIT(algs.mgf, k, algs.hashsz);
   mp_storeb(x, buf_t, sz);
-  MGF_CRYPT(&m, buf_t, buf_t, sz);
+  GC_ENCRYPT(mgf, buf_t, buf_t, sz);
+  GC_DESTROY(mgf);
+  return (mp_loadb(d, buf_t, sz));
+}
+
+static mp *mpdecrypt(mp *d, mp *x, size_t sz, const octet *k)
+{
+  gcipher *mgf;
+
+  mgf = GC_INIT(algs.mgf, k, algs.hashsz);
+  mp_storeb(x, buf_t, sz);
+  GC_DECRYPT(mgf, buf_t, buf_t, sz);
+  GC_DESTROY(mgf);
   return (mp_loadb(d, buf_t, sz));
 }
 
@@ -299,7 +310,7 @@ static kxchal *kxc_byhc(keyexch *kx, const octet *hc)
   unsigned i;
 
   for (i = 0; i < kx->nr; i++) {
-    if (memcmp(hc, kx->r[i]->hc, HASHSZ) == 0)
+    if (memcmp(hc, kx->r[i]->hc, algs.hashsz) == 0)
       return (kx->r[i]);
   }
   return (0);
@@ -337,8 +348,8 @@ static void kxc_answer(keyexch *kx, kxchal *kxc)
   if (!kxc->r)
     G_TOBUF(gg, b, kx->c);
   else
-    buf_put(b, kx->hc, HASHSZ);
-  buf_put(b, kxc->hc, HASHSZ);
+    buf_put(b, kx->hc, algs.hashsz);
+  buf_put(b, kxc->hc, algs.hashsz);
   buf_putmp(b, kxc->ck);
 
   /* --- Maybe send an actual reply, if we have one --- */
@@ -390,24 +401,25 @@ static ge *getreply(keyexch *kx, ge *c, mp *ck)
   ge *r = G_CREATE(gg);
   ge *y = G_CREATE(gg);
   mp *a = MP_NEW;
-  HASH_CTX h;
-  octet buf[HASHSZ];  
+  ghash *h;
+  const octet *hh;
   int ok;
 
   G_EXP(gg, r, c, kpriv);
-  HASH_INIT(&h);
-  HASH_STRING(&h, "tripe-expected-reply");
-  hashge(&h, c);
-  hashge(&h, kx->c);
-  hashge(&h, r);
-  HASH_DONE(&h, buf);
-
-  a = mpcrypt(MP_NEW, ck, mp_octets(gg->r), buf, sizeof(buf));
+  h = GH_INIT(algs.h);
+  HASH_STRING(h, "tripe-expected-reply");
+  hashge(h, c);
+  hashge(h, kx->c);
+  hashge(h, r);
+  hh = GH_DONE(h, 0);
+
+  a = mpdecrypt(MP_NEW, ck, mp_octets(gg->r), hh);
   IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, {
     trace(T_CRYPTO, "crypto: computed reply = %s", gestr(gg, r));
-    trace_block(T_CRYPTO, "crypto: computed reply hash", buf, HASHSZ);
+    trace_block(T_CRYPTO, "crypto: computed reply hash", hh, algs.hashsz);
     trace(T_CRYPTO, "crypto: recovered log = %s", mpstr(a));
   }))
+  GH_DESTROY(h);
   G_EXP(gg, y, gg->g, a);
   ok = G_EQ(gg, y, c);
   if (!ok) {
@@ -440,8 +452,7 @@ static int dochallenge(keyexch *kx, unsigned msg, buf *b)
   mp *ck = MP_NEW;
   const octet *hc = 0;
   kxchal *kxc;
-  HASH_CTX h;
-  octet buf[HASHSZ];
+  ghash *h;
 
   /* --- Ensure that we're in a sensible state --- */
 
@@ -453,7 +464,7 @@ static int dochallenge(keyexch *kx, unsigned msg, buf *b)
   /* --- Unpack the packet --- */
 
   if (G_FROMBUF(gg, b, c) ||
-      (msg >= KX_COOKIE && (hc = buf_get(b, HASHSZ)) == 0) ||
+      (msg >= KX_COOKIE && (hc = buf_get(b, algs.hashsz)) == 0) ||
       (msg >= KX_CHAL && (ck = buf_getmp(b)) == 0) ||
       BLEFT(b)) {
     a_warn("malformed packet from `%s'", p_name(kx->p));
@@ -462,7 +473,7 @@ static int dochallenge(keyexch *kx, unsigned msg, buf *b)
 
   IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, {
     trace(T_CRYPTO, "crypto: challenge = %s", gestr(gg, c));
-    if (hc) trace_block(T_CRYPTO, "crypto: cookie", hc, HASHSZ);
+    if (hc) trace_block(T_CRYPTO, "crypto: cookie", hc, algs.hashsz);
     if (ck) trace(T_CRYPTO, "crypto: check value = %s", mpstr(ck));
   }))
 
@@ -475,17 +486,18 @@ static int dochallenge(keyexch *kx, unsigned msg, buf *b)
     T( trace(T_KEYEXCH, "keyexch: too many challenges -- sending cookie"); )
     b = p_txstart(kx->p, MSG_KEYEXCH | KX_COOKIE);
     G_TOBUF(gg, b, kx->c);
-    HASH_INIT(&h);
-    HASH_STRING(&h, "tripe-cookie");
-    hashge(&h, c);
-    HASH_DONE(&h, buf_get(b, HASHSZ));
+    h = GH_INIT(algs.h);
+    HASH_STRING(h, "tripe-cookie");
+    hashge(h, c);
+    GH_DONE(h, buf_get(b, algs.hashsz));
+    GH_DESTROY(h);
     p_txend(kx->p);
     goto tidy;
   }
 
   /* --- Discard a packet with an invalid cookie --- */
 
-  if (hc && memcmp(hc, kx->hc, HASHSZ) != 0) {
+  if (hc && memcmp(hc, kx->hc, algs.hashsz) != 0) {
     a_warn("incorrect cookie from `%s'", p_name(kx->p));
     goto bad;
   }
@@ -519,57 +531,64 @@ static int dochallenge(keyexch *kx, unsigned msg, buf *b)
 
     /* --- Work out the cookie for this challenge --- */
 
-    HASH_INIT(&h);
-    HASH_STRING(&h, "tripe-cookie");
-    hashge(&h, kxc->c);
-    HASH_DONE(&h, kxc->hc);    
+    h = GH_INIT(algs.h);
+    HASH_STRING(h, "tripe-cookie");
+    hashge(h, kxc->c);
+    GH_DONE(h, kxc->hc);
+    GH_DESTROY(h);
+
+    IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, {
+      trace_block(T_CRYPTO, "crypto: computed cookie", kxc->hc, algs.hashsz);
+    }))
 
     /* --- Compute the expected-reply hash --- */
 
-    HASH_INIT(&h);
-    HASH_STRING(&h, "tripe-expected-reply");
-    hashge(&h, kx->c);
-    hashge(&h, kxc->c);
-    hashge(&h, kx->rx);
-    HASH_DONE(&h, buf);
-    kxc->ck = mpcrypt(MP_NEW, kx->alpha, mp_octets(gg->r),
-                     buf, sizeof(buf));
+    h = GH_INIT(algs.h);
+    HASH_STRING(h, "tripe-expected-reply");
+    hashge(h, kx->c);
+    hashge(h, kxc->c);
+    hashge(h, kx->rx);
+    hc = GH_DONE(h, 0);
+    kxc->ck = mpencrypt(MP_NEW, kx->alpha, mp_octets(gg->r), hc);
+    IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, {
+      trace_block(T_CRYPTO, "crypto: expected-reply hash", hc, algs.hashsz);
+      trace(T_CRYPTO, "crypto: my reply check = %s", mpstr(kxc->ck));
+    }))
+    GH_DESTROY(h);
 
     /* --- Work out the shared key --- */
 
     r = G_CREATE(gg);
     G_EXP(gg, r, c, kx->alpha);
+    IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, {
+      trace(T_CRYPTO, "crypto: shared secret = %s", gestr(gg, r));
+    }))
 
     /* --- Compute the switch messages --- */
 
-    HASH_INIT(&h); HASH_STRING(&h, "tripe-switch-request");
-    hashge(&h, kx->c); hashge(&h, kxc->c);
-    HASH_DONE(&h, kxc->hswrq_out);
-    HASH_INIT(&h); HASH_STRING(&h, "tripe-switch-confirm");
-    hashge(&h, kx->c); hashge(&h, kxc->c);
-    HASH_DONE(&h, kxc->hswok_out);
+    h = GH_INIT(algs.h); HASH_STRING(h, "tripe-switch-request");
+    hashge(h, kx->c); hashge(h, kxc->c);
+    GH_DONE(h, kxc->hswrq_out); GH_DESTROY(h);
+    h = GH_INIT(algs.h); HASH_STRING(h, "tripe-switch-confirm");
+    hashge(h, kx->c); hashge(h, kxc->c);
+    GH_DONE(h, kxc->hswok_out); GH_DESTROY(h);
 
-    HASH_INIT(&h); HASH_STRING(&h, "tripe-switch-request");
-    hashge(&h, kxc->c); hashge(&h, kx->c);
-    HASH_DONE(&h, kxc->hswrq_in);
-    HASH_INIT(&h); HASH_STRING(&h, "tripe-switch-confirm");
-    hashge(&h, kxc->c); hashge(&h, kx->c);
-    HASH_DONE(&h, kxc->hswok_in);
+    h = GH_INIT(algs.h); HASH_STRING(h, "tripe-switch-request");
+    hashge(h, kxc->c); hashge(h, kx->c);
+    GH_DONE(h, kxc->hswrq_in); GH_DESTROY(h);
+    h = GH_INIT(algs.h); HASH_STRING(h, "tripe-switch-confirm");
+    hashge(h, kxc->c); hashge(h, kx->c);
+    GH_DONE(h, kxc->hswok_in); GH_DESTROY(h);
 
     IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, {
-      trace_block(T_CRYPTO, "crypto: computed cookie", kxc->hc, HASHSZ);
-      trace_block(T_CRYPTO, "crypto: expected-reply hash",
-                 buf, HASHSZ);
-      trace(T_CRYPTO, "crypto: my reply check = %s", mpstr(kxc->ck));
-      trace(T_CRYPTO, "crypto: shared secret = %s", gestr(gg, r));
       trace_block(T_CRYPTO, "crypto: outbound switch request",
-                 kxc->hswrq_out, HASHSZ);
+                 kxc->hswrq_out, algs.hashsz);
       trace_block(T_CRYPTO, "crypto: outbound switch confirm",
-                 kxc->hswok_out, HASHSZ);
+                 kxc->hswok_out, algs.hashsz);
       trace_block(T_CRYPTO, "crypto: inbound switch request",
-                 kxc->hswrq_in, HASHSZ);
+                 kxc->hswrq_in, algs.hashsz);
       trace_block(T_CRYPTO, "crypto: inbound switch confirm",
-                 kxc->hswok_in, HASHSZ);
+                 kxc->hswok_in, algs.hashsz);
     }))
 
     /* --- Create a new symmetric keyset --- */
@@ -636,11 +655,11 @@ static void resend(keyexch *kx)
               p_name(kx->p)); )
       kxc = kx->r[0];
       b = p_txstart(kx->p, MSG_KEYEXCH | KX_SWITCH);
-      buf_put(b, kx->hc, HASHSZ);
-      buf_put(b, kxc->hc, HASHSZ);
+      buf_put(b, kx->hc, algs.hashsz);
+      buf_put(b, kxc->hc, algs.hashsz);
       buf_init(&bb, buf_i, sizeof(buf_i));
       G_TOBUF(gg, &bb, kxc->r);
-      buf_put(&bb, kxc->hswrq_out, HASHSZ);
+      buf_put(&bb, kxc->hswrq_out, algs.hashsz);
       buf_flip(&bb);
       ks_encrypt(kxc->ks, MSG_KEYEXCH | KX_SWITCH, &bb, b);
       break;
@@ -650,7 +669,7 @@ static void resend(keyexch *kx)
       kxc = kx->r[0];
       b = p_txstart(kx->p, MSG_KEYEXCH | KX_SWITCHOK);
       buf_init(&bb, buf_i, sizeof(buf_i));
-      buf_put(&bb, kxc->hswok_out, HASHSZ);
+      buf_put(&bb, kxc->hswok_out, algs.hashsz);
       buf_flip(&bb);
       ks_encrypt(kxc->ks, MSG_KEYEXCH | KX_SWITCHOK, &bb, b);
       break;
@@ -695,11 +714,11 @@ static kxchal *matchreply(keyexch *kx, unsigned ty, const octet *hc_in,
   /* --- Check the plaintext portions of the data --- */
 
   IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, {
-    trace_block(T_CRYPTO, "crypto: challenge", hc_in, HASHSZ);
-    trace_block(T_CRYPTO, "crypto: cookie", hc_out, HASHSZ);
+    trace_block(T_CRYPTO, "crypto: challenge", hc_in, algs.hashsz);
+    trace_block(T_CRYPTO, "crypto: cookie", hc_out, algs.hashsz);
     if (ck) trace(T_CRYPTO, "crypto: check value = %s", mpstr(ck));
   }))
-  if (memcmp(hc_out, kx->hc, HASHSZ) != 0) {
+  if (memcmp(hc_out, kx->hc, algs.hashsz) != 0) {
     a_warn("incorrect cookie from `%s'", p_name(kx->p));
     goto bad;
   }
@@ -798,8 +817,8 @@ static int doreply(keyexch *kx, buf *b)
     a_warn("unexpected reply from `%s'", p_name(kx->p));
     goto bad;
   }
-  if ((hc_in = buf_get(b, HASHSZ)) == 0 ||
-      (hc_out = buf_get(b, HASHSZ)) == 0 ||
+  if ((hc_in = buf_get(b, algs.hashsz)) == 0 ||
+      (hc_out = buf_get(b, algs.hashsz)) == 0 ||
       (ck = buf_getmp(b)) == 0) {
     a_warn("invalid reply packet from `%s'", p_name(kx->p));
     goto bad;
@@ -838,22 +857,22 @@ static int doswitch(keyexch *kx, buf *b)
   const octet *hc_in, *hc_out, *hswrq;
   kxchal *kxc;
 
-  if ((hc_in = buf_get(b, HASHSZ)) == 0 ||
-      (hc_out = buf_get(b, HASHSZ)) == 0) {
+  if ((hc_in = buf_get(b, algs.hashsz)) == 0 ||
+      (hc_out = buf_get(b, algs.hashsz)) == 0) {
     a_warn("invalid switch request from `%s'", p_name(kx->p));
     goto bad;
   }
   if ((kxc = matchreply(kx, MSG_KEYEXCH | KX_SWITCH,
                        hc_in, hc_out, 0, b)) == 0)
     goto bad;
-  if ((hswrq = buf_get(b, HASHSZ)) == 0 || BLEFT(b)) {
+  if ((hswrq = buf_get(b, algs.hashsz)) == 0 || BLEFT(b)) {
     a_warn("invalid switch request from `%s'", p_name(kx->p));
     goto bad;
   }
   IF_TRACING(T_KEYEXCH, {
-    trace_block(T_CRYPTO, "crypto: switch request hash", hswrq, HASHSZ);
+    trace_block(T_CRYPTO, "crypto: switch request hash", hswrq, algs.hashsz);
   })
-  if (memcmp(hswrq, kxc->hswrq_in, HASHSZ) != 0) {
+  if (memcmp(hswrq, kxc->hswrq_in, algs.hashsz) != 0) {
     a_warn("incorrect switch request hash from `%s'", p_name(kx->p));
     goto bad;
   }
@@ -900,14 +919,15 @@ static int doswitchok(keyexch *kx, buf *b)
     goto bad;
   }
   buf_init(b, BBASE(&bb), BLEN(&bb));
-  if ((hswok = buf_get(b, HASHSZ)) == 0 || BLEFT(b)) {
+  if ((hswok = buf_get(b, algs.hashsz)) == 0 || BLEFT(b)) {
     a_warn("invalid switch confirmation from `%s'", p_name(kx->p));
     goto bad;
   }
   IF_TRACING(T_KEYEXCH, {
-    trace_block(T_CRYPTO, "crypto: switch confirmation hash", hswok, HASHSZ);
+    trace_block(T_CRYPTO, "crypto: switch confirmation hash",
+               hswok, algs.hashsz);
   })
-  if (memcmp(hswok, kxc->hswok_in, HASHSZ) != 0) {
+  if (memcmp(hswok, kxc->hswok_in, algs.hashsz) != 0) {
     a_warn("incorrect switch confirmation hash from `%s'", p_name(kx->p));
     goto bad;
   }
@@ -970,7 +990,7 @@ static void stop(keyexch *kx)
 
 static void start(keyexch *kx, time_t now)
 {
-  HASH_CTX h;
+  ghash *h;
 
   assert(kx->f & KXF_DEAD);
 
@@ -982,10 +1002,11 @@ static void start(keyexch *kx, time_t now)
   kx->s = KXS_CHAL;
   kx->t_valid = now + T_VALID;
 
-  HASH_INIT(&h);
-  HASH_STRING(&h, "tripe-cookie");
-  hashge(&h, kx->c);
-  HASH_DONE(&h, kx->hc);
+  h = GH_INIT(algs.h);
+  HASH_STRING(h, "tripe-cookie");
+  hashge(h, kx->c);
+  GH_DONE(h, kx->hc);
+  GH_DESTROY(h);
 
   IF_TRACING(T_KEYEXCH, {
     trace(T_KEYEXCH, "keyexch: creating new challenge");
@@ -993,7 +1014,7 @@ static void start(keyexch *kx, time_t now)
       trace(T_CRYPTO, "crypto: secret = %s", mpstr(kx->alpha));
       trace(T_CRYPTO, "crypto: challenge = %s", gestr(gg, kx->c));
       trace(T_CRYPTO, "crypto: expected response = %s", gestr(gg, kx->rx));
-      trace_block(T_CRYPTO, "crypto: challenge cookie", kx->hc, HASHSZ);
+      trace_block(T_CRYPTO, "crypto: challenge cookie", kx->hc, algs.hashsz);
     })
   })
 }
index 2935f1c9c8eada69cb6ecd488d92e66a92d9f328..e05706aca251d050d3369981ff67ea869c8a1bb0 100644 (file)
--- a/keymgmt.c
+++ b/keymgmt.c
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: keymgmt.c,v 1.5 2004/04/08 01:36:17 mdw Exp $
+ * $Id: keymgmt.c,v 1.6 2004/04/18 18:08:11 mdw Exp $
  *
  * Key loading and storing
  *
@@ -34,6 +34,7 @@
 
 group *gg;
 mp *kpriv;
+algswitch algs;
 
 /*----- Static variables --------------------------------------------------*/
 
@@ -159,6 +160,132 @@ static const kgops kgec_ops = { "tripe-ec", kgec_priv, kgec_pub };
 
 static const kgops *kgtab[] = { &kgdh_ops, &kgec_ops, 0 };
 
+/*----- Algswitch stuff ---------------------------------------------------*/
+
+/* --- @algs_get@ --- *
+ *
+ * Arguments:  @algswitch *a@ = where to put the algorithms
+ *             @key_file *kf@ = key file (for some stupid reason)
+ *             @key *k@ = key to inspect
+ *
+ * Returns:    Null if OK, or an error message.
+ *
+ * Use:                Extracts an algorithm choice from a key.
+ */
+
+static const char *algs_get(algswitch *a, key_file *kf, key *k)
+{
+  const char *p;
+  char *q;
+  dstr d = DSTR_INIT;
+  const char *e;
+
+#define FAIL(msg) do { e = msg; goto done; } while (0)
+
+  if ((p = key_getattr(kf, k, "cipher")) == 0)
+    p = "blowfish-cbc";
+  if ((a->c = gcipher_byname(p)) == 0)
+    FAIL("unknown cipher");
+
+  if ((p = key_getattr(kf, k, "hash")) == 0)
+    p = "rmd160";
+  if ((a->h = ghash_byname(p)) == 0)
+    FAIL("unknown hash function");
+
+  if ((p = key_getattr(kf, k, "mgf")) != 0) {
+    dstr_reset(&d);
+    dstr_putf(&d, "%s-mgf");
+    p = d.buf;
+  }
+  if ((a->mgf = gcipher_byname(p)) == 0)
+    FAIL("unknown MGF cipher");
+
+  if ((p = key_getattr(kf, k, "mac")) != 0) {
+    dstr_reset(&d);
+    dstr_puts(&d, p);
+    if ((q = strchr(d.buf, '/')) != 0)
+      *q++ = 0;
+    if ((a->m = gmac_byname(d.buf)) == 0)
+      FAIL("unknown message authentication code");
+    if (!q)
+      a->tagsz = a->m->hashsz;
+    else {
+      unsigned long n = strtoul(q, &q, 0);
+      if (*q) FAIL("bad tag length string");
+      if (n%8 || n > ~(size_t)0) FAIL("bad tag length");
+      a->tagsz = n/8;
+    }
+  } else {
+    dstr_reset(&d);
+    dstr_putf(&d, "%s-hmac", a->h->name);
+    if ((a->m = gmac_byname(d.buf)) == 0)
+      FAIL("failed to derive HMAC from hash function");
+    a->tagsz = a->h->hashsz/2;
+  }
+
+  e = 0;
+done:
+  dstr_destroy(&d);
+  return (e);
+}
+
+/* --- @algs_check@ --- *
+ *
+ * Arguments:  @algswitch *a@ = a choice of algorithms
+ *             @const group *g@ = the group we're working in
+ *
+ * Returns:    Null if OK, or an error message.
+ *
+ * Use:                Checks an algorithm choice for sensibleness.  This also
+ *             derives some useful information from the choices, and you
+ *             must call this before committing the algorithm selection
+ *             for use by @keyset@ functions.
+ */
+
+static const char *algs_check(algswitch *a, const group *g)
+{
+  /* --- Derive the key sizes --- *
+   *
+   * Must ensure that we have non-empty keys.  This isn't ideal, but it
+   * provides a handy sanity check.
+   */
+
+  a->hashsz = a->h->hashsz;
+  if ((a->cksz = keysz(a->hashsz, a->c->keysz)) == 0)
+    return ("no key size found for cipher");
+  if ((a->mksz = keysz(a->hashsz, a->m->keysz)) == 0)
+    return ("no key size found for MAC");
+
+  /* --- Ensure that the tag size is sane --- */
+
+  if (a->tagsz > a->m->hashsz) return ("tag length too large");
+
+  /* --- Ensure the MGF accepts hashes as keys --- */
+
+  if (keysz(a->hashsz, a->mgf->keysz) != a->hashsz)
+    return ("MGF not suitable -- restrictive key schedule");
+
+  /* --- All ship-shape and Bristol-fashion --- */
+
+  return (0);
+}
+
+/* --- @algs_samep@ --- *
+ *
+ * Arguments:  @const algswitch *a, *aa@ = two algorithm selections
+ *
+ * Returns:    Nonzero if the two selections are the same.
+ *
+ * Use:                Checks sameness of algorithm selections: used to ensure that
+ *             peers are using sensible algorithms.
+ */
+
+static int algs_samep(const algswitch *a, const algswitch *aa)
+{
+  return (a->c == aa->c && a->mgf == aa->mgf && a->h == aa->h &&
+         a->m == aa->m && a->tagsz == aa->tagsz);
+}
+
 /*----- Main code ---------------------------------------------------------*/
 
 /* --- @keymoan@ --- *
@@ -196,6 +323,7 @@ static int loadpriv(dstr *d)
   int rc = -1;
   const kgops **ko;
   const char *e;
+  algswitch a;
 
   /* --- Open the private key file --- */
 
@@ -237,6 +365,15 @@ tymatch:;
     goto done_1;
   }
 
+  /* --- Collect the algorithms --- */
+
+  if ((e = algs_get(&a, &kf, k)) != 0 ||
+      (e = algs_check(&a, g)) != 0) {
+    dstr_putf(d, "bad symmetric algorithm selection in private key `%s': %s",
+             t.buf, e);
+    goto done_1;
+  }
+
   /* --- Good, we're happy --- *
    *
    * Dodginess!  We change the group over here, but don't free any old group
@@ -263,12 +400,18 @@ tymatch:;
       trace(T_CRYPTO, "crypto: r = %s", mpstr(g->r));
       trace(T_CRYPTO, "crypto: h = %s", mpstr(g->h));
       trace(T_CRYPTO, "crypto: x = %s", mpstr(x));
+      trace(T_CRYPTO, "crypto: cipher = %s", a.c->name);
+      trace(T_CRYPTO, "crypto: mgf = %s", a.mgf->name);
+      trace(T_CRYPTO, "crypto: hash = %s", a.h->name);
+      trace(T_CRYPTO, "crypto: mac = %s/%lu",
+           a.m->name, (unsigned long)a.tagsz * 8);
     })
   })
 
   /* --- Success! --- */
 
   gg = g; g = 0;
+  algs = a;
   kpriv = x; x = 0;
   rc = 0;
 
@@ -367,6 +510,7 @@ int km_interval(void)
 void km_init(const char *priv, const char *pub, const char *tag)
 {
   dstr d = DSTR_INIT;
+  const gchash *const *hh;
 
   kr_priv = priv;
   kr_pub = pub;
@@ -374,6 +518,13 @@ void km_init(const char *priv, const char *pub, const char *tag)
   fwatch_init(&w_priv, kr_priv);
   fwatch_init(&w_pub, kr_pub);
 
+  for (hh = ghashtab; *hh; hh++) {
+    if ((*hh)->hashsz > MAXHASHSZ) {
+      die(EXIT_FAILURE, "INTERNAL ERROR: %s hash length %lu > MAXHASHSZ %d",
+         (*hh)->name, (unsigned long)(*hh)->hashsz, MAXHASHSZ);
+    }
+  }
+
   DRESET(&d);
   if (loadpriv(&d))
     die(EXIT_FAILURE, "%s", d.buf);
@@ -401,12 +552,13 @@ int km_getpubkey(const char *tag, ge *kpub, time_t *t_exp)
   const char *e;
   group *g = 0;
   ge *p = 0;
+  algswitch a;
   int rc = -1;
 
   /* --- Find the key --- */
 
   if (key_qtag(kf_pub, tag, &t, &k, &kd)) {
-    a_warn("private key `%s' not found in keyring `%s'", tag_priv, kr_priv);
+    a_warn("public key `%s' not found in keyring `%s'", tag, kr_pub);
     goto done;
   }
 
@@ -445,6 +597,17 @@ tymatch:;
     goto done;
   }
 
+  /* --- Check the algorithms --- */
+
+  if ((e = algs_get(&a, kf_pub, k)) != 0) {
+    a_warn("public key `%s' has bad algorithm selection: %s", t.buf, e);
+    goto done;
+  }
+  if (!algs_samep(&a, &algs)) {    
+    a_warn("public key `%s' specifies different algorithms", t.buf);
+    goto done;
+  }
+
   /* --- Dump the public key --- */
 
   IF_TRACING(T_KEYMGMT, {
index 0a3204576a56b13382e7f75db9c92346c39641f5..8893e6066ed7d89cb791605a8413e85464f94e3e 100644 (file)
--- a/keyset.c
+++ b/keyset.c
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: keyset.c,v 1.10 2004/04/08 01:36:17 mdw Exp $
+ * $Id: keyset.c,v 1.11 2004/04/18 18:08:11 mdw Exp $
  *
  * Handling of symmetric keysets
  *
@@ -36,7 +36,8 @@
  *
  * For a 64-bit block cipher (e.g., Blowfish), the probability of a collision
  * occurring after 32 MB is less than %$2^{-21}$%, and the probability of a
- * collision occurring after 64 MB is less than %$2^{-19}$%.
+ * collision occurring after 64 MB is less than %$2^{-19}$%.  These could be
+ * adjusted dependent on the encryption scheme, but it's too much pain.
  */
 
 #define T_EXP MIN(60)                  /* Expiry time for a key */
@@ -48,6 +49,8 @@
 
 #define KEYOK(ks, now) ((ks)->sz_exp > 0 && (ks)->t_exp > now)
 
+#define SEQSZ 4                                /* Size of sequence number packet */
+
 /*----- Low-level packet encryption and decryption ------------------------*/
 
 /* --- Encrypted data format --- *
 static int doencrypt(keyset *ks, unsigned ty, buf *b, buf *bb)
 {
   ghash *h;
-  gcipher *c;
+  gcipher *c = ks->cout;
   const octet *p = BCUR(b);
   size_t sz = BLEFT(b);
   octet *qmac, *qseq, *qiv, *qpk;
   uint32 oseq;
+  size_t ivsz = GC_CLASS(c)->blksz;
+  size_t tagsz = ks->tagsz;
   size_t osz, nsz;
   octet t[4];
   int rc = 0;
 
   /* --- Allocate the required buffer space --- */
 
-  c = ks->cout;
-  if (buf_ensure(bb, MACSZ + SEQSZ + IVSZ + sz))
+  if (buf_ensure(bb, tagsz + SEQSZ + ivsz + sz))
     return (0); /* Caution! */
-  qmac = BCUR(bb); qseq = qmac + MACSZ; qiv = qseq + SEQSZ; qpk = qiv + IVSZ;
-  BSTEP(bb, MACSZ + SEQSZ + IVSZ + sz);
+  qmac = BCUR(bb); qseq = qmac + tagsz; qiv = qseq + SEQSZ; qpk = qiv + ivsz;
+  BSTEP(bb, tagsz + SEQSZ + ivsz + sz);
   STORE32(t, ty);
 
-  /* --- Encrypt the packet --- */
-
   oseq = ks->oseq++; STORE32(qseq, oseq);
-  rand_get(RAND_GLOBAL, qiv, IVSZ);
-  c->ops->setiv(c, qiv);
-  c->ops->encrypt(c, p, qpk, sz);
   IF_TRACING(T_KEYSET, {
     trace(T_KEYSET, "keyset: encrypting packet %lu using keyset %u",
          (unsigned long)oseq, ks->seq);
-    trace_block(T_CRYPTO, "crypto: encrypted packet", qpk, sz);
+    trace_block(T_CRYPTO, "crypto: plaintext packet", p, sz);
   })
 
-  /* --- Now compute the MAC --- */
+  /* --- Encrypt the packet --- */
 
-  h = ks->mout->ops->init(ks->mout);
-  h->ops->hash(h, t, sizeof(t));
-  h->ops->hash(h, qseq, SEQSZ + IVSZ + sz);
-  memcpy(qmac, h->ops->done(h, 0), MACSZ);
-  h->ops->destroy(h);
+  if (ivsz) {
+    rand_get(RAND_GLOBAL, qiv, ivsz);
+    GC_SETIV(c, qiv);
+    IF_TRACING(T_KEYSET, {
+      trace_block(T_CRYPTO, "crypto: initialization vector", qiv, ivsz);
+    })
+  }
+  GC_ENCRYPT(c, p, qpk, sz);
   IF_TRACING(T_KEYSET, {
-    trace_block(T_CRYPTO, "crypto: computed MAC", qmac, MACSZ);
+    trace_block(T_CRYPTO, "crypto: encrypted packet", qpk, sz);
   })
 
+  /* --- Now compute the MAC --- */
+
+  if (tagsz) {
+    h = GM_INIT(ks->mout);
+    GH_HASH(h, t, sizeof(t));
+    GH_HASH(h, qseq, SEQSZ + ivsz + sz);
+    memcpy(qmac, GH_DONE(h, 0), tagsz);
+    GH_DESTROY(h);
+    IF_TRACING(T_KEYSET, {
+      trace_block(T_CRYPTO, "crypto: computed MAC", qmac, tagsz);
+    })
+  }
+
   /* --- Deduct the packet size from the key's data life --- */
 
   osz = ks->sz_exp;
@@ -173,45 +188,57 @@ static int dodecrypt(keyset *ks, unsigned ty, buf *b, buf *bb, uint32 *seq)
   octet *q = BCUR(bb);
   ghash *h;
   gcipher *c = ks->cin;
-  size_t ivsz = c->ops->c->blksz;
+  size_t ivsz = GC_CLASS(c)->blksz;
+  size_t tagsz = ks->tagsz;
   octet *mac;
   int eq;
   octet t[4];
 
   /* --- Break up the packet into its components --- */
 
-  if (psz < ivsz + 4) {
+  if (psz < ivsz + SEQSZ + tagsz) {
     T( trace(T_KEYSET, "keyset: block too small for keyset %u", ks->seq); )
     return (-1);
   }
-  sz = psz - IVSZ - SEQSZ - MACSZ;
-  pmac = BCUR(b); pseq = pmac + MACSZ; piv = pseq + SEQSZ; ppk = piv + IVSZ;
+  sz = psz - ivsz - SEQSZ - tagsz;
+  pmac = BCUR(b); pseq = pmac + tagsz; piv = pseq + SEQSZ; ppk = piv + ivsz;
   STORE32(t, ty);
 
-  /* --- Verify the MAC on the packet --- */
-
-  h = ks->min->ops->init(ks->min);
-  h->ops->hash(h, t, sizeof(t));
-  h->ops->hash(h, pseq, SEQSZ + IVSZ + sz);
-  mac = h->ops->done(h, 0);
-  eq = !memcmp(mac, pmac, MACSZ);
   IF_TRACING(T_KEYSET, {
     trace(T_KEYSET, "keyset: decrypting using keyset %u", ks->seq);
-    trace_block(T_CRYPTO, "crypto: computed MAC", mac, MACSZ);
+    trace_block(T_CRYPTO, "crypto: ciphertext packet", ppk, sz);
   })
-  h->ops->destroy(h);
-  if (!eq) {
+
+  /* --- Verify the MAC on the packet --- */
+
+  if (tagsz) {
+    h = GM_INIT(ks->min);
+    GH_HASH(h, t, sizeof(t));
+    GH_HASH(h, pseq, SEQSZ + ivsz + sz);
+    mac = GH_DONE(h, 0);
+    eq = !memcmp(mac, pmac, tagsz);
     IF_TRACING(T_KEYSET, {
-      trace(T_KEYSET, "keyset: incorrect MAC: decryption failed");
-      trace_block(T_CRYPTO, "crypto: expected MAC", pmac, MACSZ);
+      trace_block(T_CRYPTO, "crypto: computed MAC", mac, tagsz);
     })
-    return (-1);
+    GH_DESTROY(h);
+    if (!eq) {
+      IF_TRACING(T_KEYSET, {
+       trace(T_KEYSET, "keyset: incorrect MAC: decryption failed");
+       trace_block(T_CRYPTO, "crypto: expected MAC", pmac, tagsz);
+      })
+      return (-1);
+    }
   }
 
   /* --- Decrypt the packet --- */
 
-  c->ops->setiv(c, piv);
-  c->ops->decrypt(c, ppk, q, sz);
+  if (ivsz) {
+    GC_SETIV(c, piv);
+    IF_TRACING(T_KEYSET, {
+      trace_block(T_CRYPTO, "crypto: initialization vector", piv, ivsz);
+    })
+  }
+  GC_DECRYPT(c, ppk, q, sz);
   if (seq)
     *seq = LOAD32(pseq);
   IF_TRACING(T_KEYSET, {
@@ -278,10 +305,10 @@ void ks_drop(keyset *ks)
 {
   if (--ks->ref)
     return;
-  ks->cin->ops->destroy(ks->cin);
-  ks->cout->ops->destroy(ks->cout);
-  ks->min->ops->destroy(ks->min);
-  ks->mout->ops->destroy(ks->mout);
+  GC_DESTROY(ks->cin);
+  GC_DESTROY(ks->cout);
+  GM_DESTROY(ks->min);
+  GM_DESTROY(ks->mout);
   DESTROY(ks);
 }
 
@@ -310,8 +337,8 @@ void ks_drop(keyset *ks)
 
 keyset *ks_gen(const void *k, size_t x, size_t y, size_t z, peer *p)
 {
-  HASH_CTX h;
-  octet buf[HASHSZ];
+  ghash *h;
+  const octet *hh;
   keyset *ks = CREATE(keyset);
   time_t now = time(0);
   const octet *pp = k;
@@ -324,39 +351,47 @@ keyset *ks_gen(const void *k, size_t x, size_t y, size_t z, peer *p)
    * This is done with macros, because it's quite tedious.
    */
 
-#define MINE HASH(&h, pp, x)
-#define YOURS HASH(&h, pp + x, y - x)
-#define OURS HASH(&h, pp + y, z - y)
-
-#define IN MINE; YOURS; OURS
-#define OUT YOURS; MINE; OURS
-#define STR_IN "incoming"
-#define STR_OUT "outgoing"
-
-#define GETHASH(str, dir) do {                                         \
-  HASH_INIT(&h);                                                       \
-  HASH_STRING(&h, "tripe-" str);                                       \
-  dir;                                                                 \
-  HASH_DONE(&h, buf);                                                  \
+#define MINE GH_HASH(h, pp, x)
+#define YOURS GH_HASH(h, pp + x, y - x)
+#define OURS GH_HASH(h, pp + y, z - y)
+
+#define HASH_in MINE; YOURS; OURS
+#define HASH_out YOURS; MINE; OURS
+#define INIT_c(k) GC_INIT(algs.c, (k), algs.cksz)
+#define INIT_m(k) GM_KEY(algs.m, (k), algs.mksz)
+#define STR_c "encryption"
+#define STR_m "integrity"
+#define STR_in "incoming"
+#define STR_out "outgoing"
+
+#define SETKEY(a, dir) do {                                            \
+  h = GH_INIT(algs.h);                                                 \
+  HASH_STRING(h, "tripe-" STR_##a);                                    \
+  HASH_##dir;                                                          \
+  hh = GH_DONE(h, 0);                                                  \
   IF_TRACING(T_KEYSET, {                                               \
-    trace_block(T_CRYPTO, "crypto: " STR_##dir " key " str,            \
-               buf, sizeof(buf));                                      \
+    trace_block(T_CRYPTO, "crypto: " STR_##dir " key " STR_##a,                \
+               hh, algs.a##ksz);                                       \
   })                                                                   \
+  ks->a##dir = INIT_##a(hh);                                           \
+  GH_DESTROY(h);                                                       \
 } while (0)
 
-  GETHASH("encryption", IN); ks->cin = CIPHER->init(buf, sizeof(buf));
-  GETHASH("integrity", IN); ks->min = MAC->key(buf, sizeof(buf));
-  GETHASH("encryption", OUT); ks->cout = CIPHER->init(buf, sizeof(buf));
-  GETHASH("integrity", OUT); ks->mout = MAC->key(buf, sizeof(buf));
+  SETKEY(c, in); SETKEY(c, out);
+  SETKEY(m, in); SETKEY(m, out);
 
 #undef MINE
 #undef YOURS
 #undef OURS
-#undef IN
-#undef OUT
-#undef STR_IN
-#undef STR_OUT
-#undef GETHASH
+#undef STR_c
+#undef STR_m
+#undef STR_in
+#undef STR_out
+#undef INIT_c
+#undef INIT_m
+#undef HASH_in
+#undef HASH_out
+#undef SETKEY
 
   T( ks->seq = seq++; )
   ks->ref = 1;
@@ -367,7 +402,7 @@ keyset *ks_gen(const void *k, size_t x, size_t y, size_t z, peer *p)
   ks->next = 0;
   ks->p = p;
   ks->f = KSF_LISTEN;
-  BURN(buf);
+  ks->tagsz = algs.tagsz;
   return (ks);
 }
 
diff --git a/tripe.c b/tripe.c
index 9680dd4a5b6d3acd09b298276f56c5e711f2d781..92a6a62d398a2a158042e06efe1d243e8b3e5e00 100644 (file)
--- a/tripe.c
+++ b/tripe.c
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: tripe.c,v 1.13 2004/04/08 01:36:17 mdw Exp $
+ * $Id: tripe.c,v 1.14 2004/04/18 18:08:11 mdw Exp $
  *
  * Main program
  *
@@ -55,7 +55,7 @@ void interval(struct timeval *tv, void *v)
 {
   struct timeval tvv;
   T( trace(T_PEER, "peer: interval timer"); )
-  rand_seed(RAND_GLOBAL, HASHSZ);
+  rand_seed(RAND_GLOBAL, MAXHASHSZ);
   p_interval();
   tvv = *tv;
   tvv.tv_sec += T_INTERVAL;
@@ -269,7 +269,7 @@ int main(int argc, char *argv[])
   sel_init(&sel);
   sig_init(&sel);
   rand_noisesrc(RAND_GLOBAL, &noise_source);
-  rand_seed(RAND_GLOBAL, RMD160_HASHSZ);
+  rand_seed(RAND_GLOBAL, MAXHASHSZ);
   signal(SIGPIPE, SIG_IGN);
   tun_init();
   p_init(baddr, port);
diff --git a/tripe.h b/tripe.h
index 5138d110a03c8f8ce0e5accbb41910153977b7cc..7de033d3326a7015a37064d535a80e5b70745cd0 100644 (file)
--- a/tripe.h
+++ b/tripe.h
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: tripe.h,v 1.19 2004/04/08 01:36:17 mdw Exp $
+ * $Id: tripe.h,v 1.20 2004/04/18 18:08:11 mdw Exp $
  *
  * Main header file for TrIPE
  *
 
 /*----- Cipher selections -------------------------------------------------*/
 
-#include <catacomb/blowfish.h>
-#include <catacomb/blowfish-cbc.h>
-#include <catacomb/blowfish-counter.h>
-#include <catacomb/rmd160.h>
-#include <catacomb/rmd160-hmac.h>
+typedef struct algswitch {
+  const gccipher *c;                   /* Symmetric encryption scheme */
+  const gccipher *mgf;                 /* Mask-generation function */
+  const gchash *h;                     /* Hash function */
+  const gcmac *m;                      /* Message authentication code */
+  size_t hashsz;                       /* Hash output size */
+  size_t tagsz;                                /* Length to truncate MAC tags */
+  size_t cksz, mksz;                   /* Key lengths for @c@ and @m@ */
+} algswitch;
 
-#define CIPHER (&blowfish_cbc)
-#define MAC (&rmd160_hmac)
+extern algswitch algs;
 
-#define HASH_CTX rmd160_ctx
-#define HASH_INIT rmd160_init
-#define HASH rmd160_hash
-#define HASH_STRING(c, s) HASH((c), s, sizeof(s))
-#define HASH_DONE rmd160_done
-#define HASHSZ RMD160_HASHSZ
+#define MAXHASHSZ 64                   /* Largest possible hash size */
 
-#define MGF_CTX blowfish_counterctx
-#define MGF_INIT blowfish_counterinit
-#define MGF_CRYPT blowfish_counterencrypt
-
-#define SEQSZ 4
-#define IVSZ BLOWFISH_BLKSZ
-#define MACSZ 10
+#define HASH_STRING(h, s) GH_HASH((h), (s), sizeof(s))
 
 /*----- Data structures ---------------------------------------------------*/
 
@@ -195,6 +187,7 @@ typedef struct keyset {
   T( unsigned seq; )                   /* Sequence number for tracing */
   unsigned f;                          /* Various useful flags */
   gcipher *cin, *cout;                         /* Keyset ciphers for encryption */
+  size_t tagsz;                                /* Length to truncate MAC tags */
   gmac *min, *mout;                    /* Keyset MACs for integrity */
   uint32 oseq;                         /* Outbound sequence number */
   uint32 iseq, iwin;                   /* Inbound sequence number */
@@ -224,12 +217,12 @@ typedef struct kxchal {
   keyset *ks;                          /* Pointer to temporary keyset */
   unsigned f;                          /* Various useful flags */
   sel_timer t;                         /* Response timer for challenge */
-  octet hc[HASHSZ];                    /* Hash of his challenge */
+  octet hc[MAXHASHSZ];                 /* Hash of his challenge */
   mp *ck;                              /* The check value */
-  octet hswrq_in[HASHSZ];              /* Inbound switch request message */
-  octet hswok_in[HASHSZ];              /* Inbound switch confirmation */
-  octet hswrq_out[HASHSZ];             /* Outbound switch request message */
-  octet hswok_out[HASHSZ];             /* Outbound switch confirmation */
+  octet hswrq_in[MAXHASHSZ];           /* Inbound switch request message */
+  octet hswok_in[MAXHASHSZ];           /* Inbound switch confirmation */
+  octet hswrq_out[MAXHASHSZ];          /* Outbound switch request message */
+  octet hswok_out[MAXHASHSZ];          /* Outbound switch confirmation */
 } kxchal;
 
 typedef struct keyexch {
@@ -245,7 +238,7 @@ typedef struct keyexch {
   ge *rx;                              /* The expected response */
   unsigned nr;                         /* Number of extant responses */
   time_t t_valid;                      /* When this exchange goes bad */
-  octet hc[HASHSZ];                    /* Hash of my challenge */
+  octet hc[MAXHASHSZ];                 /* Hash of my challenge */
   kxchal *r[KX_NCHAL];                 /* Array of challenges */
 } keyexch;