factorial: Fix usage message to fit in with conventions.
[u/mdw/catacomb] / keyutil.c
index 1d4bbca..1adb840 100644 (file)
--- a/keyutil.c
+++ b/keyutil.c
@@ -197,6 +197,7 @@ typedef struct keyopts {
 #define f_limlee 8u                    /* Generate Lim-Lee primes */
 #define f_subgroup 16u                 /* Generate a subgroup */
 #define f_retag 32u                    /* Remove any existing tag */
+#define f_kcdsa 64u                    /* Generate KCDSA primes */
 
 /* --- @dolock@ --- *
  *
@@ -609,6 +610,24 @@ static void alg_dhparam(keyopts *k)
        key_putattr(k->kf, k->k, "factors", d.buf);
        dstr_destroy(&d);
       }
+    } else if (k->f & f_kcdsa) {
+      if (!k->qbits)
+       k->qbits = 256;
+      rc = dh_kcdsagen(&dp, k->qbits, k->bits, 0,
+                      0, k->r, (k->f & f_quiet) ? 0 : pgen_ev, 0);
+      if (!rc) {
+       dstr d = DSTR_INIT;
+       mp *v = MP_NEW;
+
+       mp_writedstr(dp.q, &d, 10);
+       mp_div(&v, 0, dp.p, dp.q);
+       v = mp_lsr(v, v, 1);
+       dstr_puts(&d, ", ");
+       mp_writedstr(v, &d, 10);
+       mp_drop(v);
+       key_putattr(k->kf, k->k, "factors", d.buf);
+       dstr_destroy(&d);
+      }
     } else
       rc = dh_gen(&dp, k->qbits, k->bits, 0, k->r,
                  (k->f & f_quiet) ? 0 : pgen_ev, 0);
@@ -951,9 +970,10 @@ static int cmd_add(int argc, char *argv[])
       { "quiet",       0,              0,      'q' },
       { "lim-lee",     0,              0,      'L' },
       { "subgroup",    0,              0,      'S' },
+      { "kcdsa",       0,              0,      'K' },
       { 0,             0,              0,      0 }
     };
-    int i = mdwopt(argc, argv, "+a:b:B:p:e:c:t:R:C:A:s:n:lqrLS",
+    int i = mdwopt(argc, argv, "+a:b:B:p:e:c:t:R:C:A:s:n:lqrLKS",
                   opt, 0, 0, 0);
     if (i < 0)
       break;
@@ -1015,7 +1035,7 @@ static int cmd_add(int argc, char *argv[])
       /* --- Expiry dates get passed to @get_date@ for parsing --- */
 
       case 'e':
-       if (strncmp(optarg, "forever", strlen(optarg)) == 0)
+       if (strcmp(optarg, "forever") == 0)
          exp = KEXP_FOREVER;
        else {
          exp = get_date(optarg, 0);
@@ -1113,6 +1133,9 @@ static int cmd_add(int argc, char *argv[])
       case 'L':
        k.f |= f_limlee;
        break;
+      case 'K':
+       k.f |= f_kcdsa;
+       break;
       case 'S':
        k.f |= f_subgroup;
        break;
@@ -1166,7 +1189,9 @@ static int cmd_add(int argc, char *argv[])
     int err;
     key *kk;
     if (k.f & f_retag) {
-      if ((kk = key_bytag(&f, tag)) != 0 && strcmp(kk->tag, tag) == 0)
+      if ((kk = key_bytag(&f, tag)) != 0 &&
+         kk->tag &&
+         strcmp(kk->tag, tag) == 0)
        key_settag(&f, kk, 0);
     }
     if ((err = key_settag(&f, k.k, tag)) != 0)
@@ -1609,6 +1634,29 @@ static int cmd_setattr(int argc, char *argv[])
   return (0);
 }
 
+/* --- @cmd_getattr@ --- */
+
+static int cmd_getattr(int argc, char *argv[])
+{
+  key_file f;
+  key *k;
+  dstr d = DSTR_INIT;
+  const char *p;
+
+  if (argc != 3)
+    die(EXIT_FAILURE, "Usage: getattr TAG ATTR");
+  doopen(&f, KOPEN_READ);
+  if ((k = key_bytag(&f, argv[1])) == 0)
+    die(EXIT_FAILURE, "key `%s' not found", argv[1]);
+  key_fulltag(k, &d);
+  if ((p = key_getattr(&f, k, argv[2])) == 0)
+    die(EXIT_FAILURE, "no attribute `%s' for key `%s'", argv[2], d.buf);
+  puts(p);
+  dstr_destroy(&d);
+  doclose(&f);
+  return (0);
+}
+
 /* --- @cmd_finger@ --- */
 
 static void fingerprint(key *k, const gchash *ch, const key_filter *kf)
@@ -1784,6 +1832,7 @@ static int cmd_verify(int argc, char *argv[])
   fpr = GH_DONE(h, 0);
   if (memcmp(fpr, buf, ch->hashsz) != 0)
     die(EXIT_FAILURE, "key fingerprint mismatch");
+  doclose(&f);
   return (0);
 }
   
