/* $Id: sfskeygen.C,v 1.32 2001/08/19 00:27:15 dm Exp $ */ /* * * Copyright (C) 1999 Michael Kaminsky (kaminsky@lcs.mit.edu) * Copyright (C) 1998, 1999 David Mazieres (dm@uun.org) * * This program 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, or (at * your option) any later version. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * */ #include "sfskey.h" #include "srp.h" str keysave (str keyfile, const sfskey *sk, bool excl) { assert (!sk->pwd || sk->cost); str s = export_rabin_priv (*sk->key, sk->pwd, sk->keyname, sk->cost); if (!s) panic ("export_rabin_priv failed\n"); ptr x = import_rabin_priv (s, sk->pwd); assert (x); assert (sk->key->p == x->p); assert (sk->key->q == x->q); if (!str2file (keyfile, s, 0600, excl)) return keyfile << ": " << strerror (errno); return NULL; } str defkeyname (str user) { if (!user && !(user = myusername ())) fatal << "cannot find login name\n"; if (str host = myname ()) return user << "@" << host; else fatal << "cannot find local host name\n"; } str keygen (sfskey *sk, u_int nbits, str prompt, bool askname, bool nopwd, bool nokbdnoise) { if (!nbits) nbits = sfs_pubkeysize; if (nbits < sfs_minpubkeysize) return strbuf ("public keys must be at least %d bits", sfs_minpubkeysize); random_start (); rndaskcd (); sk->key = NULL; if (!sk->keyname) sk->keyname = defkeyname (); if (!prompt) prompt = sk->keyname; warnx << "Creating new key for " << prompt << ".\n"; if (askname) sk->keyname = getline (" Key Name: ", sk->keyname); else warnx << " Key Name: " << sk->keyname << "\n"; if (nopwd) sk->pwd = NULL; else if (!(sk->pwd = getpwdconfirm ("Enter passprase: "))) return "Aborted."; if (!nokbdnoise) rndkbd (); random_init (); if (!sk->cost) sk->cost = sfs_pwdcost; sk->key = New refcounted (rabin_keygen (nbits)); return NULL; } void sfskey_edit (int argc, char **argv) { bool nopwd = false; u_int cost = 0; str outfile, comment, keyname; int ch; while ((ch = getopt (argc, argv, "Po:c:n:")) != -1) switch (ch) { case 'P': nopwd = true; break; case 'o': outfile = optarg; break; case 'c': if (!convertint (optarg, &cost)) usage (); if (cost > sfs_maxpwdcost) fatal ("password cost must be far less than %d\n", sfs_minpubkeysize); break; case 'n': comment = optarg; break; default: usage (); break; } if (argc == optind) keyname = defkey (); else if (argc == optind + 1) keyname = argv[optind]; else usage (); if ((outfile && isremote (outfile)) || (!outfile && isremote (keyname))) fatal ("must specify a local output file with -o\n"); errno = EEXIST; if (outfile && (access (outfile, 0) >= 0 || errno != ENOENT)) fatal << outfile << ": " << strerror (errno) << "\n"; random_start (); if (outfile) warnx << "Copying key " << keyname << " to " << outfile << ".\n"; else if (nopwd) warnx << "Removing passphrase from key " << keyname << ".\n"; else warnx << "Editing passphrase on key " << keyname << ".\n"; sfskey k; if (str err = keyfetch (&k, keyname)) fatal << err << "\n"; if (cost) k.cost = cost; if (comment) k.keyname = comment; if (nopwd) k.pwd = NULL; else if (!isremote (keyname)) k.pwd = getpwdconfirm (" New passphrase: "); random_init (); if (str err = keysave (outfile ? outfile : keyname, &k, outfile)) fatal << err << "\n"; exit (0); } void sfskey_gen (int argc, char **argv) { bool nopwd = false, nokbdnoise = false; u_int nbits = 0, cost = 0; str keyname, keyfile; int ch; while ((ch = getopt (argc, argv, "b:c:n:KP")) != -1) switch (ch) { case 'b': if (!convertint (optarg, &nbits)) usage (); break; case 'c': if (!convertint (optarg, &cost)) usage (); if (cost > sfs_maxpwdcost) fatal ("password cost must be far less than %d\n", sfs_minpubkeysize); break; case 'n': keyname = optarg; break; case 'K': nokbdnoise = true; break; case 'P': nopwd = true; break; default: usage (); break; } if (optind == argc) { agent_mkdir (); keyfile = defkey (); } else if (optind + 1 == argc) keyfile = argv[optind]; else usage (); if (isremote (keyfile)) fatal << keyfile << ": not local\n(Try ./" << keyfile << " if you really want '@' in the file name.)\n"; errno = EEXIST; if (access (keyfile, 0) >= 0 || errno != ENOENT) fatal << keyfile << "; " << strerror (errno) << "\n"; sfskey k; k.keyname = keyname; k.cost = cost; if (str err = keygen (&k, nbits, keyfile, !keyname, nopwd, nokbdnoise)) fatal << err << "\n"; if (str err = keysave (keyfile, &k)) fatal << err << "\n"; exit (0); } void sfskey_srpgen (int argc, char **argv) { u_int nbits = sfs_pubkeysize; int ch; while ((ch = getopt (argc, argv, "b:c:n:KP")) != -1) switch (ch) { case 'b': if (!convertint (optarg, &nbits)) usage (); if (nbits < srp_base::minprimsize) fatal ("srp primes must be at least %d bits\n", srp_base::minprimsize); break; default: usage (); break; } if (optind + 1 != argc) usage (); random_set_seedfile (RANDOM_SEED); random_init (); warnx ("Generating SRP parameters. This can take several minutes..."); err_flush (); bigint N, g; srp_base::genparam (nbits, &N, &g); warnx (" done\n"); if (!str2file (argv[optind], export_srp_params (N, g), 0444)) fatal ("%s: %m\n", argv[optind]); exit (0); }