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 }