comparison keyimport.c @ 1306:34e6127ef02e

merge fixes from PuTTY import.c toint() from misc.c (revids are from hggit conversion) changeset: 4620:60a336a6c85c user: Simon Tatham <[email protected]> date: Thu Feb 25 20:26:33 2016 +0000 files: import.c description: Fix potential segfaults in reading OpenSSH's ASN.1 key format. The length coming back from ber_read_id_len might have overflowed, so treat it as potentially negative. Also, while I'm here, accumulate it inside ber_read_id_len as an unsigned, so as to avoid undefined behaviour on integer overflow, and toint() it before return. Thanks to Hanno Böck for spotting this, with the aid of AFL. (cherry picked from commit 5b7833cd474a24ec098654dcba8cb9509f3bf2c1) Conflicts: import.c (cherry-picker's note: resolving the conflict involved removing an entire section of the original commit which fixed ECDSA code not present on this branch) changeset: 4619:9c6c638d98d8 user: Simon Tatham <[email protected]> date: Sun Jul 14 10:45:54 2013 +0000 files: import.c ssh.c sshdss.c sshpubk.c sshrsa.c description: Tighten up a lot of casts from unsigned to int which are read by one of the GET_32BIT macros and then used as length fields. Missing bounds checks against zero have been added, and also I've introduced a helper function toint() which casts from unsigned to int in such a way as to avoid C undefined behaviour, since I'm not sure I trust compilers any more to do the obviously sensible thing. [originally from svn r9918] changeset: 4618:3957829f24d3 user: Simon Tatham <[email protected]> date: Mon Jul 08 22:36:04 2013 +0000 files: import.c sshdss.c sshrsa.c description: Add an assortment of extra safety checks. [originally from svn r9896] changeset: 4617:2cddee0bce12 user: Jacob Nevins <[email protected]> date: Wed Dec 07 00:24:45 2005 +0000 files: import.c description: Institutional failure to memset() things pointed at rather than pointers. Things should now be zeroed and memory not leaked. Spotted by Brant Thomsen. [originally from svn r6476] changeset: 4616:24ac78a9c71d user: Simon Tatham <[email protected]> date: Wed Feb 11 13:58:27 2004 +0000 files: import.c description: Jacob's last-minute testing found a couple of trivial bugs in import.c, and my attempts to reproduce them in cmdgen found another one there :-) [originally from svn r3847] changeset: 4615:088d39a73db0 user: Simon Tatham <[email protected]> date: Thu Jan 22 18:52:49 2004 +0000 files: import.c description: Placate some gcc warnings. [originally from svn r3761] changeset: 4614:e4288bad4d93 parent: 1758:108b8924593d user: Simon Tatham <[email protected]> date: Fri Oct 03 21:21:23 2003 +0000 files: import.c description: My ASN.1 decoder returned wrong IDs for anything above 0x1E! Good job it's never had to yet. Ahem. [originally from svn r3479]
author Matt Johnston <matt@ucc.asn.au>
date Tue, 12 Jul 2016 23:00:01 +0800
parents 2bb4c662d1c2
children ad9c40aca3bc
comparison
equal deleted inserted replaced
1305:6914eedb1072 1306:34e6127ef02e
45 (cp)[2] = (unsigned char)((value) >> 8); \ 45 (cp)[2] = (unsigned char)((value) >> 8); \
46 (cp)[1] = (unsigned char)((value) >> 16); \ 46 (cp)[1] = (unsigned char)((value) >> 16); \
47 (cp)[0] = (unsigned char)((value) >> 24); } while (0) 47 (cp)[0] = (unsigned char)((value) >> 24); } while (0)
48 48
49 #define GET_32BIT(cp) \ 49 #define GET_32BIT(cp) \
50 (((unsigned long)(unsigned char)(cp)[0] << 24) | \ 50 (((unsigned long)(unsigned char)(cp)[0] << 24) | \
51 ((unsigned long)(unsigned char)(cp)[1] << 16) | \ 51 ((unsigned long)(unsigned char)(cp)[1] << 16) | \
52 ((unsigned long)(unsigned char)(cp)[2] << 8) | \ 52 ((unsigned long)(unsigned char)(cp)[2] << 8) | \
53 ((unsigned long)(unsigned char)(cp)[3])) 53 ((unsigned long)(unsigned char)(cp)[3]))
54 54
55 static int openssh_encrypted(const char *filename); 55 static int openssh_encrypted(const char *filename);
56 static sign_key *openssh_read(const char *filename, char *passphrase); 56 static sign_key *openssh_read(const char *filename, char *passphrase);
57 static int openssh_write(const char *filename, sign_key *key, 57 static int openssh_write(const char *filename, sign_key *key,
58 char *passphrase); 58 char *passphrase);
59 59
60 static int dropbear_write(const char*filename, sign_key * key); 60 static int dropbear_write(const char*filename, sign_key * key);
61 static sign_key *dropbear_read(const char* filename); 61 static sign_key *dropbear_read(const char* filename);
62
63 static int toint(unsigned u);
62 64
63 #if 0 65 #if 0
64 static int sshcom_encrypted(const char *filename, char **comment); 66 static int sshcom_encrypted(const char *filename, char **comment);
65 static struct ssh2_userkey *sshcom_read(const char *filename, char *passphrase); 67 static struct ssh2_userkey *sshcom_read(const char *filename, char *passphrase);
66 static int sshcom_write(const char *filename, struct ssh2_userkey *key, 68 static int sshcom_write(const char *filename, struct ssh2_userkey *key,
67 char *passphrase); 69 char *passphrase);
68 #endif 70 #endif
69 71
70 int import_encrypted(const char* filename, int filetype) { 72 int import_encrypted(const char* filename, int filetype) {
71 73
72 if (filetype == KEYFILE_OPENSSH) { 74 if (filetype == KEYFILE_OPENSSH) {
73 return openssh_encrypted(filename); 75 return openssh_encrypted(filename);
74 #if 0 76 #if 0
75 } else if (filetype == KEYFILE_SSHCOM) { 77 } else if (filetype == KEYFILE_SSHCOM) {
76 return sshcom_encrypted(filename, NULL); 78 return sshcom_encrypted(filename, NULL);
77 #endif 79 #endif
78 } 80 }
79 return 0; 81 return 0;
80 } 82 }
81 83
82 sign_key *import_read(const char *filename, char *passphrase, int filetype) { 84 sign_key *import_read(const char *filename, char *passphrase, int filetype) {
83 85
84 if (filetype == KEYFILE_OPENSSH) { 86 if (filetype == KEYFILE_OPENSSH) {
85 return openssh_read(filename, passphrase); 87 return openssh_read(filename, passphrase);
86 } else if (filetype == KEYFILE_DROPBEAR) { 88 } else if (filetype == KEYFILE_DROPBEAR) {
87 return dropbear_read(filename); 89 return dropbear_read(filename);
88 #if 0 90 #if 0
89 } else if (filetype == KEYFILE_SSHCOM) { 91 } else if (filetype == KEYFILE_SSHCOM) {
90 return sshcom_read(filename, passphrase); 92 return sshcom_read(filename, passphrase);
91 #endif 93 #endif
92 } 94 }
93 return NULL; 95 return NULL;
94 } 96 }
95 97
96 int import_write(const char *filename, sign_key *key, char *passphrase, 98 int import_write(const char *filename, sign_key *key, char *passphrase,
97 int filetype) { 99 int filetype) {
98 100
99 if (filetype == KEYFILE_OPENSSH) { 101 if (filetype == KEYFILE_OPENSSH) {
100 return openssh_write(filename, key, passphrase); 102 return openssh_write(filename, key, passphrase);
101 } else if (filetype == KEYFILE_DROPBEAR) { 103 } else if (filetype == KEYFILE_DROPBEAR) {
102 return dropbear_write(filename, key); 104 return dropbear_write(filename, key);
103 #if 0 105 #if 0
104 } else if (filetype == KEYFILE_SSHCOM) { 106 } else if (filetype == KEYFILE_SSHCOM) {
105 return sshcom_write(filename, key, passphrase); 107 return sshcom_write(filename, key, passphrase);
106 #endif 108 #endif
107 } 109 }
108 return 0; 110 return 0;
109 } 111 }
110 112
111 static sign_key *dropbear_read(const char* filename) { 113 static sign_key *dropbear_read(const char* filename) {
112 114
113 buffer * buf = NULL; 115 buffer * buf = NULL;
181 183
182 /* ---------------------------------------------------------------------- 184 /* ----------------------------------------------------------------------
183 * Helper routines. (The base64 ones are defined in sshpubk.c.) 185 * Helper routines. (The base64 ones are defined in sshpubk.c.)
184 */ 186 */
185 187
186 #define isbase64(c) ( ((c) >= 'A' && (c) <= 'Z') || \ 188 #define isbase64(c) ( ((c) >= 'A' && (c) <= 'Z') || \
187 ((c) >= 'a' && (c) <= 'z') || \ 189 ((c) >= 'a' && (c) <= 'z') || \
188 ((c) >= '0' && (c) <= '9') || \ 190 ((c) >= '0' && (c) <= '9') || \
189 (c) == '+' || (c) == '/' || (c) == '=' \ 191 (c) == '+' || (c) == '/' || (c) == '=' \
190 ) 192 )
191 193
192 /* cpl has to be less than 100 */ 194 /* cpl has to be less than 100 */
193 static void base64_encode_fp(FILE * fp, unsigned char *data, 195 static void base64_encode_fp(FILE * fp, unsigned char *data,
194 int datalen, int cpl) 196 int datalen, int cpl)
195 { 197 {
218 * Returns -1 if unsuccessful; otherwise returns the number of 220 * Returns -1 if unsuccessful; otherwise returns the number of
219 * bytes used out of the source data. 221 * bytes used out of the source data.
220 */ 222 */
221 223
222 /* ASN.1 tag classes. */ 224 /* ASN.1 tag classes. */
223 #define ASN1_CLASS_UNIVERSAL (0 << 6) 225 #define ASN1_CLASS_UNIVERSAL (0 << 6)
224 #define ASN1_CLASS_APPLICATION (1 << 6) 226 #define ASN1_CLASS_APPLICATION (1 << 6)
225 #define ASN1_CLASS_CONTEXT_SPECIFIC (2 << 6) 227 #define ASN1_CLASS_CONTEXT_SPECIFIC (2 << 6)
226 #define ASN1_CLASS_PRIVATE (3 << 6) 228 #define ASN1_CLASS_PRIVATE (3 << 6)
227 #define ASN1_CLASS_MASK (3 << 6) 229 #define ASN1_CLASS_MASK (3 << 6)
228 230
229 /* Primitive versus constructed bit. */ 231 /* Primitive versus constructed bit. */
230 #define ASN1_CONSTRUCTED (1 << 5) 232 #define ASN1_CONSTRUCTED (1 << 5)
231 233
232 static int ber_read_id_len(void *source, int sourcelen, 234 static int ber_read_id_len(void *source, int sourcelen,
233 int *id, int *length, int *flags) 235 int *id, int *length, int *flags)
234 { 236 {
235 unsigned char *p = (unsigned char *) source; 237 unsigned char *p = (unsigned char *) source;
236 238
237 if (sourcelen == 0) 239 if (sourcelen == 0)
240 return -1;
241
242 *flags = (*p & 0xE0);
243 if ((*p & 0x1F) == 0x1F) {
244 *id = 0;
245 while (*p & 0x80) {
246 p++, sourcelen--;
247 if (sourcelen == 0)
238 return -1; 248 return -1;
239 249 *id = (*id << 7) | (*p & 0x7F);
240 *flags = (*p & 0xE0); 250 }
241 if ((*p & 0x1F) == 0x1F) { 251 p++, sourcelen--;
242 *id = 0; 252 } else {
243 while (*p & 0x80) { 253 *id = *p & 0x1F;
244 *id = (*id << 7) | (*p & 0x7F); 254 p++, sourcelen--;
245 p++, sourcelen--; 255 }
246 if (sourcelen == 0) 256
247 return -1; 257 if (sourcelen == 0)
248 } 258 return -1;
249 *id = (*id << 7) | (*p & 0x7F); 259
250 p++, sourcelen--; 260 if (*p & 0x80) {
251 } else { 261 unsigned len;
252 *id = *p & 0x1F; 262 int n = *p & 0x7F;
253 p++, sourcelen--; 263 p++, sourcelen--;
254 } 264 if (sourcelen < n)
255 265 return -1;
256 if (sourcelen == 0) 266 len = 0;
257 return -1; 267 while (n--)
258 268 len = (len << 8) | (*p++);
259 if (*p & 0x80) { 269 sourcelen -= n;
260 int n = *p & 0x7F; 270 *length = toint(len);
261 p++, sourcelen--; 271 } else {
262 if (sourcelen < n) 272 *length = *p;
263 return -1; 273 p++, sourcelen--;
264 *length = 0; 274 }
265 while (n--) 275
266 *length = (*length << 8) | (*p++); 276 return p - (unsigned char *) source;
267 sourcelen -= n;
268 } else {
269 *length = *p;
270 p++, sourcelen--;
271 }
272
273 return p - (unsigned char *) source;
274 } 277 }
275 278
276 /* 279 /*
277 * Write an ASN.1/BER identifier and length pair. Returns the 280 * Write an ASN.1/BER identifier and length pair. Returns the
278 * number of bytes consumed. Assumes dest contains enough space. 281 * number of bytes consumed. Assumes dest contains enough space.
279 * Will avoid writing anything if dest is NULL, but still return 282 * Will avoid writing anything if dest is NULL, but still return
280 * amount of space required. 283 * amount of space required.
281 */ 284 */
282 static int ber_write_id_len(void *dest, int id, int length, int flags) 285 static int ber_write_id_len(void *dest, int id, int length, int flags)
283 { 286 {
284 unsigned char *d = (unsigned char *)dest; 287 unsigned char *d = (unsigned char *)dest;
285 int len = 0; 288 int len = 0;
286 289
287 if (id <= 30) { 290 if (id <= 30) {
288 /* 291 /*
289 * Identifier is one byte. 292 * Identifier is one byte.
290 */ 293 */
291 len++; 294 len++;
292 if (d) *d++ = id | flags; 295 if (d) *d++ = id | flags;
293 } else { 296 } else {
294 int n; 297 int n;
295 /* 298 /*
296 * Identifier is multiple bytes: the first byte is 11111 299 * Identifier is multiple bytes: the first byte is 11111
297 * plus the flags, and subsequent bytes encode the value of 300 * plus the flags, and subsequent bytes encode the value of
298 * the identifier, 7 bits at a time, with the top bit of 301 * the identifier, 7 bits at a time, with the top bit of
299 * each byte 1 except the last one which is 0. 302 * each byte 1 except the last one which is 0.
300 */ 303 */
301 len++; 304 len++;
302 if (d) *d++ = 0x1F | flags; 305 if (d) *d++ = 0x1F | flags;
303 for (n = 1; (id >> (7*n)) > 0; n++) 306 for (n = 1; (id >> (7*n)) > 0; n++)
304 continue; /* count the bytes */ 307 continue; /* count the bytes */
305 while (n--) { 308 while (n--) {
306 len++; 309 len++;
307 if (d) *d++ = (n ? 0x80 : 0) | ((id >> (7*n)) & 0x7F); 310 if (d) *d++ = (n ? 0x80 : 0) | ((id >> (7*n)) & 0x7F);
308 } 311 }
309 } 312 }
310 313
311 if (length < 128) { 314 if (length < 128) {
312 /* 315 /*
313 * Length is one byte. 316 * Length is one byte.
314 */ 317 */
315 len++; 318 len++;
316 if (d) *d++ = length; 319 if (d) *d++ = length;
317 } else { 320 } else {
318 int n; 321 int n;
319 /* 322 /*
320 * Length is multiple bytes. The first is 0x80 plus the 323 * Length is multiple bytes. The first is 0x80 plus the
321 * number of subsequent bytes, and the subsequent bytes 324 * number of subsequent bytes, and the subsequent bytes
322 * encode the actual length. 325 * encode the actual length.
323 */ 326 */
324 for (n = 1; (length >> (8*n)) > 0; n++) 327 for (n = 1; (length >> (8*n)) > 0; n++)
325 continue; /* count the bytes */ 328 continue; /* count the bytes */
326 len++; 329 len++;
327 if (d) *d++ = 0x80 | n; 330 if (d) *d++ = 0x80 | n;
328 while (n--) { 331 while (n--) {
329 len++; 332 len++;
330 if (d) *d++ = (length >> (8*n)) & 0xFF; 333 if (d) *d++ = (length >> (8*n)) & 0xFF;
331 } 334 }
332 } 335 }
333 336
334 return len; 337 return len;
335 } 338 }
336 339
337 340
338 /* Simple structure to point to an mp-int within a blob. */ 341 /* Simple structure to point to an mp-int within a blob. */
339 struct mpint_pos { void *start; int bytes; }; 342 struct mpint_pos { void *start; int bytes; };
342 * Code to read and write OpenSSH private keys. 345 * Code to read and write OpenSSH private keys.
343 */ 346 */
344 347
345 enum { OSSH_DSA, OSSH_RSA, OSSH_EC }; 348 enum { OSSH_DSA, OSSH_RSA, OSSH_EC };
346 struct openssh_key { 349 struct openssh_key {
347 int type; 350 int type;
348 int encrypted; 351 int encrypted;
349 char iv[32]; 352 char iv[32];
350 unsigned char *keyblob; 353 unsigned char *keyblob;
351 unsigned int keyblob_len, keyblob_size; 354 unsigned int keyblob_len, keyblob_size;
352 }; 355 };
353 356
354 static struct openssh_key *load_openssh_key(const char *filename) 357 static struct openssh_key *load_openssh_key(const char *filename)
355 { 358 {
356 struct openssh_key *ret; 359 struct openssh_key *ret;
357 FILE *fp = NULL; 360 FILE *fp = NULL;
358 char buffer[256]; 361 char buffer[256];
359 char *errmsg = NULL, *p = NULL; 362 char *errmsg = NULL, *p = NULL;
360 int headers_done; 363 int headers_done;
361 unsigned long len, outlen; 364 unsigned long len, outlen;
362 365
363 ret = (struct openssh_key*)m_malloc(sizeof(struct openssh_key)); 366 ret = (struct openssh_key*)m_malloc(sizeof(struct openssh_key));
364 ret->keyblob = NULL; 367 ret->keyblob = NULL;
365 ret->keyblob_len = ret->keyblob_size = 0; 368 ret->keyblob_len = ret->keyblob_size = 0;
366 ret->encrypted = 0; 369 ret->encrypted = 0;
367 memset(ret->iv, 0, sizeof(ret->iv)); 370 memset(ret->iv, 0, sizeof(ret->iv));
368 371
369 if (strlen(filename) == 1 && filename[0] == '-') { 372 if (strlen(filename) == 1 && filename[0] == '-') {
370 fp = stdin; 373 fp = stdin;
371 } else { 374 } else {
372 fp = fopen(filename, "r"); 375 fp = fopen(filename, "r");
373 } 376 }
374 if (!fp) { 377 if (!fp) {
375 errmsg = "Unable to open key file"; 378 errmsg = "Unable to open key file";
376 goto error; 379 goto error;
377 } 380 }
378 if (!fgets(buffer, sizeof(buffer), fp) || 381 if (!fgets(buffer, sizeof(buffer), fp) ||
379 0 != strncmp(buffer, "-----BEGIN ", 11) || 382 0 != strncmp(buffer, "-----BEGIN ", 11) ||
380 0 != strcmp(buffer+strlen(buffer)-17, "PRIVATE KEY-----\n")) { 383 0 != strcmp(buffer+strlen(buffer)-17, "PRIVATE KEY-----\n")) {
381 errmsg = "File does not begin with OpenSSH key header"; 384 errmsg = "File does not begin with OpenSSH key header";
382 goto error; 385 goto error;
383 } 386 }
384 if (!strcmp(buffer, "-----BEGIN RSA PRIVATE KEY-----\n")) 387 if (!strcmp(buffer, "-----BEGIN RSA PRIVATE KEY-----\n"))
385 ret->type = OSSH_RSA; 388 ret->type = OSSH_RSA;
386 else if (!strcmp(buffer, "-----BEGIN DSA PRIVATE KEY-----\n")) 389 else if (!strcmp(buffer, "-----BEGIN DSA PRIVATE KEY-----\n"))
387 ret->type = OSSH_DSA; 390 ret->type = OSSH_DSA;
388 else if (!strcmp(buffer, "-----BEGIN EC PRIVATE KEY-----\n")) 391 else if (!strcmp(buffer, "-----BEGIN EC PRIVATE KEY-----\n"))
389 ret->type = OSSH_EC; 392 ret->type = OSSH_EC;
390 else { 393 else {
391 errmsg = "Unrecognised key type"; 394 errmsg = "Unrecognised key type";
395 goto error;
396 }
397
398 headers_done = 0;
399 while (1) {
400 if (!fgets(buffer, sizeof(buffer), fp)) {
401 errmsg = "Unexpected end of file";
402 goto error;
403 }
404 if (0 == strncmp(buffer, "-----END ", 9) &&
405 0 == strcmp(buffer+strlen(buffer)-17, "PRIVATE KEY-----\n"))
406 break; /* done */
407 if ((p = strchr(buffer, ':')) != NULL) {
408 if (headers_done) {
409 errmsg = "Header found in body of key data";
392 goto error; 410 goto error;
393 } 411 }
394 412 *p++ = '\0';
395 headers_done = 0; 413 while (*p && isspace((unsigned char)*p)) p++;
396 while (1) { 414 if (!strcmp(buffer, "Proc-Type")) {
397 if (!fgets(buffer, sizeof(buffer), fp)) { 415 if (p[0] != '4' || p[1] != ',') {
398 errmsg = "Unexpected end of file"; 416 errmsg = "Proc-Type is not 4 (only 4 is supported)";
399 goto error; 417 goto error;
400 } 418 }
401 if (0 == strncmp(buffer, "-----END ", 9) && 419 p += 2;
402 0 == strcmp(buffer+strlen(buffer)-17, "PRIVATE KEY-----\n")) 420 if (!strcmp(p, "ENCRYPTED\n"))
403 break; /* done */ 421 ret->encrypted = 1;
404 if ((p = strchr(buffer, ':')) != NULL) { 422 } else if (!strcmp(buffer, "DEK-Info")) {
405 if (headers_done) { 423 int i, j;
406 errmsg = "Header found in body of key data"; 424
407 goto error; 425 if (strncmp(p, "DES-EDE3-CBC,", 13)) {
408 } 426 errmsg = "Ciphers other than DES-EDE3-CBC not supported";
409 *p++ = '\0'; 427 goto error;
410 while (*p && isspace((unsigned char)*p)) p++; 428 }
411 if (!strcmp(buffer, "Proc-Type")) { 429 p += 13;
412 if (p[0] != '4' || p[1] != ',') { 430 for (i = 0; i < 8; i++) {
413 errmsg = "Proc-Type is not 4 (only 4 is supported)"; 431 if (1 != sscanf(p, "%2x", &j))
414 goto error; 432 break;
415 } 433 ret->iv[i] = j;
416 p += 2; 434 p += 2;
417 if (!strcmp(p, "ENCRYPTED\n")) 435 }
418 ret->encrypted = 1; 436 if (i < 8) {
419 } else if (!strcmp(buffer, "DEK-Info")) { 437 errmsg = "Expected 16-digit iv in DEK-Info";
420 int i, j; 438 goto error;
421 439 }
422 if (strncmp(p, "DES-EDE3-CBC,", 13)) { 440 }
423 errmsg = "Ciphers other than DES-EDE3-CBC not supported"; 441 } else {
424 goto error; 442 headers_done = 1;
425 }
426 p += 13;
427 for (i = 0; i < 8; i++) {
428 if (1 != sscanf(p, "%2x", &j))
429 break;
430 ret->iv[i] = j;
431 p += 2;
432 }
433 if (i < 8) {
434 errmsg = "Expected 16-digit iv in DEK-Info";
435 goto error;
436 }
437 }
438 } else {
439 headers_done = 1;
440 len = strlen(buffer); 443 len = strlen(buffer);
441 outlen = len*4/3; 444 outlen = len*4/3;
442 if (ret->keyblob_len + outlen > ret->keyblob_size) { 445 if (ret->keyblob_len + outlen > ret->keyblob_size) {
443 ret->keyblob_size = ret->keyblob_len + outlen + 256; 446 ret->keyblob_size = ret->keyblob_len + outlen + 256;
444 ret->keyblob = (unsigned char*)m_realloc(ret->keyblob, 447 ret->keyblob = (unsigned char*)m_realloc(ret->keyblob,
446 } 449 }
447 outlen = ret->keyblob_size - ret->keyblob_len; 450 outlen = ret->keyblob_size - ret->keyblob_len;
448 if (base64_decode((const unsigned char *)buffer, len, 451 if (base64_decode((const unsigned char *)buffer, len,
449 ret->keyblob + ret->keyblob_len, &outlen) != CRYPT_OK){ 452 ret->keyblob + ret->keyblob_len, &outlen) != CRYPT_OK){
450 errmsg = "Error decoding base64"; 453 errmsg = "Error decoding base64";
451 goto error; 454 goto error;
452 } 455 }
453 ret->keyblob_len += outlen; 456 ret->keyblob_len += outlen;
454 } 457 }
455 } 458 }
456 459
457 if (ret->keyblob_len == 0 || !ret->keyblob) { 460 if (ret->keyblob_len == 0 || !ret->keyblob) {
458 errmsg = "Key body not present"; 461 errmsg = "Key body not present";
459 goto error; 462 goto error;
460 } 463 }
461 464
462 if (ret->encrypted && ret->keyblob_len % 8 != 0) { 465 if (ret->encrypted && ret->keyblob_len % 8 != 0) {
463 errmsg = "Encrypted key blob is not a multiple of cipher block size"; 466 errmsg = "Encrypted key blob is not a multiple of cipher block size";
464 goto error; 467 goto error;
465 } 468 }
466 469
467 m_burn(buffer, sizeof(buffer)); 470 m_burn(buffer, sizeof(buffer));
468 return ret; 471 return ret;
469 472
470 error: 473 error:
471 m_burn(buffer, sizeof(buffer)); 474 m_burn(buffer, sizeof(buffer));
472 if (ret) { 475 if (ret) {
473 if (ret->keyblob) { 476 if (ret->keyblob) {
474 m_burn(ret->keyblob, ret->keyblob_size); 477 m_burn(ret->keyblob, ret->keyblob_size);
475 m_free(ret->keyblob); 478 m_free(ret->keyblob);
476 } 479 }
477 m_free(ret); 480 m_free(ret);
478 } 481 }
479 if (fp) { 482 if (fp) {
480 fclose(fp); 483 fclose(fp);
481 } 484 }
482 if (errmsg) { 485 if (errmsg) {
483 fprintf(stderr, "Error: %s\n", errmsg); 486 fprintf(stderr, "Error: %s\n", errmsg);
484 } 487 }
485 return NULL; 488 return NULL;
486 } 489 }
487 490
488 static int openssh_encrypted(const char *filename) 491 static int openssh_encrypted(const char *filename)
489 { 492 {
490 struct openssh_key *key = load_openssh_key(filename); 493 struct openssh_key *key = load_openssh_key(filename);
491 int ret; 494 int ret;
492 495
493 if (!key) 496 if (!key)
494 return 0; 497 return 0;
495 ret = key->encrypted; 498 ret = key->encrypted;
496 m_burn(key->keyblob, key->keyblob_size); 499 m_burn(key->keyblob, key->keyblob_size);
497 m_free(key->keyblob); 500 m_free(key->keyblob);
498 m_free(key); 501 m_free(key);
499 return ret; 502 return ret;
500 } 503 }
501 504
502 static sign_key *openssh_read(const char *filename, char * UNUSED(passphrase)) 505 static sign_key *openssh_read(const char *filename, char * UNUSED(passphrase))
503 { 506 {
504 struct openssh_key *key; 507 struct openssh_key *key;
505 unsigned char *p; 508 unsigned char *p;
506 int ret, id, len, flags; 509 int ret, id, len, flags;
507 int i, num_integers = 0; 510 int i, num_integers = 0;
508 sign_key *retval = NULL; 511 sign_key *retval = NULL;
509 char *errmsg; 512 char *errmsg;
510 unsigned char *modptr = NULL; 513 unsigned char *modptr = NULL;
511 int modlen = -9999; 514 int modlen = -9999;
512 enum signkey_type type; 515 enum signkey_type type;
513 516
514 sign_key *retkey; 517 sign_key *retkey;
516 519
517 retkey = new_sign_key(); 520 retkey = new_sign_key();
518 521
519 key = load_openssh_key(filename); 522 key = load_openssh_key(filename);
520 523
521 if (!key) 524 if (!key)
522 return NULL; 525 return NULL;
523 526
524 if (key->encrypted) { 527 if (key->encrypted) {
525 errmsg = "encrypted keys not supported currently"; 528 errmsg = "encrypted keys not supported currently";
526 goto error; 529 goto error;
527 #if 0 530 #if 0
528 /* matt TODO */ 531 /* matt TODO */
529 /* 532 /*
530 * Derive encryption key from passphrase and iv/salt: 533 * Derive encryption key from passphrase and iv/salt:
531 * 534 *
532 * - let block A equal MD5(passphrase || iv) 535 * - let block A equal MD5(passphrase || iv)
533 * - let block B equal MD5(A || passphrase || iv) 536 * - let block B equal MD5(A || passphrase || iv)
534 * - block C would be MD5(B || passphrase || iv) and so on 537 * - block C would be MD5(B || passphrase || iv) and so on
535 * - encryption key is the first N bytes of A || B 538 * - encryption key is the first N bytes of A || B
536 */ 539 */
537 struct MD5Context md5c; 540 struct MD5Context md5c;
538 unsigned char keybuf[32]; 541 unsigned char keybuf[32];
539 542
540 MD5Init(&md5c); 543 MD5Init(&md5c);
541 MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase)); 544 MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase));
542 MD5Update(&md5c, (unsigned char *)key->iv, 8); 545 MD5Update(&md5c, (unsigned char *)key->iv, 8);
543 MD5Final(keybuf, &md5c); 546 MD5Final(keybuf, &md5c);
544 547
545 MD5Init(&md5c); 548 MD5Init(&md5c);
546 MD5Update(&md5c, keybuf, 16); 549 MD5Update(&md5c, keybuf, 16);
547 MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase)); 550 MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase));
548 MD5Update(&md5c, (unsigned char *)key->iv, 8); 551 MD5Update(&md5c, (unsigned char *)key->iv, 8);
549 MD5Final(keybuf+16, &md5c); 552 MD5Final(keybuf+16, &md5c);
550 553
551 /* 554 /*
552 * Now decrypt the key blob. 555 * Now decrypt the key blob.
553 */ 556 */
554 des3_decrypt_pubkey_ossh(keybuf, (unsigned char *)key->iv, 557 des3_decrypt_pubkey_ossh(keybuf, (unsigned char *)key->iv,
555 key->keyblob, key->keyblob_len); 558 key->keyblob, key->keyblob_len);
556 559
557 memset(&md5c, 0, sizeof(md5c)); 560 memset(&md5c, 0, sizeof(md5c));
558 memset(keybuf, 0, sizeof(keybuf)); 561 memset(keybuf, 0, sizeof(keybuf));
559 #endif 562 #endif
560 } 563 }
561 564
562 /* 565 /*
563 * Now we have a decrypted key blob, which contains an ASN.1 566 * Now we have a decrypted key blob, which contains an ASN.1
564 * encoded private key. We must now untangle the ASN.1. 567 * encoded private key. We must now untangle the ASN.1.
565 * 568 *
566 * We expect the whole key blob to be formatted as a SEQUENCE 569 * We expect the whole key blob to be formatted as a SEQUENCE
567 * (0x30 followed by a length code indicating that the rest of 570 * (0x30 followed by a length code indicating that the rest of
568 * the blob is part of the sequence). Within that SEQUENCE we 571 * the blob is part of the sequence). Within that SEQUENCE we
569 * expect to see a bunch of INTEGERs. What those integers mean 572 * expect to see a bunch of INTEGERs. What those integers mean
570 * depends on the key type: 573 * depends on the key type:
571 * 574 *
572 * - For RSA, we expect the integers to be 0, n, e, d, p, q, 575 * - For RSA, we expect the integers to be 0, n, e, d, p, q,
573 * dmp1, dmq1, iqmp in that order. (The last three are d mod 576 * dmp1, dmq1, iqmp in that order. (The last three are d mod
574 * (p-1), d mod (q-1), inverse of q mod p respectively.) 577 * (p-1), d mod (q-1), inverse of q mod p respectively.)
575 * 578 *
576 * - For DSA, we expect them to be 0, p, q, g, y, x in that 579 * - For DSA, we expect them to be 0, p, q, g, y, x in that
577 * order. 580 * order.
578 */ 581 */
579 582
580 p = key->keyblob; 583 p = key->keyblob;
581 584
582 /* Expect the SEQUENCE header. Take its absence as a failure to decrypt. */ 585 /* Expect the SEQUENCE header. Take its absence as a failure to decrypt. */
583 ret = ber_read_id_len(p, key->keyblob_len, &id, &len, &flags); 586 ret = ber_read_id_len(p, key->keyblob_len, &id, &len, &flags);
584 p += ret; 587 p += ret;
585 if (ret < 0 || id != 16) { 588 if (ret < 0 || id != 16 || len < 0 ||
589 key->keyblob+key->keyblob_len-p < len) {
586 errmsg = "ASN.1 decoding failure - wrong password?"; 590 errmsg = "ASN.1 decoding failure - wrong password?";
587 goto error; 591 goto error;
588 } 592 }
589 593
590 /* Expect a load of INTEGERs. */ 594 /* Expect a load of INTEGERs. */
591 if (key->type == OSSH_RSA) 595 if (key->type == OSSH_RSA)
592 num_integers = 9; 596 num_integers = 9;
593 else if (key->type == OSSH_DSA) 597 else if (key->type == OSSH_DSA)
594 num_integers = 6; 598 num_integers = 6;
595 else if (key->type == OSSH_EC) 599 else if (key->type == OSSH_EC)
596 num_integers = 1; 600 num_integers = 1;
597 601
598 /* 602 /*
599 * Space to create key blob in. 603 * Space to create key blob in.
600 */ 604 */
601 blobbuf = buf_new(3000); 605 blobbuf = buf_new(3000);
602 606
603 #ifdef DROPBEAR_DSS 607 #ifdef DROPBEAR_DSS
604 if (key->type == OSSH_DSA) { 608 if (key->type == OSSH_DSA) {
605 buf_putstring(blobbuf, "ssh-dss", 7); 609 buf_putstring(blobbuf, "ssh-dss", 7);
611 buf_putstring(blobbuf, "ssh-rsa", 7); 615 buf_putstring(blobbuf, "ssh-rsa", 7);
612 retkey->type = DROPBEAR_SIGNKEY_RSA; 616 retkey->type = DROPBEAR_SIGNKEY_RSA;
613 } 617 }
614 #endif 618 #endif
615 619
616 for (i = 0; i < num_integers; i++) { 620 for (i = 0; i < num_integers; i++) {
617 ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, 621 ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,
618 &id, &len, &flags); 622 &id, &len, &flags);
619 p += ret; 623 p += ret;
620 if (ret < 0 || id != 2 || 624 if (ret < 0 || id != 2 || len < 0 ||
621 key->keyblob+key->keyblob_len-p < len) { 625 key->keyblob+key->keyblob_len-p < len) {
622 errmsg = "ASN.1 decoding failure"; 626 errmsg = "ASN.1 decoding failure";
623 goto error; 627 goto error;
624 } 628 }
625 629
626 if (i == 0) { 630 if (i == 0) {
627 /* First integer is a version indicator */ 631 /* First integer is a version indicator */
628 int expected = -1; 632 int expected = -1;
629 switch (key->type) { 633 switch (key->type) {
630 case OSSH_RSA: 634 case OSSH_RSA:
631 case OSSH_DSA: 635 case OSSH_DSA:
634 case OSSH_EC: 638 case OSSH_EC:
635 expected = 1; 639 expected = 1;
636 break; 640 break;
637 } 641 }
638 if (len != 1 || p[0] != expected) { 642 if (len != 1 || p[0] != expected) {
639 errmsg = "Version number mismatch"; 643 errmsg = "Version number mismatch";
640 goto error; 644 goto error;
641 } 645 }
642 } else if (key->type == OSSH_RSA) { 646 } else if (key->type == OSSH_RSA) {
643 /* 647 /*
644 * OpenSSH key order is n, e, d, p, q, dmp1, dmq1, iqmp 648 * OpenSSH key order is n, e, d, p, q, dmp1, dmq1, iqmp
645 * but we want e, n, d, p, q 649 * but we want e, n, d, p, q
646 */ 650 */
647 if (i == 1) { 651 if (i == 1) {
648 /* Save the details for after we deal with number 2. */ 652 /* Save the details for after we deal with number 2. */
649 modptr = p; 653 modptr = p;
650 modlen = len; 654 modlen = len;
651 } else if (i >= 2 && i <= 5) { 655 } else if (i >= 2 && i <= 5) {
652 buf_putstring(blobbuf, (const char*)p, len); 656 buf_putstring(blobbuf, (const char*)p, len);
653 if (i == 2) { 657 if (i == 2) {
654 buf_putstring(blobbuf, (const char*)modptr, modlen); 658 buf_putstring(blobbuf, (const char*)modptr, modlen);
655 } 659 }
656 } 660 }
657 } else if (key->type == OSSH_DSA) { 661 } else if (key->type == OSSH_DSA) {
658 /* 662 /*
659 * OpenSSH key order is p, q, g, y, x, 663 * OpenSSH key order is p, q, g, y, x,
660 * we want the same. 664 * we want the same.
661 */ 665 */
662 buf_putstring(blobbuf, (const char*)p, len); 666 buf_putstring(blobbuf, (const char*)p, len);
663 } 667 }
664 668
665 /* Skip past the number. */ 669 /* Skip past the number. */
666 p += len; 670 p += len;
667 } 671 }
668 672
669 #ifdef DROPBEAR_ECDSA 673 #ifdef DROPBEAR_ECDSA
670 if (key->type == OSSH_EC) { 674 if (key->type == OSSH_EC) {
671 unsigned char* private_key_bytes = NULL; 675 unsigned char* private_key_bytes = NULL;
672 int private_key_len = 0; 676 int private_key_len = 0;
778 782
779 *signkey_key_ptr(retkey, retkey->type) = ecc; 783 *signkey_key_ptr(retkey, retkey->type) = ecc;
780 } 784 }
781 #endif /* DROPBEAR_ECDSA */ 785 #endif /* DROPBEAR_ECDSA */
782 786
783 /* 787 /*
784 * Now put together the actual key. Simplest way to do this is 788 * Now put together the actual key. Simplest way to do this is
785 * to assemble our own key blobs and feed them to the createkey 789 * to assemble our own key blobs and feed them to the createkey
786 * functions; this is a bit faffy but it does mean we get all 790 * functions; this is a bit faffy but it does mean we get all
787 * the sanity checks for free. 791 * the sanity checks for free.
788 */ 792 */
789 if (key->type == OSSH_RSA || key->type == OSSH_DSA) { 793 if (key->type == OSSH_RSA || key->type == OSSH_DSA) {
790 buf_setpos(blobbuf, 0); 794 buf_setpos(blobbuf, 0);
791 type = DROPBEAR_SIGNKEY_ANY; 795 type = DROPBEAR_SIGNKEY_ANY;
792 if (buf_get_priv_key(blobbuf, retkey, &type) 796 if (buf_get_priv_key(blobbuf, retkey, &type)
793 != DROPBEAR_SUCCESS) { 797 != DROPBEAR_SUCCESS) {
794 errmsg = "unable to create key structure"; 798 errmsg = "unable to create key structure";
795 sign_key_free(retkey); 799 sign_key_free(retkey);
796 retkey = NULL; 800 retkey = NULL;
797 goto error; 801 goto error;
798 } 802 }
799 } 803 }
800 804
801 errmsg = NULL; /* no error */ 805 errmsg = NULL; /* no error */
802 retval = retkey; 806 retval = retkey;
803 807
804 error: 808 error:
805 if (blobbuf) { 809 if (blobbuf) {
806 buf_burn(blobbuf); 810 buf_burn(blobbuf);
807 buf_free(blobbuf); 811 buf_free(blobbuf);
808 } 812 }
809 m_burn(key->keyblob, key->keyblob_size); 813 m_burn(key->keyblob, key->keyblob_size);
810 m_free(key->keyblob); 814 m_free(key->keyblob);
811 m_burn(key, sizeof(*key)); 815 m_burn(key, sizeof(*key));
812 m_free(key); 816 m_free(key);
813 if (errmsg) { 817 if (errmsg) {
814 fprintf(stderr, "Error: %s\n", errmsg); 818 fprintf(stderr, "Error: %s\n", errmsg);
815 } 819 }
816 return retval; 820 return retval;
817 } 821 }
818 822
819 static int openssh_write(const char *filename, sign_key *key, 823 static int openssh_write(const char *filename, sign_key *key,
820 char *passphrase) 824 char *passphrase)
821 { 825 {
822 buffer * keyblob = NULL; 826 buffer * keyblob = NULL;
823 buffer * extrablob = NULL; /* used for calculated values to write */ 827 buffer * extrablob = NULL; /* used for calculated values to write */
824 unsigned char *outblob = NULL; 828 unsigned char *outblob = NULL;
825 int outlen = -9999; 829 int outlen = -9999;
826 struct mpint_pos numbers[9]; 830 struct mpint_pos numbers[9];
827 int nnumbers = -1, pos = 0, len = 0, seqlen, i; 831 int nnumbers = -1, pos = 0, len = 0, seqlen, i;
828 char *header = NULL, *footer = NULL; 832 char *header = NULL, *footer = NULL;
829 char zero[1]; 833 char zero[1];
830 int ret = 0; 834 int ret = 0;
831 FILE *fp; 835 FILE *fp;
832 836
833 #ifdef DROPBEAR_RSA 837 #ifdef DROPBEAR_RSA
834 mp_int dmp1, dmq1, iqmp, tmpval; /* for rsa */ 838 mp_int dmp1, dmq1, iqmp, tmpval; /* for rsa */
835 #endif 839 #endif
836 840
841 #ifdef DROPBEAR_DSS 845 #ifdef DROPBEAR_DSS
842 key->type == DROPBEAR_SIGNKEY_DSS || 846 key->type == DROPBEAR_SIGNKEY_DSS ||
843 #endif 847 #endif
844 0) 848 0)
845 { 849 {
846 /* 850 /*
847 * Fetch the key blobs. 851 * Fetch the key blobs.
848 */ 852 */
849 keyblob = buf_new(3000); 853 keyblob = buf_new(3000);
850 buf_put_priv_key(keyblob, key, key->type); 854 buf_put_priv_key(keyblob, key, key->type);
851 855
852 buf_setpos(keyblob, 0); 856 buf_setpos(keyblob, 0);
853 /* skip the "ssh-rsa" or "ssh-dss" header */ 857 /* skip the "ssh-rsa" or "ssh-dss" header */
854 buf_incrpos(keyblob, buf_getint(keyblob)); 858 buf_incrpos(keyblob, buf_getint(keyblob));
855 859
856 /* 860 /*
857 * Find the sequence of integers to be encoded into the OpenSSH 861 * Find the sequence of integers to be encoded into the OpenSSH
858 * key blob, and also decide on the header line. 862 * key blob, and also decide on the header line.
859 */ 863 */
860 numbers[0].start = zero; numbers[0].bytes = 1; zero[0] = '\0'; 864 numbers[0].start = zero; numbers[0].bytes = 1; zero[0] = '\0';
861 865
862 #ifdef DROPBEAR_RSA 866 #ifdef DROPBEAR_RSA
863 if (key->type == DROPBEAR_SIGNKEY_RSA) { 867 if (key->type == DROPBEAR_SIGNKEY_RSA) {
864 868
869 873
870 /* e */ 874 /* e */
871 numbers[2].bytes = buf_getint(keyblob); 875 numbers[2].bytes = buf_getint(keyblob);
872 numbers[2].start = buf_getptr(keyblob, numbers[2].bytes); 876 numbers[2].start = buf_getptr(keyblob, numbers[2].bytes);
873 buf_incrpos(keyblob, numbers[2].bytes); 877 buf_incrpos(keyblob, numbers[2].bytes);
874 878
875 /* n */ 879 /* n */
876 numbers[1].bytes = buf_getint(keyblob); 880 numbers[1].bytes = buf_getint(keyblob);
877 numbers[1].start = buf_getptr(keyblob, numbers[1].bytes); 881 numbers[1].start = buf_getptr(keyblob, numbers[1].bytes);
878 buf_incrpos(keyblob, numbers[1].bytes); 882 buf_incrpos(keyblob, numbers[1].bytes);
879 883
880 /* d */ 884 /* d */
881 numbers[3].bytes = buf_getint(keyblob); 885 numbers[3].bytes = buf_getint(keyblob);
882 numbers[3].start = buf_getptr(keyblob, numbers[3].bytes); 886 numbers[3].start = buf_getptr(keyblob, numbers[3].bytes);
883 buf_incrpos(keyblob, numbers[3].bytes); 887 buf_incrpos(keyblob, numbers[3].bytes);
884 888
885 /* p */ 889 /* p */
886 numbers[4].bytes = buf_getint(keyblob); 890 numbers[4].bytes = buf_getint(keyblob);
887 numbers[4].start = buf_getptr(keyblob, numbers[4].bytes); 891 numbers[4].start = buf_getptr(keyblob, numbers[4].bytes);
888 buf_incrpos(keyblob, numbers[4].bytes); 892 buf_incrpos(keyblob, numbers[4].bytes);
889 893
947 /* iqmp */ 951 /* iqmp */
948 numbers[8].bytes = buf_getint(extrablob); 952 numbers[8].bytes = buf_getint(extrablob);
949 numbers[8].start = buf_getptr(extrablob, numbers[8].bytes); 953 numbers[8].start = buf_getptr(extrablob, numbers[8].bytes);
950 buf_incrpos(extrablob, numbers[8].bytes); 954 buf_incrpos(extrablob, numbers[8].bytes);
951 955
952 nnumbers = 9; 956 nnumbers = 9;
953 header = "-----BEGIN RSA PRIVATE KEY-----\n"; 957 header = "-----BEGIN RSA PRIVATE KEY-----\n";
954 footer = "-----END RSA PRIVATE KEY-----\n"; 958 footer = "-----END RSA PRIVATE KEY-----\n";
955 } 959 }
956 #endif /* DROPBEAR_RSA */ 960 #endif /* DROPBEAR_RSA */
957 961
958 #ifdef DROPBEAR_DSS 962 #ifdef DROPBEAR_DSS
959 if (key->type == DROPBEAR_SIGNKEY_DSS) { 963 if (key->type == DROPBEAR_SIGNKEY_DSS) {
981 /* x */ 985 /* x */
982 numbers[5].bytes = buf_getint(keyblob); 986 numbers[5].bytes = buf_getint(keyblob);
983 numbers[5].start = buf_getptr(keyblob, numbers[5].bytes); 987 numbers[5].start = buf_getptr(keyblob, numbers[5].bytes);
984 buf_incrpos(keyblob, numbers[5].bytes); 988 buf_incrpos(keyblob, numbers[5].bytes);
985 989
986 nnumbers = 6; 990 nnumbers = 6;
987 header = "-----BEGIN DSA PRIVATE KEY-----\n"; 991 header = "-----BEGIN DSA PRIVATE KEY-----\n";
988 footer = "-----END DSA PRIVATE KEY-----\n"; 992 footer = "-----END DSA PRIVATE KEY-----\n";
989 } 993 }
990 #endif /* DROPBEAR_DSS */ 994 #endif /* DROPBEAR_DSS */
991 995
992 /* 996 /*
993 * Now count up the total size of the ASN.1 encoded integers, 997 * Now count up the total size of the ASN.1 encoded integers,
994 * so as to determine the length of the containing SEQUENCE. 998 * so as to determine the length of the containing SEQUENCE.
995 */ 999 */
996 len = 0; 1000 len = 0;
997 for (i = 0; i < nnumbers; i++) { 1001 for (i = 0; i < nnumbers; i++) {
998 len += ber_write_id_len(NULL, 2, numbers[i].bytes, 0); 1002 len += ber_write_id_len(NULL, 2, numbers[i].bytes, 0);
999 len += numbers[i].bytes; 1003 len += numbers[i].bytes;
1000 } 1004 }
1001 seqlen = len; 1005 seqlen = len;
1002 /* Now add on the SEQUENCE header. */ 1006 /* Now add on the SEQUENCE header. */
1003 len += ber_write_id_len(NULL, 16, seqlen, ASN1_CONSTRUCTED); 1007 len += ber_write_id_len(NULL, 16, seqlen, ASN1_CONSTRUCTED);
1004 /* Round up to the cipher block size, ensuring we have at least one 1008 /* Round up to the cipher block size, ensuring we have at least one
1005 * byte of padding (see below). */ 1009 * byte of padding (see below). */
1006 outlen = len; 1010 outlen = len;
1007 if (passphrase) 1011 if (passphrase)
1008 outlen = (outlen+8) &~ 7; 1012 outlen = (outlen+8) &~ 7;
1009 1013
1010 /* 1014 /*
1011 * Now we know how big outblob needs to be. Allocate it. 1015 * Now we know how big outblob needs to be. Allocate it.
1012 */ 1016 */
1013 outblob = (unsigned char*)m_malloc(outlen); 1017 outblob = (unsigned char*)m_malloc(outlen);
1014 1018
1015 /* 1019 /*
1016 * And write the data into it. 1020 * And write the data into it.
1017 */ 1021 */
1018 pos = 0; 1022 pos = 0;
1019 pos += ber_write_id_len(outblob+pos, 16, seqlen, ASN1_CONSTRUCTED); 1023 pos += ber_write_id_len(outblob+pos, 16, seqlen, ASN1_CONSTRUCTED);
1020 for (i = 0; i < nnumbers; i++) { 1024 for (i = 0; i < nnumbers; i++) {
1021 pos += ber_write_id_len(outblob+pos, 2, numbers[i].bytes, 0); 1025 pos += ber_write_id_len(outblob+pos, 2, numbers[i].bytes, 0);
1022 memcpy(outblob+pos, numbers[i].start, numbers[i].bytes); 1026 memcpy(outblob+pos, numbers[i].start, numbers[i].bytes);
1023 pos += numbers[i].bytes; 1027 pos += numbers[i].bytes;
1024 } 1028 }
1025 } /* end RSA and DSS handling */ 1029 } /* end RSA and DSS handling */
1026 1030
1027 #ifdef DROPBEAR_ECDSA 1031 #ifdef DROPBEAR_ECDSA
1028 if (key->type == DROPBEAR_SIGNKEY_ECDSA_NISTP256 1032 if (key->type == DROPBEAR_SIGNKEY_ECDSA_NISTP256
1029 || key->type == DROPBEAR_SIGNKEY_ECDSA_NISTP384 1033 || key->type == DROPBEAR_SIGNKEY_ECDSA_NISTP384
1114 header = "-----BEGIN EC PRIVATE KEY-----\n"; 1118 header = "-----BEGIN EC PRIVATE KEY-----\n";
1115 footer = "-----END EC PRIVATE KEY-----\n"; 1119 footer = "-----END EC PRIVATE KEY-----\n";
1116 } 1120 }
1117 #endif 1121 #endif
1118 1122
1119 /* 1123 /*
1120 * Padding on OpenSSH keys is deterministic. The number of 1124 * Padding on OpenSSH keys is deterministic. The number of
1121 * padding bytes is always more than zero, and always at most 1125 * padding bytes is always more than zero, and always at most
1122 * the cipher block length. The value of each padding byte is 1126 * the cipher block length. The value of each padding byte is
1123 * equal to the number of padding bytes. So a plaintext that's 1127 * equal to the number of padding bytes. So a plaintext that's
1124 * an exact multiple of the block size will be padded with 08 1128 * an exact multiple of the block size will be padded with 08
1125 * 08 08 08 08 08 08 08 (assuming a 64-bit block cipher); a 1129 * 08 08 08 08 08 08 08 (assuming a 64-bit block cipher); a
1126 * plaintext one byte less than a multiple of the block size 1130 * plaintext one byte less than a multiple of the block size
1127 * will be padded with just 01. 1131 * will be padded with just 01.
1128 * 1132 *
1129 * This enables the OpenSSL key decryption function to strip 1133 * This enables the OpenSSL key decryption function to strip
1130 * off the padding algorithmically and return the unpadded 1134 * off the padding algorithmically and return the unpadded
1131 * plaintext to the next layer: it looks at the final byte, and 1135 * plaintext to the next layer: it looks at the final byte, and
1132 * then expects to find that many bytes at the end of the data 1136 * then expects to find that many bytes at the end of the data
1133 * with the same value. Those are all removed and the rest is 1137 * with the same value. Those are all removed and the rest is
1134 * returned. 1138 * returned.
1135 */ 1139 */
1136 dropbear_assert(pos == len); 1140 dropbear_assert(pos == len);
1137 while (pos < outlen) { 1141 while (pos < outlen) {
1138 outblob[pos++] = outlen - len; 1142 outblob[pos++] = outlen - len;
1139 } 1143 }
1140 1144
1141 /* 1145 /*
1142 * Encrypt the key. 1146 * Encrypt the key.
1143 */ 1147 */
1144 if (passphrase) { 1148 if (passphrase) {
1145 fprintf(stderr, "Encrypted keys aren't supported currently\n"); 1149 fprintf(stderr, "Encrypted keys aren't supported currently\n");
1146 goto error; 1150 goto error;
1147 } 1151 }
1148 1152
1149 /* 1153 /*
1150 * And save it. We'll use Unix line endings just in case it's 1154 * And save it. We'll use Unix line endings just in case it's
1151 * subsequently transferred in binary mode. 1155 * subsequently transferred in binary mode.
1152 */ 1156 */
1153 if (strlen(filename) == 1 && filename[0] == '-') { 1157 if (strlen(filename) == 1 && filename[0] == '-') {
1154 fp = stdout; 1158 fp = stdout;
1155 } else { 1159 } else {
1156 fp = fopen(filename, "wb"); /* ensure Unix line endings */ 1160 fp = fopen(filename, "wb"); /* ensure Unix line endings */
1157 } 1161 }
1158 if (!fp) { 1162 if (!fp) {
1159 fprintf(stderr, "Failed opening output file\n"); 1163 fprintf(stderr, "Failed opening output file\n");
1160 goto error; 1164 goto error;
1161 } 1165 }
1162 fputs(header, fp); 1166 fputs(header, fp);
1163 base64_encode_fp(fp, outblob, outlen, 64); 1167 base64_encode_fp(fp, outblob, outlen, 64);
1164 fputs(footer, fp); 1168 fputs(footer, fp);
1165 fclose(fp); 1169 fclose(fp);
1166 ret = 1; 1170 ret = 1;
1167 1171
1168 error: 1172 error:
1169 if (outblob) { 1173 if (outblob) {
1170 memset(outblob, 0, outlen); 1174 memset(outblob, 0, outlen);
1171 m_free(outblob); 1175 m_free(outblob);
1172 } 1176 }
1173 if (keyblob) { 1177 if (keyblob) {
1174 buf_burn(keyblob); 1178 buf_burn(keyblob);
1175 buf_free(keyblob); 1179 buf_free(keyblob);
1176 } 1180 }
1177 if (extrablob) { 1181 if (extrablob) {
1178 buf_burn(extrablob); 1182 buf_burn(extrablob);
1179 buf_free(extrablob); 1183 buf_free(extrablob);
1180 } 1184 }
1181 return ret; 1185 return ret;
1182 } 1186 }
1183 1187
1184 #if 0 1188 #if 0
1185 /* XXX TODO ssh.com stuff isn't going yet */ 1189 /* XXX TODO ssh.com stuff isn't going yet */
1186 1190
1194 * old ssh1 mpint. You have a 32-bit bit count N, followed by 1198 * old ssh1 mpint. You have a 32-bit bit count N, followed by
1195 * (N+7)/8 bytes of data. 1199 * (N+7)/8 bytes of data.
1196 * 1200 *
1197 * So. The blob contains: 1201 * So. The blob contains:
1198 * 1202 *
1199 * - uint32 0x3f6ff9eb (magic number) 1203 * - uint32 0x3f6ff9eb (magic number)
1200 * - uint32 size (total blob size) 1204 * - uint32 size (total blob size)
1201 * - string key-type (see below) 1205 * - string key-type (see below)
1202 * - string cipher-type (tells you if key is encrypted) 1206 * - string cipher-type (tells you if key is encrypted)
1203 * - string encrypted-blob 1207 * - string encrypted-blob
1204 * 1208 *
1205 * (The first size field includes the size field itself and the 1209 * (The first size field includes the size field itself and the
1206 * magic number before it. All other size fields are ordinary ssh2 1210 * magic number before it. All other size fields are ordinary ssh2
1207 * strings, so the size field indicates how much data is to 1211 * strings, so the size field indicates how much data is to
1253 * from the passphrase by means of yet another hashing faff: 1257 * from the passphrase by means of yet another hashing faff:
1254 * 1258 *
1255 * - first 16 bytes are MD5(passphrase) 1259 * - first 16 bytes are MD5(passphrase)
1256 * - next 16 bytes are MD5(passphrase || first 16 bytes) 1260 * - next 16 bytes are MD5(passphrase || first 16 bytes)
1257 * - if there were more, they'd be MD5(passphrase || first 32), 1261 * - if there were more, they'd be MD5(passphrase || first 32),
1258 * and so on. 1262 * and so on.
1259 */ 1263 */
1260 1264
1261 #define SSHCOM_MAGIC_NUMBER 0x3f6ff9eb 1265 #define SSHCOM_MAGIC_NUMBER 0x3f6ff9eb
1262 1266
1263 struct sshcom_key { 1267 struct sshcom_key {
1264 char comment[256]; /* allowing any length is overkill */ 1268 char comment[256]; /* allowing any length is overkill */
1265 unsigned char *keyblob; 1269 unsigned char *keyblob;
1266 int keyblob_len, keyblob_size; 1270 int keyblob_len, keyblob_size;
1267 }; 1271 };
1268 1272
1269 static struct sshcom_key *load_sshcom_key(const char *filename) 1273 static struct sshcom_key *load_sshcom_key(const char *filename)
1270 { 1274 {
1271 struct sshcom_key *ret; 1275 struct sshcom_key *ret;
1272 FILE *fp; 1276 FILE *fp;
1273 char buffer[256]; 1277 char buffer[256];
1274 int len; 1278 int len;
1275 char *errmsg, *p; 1279 char *errmsg, *p;
1276 int headers_done; 1280 int headers_done;
1277 char base64_bit[4]; 1281 char base64_bit[4];
1278 int base64_chars = 0; 1282 int base64_chars = 0;
1279 1283
1280 ret = snew(struct sshcom_key); 1284 ret = snew(struct sshcom_key);
1281 ret->comment[0] = '\0'; 1285 ret->comment[0] = '\0';
1282 ret->keyblob = NULL; 1286 ret->keyblob = NULL;
1283 ret->keyblob_len = ret->keyblob_size = 0; 1287 ret->keyblob_len = ret->keyblob_size = 0;
1284 1288
1285 fp = fopen(filename, "r"); 1289 fp = fopen(filename, "r");
1286 if (!fp) { 1290 if (!fp) {
1287 errmsg = "Unable to open key file"; 1291 errmsg = "Unable to open key file";
1292 goto error;
1293 }
1294 if (!fgets(buffer, sizeof(buffer), fp) ||
1295 0 != strcmp(buffer, "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----\n")) {
1296 errmsg = "File does not begin with ssh.com key header";
1297 goto error;
1298 }
1299
1300 headers_done = 0;
1301 while (1) {
1302 if (!fgets(buffer, sizeof(buffer), fp)) {
1303 errmsg = "Unexpected end of file";
1304 goto error;
1305 }
1306 if (!strcmp(buffer, "---- END SSH2 ENCRYPTED PRIVATE KEY ----\n"))
1307 break; /* done */
1308 if ((p = strchr(buffer, ':')) != NULL) {
1309 if (headers_done) {
1310 errmsg = "Header found in body of key data";
1288 goto error; 1311 goto error;
1289 } 1312 }
1290 if (!fgets(buffer, sizeof(buffer), fp) || 1313 *p++ = '\0';
1291 0 != strcmp(buffer, "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----\n")) { 1314 while (*p && isspace((unsigned char)*p)) p++;
1292 errmsg = "File does not begin with ssh.com key header"; 1315 /*
1293 goto error; 1316 * Header lines can end in a trailing backslash for
1294 } 1317 * continuation.
1295 1318 */
1296 headers_done = 0; 1319 while ((len = strlen(p)) > (int)(sizeof(buffer) - (p-buffer) -1) ||
1297 while (1) { 1320 p[len-1] != '\n' || p[len-2] == '\\') {
1298 if (!fgets(buffer, sizeof(buffer), fp)) { 1321 if (len > (int)((p-buffer) + sizeof(buffer)-2)) {
1299 errmsg = "Unexpected end of file"; 1322 errmsg = "Header line too long to deal with";
1300 goto error; 1323 goto error;
1301 } 1324 }
1302 if (!strcmp(buffer, "---- END SSH2 ENCRYPTED PRIVATE KEY ----\n")) 1325 if (!fgets(p+len-2, sizeof(buffer)-(p-buffer)-(len-2), fp)) {
1303 break; /* done */ 1326 errmsg = "Unexpected end of file";
1304 if ((p = strchr(buffer, ':')) != NULL) { 1327 goto error;
1305 if (headers_done) { 1328 }
1306 errmsg = "Header found in body of key data"; 1329 }
1307 goto error; 1330 p[strcspn(p, "\n")] = '\0';
1308 } 1331 if (!strcmp(buffer, "Comment")) {
1309 *p++ = '\0'; 1332 /* Strip quotes in comment if present. */
1310 while (*p && isspace((unsigned char)*p)) p++; 1333 if (p[0] == '"' && p[strlen(p)-1] == '"') {
1311 /* 1334 p++;
1312 * Header lines can end in a trailing backslash for 1335 p[strlen(p)-1] = '\0';
1313 * continuation. 1336 }
1314 */ 1337 strncpy(ret->comment, p, sizeof(ret->comment));
1315 while ((len = strlen(p)) > (int)(sizeof(buffer) - (p-buffer) -1) || 1338 ret->comment[sizeof(ret->comment)-1] = '\0';
1316 p[len-1] != '\n' || p[len-2] == '\\') { 1339 }
1317 if (len > (int)((p-buffer) + sizeof(buffer)-2)) { 1340 } else {
1318 errmsg = "Header line too long to deal with"; 1341 headers_done = 1;
1319 goto error; 1342
1320 } 1343 p = buffer;
1321 if (!fgets(p+len-2, sizeof(buffer)-(p-buffer)-(len-2), fp)) { 1344 while (isbase64(*p)) {
1322 errmsg = "Unexpected end of file"; 1345 base64_bit[base64_chars++] = *p;
1323 goto error; 1346 if (base64_chars == 4) {
1324 } 1347 unsigned char out[3];
1325 } 1348
1326 p[strcspn(p, "\n")] = '\0'; 1349 base64_chars = 0;
1327 if (!strcmp(buffer, "Comment")) { 1350
1328 /* Strip quotes in comment if present. */ 1351 len = base64_decode_atom(base64_bit, out);
1329 if (p[0] == '"' && p[strlen(p)-1] == '"') { 1352
1330 p++; 1353 if (len <= 0) {
1331 p[strlen(p)-1] = '\0'; 1354 errmsg = "Invalid base64 encoding";
1332 } 1355 goto error;
1333 strncpy(ret->comment, p, sizeof(ret->comment)); 1356 }
1334 ret->comment[sizeof(ret->comment)-1] = '\0'; 1357
1335 } 1358 if (ret->keyblob_len + len > ret->keyblob_size) {
1336 } else { 1359 ret->keyblob_size = ret->keyblob_len + len + 256;
1337 headers_done = 1; 1360 ret->keyblob = sresize(ret->keyblob, ret->keyblob_size,
1338 1361 unsigned char);
1339 p = buffer; 1362 }
1340 while (isbase64(*p)) { 1363
1341 base64_bit[base64_chars++] = *p; 1364 memcpy(ret->keyblob + ret->keyblob_len, out, len);
1342 if (base64_chars == 4) { 1365 ret->keyblob_len += len;
1343 unsigned char out[3]; 1366 }
1344 1367
1345 base64_chars = 0; 1368 p++;
1346 1369 }
1347 len = base64_decode_atom(base64_bit, out); 1370 }
1348 1371 }
1349 if (len <= 0) { 1372
1350 errmsg = "Invalid base64 encoding"; 1373 if (ret->keyblob_len == 0 || !ret->keyblob) {
1351 goto error; 1374 errmsg = "Key body not present";
1352 } 1375 goto error;
1353 1376 }
1354 if (ret->keyblob_len + len > ret->keyblob_size) { 1377
1355 ret->keyblob_size = ret->keyblob_len + len + 256; 1378 return ret;
1356 ret->keyblob = sresize(ret->keyblob, ret->keyblob_size, 1379
1357 unsigned char); 1380 error:
1358 } 1381 if (ret) {
1359 1382 if (ret->keyblob) {
1360 memcpy(ret->keyblob + ret->keyblob_len, out, len); 1383 memset(ret->keyblob, 0, ret->keyblob_size);
1361 ret->keyblob_len += len;
1362 }
1363
1364 p++;
1365 }
1366 }
1367 }
1368
1369 if (ret->keyblob_len == 0 || !ret->keyblob) {
1370 errmsg = "Key body not present";
1371 goto error;
1372 }
1373
1374 return ret;
1375
1376 error:
1377 if (ret) {
1378 if (ret->keyblob) {
1379 memset(ret->keyblob, 0, ret->keyblob_size);
1380 m_free(ret->keyblob); 1384 m_free(ret->keyblob);
1381 } 1385 }
1382 memset(&ret, 0, sizeof(ret)); 1386 memset(ret, 0, sizeof(*ret));
1383 m_free(ret); 1387 m_free(ret);
1384 } 1388 }
1385 return NULL; 1389 return NULL;
1386 } 1390 }
1387 1391
1388 int sshcom_encrypted(const char *filename, char **comment) 1392 int sshcom_encrypted(const char *filename, char **comment)
1389 { 1393 {
1390 struct sshcom_key *key = load_sshcom_key(filename); 1394 struct sshcom_key *key = load_sshcom_key(filename);
1391 int pos, len, answer; 1395 int pos, len, answer;
1392 1396
1393 *comment = NULL; 1397 *comment = NULL;
1394 if (!key) 1398 if (!key)
1395 return 0; 1399 return 0;
1396 1400
1397 /* 1401 /*
1398 * Check magic number. 1402 * Check magic number.
1399 */ 1403 */
1400 if (GET_32BIT(key->keyblob) != 0x3f6ff9eb) 1404 if (GET_32BIT(key->keyblob) != 0x3f6ff9eb)
1401 return 0; /* key is invalid */ 1405 return 0; /* key is invalid */
1402 1406
1403 /* 1407 /*
1404 * Find the cipher-type string. 1408 * Find the cipher-type string.
1405 */ 1409 */
1406 answer = 0; 1410 answer = 0;
1407 pos = 8; 1411 pos = 8;
1408 if (key->keyblob_len < pos+4) 1412 if (key->keyblob_len < pos+4)
1409 goto done; /* key is far too short */ 1413 goto done; /* key is far too short */
1410 pos += 4 + GET_32BIT(key->keyblob + pos); /* skip key type */ 1414 len = toint(GET_32BIT(key->keyblob + pos));
1411 if (key->keyblob_len < pos+4) 1415 if (len < 0 || len > key->keyblob_len - pos - 4)
1412 goto done; /* key is far too short */ 1416 goto done; /* key is far too short */
1413 len = GET_32BIT(key->keyblob + pos); /* find cipher-type length */ 1417 pos += 4 + len; /* skip key type */
1414 if (key->keyblob_len < pos+4+len) 1418 len = toint(GET_32BIT(key->keyblob + pos)); /* find cipher-type length */
1415 goto done; /* cipher type string is incomplete */ 1419 if (len < 0 || len > key->keyblob_len - pos - 4)
1416 if (len != 4 || 0 != memcmp(key->keyblob + pos + 4, "none", 4)) 1420 goto done; /* cipher type string is incomplete */
1417 answer = 1; 1421 if (len != 4 || 0 != memcmp(key->keyblob + pos + 4, "none", 4))
1418 1422 answer = 1;
1419 done: 1423
1420 *comment = dupstr(key->comment); 1424 done:
1421 memset(key->keyblob, 0, key->keyblob_size); 1425 *comment = dupstr(key->comment);
1426 memset(key->keyblob, 0, key->keyblob_size);
1422 m_free(key->keyblob); 1427 m_free(key->keyblob);
1423 memset(&key, 0, sizeof(key)); 1428 memset(key, 0, sizeof(*key));
1424 m_free(key); 1429 m_free(key);
1425 return answer; 1430 return answer;
1426 } 1431 }
1427 1432
1428 static int sshcom_read_mpint(void *data, int len, struct mpint_pos *ret) 1433 static int sshcom_read_mpint(void *data, int len, struct mpint_pos *ret)
1429 { 1434 {
1430 int bits; 1435 unsigned bits, bytes;
1431 int bytes; 1436 unsigned char *d = (unsigned char *) data;
1432 unsigned char *d = (unsigned char *) data; 1437
1433 1438 if (len < 4)
1434 if (len < 4) 1439 goto error;
1435 goto error; 1440 bits = GET_32BIT(d);
1436 bits = GET_32BIT(d); 1441
1437 1442 bytes = (bits + 7) / 8;
1438 bytes = (bits + 7) / 8; 1443 if (len < 4+bytes)
1439 if (len < 4+bytes) 1444 goto error;
1440 goto error; 1445
1441 1446 ret->start = d + 4;
1442 ret->start = d + 4; 1447 ret->bytes = bytes;
1443 ret->bytes = bytes; 1448 return bytes+4;
1444 return bytes+4; 1449
1445 1450 error:
1446 error: 1451 ret->start = NULL;
1447 ret->start = NULL; 1452 ret->bytes = -1;
1448 ret->bytes = -1; 1453 return len; /* ensure further calls fail as well */
1449 return len; /* ensure further calls fail as well */
1450 } 1454 }
1451 1455
1452 static int sshcom_put_mpint(void *target, void *data, int len) 1456 static int sshcom_put_mpint(void *target, void *data, int len)
1453 { 1457 {
1454 unsigned char *d = (unsigned char *)target; 1458 unsigned char *d = (unsigned char *)target;
1455 unsigned char *i = (unsigned char *)data; 1459 unsigned char *i = (unsigned char *)data;
1456 int bits = len * 8 - 1; 1460 int bits = len * 8 - 1;
1457 1461
1458 while (bits > 0) { 1462 while (bits > 0) {
1459 if (*i & (1 << (bits & 7))) 1463 if (*i & (1 << (bits & 7)))
1460 break; 1464 break;
1461 if (!(bits-- & 7)) 1465 if (!(bits-- & 7))
1462 i++, len--; 1466 i++, len--;
1463 } 1467 }
1464 1468
1465 PUT_32BIT(d, bits+1); 1469 PUT_32BIT(d, bits+1);
1466 memcpy(d+4, i, len); 1470 memcpy(d+4, i, len);
1467 return len+4; 1471 return len+4;
1468 } 1472 }
1469 1473
1470 sign_key *sshcom_read(const char *filename, char *passphrase) 1474 sign_key *sshcom_read(const char *filename, char *passphrase)
1471 { 1475 {
1472 struct sshcom_key *key = load_sshcom_key(filename); 1476 struct sshcom_key *key = load_sshcom_key(filename);
1473 char *errmsg; 1477 char *errmsg;
1474 int pos, len; 1478 int pos, len;
1475 const char prefix_rsa[] = "if-modn{sign{rsa"; 1479 const char prefix_rsa[] = "if-modn{sign{rsa";
1476 const char prefix_dsa[] = "dl-modp{sign{dsa"; 1480 const char prefix_dsa[] = "dl-modp{sign{dsa";
1477 enum { RSA, DSA } type; 1481 enum { RSA, DSA } type;
1478 int encrypted; 1482 int encrypted;
1479 char *ciphertext; 1483 char *ciphertext;
1480 int cipherlen; 1484 int cipherlen;
1481 struct ssh2_userkey *ret = NULL, *retkey; 1485 struct ssh2_userkey *ret = NULL, *retkey;
1482 const struct ssh_signkey *alg; 1486 const struct ssh_signkey *alg;
1483 unsigned char *blob = NULL; 1487 unsigned char *blob = NULL;
1484 int blobsize, publen, privlen; 1488 int blobsize = 0, publen, privlen;
1485 1489
1486 if (!key) 1490 if (!key)
1487 return NULL; 1491 return NULL;
1488 1492
1493 /*
1494 * Check magic number.
1495 */
1496 if (GET_32BIT(key->keyblob) != SSHCOM_MAGIC_NUMBER) {
1497 errmsg = "Key does not begin with magic number";
1498 goto error;
1499 }
1500
1501 /*
1502 * Determine the key type.
1503 */
1504 pos = 8;
1505 if (key->keyblob_len < pos+4 ||
1506 (len = GET_32BIT(key->keyblob + pos)) > key->keyblob_len - pos - 4) {
1507 errmsg = "Key blob does not contain a key type string";
1508 goto error;
1509 }
1510 if (len > sizeof(prefix_rsa) - 1 &&
1511 !memcmp(key->keyblob+pos+4, prefix_rsa, sizeof(prefix_rsa) - 1)) {
1512 type = RSA;
1513 } else if (len > sizeof(prefix_dsa) - 1 &&
1514 !memcmp(key->keyblob+pos+4, prefix_dsa, sizeof(prefix_dsa) - 1)) {
1515 type = DSA;
1516 } else {
1517 errmsg = "Key is of unknown type";
1518 goto error;
1519 }
1520 pos += 4+len;
1521
1522 /*
1523 * Determine the cipher type.
1524 */
1525 if (key->keyblob_len < pos+4 ||
1526 (len = GET_32BIT(key->keyblob + pos)) > key->keyblob_len - pos - 4) {
1527 errmsg = "Key blob does not contain a cipher type string";
1528 goto error;
1529 }
1530 if (len == 4 && !memcmp(key->keyblob+pos+4, "none", 4))
1531 encrypted = 0;
1532 else if (len == 8 && !memcmp(key->keyblob+pos+4, "3des-cbc", 8))
1533 encrypted = 1;
1534 else {
1535 errmsg = "Key encryption is of unknown type";
1536 goto error;
1537 }
1538 pos += 4+len;
1539
1540 /*
1541 * Get hold of the encrypted part of the key.
1542 */
1543 if (key->keyblob_len < pos+4 ||
1544 (len = GET_32BIT(key->keyblob + pos)) > key->keyblob_len - pos - 4) {
1545 errmsg = "Key blob does not contain actual key data";
1546 goto error;
1547 }
1548 ciphertext = (char *)key->keyblob + pos + 4;
1549 cipherlen = len;
1550 if (cipherlen == 0) {
1551 errmsg = "Length of key data is zero";
1552 goto error;
1553 }
1554
1555 /*
1556 * Decrypt it if necessary.
1557 */
1558 if (encrypted) {
1489 /* 1559 /*
1490 * Check magic number. 1560 * Derive encryption key from passphrase and iv/salt:
1561 *
1562 * - let block A equal MD5(passphrase)
1563 * - let block B equal MD5(passphrase || A)
1564 * - block C would be MD5(passphrase || A || B) and so on
1565 * - encryption key is the first N bytes of A || B
1491 */ 1566 */
1492 if (GET_32BIT(key->keyblob) != SSHCOM_MAGIC_NUMBER) { 1567 struct MD5Context md5c;
1493 errmsg = "Key does not begin with magic number"; 1568 unsigned char keybuf[32], iv[8];
1494 goto error; 1569
1495 } 1570 if (cipherlen % 8 != 0) {
1571 errmsg = "Encrypted part of key is not a multiple of cipher block"
1572 " size";
1573 goto error;
1574 }
1575
1576 MD5Init(&md5c);
1577 MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase));
1578 MD5Final(keybuf, &md5c);
1579
1580 MD5Init(&md5c);
1581 MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase));
1582 MD5Update(&md5c, keybuf, 16);
1583 MD5Final(keybuf+16, &md5c);
1496 1584
1497 /* 1585 /*
1498 * Determine the key type. 1586 * Now decrypt the key blob.
1499 */ 1587 */
1500 pos = 8; 1588 memset(iv, 0, sizeof(iv));
1501 if (key->keyblob_len < pos+4 || 1589 des3_decrypt_pubkey_ossh(keybuf, iv, (unsigned char *)ciphertext,
1502 (len = GET_32BIT(key->keyblob + pos)) > key->keyblob_len - pos - 4) { 1590 cipherlen);
1503 errmsg = "Key blob does not contain a key type string"; 1591
1504 goto error; 1592 memset(&md5c, 0, sizeof(md5c));
1505 } 1593 memset(keybuf, 0, sizeof(keybuf));
1506 if (len > sizeof(prefix_rsa) - 1 && 1594
1507 !memcmp(key->keyblob+pos+4, prefix_rsa, sizeof(prefix_rsa) - 1)) { 1595 /*
1508 type = RSA; 1596 * Hereafter we return WRONG_PASSPHRASE for any parsing
1509 } else if (len > sizeof(prefix_dsa) - 1 && 1597 * error. (But only if we've just tried to decrypt it!
1510 !memcmp(key->keyblob+pos+4, prefix_dsa, sizeof(prefix_dsa) - 1)) { 1598 * Returning WRONG_PASSPHRASE for an unencrypted key is
1511 type = DSA; 1599 * automatic doom.)
1512 } else { 1600 */
1513 errmsg = "Key is of unknown type"; 1601 if (encrypted)
1514 goto error; 1602 ret = SSH2_WRONG_PASSPHRASE;
1515 } 1603 }
1516 pos += 4+len; 1604
1517 1605 /*
1606 * Strip away the containing string to get to the real meat.
1607 */
1608 len = toint(GET_32BIT(ciphertext));
1609 if (len < 0 || len > cipherlen-4) {
1610 errmsg = "containing string was ill-formed";
1611 goto error;
1612 }
1613 ciphertext += 4;
1614 cipherlen = len;
1615
1616 /*
1617 * Now we break down into RSA versus DSA. In either case we'll
1618 * construct public and private blobs in our own format, and
1619 * end up feeding them to alg->createkey().
1620 */
1621 blobsize = cipherlen + 256;
1622 blob = snewn(blobsize, unsigned char);
1623 privlen = 0;
1624 if (type == RSA) {
1625 struct mpint_pos n, e, d, u, p, q;
1626 int pos = 0;
1627 pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &e);
1628 pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &d);
1629 pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &n);
1630 pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &u);
1631 pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &p);
1632 pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &q);
1633 if (!q.start) {
1634 errmsg = "key data did not contain six integers";
1635 goto error;
1636 }
1637
1638 alg = &ssh_rsa;
1639 pos = 0;
1640 pos += put_string(blob+pos, "ssh-rsa", 7);
1641 pos += put_mp(blob+pos, e.start, e.bytes);
1642 pos += put_mp(blob+pos, n.start, n.bytes);
1643 publen = pos;
1644 pos += put_string(blob+pos, d.start, d.bytes);
1645 pos += put_mp(blob+pos, q.start, q.bytes);
1646 pos += put_mp(blob+pos, p.start, p.bytes);
1647 pos += put_mp(blob+pos, u.start, u.bytes);
1648 privlen = pos - publen;
1649 } else if (type == DSA) {
1650 struct mpint_pos p, q, g, x, y;
1651 int pos = 4;
1652 if (GET_32BIT(ciphertext) != 0) {
1653 errmsg = "predefined DSA parameters not supported";
1654 goto error;
1655 }
1656 pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &p);
1657 pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &g);
1658 pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &q);
1659 pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &y);
1660 pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &x);
1661 if (!x.start) {
1662 errmsg = "key data did not contain five integers";
1663 goto error;
1664 }
1665
1666 alg = &ssh_dss;
1667 pos = 0;
1668 pos += put_string(blob+pos, "ssh-dss", 7);
1669 pos += put_mp(blob+pos, p.start, p.bytes);
1670 pos += put_mp(blob+pos, q.start, q.bytes);
1671 pos += put_mp(blob+pos, g.start, g.bytes);
1672 pos += put_mp(blob+pos, y.start, y.bytes);
1673 publen = pos;
1674 pos += put_mp(blob+pos, x.start, x.bytes);
1675 privlen = pos - publen;
1676 } else
1677 return NULL;
1678
1679 dropbear_assert(privlen > 0); /* should have bombed by now if not */
1680
1681 retkey = snew(struct ssh2_userkey);
1682 retkey->alg = alg;
1683 retkey->data = alg->createkey(blob, publen, blob+publen, privlen);
1684 if (!retkey->data) {
1685 m_free(retkey);
1686 errmsg = "unable to create key data structure";
1687 goto error;
1688 }
1689 retkey->comment = dupstr(key->comment);
1690
1691 errmsg = NULL; /* no error */
1692 ret = retkey;
1693
1694 error:
1695 if (blob) {
1696 memset(blob, 0, blobsize);
1697 m_free(blob);
1698 }
1699 memset(key->keyblob, 0, key->keyblob_size);
1700 m_free(key->keyblob);
1701 memset(key, 0, sizeof(*key));
1702 m_free(key);
1703 return ret;
1704 }
1705
1706 int sshcom_write(const char *filename, sign_key *key,
1707 char *passphrase)
1708 {
1709 unsigned char *pubblob, *privblob;
1710 int publen, privlen;
1711 unsigned char *outblob;
1712 int outlen;
1713 struct mpint_pos numbers[6];
1714 int nnumbers, initial_zero, pos, lenpos, i;
1715 char *type;
1716 char *ciphertext;
1717 int cipherlen;
1718 int ret = 0;
1719 FILE *fp;
1720
1721 /*
1722 * Fetch the key blobs.
1723 */
1724 pubblob = key->alg->public_blob(key->data, &publen);
1725 privblob = key->alg->private_blob(key->data, &privlen);
1726 outblob = NULL;
1727
1728 /*
1729 * Find the sequence of integers to be encoded into the OpenSSH
1730 * key blob, and also decide on the header line.
1731 */
1732 if (key->alg == &ssh_rsa) {
1733 int pos;
1734 struct mpint_pos n, e, d, p, q, iqmp;
1735
1736 pos = 4 + GET_32BIT(pubblob);
1737 pos += ssh2_read_mpint(pubblob+pos, publen-pos, &e);
1738 pos += ssh2_read_mpint(pubblob+pos, publen-pos, &n);
1739 pos = 0;
1740 pos += ssh2_read_mpint(privblob+pos, privlen-pos, &d);
1741 pos += ssh2_read_mpint(privblob+pos, privlen-pos, &p);
1742 pos += ssh2_read_mpint(privblob+pos, privlen-pos, &q);
1743 pos += ssh2_read_mpint(privblob+pos, privlen-pos, &iqmp);
1744
1745 dropbear_assert(e.start && iqmp.start); /* can't go wrong */
1746
1747 numbers[0] = e;
1748 numbers[1] = d;
1749 numbers[2] = n;
1750 numbers[3] = iqmp;
1751 numbers[4] = q;
1752 numbers[5] = p;
1753
1754 nnumbers = 6;
1755 initial_zero = 0;
1756 type = "if-modn{sign{rsa-pkcs1-sha1},encrypt{rsa-pkcs1v2-oaep}}";
1757 } else if (key->alg == &ssh_dss) {
1758 int pos;
1759 struct mpint_pos p, q, g, y, x;
1760
1761 pos = 4 + GET_32BIT(pubblob);
1762 pos += ssh2_read_mpint(pubblob+pos, publen-pos, &p);
1763 pos += ssh2_read_mpint(pubblob+pos, publen-pos, &q);
1764 pos += ssh2_read_mpint(pubblob+pos, publen-pos, &g);
1765 pos += ssh2_read_mpint(pubblob+pos, publen-pos, &y);
1766 pos = 0;
1767 pos += ssh2_read_mpint(privblob+pos, privlen-pos, &x);
1768
1769 dropbear_assert(y.start && x.start); /* can't go wrong */
1770
1771 numbers[0] = p;
1772 numbers[1] = g;
1773 numbers[2] = q;
1774 numbers[3] = y;
1775 numbers[4] = x;
1776
1777 nnumbers = 5;
1778 initial_zero = 1;
1779 type = "dl-modp{sign{dsa-nist-sha1},dh{plain}}";
1780 } else {
1781 dropbear_assert(0); /* zoinks! */
1782 }
1783
1784 /*
1785 * Total size of key blob will be somewhere under 512 plus
1786 * combined length of integers. We'll calculate the more
1787 * precise size as we construct the blob.
1788 */
1789 outlen = 512;
1790 for (i = 0; i < nnumbers; i++)
1791 outlen += 4 + numbers[i].bytes;
1792 outblob = snewn(outlen, unsigned char);
1793
1794 /*
1795 * Create the unencrypted key blob.
1796 */
1797 pos = 0;
1798 PUT_32BIT(outblob+pos, SSHCOM_MAGIC_NUMBER); pos += 4;
1799 pos += 4; /* length field, fill in later */
1800 pos += put_string(outblob+pos, type, strlen(type));
1801 {
1802 char *ciphertype = passphrase ? "3des-cbc" : "none";
1803 pos += put_string(outblob+pos, ciphertype, strlen(ciphertype));
1804 }
1805 lenpos = pos; /* remember this position */
1806 pos += 4; /* encrypted-blob size */
1807 pos += 4; /* encrypted-payload size */
1808 if (initial_zero) {
1809 PUT_32BIT(outblob+pos, 0);
1810 pos += 4;
1811 }
1812 for (i = 0; i < nnumbers; i++)
1813 pos += sshcom_put_mpint(outblob+pos,
1814 numbers[i].start, numbers[i].bytes);
1815 /* Now wrap up the encrypted payload. */
1816 PUT_32BIT(outblob+lenpos+4, pos - (lenpos+8));
1817 /* Pad encrypted blob to a multiple of cipher block size. */
1818 if (passphrase) {
1819 int padding = -(pos - (lenpos+4)) & 7;
1820 while (padding--)
1821 outblob[pos++] = random_byte();
1822 }
1823 ciphertext = (char *)outblob+lenpos+4;
1824 cipherlen = pos - (lenpos+4);
1825 dropbear_assert(!passphrase || cipherlen % 8 == 0);
1826 /* Wrap up the encrypted blob string. */
1827 PUT_32BIT(outblob+lenpos, cipherlen);
1828 /* And finally fill in the total length field. */
1829 PUT_32BIT(outblob+4, pos);
1830
1831 dropbear_assert(pos < outlen);
1832
1833 /*
1834 * Encrypt the key.
1835 */
1836 if (passphrase) {
1518 /* 1837 /*
1519 * Determine the cipher type. 1838 * Derive encryption key from passphrase and iv/salt:
1839 *
1840 * - let block A equal MD5(passphrase)
1841 * - let block B equal MD5(passphrase || A)
1842 * - block C would be MD5(passphrase || A || B) and so on
1843 * - encryption key is the first N bytes of A || B
1520 */ 1844 */
1521 if (key->keyblob_len < pos+4 || 1845 struct MD5Context md5c;
1522 (len = GET_32BIT(key->keyblob + pos)) > key->keyblob_len - pos - 4) { 1846 unsigned char keybuf[32], iv[8];
1523 errmsg = "Key blob does not contain a cipher type string"; 1847
1524 goto error; 1848 MD5Init(&md5c);
1525 } 1849 MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase));
1526 if (len == 4 && !memcmp(key->keyblob+pos+4, "none", 4)) 1850 MD5Final(keybuf, &md5c);
1527 encrypted = 0; 1851
1528 else if (len == 8 && !memcmp(key->keyblob+pos+4, "3des-cbc", 8)) 1852 MD5Init(&md5c);
1529 encrypted = 1; 1853 MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase));
1530 else { 1854 MD5Update(&md5c, keybuf, 16);
1531 errmsg = "Key encryption is of unknown type"; 1855 MD5Final(keybuf+16, &md5c);
1532 goto error;
1533 }
1534 pos += 4+len;
1535 1856
1536 /* 1857 /*
1537 * Get hold of the encrypted part of the key. 1858 * Now decrypt the key blob.
1538 */ 1859 */
1539 if (key->keyblob_len < pos+4 || 1860 memset(iv, 0, sizeof(iv));
1540 (len = GET_32BIT(key->keyblob + pos)) > key->keyblob_len - pos - 4) { 1861 des3_encrypt_pubkey_ossh(keybuf, iv, (unsigned char *)ciphertext,
1541 errmsg = "Key blob does not contain actual key data"; 1862 cipherlen);
1542 goto error; 1863
1543 } 1864 memset(&md5c, 0, sizeof(md5c));
1544 ciphertext = (char *)key->keyblob + pos + 4; 1865 memset(keybuf, 0, sizeof(keybuf));
1545 cipherlen = len; 1866 }
1546 if (cipherlen == 0) { 1867
1547 errmsg = "Length of key data is zero"; 1868 /*
1548 goto error; 1869 * And save it. We'll use Unix line endings just in case it's
1549 } 1870 * subsequently transferred in binary mode.
1550 1871 */
1551 /*
1552 * Decrypt it if necessary.
1553 */
1554 if (encrypted) {
1555 /*
1556 * Derive encryption key from passphrase and iv/salt:
1557 *
1558 * - let block A equal MD5(passphrase)
1559 * - let block B equal MD5(passphrase || A)
1560 * - block C would be MD5(passphrase || A || B) and so on
1561 * - encryption key is the first N bytes of A || B
1562 */
1563 struct MD5Context md5c;
1564 unsigned char keybuf[32], iv[8];
1565
1566 if (cipherlen % 8 != 0) {
1567 errmsg = "Encrypted part of key is not a multiple of cipher block"
1568 " size";
1569 goto error;
1570 }
1571
1572 MD5Init(&md5c);
1573 MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase));
1574 MD5Final(keybuf, &md5c);
1575
1576 MD5Init(&md5c);
1577 MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase));
1578 MD5Update(&md5c, keybuf, 16);
1579 MD5Final(keybuf+16, &md5c);
1580
1581 /*
1582 * Now decrypt the key blob.
1583 */
1584 memset(iv, 0, sizeof(iv));
1585 des3_decrypt_pubkey_ossh(keybuf, iv, (unsigned char *)ciphertext,
1586 cipherlen);
1587
1588 memset(&md5c, 0, sizeof(md5c));
1589 memset(keybuf, 0, sizeof(keybuf));
1590
1591 /*
1592 * Hereafter we return WRONG_PASSPHRASE for any parsing
1593 * error. (But only if we've just tried to decrypt it!
1594 * Returning WRONG_PASSPHRASE for an unencrypted key is
1595 * automatic doom.)
1596 */
1597 if (encrypted)
1598 ret = SSH2_WRONG_PASSPHRASE;
1599 }
1600
1601 /*
1602 * Strip away the containing string to get to the real meat.
1603 */
1604 len = GET_32BIT(ciphertext);
1605 if (len > cipherlen-4) {
1606 errmsg = "containing string was ill-formed";
1607 goto error;
1608 }
1609 ciphertext += 4;
1610 cipherlen = len;
1611
1612 /*
1613 * Now we break down into RSA versus DSA. In either case we'll
1614 * construct public and private blobs in our own format, and
1615 * end up feeding them to alg->createkey().
1616 */
1617 blobsize = cipherlen + 256;
1618 blob = snewn(blobsize, unsigned char);
1619 privlen = 0;
1620 if (type == RSA) {
1621 struct mpint_pos n, e, d, u, p, q;
1622 int pos = 0;
1623 pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &e);
1624 pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &d);
1625 pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &n);
1626 pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &u);
1627 pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &p);
1628 pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &q);
1629 if (!q.start) {
1630 errmsg = "key data did not contain six integers";
1631 goto error;
1632 }
1633
1634 alg = &ssh_rsa;
1635 pos = 0;
1636 pos += put_string(blob+pos, "ssh-rsa", 7);
1637 pos += put_mp(blob+pos, e.start, e.bytes);
1638 pos += put_mp(blob+pos, n.start, n.bytes);
1639 publen = pos;
1640 pos += put_string(blob+pos, d.start, d.bytes);
1641 pos += put_mp(blob+pos, q.start, q.bytes);
1642 pos += put_mp(blob+pos, p.start, p.bytes);
1643 pos += put_mp(blob+pos, u.start, u.bytes);
1644 privlen = pos - publen;
1645 } else if (type == DSA) {
1646 struct mpint_pos p, q, g, x, y;
1647 int pos = 4;
1648 if (GET_32BIT(ciphertext) != 0) {
1649 errmsg = "predefined DSA parameters not supported";
1650 goto error;
1651 }
1652 pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &p);
1653 pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &g);
1654 pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &q);
1655 pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &y);
1656 pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &x);
1657 if (!x.start) {
1658 errmsg = "key data did not contain five integers";
1659 goto error;
1660 }
1661
1662 alg = &ssh_dss;
1663 pos = 0;
1664 pos += put_string(blob+pos, "ssh-dss", 7);
1665 pos += put_mp(blob+pos, p.start, p.bytes);
1666 pos += put_mp(blob+pos, q.start, q.bytes);
1667 pos += put_mp(blob+pos, g.start, g.bytes);
1668 pos += put_mp(blob+pos, y.start, y.bytes);
1669 publen = pos;
1670 pos += put_mp(blob+pos, x.start, x.bytes);
1671 privlen = pos - publen;
1672 }
1673
1674 dropbear_assert(privlen > 0); /* should have bombed by now if not */
1675
1676 retkey = snew(struct ssh2_userkey);
1677 retkey->alg = alg;
1678 retkey->data = alg->createkey(blob, publen, blob+publen, privlen);
1679 if (!retkey->data) {
1680 m_free(retkey);
1681 errmsg = "unable to create key data structure";
1682 goto error;
1683 }
1684 retkey->comment = dupstr(key->comment);
1685
1686 errmsg = NULL; /* no error */
1687 ret = retkey;
1688
1689 error:
1690 if (blob) {
1691 memset(blob, 0, blobsize);
1692 m_free(blob);
1693 }
1694 memset(key->keyblob, 0, key->keyblob_size);
1695 m_free(key->keyblob);
1696 memset(&key, 0, sizeof(key));
1697 m_free(key);
1698 return ret;
1699 }
1700
1701 int sshcom_write(const char *filename, sign_key *key,
1702 char *passphrase)
1703 {
1704 unsigned char *pubblob, *privblob;
1705 int publen, privlen;
1706 unsigned char *outblob;
1707 int outlen;
1708 struct mpint_pos numbers[6];
1709 int nnumbers, initial_zero, pos, lenpos, i;
1710 char *type;
1711 char *ciphertext;
1712 int cipherlen;
1713 int ret = 0;
1714 FILE *fp;
1715
1716 /*
1717 * Fetch the key blobs.
1718 */
1719 pubblob = key->alg->public_blob(key->data, &publen);
1720 privblob = key->alg->private_blob(key->data, &privlen);
1721 outblob = NULL;
1722
1723 /*
1724 * Find the sequence of integers to be encoded into the OpenSSH
1725 * key blob, and also decide on the header line.
1726 */
1727 if (key->alg == &ssh_rsa) {
1728 int pos;
1729 struct mpint_pos n, e, d, p, q, iqmp;
1730
1731 pos = 4 + GET_32BIT(pubblob);
1732 pos += ssh2_read_mpint(pubblob+pos, publen-pos, &e);
1733 pos += ssh2_read_mpint(pubblob+pos, publen-pos, &n);
1734 pos = 0;
1735 pos += ssh2_read_mpint(privblob+pos, privlen-pos, &d);
1736 pos += ssh2_read_mpint(privblob+pos, privlen-pos, &p);
1737 pos += ssh2_read_mpint(privblob+pos, privlen-pos, &q);
1738 pos += ssh2_read_mpint(privblob+pos, privlen-pos, &iqmp);
1739
1740 dropbear_assert(e.start && iqmp.start); /* can't go wrong */
1741
1742 numbers[0] = e;
1743 numbers[1] = d;
1744 numbers[2] = n;
1745 numbers[3] = iqmp;
1746 numbers[4] = q;
1747 numbers[5] = p;
1748
1749 nnumbers = 6;
1750 initial_zero = 0;
1751 type = "if-modn{sign{rsa-pkcs1-sha1},encrypt{rsa-pkcs1v2-oaep}}";
1752 } else if (key->alg == &ssh_dss) {
1753 int pos;
1754 struct mpint_pos p, q, g, y, x;
1755
1756 pos = 4 + GET_32BIT(pubblob);
1757 pos += ssh2_read_mpint(pubblob+pos, publen-pos, &p);
1758 pos += ssh2_read_mpint(pubblob+pos, publen-pos, &q);
1759 pos += ssh2_read_mpint(pubblob+pos, publen-pos, &g);
1760 pos += ssh2_read_mpint(pubblob+pos, publen-pos, &y);
1761 pos = 0;
1762 pos += ssh2_read_mpint(privblob+pos, privlen-pos, &x);
1763
1764 dropbear_assert(y.start && x.start); /* can't go wrong */
1765
1766 numbers[0] = p;
1767 numbers[1] = g;
1768 numbers[2] = q;
1769 numbers[3] = y;
1770 numbers[4] = x;
1771
1772 nnumbers = 5;
1773 initial_zero = 1;
1774 type = "dl-modp{sign{dsa-nist-sha1},dh{plain}}";
1775 } else {
1776 dropbear_assert(0); /* zoinks! */
1777 }
1778
1779 /*
1780 * Total size of key blob will be somewhere under 512 plus
1781 * combined length of integers. We'll calculate the more
1782 * precise size as we construct the blob.
1783 */
1784 outlen = 512;
1785 for (i = 0; i < nnumbers; i++)
1786 outlen += 4 + numbers[i].bytes;
1787 outblob = snewn(outlen, unsigned char);
1788
1789 /*
1790 * Create the unencrypted key blob.
1791 */
1792 pos = 0;
1793 PUT_32BIT(outblob+pos, SSHCOM_MAGIC_NUMBER); pos += 4;
1794 pos += 4; /* length field, fill in later */
1795 pos += put_string(outblob+pos, type, strlen(type));
1796 {
1797 char *ciphertype = passphrase ? "3des-cbc" : "none";
1798 pos += put_string(outblob+pos, ciphertype, strlen(ciphertype));
1799 }
1800 lenpos = pos; /* remember this position */
1801 pos += 4; /* encrypted-blob size */
1802 pos += 4; /* encrypted-payload size */
1803 if (initial_zero) {
1804 PUT_32BIT(outblob+pos, 0);
1805 pos += 4;
1806 }
1807 for (i = 0; i < nnumbers; i++)
1808 pos += sshcom_put_mpint(outblob+pos,
1809 numbers[i].start, numbers[i].bytes);
1810 /* Now wrap up the encrypted payload. */
1811 PUT_32BIT(outblob+lenpos+4, pos - (lenpos+8));
1812 /* Pad encrypted blob to a multiple of cipher block size. */
1813 if (passphrase) {
1814 int padding = -(pos - (lenpos+4)) & 7;
1815 while (padding--)
1816 outblob[pos++] = random_byte();
1817 }
1818 ciphertext = (char *)outblob+lenpos+4;
1819 cipherlen = pos - (lenpos+4);
1820 dropbear_assert(!passphrase || cipherlen % 8 == 0);
1821 /* Wrap up the encrypted blob string. */
1822 PUT_32BIT(outblob+lenpos, cipherlen);
1823 /* And finally fill in the total length field. */
1824 PUT_32BIT(outblob+4, pos);
1825
1826 dropbear_assert(pos < outlen);
1827
1828 /*
1829 * Encrypt the key.
1830 */
1831 if (passphrase) {
1832 /*
1833 * Derive encryption key from passphrase and iv/salt:
1834 *
1835 * - let block A equal MD5(passphrase)
1836 * - let block B equal MD5(passphrase || A)
1837 * - block C would be MD5(passphrase || A || B) and so on
1838 * - encryption key is the first N bytes of A || B
1839 */
1840 struct MD5Context md5c;
1841 unsigned char keybuf[32], iv[8];
1842
1843 MD5Init(&md5c);
1844 MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase));
1845 MD5Final(keybuf, &md5c);
1846
1847 MD5Init(&md5c);
1848 MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase));
1849 MD5Update(&md5c, keybuf, 16);
1850 MD5Final(keybuf+16, &md5c);
1851
1852 /*
1853 * Now decrypt the key blob.
1854 */
1855 memset(iv, 0, sizeof(iv));
1856 des3_encrypt_pubkey_ossh(keybuf, iv, (unsigned char *)ciphertext,
1857 cipherlen);
1858
1859 memset(&md5c, 0, sizeof(md5c));
1860 memset(keybuf, 0, sizeof(keybuf));
1861 }
1862
1863 /*
1864 * And save it. We'll use Unix line endings just in case it's
1865 * subsequently transferred in binary mode.
1866 */
1867 fp = fopen(filename, "wb"); /* ensure Unix line endings */ 1872 fp = fopen(filename, "wb"); /* ensure Unix line endings */
1868 if (!fp) 1873 if (!fp)
1869 goto error; 1874 goto error;
1870 fputs("---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----\n", fp); 1875 fputs("---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----\n", fp);
1871 fprintf(fp, "Comment: \""); 1876 fprintf(fp, "Comment: \"");
1872 /* 1877 /*
1873 * Comment header is broken with backslash-newline if it goes 1878 * Comment header is broken with backslash-newline if it goes
1874 * over 70 chars. Although it's surrounded by quotes, it 1879 * over 70 chars. Although it's surrounded by quotes, it
1875 * _doesn't_ escape backslashes or quotes within the string. 1880 * _doesn't_ escape backslashes or quotes within the string.
1876 * Don't ask me, I didn't design it. 1881 * Don't ask me, I didn't design it.
1877 */ 1882 */
1878 { 1883 {
1879 int slen = 60; /* starts at 60 due to "Comment: " */ 1884 int slen = 60; /* starts at 60 due to "Comment: " */
1880 char *c = key->comment; 1885 char *c = key->comment;
1881 while ((int)strlen(c) > slen) { 1886 while ((int)strlen(c) > slen) {
1882 fprintf(fp, "%.*s\\\n", slen, c); 1887 fprintf(fp, "%.*s\\\n", slen, c);
1883 c += slen; 1888 c += slen;
1884 slen = 70; /* allow 70 chars on subsequent lines */ 1889 slen = 70; /* allow 70 chars on subsequent lines */
1885 } 1890 }
1886 fprintf(fp, "%s\"\n", c); 1891 fprintf(fp, "%s\"\n", c);
1887 } 1892 }
1888 base64_encode_fp(fp, outblob, pos, 70); 1893 base64_encode_fp(fp, outblob, pos, 70);
1889 fputs("---- END SSH2 ENCRYPTED PRIVATE KEY ----\n", fp); 1894 fputs("---- END SSH2 ENCRYPTED PRIVATE KEY ----\n", fp);
1890 fclose(fp); 1895 fclose(fp);
1891 ret = 1; 1896 ret = 1;
1892 1897
1893 error: 1898 error:
1894 if (outblob) { 1899 if (outblob) {
1895 memset(outblob, 0, outlen); 1900 memset(outblob, 0, outlen);
1896 m_free(outblob); 1901 m_free(outblob);
1897 } 1902 }
1898 if (privblob) { 1903 if (privblob) {
1899 memset(privblob, 0, privlen); 1904 memset(privblob, 0, privlen);
1900 m_free(privblob); 1905 m_free(privblob);
1901 } 1906 }
1902 if (pubblob) { 1907 if (pubblob) {
1903 memset(pubblob, 0, publen); 1908 memset(pubblob, 0, publen);
1904 m_free(pubblob); 1909 m_free(pubblob);
1905 } 1910 }
1906 return ret; 1911 return ret;
1907 } 1912 }
1908 #endif /* ssh.com stuff disabled */ 1913 #endif /* ssh.com stuff disabled */
1914
1915 /* From PuTTY misc.c */
1916 static int toint(unsigned u)
1917 {
1918 /*
1919 * Convert an unsigned to an int, without running into the
1920 * undefined behaviour which happens by the strict C standard if
1921 * the value overflows. You'd hope that sensible compilers would
1922 * do the sensible thing in response to a cast, but actually I
1923 * don't trust modern compilers not to do silly things like
1924 * assuming that _obviously_ you wouldn't have caused an overflow
1925 * and so they can elide an 'if (i < 0)' test immediately after
1926 * the cast.
1927 *
1928 * Sensible compilers ought of course to optimise this entire
1929 * function into 'just return the input value'!
1930 */
1931 if (u <= (unsigned)INT_MAX)
1932 return (int)u;
1933 else if (u >= (unsigned)INT_MIN) /* wrap in cast _to_ unsigned is OK */
1934 return INT_MIN + (int)(u - (unsigned)INT_MIN);
1935 else
1936 return INT_MIN; /* fallback; should never occur on binary machines */
1937 }