@@ -1905,6 +1954,8 @@ static int cmd_extract(int argc, char *argv[])
   int i;
   int rc = 0;
   key_filter kf = { 0, 0 };
+  dstr d = DSTR_INIT;
+  const char *outfile = 0;
   FILE *fp;
 
   for (;;) {
@@ -1933,9 +1984,13 @@ static int cmd_extract(int argc, char *argv[])
     die(EXIT_FAILURE, "Usage: extract [-f FILTER] FILE [TAG...]");
   if (strcmp(*argv, "-") == 0)
     fp = stdout;
-  else if (!(fp = fopen(*argv, "w"))) {
-    die(EXIT_FAILURE, "couldn't open `%s' for writing: %s",
-       *argv, strerror(errno));
+  else {
+    outfile = *argv;
+    dstr_putf(&d, "%s.new", outfile);
+    if (!(fp = fopen(d.buf, "w"))) {
+      die(EXIT_FAILURE, "couldn't open `%s' for writing: %s",
+         d.buf, strerror(errno));
+    }
   }
 
   doopen(&f, KOPEN_READ);
@@ -1954,8 +2009,9 @@ static int cmd_extract(int argc, char *argv[])
       }
     }
   }
-  if (fclose(fp))
+  if (fclose(fp) || (outfile && rename(d.buf, outfile)))
     die(EXIT_FAILURE, "error writing file: %s", strerror(errno));
+  dstr_destroy(&d);
   doclose(&f);
   return (rc);
 }
@@ -2057,6 +2113,7 @@ Options:\n\
   { "expire", cmd_expire, "expire TAG..." },
   { "delete", cmd_delete, "delete TAG..." },
   { "setattr", cmd_setattr, "setattr TAG ATTR..." },
+  { "getattr", cmd_getattr, "getattr TAG ATTR" },
   { "comment", cmd_comment, "comment TAG [COMMENT]" },
   { "lock", cmd_lock, "lock QTAG" },
   { "unlock", cmd_unlock, "unlock QTAG" },
@@ -2068,7 +2125,7 @@ Options:\n\
   { "tidy", cmd_tidy, "tidy" },
   { "add", cmd_add,
     "add [-OPTIONS] TYPE [ATTR...]\n\
-       Options: [-lqrLS] [-a ALG] [-bB BITS] [-p PARAM] [-R TAG]\n\
+       Options: [-lqrLKS] [-a ALG] [-bB BITS] [-p PARAM] [-R TAG]\n\
                 [-A SEEDALG] [-s SEED] [-n BITS]\n\
                 [-e EXPIRE] [-t TAG] [-c COMMENT]", "\
 Options:\n\
@@ -2092,6 +2149,7 @@ Options:\n\
 -l, --lock             Lock the generated key with a passphrase.\n\
 -q, --quiet            Don't give progress indicators while working.\n\
 -L, --lim-lee          Generate Lim-Lee primes for Diffie-Hellman groups.\n\
+-K, --kcdsa            Generate KCDSA-style Lim-Lee primes for DH groups.\n\
 -S, --subgroup         Use a prime-order subgroup for Diffie-Hellman.\n\
 " },
   { 0, 0, 0 }