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

Niels Möller's avatar
Niels Möller committed
43
44
#include <unistd.h>

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

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

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

  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))
	    {
79
	      wwrite("lsh_keygen: nist-level should be in the range 0-8.\n");
80
81
82
83
84
85
86
	      usage();
	    }
	  break;
	}
      case 'a':
	if (strcmp(optarg, "dss"))
	  {
87
	    wwrite("lsh_keygen: Sorry, doesn't support any algorithm but dss.\n");
88
89
90
91
92
93
94
95
96
97
98
99
100
101
	    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
	  {
102
	    wwrite("lsh_keygen: Style must be one of\n"
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
		   "  '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
119
  
120
  if (argc != optind)
Niels Möller's avatar
Niels Möller committed
121
122
123
124
125
126
127
128
129
130
131
132
133
134
    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
135
136
137
138
  debug_mpz(public.p);
  debug("\n");
  debug_mpz(public.q);
  debug("\n");
Niels Möller's avatar
Niels Möller committed
139
140

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

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

Niels Möller's avatar
Niels Möller committed
153
  mpz_fdiv_r(t, public.p, public.q);
Niels Möller's avatar
Niels Möller committed
154
155
  if (mpz_cmp_ui(t, 1))
    {
156
      wwrite("q doesn't divide p-1 !\n");
Niels Möller's avatar
Niels Möller committed
157
158
159
160
161
162
      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
163
  mpz_set(t, public.q);
Niels Möller's avatar
Niels Möller committed
164
165
166
167
168
  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
169
  mpz_powm(public.y, public.g, x, public.p);
Niels Möller's avatar
Niels Möller committed
170
  
Niels Möller's avatar
Niels Möller committed
171
172
  {
    /* Now, output a private key spki structure. */
173
    struct abstract_write *output = make_blocking_write(STDOUT_FILENO, 0);
Niels Möller's avatar
Niels Möller committed
174
175
176
177
178
179
180
181
182
    
    struct lsh_string *key = sexp_format
      (sexp_l(2, sexp_z("private-key"),
	      sexp_l(6, sexp_z("dss"),
		     sexp_l(2, sexp_z("p"), sexp_n(public.p), -1),
		     sexp_l(2, sexp_z("q"), sexp_n(public.q), -1),
		     sexp_l(2, sexp_z("g"), sexp_n(public.g), -1),
		     sexp_l(2, sexp_z("y"), sexp_n(public.y), -1),
		     sexp_l(2, sexp_z("x"), sexp_n(x), -1), -1), -1),
183
       style, 0);
Niels Möller's avatar
Niels Möller committed
184
185
186
187

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