6d355bc4d04edb9ca55b43f579fab9a450fabe26
[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 "runopts.h"
49 #include "signkey.h"
50 #include "buffer.h"
51 #include "util.h"
52
53 #include "genrsa.h"
54 #include "gendss.h"
55
56 static void printhelp(char * progname);
57
58 #define BUF_SIZE 2000
59
60 #define RSA_SIZE (1024/8) /* 1024 bit */
61 #define DSS_SIZE (1024/8) /* 1024 bit */
62
63 static void buf_writefile(buffer * buf, const char * filename);
64
65 /* Print a help message */
66 static void printhelp(char * progname) {
67
68         fprintf(stderr, "Usage: %s -t <type> -f <filename> [-s bits]\n"
69                                         "Options are:\n"
70                                         "-t type           Type of key to generate. One of:\n"
71 #ifdef DROPBEAR_RSA
72                                         "                  rsa\n"
73 #endif
74 #ifdef DROPBEAR_DSS
75                                         "                  dss\n"
76 #endif
77                                         "-f filename       Use filename for the secret key\n"
78                                         "-s bits           Key size in bits, should be "
79                                         "multiple of 8 (optional)\n",
80                                         progname);
81 }
82
83 int main(int argc, char ** argv) {
84
85         int i;
86         char ** next = 0;
87         sign_key *key;
88         buffer *buf;
89         char * filename = NULL;
90         int keytype = -1;
91         char * typetext = NULL;
92         char * sizetext = NULL;
93         unsigned int bits;
94         unsigned int keysize;
95
96         /* get the commandline options */
97         for (i = 1; i < argc; i++) {
98                 if (next) {
99                         *next = argv[i];
100                         if (*next == NULL) {
101                                 fprintf(stderr, "Invalid null argument");
102                         }
103                         next = 0x00;
104                         continue;
105                 }
106
107                 if (argv[i][0] == '-') {
108                         switch (argv[i][1]) {
109                                 case 'f':
110                                         next = &filename;
111                                         break;
112                                 case 't':
113                                         next = &typetext;
114                                         break;
115                                 case 's':
116                                         next = &sizetext;
117                                         break;
118                                 case 'h':
119                                         printhelp(argv[0]);
120                                         exit(EXIT_SUCCESS);
121                                         break;
122                                 default:
123                                         fprintf(stderr, "Unknown argument %s\n", argv[i]);
124                                         printhelp(argv[0]);
125                                         exit(EXIT_FAILURE);
126                                         break;
127                         }
128                 }
129         }
130
131         /* check/parse args */
132         if (!typetext) {
133                 fprintf(stderr, "Must specify file type, one of:\n"
134 #ifdef DROPBEAR_RSA
135                                 "rsa\n"
136 #endif
137 #ifdef DROPBEAR_DSS
138                                 "dss\n"
139 #endif
140                                 "\n"
141                            );
142                 printhelp(argv[0]);
143                 exit(EXIT_FAILURE);
144         }
145
146         if (strlen(typetext) == 3) {
147 #ifdef DROPBEAR_RSA
148                 if (strncmp(typetext, "rsa", 3) == 0) {
149                         keytype = DROPBEAR_SIGNKEY_RSA;
150                         TRACE(("type is rsa"));
151                 }
152 #endif
153 #ifdef DROPBEAR_DSS
154                 if (strncmp(typetext, "dss", 3) == 0) {
155                         keytype = DROPBEAR_SIGNKEY_DSS;
156                         TRACE(("type is dss"));
157                 }
158 #endif
159         }
160         if (keytype == -1) {
161                 fprintf(stderr, "Unknown key type '%s'\n", typetext);
162                 printhelp(argv[0]);
163                 exit(EXIT_FAILURE);
164         }
165
166         if (sizetext) {
167                 if (sscanf(sizetext, "%u", &bits) != 1) {
168                         fprintf(stderr, "Bits must be an integer\n");
169                         exit(EXIT_FAILURE);
170                 }
171         
172                 if (bits < 512 || bits > 4096 || (bits % 8 != 0)) {
173                         fprintf(stderr, "Bits must satisfy 512 <= bits <= 4096, and be a"
174                                         " multiple of 8\n");
175                         exit(EXIT_FAILURE);
176                 }
177
178                 keysize = bits / 8;
179         } else {
180                 if (keytype == DROPBEAR_SIGNKEY_DSS) {
181                         keysize = DSS_SIZE;
182                 } else if (keytype == DROPBEAR_SIGNKEY_RSA) {
183                         keysize = RSA_SIZE;
184                 } else {
185                         exit(EXIT_FAILURE); /* not reached */
186                 }
187         }
188
189         if (!filename) {
190                 fprintf(stderr, "Must specify a key filename\n");
191                 printhelp(argv[0]);
192                 exit(EXIT_FAILURE);
193         }
194
195         fprintf(stderr, "Will output %d bit %s secret key to '%s'\n", keysize*8,
196                         typetext, filename);
197
198         /* don't want the file readable by others */
199         umask(077);
200
201         /* now we can generate the key */
202         key = new_sign_key();
203         
204         fprintf(stderr, "Generating key, this may take a while...\n");
205         switch(keytype) {
206 #ifdef DROPBEAR_RSA
207                 case DROPBEAR_SIGNKEY_RSA:
208                         key->rsakey = gen_rsa_priv_key(keysize); /* 128 bytes = 1024 bit */
209                         break;
210 #endif
211 #ifdef DROPBEAR_DSS
212                 case DROPBEAR_SIGNKEY_DSS:
213                         key->dsskey = gen_dss_priv_key(keysize); /* 128 bytes = 1024 bit */
214                         break;
215 #endif
216                 default:
217                         fprintf(stderr, "Internal error, bad key type\n");
218                         exit(EXIT_FAILURE);
219         }
220
221         buf = buf_new(BUF_SIZE); 
222
223         buf_put_priv_key(buf, key, keytype);
224         buf_setpos(buf, 0);
225         buf_writefile(buf, filename);
226
227         buf_burn(buf);
228         buf_free(buf);
229         sign_key_free(key);
230
231         fprintf(stderr, "Done.\n");
232
233         return EXIT_SUCCESS;
234 }
235
236 /* Write a buffer to a file specified, failing if the file exists */
237 static void buf_writefile(buffer * buf, const char * filename) {
238
239         int fd;
240         int len;
241
242         fd = open(filename, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
243         if (fd < 0) {
244                 fprintf(stderr, "Couldn't create new file %s\n", filename);
245                 perror("Reason");
246                 buf_burn(buf);
247                 exit(EXIT_FAILURE);
248         }
249
250         /* write the file now */
251         while (buf->pos != buf->len) {
252                 len = write(fd, buf_getptr(buf, buf->len - buf->pos),
253                                 buf->len - buf->pos);
254                 if (errno == EINTR) {
255                         continue;
256                 }
257                 if (len <= 0) {
258                         fprintf(stderr, "Failed writing file '%s'\n",filename);
259                         perror("Reason");
260                         exit(EXIT_FAILURE);
261                 }
262                 buf_incrpos(buf, len);
263         }
264
265         close(fd);
266 }