http://downloads.netgear.com/files/GPL/GPL_Source_V361j_DM111PSP_series_consumer_rele...
[bcm963xx.git] / userapps / opensource / sshd / dropbearkey.c
1 /*
2  * Dropbear - a SSH2 server
3  * 
4  * Copyright (c) 2002,2003 Matt Johnston
5  * All rights reserved.
6  * 
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  * 
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  * 
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23  * SOFTWARE. */
24
25 /* The format of the keyfiles is basically a raw dump of the buffer. Data types
26  * are specified in the transport draft - string is a 32-bit len then the
27  * non-null-terminated string, mp_int is a 32-bit len then the bignum data.
28  * The actual functions are buf_put_rsa_priv_key() and buf_put_dss_priv_key()
29
30  * RSA:
31  * string       "ssh-rsa"
32  * mp_int       e
33  * mp_int       n
34  * mp_int       d
35  * mp_int       p (newer versions only)
36  * mp_int       q (newer versions only) 
37  *
38  * DSS:
39  * string       "ssh-dss"
40  * mp_int       p
41  * mp_int       q
42  * mp_int       g
43  * mp_int       y
44  * mp_int       x
45  *
46  */
47 #include "includes.h"
48 #include "signkey.h"
49 #include "buffer.h"
50 #include "dbutil.h"
51
52 #include "genrsa.h"
53 #include "gendss.h"
54
55 static void printhelp(char * progname);
56
57 #define RSA_SIZE (1024/8) /* 1024 bit */
58 #define DSS_SIZE (1024/8) /* 1024 bit */
59
60 static void buf_writefile(buffer * buf, const char * filename);
61 static void printpubkey(sign_key * key, int keytype);
62 static void justprintpub(const char* filename);
63
64 /* Print a help message */
65 static void printhelp(char * progname) {
66
67         fprintf(stderr, "Usage: %s -t <type> -f <filename> [-s bits]\n"
68                                         "Options are:\n"
69                                         "-t type        Type of key to generate. One of:\n"
70 #ifdef DROPBEAR_RSA
71                                         "               rsa\n"
72 #endif
73 #ifdef DROPBEAR_DSS
74                                         "               dss\n"
75 #endif
76                                         "-f filename    Use filename for the secret key\n"
77                                         "-s bits        Key size in bits, should be a multiple of 8 (optional)\n"
78                                         "-y             Just print the publickey and fingerprint for the\n              private key in <filename>.\n"
79 #ifdef DEBUG_TRACE
80                                         "-v             verbose\n"
81 #endif
82                                         ,progname);
83 }
84
85 #if defined(DBMULTI_dropbearkey) || !defined(DROPBEAR_MULTI)
86 #if defined(DBMULTI_dropbearkey) && defined(DROPBEAR_MULTI)
87 int dropbearkey_main(int argc, char ** argv) {
88 #else
89 int main(int argc, char ** argv) {
90 #endif
91
92         int i;
93         char ** next = 0;
94         sign_key *key = NULL;
95         buffer *buf = NULL;
96         char * filename = NULL;
97         int keytype = -1;
98         char * typetext = NULL;
99         char * sizetext = NULL;
100         unsigned int bits;
101         unsigned int keysize;
102         int printpub = 0;
103
104         /* get the commandline options */
105         for (i = 1; i < argc; i++) {
106                 if (argv[i] == NULL) {
107                         continue; /* Whack */
108                 } 
109                 if (next) {
110                         *next = argv[i];
111                         next = NULL;
112                         continue;
113                 }
114
115                 if (argv[i][0] == '-') {
116                         switch (argv[i][1]) {
117                                 case 'f':
118                                         next = &filename;
119                                         break;
120                                 case 't':
121                                         next = &typetext;
122                                         break;
123                                 case 's':
124                                         next = &sizetext;
125                                         break;
126                                 case 'y':
127                                         printpub = 1;
128                                         break;
129                                 case 'h':
130                                         printhelp(argv[0]);
131                                         exit(EXIT_SUCCESS);
132                                         break;
133 #ifdef DEBUG_TRACE
134                                 case 'v':
135                                         debug_trace = 1;
136                                         break;
137 #endif
138                                 default:
139                                         fprintf(stderr, "Unknown argument %s\n", argv[i]);
140                                         printhelp(argv[0]);
141                                         exit(EXIT_FAILURE);
142                                         break;
143                         }
144                 }
145         }
146
147         if (!filename) {
148                 fprintf(stderr, "Must specify a key filename\n");
149                 printhelp(argv[0]);
150                 exit(EXIT_FAILURE);
151         }
152
153         if (printpub) {
154                 justprintpub(filename);
155                 /* Not reached */
156         }
157
158         /* check/parse args */
159         if (!typetext) {
160                 fprintf(stderr, "Must specify key type\n");
161                 printhelp(argv[0]);
162                 exit(EXIT_FAILURE);
163         }
164
165         if (strlen(typetext) == 3) {
166 #ifdef DROPBEAR_RSA
167                 if (strncmp(typetext, "rsa", 3) == 0) {
168                         keytype = DROPBEAR_SIGNKEY_RSA;
169                         TRACE(("type is rsa"))
170                 }
171 #endif
172 #ifdef DROPBEAR_DSS
173                 if (strncmp(typetext, "dss", 3) == 0) {
174                         keytype = DROPBEAR_SIGNKEY_DSS;
175                         TRACE(("type is dss"))
176                 }
177 #endif
178         }
179         if (keytype == -1) {
180                 fprintf(stderr, "Unknown key type '%s'\n", typetext);
181                 printhelp(argv[0]);
182                 exit(EXIT_FAILURE);
183         }
184
185         if (sizetext) {
186                 if (sscanf(sizetext, "%u", &bits) != 1) {
187                         fprintf(stderr, "Bits must be an integer\n");
188                         exit(EXIT_FAILURE);
189                 }
190         
191                 if (bits < 512 || bits > 4096 || (bits % 8 != 0)) {
192                         fprintf(stderr, "Bits must satisfy 512 <= bits <= 4096, and be a"
193                                         " multiple of 8\n");
194                         exit(EXIT_FAILURE);
195                 }
196
197                 keysize = bits / 8;
198         } else {
199                 if (keytype == DROPBEAR_SIGNKEY_DSS) {
200                         keysize = DSS_SIZE;
201                 } else if (keytype == DROPBEAR_SIGNKEY_RSA) {
202                         keysize = RSA_SIZE;
203                 } else {
204                         exit(EXIT_FAILURE); /* not reached */
205                 }
206         }
207
208
209         fprintf(stderr, "Will output %d bit %s secret key to '%s'\n", keysize*8,
210                         typetext, filename);
211
212         /* don't want the file readable by others */
213         umask(077);
214
215         /* now we can generate the key */
216         key = new_sign_key();
217         
218         fprintf(stderr, "Generating key, this may take a while...\n");
219         switch(keytype) {
220 #ifdef DROPBEAR_RSA
221                 case DROPBEAR_SIGNKEY_RSA:
222                         key->rsakey = gen_rsa_priv_key(keysize); /* 128 bytes = 1024 bit */
223                         break;
224 #endif
225 #ifdef DROPBEAR_DSS
226                 case DROPBEAR_SIGNKEY_DSS:
227                         key->dsskey = gen_dss_priv_key(keysize); /* 128 bytes = 1024 bit */
228                         break;
229 #endif
230                 default:
231                         fprintf(stderr, "Internal error, bad key type\n");
232                         exit(EXIT_FAILURE);
233         }
234
235         buf = buf_new(MAX_PRIVKEY_SIZE); 
236
237         buf_put_priv_key(buf, key, keytype);
238         buf_setpos(buf, 0);
239         buf_writefile(buf, filename);
240
241         buf_burn(buf);
242         buf_free(buf);
243
244         printpubkey(key, keytype);
245
246         sign_key_free(key);
247
248         return EXIT_SUCCESS;
249 }
250 #endif
251
252 static void justprintpub(const char* filename) {
253
254         buffer *buf = NULL;
255         sign_key *key = NULL;
256         int keytype;
257         int ret;
258         int err = DROPBEAR_FAILURE;
259
260         buf = buf_new(MAX_PRIVKEY_SIZE);
261         ret = buf_readfile(buf, filename);
262
263         if (ret != DROPBEAR_SUCCESS) {
264                 fprintf(stderr, "Failed reading '%s'\n", filename);
265                 goto out;
266         }
267
268         key = new_sign_key();
269         keytype = DROPBEAR_SIGNKEY_ANY;
270
271         buf_setpos(buf, 0);
272         ret = buf_get_priv_key(buf, key, &keytype);
273         if (ret == DROPBEAR_FAILURE) {
274                 fprintf(stderr, "Bad key in '%s'\n", filename);
275                 goto out;
276         }
277
278         printpubkey(key, keytype);
279
280         err = DROPBEAR_SUCCESS;
281
282 out:
283         buf_burn(buf);
284         buf_free(buf);
285         buf = NULL;
286         sign_key_free(key);
287         key = NULL;
288         exit(err);
289 }
290
291 static void printpubkey(sign_key * key, int keytype) {
292
293         buffer * buf = NULL;
294         unsigned char base64key[MAX_PUBKEY_SIZE*2];
295         unsigned long base64len;
296         int err;
297         const char * typestring = NULL;
298         char *fp = NULL;
299         int len;
300
301         buf = buf_new(MAX_PUBKEY_SIZE);
302         buf_put_pub_key(buf, key, keytype);
303         buf_setpos(buf, 4);
304
305         len = buf->len - buf->pos;
306
307         base64len = sizeof(base64key);
308         err = base64_encode(buf_getptr(buf, len), len, base64key, &base64len);
309
310         if (err != CRYPT_OK) {
311                 fprintf(stderr, "base64 failed");
312         }
313
314         typestring = signkey_name_from_type(keytype, &err);
315
316         fp = sign_key_fingerprint(buf_getptr(buf, len), len);
317
318         printf("Public key portion is:\n%s %s\nFingerprint: %s\n",
319                         typestring, base64key, fp);
320
321         m_free(fp);
322         buf_free(buf);
323 }
324
325 /* Write a buffer to a file specified, failing if the file exists */
326 static void buf_writefile(buffer * buf, const char * filename) {
327
328         int fd;
329         int len;
330
331         fd = open(filename, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
332         if (fd < 0) {
333                 fprintf(stderr, "Couldn't create new file %s\n", filename);
334                 perror("Reason");
335                 buf_burn(buf);
336                 exit(EXIT_FAILURE);
337         }
338
339         /* write the file now */
340         while (buf->pos != buf->len) {
341                 len = write(fd, buf_getptr(buf, buf->len - buf->pos),
342                                 buf->len - buf->pos);
343                 if (errno == EINTR) {
344                         continue;
345                 }
346                 if (len <= 0) {
347                         fprintf(stderr, "Failed writing file '%s'\n",filename);
348                         perror("Reason");
349                         exit(EXIT_FAILURE);
350                 }
351                 buf_incrpos(buf, len);
352         }
353
354         close(fd);
355 }