lsh_keygen.c 4.46 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

/* 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
J.H.M. Dassen's avatar
J.H.M. Dassen committed
26
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
Niels Möller's avatar
Niels Möller committed
27
28
 */

Niels Möller's avatar
Niels Möller committed
29
#include "dsa_keygen.h"
Niels Möller's avatar
Niels Möller committed
30

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

#include "getopt.h"

#include <stdio.h>
Niels Möller's avatar
Niels Möller committed
42
#include <stdlib.h>
Niels Möller's avatar
Niels Möller committed
43

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

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

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

Niels Möller's avatar
Niels Möller committed
56
57
58
59
60
61
62
63
64
65
66
67
static void
do_lsh_keygen_handler(struct exception_handler *s UNUSED,
		      const struct exception *e)
{
  werror("lsh_keygen: %z\n", e->msg);

  exit(EXIT_FAILURE);
}

static struct exception_handler handler =
STATIC_EXCEPTION_HANDLER(do_lsh_keygen_handler, NULL);

Niels Möller's avatar
Niels Möller committed
68
69
int main(int argc, char **argv)
{
70
71
72
73
  int option;
  long l = 4;
  int style = SEXP_TRANSPORT;
  
Niels Möller's avatar
Niels Möller committed
74
  struct dsa_public public;
Niels Möller's avatar
Niels Möller committed
75
76
77
78
  mpz_t x;
  
  mpz_t t;
  struct randomness *r;
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93

  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))
	    {
94
	      werror("lsh_keygen: nist-level should be in the range 0-8.\n");
95
96
97
98
99
	      usage();
	    }
	  break;
	}
      case 'a':
Niels Möller's avatar
Niels Möller committed
100
	if (strcmp(optarg, "dsa"))
101
	  {
102
	    werror("lsh_keygen: Sorry, doesn't support any algorithm but dsa.\n");
103
104
105
106
107
108
109
110
111
112
113
114
115
116
	    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
	  {
117
	    werror("lsh_keygen: Style must be one of\n"
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
		   "  '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
134
  
135
  if (argc != optind)
Niels Möller's avatar
Niels Möller committed
136
137
138
139
140
141
142
143
144
145
146
147
    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);
Niels Möller's avatar
Niels Möller committed
148
  dsa_nist_gen(public.p, public.q, r, l);
Niels Möller's avatar
Niels Möller committed
149

150
151
  debug("%xn\n"
	"%xn\n", public.p, public.q);
Niels Möller's avatar
Niels Möller committed
152
153

  /* Sanity check. */
Niels Möller's avatar
Niels Möller committed
154
  if (!mpz_probab_prime_p(public.p, 10))
Niels Möller's avatar
Niels Möller committed
155
    {
156
      werror("p not a prime!\n");
Niels Möller's avatar
Niels Möller committed
157
158
159
      return 1;
    }

Niels Möller's avatar
Niels Möller committed
160
  if (!mpz_probab_prime_p(public.q, 10))
Niels Möller's avatar
Niels Möller committed
161
    {
162
      werror("q not a prime!\n");
Niels Möller's avatar
Niels Möller committed
163
164
165
      return 1;
    }

Niels Möller's avatar
Niels Möller committed
166
  mpz_fdiv_r(t, public.p, public.q);
Niels Möller's avatar
Niels Möller committed
167
168
  if (mpz_cmp_ui(t, 1))
    {
169
      werror("q doesn't divide p-1 !\n");
Niels Möller's avatar
Niels Möller committed
170
171
172
      return 1;
    }

Niels Möller's avatar
Niels Möller committed
173
  dsa_find_generator(public.g, r, public.p, public.q);
Niels Möller's avatar
Niels Möller committed
174
175

  r = make_reasonably_random();
Niels Möller's avatar
Niels Möller committed
176
  mpz_set(t, public.q);
Niels Möller's avatar
Niels Möller committed
177
178
179
180
181
  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
182
  mpz_powm(public.y, public.g, x, public.p);
Niels Möller's avatar
Niels Möller committed
183
  
Niels Möller's avatar
Niels Möller committed
184
185
  {
    /* Now, output a private key spki structure. */
186
    struct abstract_write *output = make_blocking_write(STDOUT_FILENO, 0);
Niels Möller's avatar
Niels Möller committed
187
188
189
    
    struct lsh_string *key = sexp_format
      (sexp_l(2, sexp_z("private-key"),
Niels Möller's avatar
Niels Möller committed
190
	      sexp_l(6, sexp_z("dsa"),
Niels Möller's avatar
Niels Möller committed
191
192
193
194
195
		     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),
196
       style, 0);
Niels Möller's avatar
Niels Möller committed
197

Niels Möller's avatar
Niels Möller committed
198
199
200
    A_WRITE(output, key, &handler);

    return EXIT_SUCCESS;
Niels Möller's avatar
Niels Möller committed
201
  }
Niels Möller's avatar
Niels Möller committed
202
203
204
}