dropbear: update to 2015.67
[tomato.git] / release / src-rt-6.x.4708 / router / dropbear / dropbearkey.c
blob7eb2f3f01fc77433b75e3a10e505c58436031912
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:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
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. */
25 /* The format of the keyfiles is basically a raw dump of the buffer. Data types
26 * are specified in the transport rfc 4253 - 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()
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)
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
47 #include "includes.h"
48 #include "signkey.h"
49 #include "buffer.h"
50 #include "dbutil.h"
52 #include "genrsa.h"
53 #include "gendss.h"
54 #include "ecdsa.h"
55 #include "crypto_desc.h"
56 #include "dbrandom.h"
57 #include "gensignkey.h"
59 static void printhelp(char * progname);
62 static void printpubkey(sign_key * key, int keytype);
63 static int printpubfile(const char* filename);
65 /* Print a help message */
66 static void printhelp(char * progname) {
68 fprintf(stderr, "Usage: %s -t <type> -f <filename> [-s bits]\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 #ifdef DROPBEAR_ECDSA
77 " ecdsa\n"
78 #endif
79 "-f filename Use filename for the secret key.\n"
80 " ~/.ssh/id_dropbear is recommended for client keys.\n"
81 "-s bits Key size in bits, should be a multiple of 8 (optional)\n"
82 #ifdef DROPBEAR_DSS
83 " DSS has a fixed size of 1024 bits\n"
84 #endif
85 #ifdef DROPBEAR_ECDSA
86 " ECDSA has sizes "
87 #ifdef DROPBEAR_ECC_256
88 "256 "
89 #endif
90 #ifdef DROPBEAR_ECC_384
91 "384 "
92 #endif
93 #ifdef DROPBEAR_ECC_521
94 "521 "
95 #endif
96 "\n"
97 #endif
98 "-y Just print the publickey and fingerprint for the\n private key in <filename>.\n"
99 #ifdef DEBUG_TRACE
100 "-v verbose\n"
101 #endif
102 ,progname);
105 /* fails fatally */
106 static void check_signkey_bits(enum signkey_type type, int bits)
108 switch (type) {
109 #ifdef DROPBEAR_RSA
110 case DROPBEAR_SIGNKEY_RSA:
111 if (bits < 512 || bits > 4096 || (bits % 8 != 0)) {
112 dropbear_exit("Bits must satisfy 512 <= bits <= 4096, and be a"
113 " multiple of 8\n");
115 break;
116 #endif
117 #ifdef DROPEAR_DSS
118 case DROPBEAR_SIGNKEY_DSS:
119 if (bits != 1024) {
120 dropbear_exit("DSS keys have a fixed size of 1024 bits\n");
121 exit(EXIT_FAILURE);
123 #endif
124 default:
125 (void)0; /* quiet, compiler. ecdsa handles checks itself */
129 #if defined(DBMULTI_dropbearkey) || !defined(DROPBEAR_MULTI)
130 #if defined(DBMULTI_dropbearkey) && defined(DROPBEAR_MULTI)
131 int dropbearkey_main(int argc, char ** argv) {
132 #else
133 int main(int argc, char ** argv) {
134 #endif
136 int i;
137 char ** next = 0;
138 char * filename = NULL;
139 enum signkey_type keytype = DROPBEAR_SIGNKEY_NONE;
140 char * typetext = NULL;
141 char * sizetext = NULL;
142 unsigned int bits = 0;
143 int printpub = 0;
145 crypto_init();
146 seedrandom();
148 /* get the commandline options */
149 for (i = 1; i < argc; i++) {
150 if (argv[i] == NULL) {
151 continue; /* Whack */
153 if (next) {
154 *next = argv[i];
155 next = NULL;
156 continue;
159 if (argv[i][0] == '-') {
160 switch (argv[i][1]) {
161 case 'f':
162 next = &filename;
163 break;
164 case 't':
165 next = &typetext;
166 break;
167 case 's':
168 next = &sizetext;
169 break;
170 case 'y':
171 printpub = 1;
172 break;
173 case 'h':
174 printhelp(argv[0]);
175 exit(EXIT_SUCCESS);
176 break;
177 #ifdef DEBUG_TRACE
178 case 'v':
179 debug_trace = 1;
180 break;
181 #endif
182 default:
183 fprintf(stderr, "Unknown argument %s\n", argv[i]);
184 printhelp(argv[0]);
185 exit(EXIT_FAILURE);
186 break;
191 if (!filename) {
192 fprintf(stderr, "Must specify a key filename\n");
193 printhelp(argv[0]);
194 exit(EXIT_FAILURE);
197 if (printpub) {
198 int ret = printpubfile(filename);
199 exit(ret);
202 /* check/parse args */
203 if (!typetext) {
204 fprintf(stderr, "Must specify key type\n");
205 printhelp(argv[0]);
206 exit(EXIT_FAILURE);
209 #ifdef DROPBEAR_RSA
210 if (strcmp(typetext, "rsa") == 0)
212 keytype = DROPBEAR_SIGNKEY_RSA;
214 #endif
215 #ifdef DROPBEAR_DSS
216 if (strcmp(typetext, "dss") == 0)
218 keytype = DROPBEAR_SIGNKEY_DSS;
220 #endif
221 #ifdef DROPBEAR_ECDSA
222 if (strcmp(typetext, "ecdsa") == 0)
224 keytype = DROPBEAR_SIGNKEY_ECDSA_KEYGEN;
226 #endif
228 if (keytype == DROPBEAR_SIGNKEY_NONE) {
229 fprintf(stderr, "Unknown key type '%s'\n", typetext);
230 printhelp(argv[0]);
231 exit(EXIT_FAILURE);
234 if (sizetext) {
235 if (sscanf(sizetext, "%u", &bits) != 1) {
236 fprintf(stderr, "Bits must be an integer\n");
237 exit(EXIT_FAILURE);
240 check_signkey_bits(keytype, bits);;
243 fprintf(stderr, "Generating key, this may take a while...\n");
244 if (signkey_generate(keytype, bits, filename) == DROPBEAR_FAILURE)
246 dropbear_exit("Failed to generate key.\n");
249 printpubfile(filename);
251 return EXIT_SUCCESS;
253 #endif
255 static int printpubfile(const char* filename) {
257 buffer *buf = NULL;
258 sign_key *key = NULL;
259 enum signkey_type keytype;
260 int ret;
261 int err = DROPBEAR_FAILURE;
263 buf = buf_new(MAX_PRIVKEY_SIZE);
264 ret = buf_readfile(buf, filename);
266 if (ret != DROPBEAR_SUCCESS) {
267 fprintf(stderr, "Failed reading '%s'\n", filename);
268 goto out;
271 key = new_sign_key();
272 keytype = DROPBEAR_SIGNKEY_ANY;
274 buf_setpos(buf, 0);
275 ret = buf_get_priv_key(buf, key, &keytype);
276 if (ret == DROPBEAR_FAILURE) {
277 fprintf(stderr, "Bad key in '%s'\n", filename);
278 goto out;
281 printpubkey(key, keytype);
283 err = DROPBEAR_SUCCESS;
285 out:
286 buf_burn(buf);
287 buf_free(buf);
288 buf = NULL;
289 if (key) {
290 sign_key_free(key);
291 key = NULL;
293 return err;
296 static void printpubkey(sign_key * key, int keytype) {
298 buffer * buf = NULL;
299 unsigned char base64key[MAX_PUBKEY_SIZE*2];
300 unsigned long base64len;
301 int err;
302 const char * typestring = NULL;
303 char *fp = NULL;
304 int len;
305 struct passwd * pw = NULL;
306 char * username = NULL;
307 char hostname[100];
309 buf = buf_new(MAX_PUBKEY_SIZE);
310 buf_put_pub_key(buf, key, keytype);
311 buf_setpos(buf, 4);
313 len = buf->len - buf->pos;
315 base64len = sizeof(base64key);
316 err = base64_encode(buf_getptr(buf, len), len, base64key, &base64len);
318 if (err != CRYPT_OK) {
319 fprintf(stderr, "base64 failed");
322 typestring = signkey_name_from_type(keytype, NULL);
324 fp = sign_key_fingerprint(buf_getptr(buf, len), len);
326 /* a user@host comment is informative */
327 username = "";
328 pw = getpwuid(getuid());
329 if (pw) {
330 username = pw->pw_name;
333 gethostname(hostname, sizeof(hostname));
334 hostname[sizeof(hostname)-1] = '\0';
336 printf("Public key portion is:\n%s %s %s@%s\nFingerprint: %s\n",
337 typestring, base64key, username, hostname, fp);
339 m_free(fp);
340 buf_free(buf);