2 * Dropbear - a SSH2 server
4 * Copyright (c) 2002,2003 Matt Johnston
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
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()
35 * mp_int p (newer versions only)
36 * mp_int q (newer versions only)
55 static void printhelp(char * progname
);
57 #define RSA_SIZE (1024/8) /* 1024 bit */
58 #define DSS_SIZE (1024/8) /* 1024 bit */
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
);
64 /* Print a help message */
65 static void printhelp(char * progname
) {
67 fprintf(stderr
, "Usage: %s -t <type> -f <filename> [-s bits]\n"
69 "-t type Type of key to generate. One of:\n"
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 " (DSS has a fixed size of 1024 bits)\n"
79 "-y Just print the publickey and fingerprint for the\n private key in <filename>.\n"
86 #if defined(DBMULTI_dropbearkey) || !defined(DROPBEAR_MULTI)
87 #if defined(DBMULTI_dropbearkey) && defined(DROPBEAR_MULTI)
88 int dropbearkey_main(int argc
, char ** argv
) {
90 int main(int argc
, char ** argv
) {
97 char * filename
= NULL
;
99 char * typetext
= NULL
;
100 char * sizetext
= NULL
;
102 unsigned int keysize
;
105 /* get the commandline options */
106 for (i
= 1; i
< argc
; i
++) {
107 if (argv
[i
] == NULL
) {
108 continue; /* Whack */
116 if (argv
[i
][0] == '-') {
117 switch (argv
[i
][1]) {
140 fprintf(stderr
, "Unknown argument %s\n", argv
[i
]);
149 fprintf(stderr
, "Must specify a key filename\n");
155 justprintpub(filename
);
159 /* check/parse args */
161 fprintf(stderr
, "Must specify key type\n");
166 if (strlen(typetext
) == 3) {
168 if (strncmp(typetext
, "rsa", 3) == 0) {
169 keytype
= DROPBEAR_SIGNKEY_RSA
;
170 TRACE(("type is rsa"))
174 if (strncmp(typetext
, "dss", 3) == 0) {
175 keytype
= DROPBEAR_SIGNKEY_DSS
;
176 TRACE(("type is dss"))
181 fprintf(stderr
, "Unknown key type '%s'\n", typetext
);
187 if (sscanf(sizetext
, "%u", &bits
) != 1) {
188 fprintf(stderr
, "Bits must be an integer\n");
192 if (keytype
== DROPBEAR_SIGNKEY_DSS
&& bits
!= 1024) {
193 fprintf(stderr
, "DSS keys have a fixed size of 1024 bits\n");
195 } else if (bits
< 512 || bits
> 4096 || (bits
% 8 != 0)) {
196 fprintf(stderr
, "Bits must satisfy 512 <= bits <= 4096, and be a"
203 if (keytype
== DROPBEAR_SIGNKEY_DSS
) {
205 } else if (keytype
== DROPBEAR_SIGNKEY_RSA
) {
208 exit(EXIT_FAILURE
); /* not reached */
213 fprintf(stderr
, "Will output %d bit %s secret key to '%s'\n", keysize
*8,
216 /* don't want the file readable by others */
219 /* now we can generate the key */
220 key
= new_sign_key();
222 fprintf(stderr
, "Generating key, this may take a while...\n");
225 case DROPBEAR_SIGNKEY_RSA
:
226 key
->rsakey
= gen_rsa_priv_key(keysize
); /* 128 bytes = 1024 bit */
230 case DROPBEAR_SIGNKEY_DSS
:
231 key
->dsskey
= gen_dss_priv_key(keysize
); /* 128 bytes = 1024 bit */
235 fprintf(stderr
, "Internal error, bad key type\n");
239 buf
= buf_new(MAX_PRIVKEY_SIZE
);
241 buf_put_priv_key(buf
, key
, keytype
);
243 buf_writefile(buf
, filename
);
248 printpubkey(key
, keytype
);
256 static void justprintpub(const char* filename
) {
259 sign_key
*key
= NULL
;
262 int err
= DROPBEAR_FAILURE
;
264 buf
= buf_new(MAX_PRIVKEY_SIZE
);
265 ret
= buf_readfile(buf
, filename
);
267 if (ret
!= DROPBEAR_SUCCESS
) {
268 fprintf(stderr
, "Failed reading '%s'\n", filename
);
272 key
= new_sign_key();
273 keytype
= DROPBEAR_SIGNKEY_ANY
;
276 ret
= buf_get_priv_key(buf
, key
, &keytype
);
277 if (ret
== DROPBEAR_FAILURE
) {
278 fprintf(stderr
, "Bad key in '%s'\n", filename
);
282 printpubkey(key
, keytype
);
284 err
= DROPBEAR_SUCCESS
;
297 static void printpubkey(sign_key
* key
, int keytype
) {
300 unsigned char base64key
[MAX_PUBKEY_SIZE
*2];
301 unsigned long base64len
;
303 const char * typestring
= NULL
;
306 struct passwd
* pw
= NULL
;
307 char * username
= NULL
;
310 buf
= buf_new(MAX_PUBKEY_SIZE
);
311 buf_put_pub_key(buf
, key
, keytype
);
314 len
= buf
->len
- buf
->pos
;
316 base64len
= sizeof(base64key
);
317 err
= base64_encode(buf_getptr(buf
, len
), len
, base64key
, &base64len
);
319 if (err
!= CRYPT_OK
) {
320 fprintf(stderr
, "base64 failed");
323 typestring
= signkey_name_from_type(keytype
, &err
);
325 fp
= sign_key_fingerprint(buf_getptr(buf
, len
), len
);
327 /* a user@host comment is informative */
329 pw
= getpwuid(getuid());
331 username
= pw
->pw_name
;
334 gethostname(hostname
, sizeof(hostname
));
335 hostname
[sizeof(hostname
)-1] = '\0';
337 printf("Public key portion is:\n%s %s %s@%s\nFingerprint: %s\n",
338 typestring
, base64key
, username
, hostname
, fp
);
344 /* Write a buffer to a file specified, failing if the file exists */
345 static void buf_writefile(buffer
* buf
, const char * filename
) {
350 fd
= open(filename
, O_RDWR
| O_CREAT
| O_EXCL
, S_IRUSR
| S_IWUSR
);
352 fprintf(stderr
, "Couldn't create new file %s\n", filename
);
358 /* write the file now */
359 while (buf
->pos
!= buf
->len
) {
360 len
= write(fd
, buf_getptr(buf
, buf
->len
- buf
->pos
),
361 buf
->len
- buf
->pos
);
362 if (errno
== EINTR
) {
366 fprintf(stderr
, "Failed writing file '%s'\n",filename
);
370 buf_incrpos(buf
, len
);