]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - import.c
Add some basic framework code preparatory to adding key export.
[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
29 int sshcom_encrypted(char *filename, char **comment);
30 struct ssh2_userkey *sshcom_read(char *filename, char *passphrase);
31
32 /*
33  * Given a key type, determine whether we know how to import it.
34  */
35 int import_possible(int type)
36 {
37     if (type == SSH_KEYTYPE_OPENSSH)
38         return 1;
39     if (type == SSH_KEYTYPE_SSHCOM)
40         return 1;
41     return 0;
42 }
43
44 /*
45  * Given a key type, determine what native key type
46  * (SSH_KEYTYPE_SSH1 or SSH_KEYTYPE_SSH2) it will come out as once
47  * we've imported it.
48  */
49 int import_target_type(int type)
50 {
51     /*
52      * There are no known foreign SSH1 key formats.
53      */
54     return SSH_KEYTYPE_SSH2;
55 }
56
57 /*
58  * Determine whether a foreign key is encrypted.
59  */
60 int import_encrypted(char *filename, int type, char **comment)
61 {
62     if (type == SSH_KEYTYPE_OPENSSH) {
63         *comment = filename;           /* OpenSSH doesn't do key comments */
64         return openssh_encrypted(filename);
65     }
66     if (type == SSH_KEYTYPE_SSHCOM) {
67         return sshcom_encrypted(filename, comment);
68     }
69     return 0;
70 }
71
72 /*
73  * Import an SSH1 key.
74  */
75 int import_ssh1(char *filename, int type, struct RSAKey *key, char *passphrase)
76 {
77     return 0;
78 }
79
80 /*
81  * Import an SSH2 key.
82  */
83 struct ssh2_userkey *import_ssh2(char *filename, int type, char *passphrase)
84 {
85     if (type == SSH_KEYTYPE_OPENSSH)
86         return openssh_read(filename, passphrase);
87     if (type == SSH_KEYTYPE_SSHCOM)
88         return sshcom_read(filename, passphrase);
89     return NULL;
90 }
91
92 /*
93  * Export an SSH1 key.
94  */
95 int export_ssh1(char *filename, int type, struct RSAKey *key, char *passphrase)
96 {
97     return 0;
98 }
99
100 /*
101  * Export an SSH2 key.
102  */
103 int export_ssh2(char *filename, int type,
104                 struct ssh2_userkey *key, char *passphrase)
105 {
106 #if 0
107     if (type == SSH_KEYTYPE_OPENSSH)
108         return openssh_write(filename, key, passphrase);
109     if (type == SSH_KEYTYPE_SSHCOM)
110         return sshcom_write(filename, key, passphrase);
111 #endif
112     return 0;
113 }
114
115 /* ----------------------------------------------------------------------
116  * Helper routines. (The base64 ones are defined in sshpubk.c.)
117  */
118
119 #define isbase64(c) (    ((c) >= 'A' && (c) <= 'Z') || \
120                          ((c) >= 'a' && (c) <= 'z') || \
121                          ((c) >= '0' && (c) <= '9') || \
122                          (c) == '+' || (c) == '/' || (c) == '=' \
123                          )
124
125 extern int base64_decode_atom(char *atom, unsigned char *out);
126 extern int base64_lines(int datalen);
127 extern void base64_encode_atom(unsigned char *data, int n, char *out);
128 extern void base64_encode(FILE * fp, unsigned char *data, int datalen);
129
130 /*
131  * Read an ASN.1/BER identifier and length pair.
132  * 
133  * Flags are a combination of the #defines listed below.
134  * 
135  * Returns -1 if unsuccessful; otherwise returns the number of
136  * bytes used out of the source data.
137  */
138
139 /* ASN.1 tag classes. */
140 #define ASN1_CLASS_UNIVERSAL        (0 << 6)
141 #define ASN1_CLASS_APPLICATION      (1 << 6)
142 #define ASN1_CLASS_CONTEXT_SPECIFIC (2 << 6)
143 #define ASN1_CLASS_PRIVATE          (3 << 6)
144 #define ASN1_CLASS_MASK             (3 << 6)
145
146 /* Primitive versus constructed bit. */
147 #define ASN1_CONSTRUCTED            (1 << 5)
148
149 int ber_read_id_len(void *source, int sourcelen,
150                     int *id, int *length, int *flags)
151 {
152     unsigned char *p = (unsigned char *) source;
153
154     if (sourcelen == 0)
155         return -1;
156
157     *flags = (*p & 0xE0);
158     if ((*p & 0x1F) == 0x1F) {
159         *id = 0;
160         while (*p & 0x80) {
161             *id = (*id << 7) | (*p & 0x7F);
162             p++, sourcelen--;
163             if (sourcelen == 0)
164                 return -1;
165         }
166         *id = (*id << 7) | (*p & 0x7F);
167         p++, sourcelen--;
168     } else {
169         *id = *p & 0x1F;
170         p++, sourcelen--;
171     }
172
173     if (sourcelen == 0)
174         return -1;
175
176     if (*p & 0x80) {
177         int n = *p & 0x7F;
178         p++, sourcelen--;
179         if (sourcelen < n)
180             return -1;
181         *length = 0;
182         while (n--)
183             *length = (*length << 8) | (*p++);
184         sourcelen -= n;
185     } else {
186         *length = *p;
187         p++, sourcelen--;
188     }
189
190     return p - (unsigned char *) source;
191 }
192
193 static int put_string(void *target, void *data, int len)
194 {
195     unsigned char *d = (unsigned char *)target;
196
197     PUT_32BIT(d, len);
198     memcpy(d+4, data, len);
199     return len+4;
200 }
201
202 static int put_mp(void *target, void *data, int len)
203 {
204     unsigned char *d = (unsigned char *)target;
205     unsigned char *i = (unsigned char *)data;
206
207     if (*i & 0x80) {
208         PUT_32BIT(d, len+1);
209         d[4] = 0;
210         memcpy(d+5, data, len);
211         return len+5;
212     } else {
213         PUT_32BIT(d, len);
214         memcpy(d+4, data, len);
215         return len+4;
216     }
217 }
218
219 /* ----------------------------------------------------------------------
220  * Code to read OpenSSH private keys.
221  */
222
223 enum { OSSH_DSA, OSSH_RSA };
224 struct openssh_key {
225     int type;
226     int encrypted;
227     char iv[32];
228     unsigned char *keyblob;
229     int keyblob_len, keyblob_size;
230 };
231
232 struct openssh_key *load_openssh_key(char *filename)
233 {
234     struct openssh_key *ret;
235     FILE *fp;
236     char buffer[256];
237     char *errmsg, *p;
238     int headers_done;
239     char base64_bit[4];
240     int base64_chars = 0;
241
242     ret = smalloc(sizeof(*ret));
243     ret->keyblob = NULL;
244     ret->keyblob_len = ret->keyblob_size = 0;
245     ret->encrypted = 0;
246     memset(ret->iv, 0, sizeof(ret->iv));
247
248     fp = fopen(filename, "r");
249     if (!fp) {
250         errmsg = "Unable to open key file";
251         goto error;
252     }
253     if (!fgets(buffer, sizeof(buffer), fp) ||
254         0 != strncmp(buffer, "-----BEGIN ", 11) ||
255         0 != strcmp(buffer+strlen(buffer)-17, "PRIVATE KEY-----\n")) {
256         errmsg = "File does not begin with OpenSSH key header";
257         goto error;
258     }
259     if (!strcmp(buffer, "-----BEGIN RSA PRIVATE KEY-----\n"))
260         ret->type = OSSH_RSA;
261     else if (!strcmp(buffer, "-----BEGIN DSA PRIVATE KEY-----\n"))
262         ret->type = OSSH_DSA;
263     else {
264         errmsg = "Unrecognised key type";
265         goto error;
266     }
267
268     headers_done = 0;
269     while (1) {
270         if (!fgets(buffer, sizeof(buffer), fp)) {
271             errmsg = "Unexpected end of file";
272             goto error;
273         }
274         if (0 == strncmp(buffer, "-----END ", 9) &&
275             0 == strcmp(buffer+strlen(buffer)-17, "PRIVATE KEY-----\n"))
276             break;                     /* done */
277         if ((p = strchr(buffer, ':')) != NULL) {
278             if (headers_done) {
279                 errmsg = "Header found in body of key data";
280                 goto error;
281             }
282             *p++ = '\0';
283             while (*p && isspace((unsigned char)*p)) p++;
284             if (!strcmp(buffer, "Proc-Type")) {
285                 if (p[0] != '4' || p[1] != ',') {
286                     errmsg = "Proc-Type is not 4 (only 4 is supported)";
287                     goto error;
288                 }
289                 p += 2;
290                 if (!strcmp(p, "ENCRYPTED\n"))
291                     ret->encrypted = 1;
292             } else if (!strcmp(buffer, "DEK-Info")) {
293                 int i, j;
294
295                 if (strncmp(p, "DES-EDE3-CBC,", 13)) {
296                     errmsg = "Ciphers other than DES-EDE3-CBC not supported";
297                     goto error;
298                 }
299                 p += 13;
300                 for (i = 0; i < 8; i++) {
301                     if (1 != sscanf(p, "%2x", &j))
302                         break;
303                     ret->iv[i] = j;
304                     p += 2;
305                 }
306                 if (i < 8) {
307                     errmsg = "Expected 16-digit iv in DEK-Info";
308                     goto error;
309                 }
310             }
311         } else {
312             headers_done = 1;
313
314             p = buffer;
315             while (isbase64(*p)) {
316                 base64_bit[base64_chars++] = *p;
317                 if (base64_chars == 4) {
318                     unsigned char out[3];
319                     int len;
320
321                     base64_chars = 0;
322
323                     len = base64_decode_atom(base64_bit, out);
324
325                     if (len <= 0) {
326                         errmsg = "Invalid base64 encoding";
327                         goto error;
328                     }
329
330                     if (ret->keyblob_len + len > ret->keyblob_size) {
331                         ret->keyblob_size = ret->keyblob_len + len + 256;
332                         ret->keyblob = srealloc(ret->keyblob, ret->keyblob_size);
333                     }
334
335                     memcpy(ret->keyblob + ret->keyblob_len, out, len);
336                     ret->keyblob_len += len;
337
338                     memset(out, 0, sizeof(out));
339                 }
340
341                 p++;
342             }
343         }
344     }
345
346     if (ret->keyblob_len == 0 || !ret->keyblob) {
347         errmsg = "Key body not present";
348         goto error;
349     }
350
351     if (ret->encrypted && ret->keyblob_len % 8 != 0) {
352         errmsg = "Encrypted key blob is not a multiple of cipher block size";
353         goto error;
354     }
355
356     memset(buffer, 0, sizeof(buffer));
357     memset(base64_bit, 0, sizeof(base64_bit));
358     return ret;
359
360     error:
361     memset(buffer, 0, sizeof(buffer));
362     memset(base64_bit, 0, sizeof(base64_bit));
363     if (ret) {
364         if (ret->keyblob) {
365             memset(ret->keyblob, 0, ret->keyblob_size);
366             sfree(ret->keyblob);
367         }
368         memset(&ret, 0, sizeof(ret));
369         sfree(ret);
370     }
371     return NULL;
372 }
373
374 int openssh_encrypted(char *filename)
375 {
376     struct openssh_key *key = load_openssh_key(filename);
377     int ret;
378
379     if (!key)
380         return 0;
381     ret = key->encrypted;
382     memset(key->keyblob, 0, key->keyblob_size);
383     sfree(key->keyblob);
384     memset(&key, 0, sizeof(key));
385     sfree(key);
386     return ret;
387 }
388
389 struct ssh2_userkey *openssh_read(char *filename, char *passphrase)
390 {
391     struct openssh_key *key = load_openssh_key(filename);
392     struct ssh2_userkey *retkey;
393     unsigned char *p;
394     int ret, id, len, flags;
395     int i, num_integers;
396     struct ssh2_userkey *retval = NULL;
397     char *errmsg;
398     unsigned char *blob;
399     int blobsize, blobptr, privptr;
400     char *modptr;
401     int modlen;
402
403     if (!key)
404         return NULL;
405
406     if (key->encrypted) {
407         /*
408          * Derive encryption key from passphrase and iv/salt:
409          * 
410          *  - let block A equal MD5(passphrase || iv)
411          *  - let block B equal MD5(A || passphrase || iv)
412          *  - block C would be MD5(B || passphrase || iv) and so on
413          *  - encryption key is the first N bytes of A || B
414          */
415         struct MD5Context md5c;
416         unsigned char keybuf[32];
417
418         MD5Init(&md5c);
419         MD5Update(&md5c, passphrase, strlen(passphrase));
420         MD5Update(&md5c, key->iv, 8);
421         MD5Final(keybuf, &md5c);
422
423         MD5Init(&md5c);
424         MD5Update(&md5c, keybuf, 16);
425         MD5Update(&md5c, passphrase, strlen(passphrase));
426         MD5Update(&md5c, key->iv, 8);
427         MD5Final(keybuf+16, &md5c);
428
429         /*
430          * Now decrypt the key blob.
431          */
432         des3_decrypt_pubkey_ossh(keybuf, key->iv,
433                                  key->keyblob, key->keyblob_len);
434
435         memset(&md5c, 0, sizeof(md5c));
436         memset(keybuf, 0, sizeof(keybuf));
437     }
438
439     /*
440      * Now we have a decrypted key blob, which contains an ASN.1
441      * encoded private key. We must now untangle the ASN.1.
442      *
443      * We expect the whole key blob to be formatted as a SEQUENCE
444      * (0x30 followed by a length code indicating that the rest of
445      * the blob is part of the sequence). Within that SEQUENCE we
446      * expect to see a bunch of INTEGERs. What those integers mean
447      * depends on the key type:
448      *
449      *  - For RSA, we expect the integers to be 0, n, e, d, p, q,
450      *    dmp1, dmq1, iqmp in that order. (The last three are d mod
451      *    (p-1), d mod (q-1), inverse of q mod p respectively.)
452      *
453      *  - For DSA, we expect them to be 0, p, q, g, y, x in that
454      *    order.
455      */
456     
457     p = key->keyblob;
458
459     /* Expect the SEQUENCE header. Take its absence as a failure to decrypt. */
460     ret = ber_read_id_len(p, key->keyblob_len, &id, &len, &flags);
461     p += ret;
462     if (ret < 0 || id != 16) {
463         errmsg = "ASN.1 decoding failure";
464         retval = SSH2_WRONG_PASSPHRASE;
465         goto error;
466     }
467
468     /* Expect a load of INTEGERs. */
469     if (key->type == OSSH_RSA)
470         num_integers = 9;
471     else if (key->type == OSSH_DSA)
472         num_integers = 6;
473
474     /*
475      * Space to create key blob in.
476      */
477     blobsize = 256+key->keyblob_len;
478     blob = smalloc(blobsize);
479     PUT_32BIT(blob, 7);
480     if (key->type == OSSH_DSA)
481         memcpy(blob+4, "ssh-dss", 7);
482     else if (key->type == OSSH_RSA)
483         memcpy(blob+4, "ssh-rsa", 7);
484     blobptr = 4+7;
485     privptr = -1;
486
487     for (i = 0; i < num_integers; i++) {
488         ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,
489                               &id, &len, &flags);
490         p += ret;
491         if (ret < 0 || id != 2 ||
492             key->keyblob+key->keyblob_len-p < len) {
493             errmsg = "ASN.1 decoding failure";
494             goto error;
495         }
496
497         if (i == 0) {
498             /*
499              * The first integer should be zero always (I think
500              * this is some sort of version indication).
501              */
502             if (len != 1 || p[0] != 0) {
503                 errmsg = "Version number mismatch";
504                 goto error;
505             }
506         } else if (key->type == OSSH_RSA) {
507             /*
508              * Integers 1 and 2 go into the public blob but in the
509              * opposite order; integers 3, 4, 5 and 8 go into the
510              * private blob. The other two (6 and 7) are ignored.
511              */
512             if (i == 1) {
513                 /* Save the details for after we deal with number 2. */
514                 modptr = p;
515                 modlen = len;
516             } else if (i != 6 && i != 7) {
517                 PUT_32BIT(blob+blobptr, len);
518                 memcpy(blob+blobptr+4, p, len);
519                 blobptr += 4+len;
520                 if (i == 2) {
521                     PUT_32BIT(blob+blobptr, modlen);
522                     memcpy(blob+blobptr+4, modptr, modlen);
523                     blobptr += 4+modlen;
524                     privptr = blobptr;
525                 }
526             }
527         } else if (key->type == OSSH_DSA) {
528             /*
529              * Integers 1-4 go into the public blob; integer 5 goes
530              * into the private blob.
531              */
532             PUT_32BIT(blob+blobptr, len);
533             memcpy(blob+blobptr+4, p, len);
534             blobptr += 4+len;
535             if (i == 4)
536                 privptr = blobptr;
537         }
538
539         /* Skip past the number. */
540         p += len;
541     }
542
543     /*
544      * Now put together the actual key. Simplest way to do this is
545      * to assemble our own key blobs and feed them to the createkey
546      * functions; this is a bit faffy but it does mean we get all
547      * the sanity checks for free.
548      */
549     assert(privptr > 0);               /* should have bombed by now if not */
550     retkey = smalloc(sizeof(struct ssh2_userkey));
551     retkey->alg = (key->type == OSSH_RSA ? &ssh_rsa : &ssh_dss);
552     retkey->data = retkey->alg->createkey(blob, privptr,
553                                           blob+privptr, blobptr-privptr);
554     if (!retkey->data) {
555         sfree(retkey);
556         errmsg = "unable to create key data structure";
557         goto error;
558     }
559
560     retkey->comment = dupstr("imported-openssh-key");
561     errmsg = NULL;                     /* no error */
562     retval = retkey;
563
564     error:
565     if (blob) {
566         memset(blob, 0, blobsize);
567         sfree(blob);
568     }
569     memset(key->keyblob, 0, key->keyblob_size);
570     sfree(key->keyblob);
571     memset(&key, 0, sizeof(key));
572     sfree(key);
573     return retval;
574 }
575
576 /* ----------------------------------------------------------------------
577  * Code to read ssh.com private keys.
578  */
579
580 /*
581  * The format of the base64 blob is largely ssh2-packet-formatted,
582  * except that mpints are a bit different: they're more like the
583  * old ssh1 mpint. You have a 32-bit bit count N, followed by
584  * (N+7)/8 bytes of data.
585  * 
586  * So. The blob contains:
587  * 
588  *  - uint32 0x3f6ff9eb       (magic number)
589  *  - uint32 size             (total blob size)
590  *  - string key-type         (see below)
591  *  - string cipher-type      (tells you if key is encrypted)
592  *  - string encrypted-blob
593  * 
594  * (The first size field includes the size field itself and the
595  * magic number before it. All other size fields are ordinary ssh2
596  * strings, so the size field indicates how much data is to
597  * _follow_.)
598  * 
599  * The encrypted blob, once decrypted, contains a single string
600  * which in turn contains the payload. (This allows padding to be
601  * added after that string while still making it clear where the
602  * real payload ends. Also it probably makes for a reasonable
603  * decryption check.)
604  * 
605  * The payload blob, for an RSA key, contains:
606  *  - mpint e
607  *  - mpint d
608  *  - mpint n  (yes, the public and private stuff is intermixed)
609  *  - mpint u  (presumably inverse of p mod q)
610  *  - mpint p  (p is the smaller prime)
611  *  - mpint q  (q is the larger)
612  * 
613  * For a DSA key, the payload blob contains:
614  *  - uint32 0
615  *  - mpint p
616  *  - mpint g
617  *  - mpint q
618  *  - mpint y
619  *  - mpint x
620  * 
621  * Alternatively, if the parameters are `predefined', that
622  * (0,p,g,q) sequence can be replaced by a uint32 1 and a string
623  * containing some predefined parameter specification. *shudder*,
624  * but I doubt we'll encounter this in real life.
625  * 
626  * The key type strings are ghastly. The RSA key I looked at had a
627  * type string of
628  * 
629  *   `if-modn{sign{rsa-pkcs1-sha1},encrypt{rsa-pkcs1v2-oaep}}'
630  * 
631  * and the DSA key wasn't much better:
632  * 
633  *   `dl-modp{sign{dsa-nist-sha1},dh{plain}}'
634  * 
635  * It isn't clear that these will always be the same. I think it
636  * might be wise just to look at the `if-modn{sign{rsa' and
637  * `dl-modp{sign{dsa' prefixes.
638  * 
639  * Finally, the encryption. The cipher-type string appears to be
640  * either `none' or `3des-cbc'. Looks as if this is SSH2-style
641  * 3des-cbc (i.e. outer cbc rather than inner). The key is created
642  * from the passphrase by means of yet another hashing faff:
643  * 
644  *  - first 16 bytes are MD5(passphrase)
645  *  - next 16 bytes are MD5(passphrase || first 16 bytes)
646  *  - if there were more, they'd be MD5(passphrase || first 32),
647  *    and so on.
648  */
649
650 struct sshcom_key {
651     char comment[256];                 /* allowing any length is overkill */
652     unsigned char *keyblob;
653     int keyblob_len, keyblob_size;
654 };
655
656 struct sshcom_key *load_sshcom_key(char *filename)
657 {
658     struct sshcom_key *ret;
659     FILE *fp;
660     char buffer[256];
661     int len;
662     char *errmsg, *p;
663     int headers_done;
664     char base64_bit[4];
665     int base64_chars = 0;
666
667     ret = smalloc(sizeof(*ret));
668     ret->comment[0] = '\0';
669     ret->keyblob = NULL;
670     ret->keyblob_len = ret->keyblob_size = 0;
671
672     fp = fopen(filename, "r");
673     if (!fp) {
674         errmsg = "Unable to open key file";
675         goto error;
676     }
677     if (!fgets(buffer, sizeof(buffer), fp) ||
678         0 != strcmp(buffer, "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----\n")) {
679         errmsg = "File does not begin with ssh.com key header";
680         goto error;
681     }
682
683     headers_done = 0;
684     while (1) {
685         if (!fgets(buffer, sizeof(buffer), fp)) {
686             errmsg = "Unexpected end of file";
687             goto error;
688         }
689         if (!strcmp(buffer, "---- END SSH2 ENCRYPTED PRIVATE KEY ----\n"))
690             break;                     /* done */
691         if ((p = strchr(buffer, ':')) != NULL) {
692             if (headers_done) {
693                 errmsg = "Header found in body of key data";
694                 goto error;
695             }
696             *p++ = '\0';
697             while (*p && isspace((unsigned char)*p)) p++;
698             /*
699              * Header lines can end in a trailing backslash for
700              * continuation.
701              */
702             while ((len = strlen(p)) > sizeof(buffer) - (p-buffer) -1 ||
703                    p[len-1] != '\n' || p[len-2] == '\\') {
704                 if (len > (p-buffer) + sizeof(buffer)-2) {
705                     errmsg = "Header line too long to deal with";
706                     goto error;
707                 }
708                 if (!fgets(p+len-2, sizeof(buffer)-(p-buffer)-(len-2), fp)) {
709                     errmsg = "Unexpected end of file";
710                     goto error;
711                 }
712             }
713             p[strcspn(p, "\n")] = '\0';
714             if (!strcmp(buffer, "Comment")) {
715                 /* Strip quotes in comment if present. */
716                 if (p[0] == '"' && p[strlen(p)-1] == '"') {
717                     p++;
718                     p[strlen(p)-1] = '\0';
719                 }
720                 strncpy(ret->comment, p, sizeof(ret->comment));
721                 ret->comment[sizeof(ret->comment)-1] = '\0';
722             }
723         } else {
724             headers_done = 1;
725
726             p = buffer;
727             while (isbase64(*p)) {
728                 base64_bit[base64_chars++] = *p;
729                 if (base64_chars == 4) {
730                     unsigned char out[3];
731
732                     base64_chars = 0;
733
734                     len = base64_decode_atom(base64_bit, out);
735
736                     if (len <= 0) {
737                         errmsg = "Invalid base64 encoding";
738                         goto error;
739                     }
740
741                     if (ret->keyblob_len + len > ret->keyblob_size) {
742                         ret->keyblob_size = ret->keyblob_len + len + 256;
743                         ret->keyblob = srealloc(ret->keyblob, ret->keyblob_size);
744                     }
745
746                     memcpy(ret->keyblob + ret->keyblob_len, out, len);
747                     ret->keyblob_len += len;
748                 }
749
750                 p++;
751             }
752         }
753     }
754
755     if (ret->keyblob_len == 0 || !ret->keyblob) {
756         errmsg = "Key body not present";
757         goto error;
758     }
759
760     return ret;
761
762     error:
763     if (ret) {
764         if (ret->keyblob) {
765             memset(ret->keyblob, 0, ret->keyblob_size);
766             sfree(ret->keyblob);
767         }
768         memset(&ret, 0, sizeof(ret));
769         sfree(ret);
770     }
771     return NULL;
772 }
773
774 int sshcom_encrypted(char *filename, char **comment)
775 {
776     struct sshcom_key *key = load_sshcom_key(filename);
777     int pos, len, answer;
778
779     *comment = NULL;
780     if (!key)
781         return 0;
782
783     /*
784      * Check magic number.
785      */
786     if (GET_32BIT(key->keyblob) != 0x3f6ff9eb)
787         return 0;                      /* key is invalid */
788
789     /*
790      * Find the cipher-type string.
791      */
792     answer = 0;
793     pos = 8;
794     if (key->keyblob_len < pos+4)
795         goto done;                     /* key is far too short */
796     pos += 4 + GET_32BIT(key->keyblob + pos);   /* skip key type */
797     if (key->keyblob_len < pos+4)
798         goto done;                     /* key is far too short */
799     len = GET_32BIT(key->keyblob + pos);   /* find cipher-type length */
800     if (key->keyblob_len < pos+4+len)
801         goto done;                     /* cipher type string is incomplete */
802     if (len != 4 || 0 != memcmp(key->keyblob + pos + 4, "none", 4))
803         answer = 1;
804
805     done:
806     *comment = dupstr(key->comment);
807     memset(key->keyblob, 0, key->keyblob_size);
808     sfree(key->keyblob);
809     memset(&key, 0, sizeof(key));
810     sfree(key);
811     return answer;
812 }
813
814 struct mpint_pos { void *start; int bytes; };
815
816 int sshcom_read_mpint(void *data, int len, struct mpint_pos *ret)
817 {
818     int bits;
819     int bytes;
820     unsigned char *d = (unsigned char *) data;
821
822     if (len < 4)
823         goto error;
824     bits = GET_32BIT(d);
825
826     bytes = (bits + 7) / 8;
827     if (len < 4+bytes)
828         goto error;
829
830     ret->start = d + 4;
831     ret->bytes = bytes;
832     return bytes+4;
833
834     error:
835     ret->start = NULL;
836     ret->bytes = -1;
837     return len;                        /* ensure further calls fail as well */
838 }
839
840 struct ssh2_userkey *sshcom_read(char *filename, char *passphrase)
841 {
842     struct sshcom_key *key = load_sshcom_key(filename);
843     char *errmsg;
844     int pos, len;
845     const char prefix_rsa[] = "if-modn{sign{rsa";
846     const char prefix_dsa[] = "dl-modp{sign{dsa";
847     enum { RSA, DSA } type;
848     int encrypted;
849     char *ciphertext;
850     int cipherlen;
851     struct ssh2_userkey *ret = NULL, *retkey;
852     const struct ssh_signkey *alg;
853     unsigned char *blob = NULL;
854     int blobsize, publen, privlen;
855
856     if (!key)
857         return NULL;
858
859     /*
860      * Check magic number.
861      */
862     if (GET_32BIT(key->keyblob) != 0x3f6ff9eb) {
863         errmsg = "Key does not begin with magic number";
864         goto error;
865     }
866
867     /*
868      * Determine the key type.
869      */
870     pos = 8;
871     if (key->keyblob_len < pos+4 ||
872         (len = GET_32BIT(key->keyblob + pos)) > key->keyblob_len - pos - 4) {
873         errmsg = "Key blob does not contain a key type string";
874         goto error;
875     }
876     if (len > sizeof(prefix_rsa) - 1 &&
877         !memcmp(key->keyblob+pos+4, prefix_rsa, sizeof(prefix_rsa) - 1)) {
878         type = RSA;
879     } else if (len > sizeof(prefix_dsa) - 1 &&
880         !memcmp(key->keyblob+pos+4, prefix_dsa, sizeof(prefix_dsa) - 1)) {
881         type = DSA;
882     } else {
883         errmsg = "Key is of unknown type";
884         goto error;
885     }
886     pos += 4+len;
887
888     /*
889      * Determine the cipher type.
890      */
891     if (key->keyblob_len < pos+4 ||
892         (len = GET_32BIT(key->keyblob + pos)) > key->keyblob_len - pos - 4) {
893         errmsg = "Key blob does not contain a cipher type string";
894         goto error;
895     }
896     if (len == 4 && !memcmp(key->keyblob+pos+4, "none", 4))
897         encrypted = 0;
898     else if (len == 8 && !memcmp(key->keyblob+pos+4, "3des-cbc", 8))
899         encrypted = 1;
900     else {
901         errmsg = "Key encryption is of unknown type";
902         goto error;
903     }
904     pos += 4+len;
905
906     /*
907      * Get hold of the encrypted part of the key.
908      */
909     if (key->keyblob_len < pos+4 ||
910         (len = GET_32BIT(key->keyblob + pos)) > key->keyblob_len - pos - 4) {
911         errmsg = "Key blob does not contain actual key data";
912         goto error;
913     }
914     ciphertext = key->keyblob + pos + 4;
915     cipherlen = len;
916     if (cipherlen == 0) {
917         errmsg = "Length of key data is zero";
918         goto error;
919     }
920
921     /*
922      * Decrypt it if necessary.
923      */
924     if (encrypted) {
925         /*
926          * Derive encryption key from passphrase and iv/salt:
927          * 
928          *  - let block A equal MD5(passphrase)
929          *  - let block B equal MD5(passphrase || A)
930          *  - block C would be MD5(passphrase || A || B) and so on
931          *  - encryption key is the first N bytes of A || B
932          */
933         struct MD5Context md5c;
934         unsigned char keybuf[32], iv[8];
935
936         if (cipherlen % 8 != 0) {
937             errmsg = "Encrypted part of key is not a multiple of cipher block"
938                 " size";
939             goto error;
940         }
941
942         MD5Init(&md5c);
943         MD5Update(&md5c, passphrase, strlen(passphrase));
944         MD5Final(keybuf, &md5c);
945
946         MD5Init(&md5c);
947         MD5Update(&md5c, passphrase, strlen(passphrase));
948         MD5Update(&md5c, keybuf, 16);
949         MD5Final(keybuf+16, &md5c);
950
951         /*
952          * Now decrypt the key blob.
953          */
954         memset(iv, 0, sizeof(iv));
955         des3_decrypt_pubkey_ossh(keybuf, iv, ciphertext, cipherlen);
956
957         memset(&md5c, 0, sizeof(md5c));
958         memset(keybuf, 0, sizeof(keybuf));
959
960         /*
961          * Hereafter we return WRONG_PASSPHRASE for any parsing
962          * error. (But only if we've just tried to decrypt it!
963          * Returning WRONG_PASSPHRASE for an unencrypted key is
964          * automatic doom.)
965          */
966         if (encrypted)
967             ret = SSH2_WRONG_PASSPHRASE;
968     }
969
970     /*
971      * Strip away the containing string to get to the real meat.
972      */
973     len = GET_32BIT(ciphertext);
974     if (len > cipherlen-4) {
975         errmsg = "containing string was ill-formed";
976         goto error;
977     }
978     ciphertext += 4;
979     cipherlen = len;
980
981     /*
982      * Now we break down into RSA versus DSA. In either case we'll
983      * construct public and private blobs in our own format, and
984      * end up feeding them to alg->createkey().
985      */
986     blobsize = cipherlen + 256;
987     blob = smalloc(blobsize);
988     privlen = 0;
989     if (type == RSA) {
990         struct mpint_pos n, e, d, u, p, q;
991         int pos = 0;
992         pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &e);
993         pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &d);
994         pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &n);
995         pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &u);
996         pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &p);
997         pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &q);
998         if (!q.start) {
999             errmsg = "key data did not contain six integers";
1000             goto error;
1001         }
1002
1003         alg = &ssh_rsa;
1004         pos = 0;
1005         pos += put_string(blob+pos, "ssh-rsa", 7);
1006         pos += put_mp(blob+pos, e.start, e.bytes);
1007         pos += put_mp(blob+pos, n.start, n.bytes);
1008         publen = pos;
1009         pos += put_string(blob+pos, d.start, d.bytes);
1010         pos += put_mp(blob+pos, q.start, q.bytes);
1011         pos += put_mp(blob+pos, p.start, p.bytes);
1012         pos += put_mp(blob+pos, u.start, u.bytes);
1013         privlen = pos - publen;
1014     } else if (type == DSA) {
1015         struct mpint_pos p, q, g, x, y;
1016         int pos = 4;
1017         if (GET_32BIT(ciphertext) != 0) {
1018             errmsg = "predefined DSA parameters not supported";
1019             goto error;
1020         }
1021         pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &p);
1022         pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &g);
1023         pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &q);
1024         pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &y);
1025         pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &x);
1026         if (!x.start) {
1027             errmsg = "key data did not contain five integers";
1028             goto error;
1029         }
1030
1031         alg = &ssh_dss;
1032         pos = 0;
1033         pos += put_string(blob+pos, "ssh-dss", 7);
1034         pos += put_mp(blob+pos, p.start, p.bytes);
1035         pos += put_mp(blob+pos, q.start, q.bytes);
1036         pos += put_mp(blob+pos, g.start, g.bytes);
1037         pos += put_mp(blob+pos, y.start, y.bytes);
1038         publen = pos;
1039         pos += put_mp(blob+pos, x.start, x.bytes);
1040         privlen = pos - publen;
1041     }
1042
1043     assert(privlen > 0);               /* should have bombed by now if not */
1044
1045     retkey = smalloc(sizeof(struct ssh2_userkey));
1046     retkey->alg = alg;
1047     retkey->data = alg->createkey(blob, publen, blob+publen, privlen);
1048     if (!retkey->data) {
1049         sfree(retkey);
1050         errmsg = "unable to create key data structure";
1051         goto error;
1052     }
1053     retkey->comment = dupstr(key->comment);
1054
1055     errmsg = NULL; /* no error */
1056     ret = retkey;
1057
1058     error:
1059     if (blob) {
1060         memset(blob, 0, blobsize);
1061         sfree(blob);
1062     }
1063     memset(key->keyblob, 0, key->keyblob_size);
1064     sfree(key->keyblob);
1065     memset(&key, 0, sizeof(key));
1066     sfree(key);
1067     return ret;
1068 }