From fc5f482398c76a2d1e81f88f2ce3e750ad029c19 Mon Sep 17 00:00:00 2001 Message-Id: From: Mark Wooding Date: Mon, 19 Apr 2010 22:00:59 +0100 Subject: [PATCH] Make `tripe' be the default key type. Organization: Straylight/Edgeware From: Mark Wooding Rather than using the key type to tell us which key-exchange group type to use, read it out of an attribute on the key. This makes the whole finding keys thing much simpler to explain (although the code becomes slightly more complicated). Fall back to the old behaviour of parsing the group type out of the key type if there's no attribute. Reorganize the tripe(8) manual page somewhat. Remove the tutorial-ish part, which is now out of place and not very useful; there's a proper Texinfo manual coming soon. --- keys/tripe-keys.in | 6 +- server/keymgmt.c | 83 ++++++++++----- server/tripe.8.in | 245 ++++++++++++--------------------------------- server/tripe.c | 2 +- 4 files changed, 125 insertions(+), 211 deletions(-) diff --git a/keys/tripe-keys.in b/keys/tripe-keys.in index 7ed3aae7..2be5e2dd 100644 --- a/keys/tripe-keys.in +++ b/keys/tripe-keys.in @@ -363,8 +363,8 @@ def cmd_setup(args): OS.mkdir('repos') run('''key -krepos/param add -a${kx}-param !${kx-param} - -eforever -tparam tripe-${kx}-param - cipher=${cipher} hash=${hash} mac=${mac} mgf=${mgf}''') + -eforever -tparam tripe-param + kx-group=${kx} cipher=${cipher} hash=${hash} mac=${mac} mgf=${mgf}''') cmd_newmaster(args) ###-------------------------------------------------------------------------- @@ -476,7 +476,7 @@ def cmd_generate(args): keyring_pub = 'peer-%s.pub' % tag zap('keyring'); zap(keyring_pub) run('key -kkeyring merge repos/param') - run('key -kkeyring add -a${kx} -pparam -e${kx-expire} -t%s tripe-${kx}' % + run('key -kkeyring add -a${kx} -pparam -e${kx-expire} -t%s tripe' % tag) run('key -kkeyring extract -f-secret %s %s' % (keyring_pub, tag)) diff --git a/server/keymgmt.c b/server/keymgmt.c index ce0d4561..20c60cb6 100644 --- a/server/keymgmt.c +++ b/server/keymgmt.c @@ -98,7 +98,7 @@ done: return (e); } -static const kgops kgdh_ops = { "tripe-dh", kgdh_priv, kgdh_pub }; +static const kgops kgdh_ops = { "dh", kgdh_priv, kgdh_pub }; /* --- Elliptic curve --- */ @@ -154,7 +154,7 @@ done: return (e); } -static const kgops kgec_ops = { "tripe-ec", kgec_priv, kgec_pub }; +static const kgops kgec_ops = { "ec", kgec_priv, kgec_pub }; /* --- Table of supported key types --- */ @@ -315,6 +315,41 @@ static void keymoan(const char *file, int line, const char *msg, void *p) A_END); } +/* --- @keykg@ --- * + * + * Arguments: @key_file *kf@ = pointer to key file + * @key *k@ = pointer to key + * @const char **tyr@ = where to put the type string + * + * Returns: Pointer to indicated key-group options, or null. + * + * Use: Looks up a key's group indicator and tries to find a matching + * table entry. + */ + +static const kgops *keykg(key_file *kf, key *k, const char **tyr) +{ + const char *ty; + const kgops **ko; + + /* --- Look up the key type in the table --- * + * + * There are several places to look for this. The most obvious is the + * `kx-group' key attribute. But there's also the key type itself. + */ + + ty = key_getattr(kf, k, "kx-group"); + if (!ty && strncmp(k->type, "tripe-", 6) == 0) ty = k->type + 6; + if (!ty) ty = "dh"; + if (tyr) *tyr = ty; + + for (ko = kgtab; *ko; ko++) { + if (strcmp((*ko)->ty, ty) == 0) + return (*ko); + } + return (0); +} + /* --- @loadpriv@ --- * * * Arguments: @dstr *d@ = string to write errors in @@ -333,8 +368,8 @@ static int loadpriv(dstr *d) group *g = 0; mp *x = 0; int rc = -1; - const kgops **ko; - const char *e; + const kgops *ko; + const char *e, *tag, *ty; algswitch a; /* --- Open the private key file --- */ @@ -347,25 +382,24 @@ static int loadpriv(dstr *d) /* --- Find the private key --- */ - if (key_qtag(&kf, tag_priv, &t, &k, &kd)) { - dstr_putf(d, "private key `%s' not found in keyring `%s'", - tag_priv, kr_priv); + if (tag_priv ? + key_qtag(&kf, tag = tag_priv, &t, &k, &kd) : + key_qtag(&kf, tag = "tripe", &t, &k, &kd) && + key_qtag(&kf, tag = "tripe-dh", &t, &k, &kd)) { + dstr_putf(d, "private key `%s' not found in keyring `%s'", tag, kr_priv); goto done_1; } /* --- Look up the key type in the table --- */ - for (ko = kgtab; *ko; ko++) { - if (strcmp((*ko)->ty, k->type) == 0) - goto tymatch; + if ((ko = keykg(&kf, k, &ty)) == 0) { + dstr_putf(d, "private key `%s' has unknown type `%s'", t.buf, ty); + goto done_1; } - dstr_putf(d, "private key `%s' has unknown type `%s'", t.buf, k->type); - goto done_1; -tymatch:; /* --- Load the key --- */ - if ((e = (*ko)->loadpriv(*kd, &g, &x, &t)) != 0) { + if ((e = ko->loadpriv(*kd, &g, &x, &t)) != 0) { dstr_putf(d, "error reading private key `%s': %s", t.buf, e); goto done_1; } @@ -566,8 +600,8 @@ int km_getpubkey(const char *tag, ge *kpub, time_t *t_exp) key *k; key_data **kd; dstr t = DSTR_INIT; - const kgops **ko; - const char *e; + const kgops *ko; + const char *e, *ty; group *g = 0; ge *p = 0; algswitch a; @@ -582,20 +616,17 @@ int km_getpubkey(const char *tag, ge *kpub, time_t *t_exp) /* --- Look up the key type in the table --- */ - for (ko = kgtab; *ko; ko++) { - if (strcmp((*ko)->ty, k->type) == 0) - goto tymatch; + if ((ko = keykg(kf_pub, k, &ty)) == 0) { + a_warn("KEYMGMT", + "public-key", "%s", t.buf, + "unknown-type", "%s", ty, + A_END); + goto done; } - a_warn("KEYMGMT", - "public-key", "%s", t.buf, - "unknown-type", "%s", k->type, - A_END); - goto done; -tymatch:; /* --- Load the key --- */ - if ((e = (*ko)->loadpub(*kd, &g, &p, &t)) != 0) { + if ((e = ko->loadpub(*kd, &g, &p, &t)) != 0) { a_warn("KEYMGMT", "public-key", "%s", t.buf, "bad", "%s", e, A_END); goto done; } diff --git a/server/tripe.8.in b/server/tripe.8.in index ad71bc91..f43ab5f8 100644 --- a/server/tripe.8.in +++ b/server/tripe.8.in @@ -117,8 +117,10 @@ admin command (see .BR tripe\-admin (5)). .hP 3. It loads the private key with the tag or type name +.B tripe +(or, failing that, .B tripe\-dh -from the Catacomb-format file +for backwards compatibility reasons) from the Catacomb-format file .BR keyring , and loads the file .B keyring.pub @@ -240,6 +242,8 @@ This can be the same as the private keyring, but that's not recommended. Uses the private key whose tag or type is .I tag rather than the default +.B tripe +or .BR tripe\-dh . .TP .BI "\-a, \-\-admin\-socket=" socket @@ -255,189 +259,67 @@ is used instead. .BI "\-T, \-\-trace=" trace-opts Allows the enabling or disabling of various internal diagnostics. See below for the list of options. -.SS "Setting up a VPN with tripe" +.SS "Key exchange group types" The .B tripe -server identifies peers by name. While it's -.I possible -for each host to maintain its own naming system for its peers, this is -likely to lead to confusion, and it's more sensible to organize a naming -system that works everywhere. How you manage this naming is up to you. -The only restriction on the format of names is that they must be valid -Catacomb key tags, since this is how +server uses Diffie\(en\&Hellman key exchange to agree the symmetric keys +used for bulk data transfer. Currently .B tripe -identifies which public key to use for a particular peer: they may not -contain whitespace characters, or a colon -.RB ` : ' -or dot -.RB ` . ', +can do Diffie\(en\&Hellman in two different kinds of cyclic groups: +.I "Schnorr groups" +(denoted +.BR dh ) +and +.I "elliptic curve groups" +(denoted +.BR ec ). .PP -Allocating IP addresses for VPNs can get quite complicated. I'll -attempt to illustrate with a relatively simple example. Our objective -will be to set up a virtual private network between two sites of -.BR example.com . -The two sites are using distinct IP address ranges from the private -address space described in RFC1918: site A is using addresses from -10.0.1.0/24 and site B is using 10.0.2.0/24. Each site has a gateway -host set up with both an address on the site's private network, and an -externally-routable address from the public IP address space. Site A's -gateway machine, -.BR alice , -has the addresses 10.0.1.1 and 200.0.1.1; site B's gateway is -.B bob -and has addresses 10.0.2.1 and 200.0.2.1. -.hP 1. -Install -.B tripe -on both of the gateway hosts. Create the directory -.BR /var/lib/tripe . -.hP 2. -On -.BR alice , -make -.B /var/lib/tripe -the current directory and generate a Diffie-Hellman group: -.RS +A Schnorr group is a prime-order subgroup of the multiplicative group of +a finite field; this is the usual +.I g\*(ssx\*(se +mod +.I p +kind of Diffie\(en\&Hellman. An elliptic curve group is a prime-order +subgroup of the abelian group of +.BR K -rational +points on an elliptic curve defined over a finite field +.BR K . +.PP +Given current public knowledge, elliptic curves can provide similar or +better security to systems based on integer discrete log problems, +faster, and with less transmitted data. It's a matter of controversy +whether this will continue to be the case. The author uses elliptic +curves. +.PP +The server works out which it should be doing based on the key's +.B kx-group +attribute, which should be either +.B dh +or +.BR ec . +If this attribute isn't present, then the key's type is examined: if +it's of the form +.BR tripe\- group +then the +.I group +is used. If no group is specified, +.B dh +is used as a fallback. +.PP +To create usual Schnorr-group keys, say something like .VS -key add \-adh\-param \-LS \-b2048 \-B256 \e - \-eforever \-tparam tripe\-dh\-param +key add \-adh-param \-LS \-b3072 \-B256 \e + \-eforever \-tparam tripe\-param kx-group=dh .VE -(See -.BR key (1) -from the Catacomb distribution for details about the -.B key -command.) Also generate a private key for -.BR alice : +to construct a parameters key; and create the private keys by .VS key add \-adh \-pparam \-talice \e - \-e"now + 1 year" tripe\-dh -.VE -Extract the group parameters and -.BR alice 's -public key to -.I separate -files, and put the public key in -.BR keyring.pub : -.VS -key extract param param -key extract \-f\-secret alice.pub alice -key \-kkeyring.pub merge alice.pub -.VE -Send the files -.B param -and -.B alice.pub -to -.B bob -in some secure way (e.g., in PGP-signed email, or by using SSH), so that -you can be sure they've not been altered in transit. -.RE -.hP 3. -On -.B bob -now, make -.B /var/lib/tripe -the current directory, and import the key material from -.BR alice : -.RS -.VS -key merge param -key \-kkeyring.pub merge alice.pub -.VE -Generate a private key for -.B bob -and extract the public half, as before: -.VS -key add \-adh \-pparam \-tbob \e - \-e"now + 1 year" tripe\-dh -key extract \-f\-secret bob.pub bob -key \-kkeyring.pub merge bob.pub -.VE -and send -.B bob.pub -back to -.B alice -using some secure method. -.RE -.hP 4 -On -.BR alice , -merge -.B bob 's -key into the public keyring. Now, on each host, run -.RS -.VS -key \-kkeyring.pub fingerprint + \-e"now + 1 year" tripe .VE -and check that the hashes match. If the two sites have separate -administrators, they should read the hashes to each other over the -telephone (assuming that they can recognize each other's voices). -.RE -.hP 5. -Start the -.B tripe -servers up. Run -.RS +To create elliptic curve keys, say something like .VS -tripectl \-slD -.VE -on each of -.B alice -and -.BR bob . -.RE -.hP 6. -To get -.B alice -talking to -.BR bob , -run this shell script (or one like it): -.RS -.VS -#! /bin/sh - -tripectl add bob 200.0.2.1 4070 -ifname=`tripectl ifname bob` -ifconfig $ifname 10.0.1.1 pointopoint 10.0.2.1 -route add -net \e - 10.0.2.0 netmask 255.255.255.0 \e - gw 10.0.2.1 -.VE -Read -.BR ifconfig (8) -and -.BR route (8) -to find out about your system's variants of these commands. The -versions shown above assume a Linux system. -Run a similar script on -.BR bob , -to tell its -.B tripe -server to talk to -.BR alice . -.RE -.hP 7. -Congratulations. The two servers will exchange keys and begin sending -packets almost immediately. You've set up a virtual private network. -.SS "Using elliptic curve keys" -The -.B tripe -server can use elliptic curve Diffie-Hellman for key exchange, rather -than traditional integer Diffie-Hellman. Given current public -knowledge, elliptic curves can provide similar or better security to -systems based on integer discrete log problems, faster, and with less -transmitted data. It's a matter of controversy whether this will -continue to be the case. The author uses elliptic curves. -.PP -The server works out which it -should be doing based on the key type, which is either -.B tripe\-dh -for standard Diffie-Hellman, or -.B tripe\-ec -for elliptic curves. To create elliptic curve keys, say something like -.VS -key add \-aec\-param \-Cnist-p192 \-eforever \e - \-tparam tripe\-ec\-param +key add \-aec\-param \-Cnist-p256 \-eforever \e + \-tparam tripe\-param kx-group=ec .VE to construct a parameters key, using your preferred elliptic curve in the @@ -447,13 +329,13 @@ option (see for details); and create the private keys by .VS key add \-aec \-pparam \-talice \e - \-e"now + 1 year" tripe\-ec + \-e"now + 1 year" tripe .VE -Now start -.B tripe -with the -.B \-ttripe\-ec -option, and all should be well. +Note that the +.BR tripe-keys (8) +program provides a rather more convenient means for generating and +managing keys for +.BR tripe . .SS "Using other symmetric algorithms" The default symmetric algorithms .B tripe @@ -559,7 +441,8 @@ find one, please inform the author . .BR key (1), .BR tripectl (1), -.BR tripe\-admin (5). +.BR tripe\-admin (5), +.BR tripe\-keys (8). .PP .IR "The Trivial IP Encryption Protocol" , .IR "The Wrestlers Protocol" . diff --git a/server/tripe.c b/server/tripe.c index a2731c38..2dc03434 100644 --- a/server/tripe.c +++ b/server/tripe.c @@ -114,7 +114,7 @@ Options:\n\ int main(int argc, char *argv[]) { const char *kr_priv = "keyring", *kr_pub = "keyring.pub"; - const char *tag_priv = "tripe-dh"; + const char *tag_priv = 0; const char *csock = SOCKETDIR "/tripesock"; const char *dir = CONFIGDIR; const char *p; -- [mdw]