]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - sshpubk.c
Const-correctness in the base64 functions.
[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 SSH-2 (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 rsa_signature "SSH PRIVATE KEY FILE FORMAT 1.1\n"
17
18 #define BASE64_TOINT(x) ( (x)-'A'<26 ? (x)-'A'+0 :\
19                           (x)-'a'<26 ? (x)-'a'+26 :\
20                           (x)-'0'<10 ? (x)-'0'+52 :\
21                           (x)=='+' ? 62 : \
22                           (x)=='/' ? 63 : 0 )
23
24 static int key_type_fp(FILE *fp);
25
26 static int loadrsakey_main(FILE * fp, struct RSAKey *key, int pub_only,
27                            char **commentptr, const char *passphrase,
28                            const char **error)
29 {
30     unsigned char buf[16384];
31     unsigned char keybuf[16];
32     int len;
33     int i, j, ciphertype;
34     int ret = 0;
35     struct MD5Context md5c;
36     char *comment;
37
38     *error = NULL;
39
40     /* Slurp the whole file (minus the header) into a buffer. */
41     len = fread(buf, 1, sizeof(buf), fp);
42     fclose(fp);
43     if (len < 0 || len == sizeof(buf)) {
44         *error = "error reading file";
45         goto end;                      /* file too big or not read */
46     }
47
48     i = 0;
49     *error = "file format error";
50
51     /*
52      * A zero byte. (The signature includes a terminating NUL.)
53      */
54     if (len - i < 1 || buf[i] != 0)
55         goto end;
56     i++;
57
58     /* One byte giving encryption type, and one reserved uint32. */
59     if (len - i < 1)
60         goto end;
61     ciphertype = buf[i];
62     if (ciphertype != 0 && ciphertype != SSH_CIPHER_3DES)
63         goto end;
64     i++;
65     if (len - i < 4)
66         goto end;                      /* reserved field not present */
67     if (buf[i] != 0 || buf[i + 1] != 0 || buf[i + 2] != 0
68         || buf[i + 3] != 0) goto end;  /* reserved field nonzero, panic! */
69     i += 4;
70
71     /* Now the serious stuff. An ordinary SSH-1 public key. */
72     j = makekey(buf + i, len - i, key, NULL, 1);
73     if (j < 0)
74         goto end;                      /* overran */
75     i += j;
76
77     /* Next, the comment field. */
78     j = toint(GET_32BIT(buf + i));
79     i += 4;
80     if (j < 0 || len - i < j)
81         goto end;
82     comment = snewn(j + 1, char);
83     if (comment) {
84         memcpy(comment, buf + i, j);
85         comment[j] = '\0';
86     }
87     i += j;
88     if (commentptr)
89         *commentptr = dupstr(comment);
90     if (key)
91         key->comment = comment;
92     else
93         sfree(comment);
94
95     if (pub_only) {
96         ret = 1;
97         goto end;
98     }
99
100     if (!key) {
101         ret = ciphertype != 0;
102         *error = NULL;
103         goto end;
104     }
105
106     /*
107      * Decrypt remainder of buffer.
108      */
109     if (ciphertype) {
110         MD5Init(&md5c);
111         MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase));
112         MD5Final(keybuf, &md5c);
113         des3_decrypt_pubkey(keybuf, buf + i, (len - i + 7) & ~7);
114         smemclr(keybuf, sizeof(keybuf));        /* burn the evidence */
115     }
116
117     /*
118      * We are now in the secret part of the key. The first four
119      * bytes should be of the form a, b, a, b.
120      */
121     if (len - i < 4)
122         goto end;
123     if (buf[i] != buf[i + 2] || buf[i + 1] != buf[i + 3]) {
124         *error = "wrong passphrase";
125         ret = -1;
126         goto end;
127     }
128     i += 4;
129
130     /*
131      * After that, we have one further bignum which is our
132      * decryption exponent, and then the three auxiliary values
133      * (iqmp, q, p).
134      */
135     j = makeprivate(buf + i, len - i, key);
136     if (j < 0) goto end;
137     i += j;
138     j = ssh1_read_bignum(buf + i, len - i, &key->iqmp);
139     if (j < 0) goto end;
140     i += j;
141     j = ssh1_read_bignum(buf + i, len - i, &key->q);
142     if (j < 0) goto end;
143     i += j;
144     j = ssh1_read_bignum(buf + i, len - i, &key->p);
145     if (j < 0) goto end;
146     i += j;
147
148     if (!rsa_verify(key)) {
149         *error = "rsa_verify failed";
150         freersakey(key);
151         ret = 0;
152     } else
153         ret = 1;
154
155   end:
156     smemclr(buf, sizeof(buf));       /* burn the evidence */
157     return ret;
158 }
159
160 int loadrsakey(const Filename *filename, struct RSAKey *key,
161                const char *passphrase, const char **errorstr)
162 {
163     FILE *fp;
164     char buf[64];
165     int ret = 0;
166     const char *error = NULL;
167
168     fp = f_open(filename, "rb", FALSE);
169     if (!fp) {
170         error = "can't open file";
171         goto end;
172     }
173
174     /*
175      * Read the first line of the file and see if it's a v1 private
176      * key file.
177      */
178     if (fgets(buf, sizeof(buf), fp) && !strcmp(buf, rsa_signature)) {
179         /*
180          * This routine will take care of calling fclose() for us.
181          */
182         ret = loadrsakey_main(fp, key, FALSE, NULL, passphrase, &error);
183         fp = NULL;
184         goto end;
185     }
186
187     /*
188      * Otherwise, we have nothing. Return empty-handed.
189      */
190     error = "not an SSH-1 RSA file";
191
192   end:
193     if (fp)
194         fclose(fp);
195     if ((ret != 1) && errorstr)
196         *errorstr = error;
197     return ret;
198 }
199
200 /*
201  * See whether an RSA key is encrypted. Return its comment field as
202  * well.
203  */
204 int rsakey_encrypted(const Filename *filename, char **comment)
205 {
206     FILE *fp;
207     char buf[64];
208
209     fp = f_open(filename, "rb", FALSE);
210     if (!fp)
211         return 0;                      /* doesn't even exist */
212
213     /*
214      * Read the first line of the file and see if it's a v1 private
215      * key file.
216      */
217     if (fgets(buf, sizeof(buf), fp) && !strcmp(buf, rsa_signature)) {
218         const char *dummy;
219         /*
220          * This routine will take care of calling fclose() for us.
221          */
222         return loadrsakey_main(fp, NULL, FALSE, comment, NULL, &dummy);
223     }
224     fclose(fp);
225     return 0;                          /* wasn't the right kind of file */
226 }
227
228 /*
229  * Return a malloc'ed chunk of memory containing the public blob of
230  * an RSA key, as given in the agent protocol (modulus bits,
231  * exponent, modulus).
232  */
233 int rsakey_pubblob(const Filename *filename, void **blob, int *bloblen,
234                    char **commentptr, const char **errorstr)
235 {
236     FILE *fp;
237     char buf[64];
238     struct RSAKey key;
239     int ret;
240     const char *error = NULL;
241
242     /* Default return if we fail. */
243     *blob = NULL;
244     *bloblen = 0;
245     ret = 0;
246
247     fp = f_open(filename, "rb", FALSE);
248     if (!fp) {
249         error = "can't open file";
250         goto end;
251     }
252
253     /*
254      * Read the first line of the file and see if it's a v1 private
255      * key file.
256      */
257     if (fgets(buf, sizeof(buf), fp) && !strcmp(buf, rsa_signature)) {
258         memset(&key, 0, sizeof(key));
259         if (loadrsakey_main(fp, &key, TRUE, commentptr, NULL, &error)) {
260             *blob = rsa_public_blob(&key, bloblen);
261             freersakey(&key);
262             ret = 1;
263         }
264         fp = NULL; /* loadrsakey_main unconditionally closes fp */
265     } else {
266         /*
267          * Try interpreting the file as an SSH-1 public key.
268          */
269         char *line, *p, *bitsp, *expp, *modp, *commentp;
270
271         rewind(fp);
272         line = chomp(fgetline(fp));
273         p = line;
274
275         bitsp = p;
276         p += strspn(p, "0123456789");
277         if (*p != ' ')
278             goto not_public_either;
279         *p++ = '\0';
280
281         expp = p;
282         p += strspn(p, "0123456789");
283         if (*p != ' ')
284             goto not_public_either;
285         *p++ = '\0';
286
287         modp = p;
288         p += strspn(p, "0123456789");
289         if (*p) {
290             if (*p != ' ')
291                 goto not_public_either;
292             *p++ = '\0';
293             commentp = p;
294         } else {
295             commentp = NULL;
296         }
297
298         memset(&key, 0, sizeof(key));
299         key.exponent = bignum_from_decimal(expp);
300         key.modulus = bignum_from_decimal(modp);
301         if (atoi(bitsp) != bignum_bitcount(key.modulus)) {
302             freebn(key.exponent);
303             freebn(key.modulus);
304             sfree(line);
305             error = "key bit count does not match in SSH-1 public key file";
306             goto end;
307         }
308         if (commentptr)
309             *commentptr = commentp ? dupstr(commentp) : NULL;
310         *blob = rsa_public_blob(&key, bloblen);
311         freersakey(&key);
312         return 1;
313
314       not_public_either:
315         sfree(line);
316         error = "not an SSH-1 RSA file";
317     }
318
319   end:
320     if (fp)
321         fclose(fp);
322     if ((ret != 1) && errorstr)
323         *errorstr = error;
324     return ret;
325 }
326
327 /*
328  * Save an RSA key file. Return nonzero on success.
329  */
330 int saversakey(const Filename *filename, struct RSAKey *key, char *passphrase)
331 {
332     unsigned char buf[16384];
333     unsigned char keybuf[16];
334     struct MD5Context md5c;
335     unsigned char *p, *estart;
336     FILE *fp;
337
338     /*
339      * Write the initial signature.
340      */
341     p = buf;
342     memcpy(p, rsa_signature, sizeof(rsa_signature));
343     p += sizeof(rsa_signature);
344
345     /*
346      * One byte giving encryption type, and one reserved (zero)
347      * uint32.
348      */
349     *p++ = (passphrase ? SSH_CIPHER_3DES : 0);
350     PUT_32BIT(p, 0);
351     p += 4;
352
353     /*
354      * An ordinary SSH-1 public key consists of: a uint32
355      * containing the bit count, then two bignums containing the
356      * modulus and exponent respectively.
357      */
358     PUT_32BIT(p, bignum_bitcount(key->modulus));
359     p += 4;
360     p += ssh1_write_bignum(p, key->modulus);
361     p += ssh1_write_bignum(p, key->exponent);
362
363     /*
364      * A string containing the comment field.
365      */
366     if (key->comment) {
367         PUT_32BIT(p, strlen(key->comment));
368         p += 4;
369         memcpy(p, key->comment, strlen(key->comment));
370         p += strlen(key->comment);
371     } else {
372         PUT_32BIT(p, 0);
373         p += 4;
374     }
375
376     /*
377      * The encrypted portion starts here.
378      */
379     estart = p;
380
381     /*
382      * Two bytes, then the same two bytes repeated.
383      */
384     *p++ = random_byte();
385     *p++ = random_byte();
386     p[0] = p[-2];
387     p[1] = p[-1];
388     p += 2;
389
390     /*
391      * Four more bignums: the decryption exponent, then iqmp, then
392      * q, then p.
393      */
394     p += ssh1_write_bignum(p, key->private_exponent);
395     p += ssh1_write_bignum(p, key->iqmp);
396     p += ssh1_write_bignum(p, key->q);
397     p += ssh1_write_bignum(p, key->p);
398
399     /*
400      * Now write zeros until the encrypted portion is a multiple of
401      * 8 bytes.
402      */
403     while ((p - estart) % 8)
404         *p++ = '\0';
405
406     /*
407      * Now encrypt the encrypted portion.
408      */
409     if (passphrase) {
410         MD5Init(&md5c);
411         MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase));
412         MD5Final(keybuf, &md5c);
413         des3_encrypt_pubkey(keybuf, estart, p - estart);
414         smemclr(keybuf, sizeof(keybuf));        /* burn the evidence */
415     }
416
417     /*
418      * Done. Write the result to the file.
419      */
420     fp = f_open(filename, "wb", TRUE);
421     if (fp) {
422         int ret = (fwrite(buf, 1, p - buf, fp) == (size_t) (p - buf));
423         if (fclose(fp))
424             ret = 0;
425         return ret;
426     } else
427         return 0;
428 }
429
430 /* ----------------------------------------------------------------------
431  * SSH-2 private key load/store functions.
432  */
433
434 /*
435  * PuTTY's own format for SSH-2 keys is as follows:
436  *
437  * The file is text. Lines are terminated by CRLF, although CR-only
438  * and LF-only are tolerated on input.
439  *
440  * The first line says "PuTTY-User-Key-File-2: " plus the name of the
441  * algorithm ("ssh-dss", "ssh-rsa" etc).
442  *
443  * The next line says "Encryption: " plus an encryption type.
444  * Currently the only supported encryption types are "aes256-cbc"
445  * and "none".
446  *
447  * The next line says "Comment: " plus the comment string.
448  *
449  * Next there is a line saying "Public-Lines: " plus a number N.
450  * The following N lines contain a base64 encoding of the public
451  * part of the key. This is encoded as the standard SSH-2 public key
452  * blob (with no initial length): so for RSA, for example, it will
453  * read
454  *
455  *    string "ssh-rsa"
456  *    mpint  exponent
457  *    mpint  modulus
458  *
459  * Next, there is a line saying "Private-Lines: " plus a number N,
460  * and then N lines containing the (potentially encrypted) private
461  * part of the key. For the key type "ssh-rsa", this will be
462  * composed of
463  *
464  *    mpint  private_exponent
465  *    mpint  p                  (the larger of the two primes)
466  *    mpint  q                  (the smaller prime)
467  *    mpint  iqmp               (the inverse of q modulo p)
468  *    data   padding            (to reach a multiple of the cipher block size)
469  *
470  * And for "ssh-dss", it will be composed of
471  *
472  *    mpint  x                  (the private key parameter)
473  *  [ string hash   20-byte hash of mpints p || q || g   only in old format ]
474  * 
475  * Finally, there is a line saying "Private-MAC: " plus a hex
476  * representation of a HMAC-SHA-1 of:
477  *
478  *    string  name of algorithm ("ssh-dss", "ssh-rsa")
479  *    string  encryption type
480  *    string  comment
481  *    string  public-blob
482  *    string  private-plaintext (the plaintext version of the
483  *                               private part, including the final
484  *                               padding)
485  * 
486  * The key to the MAC is itself a SHA-1 hash of:
487  * 
488  *    data    "putty-private-key-file-mac-key"
489  *    data    passphrase
490  *
491  * (An empty passphrase is used for unencrypted keys.)
492  *
493  * If the key is encrypted, the encryption key is derived from the
494  * passphrase by means of a succession of SHA-1 hashes. Each hash
495  * is the hash of:
496  *
497  *    uint32  sequence-number
498  *    data    passphrase
499  *
500  * where the sequence-number increases from zero. As many of these
501  * hashes are used as necessary.
502  *
503  * For backwards compatibility with snapshots between 0.51 and
504  * 0.52, we also support the older key file format, which begins
505  * with "PuTTY-User-Key-File-1" (version number differs). In this
506  * format the Private-MAC: field only covers the private-plaintext
507  * field and nothing else (and without the 4-byte string length on
508  * the front too). Moreover, the Private-MAC: field can be replaced
509  * with a Private-Hash: field which is a plain SHA-1 hash instead of
510  * an HMAC (this was generated for unencrypted keys).
511  */
512
513 static int read_header(FILE * fp, char *header)
514 {
515     int len = 39;
516     int c;
517
518     while (1) {
519         c = fgetc(fp);
520         if (c == '\n' || c == '\r' || c == EOF)
521             return 0;                  /* failure */
522         if (c == ':') {
523             c = fgetc(fp);
524             if (c != ' ')
525                 return 0;
526             *header = '\0';
527             return 1;                  /* success! */
528         }
529         if (len == 0)
530             return 0;                  /* failure */
531         *header++ = c;
532         len--;
533     }
534     return 0;                          /* failure */
535 }
536
537 static char *read_body(FILE * fp)
538 {
539     char *text;
540     int len;
541     int size;
542     int c;
543
544     size = 128;
545     text = snewn(size, char);
546     len = 0;
547     text[len] = '\0';
548
549     while (1) {
550         c = fgetc(fp);
551         if (c == '\r' || c == '\n' || c == EOF) {
552             if (c != EOF) {
553                 c = fgetc(fp);
554                 if (c != '\r' && c != '\n')
555                     ungetc(c, fp);
556             }
557             return text;
558         }
559         if (len + 1 >= size) {
560             size += 128;
561             text = sresize(text, size, char);
562         }
563         text[len++] = c;
564         text[len] = '\0';
565     }
566 }
567
568 static unsigned char *read_blob(FILE * fp, int nlines, int *bloblen)
569 {
570     unsigned char *blob;
571     char *line;
572     int linelen, len;
573     int i, j, k;
574
575     /* We expect at most 64 base64 characters, ie 48 real bytes, per line. */
576     blob = snewn(48 * nlines, unsigned char);
577     len = 0;
578     for (i = 0; i < nlines; i++) {
579         line = read_body(fp);
580         if (!line) {
581             sfree(blob);
582             return NULL;
583         }
584         linelen = strlen(line);
585         if (linelen % 4 != 0 || linelen > 64) {
586             sfree(blob);
587             sfree(line);
588             return NULL;
589         }
590         for (j = 0; j < linelen; j += 4) {
591             k = base64_decode_atom(line + j, blob + len);
592             if (!k) {
593                 sfree(line);
594                 sfree(blob);
595                 return NULL;
596             }
597             len += k;
598         }
599         sfree(line);
600     }
601     *bloblen = len;
602     return blob;
603 }
604
605 /*
606  * Magic error return value for when the passphrase is wrong.
607  */
608 struct ssh2_userkey ssh2_wrong_passphrase = {
609     NULL, NULL, NULL
610 };
611
612 const struct ssh_signkey *find_pubkey_alg_len(int namelen, const char *name)
613 {
614     if (match_ssh_id(namelen, name, "ssh-rsa"))
615         return &ssh_rsa;
616     else if (match_ssh_id(namelen, name, "ssh-dss"))
617         return &ssh_dss;
618     else if (match_ssh_id(namelen, name, "ecdsa-sha2-nistp256"))
619         return &ssh_ecdsa_nistp256;
620     else if (match_ssh_id(namelen, name, "ecdsa-sha2-nistp384"))
621         return &ssh_ecdsa_nistp384;
622     else if (match_ssh_id(namelen, name, "ecdsa-sha2-nistp521"))
623         return &ssh_ecdsa_nistp521;
624     else if (match_ssh_id(namelen, name, "ssh-ed25519"))
625         return &ssh_ecdsa_ed25519;
626     else
627         return NULL;
628 }
629
630 const struct ssh_signkey *find_pubkey_alg(const char *name)
631 {
632     return find_pubkey_alg_len(strlen(name), name);
633 }
634
635 struct ssh2_userkey *ssh2_load_userkey(const Filename *filename,
636                                        const char *passphrase,
637                                        const char **errorstr)
638 {
639     FILE *fp;
640     char header[40], *b, *encryption, *comment, *mac;
641     const struct ssh_signkey *alg;
642     struct ssh2_userkey *ret;
643     int cipher, cipherblk;
644     unsigned char *public_blob, *private_blob;
645     int public_blob_len, private_blob_len;
646     int i, is_mac, old_fmt;
647     int passlen = passphrase ? strlen(passphrase) : 0;
648     const char *error = NULL;
649
650     ret = NULL;                        /* return NULL for most errors */
651     encryption = comment = mac = NULL;
652     public_blob = private_blob = NULL;
653
654     fp = f_open(filename, "rb", FALSE);
655     if (!fp) {
656         error = "can't open file";
657         goto error;
658     }
659
660     /* Read the first header line which contains the key type. */
661     if (!read_header(fp, header))
662         goto error;
663     if (0 == strcmp(header, "PuTTY-User-Key-File-2")) {
664         old_fmt = 0;
665     } else if (0 == strcmp(header, "PuTTY-User-Key-File-1")) {
666         /* this is an old key file; warn and then continue */
667         old_keyfile_warning();
668         old_fmt = 1;
669     } else if (0 == strncmp(header, "PuTTY-User-Key-File-", 20)) {
670         /* this is a key file FROM THE FUTURE; refuse it, but with a
671          * more specific error message than the generic one below */
672         error = "PuTTY key format too new";
673         goto error;
674     } else {
675         error = "not a PuTTY SSH-2 private key";
676         goto error;
677     }
678     error = "file format error";
679     if ((b = read_body(fp)) == NULL)
680         goto error;
681     /* Select key algorithm structure. */
682     alg = find_pubkey_alg(b);
683     if (!alg) {
684         sfree(b);
685         goto error;
686     }
687     sfree(b);
688
689     /* Read the Encryption header line. */
690     if (!read_header(fp, header) || 0 != strcmp(header, "Encryption"))
691         goto error;
692     if ((encryption = read_body(fp)) == NULL)
693         goto error;
694     if (!strcmp(encryption, "aes256-cbc")) {
695         cipher = 1;
696         cipherblk = 16;
697     } else if (!strcmp(encryption, "none")) {
698         cipher = 0;
699         cipherblk = 1;
700     } else {
701         goto error;
702     }
703
704     /* Read the Comment header line. */
705     if (!read_header(fp, header) || 0 != strcmp(header, "Comment"))
706         goto error;
707     if ((comment = read_body(fp)) == NULL)
708         goto error;
709
710     /* Read the Public-Lines header line and the public blob. */
711     if (!read_header(fp, header) || 0 != strcmp(header, "Public-Lines"))
712         goto error;
713     if ((b = read_body(fp)) == NULL)
714         goto error;
715     i = atoi(b);
716     sfree(b);
717     if ((public_blob = read_blob(fp, i, &public_blob_len)) == NULL)
718         goto error;
719
720     /* Read the Private-Lines header line and the Private blob. */
721     if (!read_header(fp, header) || 0 != strcmp(header, "Private-Lines"))
722         goto error;
723     if ((b = read_body(fp)) == NULL)
724         goto error;
725     i = atoi(b);
726     sfree(b);
727     if ((private_blob = read_blob(fp, i, &private_blob_len)) == NULL)
728         goto error;
729
730     /* Read the Private-MAC or Private-Hash header line. */
731     if (!read_header(fp, header))
732         goto error;
733     if (0 == strcmp(header, "Private-MAC")) {
734         if ((mac = read_body(fp)) == NULL)
735             goto error;
736         is_mac = 1;
737     } else if (0 == strcmp(header, "Private-Hash") && old_fmt) {
738         if ((mac = read_body(fp)) == NULL)
739             goto error;
740         is_mac = 0;
741     } else
742         goto error;
743
744     fclose(fp);
745     fp = NULL;
746
747     /*
748      * Decrypt the private blob.
749      */
750     if (cipher) {
751         unsigned char key[40];
752         SHA_State s;
753
754         if (!passphrase)
755             goto error;
756         if (private_blob_len % cipherblk)
757             goto error;
758
759         SHA_Init(&s);
760         SHA_Bytes(&s, "\0\0\0\0", 4);
761         SHA_Bytes(&s, passphrase, passlen);
762         SHA_Final(&s, key + 0);
763         SHA_Init(&s);
764         SHA_Bytes(&s, "\0\0\0\1", 4);
765         SHA_Bytes(&s, passphrase, passlen);
766         SHA_Final(&s, key + 20);
767         aes256_decrypt_pubkey(key, private_blob, private_blob_len);
768     }
769
770     /*
771      * Verify the MAC.
772      */
773     {
774         char realmac[41];
775         unsigned char binary[20];
776         unsigned char *macdata;
777         int maclen;
778         int free_macdata;
779
780         if (old_fmt) {
781             /* MAC (or hash) only covers the private blob. */
782             macdata = private_blob;
783             maclen = private_blob_len;
784             free_macdata = 0;
785         } else {
786             unsigned char *p;
787             int namelen = strlen(alg->name);
788             int enclen = strlen(encryption);
789             int commlen = strlen(comment);
790             maclen = (4 + namelen +
791                       4 + enclen +
792                       4 + commlen +
793                       4 + public_blob_len +
794                       4 + private_blob_len);
795             macdata = snewn(maclen, unsigned char);
796             p = macdata;
797 #define DO_STR(s,len) PUT_32BIT(p,(len));memcpy(p+4,(s),(len));p+=4+(len)
798             DO_STR(alg->name, namelen);
799             DO_STR(encryption, enclen);
800             DO_STR(comment, commlen);
801             DO_STR(public_blob, public_blob_len);
802             DO_STR(private_blob, private_blob_len);
803
804             free_macdata = 1;
805         }
806
807         if (is_mac) {
808             SHA_State s;
809             unsigned char mackey[20];
810             char header[] = "putty-private-key-file-mac-key";
811
812             SHA_Init(&s);
813             SHA_Bytes(&s, header, sizeof(header)-1);
814             if (cipher && passphrase)
815                 SHA_Bytes(&s, passphrase, passlen);
816             SHA_Final(&s, mackey);
817
818             hmac_sha1_simple(mackey, 20, macdata, maclen, binary);
819
820             smemclr(mackey, sizeof(mackey));
821             smemclr(&s, sizeof(s));
822         } else {
823             SHA_Simple(macdata, maclen, binary);
824         }
825
826         if (free_macdata) {
827             smemclr(macdata, maclen);
828             sfree(macdata);
829         }
830
831         for (i = 0; i < 20; i++)
832             sprintf(realmac + 2 * i, "%02x", binary[i]);
833
834         if (strcmp(mac, realmac)) {
835             /* An incorrect MAC is an unconditional Error if the key is
836              * unencrypted. Otherwise, it means Wrong Passphrase. */
837             if (cipher) {
838                 error = "wrong passphrase";
839                 ret = SSH2_WRONG_PASSPHRASE;
840             } else {
841                 error = "MAC failed";
842                 ret = NULL;
843             }
844             goto error;
845         }
846     }
847     sfree(mac);
848     mac = NULL;
849
850     /*
851      * Create and return the key.
852      */
853     ret = snew(struct ssh2_userkey);
854     ret->alg = alg;
855     ret->comment = comment;
856     ret->data = alg->createkey(public_blob, public_blob_len,
857                                private_blob, private_blob_len);
858     if (!ret->data) {
859         sfree(ret);
860         ret = NULL;
861         error = "createkey failed";
862         goto error;
863     }
864     sfree(public_blob);
865     smemclr(private_blob, private_blob_len);
866     sfree(private_blob);
867     sfree(encryption);
868     if (errorstr)
869         *errorstr = NULL;
870     return ret;
871
872     /*
873      * Error processing.
874      */
875   error:
876     if (fp)
877         fclose(fp);
878     if (comment)
879         sfree(comment);
880     if (encryption)
881         sfree(encryption);
882     if (mac)
883         sfree(mac);
884     if (public_blob)
885         sfree(public_blob);
886     if (private_blob) {
887         smemclr(private_blob, private_blob_len);
888         sfree(private_blob);
889     }
890     if (errorstr)
891         *errorstr = error;
892     return ret;
893 }
894
895 unsigned char *rfc4716_loadpub(FILE *fp, char **algorithm,
896                                int *pub_blob_len, char **commentptr,
897                                const char **errorstr)
898 {
899     const char *error;
900     char *line, *colon, *value;
901     char *comment = NULL;
902     unsigned char *pubblob = NULL;
903     int pubbloblen, pubblobsize;
904     char base64in[4];
905     unsigned char base64out[3];
906     int base64bytes;
907     int alglen;
908
909     line = chomp(fgetline(fp));
910     if (!line || 0 != strcmp(line, "---- BEGIN SSH2 PUBLIC KEY ----")) {
911         error = "invalid begin line in SSH-2 public key file";
912         goto error;
913     }
914     sfree(line); line = NULL;
915
916     while (1) {
917         line = chomp(fgetline(fp));
918         if (!line) {
919             error = "truncated SSH-2 public key file";
920             goto error;
921         }
922         colon = strstr(line, ": ");
923         if (!colon)
924             break;
925         *colon = '\0';
926         value = colon + 2;
927
928         if (!strcmp(line, "Comment")) {
929             char *p, *q;
930
931             /* Remove containing double quotes, if present */
932             p = value;
933             if (*p == '"' && p[strlen(p)-1] == '"') {
934                 p[strlen(p)-1] = '\0';
935                 p++;
936             }
937
938             /* Remove \-escaping, not in RFC4716 but seen in the wild
939              * in practice. */
940             for (q = line; *p; p++) {
941                 if (*p == '\\' && p[1])
942                     p++;
943                 *q++ = *p;
944             }
945
946             *q = '\0';
947             comment = dupstr(line);
948         } else if (!strcmp(line, "Subject") ||
949                    !strncmp(line, "x-", 2)) {
950             /* Headers we recognise and ignore. Do nothing. */
951         } else {
952             error = "unrecognised header in SSH-2 public key file";
953             goto error;
954         }
955
956         sfree(line); line = NULL;
957     }
958
959     /*
960      * Now line contains the initial line of base64 data. Loop round
961      * while it still does contain base64.
962      */
963     pubblobsize = 4096;
964     pubblob = snewn(pubblobsize, unsigned char);
965     pubbloblen = 0;
966     base64bytes = 0;
967     while (line && line[0] != '-') {
968         char *p;
969         for (p = line; *p; p++) {
970             base64in[base64bytes++] = *p;
971             if (base64bytes == 4) {
972                 int n = base64_decode_atom(base64in, base64out);
973                 if (pubbloblen + n > pubblobsize) {
974                     pubblobsize = (pubbloblen + n) * 5 / 4 + 1024;
975                     pubblob = sresize(pubblob, pubblobsize, unsigned char);
976                 }
977                 memcpy(pubblob + pubbloblen, base64out, n);
978                 pubbloblen += n;
979                 base64bytes = 0;
980             }
981         }
982         sfree(line); line = NULL;
983         line = chomp(fgetline(fp));
984     }
985
986     /*
987      * Finally, check the END line makes sense.
988      */
989     if (!line || 0 != strcmp(line, "---- END SSH2 PUBLIC KEY ----")) {
990         error = "invalid end line in SSH-2 public key file";
991         goto error;
992     }
993     sfree(line); line = NULL;
994
995     /*
996      * OK, we now have a public blob and optionally a comment. We must
997      * return the key algorithm string too, so look for that at the
998      * start of the public blob.
999      */
1000     if (pubbloblen < 4) {
1001         error = "not enough data in SSH-2 public key file";
1002         goto error;
1003     }
1004     alglen = toint(GET_32BIT(pubblob));
1005     if (alglen < 0 || alglen > pubbloblen-4) {
1006         error = "invalid algorithm prefix in SSH-2 public key file";
1007         goto error;
1008     }
1009     if (algorithm)
1010         *algorithm = dupprintf("%.*s", alglen, pubblob+4);
1011     if (pub_blob_len)
1012         *pub_blob_len = pubbloblen;
1013     if (commentptr)
1014         *commentptr = comment;
1015     else
1016         sfree(comment);
1017     return pubblob;
1018
1019   error:
1020     sfree(line);
1021     sfree(comment);
1022     sfree(pubblob);
1023     if (errorstr)
1024         *errorstr = error;
1025     return NULL;
1026 }
1027
1028 unsigned char *openssh_loadpub(FILE *fp, char **algorithm,
1029                                int *pub_blob_len, char **commentptr,
1030                                const char **errorstr)
1031 {
1032     const char *error;
1033     char *line, *base64;
1034     char *comment = NULL;
1035     unsigned char *pubblob = NULL;
1036     int pubbloblen, pubblobsize;
1037     int alglen;
1038
1039     line = chomp(fgetline(fp));
1040
1041     base64 = strchr(line, ' ');
1042     if (!base64) {
1043         error = "no key blob in OpenSSH public key file";
1044         goto error;
1045     }
1046     *base64++ = '\0';
1047
1048     comment = strchr(base64, ' ');
1049     if (comment) {
1050         *comment++ = '\0';
1051         comment = dupstr(comment);
1052     }
1053
1054     pubblobsize = strlen(base64) / 4 * 3;
1055     pubblob = snewn(pubblobsize, unsigned char);
1056     pubbloblen = 0;
1057
1058     while (!memchr(base64, '\0', 4)) {
1059         assert(pubbloblen + 3 <= pubblobsize);
1060         pubbloblen += base64_decode_atom(base64, pubblob + pubbloblen);
1061         base64 += 4;
1062     }
1063     if (*base64) {
1064         error = "invalid length for base64 data in OpenSSH public key file";
1065         goto error;
1066     }
1067
1068     /*
1069      * Sanity check: the first word on the line should be the key
1070      * algorithm, and should match the encoded string at the start of
1071      * the public blob.
1072      */
1073     alglen = strlen(line);
1074     if (pubbloblen < alglen + 4 ||
1075         GET_32BIT(pubblob) != alglen ||
1076         0 != memcmp(pubblob + 4, line, alglen)) {
1077         error = "key algorithms do not match in OpenSSH public key file";
1078         goto error;
1079     }
1080
1081     /*
1082      * Done.
1083      */
1084     if (algorithm)
1085         *algorithm = dupstr(line);
1086     if (pub_blob_len)
1087         *pub_blob_len = pubbloblen;
1088     if (commentptr)
1089         *commentptr = comment;
1090     else
1091         sfree(comment);
1092     return pubblob;
1093
1094   error:
1095     sfree(line);
1096     sfree(comment);
1097     sfree(pubblob);
1098     if (errorstr)
1099         *errorstr = error;
1100     return NULL;
1101 }
1102
1103 unsigned char *ssh2_userkey_loadpub(const Filename *filename, char **algorithm,
1104                                     int *pub_blob_len, char **commentptr,
1105                                     const char **errorstr)
1106 {
1107     FILE *fp;
1108     char header[40], *b;
1109     const struct ssh_signkey *alg;
1110     unsigned char *public_blob;
1111     int public_blob_len;
1112     int type, i;
1113     const char *error = NULL;
1114     char *comment = NULL;
1115
1116     public_blob = NULL;
1117
1118     fp = f_open(filename, "rb", FALSE);
1119     if (!fp) {
1120         error = "can't open file";
1121         goto error;
1122     }
1123
1124     /* Initially, check if this is a public-only key file. Sometimes
1125      * we'll be asked to read a public blob from one of those. */
1126     type = key_type_fp(fp);
1127     if (type == SSH_KEYTYPE_SSH2_PUBLIC_RFC4716) {
1128         unsigned char *ret = rfc4716_loadpub(fp, algorithm, pub_blob_len,
1129                                              commentptr, errorstr);
1130         fclose(fp);
1131         return ret;
1132     } else if (type == SSH_KEYTYPE_SSH2_PUBLIC_OPENSSH) {
1133         unsigned char *ret = openssh_loadpub(fp, algorithm, pub_blob_len,
1134                                              commentptr, errorstr);
1135         fclose(fp);
1136         return ret;
1137     } else if (type != SSH_KEYTYPE_SSH2) {
1138         error = "not a PuTTY SSH-2 private key";
1139         goto error;
1140     }
1141
1142     /* Read the first header line which contains the key type. */
1143     if (!read_header(fp, header)
1144         || (0 != strcmp(header, "PuTTY-User-Key-File-2") &&
1145             0 != strcmp(header, "PuTTY-User-Key-File-1"))) {
1146         if (0 == strncmp(header, "PuTTY-User-Key-File-", 20))
1147             error = "PuTTY key format too new";
1148         else
1149             error = "not a PuTTY SSH-2 private key";
1150         goto error;
1151     }
1152     error = "file format error";
1153     if ((b = read_body(fp)) == NULL)
1154         goto error;
1155     /* Select key algorithm structure. */
1156     alg = find_pubkey_alg(b);
1157     sfree(b);
1158     if (!alg) {
1159         goto error;
1160     }
1161
1162     /* Read the Encryption header line. */
1163     if (!read_header(fp, header) || 0 != strcmp(header, "Encryption"))
1164         goto error;
1165     if ((b = read_body(fp)) == NULL)
1166         goto error;
1167     sfree(b);                          /* we don't care */
1168
1169     /* Read the Comment header line. */
1170     if (!read_header(fp, header) || 0 != strcmp(header, "Comment"))
1171         goto error;
1172     if ((comment = read_body(fp)) == NULL)
1173         goto error;
1174
1175     if (commentptr)
1176         *commentptr = comment;
1177     else
1178         sfree(comment);
1179
1180     /* Read the Public-Lines header line and the public blob. */
1181     if (!read_header(fp, header) || 0 != strcmp(header, "Public-Lines"))
1182         goto error;
1183     if ((b = read_body(fp)) == NULL)
1184         goto error;
1185     i = atoi(b);
1186     sfree(b);
1187     if ((public_blob = read_blob(fp, i, &public_blob_len)) == NULL)
1188         goto error;
1189
1190     fclose(fp);
1191     if (pub_blob_len)
1192         *pub_blob_len = public_blob_len;
1193     if (algorithm)
1194         *algorithm = alg->name;
1195     return public_blob;
1196
1197     /*
1198      * Error processing.
1199      */
1200   error:
1201     if (fp)
1202         fclose(fp);
1203     if (public_blob)
1204         sfree(public_blob);
1205     if (errorstr)
1206         *errorstr = error;
1207     if (comment && commentptr) {
1208         sfree(comment);
1209         *commentptr = NULL;
1210     }
1211     return NULL;
1212 }
1213
1214 int ssh2_userkey_encrypted(const Filename *filename, char **commentptr)
1215 {
1216     FILE *fp;
1217     char header[40], *b, *comment;
1218     int ret;
1219
1220     if (commentptr)
1221         *commentptr = NULL;
1222
1223     fp = f_open(filename, "rb", FALSE);
1224     if (!fp)
1225         return 0;
1226     if (!read_header(fp, header)
1227         || (0 != strcmp(header, "PuTTY-User-Key-File-2") &&
1228             0 != strcmp(header, "PuTTY-User-Key-File-1"))) {
1229         fclose(fp);
1230         return 0;
1231     }
1232     if ((b = read_body(fp)) == NULL) {
1233         fclose(fp);
1234         return 0;
1235     }
1236     sfree(b);                          /* we don't care about key type here */
1237     /* Read the Encryption header line. */
1238     if (!read_header(fp, header) || 0 != strcmp(header, "Encryption")) {
1239         fclose(fp);
1240         return 0;
1241     }
1242     if ((b = read_body(fp)) == NULL) {
1243         fclose(fp);
1244         return 0;
1245     }
1246
1247     /* Read the Comment header line. */
1248     if (!read_header(fp, header) || 0 != strcmp(header, "Comment")) {
1249         fclose(fp);
1250         sfree(b);
1251         return 1;
1252     }
1253     if ((comment = read_body(fp)) == NULL) {
1254         fclose(fp);
1255         sfree(b);
1256         return 1;
1257     }
1258
1259     if (commentptr)
1260         *commentptr = comment;
1261     else
1262         sfree(comment);
1263
1264     fclose(fp);
1265     if (!strcmp(b, "aes256-cbc"))
1266         ret = 1;
1267     else
1268         ret = 0;
1269     sfree(b);
1270     return ret;
1271 }
1272
1273 int base64_lines(int datalen)
1274 {
1275     /* When encoding, we use 64 chars/line, which equals 48 real chars. */
1276     return (datalen + 47) / 48;
1277 }
1278
1279 void base64_encode(FILE *fp, const unsigned char *data, int datalen, int cpl)
1280 {
1281     int linelen = 0;
1282     char out[4];
1283     int n, i;
1284
1285     while (datalen > 0) {
1286         n = (datalen < 3 ? datalen : 3);
1287         base64_encode_atom(data, n, out);
1288         data += n;
1289         datalen -= n;
1290         for (i = 0; i < 4; i++) {
1291             if (linelen >= cpl) {
1292                 linelen = 0;
1293                 fputc('\n', fp);
1294             }
1295             fputc(out[i], fp);
1296             linelen++;
1297         }
1298     }
1299     fputc('\n', fp);
1300 }
1301
1302 int ssh2_save_userkey(const Filename *filename, struct ssh2_userkey *key,
1303                       char *passphrase)
1304 {
1305     FILE *fp;
1306     unsigned char *pub_blob, *priv_blob, *priv_blob_encrypted;
1307     int pub_blob_len, priv_blob_len, priv_encrypted_len;
1308     int passlen;
1309     int cipherblk;
1310     int i;
1311     char *cipherstr;
1312     unsigned char priv_mac[20];
1313
1314     /*
1315      * Fetch the key component blobs.
1316      */
1317     pub_blob = key->alg->public_blob(key->data, &pub_blob_len);
1318     priv_blob = key->alg->private_blob(key->data, &priv_blob_len);
1319     if (!pub_blob || !priv_blob) {
1320         sfree(pub_blob);
1321         sfree(priv_blob);
1322         return 0;
1323     }
1324
1325     /*
1326      * Determine encryption details, and encrypt the private blob.
1327      */
1328     if (passphrase) {
1329         cipherstr = "aes256-cbc";
1330         cipherblk = 16;
1331     } else {
1332         cipherstr = "none";
1333         cipherblk = 1;
1334     }
1335     priv_encrypted_len = priv_blob_len + cipherblk - 1;
1336     priv_encrypted_len -= priv_encrypted_len % cipherblk;
1337     priv_blob_encrypted = snewn(priv_encrypted_len, unsigned char);
1338     memset(priv_blob_encrypted, 0, priv_encrypted_len);
1339     memcpy(priv_blob_encrypted, priv_blob, priv_blob_len);
1340     /* Create padding based on the SHA hash of the unpadded blob. This prevents
1341      * too easy a known-plaintext attack on the last block. */
1342     SHA_Simple(priv_blob, priv_blob_len, priv_mac);
1343     assert(priv_encrypted_len - priv_blob_len < 20);
1344     memcpy(priv_blob_encrypted + priv_blob_len, priv_mac,
1345            priv_encrypted_len - priv_blob_len);
1346
1347     /* Now create the MAC. */
1348     {
1349         unsigned char *macdata;
1350         int maclen;
1351         unsigned char *p;
1352         int namelen = strlen(key->alg->name);
1353         int enclen = strlen(cipherstr);
1354         int commlen = strlen(key->comment);
1355         SHA_State s;
1356         unsigned char mackey[20];
1357         char header[] = "putty-private-key-file-mac-key";
1358
1359         maclen = (4 + namelen +
1360                   4 + enclen +
1361                   4 + commlen +
1362                   4 + pub_blob_len +
1363                   4 + priv_encrypted_len);
1364         macdata = snewn(maclen, unsigned char);
1365         p = macdata;
1366 #define DO_STR(s,len) PUT_32BIT(p,(len));memcpy(p+4,(s),(len));p+=4+(len)
1367         DO_STR(key->alg->name, namelen);
1368         DO_STR(cipherstr, enclen);
1369         DO_STR(key->comment, commlen);
1370         DO_STR(pub_blob, pub_blob_len);
1371         DO_STR(priv_blob_encrypted, priv_encrypted_len);
1372
1373         SHA_Init(&s);
1374         SHA_Bytes(&s, header, sizeof(header)-1);
1375         if (passphrase)
1376             SHA_Bytes(&s, passphrase, strlen(passphrase));
1377         SHA_Final(&s, mackey);
1378         hmac_sha1_simple(mackey, 20, macdata, maclen, priv_mac);
1379         smemclr(macdata, maclen);
1380         sfree(macdata);
1381         smemclr(mackey, sizeof(mackey));
1382         smemclr(&s, sizeof(s));
1383     }
1384
1385     if (passphrase) {
1386         unsigned char key[40];
1387         SHA_State s;
1388
1389         passlen = strlen(passphrase);
1390
1391         SHA_Init(&s);
1392         SHA_Bytes(&s, "\0\0\0\0", 4);
1393         SHA_Bytes(&s, passphrase, passlen);
1394         SHA_Final(&s, key + 0);
1395         SHA_Init(&s);
1396         SHA_Bytes(&s, "\0\0\0\1", 4);
1397         SHA_Bytes(&s, passphrase, passlen);
1398         SHA_Final(&s, key + 20);
1399         aes256_encrypt_pubkey(key, priv_blob_encrypted,
1400                               priv_encrypted_len);
1401
1402         smemclr(key, sizeof(key));
1403         smemclr(&s, sizeof(s));
1404     }
1405
1406     fp = f_open(filename, "w", TRUE);
1407     if (!fp) {
1408         sfree(pub_blob);
1409         smemclr(priv_blob, priv_blob_len);
1410         sfree(priv_blob);
1411         smemclr(priv_blob_encrypted, priv_blob_len);
1412         sfree(priv_blob_encrypted);
1413         return 0;
1414     }
1415     fprintf(fp, "PuTTY-User-Key-File-2: %s\n", key->alg->name);
1416     fprintf(fp, "Encryption: %s\n", cipherstr);
1417     fprintf(fp, "Comment: %s\n", key->comment);
1418     fprintf(fp, "Public-Lines: %d\n", base64_lines(pub_blob_len));
1419     base64_encode(fp, pub_blob, pub_blob_len, 64);
1420     fprintf(fp, "Private-Lines: %d\n", base64_lines(priv_encrypted_len));
1421     base64_encode(fp, priv_blob_encrypted, priv_encrypted_len, 64);
1422     fprintf(fp, "Private-MAC: ");
1423     for (i = 0; i < 20; i++)
1424         fprintf(fp, "%02x", priv_mac[i]);
1425     fprintf(fp, "\n");
1426     fclose(fp);
1427
1428     sfree(pub_blob);
1429     smemclr(priv_blob, priv_blob_len);
1430     sfree(priv_blob);
1431     smemclr(priv_blob_encrypted, priv_blob_len);
1432     sfree(priv_blob_encrypted);
1433     return 1;
1434 }
1435
1436 /* ----------------------------------------------------------------------
1437  * Determine the type of a private key file.
1438  */
1439 static int key_type_fp(FILE *fp)
1440 {
1441     char buf[1024];
1442     const char public_std_sig[] = "---- BEGIN SSH2 PUBLIC KEY";
1443     const char putty2_sig[] = "PuTTY-User-Key-File-";
1444     const char sshcom_sig[] = "---- BEGIN SSH2 ENCRYPTED PRIVAT";
1445     const char openssh_new_sig[] = "-----BEGIN OPENSSH PRIVATE KEY";
1446     const char openssh_sig[] = "-----BEGIN ";
1447     int i;
1448     char *p;
1449
1450     i = fread(buf, 1, sizeof(buf)-1, fp);
1451     rewind(fp);
1452
1453     if (i < 0)
1454         return SSH_KEYTYPE_UNOPENABLE;
1455     if (i < 32)
1456         return SSH_KEYTYPE_UNKNOWN;
1457     assert(i > 0 && i < sizeof(buf));
1458     buf[i] = '\0';
1459     if (!memcmp(buf, rsa_signature, sizeof(rsa_signature)-1))
1460         return SSH_KEYTYPE_SSH1;
1461     if (!memcmp(buf, public_std_sig, sizeof(public_std_sig)-1))
1462         return SSH_KEYTYPE_SSH2_PUBLIC_RFC4716;
1463     if (!memcmp(buf, putty2_sig, sizeof(putty2_sig)-1))
1464         return SSH_KEYTYPE_SSH2;
1465     if (!memcmp(buf, openssh_new_sig, sizeof(openssh_new_sig)-1))
1466         return SSH_KEYTYPE_OPENSSH_NEW;
1467     if (!memcmp(buf, openssh_sig, sizeof(openssh_sig)-1))
1468         return SSH_KEYTYPE_OPENSSH_PEM;
1469     if (!memcmp(buf, sshcom_sig, sizeof(sshcom_sig)-1))
1470         return SSH_KEYTYPE_SSHCOM;
1471     if ((p = buf + strspn(buf, "0123456789"), *p == ' ') &&
1472         (p = p+1 + strspn(p+1, "0123456789"), *p == ' ') &&
1473         (p = p+1 + strspn(p+1, "0123456789"), *p == ' ' || *p == '\n' || !*p))
1474         return SSH_KEYTYPE_SSH1_PUBLIC;
1475     if ((p = buf + strcspn(buf, " "), find_pubkey_alg_len(p-buf, buf)) &&
1476         (p = p+1 + strspn(p+1, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghij"
1477                           "klmnopqrstuvwxyz+/="),
1478          *p == ' ' || *p == '\n' || !*p))
1479         return SSH_KEYTYPE_SSH2_PUBLIC_OPENSSH;
1480     return SSH_KEYTYPE_UNKNOWN;        /* unrecognised or EOF */
1481 }
1482
1483 int key_type(const Filename *filename)
1484 {
1485     FILE *fp;
1486     int ret;
1487
1488     fp = f_open(filename, "r", FALSE);
1489     if (!fp)
1490         return SSH_KEYTYPE_UNOPENABLE;
1491     ret = key_type_fp(fp);
1492     fclose(fp);
1493     return ret;
1494 }
1495
1496 /*
1497  * Convert the type word to a string, for `wrong type' error
1498  * messages.
1499  */
1500 char *key_type_to_str(int type)
1501 {
1502     switch (type) {
1503       case SSH_KEYTYPE_UNOPENABLE: return "unable to open file"; break;
1504       case SSH_KEYTYPE_UNKNOWN: return "not a recognised key file format"; break;
1505       case SSH_KEYTYPE_SSH1_PUBLIC: return "SSH-1 public key"; break;
1506       case SSH_KEYTYPE_SSH2_PUBLIC_RFC4716: return "SSH-2 public key (RFC 4716 format)"; break;
1507       case SSH_KEYTYPE_SSH2_PUBLIC_OPENSSH: return "SSH-2 public key (OpenSSH format)"; break;
1508       case SSH_KEYTYPE_SSH1: return "SSH-1 private key"; break;
1509       case SSH_KEYTYPE_SSH2: return "PuTTY SSH-2 private key"; break;
1510       case SSH_KEYTYPE_OPENSSH_PEM: return "OpenSSH SSH-2 private key (old PEM format)"; break;
1511       case SSH_KEYTYPE_OPENSSH_NEW: return "OpenSSH SSH-2 private key (new format)"; break;
1512       case SSH_KEYTYPE_SSHCOM: return "ssh.com SSH-2 private key"; break;
1513         /*
1514          * This function is called with a key type derived from
1515          * looking at an actual key file, so the output-only type
1516          * OPENSSH_AUTO should never get here, and is much an INTERNAL
1517          * ERROR as a code we don't even understand.
1518          */
1519       case SSH_KEYTYPE_OPENSSH_AUTO: return "INTERNAL ERROR (OPENSSH_AUTO)"; break;
1520       default: return "INTERNAL ERROR"; break;
1521     }
1522 }