]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - sshpubk.c
Pageant interface changes. You can now do `pageant -c command' to
[PuTTY.git] / sshpubk.c
1 /*
2  * Generic SSH public-key handling operations. In particular,
3  * reading of SSH public-key files, and also the generic `sign'
4  * operation for ssh2 (which checks the type of the key and
5  * dispatches to the appropriate key-type specific function).
6  */
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <assert.h>
11
12 #include "ssh.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 #define rsa_signature "SSH PRIVATE KEY FILE FORMAT 1.1\n"
27
28 #define BASE64_TOINT(x) ( (x)-'A'<26 ? (x)-'A'+0 :\
29                           (x)-'a'<26 ? (x)-'a'+26 :\
30                           (x)-'0'<10 ? (x)-'0'+52 :\
31                           (x)=='+' ? 62 : \
32                           (x)=='/' ? 63 : 0 )
33
34 static int loadrsakey_main(FILE *fp, struct RSAKey *key,
35                            char **commentptr, char *passphrase) {
36     unsigned char buf[16384];
37     unsigned char keybuf[16];
38     int len;
39     int i, j, ciphertype;
40     int ret = 0;
41     struct MD5Context md5c;
42     char *comment;
43
44     /* Slurp the whole file (minus the header) into a buffer. */
45     len = fread(buf, 1, sizeof(buf), fp);
46     fclose(fp);
47     if (len < 0 || len == sizeof(buf))
48         goto end;                      /* file too big or not read */
49
50     i = 0;
51
52     /*
53      * A zero byte. (The signature includes a terminating NUL.)
54      */
55     if (len-i < 1 || buf[i] != 0)
56         goto end;
57     i++;
58
59     /* One byte giving encryption type, and one reserved uint32. */
60     if (len-i < 1)
61         goto end;
62     ciphertype = buf[i];
63     if (ciphertype != 0 && ciphertype != SSH_CIPHER_3DES)
64         goto end;
65     i++;
66     if (len-i < 4)
67         goto end;                      /* reserved field not present */
68     if (buf[i] != 0 || buf[i+1] != 0 || buf[i+2] != 0 || buf[i+3] != 0)
69         goto end;                      /* reserved field nonzero, panic! */
70     i += 4;
71
72     /* Now the serious stuff. An ordinary SSH 1 public key. */
73     i += makekey(buf+i, key, NULL, 1);
74     if (len-i < 0)
75         goto end;                      /* overran */
76
77     /* Next, the comment field. */
78     j = GET_32BIT(buf+i);
79     i += 4;
80     if (len-i < j) goto end;
81     comment = smalloc(j+1);
82     if (comment) {
83         memcpy(comment, buf+i, j);
84         comment[j] = '\0';
85     }
86     i += j;
87     if (commentptr)
88         *commentptr = comment;
89     if (key)
90         key->comment = comment;
91     if (!key) {
92         return ciphertype != 0;
93     }
94
95     /*
96      * Decrypt remainder of buffer.
97      */
98     if (ciphertype) {
99         MD5Init(&md5c);
100         MD5Update(&md5c, passphrase, strlen(passphrase));
101         MD5Final(keybuf, &md5c);
102         des3_decrypt_pubkey(keybuf, buf+i, (len-i+7)&~7);
103         memset(keybuf, 0, sizeof(keybuf));    /* burn the evidence */
104     }
105
106     /*
107      * We are now in the secret part of the key. The first four
108      * bytes should be of the form a, b, a, b.
109      */
110     if (len-i < 4) goto end;
111     if (buf[i] != buf[i+2] || buf[i+1] != buf[i+3]) { ret = -1; goto end; }
112     i += 4;
113
114     /*
115      * After that, we have one further bignum which is our
116      * decryption exponent, and then the three auxiliary values
117      * (iqmp, q, p).
118      */
119     i += makeprivate(buf+i, key);
120     if (len-i < 0) goto end;
121     i += ssh1_read_bignum(buf+i, &key->iqmp);
122     if (len-i < 0) goto end;
123     i += ssh1_read_bignum(buf+i, &key->q);
124     if (len-i < 0) goto end;
125     i += ssh1_read_bignum(buf+i, &key->p);
126     if (len-i < 0) goto end;
127
128     if (!rsa_verify(key)) {
129         freersakey(key);
130         ret = 0;
131     } else
132         ret = 1;
133
134     end:
135     memset(buf, 0, sizeof(buf));       /* burn the evidence */
136     return ret;
137 }
138
139 int loadrsakey(char *filename, struct RSAKey *key, char *passphrase) {
140     FILE *fp;
141     unsigned char buf[64];
142
143     fp = fopen(filename, "rb");
144     if (!fp)
145         return 0;                      /* doesn't even exist */
146
147     /*
148      * Read the first line of the file and see if it's a v1 private
149      * key file.
150      */
151     if (fgets(buf, sizeof(buf), fp) &&
152         !strcmp(buf, rsa_signature)) {
153         return loadrsakey_main(fp, key, NULL, passphrase);
154     }
155
156     /*
157      * Otherwise, we have nothing. Return empty-handed.
158      */
159     fclose(fp);
160     return 0;
161 }
162
163 /*
164  * See whether an RSA key is encrypted. Return its comment field as
165  * well.
166  */
167 int rsakey_encrypted(char *filename, char **comment) {
168     FILE *fp;
169     unsigned char buf[64];
170
171     fp = fopen(filename, "rb");
172     if (!fp)
173         return 0;                      /* doesn't even exist */
174
175     /*
176      * Read the first line of the file and see if it's a v1 private
177      * key file.
178      */
179     if (fgets(buf, sizeof(buf), fp) &&
180         !strcmp(buf, rsa_signature)) {
181         return loadrsakey_main(fp, NULL, comment, NULL);
182     }
183     fclose(fp);
184     return 0;                          /* wasn't the right kind of file */
185 }
186
187 /*
188  * Save an RSA key file. Return nonzero on success.
189  */
190 int saversakey(char *filename, struct RSAKey *key, char *passphrase) {
191     unsigned char buf[16384];
192     unsigned char keybuf[16];
193     struct MD5Context md5c;
194     unsigned char *p, *estart;
195     FILE *fp;
196
197     /*
198      * Write the initial signature.
199      */
200     p = buf;
201     memcpy(p, rsa_signature, sizeof(rsa_signature));
202     p += sizeof(rsa_signature);
203
204     /*
205      * One byte giving encryption type, and one reserved (zero)
206      * uint32.
207      */
208     *p++ = (passphrase ? SSH_CIPHER_3DES : 0);
209     PUT_32BIT(p, 0); p += 4;
210
211     /*
212      * An ordinary SSH 1 public key consists of: a uint32
213      * containing the bit count, then two bignums containing the
214      * modulus and exponent respectively.
215      */
216     PUT_32BIT(p, bignum_bitcount(key->modulus)); p += 4;
217     p += ssh1_write_bignum(p, key->modulus);
218     p += ssh1_write_bignum(p, key->exponent);
219
220     /*
221      * A string containing the comment field.
222      */
223     if (key->comment) {
224         PUT_32BIT(p, strlen(key->comment)); p += 4;
225         memcpy(p, key->comment, strlen(key->comment));
226         p += strlen(key->comment);
227     } else {
228         PUT_32BIT(p, 0); p += 4;
229     }
230
231     /*
232      * The encrypted portion starts here.
233      */
234     estart = p;
235
236     /*
237      * Two bytes, then the same two bytes repeated.
238      */
239     *p++ = random_byte();
240     *p++ = random_byte();
241     p[0] = p[-2]; p[1] = p[-1]; p += 2;
242
243     /*
244      * Four more bignums: the decryption exponent, then iqmp, then
245      * q, then p.
246      */
247     p += ssh1_write_bignum(p, key->private_exponent);
248     p += ssh1_write_bignum(p, key->iqmp);
249     p += ssh1_write_bignum(p, key->q);
250     p += ssh1_write_bignum(p, key->p);
251
252     /*
253      * Now write zeros until the encrypted portion is a multiple of
254      * 8 bytes.
255      */
256     while ((p-estart) % 8)
257         *p++ = '\0';
258
259     /*
260      * Now encrypt the encrypted portion.
261      */
262     if (passphrase) {
263         MD5Init(&md5c);
264         MD5Update(&md5c, passphrase, strlen(passphrase));
265         MD5Final(keybuf, &md5c);
266         des3_encrypt_pubkey(keybuf, estart, p-estart);
267         memset(keybuf, 0, sizeof(keybuf));    /* burn the evidence */
268     }
269
270     /*
271      * Done. Write the result to the file.
272      */
273     fp = fopen(filename, "wb");
274     if (fp) {
275         int ret = (fwrite(buf, 1, p-buf, fp) == (size_t)(p-buf));
276         ret = ret && (fclose(fp) == 0);
277         return ret;
278     } else
279         return 0;
280 }
281
282 /* ----------------------------------------------------------------------
283  * SSH2 private key load/store functions.
284  */
285
286 /*
287  * PuTTY's own format for SSH2 keys is as follows:
288  * 
289  * The file is text. Lines are terminated by CRLF, although CR-only
290  * and LF-only are tolerated on input.
291  * 
292  * The first line says "PuTTY-User-Key-File-1: " plus the name of the
293  * algorithm ("ssh-dss", "ssh-rsa" etc. Although, of course, this
294  * being PuTTY, "ssh-dss" is not supported.)
295  * 
296  * The next line says "Encryption: " plus an encryption type.
297  * Currently the only supported encryption types are "aes256-cbc"
298  * and "none".
299  * 
300  * The next line says "Comment: " plus the comment string.
301  * 
302  * Next there is a line saying "Public-Lines: " plus a number N.
303  * The following N lines contain a base64 encoding of the public
304  * part of the key. This is encoded as the standard SSH2 public key
305  * blob (with no initial length): so for RSA, for example, it will
306  * read
307  * 
308  *    string "ssh-rsa"
309  *    mpint  exponent
310  *    mpint  modulus
311  * 
312  * Next, there is a line saying "Private-Lines: " plus a number N,
313  * and then N lines containing the (potentially encrypted) private
314  * part of the key. For the key type "ssh-rsa", this will be
315  * composed of
316  * 
317  *    mpint  private_exponent
318  *    mpint  p                  (the larger of the two primes)
319  *    mpint  q                  (the smaller prime)
320  *    mpint  iqmp               (the inverse of q modulo p)
321  *    data   padding            (to reach a multiple of the cipher block size)
322  * 
323  * Finally, there is a line saying "Private-Hash: " plus a hex
324  * representation of a SHA-1 hash of the plaintext version of the
325  * private part, including the final padding.
326  * 
327  * If the key is encrypted, the encryption key is derived from the
328  * passphrase by means of a succession of SHA-1 hashes. Each hash
329  * is the hash of:
330  * 
331  *    uint32  sequence-number
332  *    string  passphrase
333  * 
334  * where the sequence-number increases from zero. As many of these
335  * hashes are used as necessary.
336  * 
337  * NOTE! It is important that all _public_ data can be verified
338  * with reference to the _private_ data. There exist attacks based
339  * on modifying the public key but leaving the private section
340  * intact.
341  * 
342  * With RSA, this is easy: verify that n = p*q, and also verify
343  * that e*d == 1 modulo (p-1)(q-1). With DSA (if we were ever to
344  * support it), we would need to store extra data in the private
345  * section other than just x.
346  */
347
348 static int read_header(FILE *fp, char *header) {
349     int len = 39;
350     int c;
351
352     while (len > 0) {
353         c = fgetc(fp);
354         if (c == '\n' || c == '\r' || c == EOF)
355             return 0;                  /* failure */
356         if (c == ':') {
357             c = fgetc(fp);
358             if (c != ' ')
359                 return 0;
360             *header = '\0';
361             return 1;                  /* success! */
362         }
363         if (len == 0)
364             return 0;                  /* failure */
365         *header++ = c;
366         len--;
367     }
368     return 0;                          /* failure */
369 }
370
371 static char *read_body(FILE *fp) {
372     char *text;
373     int len;
374     int size;
375     int c;
376
377     size = 128;
378     text = smalloc(size);
379     len = 0;
380     text[len] = '\0';
381
382     while (1) {
383         c = fgetc(fp);
384         if (c == '\r' || c == '\n') {
385             c = fgetc(fp);
386             if (c != '\r' && c != '\n' && c != EOF)
387                 ungetc(c, fp);
388             return text;
389         }
390         if (c == EOF) {
391             sfree(text);
392             return NULL;
393         }
394         if (len + 1 > size) {
395             size += 128;
396             text = srealloc(text, size);
397         }
398         text[len++] = c;
399         text[len] = '\0';
400     }
401 }
402
403 int base64_decode_atom(char *atom, unsigned char *out) {
404     int vals[4];
405     int i, v, len;
406     unsigned word;
407     char c;
408     
409     for (i = 0; i < 4; i++) {
410         c = atom[i];
411         if (c >= 'A' && c <= 'Z')
412             v = c - 'A';
413         else if (c >= 'a' && c <= 'z')
414             v = c - 'a' + 26;
415         else if (c >= '0' && c <= '9')
416             v = c - '0' + 52;
417         else if (c == '+')
418             v = 62;
419         else if (c == '/')
420             v = 63;
421         else if (c == '=')
422             v = -1;
423         else
424             return 0;                  /* invalid atom */
425         vals[i] = v;
426     }
427
428     if (vals[0] == -1 || vals[1] == -1)
429         return 0;
430     if (vals[2] == -1 && vals[3] != -1)
431         return 0;
432
433     if (vals[3] != -1)
434         len = 3;
435     else if (vals[2] != -1)
436         len = 2;
437     else
438         len = 1;
439
440     word = ((vals[0] << 18) |
441             (vals[1] << 12) |
442             ((vals[2] & 0x3F) << 6) |
443             (vals[3] & 0x3F));
444     out[0] = (word >> 16) & 0xFF;
445     if (len > 1)
446         out[1] = (word >> 8) & 0xFF;
447     if (len > 2)
448         out[2] = word & 0xFF;
449     return len;
450 }
451
452 static char *read_blob(FILE *fp, int nlines, int *bloblen) {
453     unsigned char *blob;
454     char *line;
455     int linelen, len;
456     int i, j, k;
457
458     /* We expect at most 64 base64 characters, ie 48 real bytes, per line. */
459     blob = smalloc(48 * nlines);
460     len = 0;
461     for (i = 0; i < nlines; i++) {
462         line = read_body(fp);
463         if (!line) {
464             sfree(blob);
465             return NULL;
466         }
467         linelen = strlen(line);
468         if (linelen % 4 != 0 || linelen > 64) {
469             sfree(blob);
470             sfree(line);
471             return NULL;
472         }
473         for (j = 0; j < linelen; j += 4) {
474             k = base64_decode_atom(line+j, blob+len);
475             if (!k) {
476                 sfree(line);
477                 sfree(blob);
478                 return NULL;
479             }
480             len += k;
481         }
482         sfree(line);
483     }
484     *bloblen = len;
485     return blob;
486 }
487
488 /*
489  * Magic error return value for when the passphrase is wrong.
490  */
491 struct ssh2_userkey ssh2_wrong_passphrase = {
492     NULL, NULL, NULL
493 };
494
495 struct ssh2_userkey *ssh2_load_userkey(char *filename, char *passphrase) {
496     FILE *fp;
497     char header[40], *b, *comment, *hash;
498     const struct ssh_signkey *alg;
499     struct ssh2_userkey *ret;
500     int cipher, cipherblk;
501     unsigned char *public_blob, *private_blob;
502     int public_blob_len, private_blob_len;
503     int i;
504
505     ret = NULL;                        /* return NULL for most errors */
506     comment = hash = NULL;
507     public_blob = private_blob = NULL;
508
509     fp = fopen(filename, "rb");
510     if (!fp)
511         goto error;
512
513     /* Read the first header line which contains the key type. */
514     if (!read_header(fp, header) || 0!=strcmp(header, "PuTTY-User-Key-File-1"))
515         goto error;
516     if ((b = read_body(fp)) == NULL)
517         goto error;
518     /* Select key algorithm structure. Currently only ssh-rsa. */
519     if (!strcmp(b, "ssh-rsa"))
520         alg = &ssh_rsa;
521     else {
522         sfree(b);
523         goto error;
524     }
525     sfree(b);
526     
527     /* Read the Encryption header line. */
528     if (!read_header(fp, header) || 0!=strcmp(header, "Encryption"))
529         goto error;
530     if ((b = read_body(fp)) == NULL)
531         goto error;
532     if (!strcmp(b, "aes256-cbc")) {
533         cipher = 1; cipherblk = 16;
534     } else if (!strcmp(b, "none")) {
535         cipher = 0; cipherblk = 1;
536     } else {
537         sfree(b);
538         goto error;
539     }
540     sfree(b);
541
542     /* Read the Comment header line. */
543     if (!read_header(fp, header) || 0!=strcmp(header, "Comment"))
544         goto error;
545     if ((comment = read_body(fp)) == NULL)
546         goto error;
547
548     /* Read the Public-Lines header line and the public blob. */
549     if (!read_header(fp, header) || 0!=strcmp(header, "Public-Lines"))
550         goto error;
551     if ((b = read_body(fp)) == NULL)
552         goto error;
553     i = atoi(b);
554     sfree(b);
555     if ((public_blob = read_blob(fp, i, &public_blob_len)) == NULL)
556         goto error;
557
558     /* Read the Private-Lines header line and the Private blob. */
559     if (!read_header(fp, header) || 0!=strcmp(header, "Private-Lines"))
560         goto error;
561     if ((b = read_body(fp)) == NULL)
562         goto error;
563     i = atoi(b);
564     sfree(b);
565     if ((private_blob = read_blob(fp, i, &private_blob_len)) == NULL)
566         goto error;
567
568     /* Read the Private-Hash header line. */
569     if (!read_header(fp, header) || 0!=strcmp(header, "Private-Hash"))
570         goto error;
571     if ((hash = read_body(fp)) == NULL)
572         goto error;
573
574     fclose(fp);
575     fp = NULL;
576
577     /*
578      * Decrypt the private blob.
579      */
580     if (cipher) {
581         unsigned char key[40];
582         SHA_State s;
583         int passlen;
584
585         if (!passphrase)
586             goto error;
587         if (private_blob_len % cipherblk)
588             goto error;
589
590         passlen = strlen(passphrase);
591
592         SHA_Init(&s);
593         SHA_Bytes(&s, "\0\0\0\0", 4);
594         SHA_Bytes(&s, passphrase, passlen);
595         SHA_Final(&s, key+0);
596         SHA_Init(&s);
597         SHA_Bytes(&s, "\0\0\0\1", 4);
598         SHA_Bytes(&s, passphrase, passlen);
599         SHA_Final(&s, key+20);
600         aes256_decrypt_pubkey(key, private_blob, private_blob_len);
601     }
602
603     /*
604      * Verify the private hash.
605      */
606     {
607         char realhash[41];
608         unsigned char binary[20];
609
610         SHA_Simple(private_blob, private_blob_len, binary);
611         for (i = 0; i < 20; i++)
612             sprintf(realhash+2*i, "%02x", binary[i]);
613
614         if (strcmp(hash, realhash)) {
615             /* An incorrect hash is an unconditional Error if the key is
616              * unencrypted. Otherwise, it means Wrong Passphrase. */
617             ret = cipher ? SSH2_WRONG_PASSPHRASE : NULL;
618             goto error;
619         }
620     }
621     sfree(hash);
622
623     /*
624      * Create and return the key.
625      */
626     ret = smalloc(sizeof(struct ssh2_userkey));
627     ret->alg = alg;
628     ret->comment = comment;
629     ret->data = alg->createkey(public_blob, public_blob_len,
630                                private_blob, private_blob_len);
631     if (!ret->data) {
632         sfree(ret->comment);
633         sfree(ret);
634         ret = NULL;
635     }
636     sfree(public_blob);
637     sfree(private_blob);
638     return ret;
639
640     /*
641      * Error processing.
642      */
643     error:
644     if (fp) fclose(fp);
645     if (comment) sfree(comment);
646     if (hash) sfree(hash);
647     if (public_blob) sfree(public_blob);
648     if (private_blob) sfree(private_blob);
649     return ret;
650 }
651
652 char *ssh2_userkey_loadpub(char *filename, char **algorithm, int *pub_blob_len) {
653     FILE *fp;
654     char header[40], *b;
655     const struct ssh_signkey *alg;
656     unsigned char *public_blob;
657     int public_blob_len;
658     int i;
659
660     public_blob = NULL;
661
662     fp = fopen(filename, "rb");
663     if (!fp)
664         goto error;
665
666     /* Read the first header line which contains the key type. */
667     if (!read_header(fp, header) || 0!=strcmp(header, "PuTTY-User-Key-File-1"))
668         goto error;
669     if ((b = read_body(fp)) == NULL)
670         goto error;
671     /* Select key algorithm structure. Currently only ssh-rsa. */
672     if (!strcmp(b, "ssh-rsa"))
673         alg = &ssh_rsa;
674     else {
675         sfree(b);
676         goto error;
677     }
678     sfree(b);
679     
680     /* Read the Encryption header line. */
681     if (!read_header(fp, header) || 0!=strcmp(header, "Encryption"))
682         goto error;
683     if ((b = read_body(fp)) == NULL)
684         goto error;
685     sfree(b);                          /* we don't care */
686
687     /* Read the Comment header line. */
688     if (!read_header(fp, header) || 0!=strcmp(header, "Comment"))
689         goto error;
690     if ((b = read_body(fp)) == NULL)
691         goto error;
692     sfree(b);                          /* we don't care */
693
694     /* Read the Public-Lines header line and the public blob. */
695     if (!read_header(fp, header) || 0!=strcmp(header, "Public-Lines"))
696         goto error;
697     if ((b = read_body(fp)) == NULL)
698         goto error;
699     i = atoi(b);
700     sfree(b);
701     if ((public_blob = read_blob(fp, i, &public_blob_len)) == NULL)
702         goto error;
703
704     fclose(fp);
705     *pub_blob_len = public_blob_len;
706     *algorithm = alg->name;
707     return public_blob;
708
709     /*
710      * Error processing.
711      */
712     error:
713     if (fp) fclose(fp);
714     if (public_blob) sfree(public_blob);
715     return NULL;
716 }
717
718 int ssh2_userkey_encrypted(char *filename, char **commentptr) {
719     FILE *fp;
720     char header[40], *b, *comment;
721     int ret;
722
723     if (commentptr) *commentptr = NULL;
724
725     fp = fopen(filename, "rb");
726     if (!fp)
727         return 0;
728     if (!read_header(fp, header) || 0!=strcmp(header, "PuTTY-User-Key-File-1")) {
729         fclose(fp); return 0;
730     }
731     if ((b = read_body(fp)) == NULL) {
732         fclose(fp); return 0;
733     }
734     sfree(b);                          /* we don't care about key type here */
735     /* Read the Encryption header line. */
736     if (!read_header(fp, header) || 0!=strcmp(header, "Encryption")) {
737         fclose(fp); return 0;
738     }
739     if ((b = read_body(fp)) == NULL) {
740         fclose(fp); return 0;
741     }
742
743     /* Read the Comment header line. */
744     if (!read_header(fp, header) || 0!=strcmp(header, "Comment")) {
745         fclose(fp); sfree(b); return 1;
746     }
747     if ((comment = read_body(fp)) == NULL) {
748         fclose(fp); sfree(b); return 1;
749     }
750
751     if (commentptr) *commentptr = comment;
752
753     fclose(fp);
754     if (!strcmp(b, "aes256-cbc"))
755         ret = 1;
756     else
757         ret = 0;
758     sfree(b);
759     return ret;
760 }
761
762 int base64_lines(int datalen) {
763     /* When encoding, we use 64 chars/line, which equals 48 real chars. */
764     return (datalen+47) / 48;
765 }
766
767 void base64_encode_atom(unsigned char *data, int n, char *out) {
768     static const char base64_chars[] =
769         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
770
771     unsigned word;
772
773     word = data[0] << 16;
774     if (n > 1)
775         word |= data[1] << 8;
776     if (n > 2)
777         word |= data[2];
778     out[0] = base64_chars[(word >> 18) & 0x3F];
779     out[1] = base64_chars[(word >> 12) & 0x3F];
780     if (n > 1)
781         out[2] = base64_chars[(word >> 6) & 0x3F];
782     else
783         out[2] = '=';
784     if (n > 2)
785         out[3] = base64_chars[word & 0x3F];
786     else
787         out[3] = '=';
788 }
789
790 void base64_encode(FILE *fp, unsigned char *data, int datalen) {
791     int linelen = 0;
792     char out[4];
793     int n;
794
795     while (datalen > 0) {
796         if (linelen >= 64) {
797             linelen = 0;
798             fputc('\n', fp);
799         }
800         n = (datalen < 3 ? datalen : 3);
801         base64_encode_atom(data, n, out);
802         data += n;
803         datalen -= n;
804         fwrite(out, 1, 4, fp);
805         linelen += 4;
806     }
807     fputc('\n', fp);
808 }
809
810 int ssh2_save_userkey(char *filename, struct ssh2_userkey *key, char *passphrase) {
811     FILE *fp;
812     unsigned char *pub_blob, *priv_blob, *priv_blob_encrypted;
813     int pub_blob_len, priv_blob_len, priv_encrypted_len;
814     int passlen;
815     int cipherblk;
816     int i;
817     char *cipherstr;
818     unsigned char priv_hash[20];
819
820     /*
821      * Fetch the key component blobs.
822      */
823     pub_blob = key->alg->public_blob(key->data, &pub_blob_len);
824     priv_blob = key->alg->private_blob(key->data, &priv_blob_len);
825     if (!pub_blob || !priv_blob) {
826         sfree(pub_blob);
827         sfree(priv_blob);
828         return 0;
829     }
830
831     /*
832      * Determine encryption details, and encrypt the private blob.
833      */
834     if (passphrase) {
835         cipherstr = "aes256-cbc";
836         cipherblk = 16;
837     } else {
838         cipherstr = "none";
839         cipherblk = 1;
840     }
841     priv_encrypted_len = priv_blob_len + cipherblk - 1;
842     priv_encrypted_len -= priv_encrypted_len % cipherblk;
843     priv_blob_encrypted = smalloc(priv_encrypted_len);
844     memset(priv_blob_encrypted, 0, priv_encrypted_len);
845     memcpy(priv_blob_encrypted, priv_blob, priv_blob_len);
846     /* Create padding based on the SHA hash of the unpadded blob. This prevents
847      * too easy a known-plaintext attack on the last block. */
848     SHA_Simple(priv_blob, priv_blob_len, priv_hash);
849     assert(priv_encrypted_len - priv_blob_len < 20);
850     memcpy(priv_blob_encrypted + priv_blob_len, priv_hash,
851            priv_encrypted_len - priv_blob_len);
852
853     /* Now create the _real_ private hash. */
854     SHA_Simple(priv_blob_encrypted, priv_encrypted_len, priv_hash);
855
856     if (passphrase) {
857         char key[40];
858         SHA_State s;
859
860         passlen = strlen(passphrase);
861
862         SHA_Init(&s);
863         SHA_Bytes(&s, "\0\0\0\0", 4);
864         SHA_Bytes(&s, passphrase, passlen);
865         SHA_Final(&s, key+0);
866         SHA_Init(&s);
867         SHA_Bytes(&s, "\0\0\0\1", 4);
868         SHA_Bytes(&s, passphrase, passlen);
869         SHA_Final(&s, key+20);
870         aes256_encrypt_pubkey(key, priv_blob_encrypted, priv_encrypted_len);
871     }
872
873     fp = fopen(filename, "w");
874     if (!fp)
875         return 0;
876     fprintf(fp, "PuTTY-User-Key-File-1: %s\n", key->alg->name);
877     fprintf(fp, "Encryption: %s\n", cipherstr);
878     fprintf(fp, "Comment: %s\n", key->comment);
879     fprintf(fp, "Public-Lines: %d\n", base64_lines(pub_blob_len));
880     base64_encode(fp, pub_blob, pub_blob_len);
881     fprintf(fp, "Private-Lines: %d\n", base64_lines(priv_encrypted_len));
882     base64_encode(fp, priv_blob_encrypted, priv_encrypted_len);
883     fprintf(fp, "Private-Hash: ");
884     for (i = 0; i < 20; i++)
885         fprintf(fp, "%02x", priv_hash[i]);
886     fprintf(fp, "\n");
887     fclose(fp);
888     return 1;
889 }
890
891 /* ----------------------------------------------------------------------
892  * A function to determine which version of SSH to try on a private
893  * key file. Returns 0 on failure, 1 or 2 on success.
894  */
895 int keyfile_version(char *filename) {
896     FILE *fp;
897     int i;
898
899     fp = fopen(filename, "r");
900     if (!fp)
901         return 0;
902     i = fgetc(fp);
903     fclose(fp);
904     if (i == 'S')
905         return 1;                      /* "SSH PRIVATE KEY FORMAT" etc */
906     if (i == 'P')                      /* "PuTTY-User-Key-File" etc */
907         return 2;
908     return 0;                          /* unrecognised or EOF */
909 }