]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - sshpubk.c
Introduced wrapper macros snew(), snewn() and sresize() for the
[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 "putty.h"
13 #include "ssh.h"
14 #include "misc.h"
15
16 #define PUT_32BIT(cp, value) do { \
17   (cp)[3] = (value); \
18   (cp)[2] = (value) >> 8; \
19   (cp)[1] = (value) >> 16; \
20   (cp)[0] = (value) >> 24; } while (0)
21
22 #define GET_32BIT(cp) \
23     (((unsigned long)(unsigned char)(cp)[0] << 24) | \
24     ((unsigned long)(unsigned char)(cp)[1] << 16) | \
25     ((unsigned long)(unsigned char)(cp)[2] << 8) | \
26     ((unsigned long)(unsigned char)(cp)[3]))
27
28 #define rsa_signature "SSH PRIVATE KEY FILE FORMAT 1.1\n"
29
30 #define BASE64_TOINT(x) ( (x)-'A'<26 ? (x)-'A'+0 :\
31                           (x)-'a'<26 ? (x)-'a'+26 :\
32                           (x)-'0'<10 ? (x)-'0'+52 :\
33                           (x)=='+' ? 62 : \
34                           (x)=='/' ? 63 : 0 )
35
36 static int loadrsakey_main(FILE * fp, struct RSAKey *key, int pub_only,
37                            char **commentptr, char *passphrase)
38 {
39     unsigned char buf[16384];
40     unsigned char keybuf[16];
41     int len;
42     int i, j, ciphertype;
43     int ret = 0;
44     struct MD5Context md5c;
45     char *comment;
46
47     /* Slurp the whole file (minus the header) into a buffer. */
48     len = fread(buf, 1, sizeof(buf), fp);
49     fclose(fp);
50     if (len < 0 || len == sizeof(buf))
51         goto end;                      /* file too big or not read */
52
53     i = 0;
54
55     /*
56      * A zero byte. (The signature includes a terminating NUL.)
57      */
58     if (len - i < 1 || buf[i] != 0)
59         goto end;
60     i++;
61
62     /* One byte giving encryption type, and one reserved uint32. */
63     if (len - i < 1)
64         goto end;
65     ciphertype = buf[i];
66     if (ciphertype != 0 && ciphertype != SSH_CIPHER_3DES)
67         goto end;
68     i++;
69     if (len - i < 4)
70         goto end;                      /* reserved field not present */
71     if (buf[i] != 0 || buf[i + 1] != 0 || buf[i + 2] != 0
72         || buf[i + 3] != 0) goto end;  /* reserved field nonzero, panic! */
73     i += 4;
74
75     /* Now the serious stuff. An ordinary SSH 1 public key. */
76     i += makekey(buf + i, key, NULL, 1);
77     if (len - i < 0)
78         goto end;                      /* overran */
79
80     if (pub_only) {
81         ret = 1;
82         goto end;
83     }
84
85     /* Next, the comment field. */
86     j = GET_32BIT(buf + i);
87     i += 4;
88     if (len - i < j)
89         goto end;
90     comment = snewn(j + 1, char);
91     if (comment) {
92         memcpy(comment, buf + i, j);
93         comment[j] = '\0';
94     }
95     i += j;
96     if (commentptr)
97         *commentptr = comment;
98     if (key)
99         key->comment = comment;
100     if (!key) {
101         return ciphertype != 0;
102     }
103
104     /*
105      * Decrypt remainder of buffer.
106      */
107     if (ciphertype) {
108         MD5Init(&md5c);
109         MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase));
110         MD5Final(keybuf, &md5c);
111         des3_decrypt_pubkey(keybuf, buf + i, (len - i + 7) & ~7);
112         memset(keybuf, 0, sizeof(keybuf));      /* burn the evidence */
113     }
114
115     /*
116      * We are now in the secret part of the key. The first four
117      * bytes should be of the form a, b, a, b.
118      */
119     if (len - i < 4)
120         goto end;
121     if (buf[i] != buf[i + 2] || buf[i + 1] != buf[i + 3]) {
122         ret = -1;
123         goto end;
124     }
125     i += 4;
126
127     /*
128      * After that, we have one further bignum which is our
129      * decryption exponent, and then the three auxiliary values
130      * (iqmp, q, p).
131      */
132     i += makeprivate(buf + i, key);
133     if (len - i < 0)
134         goto end;
135     i += ssh1_read_bignum(buf + i, &key->iqmp);
136     if (len - i < 0)
137         goto end;
138     i += ssh1_read_bignum(buf + i, &key->q);
139     if (len - i < 0)
140         goto end;
141     i += ssh1_read_bignum(buf + i, &key->p);
142     if (len - i < 0)
143         goto end;
144
145     if (!rsa_verify(key)) {
146         freersakey(key);
147         ret = 0;
148     } else
149         ret = 1;
150
151   end:
152     memset(buf, 0, sizeof(buf));       /* burn the evidence */
153     return ret;
154 }
155
156 int loadrsakey(const Filename *filename, struct RSAKey *key, char *passphrase)
157 {
158     FILE *fp;
159     char buf[64];
160
161     fp = f_open(*filename, "rb");
162     if (!fp)
163         return 0;                      /* doesn't even exist */
164
165     /*
166      * Read the first line of the file and see if it's a v1 private
167      * key file.
168      */
169     if (fgets(buf, sizeof(buf), fp) && !strcmp(buf, rsa_signature)) {
170         return loadrsakey_main(fp, key, FALSE, NULL, passphrase);
171     }
172
173     /*
174      * Otherwise, we have nothing. Return empty-handed.
175      */
176     fclose(fp);
177     return 0;
178 }
179
180 /*
181  * See whether an RSA key is encrypted. Return its comment field as
182  * well.
183  */
184 int rsakey_encrypted(const Filename *filename, char **comment)
185 {
186     FILE *fp;
187     char buf[64];
188
189     fp = f_open(*filename, "rb");
190     if (!fp)
191         return 0;                      /* doesn't even exist */
192
193     /*
194      * Read the first line of the file and see if it's a v1 private
195      * key file.
196      */
197     if (fgets(buf, sizeof(buf), fp) && !strcmp(buf, rsa_signature)) {
198         return loadrsakey_main(fp, NULL, FALSE, comment, NULL);
199     }
200     fclose(fp);
201     return 0;                          /* wasn't the right kind of file */
202 }
203
204 /*
205  * Return a malloc'ed chunk of memory containing the public blob of
206  * an RSA key, as given in the agent protocol (modulus bits,
207  * exponent, modulus).
208  */
209 int rsakey_pubblob(const Filename *filename, void **blob, int *bloblen)
210 {
211     FILE *fp;
212     char buf[64];
213     struct RSAKey key;
214     int ret;
215
216     /* Default return if we fail. */
217     *blob = NULL;
218     *bloblen = 0;
219     ret = 0;
220
221     fp = f_open(*filename, "rb");
222     if (!fp)
223         return 0;                      /* doesn't even exist */
224
225     /*
226      * Read the first line of the file and see if it's a v1 private
227      * key file.
228      */
229     if (fgets(buf, sizeof(buf), fp) && !strcmp(buf, rsa_signature)) {
230         memset(&key, 0, sizeof(key));
231         if (loadrsakey_main(fp, &key, TRUE, NULL, NULL)) {
232             *blob = rsa_public_blob(&key, bloblen);
233             freersakey(&key);
234             ret = 1;
235         }
236     }
237     fclose(fp);
238     return ret;
239 }
240
241 /*
242  * Save an RSA key file. Return nonzero on success.
243  */
244 int saversakey(const Filename *filename, struct RSAKey *key, char *passphrase)
245 {
246     unsigned char buf[16384];
247     unsigned char keybuf[16];
248     struct MD5Context md5c;
249     unsigned char *p, *estart;
250     FILE *fp;
251
252     /*
253      * Write the initial signature.
254      */
255     p = buf;
256     memcpy(p, rsa_signature, sizeof(rsa_signature));
257     p += sizeof(rsa_signature);
258
259     /*
260      * One byte giving encryption type, and one reserved (zero)
261      * uint32.
262      */
263     *p++ = (passphrase ? SSH_CIPHER_3DES : 0);
264     PUT_32BIT(p, 0);
265     p += 4;
266
267     /*
268      * An ordinary SSH 1 public key consists of: a uint32
269      * containing the bit count, then two bignums containing the
270      * modulus and exponent respectively.
271      */
272     PUT_32BIT(p, bignum_bitcount(key->modulus));
273     p += 4;
274     p += ssh1_write_bignum(p, key->modulus);
275     p += ssh1_write_bignum(p, key->exponent);
276
277     /*
278      * A string containing the comment field.
279      */
280     if (key->comment) {
281         PUT_32BIT(p, strlen(key->comment));
282         p += 4;
283         memcpy(p, key->comment, strlen(key->comment));
284         p += strlen(key->comment);
285     } else {
286         PUT_32BIT(p, 0);
287         p += 4;
288     }
289
290     /*
291      * The encrypted portion starts here.
292      */
293     estart = p;
294
295     /*
296      * Two bytes, then the same two bytes repeated.
297      */
298     *p++ = random_byte();
299     *p++ = random_byte();
300     p[0] = p[-2];
301     p[1] = p[-1];
302     p += 2;
303
304     /*
305      * Four more bignums: the decryption exponent, then iqmp, then
306      * q, then p.
307      */
308     p += ssh1_write_bignum(p, key->private_exponent);
309     p += ssh1_write_bignum(p, key->iqmp);
310     p += ssh1_write_bignum(p, key->q);
311     p += ssh1_write_bignum(p, key->p);
312
313     /*
314      * Now write zeros until the encrypted portion is a multiple of
315      * 8 bytes.
316      */
317     while ((p - estart) % 8)
318         *p++ = '\0';
319
320     /*
321      * Now encrypt the encrypted portion.
322      */
323     if (passphrase) {
324         MD5Init(&md5c);
325         MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase));
326         MD5Final(keybuf, &md5c);
327         des3_encrypt_pubkey(keybuf, estart, p - estart);
328         memset(keybuf, 0, sizeof(keybuf));      /* burn the evidence */
329     }
330
331     /*
332      * Done. Write the result to the file.
333      */
334     fp = f_open(*filename, "wb");
335     if (fp) {
336         int ret = (fwrite(buf, 1, p - buf, fp) == (size_t) (p - buf));
337         ret = ret && (fclose(fp) == 0);
338         return ret;
339     } else
340         return 0;
341 }
342
343 /* ----------------------------------------------------------------------
344  * SSH2 private key load/store functions.
345  */
346
347 /*
348  * PuTTY's own format for SSH2 keys is as follows:
349  *
350  * The file is text. Lines are terminated by CRLF, although CR-only
351  * and LF-only are tolerated on input.
352  *
353  * The first line says "PuTTY-User-Key-File-2: " plus the name of the
354  * algorithm ("ssh-dss", "ssh-rsa" etc).
355  *
356  * The next line says "Encryption: " plus an encryption type.
357  * Currently the only supported encryption types are "aes256-cbc"
358  * and "none".
359  *
360  * The next line says "Comment: " plus the comment string.
361  *
362  * Next there is a line saying "Public-Lines: " plus a number N.
363  * The following N lines contain a base64 encoding of the public
364  * part of the key. This is encoded as the standard SSH2 public key
365  * blob (with no initial length): so for RSA, for example, it will
366  * read
367  *
368  *    string "ssh-rsa"
369  *    mpint  exponent
370  *    mpint  modulus
371  *
372  * Next, there is a line saying "Private-Lines: " plus a number N,
373  * and then N lines containing the (potentially encrypted) private
374  * part of the key. For the key type "ssh-rsa", this will be
375  * composed of
376  *
377  *    mpint  private_exponent
378  *    mpint  p                  (the larger of the two primes)
379  *    mpint  q                  (the smaller prime)
380  *    mpint  iqmp               (the inverse of q modulo p)
381  *    data   padding            (to reach a multiple of the cipher block size)
382  *
383  * And for "ssh-dss", it will be composed of
384  *
385  *    mpint  x                  (the private key parameter)
386  *  [ string hash   20-byte hash of mpints p || q || g   only in old format ]
387  * 
388  * Finally, there is a line saying "Private-MAC: " plus a hex
389  * representation of a HMAC-SHA-1 of:
390  *
391  *    string  name of algorithm ("ssh-dss", "ssh-rsa")
392  *    string  encryption type
393  *    string  comment
394  *    string  public-blob
395  *    string  private-plaintext (the plaintext version of the
396  *                               private part, including the final
397  *                               padding)
398  * 
399  * The key to the MAC is itself a SHA-1 hash of:
400  * 
401  *    data    "putty-private-key-file-mac-key"
402  *    data    passphrase
403  *
404  * Encrypted keys should have a MAC, whereas unencrypted ones must
405  * have a hash.
406  *
407  * If the key is encrypted, the encryption key is derived from the
408  * passphrase by means of a succession of SHA-1 hashes. Each hash
409  * is the hash of:
410  *
411  *    uint32  sequence-number
412  *    data    passphrase
413  *
414  * where the sequence-number increases from zero. As many of these
415  * hashes are used as necessary.
416  *
417  * For backwards compatibility with snapshots between 0.51 and
418  * 0.52, we also support the older key file format, which begins
419  * with "PuTTY-User-Key-File-1" (version number differs). In this
420  * format the Private-MAC: field only covers the private-plaintext
421  * field and nothing else (and without the 4-byte string length on
422  * the front too). Moreover, for RSA keys the Private-MAC: field
423  * can be replaced with a Private-Hash: field which is a plain
424  * SHA-1 hash instead of an HMAC. This is not allowable in DSA
425  * keys. (Yes, the old format was a mess. Guess why it changed :-)
426  */
427
428 static int read_header(FILE * fp, char *header)
429 {
430     int len = 39;
431     int c;
432
433     while (len > 0) {
434         c = fgetc(fp);
435         if (c == '\n' || c == '\r' || c == EOF)
436             return 0;                  /* failure */
437         if (c == ':') {
438             c = fgetc(fp);
439             if (c != ' ')
440                 return 0;
441             *header = '\0';
442             return 1;                  /* success! */
443         }
444         if (len == 0)
445             return 0;                  /* failure */
446         *header++ = c;
447         len--;
448     }
449     return 0;                          /* failure */
450 }
451
452 static char *read_body(FILE * fp)
453 {
454     char *text;
455     int len;
456     int size;
457     int c;
458
459     size = 128;
460     text = snewn(size, char);
461     len = 0;
462     text[len] = '\0';
463
464     while (1) {
465         c = fgetc(fp);
466         if (c == '\r' || c == '\n') {
467             c = fgetc(fp);
468             if (c != '\r' && c != '\n' && c != EOF)
469                 ungetc(c, fp);
470             return text;
471         }
472         if (c == EOF) {
473             sfree(text);
474             return NULL;
475         }
476         if (len + 1 > size) {
477             size += 128;
478             text = sresize(text, size, char);
479         }
480         text[len++] = c;
481         text[len] = '\0';
482     }
483 }
484
485 int base64_decode_atom(char *atom, unsigned char *out)
486 {
487     int vals[4];
488     int i, v, len;
489     unsigned word;
490     char c;
491
492     for (i = 0; i < 4; i++) {
493         c = atom[i];
494         if (c >= 'A' && c <= 'Z')
495             v = c - 'A';
496         else if (c >= 'a' && c <= 'z')
497             v = c - 'a' + 26;
498         else if (c >= '0' && c <= '9')
499             v = c - '0' + 52;
500         else if (c == '+')
501             v = 62;
502         else if (c == '/')
503             v = 63;
504         else if (c == '=')
505             v = -1;
506         else
507             return 0;                  /* invalid atom */
508         vals[i] = v;
509     }
510
511     if (vals[0] == -1 || vals[1] == -1)
512         return 0;
513     if (vals[2] == -1 && vals[3] != -1)
514         return 0;
515
516     if (vals[3] != -1)
517         len = 3;
518     else if (vals[2] != -1)
519         len = 2;
520     else
521         len = 1;
522
523     word = ((vals[0] << 18) |
524             (vals[1] << 12) | ((vals[2] & 0x3F) << 6) | (vals[3] & 0x3F));
525     out[0] = (word >> 16) & 0xFF;
526     if (len > 1)
527         out[1] = (word >> 8) & 0xFF;
528     if (len > 2)
529         out[2] = word & 0xFF;
530     return len;
531 }
532
533 static unsigned char *read_blob(FILE * fp, int nlines, int *bloblen)
534 {
535     unsigned char *blob;
536     char *line;
537     int linelen, len;
538     int i, j, k;
539
540     /* We expect at most 64 base64 characters, ie 48 real bytes, per line. */
541     blob = snewn(48 * nlines, unsigned char);
542     len = 0;
543     for (i = 0; i < nlines; i++) {
544         line = read_body(fp);
545         if (!line) {
546             sfree(blob);
547             return NULL;
548         }
549         linelen = strlen(line);
550         if (linelen % 4 != 0 || linelen > 64) {
551             sfree(blob);
552             sfree(line);
553             return NULL;
554         }
555         for (j = 0; j < linelen; j += 4) {
556             k = base64_decode_atom(line + j, blob + len);
557             if (!k) {
558                 sfree(line);
559                 sfree(blob);
560                 return NULL;
561             }
562             len += k;
563         }
564         sfree(line);
565     }
566     *bloblen = len;
567     return blob;
568 }
569
570 /*
571  * Magic error return value for when the passphrase is wrong.
572  */
573 struct ssh2_userkey ssh2_wrong_passphrase = {
574     NULL, NULL, NULL
575 };
576
577 struct ssh2_userkey *ssh2_load_userkey(const Filename *filename,
578                                        char *passphrase)
579 {
580     FILE *fp;
581     char header[40], *b, *encryption, *comment, *mac;
582     const struct ssh_signkey *alg;
583     struct ssh2_userkey *ret;
584     int cipher, cipherblk;
585     unsigned char *public_blob, *private_blob;
586     int public_blob_len, private_blob_len;
587     int i, is_mac, old_fmt;
588     int passlen = passphrase ? strlen(passphrase) : 0;
589
590     ret = NULL;                        /* return NULL for most errors */
591     encryption = comment = mac = NULL;
592     public_blob = private_blob = NULL;
593
594     fp = f_open(*filename, "rb");
595     if (!fp)
596         goto error;
597
598     /* Read the first header line which contains the key type. */
599     if (!read_header(fp, header))
600         goto error;
601     if (0 == strcmp(header, "PuTTY-User-Key-File-2")) {
602         old_fmt = 0;
603     } else if (0 == strcmp(header, "PuTTY-User-Key-File-1")) {
604         /* this is an old key file; warn and then continue */
605         old_keyfile_warning();
606         old_fmt = 1;
607     } else
608         goto error;
609     if ((b = read_body(fp)) == NULL)
610         goto error;
611     /* Select key algorithm structure. */
612     if (!strcmp(b, "ssh-rsa"))
613         alg = &ssh_rsa;
614     else if (!strcmp(b, "ssh-dss"))
615         alg = &ssh_dss;
616     else {
617         sfree(b);
618         goto error;
619     }
620     sfree(b);
621
622     /* Read the Encryption header line. */
623     if (!read_header(fp, header) || 0 != strcmp(header, "Encryption"))
624         goto error;
625     if ((encryption = read_body(fp)) == NULL)
626         goto error;
627     if (!strcmp(encryption, "aes256-cbc")) {
628         cipher = 1;
629         cipherblk = 16;
630     } else if (!strcmp(encryption, "none")) {
631         cipher = 0;
632         cipherblk = 1;
633     } else {
634         sfree(encryption);
635         goto error;
636     }
637
638     /* Read the Comment header line. */
639     if (!read_header(fp, header) || 0 != strcmp(header, "Comment"))
640         goto error;
641     if ((comment = read_body(fp)) == NULL)
642         goto error;
643
644     /* Read the Public-Lines header line and the public blob. */
645     if (!read_header(fp, header) || 0 != strcmp(header, "Public-Lines"))
646         goto error;
647     if ((b = read_body(fp)) == NULL)
648         goto error;
649     i = atoi(b);
650     sfree(b);
651     if ((public_blob = read_blob(fp, i, &public_blob_len)) == NULL)
652         goto error;
653
654     /* Read the Private-Lines header line and the Private blob. */
655     if (!read_header(fp, header) || 0 != strcmp(header, "Private-Lines"))
656         goto error;
657     if ((b = read_body(fp)) == NULL)
658         goto error;
659     i = atoi(b);
660     sfree(b);
661     if ((private_blob = read_blob(fp, i, &private_blob_len)) == NULL)
662         goto error;
663
664     /* Read the Private-MAC or Private-Hash header line. */
665     if (!read_header(fp, header))
666         goto error;
667     if (0 == strcmp(header, "Private-MAC")) {
668         if ((mac = read_body(fp)) == NULL)
669             goto error;
670         is_mac = 1;
671     } else if (0 == strcmp(header, "Private-Hash") &&
672                            alg == &ssh_rsa && old_fmt) {
673         if ((mac = read_body(fp)) == NULL)
674             goto error;
675         is_mac = 0;
676     } else
677         goto error;
678
679     fclose(fp);
680     fp = NULL;
681
682     /*
683      * Decrypt the private blob.
684      */
685     if (cipher) {
686         unsigned char key[40];
687         SHA_State s;
688
689         if (!passphrase)
690             goto error;
691         if (private_blob_len % cipherblk)
692             goto error;
693
694         SHA_Init(&s);
695         SHA_Bytes(&s, "\0\0\0\0", 4);
696         SHA_Bytes(&s, passphrase, passlen);
697         SHA_Final(&s, key + 0);
698         SHA_Init(&s);
699         SHA_Bytes(&s, "\0\0\0\1", 4);
700         SHA_Bytes(&s, passphrase, passlen);
701         SHA_Final(&s, key + 20);
702         aes256_decrypt_pubkey(key, private_blob, private_blob_len);
703     }
704
705     /*
706      * Verify the MAC.
707      */
708     {
709         char realmac[41];
710         unsigned char binary[20];
711         unsigned char *macdata;
712         int maclen;
713         int free_macdata;
714
715         if (old_fmt) {
716             /* MAC (or hash) only covers the private blob. */
717             macdata = private_blob;
718             maclen = private_blob_len;
719             free_macdata = 0;
720         } else {
721             unsigned char *p;
722             int namelen = strlen(alg->name);
723             int enclen = strlen(encryption);
724             int commlen = strlen(comment);
725             maclen = (4 + namelen +
726                       4 + enclen +
727                       4 + commlen +
728                       4 + public_blob_len +
729                       4 + private_blob_len);
730             macdata = snewn(maclen, unsigned char);
731             p = macdata;
732 #define DO_STR(s,len) PUT_32BIT(p,(len));memcpy(p+4,(s),(len));p+=4+(len)
733             DO_STR(alg->name, namelen);
734             DO_STR(encryption, enclen);
735             DO_STR(comment, commlen);
736             DO_STR(public_blob, public_blob_len);
737             DO_STR(private_blob, private_blob_len);
738
739             free_macdata = 1;
740         }
741
742         if (is_mac) {
743             SHA_State s;
744             unsigned char mackey[20];
745             char header[] = "putty-private-key-file-mac-key";
746
747             SHA_Init(&s);
748             SHA_Bytes(&s, header, sizeof(header)-1);
749             if (passphrase)
750                 SHA_Bytes(&s, passphrase, passlen);
751             SHA_Final(&s, mackey);
752
753             hmac_sha1_simple(mackey, 20, macdata, maclen, binary);
754
755             memset(mackey, 0, sizeof(mackey));
756             memset(&s, 0, sizeof(s));
757         } else {
758             SHA_Simple(macdata, maclen, binary);
759         }
760
761         if (free_macdata) {
762             memset(macdata, 0, maclen);
763             sfree(macdata);
764         }
765
766         for (i = 0; i < 20; i++)
767             sprintf(realmac + 2 * i, "%02x", binary[i]);
768
769         if (strcmp(mac, realmac)) {
770             /* An incorrect MAC is an unconditional Error if the key is
771              * unencrypted. Otherwise, it means Wrong Passphrase. */
772             ret = cipher ? SSH2_WRONG_PASSPHRASE : NULL;
773             goto error;
774         }
775     }
776     sfree(mac);
777
778     /*
779      * Create and return the key.
780      */
781     ret = snew(struct ssh2_userkey);
782     ret->alg = alg;
783     ret->comment = comment;
784     ret->data = alg->createkey(public_blob, public_blob_len,
785                                private_blob, private_blob_len);
786     if (!ret->data) {
787         sfree(ret->comment);
788         sfree(ret);
789         ret = NULL;
790     }
791     sfree(public_blob);
792     sfree(private_blob);
793     sfree(encryption);
794     return ret;
795
796     /*
797      * Error processing.
798      */
799   error:
800     if (fp)
801         fclose(fp);
802     if (comment)
803         sfree(comment);
804     if (encryption)
805         sfree(encryption);
806     if (mac)
807         sfree(mac);
808     if (public_blob)
809         sfree(public_blob);
810     if (private_blob)
811         sfree(private_blob);
812     return ret;
813 }
814
815 char *ssh2_userkey_loadpub(const Filename *filename, char **algorithm,
816                            int *pub_blob_len)
817 {
818     FILE *fp;
819     char header[40], *b;
820     const struct ssh_signkey *alg;
821     unsigned char *public_blob;
822     int public_blob_len;
823     int i;
824
825     public_blob = NULL;
826
827     fp = f_open(*filename, "rb");
828     if (!fp)
829         goto error;
830
831     /* Read the first header line which contains the key type. */
832     if (!read_header(fp, header)
833         || (0 != strcmp(header, "PuTTY-User-Key-File-2") &&
834             0 != strcmp(header, "PuTTY-User-Key-File-1")))
835         goto error;
836     if ((b = read_body(fp)) == NULL)
837         goto error;
838     /* Select key algorithm structure. Currently only ssh-rsa. */
839     if (!strcmp(b, "ssh-rsa"))
840         alg = &ssh_rsa;
841     else if (!strcmp(b, "ssh-dss"))
842         alg = &ssh_dss;
843     else {
844         sfree(b);
845         goto error;
846     }
847     sfree(b);
848
849     /* Read the Encryption header line. */
850     if (!read_header(fp, header) || 0 != strcmp(header, "Encryption"))
851         goto error;
852     if ((b = read_body(fp)) == NULL)
853         goto error;
854     sfree(b);                          /* we don't care */
855
856     /* Read the Comment header line. */
857     if (!read_header(fp, header) || 0 != strcmp(header, "Comment"))
858         goto error;
859     if ((b = read_body(fp)) == NULL)
860         goto error;
861     sfree(b);                          /* we don't care */
862
863     /* Read the Public-Lines header line and the public blob. */
864     if (!read_header(fp, header) || 0 != strcmp(header, "Public-Lines"))
865         goto error;
866     if ((b = read_body(fp)) == NULL)
867         goto error;
868     i = atoi(b);
869     sfree(b);
870     if ((public_blob = read_blob(fp, i, &public_blob_len)) == NULL)
871         goto error;
872
873     fclose(fp);
874     if (pub_blob_len)
875         *pub_blob_len = public_blob_len;
876     if (algorithm)
877         *algorithm = alg->name;
878     return (char *)public_blob;
879
880     /*
881      * Error processing.
882      */
883   error:
884     if (fp)
885         fclose(fp);
886     if (public_blob)
887         sfree(public_blob);
888     return NULL;
889 }
890
891 int ssh2_userkey_encrypted(const Filename *filename, char **commentptr)
892 {
893     FILE *fp;
894     char header[40], *b, *comment;
895     int ret;
896
897     if (commentptr)
898         *commentptr = NULL;
899
900     fp = f_open(*filename, "rb");
901     if (!fp)
902         return 0;
903     if (!read_header(fp, header)
904         || (0 != strcmp(header, "PuTTY-User-Key-File-2") &&
905             0 != strcmp(header, "PuTTY-User-Key-File-1"))) {
906         fclose(fp);
907         return 0;
908     }
909     if ((b = read_body(fp)) == NULL) {
910         fclose(fp);
911         return 0;
912     }
913     sfree(b);                          /* we don't care about key type here */
914     /* Read the Encryption header line. */
915     if (!read_header(fp, header) || 0 != strcmp(header, "Encryption")) {
916         fclose(fp);
917         return 0;
918     }
919     if ((b = read_body(fp)) == NULL) {
920         fclose(fp);
921         return 0;
922     }
923
924     /* Read the Comment header line. */
925     if (!read_header(fp, header) || 0 != strcmp(header, "Comment")) {
926         fclose(fp);
927         sfree(b);
928         return 1;
929     }
930     if ((comment = read_body(fp)) == NULL) {
931         fclose(fp);
932         sfree(b);
933         return 1;
934     }
935
936     if (commentptr)
937         *commentptr = comment;
938
939     fclose(fp);
940     if (!strcmp(b, "aes256-cbc"))
941         ret = 1;
942     else
943         ret = 0;
944     sfree(b);
945     return ret;
946 }
947
948 int base64_lines(int datalen)
949 {
950     /* When encoding, we use 64 chars/line, which equals 48 real chars. */
951     return (datalen + 47) / 48;
952 }
953
954 void base64_encode(FILE * fp, unsigned char *data, int datalen, int cpl)
955 {
956     int linelen = 0;
957     char out[4];
958     int n, i;
959
960     while (datalen > 0) {
961         n = (datalen < 3 ? datalen : 3);
962         base64_encode_atom(data, n, out);
963         data += n;
964         datalen -= n;
965         for (i = 0; i < 4; i++) {
966             if (linelen >= cpl) {
967                 linelen = 0;
968                 fputc('\n', fp);
969             }
970             fputc(out[i], fp);
971             linelen++;
972         }
973     }
974     fputc('\n', fp);
975 }
976
977 int ssh2_save_userkey(const Filename *filename, struct ssh2_userkey *key,
978                       char *passphrase)
979 {
980     FILE *fp;
981     unsigned char *pub_blob, *priv_blob, *priv_blob_encrypted;
982     int pub_blob_len, priv_blob_len, priv_encrypted_len;
983     int passlen;
984     int cipherblk;
985     int i;
986     char *cipherstr;
987     unsigned char priv_mac[20];
988
989     /*
990      * Fetch the key component blobs.
991      */
992     pub_blob = key->alg->public_blob(key->data, &pub_blob_len);
993     priv_blob = key->alg->private_blob(key->data, &priv_blob_len);
994     if (!pub_blob || !priv_blob) {
995         sfree(pub_blob);
996         sfree(priv_blob);
997         return 0;
998     }
999
1000     /*
1001      * Determine encryption details, and encrypt the private blob.
1002      */
1003     if (passphrase) {
1004         cipherstr = "aes256-cbc";
1005         cipherblk = 16;
1006     } else {
1007         cipherstr = "none";
1008         cipherblk = 1;
1009     }
1010     priv_encrypted_len = priv_blob_len + cipherblk - 1;
1011     priv_encrypted_len -= priv_encrypted_len % cipherblk;
1012     priv_blob_encrypted = snewn(priv_encrypted_len, unsigned char);
1013     memset(priv_blob_encrypted, 0, priv_encrypted_len);
1014     memcpy(priv_blob_encrypted, priv_blob, priv_blob_len);
1015     /* Create padding based on the SHA hash of the unpadded blob. This prevents
1016      * too easy a known-plaintext attack on the last block. */
1017     SHA_Simple(priv_blob, priv_blob_len, priv_mac);
1018     assert(priv_encrypted_len - priv_blob_len < 20);
1019     memcpy(priv_blob_encrypted + priv_blob_len, priv_mac,
1020            priv_encrypted_len - priv_blob_len);
1021
1022     /* Now create the MAC. */
1023     {
1024         unsigned char *macdata;
1025         int maclen;
1026         unsigned char *p;
1027         int namelen = strlen(key->alg->name);
1028         int enclen = strlen(cipherstr);
1029         int commlen = strlen(key->comment);
1030         SHA_State s;
1031         unsigned char mackey[20];
1032         char header[] = "putty-private-key-file-mac-key";
1033
1034         maclen = (4 + namelen +
1035                   4 + enclen +
1036                   4 + commlen +
1037                   4 + pub_blob_len +
1038                   4 + priv_encrypted_len);
1039         macdata = snewn(maclen, unsigned char);
1040         p = macdata;
1041 #define DO_STR(s,len) PUT_32BIT(p,(len));memcpy(p+4,(s),(len));p+=4+(len)
1042         DO_STR(key->alg->name, namelen);
1043         DO_STR(cipherstr, enclen);
1044         DO_STR(key->comment, commlen);
1045         DO_STR(pub_blob, pub_blob_len);
1046         DO_STR(priv_blob_encrypted, priv_encrypted_len);
1047
1048         SHA_Init(&s);
1049         SHA_Bytes(&s, header, sizeof(header)-1);
1050         if (passphrase)
1051             SHA_Bytes(&s, passphrase, strlen(passphrase));
1052         SHA_Final(&s, mackey);
1053         hmac_sha1_simple(mackey, 20, macdata, maclen, priv_mac);
1054         memset(macdata, 0, maclen);
1055         sfree(macdata);
1056         memset(mackey, 0, sizeof(mackey));
1057         memset(&s, 0, sizeof(s));
1058     }
1059
1060     if (passphrase) {
1061         unsigned char key[40];
1062         SHA_State s;
1063
1064         passlen = strlen(passphrase);
1065
1066         SHA_Init(&s);
1067         SHA_Bytes(&s, "\0\0\0\0", 4);
1068         SHA_Bytes(&s, passphrase, passlen);
1069         SHA_Final(&s, key + 0);
1070         SHA_Init(&s);
1071         SHA_Bytes(&s, "\0\0\0\1", 4);
1072         SHA_Bytes(&s, passphrase, passlen);
1073         SHA_Final(&s, key + 20);
1074         aes256_encrypt_pubkey(key, priv_blob_encrypted,
1075                               priv_encrypted_len);
1076
1077         memset(key, 0, sizeof(key));
1078         memset(&s, 0, sizeof(s));
1079     }
1080
1081     fp = f_open(*filename, "w");
1082     if (!fp)
1083         return 0;
1084     fprintf(fp, "PuTTY-User-Key-File-2: %s\n", key->alg->name);
1085     fprintf(fp, "Encryption: %s\n", cipherstr);
1086     fprintf(fp, "Comment: %s\n", key->comment);
1087     fprintf(fp, "Public-Lines: %d\n", base64_lines(pub_blob_len));
1088     base64_encode(fp, pub_blob, pub_blob_len, 64);
1089     fprintf(fp, "Private-Lines: %d\n", base64_lines(priv_encrypted_len));
1090     base64_encode(fp, priv_blob_encrypted, priv_encrypted_len, 64);
1091     fprintf(fp, "Private-MAC: ");
1092     for (i = 0; i < 20; i++)
1093         fprintf(fp, "%02x", priv_mac[i]);
1094     fprintf(fp, "\n");
1095     fclose(fp);
1096
1097     sfree(pub_blob);
1098     memset(priv_blob, 0, priv_blob_len);
1099     sfree(priv_blob);
1100     sfree(priv_blob_encrypted);
1101     return 1;
1102 }
1103
1104 /* ----------------------------------------------------------------------
1105  * A function to determine the type of a private key file. Returns
1106  * 0 on failure, 1 or 2 on success.
1107  */
1108 int key_type(const Filename *filename)
1109 {
1110     FILE *fp;
1111     char buf[32];
1112     const char putty2_sig[] = "PuTTY-User-Key-File-";
1113     const char sshcom_sig[] = "---- BEGIN SSH2 ENCRYPTED PRIVAT";
1114     const char openssh_sig[] = "-----BEGIN ";
1115     int i;
1116
1117     fp = f_open(*filename, "r");
1118     if (!fp)
1119         return SSH_KEYTYPE_UNOPENABLE;
1120     i = fread(buf, 1, sizeof(buf), fp);
1121     fclose(fp);
1122     if (i < 0)
1123         return SSH_KEYTYPE_UNOPENABLE;
1124     if (i < 32)
1125         return SSH_KEYTYPE_UNKNOWN;
1126     if (!memcmp(buf, rsa_signature, sizeof(rsa_signature)-1))
1127         return SSH_KEYTYPE_SSH1;
1128     if (!memcmp(buf, putty2_sig, sizeof(putty2_sig)-1))
1129         return SSH_KEYTYPE_SSH2;
1130     if (!memcmp(buf, openssh_sig, sizeof(openssh_sig)-1))
1131         return SSH_KEYTYPE_OPENSSH;
1132     if (!memcmp(buf, sshcom_sig, sizeof(sshcom_sig)-1))
1133         return SSH_KEYTYPE_SSHCOM;
1134     return SSH_KEYTYPE_UNKNOWN;        /* unrecognised or EOF */
1135 }
1136
1137 /*
1138  * Convert the type word to a string, for `wrong type' error
1139  * messages.
1140  */
1141 char *key_type_to_str(int type)
1142 {
1143     switch (type) {
1144       case SSH_KEYTYPE_UNOPENABLE: return "unable to open file"; break;
1145       case SSH_KEYTYPE_UNKNOWN: return "not a private key"; break;
1146       case SSH_KEYTYPE_SSH1: return "SSH1 private key"; break;
1147       case SSH_KEYTYPE_SSH2: return "PuTTY SSH2 private key"; break;
1148       case SSH_KEYTYPE_OPENSSH: return "OpenSSH SSH2 private key"; break;
1149       case SSH_KEYTYPE_SSHCOM: return "ssh.com SSH2 private key"; break;
1150       default: return "INTERNAL ERROR"; break;
1151     }
1152 }