lsh_keygen.c 4.19 KB
Newer Older
Niels Möller's avatar
Niels Möller committed
1 2
/* lsh_keygen.c
 *
Niels Möller's avatar
Niels Möller committed
3
 * Generic key-generation program. Writes a spki-packaged private key
Niels Möller's avatar
Niels Möller committed
4 5 6
 * on stdout. You would usually pipe this to some other program to
 * extract the public key, encrypt the private key, and save the
 * results in two separate files.
Niels Möller's avatar
Niels Möller committed
7
 *
Niels Möller's avatar
Niels Möller committed
8
 * $Id$ */
Niels Möller's avatar
Niels Möller committed
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

/* lsh, an implementation of the ssh protocol
 *
 * Copyright (C) 1998 Niels Mller
 *
 * 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 of the
 * License, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include "dss_keygen.h"

Niels Möller's avatar
Niels Möller committed
31
#include "blocking_write.h"
Niels Möller's avatar
Niels Möller committed
32 33 34 35
#include "crypto.h"
#include "format.h"
#include "publickey_crypto.h"
#include "randomness.h"
Niels Möller's avatar
Niels Möller committed
36 37
#include "sexp.h"
#include "werror.h"
Niels Möller's avatar
Niels Möller committed
38 39 40 41 42

#include "getopt.h"

#include <stdio.h>

43
#if HAVE_UNISTD_H
Niels Möller's avatar
Niels Möller committed
44
#include <unistd.h>
45
#endif
Niels Möller's avatar
Niels Möller committed
46

Niels Möller's avatar
Niels Möller committed
47 48 49 50
static void usage(void) NORETURN;

static void usage(void)
{
51
  wwrite("Usage: lsh_keygen [-o style] [-l nist-level] [-a dss] [-q] [-d] [-v]\n");
Niels Möller's avatar
Niels Möller committed
52 53 54 55 56
  exit(1);
}

int main(int argc, char **argv)
{
57 58 59 60
  int option;
  long l = 4;
  int style = SEXP_TRANSPORT;
  
Niels Möller's avatar
Niels Möller committed
61 62 63 64 65
  struct dss_public public;
  mpz_t x;
  
  mpz_t t;
  struct randomness *r;
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80

  while((option = getopt(argc, argv, "a:dl:o:qv")) != -1)
    switch(option)
      {
      case 'l':
	{
	  char *end;

	  l = strtol(optarg, &end, 0);
	      
	  if (!*optarg || *end)
	    usage();

	  if ( (l<0) || (l > 8))
	    {
81
	      wwrite("lsh_keygen: nist-level should be in the range 0-8.\n");
82 83 84 85 86 87 88
	      usage();
	    }
	  break;
	}
      case 'a':
	if (strcmp(optarg, "dss"))
	  {
89
	    wwrite("lsh_keygen: Sorry, doesn't support any algorithm but dss.\n");
90 91 92 93 94 95 96 97 98 99 100 101 102 103
	    usage();
	  }
	break;
      case 'o':
	if (!strcmp(optarg, "transport"))
	  style = SEXP_TRANSPORT;
	else if (!strcmp(optarg, "canonical"))
	  style = SEXP_CANONICAL;
	else if (!strcmp(optarg, "advanced"))
	  style = SEXP_ADVANCED;
	else if (!strcmp(optarg, "international"))
	  style = SEXP_INTERNATIONAL;
	else
	  {
104
	    wwrite("lsh_keygen: Style must be one of\n"
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
		   "  'transport', 'canonical', 'advanced' or 'international'\n");
	    usage();
	  }
	break;
      case 'q':
	quiet_flag = 1;
	break;
      case 'd':
	debug_flag = 1;
	break;
      case 'v':
	verbose_flag = 1;
	break;
      default:
	usage();
      }
Niels Möller's avatar
Niels Möller committed
121
  
122
  if (argc != optind)
Niels Möller's avatar
Niels Möller committed
123 124 125 126 127 128 129 130 131 132 133 134 135 136
    usage();
  
  mpz_init(public.p);
  mpz_init(public.q);
  mpz_init(public.g);
  mpz_init(public.y);

  mpz_init(x);
  
  mpz_init(t);

  r = make_poor_random(&sha_algorithm, NULL);
  dss_nist_gen(public.p, public.q, r, l);

Niels Möller's avatar
Niels Möller committed
137 138 139 140
  debug_mpz(public.p);
  debug("\n");
  debug_mpz(public.q);
  debug("\n");
Niels Möller's avatar
Niels Möller committed
141 142

  /* Sanity check. */
Niels Möller's avatar
Niels Möller committed
143
  if (!mpz_probab_prime_p(public.p, 10))
Niels Möller's avatar
Niels Möller committed
144
    {
145
      wwrite("p not a prime!\n");
Niels Möller's avatar
Niels Möller committed
146 147 148
      return 1;
    }

Niels Möller's avatar
Niels Möller committed
149
  if (!mpz_probab_prime_p(public.q, 10))
Niels Möller's avatar
Niels Möller committed
150
    {
151
      wwrite("q not a prime!\n");
Niels Möller's avatar
Niels Möller committed
152 153 154
      return 1;
    }

Niels Möller's avatar
Niels Möller committed
155
  mpz_fdiv_r(t, public.p, public.q);
Niels Möller's avatar
Niels Möller committed
156 157
  if (mpz_cmp_ui(t, 1))
    {
158
      wwrite("q doesn't divide p-1 !\n");
Niels Möller's avatar
Niels Möller committed
159 160 161 162 163 164
      return 1;
    }

  dss_find_generator(public.g, r, public.p, public.q);

  r = make_reasonably_random();
Niels Möller's avatar
Niels Möller committed
165
  mpz_set(t, public.q);
Niels Möller's avatar
Niels Möller committed
166 167 168 169 170
  mpz_sub_ui(t, t, 2);
  bignum_random(x, r, t);

  mpz_add_ui(x, x, 1);

Niels Möller's avatar
Niels Möller committed
171
  mpz_powm(public.y, public.g, x, public.p);
Niels Möller's avatar
Niels Möller committed
172
  
Niels Möller's avatar
Niels Möller committed
173 174
  {
    /* Now, output a private key spki structure. */
175
    struct abstract_write *output = make_blocking_write(STDOUT_FILENO, 0);
Niels Möller's avatar
Niels Möller committed
176 177 178 179
    
    struct lsh_string *key = sexp_format
      (sexp_l(2, sexp_z("private-key"),
	      sexp_l(6, sexp_z("dss"),
Niels Möller's avatar
Niels Möller committed
180 181 182 183 184
		     sexp_l(2, sexp_z("p"), sexp_un(public.p), -1),
		     sexp_l(2, sexp_z("q"), sexp_un(public.q), -1),
		     sexp_l(2, sexp_z("g"), sexp_un(public.g), -1),
		     sexp_l(2, sexp_z("y"), sexp_un(public.y), -1),
		     sexp_l(2, sexp_z("x"), sexp_un(x), -1), -1), -1),
185
       style, 0);
Niels Möller's avatar
Niels Möller committed
186 187 188 189

    return LSH_FAILUREP(A_WRITE(output, key))
      ? 1 : 0;
  }
Niels Möller's avatar
Niels Möller committed
190 191 192
}