Mercurial > dropbear
comparison dropbearkey.c @ 910:89555751c489 asm
merge up to 2013.63, improve ASM makefile rules a bit
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Thu, 27 Feb 2014 21:35:58 +0800 |
parents | 220f55d540ae |
children | 6fb4c010c448 |
comparison
equal
deleted
inserted
replaced
909:e4b75744acab | 910:89555751c489 |
---|---|
49 #include "buffer.h" | 49 #include "buffer.h" |
50 #include "dbutil.h" | 50 #include "dbutil.h" |
51 | 51 |
52 #include "genrsa.h" | 52 #include "genrsa.h" |
53 #include "gendss.h" | 53 #include "gendss.h" |
54 #include "ecdsa.h" | |
55 #include "crypto_desc.h" | |
56 #include "dbrandom.h" | |
57 #include "gensignkey.h" | |
54 | 58 |
55 static void printhelp(char * progname); | 59 static void printhelp(char * progname); |
56 | 60 |
57 #define RSA_SIZE (1024/8) /* 1024 bit */ | 61 |
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 printpubkey(sign_key * key, int keytype); |
62 static void justprintpub(const char* filename); | 63 static int printpubfile(const char* filename); |
63 | 64 |
64 /* Print a help message */ | 65 /* Print a help message */ |
65 static void printhelp(char * progname) { | 66 static void printhelp(char * progname) { |
66 | 67 |
67 fprintf(stderr, "Usage: %s -t <type> -f <filename> [-s bits]\n" | 68 fprintf(stderr, "Usage: %s -t <type> -f <filename> [-s bits]\n" |
70 " rsa\n" | 71 " rsa\n" |
71 #endif | 72 #endif |
72 #ifdef DROPBEAR_DSS | 73 #ifdef DROPBEAR_DSS |
73 " dss\n" | 74 " dss\n" |
74 #endif | 75 #endif |
76 #ifdef DROPBEAR_ECDSA | |
77 " ecdsa\n" | |
78 #endif | |
75 "-f filename Use filename for the secret key\n" | 79 "-f filename Use filename for the secret key\n" |
76 "-s bits Key size in bits, should be a multiple of 8 (optional)\n" | 80 "-s bits Key size in bits, should be a multiple of 8 (optional)\n" |
77 " (DSS has a fixed size of 1024 bits)\n" | 81 #ifdef DROPBEAR_DSS |
82 " DSS has a fixed size of 1024 bits\n" | |
83 #endif | |
84 #ifdef DROPBEAR_ECDSA | |
85 " ECDSA has sizes " | |
86 #ifdef DROPBEAR_ECC_256 | |
87 "256 " | |
88 #endif | |
89 #ifdef DROPBEAR_ECC_384 | |
90 "384 " | |
91 #endif | |
92 #ifdef DROPBEAR_ECC_521 | |
93 "521 " | |
94 #endif | |
95 "\n" | |
96 #endif | |
78 "-y Just print the publickey and fingerprint for the\n private key in <filename>.\n" | 97 "-y Just print the publickey and fingerprint for the\n private key in <filename>.\n" |
79 #ifdef DEBUG_TRACE | 98 #ifdef DEBUG_TRACE |
80 "-v verbose\n" | 99 "-v verbose\n" |
81 #endif | 100 #endif |
82 ,progname); | 101 ,progname); |
102 } | |
103 | |
104 /* fails fatally */ | |
105 static void check_signkey_bits(enum signkey_type type, int bits) | |
106 { | |
107 switch (type) { | |
108 #ifdef DROPBEAR_RSA | |
109 case DROPBEAR_SIGNKEY_RSA: | |
110 if (bits < 512 || bits > 4096 || (bits % 8 != 0)) { | |
111 dropbear_exit("Bits must satisfy 512 <= bits <= 4096, and be a" | |
112 " multiple of 8\n"); | |
113 } | |
114 break; | |
115 #endif | |
116 #ifdef DROPEAR_DSS | |
117 case DROPBEAR_SIGNKEY_DSS: | |
118 if (bits != 1024) { | |
119 dropbear_exit("DSS keys have a fixed size of 1024 bits\n"); | |
120 exit(EXIT_FAILURE); | |
121 } | |
122 #endif | |
123 default: | |
124 (void)0; /* quiet, compiler. ecdsa handles checks itself */ | |
125 } | |
83 } | 126 } |
84 | 127 |
85 #if defined(DBMULTI_dropbearkey) || !defined(DROPBEAR_MULTI) | 128 #if defined(DBMULTI_dropbearkey) || !defined(DROPBEAR_MULTI) |
86 #if defined(DBMULTI_dropbearkey) && defined(DROPBEAR_MULTI) | 129 #if defined(DBMULTI_dropbearkey) && defined(DROPBEAR_MULTI) |
87 int dropbearkey_main(int argc, char ** argv) { | 130 int dropbearkey_main(int argc, char ** argv) { |
89 int main(int argc, char ** argv) { | 132 int main(int argc, char ** argv) { |
90 #endif | 133 #endif |
91 | 134 |
92 int i; | 135 int i; |
93 char ** next = 0; | 136 char ** next = 0; |
94 sign_key *key = NULL; | |
95 buffer *buf = NULL; | |
96 char * filename = NULL; | 137 char * filename = NULL; |
97 int keytype = -1; | 138 enum signkey_type keytype = DROPBEAR_SIGNKEY_NONE; |
98 char * typetext = NULL; | 139 char * typetext = NULL; |
99 char * sizetext = NULL; | 140 char * sizetext = NULL; |
100 unsigned int bits; | 141 unsigned int bits = 0; |
101 unsigned int keysize; | |
102 int printpub = 0; | 142 int printpub = 0; |
143 | |
144 crypto_init(); | |
145 seedrandom(); | |
103 | 146 |
104 /* get the commandline options */ | 147 /* get the commandline options */ |
105 for (i = 1; i < argc; i++) { | 148 for (i = 1; i < argc; i++) { |
106 if (argv[i] == NULL) { | 149 if (argv[i] == NULL) { |
107 continue; /* Whack */ | 150 continue; /* Whack */ |
149 printhelp(argv[0]); | 192 printhelp(argv[0]); |
150 exit(EXIT_FAILURE); | 193 exit(EXIT_FAILURE); |
151 } | 194 } |
152 | 195 |
153 if (printpub) { | 196 if (printpub) { |
154 justprintpub(filename); | 197 int ret = printpubfile(filename); |
155 /* Not reached */ | 198 exit(ret); |
156 } | 199 } |
157 | 200 |
158 /* check/parse args */ | 201 /* check/parse args */ |
159 if (!typetext) { | 202 if (!typetext) { |
160 fprintf(stderr, "Must specify key type\n"); | 203 fprintf(stderr, "Must specify key type\n"); |
161 printhelp(argv[0]); | 204 printhelp(argv[0]); |
162 exit(EXIT_FAILURE); | 205 exit(EXIT_FAILURE); |
163 } | 206 } |
164 | 207 |
165 if (strlen(typetext) == 3) { | |
166 #ifdef DROPBEAR_RSA | 208 #ifdef DROPBEAR_RSA |
167 if (strncmp(typetext, "rsa", 3) == 0) { | 209 if (strcmp(typetext, "rsa") == 0) |
168 keytype = DROPBEAR_SIGNKEY_RSA; | 210 { |
169 TRACE(("type is rsa")) | 211 keytype = DROPBEAR_SIGNKEY_RSA; |
170 } | 212 } |
171 #endif | 213 #endif |
172 #ifdef DROPBEAR_DSS | 214 #ifdef DROPBEAR_DSS |
173 if (strncmp(typetext, "dss", 3) == 0) { | 215 if (strcmp(typetext, "dss") == 0) |
174 keytype = DROPBEAR_SIGNKEY_DSS; | 216 { |
175 TRACE(("type is dss")) | 217 keytype = DROPBEAR_SIGNKEY_DSS; |
176 } | 218 } |
177 #endif | 219 #endif |
178 } | 220 #ifdef DROPBEAR_ECDSA |
179 if (keytype == -1) { | 221 if (strcmp(typetext, "ecdsa") == 0) |
222 { | |
223 keytype = DROPBEAR_SIGNKEY_ECDSA_KEYGEN; | |
224 } | |
225 #endif | |
226 | |
227 if (keytype == DROPBEAR_SIGNKEY_NONE) { | |
180 fprintf(stderr, "Unknown key type '%s'\n", typetext); | 228 fprintf(stderr, "Unknown key type '%s'\n", typetext); |
181 printhelp(argv[0]); | 229 printhelp(argv[0]); |
182 exit(EXIT_FAILURE); | 230 exit(EXIT_FAILURE); |
183 } | 231 } |
184 | 232 |
186 if (sscanf(sizetext, "%u", &bits) != 1) { | 234 if (sscanf(sizetext, "%u", &bits) != 1) { |
187 fprintf(stderr, "Bits must be an integer\n"); | 235 fprintf(stderr, "Bits must be an integer\n"); |
188 exit(EXIT_FAILURE); | 236 exit(EXIT_FAILURE); |
189 } | 237 } |
190 | 238 |
191 if (keytype == DROPBEAR_SIGNKEY_DSS && bits != 1024) { | 239 check_signkey_bits(keytype, bits);; |
192 fprintf(stderr, "DSS keys have a fixed size of 1024 bits\n"); | 240 } |
193 exit(EXIT_FAILURE); | 241 |
194 } else if (bits < 512 || bits > 4096 || (bits % 8 != 0)) { | |
195 fprintf(stderr, "Bits must satisfy 512 <= bits <= 4096, and be a" | |
196 " multiple of 8\n"); | |
197 exit(EXIT_FAILURE); | |
198 } | |
199 | |
200 keysize = bits / 8; | |
201 } else { | |
202 if (keytype == DROPBEAR_SIGNKEY_DSS) { | |
203 keysize = DSS_SIZE; | |
204 } else if (keytype == DROPBEAR_SIGNKEY_RSA) { | |
205 keysize = RSA_SIZE; | |
206 } else { | |
207 exit(EXIT_FAILURE); /* not reached */ | |
208 } | |
209 } | |
210 | |
211 | |
212 fprintf(stderr, "Will output %d bit %s secret key to '%s'\n", keysize*8, | |
213 typetext, filename); | |
214 | |
215 /* don't want the file readable by others */ | |
216 umask(077); | |
217 | |
218 /* now we can generate the key */ | |
219 key = new_sign_key(); | |
220 | |
221 fprintf(stderr, "Generating key, this may take a while...\n"); | 242 fprintf(stderr, "Generating key, this may take a while...\n"); |
222 switch(keytype) { | 243 if (signkey_generate(keytype, bits, filename) == DROPBEAR_FAILURE) |
223 #ifdef DROPBEAR_RSA | 244 { |
224 case DROPBEAR_SIGNKEY_RSA: | 245 dropbear_exit("Failed to generate key.\n"); |
225 key->rsakey = gen_rsa_priv_key(keysize); /* 128 bytes = 1024 bit */ | 246 } |
226 break; | 247 |
227 #endif | 248 printpubfile(filename); |
228 #ifdef DROPBEAR_DSS | |
229 case DROPBEAR_SIGNKEY_DSS: | |
230 key->dsskey = gen_dss_priv_key(keysize); /* 128 bytes = 1024 bit */ | |
231 break; | |
232 #endif | |
233 default: | |
234 fprintf(stderr, "Internal error, bad key type\n"); | |
235 exit(EXIT_FAILURE); | |
236 } | |
237 | |
238 buf = buf_new(MAX_PRIVKEY_SIZE); | |
239 | |
240 buf_put_priv_key(buf, key, keytype); | |
241 buf_setpos(buf, 0); | |
242 buf_writefile(buf, filename); | |
243 | |
244 buf_burn(buf); | |
245 buf_free(buf); | |
246 | |
247 printpubkey(key, keytype); | |
248 | |
249 sign_key_free(key); | |
250 | 249 |
251 return EXIT_SUCCESS; | 250 return EXIT_SUCCESS; |
252 } | 251 } |
253 #endif | 252 #endif |
254 | 253 |
255 static void justprintpub(const char* filename) { | 254 static int printpubfile(const char* filename) { |
256 | 255 |
257 buffer *buf = NULL; | 256 buffer *buf = NULL; |
258 sign_key *key = NULL; | 257 sign_key *key = NULL; |
259 int keytype; | 258 enum signkey_type keytype; |
260 int ret; | 259 int ret; |
261 int err = DROPBEAR_FAILURE; | 260 int err = DROPBEAR_FAILURE; |
262 | 261 |
263 buf = buf_new(MAX_PRIVKEY_SIZE); | 262 buf = buf_new(MAX_PRIVKEY_SIZE); |
264 ret = buf_readfile(buf, filename); | 263 ret = buf_readfile(buf, filename); |
288 buf = NULL; | 287 buf = NULL; |
289 if (key) { | 288 if (key) { |
290 sign_key_free(key); | 289 sign_key_free(key); |
291 key = NULL; | 290 key = NULL; |
292 } | 291 } |
293 exit(err); | 292 return err; |
294 } | 293 } |
295 | 294 |
296 static void printpubkey(sign_key * key, int keytype) { | 295 static void printpubkey(sign_key * key, int keytype) { |
297 | 296 |
298 buffer * buf = NULL; | 297 buffer * buf = NULL; |
317 | 316 |
318 if (err != CRYPT_OK) { | 317 if (err != CRYPT_OK) { |
319 fprintf(stderr, "base64 failed"); | 318 fprintf(stderr, "base64 failed"); |
320 } | 319 } |
321 | 320 |
322 typestring = signkey_name_from_type(keytype, &err); | 321 typestring = signkey_name_from_type(keytype, NULL); |
323 | 322 |
324 fp = sign_key_fingerprint(buf_getptr(buf, len), len); | 323 fp = sign_key_fingerprint(buf_getptr(buf, len), len); |
325 | 324 |
326 /* a user@host comment is informative */ | 325 /* a user@host comment is informative */ |
327 username = ""; | 326 username = ""; |
337 typestring, base64key, username, hostname, fp); | 336 typestring, base64key, username, hostname, fp); |
338 | 337 |
339 m_free(fp); | 338 m_free(fp); |
340 buf_free(buf); | 339 buf_free(buf); |
341 } | 340 } |
342 | |
343 /* Write a buffer to a file specified, failing if the file exists */ | |
344 static void buf_writefile(buffer * buf, const char * filename) { | |
345 | |
346 int fd; | |
347 int len; | |
348 | |
349 fd = open(filename, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); | |
350 if (fd < 0) { | |
351 fprintf(stderr, "Couldn't create new file %s\n", filename); | |
352 perror("Reason"); | |
353 buf_burn(buf); | |
354 exit(EXIT_FAILURE); | |
355 } | |
356 | |
357 /* write the file now */ | |
358 while (buf->pos != buf->len) { | |
359 len = write(fd, buf_getptr(buf, buf->len - buf->pos), | |
360 buf->len - buf->pos); | |
361 if (errno == EINTR) { | |
362 continue; | |
363 } | |
364 if (len <= 0) { | |
365 fprintf(stderr, "Failed writing file '%s'\n",filename); | |
366 perror("Reason"); | |
367 exit(EXIT_FAILURE); | |
368 } | |
369 buf_incrpos(buf, len); | |
370 } | |
371 | |
372 close(fd); | |
373 } |