]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - import.c
Implemented export of OpenSSH keys.
[PuTTY.git] / import.c
1 /*
2  * Code for PuTTY to import and export private key files in other
3  * SSH clients' formats.
4  */
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <assert.h>
9 #include <ctype.h>
10
11 #include "ssh.h"
12 #include "misc.h"
13
14 #define PUT_32BIT(cp, value) do { \
15   (cp)[3] = (value); \
16   (cp)[2] = (value) >> 8; \
17   (cp)[1] = (value) >> 16; \
18   (cp)[0] = (value) >> 24; } while (0)
19
20 #define GET_32BIT(cp) \
21     (((unsigned long)(unsigned char)(cp)[0] << 24) | \
22     ((unsigned long)(unsigned char)(cp)[1] << 16) | \
23     ((unsigned long)(unsigned char)(cp)[2] << 8) | \
24     ((unsigned long)(unsigned char)(cp)[3]))
25
26 int openssh_encrypted(char *filename);
27 struct ssh2_userkey *openssh_read(char *filename, char *passphrase);
28 int openssh_write(char *filename, struct ssh2_userkey *key, char *passphrase);
29
30 int sshcom_encrypted(char *filename, char **comment);
31 struct ssh2_userkey *sshcom_read(char *filename, char *passphrase);
32
33 /*
34  * Given a key type, determine whether we know how to import it.
35  */
36 int import_possible(int type)
37 {
38     if (type == SSH_KEYTYPE_OPENSSH)
39         return 1;
40     if (type == SSH_KEYTYPE_SSHCOM)
41         return 1;
42     return 0;
43 }
44
45 /*
46  * Given a key type, determine what native key type
47  * (SSH_KEYTYPE_SSH1 or SSH_KEYTYPE_SSH2) it will come out as once
48  * we've imported it.
49  */
50 int import_target_type(int type)
51 {
52     /*
53      * There are no known foreign SSH1 key formats.
54      */
55     return SSH_KEYTYPE_SSH2;
56 }
57
58 /*
59  * Determine whether a foreign key is encrypted.
60  */
61 int import_encrypted(char *filename, int type, char **comment)
62 {
63     if (type == SSH_KEYTYPE_OPENSSH) {
64         *comment = filename;           /* OpenSSH doesn't do key comments */
65         return openssh_encrypted(filename);
66     }
67     if (type == SSH_KEYTYPE_SSHCOM) {
68         return sshcom_encrypted(filename, comment);
69     }
70     return 0;
71 }
72
73 /*
74  * Import an SSH1 key.
75  */
76 int import_ssh1(char *filename, int type, struct RSAKey *key, char *passphrase)
77 {
78     return 0;
79 }
80
81 /*
82  * Import an SSH2 key.
83  */
84 struct ssh2_userkey *import_ssh2(char *filename, int type, char *passphrase)
85 {
86     if (type == SSH_KEYTYPE_OPENSSH)
87         return openssh_read(filename, passphrase);
88     if (type == SSH_KEYTYPE_SSHCOM)
89         return sshcom_read(filename, passphrase);
90     return NULL;
91 }
92
93 /*
94  * Export an SSH1 key.
95  */
96 int export_ssh1(char *filename, int type, struct RSAKey *key, char *passphrase)
97 {
98     return 0;
99 }
100
101 /*
102  * Export an SSH2 key.
103  */
104 int export_ssh2(char *filename, int type,
105                 struct ssh2_userkey *key, char *passphrase)
106 {
107     if (type == SSH_KEYTYPE_OPENSSH)
108         return openssh_write(filename, key, passphrase);
109 #if 0
110     if (type == SSH_KEYTYPE_SSHCOM)
111         return sshcom_write(filename, key, passphrase);
112 #endif
113     return 0;
114 }
115
116 /* ----------------------------------------------------------------------
117  * Helper routines. (The base64 ones are defined in sshpubk.c.)
118  */
119
120 #define isbase64(c) (    ((c) >= 'A' && (c) <= 'Z') || \
121                          ((c) >= 'a' && (c) <= 'z') || \
122                          ((c) >= '0' && (c) <= '9') || \
123                          (c) == '+' || (c) == '/' || (c) == '=' \
124                          )
125
126 extern int base64_decode_atom(char *atom, unsigned char *out);
127 extern int base64_lines(int datalen);
128 extern void base64_encode_atom(unsigned char *data, int n, char *out);
129 extern void base64_encode(FILE *fp, unsigned char *data, int datalen);
130
131 /*
132  * Read an ASN.1/BER identifier and length pair.
133  * 
134  * Flags are a combination of the #defines listed below.
135  * 
136  * Returns -1 if unsuccessful; otherwise returns the number of
137  * bytes used out of the source data.
138  */
139
140 /* ASN.1 tag classes. */
141 #define ASN1_CLASS_UNIVERSAL        (0 << 6)
142 #define ASN1_CLASS_APPLICATION      (1 << 6)
143 #define ASN1_CLASS_CONTEXT_SPECIFIC (2 << 6)
144 #define ASN1_CLASS_PRIVATE          (3 << 6)
145 #define ASN1_CLASS_MASK             (3 << 6)
146
147 /* Primitive versus constructed bit. */
148 #define ASN1_CONSTRUCTED            (1 << 5)
149
150 int ber_read_id_len(void *source, int sourcelen,
151                     int *id, int *length, int *flags)
152 {
153     unsigned char *p = (unsigned char *) source;
154
155     if (sourcelen == 0)
156         return -1;
157
158     *flags = (*p & 0xE0);
159     if ((*p & 0x1F) == 0x1F) {
160         *id = 0;
161         while (*p & 0x80) {
162             *id = (*id << 7) | (*p & 0x7F);
163             p++, sourcelen--;
164             if (sourcelen == 0)
165                 return -1;
166         }
167         *id = (*id << 7) | (*p & 0x7F);
168         p++, sourcelen--;
169     } else {
170         *id = *p & 0x1F;
171         p++, sourcelen--;
172     }
173
174     if (sourcelen == 0)
175         return -1;
176
177     if (*p & 0x80) {
178         int n = *p & 0x7F;
179         p++, sourcelen--;
180         if (sourcelen < n)
181             return -1;
182         *length = 0;
183         while (n--)
184             *length = (*length << 8) | (*p++);
185         sourcelen -= n;
186     } else {
187         *length = *p;
188         p++, sourcelen--;
189     }
190
191     return p - (unsigned char *) source;
192 }
193
194 /*
195  * Write an ASN.1/BER identifier and length pair. Returns the
196  * number of bytes consumed. Assumes dest contains enough space.
197  * Will avoid writing anything if dest is NULL, but still return
198  * amount of space required.
199  */
200 int ber_write_id_len(void *dest, int id, int length, int flags)
201 {
202     unsigned char *d = (unsigned char *)dest;
203     int len = 0;
204
205     if (id <= 30) {
206         /*
207          * Identifier is one byte.
208          */
209         len++;
210         if (d) *d++ = id | flags;
211     } else {
212         int n;
213         /*
214          * Identifier is multiple bytes: the first byte is 11111
215          * plus the flags, and subsequent bytes encode the value of
216          * the identifier, 7 bits at a time, with the top bit of
217          * each byte 1 except the last one which is 0.
218          */
219         len++;
220         if (d) *d++ = 0x1F | flags;
221         for (n = 1; (id >> (7*n)) > 0; n++)
222             continue;                  /* count the bytes */
223         while (n--) {
224             len++;
225             if (d) *d++ = (n ? 0x80 : 0) | ((id >> (7*n)) & 0x7F);
226         }
227     }
228
229     if (length < 128) {
230         /*
231          * Length is one byte.
232          */
233         len++;
234         if (d) *d++ = length;
235     } else {
236         int n;
237         /*
238          * Length is multiple bytes. The first is 0x80 plus the
239          * number of subsequent bytes, and the subsequent bytes
240          * encode the actual length.
241          */
242         for (n = 1; (length >> (8*n)) > 0; n++)
243             continue;                  /* count the bytes */
244         len++;
245         if (d) *d++ = 0x80 | n;
246         while (n--) {
247             len++;
248             if (d) *d++ = (length >> (8*n)) & 0xFF;
249         }
250     }
251
252     return len;
253 }
254
255 static int put_string(void *target, void *data, int len)
256 {
257     unsigned char *d = (unsigned char *)target;
258
259     PUT_32BIT(d, len);
260     memcpy(d+4, data, len);
261     return len+4;
262 }
263
264 static int put_mp(void *target, void *data, int len)
265 {
266     unsigned char *d = (unsigned char *)target;
267     unsigned char *i = (unsigned char *)data;
268
269     if (*i & 0x80) {
270         PUT_32BIT(d, len+1);
271         d[4] = 0;
272         memcpy(d+5, data, len);
273         return len+5;
274     } else {
275         PUT_32BIT(d, len);
276         memcpy(d+4, data, len);
277         return len+4;
278     }
279 }
280
281 /* Simple structure to point to an mp-int within a blob. */
282 struct mpint_pos { void *start; int bytes; };
283
284 int ssh2_read_mpint(void *data, int len, struct mpint_pos *ret)
285 {
286     int bytes;
287     unsigned char *d = (unsigned char *) data;
288
289     if (len < 4)
290         goto error;
291     bytes = GET_32BIT(d);
292     if (len < 4+bytes)
293         goto error;
294
295     ret->start = d + 4;
296     ret->bytes = bytes;
297     return bytes+4;
298
299     error:
300     ret->start = NULL;
301     ret->bytes = -1;
302     return len;                        /* ensure further calls fail as well */
303 }
304
305 /* ----------------------------------------------------------------------
306  * Code to read and write OpenSSH private keys.
307  */
308
309 enum { OSSH_DSA, OSSH_RSA };
310 struct openssh_key {
311     int type;
312     int encrypted;
313     char iv[32];
314     unsigned char *keyblob;
315     int keyblob_len, keyblob_size;
316 };
317
318 struct openssh_key *load_openssh_key(char *filename)
319 {
320     struct openssh_key *ret;
321     FILE *fp;
322     char buffer[256];
323     char *errmsg, *p;
324     int headers_done;
325     char base64_bit[4];
326     int base64_chars = 0;
327
328     ret = smalloc(sizeof(*ret));
329     ret->keyblob = NULL;
330     ret->keyblob_len = ret->keyblob_size = 0;
331     ret->encrypted = 0;
332     memset(ret->iv, 0, sizeof(ret->iv));
333
334     fp = fopen(filename, "r");
335     if (!fp) {
336         errmsg = "Unable to open key file";
337         goto error;
338     }
339     if (!fgets(buffer, sizeof(buffer), fp) ||
340         0 != strncmp(buffer, "-----BEGIN ", 11) ||
341         0 != strcmp(buffer+strlen(buffer)-17, "PRIVATE KEY-----\n")) {
342         errmsg = "File does not begin with OpenSSH key header";
343         goto error;
344     }
345     if (!strcmp(buffer, "-----BEGIN RSA PRIVATE KEY-----\n"))
346         ret->type = OSSH_RSA;
347     else if (!strcmp(buffer, "-----BEGIN DSA PRIVATE KEY-----\n"))
348         ret->type = OSSH_DSA;
349     else {
350         errmsg = "Unrecognised key type";
351         goto error;
352     }
353
354     headers_done = 0;
355     while (1) {
356         if (!fgets(buffer, sizeof(buffer), fp)) {
357             errmsg = "Unexpected end of file";
358             goto error;
359         }
360         if (0 == strncmp(buffer, "-----END ", 9) &&
361             0 == strcmp(buffer+strlen(buffer)-17, "PRIVATE KEY-----\n"))
362             break;                     /* done */
363         if ((p = strchr(buffer, ':')) != NULL) {
364             if (headers_done) {
365                 errmsg = "Header found in body of key data";
366                 goto error;
367             }
368             *p++ = '\0';
369             while (*p && isspace((unsigned char)*p)) p++;
370             if (!strcmp(buffer, "Proc-Type")) {
371                 if (p[0] != '4' || p[1] != ',') {
372                     errmsg = "Proc-Type is not 4 (only 4 is supported)";
373                     goto error;
374                 }
375                 p += 2;
376                 if (!strcmp(p, "ENCRYPTED\n"))
377                     ret->encrypted = 1;
378             } else if (!strcmp(buffer, "DEK-Info")) {
379                 int i, j;
380
381                 if (strncmp(p, "DES-EDE3-CBC,", 13)) {
382                     errmsg = "Ciphers other than DES-EDE3-CBC not supported";
383                     goto error;
384                 }
385                 p += 13;
386                 for (i = 0; i < 8; i++) {
387                     if (1 != sscanf(p, "%2x", &j))
388                         break;
389                     ret->iv[i] = j;
390                     p += 2;
391                 }
392                 if (i < 8) {
393                     errmsg = "Expected 16-digit iv in DEK-Info";
394                     goto error;
395                 }
396             }
397         } else {
398             headers_done = 1;
399
400             p = buffer;
401             while (isbase64(*p)) {
402                 base64_bit[base64_chars++] = *p;
403                 if (base64_chars == 4) {
404                     unsigned char out[3];
405                     int len;
406
407                     base64_chars = 0;
408
409                     len = base64_decode_atom(base64_bit, out);
410
411                     if (len <= 0) {
412                         errmsg = "Invalid base64 encoding";
413                         goto error;
414                     }
415
416                     if (ret->keyblob_len + len > ret->keyblob_size) {
417                         ret->keyblob_size = ret->keyblob_len + len + 256;
418                         ret->keyblob = srealloc(ret->keyblob, ret->keyblob_size);
419                     }
420
421                     memcpy(ret->keyblob + ret->keyblob_len, out, len);
422                     ret->keyblob_len += len;
423
424                     memset(out, 0, sizeof(out));
425                 }
426
427                 p++;
428             }
429         }
430     }
431
432     if (ret->keyblob_len == 0 || !ret->keyblob) {
433         errmsg = "Key body not present";
434         goto error;
435     }
436
437     if (ret->encrypted && ret->keyblob_len % 8 != 0) {
438         errmsg = "Encrypted key blob is not a multiple of cipher block size";
439         goto error;
440     }
441
442     memset(buffer, 0, sizeof(buffer));
443     memset(base64_bit, 0, sizeof(base64_bit));
444     return ret;
445
446     error:
447     memset(buffer, 0, sizeof(buffer));
448     memset(base64_bit, 0, sizeof(base64_bit));
449     if (ret) {
450         if (ret->keyblob) {
451             memset(ret->keyblob, 0, ret->keyblob_size);
452             sfree(ret->keyblob);
453         }
454         memset(&ret, 0, sizeof(ret));
455         sfree(ret);
456     }
457     return NULL;
458 }
459
460 int openssh_encrypted(char *filename)
461 {
462     struct openssh_key *key = load_openssh_key(filename);
463     int ret;
464
465     if (!key)
466         return 0;
467     ret = key->encrypted;
468     memset(key->keyblob, 0, key->keyblob_size);
469     sfree(key->keyblob);
470     memset(&key, 0, sizeof(key));
471     sfree(key);
472     return ret;
473 }
474
475 struct ssh2_userkey *openssh_read(char *filename, char *passphrase)
476 {
477     struct openssh_key *key = load_openssh_key(filename);
478     struct ssh2_userkey *retkey;
479     unsigned char *p;
480     int ret, id, len, flags;
481     int i, num_integers;
482     struct ssh2_userkey *retval = NULL;
483     char *errmsg;
484     unsigned char *blob;
485     int blobsize, blobptr, privptr;
486     char *modptr;
487     int modlen;
488
489     if (!key)
490         return NULL;
491
492     if (key->encrypted) {
493         /*
494          * Derive encryption key from passphrase and iv/salt:
495          * 
496          *  - let block A equal MD5(passphrase || iv)
497          *  - let block B equal MD5(A || passphrase || iv)
498          *  - block C would be MD5(B || passphrase || iv) and so on
499          *  - encryption key is the first N bytes of A || B
500          */
501         struct MD5Context md5c;
502         unsigned char keybuf[32];
503
504         MD5Init(&md5c);
505         MD5Update(&md5c, passphrase, strlen(passphrase));
506         MD5Update(&md5c, key->iv, 8);
507         MD5Final(keybuf, &md5c);
508
509         MD5Init(&md5c);
510         MD5Update(&md5c, keybuf, 16);
511         MD5Update(&md5c, passphrase, strlen(passphrase));
512         MD5Update(&md5c, key->iv, 8);
513         MD5Final(keybuf+16, &md5c);
514
515         /*
516          * Now decrypt the key blob.
517          */
518         des3_decrypt_pubkey_ossh(keybuf, key->iv,
519                                  key->keyblob, key->keyblob_len);
520
521         memset(&md5c, 0, sizeof(md5c));
522         memset(keybuf, 0, sizeof(keybuf));
523     }
524
525     /*
526      * Now we have a decrypted key blob, which contains an ASN.1
527      * encoded private key. We must now untangle the ASN.1.
528      *
529      * We expect the whole key blob to be formatted as a SEQUENCE
530      * (0x30 followed by a length code indicating that the rest of
531      * the blob is part of the sequence). Within that SEQUENCE we
532      * expect to see a bunch of INTEGERs. What those integers mean
533      * depends on the key type:
534      *
535      *  - For RSA, we expect the integers to be 0, n, e, d, p, q,
536      *    dmp1, dmq1, iqmp in that order. (The last three are d mod
537      *    (p-1), d mod (q-1), inverse of q mod p respectively.)
538      *
539      *  - For DSA, we expect them to be 0, p, q, g, y, x in that
540      *    order.
541      */
542     
543     p = key->keyblob;
544
545     /* Expect the SEQUENCE header. Take its absence as a failure to decrypt. */
546     ret = ber_read_id_len(p, key->keyblob_len, &id, &len, &flags);
547     p += ret;
548     if (ret < 0 || id != 16) {
549         errmsg = "ASN.1 decoding failure";
550         retval = SSH2_WRONG_PASSPHRASE;
551         goto error;
552     }
553
554     /* Expect a load of INTEGERs. */
555     if (key->type == OSSH_RSA)
556         num_integers = 9;
557     else if (key->type == OSSH_DSA)
558         num_integers = 6;
559
560     /*
561      * Space to create key blob in.
562      */
563     blobsize = 256+key->keyblob_len;
564     blob = smalloc(blobsize);
565     PUT_32BIT(blob, 7);
566     if (key->type == OSSH_DSA)
567         memcpy(blob+4, "ssh-dss", 7);
568     else if (key->type == OSSH_RSA)
569         memcpy(blob+4, "ssh-rsa", 7);
570     blobptr = 4+7;
571     privptr = -1;
572
573     for (i = 0; i < num_integers; i++) {
574         ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,
575                               &id, &len, &flags);
576         p += ret;
577         if (ret < 0 || id != 2 ||
578             key->keyblob+key->keyblob_len-p < len) {
579             errmsg = "ASN.1 decoding failure";
580             goto error;
581         }
582
583         if (i == 0) {
584             /*
585              * The first integer should be zero always (I think
586              * this is some sort of version indication).
587              */
588             if (len != 1 || p[0] != 0) {
589                 errmsg = "Version number mismatch";
590                 goto error;
591             }
592         } else if (key->type == OSSH_RSA) {
593             /*
594              * Integers 1 and 2 go into the public blob but in the
595              * opposite order; integers 3, 4, 5 and 8 go into the
596              * private blob. The other two (6 and 7) are ignored.
597              */
598             if (i == 1) {
599                 /* Save the details for after we deal with number 2. */
600                 modptr = p;
601                 modlen = len;
602             } else if (i != 6 && i != 7) {
603                 PUT_32BIT(blob+blobptr, len);
604                 memcpy(blob+blobptr+4, p, len);
605                 blobptr += 4+len;
606                 if (i == 2) {
607                     PUT_32BIT(blob+blobptr, modlen);
608                     memcpy(blob+blobptr+4, modptr, modlen);
609                     blobptr += 4+modlen;
610                     privptr = blobptr;
611                 }
612             }
613         } else if (key->type == OSSH_DSA) {
614             /*
615              * Integers 1-4 go into the public blob; integer 5 goes
616              * into the private blob.
617              */
618             PUT_32BIT(blob+blobptr, len);
619             memcpy(blob+blobptr+4, p, len);
620             blobptr += 4+len;
621             if (i == 4)
622                 privptr = blobptr;
623         }
624
625         /* Skip past the number. */
626         p += len;
627     }
628
629     /*
630      * Now put together the actual key. Simplest way to do this is
631      * to assemble our own key blobs and feed them to the createkey
632      * functions; this is a bit faffy but it does mean we get all
633      * the sanity checks for free.
634      */
635     assert(privptr > 0);               /* should have bombed by now if not */
636     retkey = smalloc(sizeof(struct ssh2_userkey));
637     retkey->alg = (key->type == OSSH_RSA ? &ssh_rsa : &ssh_dss);
638     retkey->data = retkey->alg->createkey(blob, privptr,
639                                           blob+privptr, blobptr-privptr);
640     if (!retkey->data) {
641         sfree(retkey);
642         errmsg = "unable to create key data structure";
643         goto error;
644     }
645
646     retkey->comment = dupstr("imported-openssh-key");
647     errmsg = NULL;                     /* no error */
648     retval = retkey;
649
650     error:
651     if (blob) {
652         memset(blob, 0, blobsize);
653         sfree(blob);
654     }
655     memset(key->keyblob, 0, key->keyblob_size);
656     sfree(key->keyblob);
657     memset(&key, 0, sizeof(key));
658     sfree(key);
659     return retval;
660 }
661
662 int openssh_write(char *filename, struct ssh2_userkey *key, char *passphrase)
663 {
664     unsigned char *pubblob, *privblob, *spareblob;
665     int publen, privlen, sparelen;
666     unsigned char *outblob;
667     int outlen;
668     struct mpint_pos numbers[9];
669     int nnumbers, pos, len, seqlen, i;
670     char *header, *footer;
671     char zero[1];
672     unsigned char iv[8];
673     int ret = 0;
674     FILE *fp;
675
676     /*
677      * Fetch the key blobs.
678      */
679     pubblob = key->alg->public_blob(key->data, &publen);
680     privblob = key->alg->private_blob(key->data, &privlen);
681     spareblob = outblob = NULL;
682
683     /*
684      * Find the sequence of integers to be encoded into the OpenSSH
685      * key blob, and also decide on the header line.
686      */
687     if (key->alg == &ssh_rsa) {
688         int pos;
689         struct mpint_pos n, e, d, p, q, iqmp, dmp1, dmq1;
690         Bignum bd, bp, bq, bdmp1, bdmq1;
691
692         pos = 4 + GET_32BIT(pubblob);
693         pos += ssh2_read_mpint(pubblob+pos, publen-pos, &e);
694         pos += ssh2_read_mpint(pubblob+pos, publen-pos, &n);
695         pos = 0;
696         pos += ssh2_read_mpint(privblob+pos, privlen-pos, &d);
697         pos += ssh2_read_mpint(privblob+pos, privlen-pos, &p);
698         pos += ssh2_read_mpint(privblob+pos, privlen-pos, &q);
699         pos += ssh2_read_mpint(privblob+pos, privlen-pos, &iqmp);
700
701         assert(e.start && iqmp.start); /* can't go wrong */
702
703         /* We also need d mod (p-1) and d mod (q-1). */
704         bd = bignum_from_bytes(d.start, d.bytes);
705         bp = bignum_from_bytes(p.start, p.bytes);
706         bq = bignum_from_bytes(q.start, q.bytes);
707         decbn(bp);
708         decbn(bq);
709         bdmp1 = bigmod(bd, bp);
710         bdmq1 = bigmod(bd, bq);
711         freebn(bd);
712         freebn(bp);
713         freebn(bq);
714
715         dmp1.bytes = (bignum_bitcount(bdmp1)+8)/8;
716         dmq1.bytes = (bignum_bitcount(bdmq1)+8)/8;
717         sparelen = dmp1.bytes + dmq1.bytes;
718         spareblob = smalloc(sparelen);
719         dmp1.start = spareblob;
720         dmq1.start = spareblob + dmp1.bytes;
721         for (i = 0; i < dmp1.bytes; i++)
722             spareblob[i] = bignum_byte(bdmp1, dmp1.bytes-1 - i);
723         for (i = 0; i < dmq1.bytes; i++)
724             spareblob[i+dmp1.bytes] = bignum_byte(bdmq1, dmq1.bytes-1 - i);
725         freebn(bdmp1);
726         freebn(bdmq1);
727
728         numbers[0].start = zero; numbers[0].bytes = 1; zero[0] = '\0';
729         numbers[1] = n;
730         numbers[2] = e;
731         numbers[3] = d;
732         numbers[4] = p;
733         numbers[5] = q;
734         numbers[6] = dmp1;
735         numbers[7] = dmq1;
736         numbers[8] = iqmp;
737
738         nnumbers = 9;
739         header = "-----BEGIN RSA PRIVATE KEY-----\n";
740         footer = "-----END RSA PRIVATE KEY-----\n";
741     } else if (key->alg == &ssh_dss) {
742         int pos;
743         struct mpint_pos p, q, g, y, x;
744
745         pos = 4 + GET_32BIT(pubblob);
746         pos += ssh2_read_mpint(pubblob+pos, publen-pos, &p);
747         pos += ssh2_read_mpint(pubblob+pos, publen-pos, &q);
748         pos += ssh2_read_mpint(pubblob+pos, publen-pos, &g);
749         pos += ssh2_read_mpint(pubblob+pos, publen-pos, &y);
750         pos = 0;
751         pos += ssh2_read_mpint(privblob+pos, privlen-pos, &x);
752
753         assert(y.start && x.start); /* can't go wrong */
754
755         numbers[0].start = zero; numbers[0].bytes = 1; zero[0] = '\0'; 
756         numbers[1] = p;
757         numbers[2] = q;
758         numbers[3] = g;
759         numbers[4] = y;
760         numbers[5] = x;
761
762         nnumbers = 6;
763         header = "-----BEGIN DSA PRIVATE KEY-----\n";
764         footer = "-----END DSA PRIVATE KEY-----\n";
765     } else {
766         assert(0);                     /* zoinks! */
767     }
768
769     /*
770      * Now count up the total size of the ASN.1 encoded integers,
771      * so as to determine the length of the containing SEQUENCE.
772      */
773     len = 0;
774     for (i = 0; i < nnumbers; i++) {
775         len += ber_write_id_len(NULL, 2, numbers[i].bytes, 0);
776         len += numbers[i].bytes;
777     }
778     seqlen = len;
779     /* Now add on the SEQUENCE header. */
780     len += ber_write_id_len(NULL, 16, seqlen, ASN1_CONSTRUCTED);
781     /* And round up to the cipher block size. */
782     if (passphrase)
783         len = (len+7) &~ 7;
784
785     /*
786      * Now we know how big outblob needs to be. Allocate it.
787      */
788     outlen = len;
789     outblob = smalloc(outlen);
790
791     /*
792      * And write the data into it.
793      */
794     pos = 0;
795     pos += ber_write_id_len(outblob+pos, 16, seqlen, ASN1_CONSTRUCTED);
796     for (i = 0; i < nnumbers; i++) {
797         pos += ber_write_id_len(outblob+pos, 2, numbers[i].bytes, 0);
798         memcpy(outblob+pos, numbers[i].start, numbers[i].bytes);
799         pos += numbers[i].bytes;
800     }
801     while (pos < outlen) {
802         outblob[pos++] = random_byte();
803     }
804
805     /*
806      * Encrypt the key.
807      */
808     if (passphrase) {
809         /*
810          * Invent an iv. Then derive encryption key from passphrase
811          * and iv/salt:
812          * 
813          *  - let block A equal MD5(passphrase || iv)
814          *  - let block B equal MD5(A || passphrase || iv)
815          *  - block C would be MD5(B || passphrase || iv) and so on
816          *  - encryption key is the first N bytes of A || B
817          */
818         struct MD5Context md5c;
819         unsigned char keybuf[32];
820
821         for (i = 0; i < 8; i++) iv[i] = random_byte();
822
823         MD5Init(&md5c);
824         MD5Update(&md5c, passphrase, strlen(passphrase));
825         MD5Update(&md5c, iv, 8);
826         MD5Final(keybuf, &md5c);
827
828         MD5Init(&md5c);
829         MD5Update(&md5c, keybuf, 16);
830         MD5Update(&md5c, passphrase, strlen(passphrase));
831         MD5Update(&md5c, iv, 8);
832         MD5Final(keybuf+16, &md5c);
833
834         /*
835          * Now encrypt the key blob.
836          */
837         des3_encrypt_pubkey_ossh(keybuf, iv, outblob, outlen);
838
839         memset(&md5c, 0, sizeof(md5c));
840         memset(keybuf, 0, sizeof(keybuf));
841     }
842
843     /*
844      * And save it. We'll use Unix line endings just in case it's
845      * subsequently transferred in binary mode.
846      */
847     fp = fopen(filename, "wb");        /* ensure Unix line endings */
848     if (!fp)
849         goto error;
850     fputs(header, fp);
851     if (passphrase) {
852         fprintf(fp, "Proc-Type: 4,ENCRYPTED\nDEK-Info: DES-EDE3-CBC,");
853         for (i = 0; i < 8; i++)
854             fprintf(fp, "%02X", iv[i]);
855         fprintf(fp, "\n\n");
856     }
857     base64_encode(fp, outblob, outlen);
858     fputs(footer, fp);
859     fclose(fp);
860     ret = 1;
861
862     error:
863     if (outblob) {
864         memset(outblob, 0, outlen);
865         sfree(outblob);
866     }
867     if (spareblob) {
868         memset(spareblob, 0, sparelen);
869         sfree(spareblob);
870     }
871     if (privblob) {
872         memset(privblob, 0, privlen);
873         sfree(privblob);
874     }
875     if (pubblob) {
876         memset(pubblob, 0, publen);
877         sfree(pubblob);
878     }
879     return ret;
880 }
881
882 /* ----------------------------------------------------------------------
883  * Code to read ssh.com private keys.
884  */
885
886 /*
887  * The format of the base64 blob is largely ssh2-packet-formatted,
888  * except that mpints are a bit different: they're more like the
889  * old ssh1 mpint. You have a 32-bit bit count N, followed by
890  * (N+7)/8 bytes of data.
891  * 
892  * So. The blob contains:
893  * 
894  *  - uint32 0x3f6ff9eb       (magic number)
895  *  - uint32 size             (total blob size)
896  *  - string key-type         (see below)
897  *  - string cipher-type      (tells you if key is encrypted)
898  *  - string encrypted-blob
899  * 
900  * (The first size field includes the size field itself and the
901  * magic number before it. All other size fields are ordinary ssh2
902  * strings, so the size field indicates how much data is to
903  * _follow_.)
904  * 
905  * The encrypted blob, once decrypted, contains a single string
906  * which in turn contains the payload. (This allows padding to be
907  * added after that string while still making it clear where the
908  * real payload ends. Also it probably makes for a reasonable
909  * decryption check.)
910  * 
911  * The payload blob, for an RSA key, contains:
912  *  - mpint e
913  *  - mpint d
914  *  - mpint n  (yes, the public and private stuff is intermixed)
915  *  - mpint u  (presumably inverse of p mod q)
916  *  - mpint p  (p is the smaller prime)
917  *  - mpint q  (q is the larger)
918  * 
919  * For a DSA key, the payload blob contains:
920  *  - uint32 0
921  *  - mpint p
922  *  - mpint g
923  *  - mpint q
924  *  - mpint y
925  *  - mpint x
926  * 
927  * Alternatively, if the parameters are `predefined', that
928  * (0,p,g,q) sequence can be replaced by a uint32 1 and a string
929  * containing some predefined parameter specification. *shudder*,
930  * but I doubt we'll encounter this in real life.
931  * 
932  * The key type strings are ghastly. The RSA key I looked at had a
933  * type string of
934  * 
935  *   `if-modn{sign{rsa-pkcs1-sha1},encrypt{rsa-pkcs1v2-oaep}}'
936  * 
937  * and the DSA key wasn't much better:
938  * 
939  *   `dl-modp{sign{dsa-nist-sha1},dh{plain}}'
940  * 
941  * It isn't clear that these will always be the same. I think it
942  * might be wise just to look at the `if-modn{sign{rsa' and
943  * `dl-modp{sign{dsa' prefixes.
944  * 
945  * Finally, the encryption. The cipher-type string appears to be
946  * either `none' or `3des-cbc'. Looks as if this is SSH2-style
947  * 3des-cbc (i.e. outer cbc rather than inner). The key is created
948  * from the passphrase by means of yet another hashing faff:
949  * 
950  *  - first 16 bytes are MD5(passphrase)
951  *  - next 16 bytes are MD5(passphrase || first 16 bytes)
952  *  - if there were more, they'd be MD5(passphrase || first 32),
953  *    and so on.
954  */
955
956 struct sshcom_key {
957     char comment[256];                 /* allowing any length is overkill */
958     unsigned char *keyblob;
959     int keyblob_len, keyblob_size;
960 };
961
962 struct sshcom_key *load_sshcom_key(char *filename)
963 {
964     struct sshcom_key *ret;
965     FILE *fp;
966     char buffer[256];
967     int len;
968     char *errmsg, *p;
969     int headers_done;
970     char base64_bit[4];
971     int base64_chars = 0;
972
973     ret = smalloc(sizeof(*ret));
974     ret->comment[0] = '\0';
975     ret->keyblob = NULL;
976     ret->keyblob_len = ret->keyblob_size = 0;
977
978     fp = fopen(filename, "r");
979     if (!fp) {
980         errmsg = "Unable to open key file";
981         goto error;
982     }
983     if (!fgets(buffer, sizeof(buffer), fp) ||
984         0 != strcmp(buffer, "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----\n")) {
985         errmsg = "File does not begin with ssh.com key header";
986         goto error;
987     }
988
989     headers_done = 0;
990     while (1) {
991         if (!fgets(buffer, sizeof(buffer), fp)) {
992             errmsg = "Unexpected end of file";
993             goto error;
994         }
995         if (!strcmp(buffer, "---- END SSH2 ENCRYPTED PRIVATE KEY ----\n"))
996             break;                     /* done */
997         if ((p = strchr(buffer, ':')) != NULL) {
998             if (headers_done) {
999                 errmsg = "Header found in body of key data";
1000                 goto error;
1001             }
1002             *p++ = '\0';
1003             while (*p && isspace((unsigned char)*p)) p++;
1004             /*
1005              * Header lines can end in a trailing backslash for
1006              * continuation.
1007              */
1008             while ((len = strlen(p)) > sizeof(buffer) - (p-buffer) -1 ||
1009                    p[len-1] != '\n' || p[len-2] == '\\') {
1010                 if (len > (p-buffer) + sizeof(buffer)-2) {
1011                     errmsg = "Header line too long to deal with";
1012                     goto error;
1013                 }
1014                 if (!fgets(p+len-2, sizeof(buffer)-(p-buffer)-(len-2), fp)) {
1015                     errmsg = "Unexpected end of file";
1016                     goto error;
1017                 }
1018             }
1019             p[strcspn(p, "\n")] = '\0';
1020             if (!strcmp(buffer, "Comment")) {
1021                 /* Strip quotes in comment if present. */
1022                 if (p[0] == '"' && p[strlen(p)-1] == '"') {
1023                     p++;
1024                     p[strlen(p)-1] = '\0';
1025                 }
1026                 strncpy(ret->comment, p, sizeof(ret->comment));
1027                 ret->comment[sizeof(ret->comment)-1] = '\0';
1028             }
1029         } else {
1030             headers_done = 1;
1031
1032             p = buffer;
1033             while (isbase64(*p)) {
1034                 base64_bit[base64_chars++] = *p;
1035                 if (base64_chars == 4) {
1036                     unsigned char out[3];
1037
1038                     base64_chars = 0;
1039
1040                     len = base64_decode_atom(base64_bit, out);
1041
1042                     if (len <= 0) {
1043                         errmsg = "Invalid base64 encoding";
1044                         goto error;
1045                     }
1046
1047                     if (ret->keyblob_len + len > ret->keyblob_size) {
1048                         ret->keyblob_size = ret->keyblob_len + len + 256;
1049                         ret->keyblob = srealloc(ret->keyblob, ret->keyblob_size);
1050                     }
1051
1052                     memcpy(ret->keyblob + ret->keyblob_len, out, len);
1053                     ret->keyblob_len += len;
1054                 }
1055
1056                 p++;
1057             }
1058         }
1059     }
1060
1061     if (ret->keyblob_len == 0 || !ret->keyblob) {
1062         errmsg = "Key body not present";
1063         goto error;
1064     }
1065
1066     return ret;
1067
1068     error:
1069     if (ret) {
1070         if (ret->keyblob) {
1071             memset(ret->keyblob, 0, ret->keyblob_size);
1072             sfree(ret->keyblob);
1073         }
1074         memset(&ret, 0, sizeof(ret));
1075         sfree(ret);
1076     }
1077     return NULL;
1078 }
1079
1080 int sshcom_encrypted(char *filename, char **comment)
1081 {
1082     struct sshcom_key *key = load_sshcom_key(filename);
1083     int pos, len, answer;
1084
1085     *comment = NULL;
1086     if (!key)
1087         return 0;
1088
1089     /*
1090      * Check magic number.
1091      */
1092     if (GET_32BIT(key->keyblob) != 0x3f6ff9eb)
1093         return 0;                      /* key is invalid */
1094
1095     /*
1096      * Find the cipher-type string.
1097      */
1098     answer = 0;
1099     pos = 8;
1100     if (key->keyblob_len < pos+4)
1101         goto done;                     /* key is far too short */
1102     pos += 4 + GET_32BIT(key->keyblob + pos);   /* skip key type */
1103     if (key->keyblob_len < pos+4)
1104         goto done;                     /* key is far too short */
1105     len = GET_32BIT(key->keyblob + pos);   /* find cipher-type length */
1106     if (key->keyblob_len < pos+4+len)
1107         goto done;                     /* cipher type string is incomplete */
1108     if (len != 4 || 0 != memcmp(key->keyblob + pos + 4, "none", 4))
1109         answer = 1;
1110
1111     done:
1112     *comment = dupstr(key->comment);
1113     memset(key->keyblob, 0, key->keyblob_size);
1114     sfree(key->keyblob);
1115     memset(&key, 0, sizeof(key));
1116     sfree(key);
1117     return answer;
1118 }
1119
1120 int sshcom_read_mpint(void *data, int len, struct mpint_pos *ret)
1121 {
1122     int bits;
1123     int bytes;
1124     unsigned char *d = (unsigned char *) data;
1125
1126     if (len < 4)
1127         goto error;
1128     bits = GET_32BIT(d);
1129
1130     bytes = (bits + 7) / 8;
1131     if (len < 4+bytes)
1132         goto error;
1133
1134     ret->start = d + 4;
1135     ret->bytes = bytes;
1136     return bytes+4;
1137
1138     error:
1139     ret->start = NULL;
1140     ret->bytes = -1;
1141     return len;                        /* ensure further calls fail as well */
1142 }
1143
1144 struct ssh2_userkey *sshcom_read(char *filename, char *passphrase)
1145 {
1146     struct sshcom_key *key = load_sshcom_key(filename);
1147     char *errmsg;
1148     int pos, len;
1149     const char prefix_rsa[] = "if-modn{sign{rsa";
1150     const char prefix_dsa[] = "dl-modp{sign{dsa";
1151     enum { RSA, DSA } type;
1152     int encrypted;
1153     char *ciphertext;
1154     int cipherlen;
1155     struct ssh2_userkey *ret = NULL, *retkey;
1156     const struct ssh_signkey *alg;
1157     unsigned char *blob = NULL;
1158     int blobsize, publen, privlen;
1159
1160     if (!key)
1161         return NULL;
1162
1163     /*
1164      * Check magic number.
1165      */
1166     if (GET_32BIT(key->keyblob) != 0x3f6ff9eb) {
1167         errmsg = "Key does not begin with magic number";
1168         goto error;
1169     }
1170
1171     /*
1172      * Determine the key type.
1173      */
1174     pos = 8;
1175     if (key->keyblob_len < pos+4 ||
1176         (len = GET_32BIT(key->keyblob + pos)) > key->keyblob_len - pos - 4) {
1177         errmsg = "Key blob does not contain a key type string";
1178         goto error;
1179     }
1180     if (len > sizeof(prefix_rsa) - 1 &&
1181         !memcmp(key->keyblob+pos+4, prefix_rsa, sizeof(prefix_rsa) - 1)) {
1182         type = RSA;
1183     } else if (len > sizeof(prefix_dsa) - 1 &&
1184         !memcmp(key->keyblob+pos+4, prefix_dsa, sizeof(prefix_dsa) - 1)) {
1185         type = DSA;
1186     } else {
1187         errmsg = "Key is of unknown type";
1188         goto error;
1189     }
1190     pos += 4+len;
1191
1192     /*
1193      * Determine the cipher type.
1194      */
1195     if (key->keyblob_len < pos+4 ||
1196         (len = GET_32BIT(key->keyblob + pos)) > key->keyblob_len - pos - 4) {
1197         errmsg = "Key blob does not contain a cipher type string";
1198         goto error;
1199     }
1200     if (len == 4 && !memcmp(key->keyblob+pos+4, "none", 4))
1201         encrypted = 0;
1202     else if (len == 8 && !memcmp(key->keyblob+pos+4, "3des-cbc", 8))
1203         encrypted = 1;
1204     else {
1205         errmsg = "Key encryption is of unknown type";
1206         goto error;
1207     }
1208     pos += 4+len;
1209
1210     /*
1211      * Get hold of the encrypted part of the key.
1212      */
1213     if (key->keyblob_len < pos+4 ||
1214         (len = GET_32BIT(key->keyblob + pos)) > key->keyblob_len - pos - 4) {
1215         errmsg = "Key blob does not contain actual key data";
1216         goto error;
1217     }
1218     ciphertext = key->keyblob + pos + 4;
1219     cipherlen = len;
1220     if (cipherlen == 0) {
1221         errmsg = "Length of key data is zero";
1222         goto error;
1223     }
1224
1225     /*
1226      * Decrypt it if necessary.
1227      */
1228     if (encrypted) {
1229         /*
1230          * Derive encryption key from passphrase and iv/salt:
1231          * 
1232          *  - let block A equal MD5(passphrase)
1233          *  - let block B equal MD5(passphrase || A)
1234          *  - block C would be MD5(passphrase || A || B) and so on
1235          *  - encryption key is the first N bytes of A || B
1236          */
1237         struct MD5Context md5c;
1238         unsigned char keybuf[32], iv[8];
1239
1240         if (cipherlen % 8 != 0) {
1241             errmsg = "Encrypted part of key is not a multiple of cipher block"
1242                 " size";
1243             goto error;
1244         }
1245
1246         MD5Init(&md5c);
1247         MD5Update(&md5c, passphrase, strlen(passphrase));
1248         MD5Final(keybuf, &md5c);
1249
1250         MD5Init(&md5c);
1251         MD5Update(&md5c, passphrase, strlen(passphrase));
1252         MD5Update(&md5c, keybuf, 16);
1253         MD5Final(keybuf+16, &md5c);
1254
1255         /*
1256          * Now decrypt the key blob.
1257          */
1258         memset(iv, 0, sizeof(iv));
1259         des3_decrypt_pubkey_ossh(keybuf, iv, ciphertext, cipherlen);
1260
1261         memset(&md5c, 0, sizeof(md5c));
1262         memset(keybuf, 0, sizeof(keybuf));
1263
1264         /*
1265          * Hereafter we return WRONG_PASSPHRASE for any parsing
1266          * error. (But only if we've just tried to decrypt it!
1267          * Returning WRONG_PASSPHRASE for an unencrypted key is
1268          * automatic doom.)
1269          */
1270         if (encrypted)
1271             ret = SSH2_WRONG_PASSPHRASE;
1272     }
1273
1274     /*
1275      * Strip away the containing string to get to the real meat.
1276      */
1277     len = GET_32BIT(ciphertext);
1278     if (len > cipherlen-4) {
1279         errmsg = "containing string was ill-formed";
1280         goto error;
1281     }
1282     ciphertext += 4;
1283     cipherlen = len;
1284
1285     /*
1286      * Now we break down into RSA versus DSA. In either case we'll
1287      * construct public and private blobs in our own format, and
1288      * end up feeding them to alg->createkey().
1289      */
1290     blobsize = cipherlen + 256;
1291     blob = smalloc(blobsize);
1292     privlen = 0;
1293     if (type == RSA) {
1294         struct mpint_pos n, e, d, u, p, q;
1295         int pos = 0;
1296         pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &e);
1297         pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &d);
1298         pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &n);
1299         pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &u);
1300         pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &p);
1301         pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &q);
1302         if (!q.start) {
1303             errmsg = "key data did not contain six integers";
1304             goto error;
1305         }
1306
1307         alg = &ssh_rsa;
1308         pos = 0;
1309         pos += put_string(blob+pos, "ssh-rsa", 7);
1310         pos += put_mp(blob+pos, e.start, e.bytes);
1311         pos += put_mp(blob+pos, n.start, n.bytes);
1312         publen = pos;
1313         pos += put_string(blob+pos, d.start, d.bytes);
1314         pos += put_mp(blob+pos, q.start, q.bytes);
1315         pos += put_mp(blob+pos, p.start, p.bytes);
1316         pos += put_mp(blob+pos, u.start, u.bytes);
1317         privlen = pos - publen;
1318     } else if (type == DSA) {
1319         struct mpint_pos p, q, g, x, y;
1320         int pos = 4;
1321         if (GET_32BIT(ciphertext) != 0) {
1322             errmsg = "predefined DSA parameters not supported";
1323             goto error;
1324         }
1325         pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &p);
1326         pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &g);
1327         pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &q);
1328         pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &y);
1329         pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &x);
1330         if (!x.start) {
1331             errmsg = "key data did not contain five integers";
1332             goto error;
1333         }
1334
1335         alg = &ssh_dss;
1336         pos = 0;
1337         pos += put_string(blob+pos, "ssh-dss", 7);
1338         pos += put_mp(blob+pos, p.start, p.bytes);
1339         pos += put_mp(blob+pos, q.start, q.bytes);
1340         pos += put_mp(blob+pos, g.start, g.bytes);
1341         pos += put_mp(blob+pos, y.start, y.bytes);
1342         publen = pos;
1343         pos += put_mp(blob+pos, x.start, x.bytes);
1344         privlen = pos - publen;
1345     }
1346
1347     assert(privlen > 0);               /* should have bombed by now if not */
1348
1349     retkey = smalloc(sizeof(struct ssh2_userkey));
1350     retkey->alg = alg;
1351     retkey->data = alg->createkey(blob, publen, blob+publen, privlen);
1352     if (!retkey->data) {
1353         sfree(retkey);
1354         errmsg = "unable to create key data structure";
1355         goto error;
1356     }
1357     retkey->comment = dupstr(key->comment);
1358
1359     errmsg = NULL; /* no error */
1360     ret = retkey;
1361
1362     error:
1363     if (blob) {
1364         memset(blob, 0, blobsize);
1365         sfree(blob);
1366     }
1367     memset(key->keyblob, 0, key->keyblob_size);
1368     sfree(key->keyblob);
1369     memset(&key, 0, sizeof(key));
1370     sfree(key);
1371     return ret;
1372 }