source: filezilla/trunk/fuentes/src/putty/import.c @ 3185

Last change on this file since 3185 was 3185, checked in by jrpelegrina, 2 years ago

Update new version: 3.15.02

File size: 79.3 KB
Line 
1/*
2 * Code for PuTTY to import and export private key files in other
3 * SSH clients' formats.
4 */
5
6#include <stdio.h>
7#include <stdlib.h>
8#include <assert.h>
9#include <ctype.h>
10
11#include "putty.h"
12#include "ssh.h"
13#include "misc.h"
14
15int openssh_pem_encrypted(const Filename *filename);
16int openssh_new_encrypted(const Filename *filename);
17struct ssh2_userkey *openssh_pem_read(const Filename *filename,
18                                      char *passphrase,
19                                      const char **errmsg_p);
20struct ssh2_userkey *openssh_new_read(const Filename *filename,
21                                      char *passphrase,
22                                      const char **errmsg_p);
23int openssh_auto_write(const Filename *filename, struct ssh2_userkey *key,
24                       char *passphrase);
25int openssh_pem_write(const Filename *filename, struct ssh2_userkey *key,
26                      char *passphrase);
27int openssh_new_write(const Filename *filename, struct ssh2_userkey *key,
28                      char *passphrase);
29
30int sshcom_encrypted(const Filename *filename, char **comment);
31struct ssh2_userkey *sshcom_read(const Filename *filename, char *passphrase,
32                                 const char **errmsg_p);
33int sshcom_write(const Filename *filename, struct ssh2_userkey *key,
34                 char *passphrase);
35
36/*
37 * Given a key type, determine whether we know how to import it.
38 */
39int import_possible(int type)
40{
41    if (type == SSH_KEYTYPE_OPENSSH_PEM)
42        return 1;
43    if (type == SSH_KEYTYPE_OPENSSH_NEW)
44        return 1;
45    if (type == SSH_KEYTYPE_SSHCOM)
46        return 1;
47    return 0;
48}
49
50/*
51 * Given a key type, determine what native key type
52 * (SSH_KEYTYPE_SSH1 or SSH_KEYTYPE_SSH2) it will come out as once
53 * we've imported it.
54 */
55int import_target_type(int type)
56{
57    /*
58     * There are no known foreign SSH-1 key formats.
59     */
60    return SSH_KEYTYPE_SSH2;
61}
62
63/*
64 * Determine whether a foreign key is encrypted.
65 */
66int import_encrypted(const Filename *filename, int type, char **comment)
67{
68    if (type == SSH_KEYTYPE_OPENSSH_PEM) {
69        /* OpenSSH PEM format doesn't contain a key comment at all */
70        *comment = dupstr(filename_to_str(filename));
71        return openssh_pem_encrypted(filename);
72    } else if (type == SSH_KEYTYPE_OPENSSH_NEW) {
73        /* OpenSSH new format does, but it's inside the encrypted
74         * section for some reason */
75        *comment = dupstr(filename_to_str(filename));
76        return openssh_new_encrypted(filename);
77    } else if (type == SSH_KEYTYPE_SSHCOM) {
78        return sshcom_encrypted(filename, comment);
79    }
80    return 0;
81}
82
83/*
84 * Import an SSH-1 key.
85 */
86int import_ssh1(const Filename *filename, int type,
87                struct RSAKey *key, char *passphrase, const char **errmsg_p)
88{
89    return 0;
90}
91
92/*
93 * Import an SSH-2 key.
94 */
95struct ssh2_userkey *import_ssh2(const Filename *filename, int type,
96                                 char *passphrase, const char **errmsg_p)
97{
98    if (type == SSH_KEYTYPE_OPENSSH_PEM)
99        return openssh_pem_read(filename, passphrase, errmsg_p);
100    else if (type == SSH_KEYTYPE_OPENSSH_NEW)
101        return openssh_new_read(filename, passphrase, errmsg_p);
102    if (type == SSH_KEYTYPE_SSHCOM)
103        return sshcom_read(filename, passphrase, errmsg_p);
104    return NULL;
105}
106
107/*
108 * Export an SSH-1 key.
109 */
110int export_ssh1(const Filename *filename, int type, struct RSAKey *key,
111                char *passphrase)
112{
113    return 0;
114}
115
116/*
117 * Export an SSH-2 key.
118 */
119int export_ssh2(const Filename *filename, int type,
120                struct ssh2_userkey *key, char *passphrase)
121{
122    if (type == SSH_KEYTYPE_OPENSSH_AUTO)
123        return openssh_auto_write(filename, key, passphrase);
124    if (type == SSH_KEYTYPE_OPENSSH_NEW)
125        return openssh_new_write(filename, key, passphrase);
126    if (type == SSH_KEYTYPE_SSHCOM)
127        return sshcom_write(filename, key, passphrase);
128    return 0;
129}
130
131/*
132 * Strip trailing CRs and LFs at the end of a line of text.
133 */
134void strip_crlf(char *str)
135{
136    char *p = str + strlen(str);
137
138    while (p > str && (p[-1] == '\r' || p[-1] == '\n'))
139        *--p = '\0';
140}
141
142/* ----------------------------------------------------------------------
143 * Helper routines. (The base64 ones are defined in sshpubk.c.)
144 */
145
146#define isbase64(c) (    ((c) >= 'A' && (c) <= 'Z') || \
147                         ((c) >= 'a' && (c) <= 'z') || \
148                         ((c) >= '0' && (c) <= '9') || \
149                         (c) == '+' || (c) == '/' || (c) == '=' \
150                         )
151
152/*
153 * Read an ASN.1/BER identifier and length pair.
154 *
155 * Flags are a combination of the #defines listed below.
156 *
157 * Returns -1 if unsuccessful; otherwise returns the number of
158 * bytes used out of the source data.
159 */
160
161/* ASN.1 tag classes. */
162#define ASN1_CLASS_UNIVERSAL        (0 << 6)
163#define ASN1_CLASS_APPLICATION      (1 << 6)
164#define ASN1_CLASS_CONTEXT_SPECIFIC (2 << 6)
165#define ASN1_CLASS_PRIVATE          (3 << 6)
166#define ASN1_CLASS_MASK             (3 << 6)
167
168/* Primitive versus constructed bit. */
169#define ASN1_CONSTRUCTED            (1 << 5)
170
171static int ber_read_id_len(void *source, int sourcelen,
172                           int *id, int *length, int *flags)
173{
174    unsigned char *p = (unsigned char *) source;
175
176    if (sourcelen == 0)
177        return -1;
178
179    *flags = (*p & 0xE0);
180    if ((*p & 0x1F) == 0x1F) {
181        *id = 0;
182        while (*p & 0x80) {
183            p++, sourcelen--;
184            if (sourcelen == 0)
185                return -1;
186            *id = (*id << 7) | (*p & 0x7F);
187        }
188        p++, sourcelen--;
189    } else {
190        *id = *p & 0x1F;
191        p++, sourcelen--;
192    }
193
194    if (sourcelen == 0)
195        return -1;
196
197    if (*p & 0x80) {
198        unsigned len;
199        int n = *p & 0x7F;
200        p++, sourcelen--;
201        if (sourcelen < n)
202            return -1;
203        len = 0;
204        while (n--)
205            len = (len << 8) | (*p++);
206        sourcelen -= n;
207        *length = toint(len);
208    } else {
209        *length = *p;
210        p++, sourcelen--;
211    }
212
213    return p - (unsigned char *) source;
214}
215
216/*
217 * Write an ASN.1/BER identifier and length pair. Returns the
218 * number of bytes consumed. Assumes dest contains enough space.
219 * Will avoid writing anything if dest is NULL, but still return
220 * amount of space required.
221 */
222static int ber_write_id_len(void *dest, int id, int length, int flags)
223{
224    unsigned char *d = (unsigned char *)dest;
225    int len = 0;
226
227    if (id <= 30) {
228        /*
229         * Identifier is one byte.
230         */
231        len++;
232        if (d) *d++ = id | flags;
233    } else {
234        int n;
235        /*
236         * Identifier is multiple bytes: the first byte is 11111
237         * plus the flags, and subsequent bytes encode the value of
238         * the identifier, 7 bits at a time, with the top bit of
239         * each byte 1 except the last one which is 0.
240         */
241        len++;
242        if (d) *d++ = 0x1F | flags;
243        for (n = 1; (id >> (7*n)) > 0; n++)
244            continue;                  /* count the bytes */
245        while (n--) {
246            len++;
247            if (d) *d++ = (n ? 0x80 : 0) | ((id >> (7*n)) & 0x7F);
248        }
249    }
250
251    if (length < 128) {
252        /*
253         * Length is one byte.
254         */
255        len++;
256        if (d) *d++ = length;
257    } else {
258        int n;
259        /*
260         * Length is multiple bytes. The first is 0x80 plus the
261         * number of subsequent bytes, and the subsequent bytes
262         * encode the actual length.
263         */
264        for (n = 1; (length >> (8*n)) > 0; n++)
265            continue;                  /* count the bytes */
266        len++;
267        if (d) *d++ = 0x80 | n;
268        while (n--) {
269            len++;
270            if (d) *d++ = (length >> (8*n)) & 0xFF;
271        }
272    }
273
274    return len;
275}
276
277static int put_uint32(void *target, unsigned val)
278{
279    unsigned char *d = (unsigned char *)target;
280
281    PUT_32BIT(d, val);
282    return 4;
283}
284
285static int put_string(void *target, const void *data, int len)
286{
287    unsigned char *d = (unsigned char *)target;
288
289    PUT_32BIT(d, len);
290    memcpy(d+4, data, len);
291    return len+4;
292}
293
294static int put_string_z(void *target, const char *string)
295{
296    return put_string(target, string, strlen(string));
297}
298
299static int put_mp(void *target, void *data, int len)
300{
301    unsigned char *d = (unsigned char *)target;
302    unsigned char *i = (unsigned char *)data;
303
304    if (*i & 0x80) {
305        PUT_32BIT(d, len+1);
306        d[4] = 0;
307        memcpy(d+5, data, len);
308        return len+5;
309    } else {
310        PUT_32BIT(d, len);
311        memcpy(d+4, data, len);
312        return len+4;
313    }
314}
315
316/* Simple structure to point to an mp-int within a blob. */
317struct mpint_pos { void *start; int bytes; };
318
319static int ssh2_read_mpint(void *data, int len, struct mpint_pos *ret)
320{
321    int bytes;
322    unsigned char *d = (unsigned char *) data;
323
324    if (len < 4)
325        goto error;
326    bytes = toint(GET_32BIT(d));
327    if (bytes < 0 || len-4 < bytes)
328        goto error;
329
330    ret->start = d + 4;
331    ret->bytes = bytes;
332    return bytes+4;
333
334    error:
335    ret->start = NULL;
336    ret->bytes = -1;
337    return len;                        /* ensure further calls fail as well */
338}
339
340/* ----------------------------------------------------------------------
341 * Code to read and write OpenSSH private keys, in the old-style PEM
342 * format.
343 */
344
345typedef enum {
346    OP_DSA, OP_RSA, OP_ECDSA
347} openssh_pem_keytype;
348typedef enum {
349    OP_E_3DES, OP_E_AES
350} openssh_pem_enc;
351
352struct openssh_pem_key {
353    openssh_pem_keytype keytype;
354    int encrypted;
355    openssh_pem_enc encryption;
356    char iv[32];
357    unsigned char *keyblob;
358    int keyblob_len, keyblob_size;
359};
360
361static struct openssh_pem_key *load_openssh_pem_key(const Filename *filename,
362                                                    const char **errmsg_p)
363{
364    struct openssh_pem_key *ret;
365    FILE *fp = NULL;
366    char *line = NULL;
367    const char *errmsg;
368    char *p;
369    int headers_done;
370    char base64_bit[4];
371    int base64_chars = 0;
372
373    ret = snew(struct openssh_pem_key);
374    ret->keyblob = NULL;
375    ret->keyblob_len = ret->keyblob_size = 0;
376
377    fp = f_open(filename, "r", FALSE);
378    if (!fp) {
379        errmsg = "unable to open key file";
380        goto error;
381    }
382
383    if (!(line = fgetline(fp))) {
384        errmsg = "unexpected end of file";
385        goto error;
386    }
387    strip_crlf(line);
388    if (!strstartswith(line, "-----BEGIN ") ||
389        !strendswith(line, "PRIVATE KEY-----")) {
390        errmsg = "file does not begin with OpenSSH key header";
391        goto error;
392    }
393    /*
394     * Parse the BEGIN line. For old-format keys, this tells us the
395     * type of the key; for new-format keys, all it tells us is the
396     * format, and we'll find out the key type once we parse the
397     * base64.
398     */
399    if (!strcmp(line, "-----BEGIN RSA PRIVATE KEY-----")) {
400        ret->keytype = OP_RSA;
401    } else if (!strcmp(line, "-----BEGIN DSA PRIVATE KEY-----")) {
402        ret->keytype = OP_DSA;
403    } else if (!strcmp(line, "-----BEGIN EC PRIVATE KEY-----")) {
404        ret->keytype = OP_ECDSA;
405    } else if (!strcmp(line, "-----BEGIN OPENSSH PRIVATE KEY-----")) {
406        errmsg = "this is a new-style OpenSSH key";
407        goto error;
408    } else {
409        errmsg = "unrecognised key type";
410        goto error;
411    }
412    smemclr(line, strlen(line));
413    sfree(line);
414    line = NULL;
415
416    ret->encrypted = FALSE;
417    memset(ret->iv, 0, sizeof(ret->iv));
418
419    headers_done = 0;
420    while (1) {
421        if (!(line = fgetline(fp))) {
422            errmsg = "unexpected end of file";
423            goto error;
424        }
425        strip_crlf(line);
426        if (strstartswith(line, "-----END ") &&
427            strendswith(line, "PRIVATE KEY-----")) {
428            sfree(line);
429            line = NULL;
430            break;                     /* done */
431        }
432        if ((p = strchr(line, ':')) != NULL) {
433            if (headers_done) {
434                errmsg = "header found in body of key data";
435                goto error;
436            }
437            *p++ = '\0';
438            while (*p && isspace((unsigned char)*p)) p++;
439            if (!strcmp(line, "Proc-Type")) {
440                if (p[0] != '4' || p[1] != ',') {
441                    errmsg = "Proc-Type is not 4 (only 4 is supported)";
442                    goto error;
443                }
444                p += 2;
445                if (!strcmp(p, "ENCRYPTED"))
446                    ret->encrypted = TRUE;
447            } else if (!strcmp(line, "DEK-Info")) {
448                int i, j, ivlen;
449
450                if (!strncmp(p, "DES-EDE3-CBC,", 13)) {
451                    ret->encryption = OP_E_3DES;
452                    ivlen = 8;
453                } else if (!strncmp(p, "AES-128-CBC,", 12)) {
454                    ret->encryption = OP_E_AES;
455                    ivlen = 16;
456                } else {
457                    errmsg = "unsupported cipher";
458                    goto error;
459                }
460                p = strchr(p, ',') + 1;/* always non-NULL, by above checks */
461                for (i = 0; i < ivlen; i++) {
462                    if (1 != sscanf(p, "%2x", &j)) {
463                        errmsg = "expected more iv data in DEK-Info";
464                        goto error;
465                    }
466                    ret->iv[i] = j;
467                    p += 2;
468                }
469                if (*p) {
470                    errmsg = "more iv data than expected in DEK-Info";
471                    goto error;
472                }
473            }
474        } else {
475            headers_done = 1;
476
477            p = line;
478            while (isbase64(*p)) {
479                base64_bit[base64_chars++] = *p;
480                if (base64_chars == 4) {
481                    unsigned char out[3];
482                    int len;
483
484                    base64_chars = 0;
485
486                    len = base64_decode_atom(base64_bit, out);
487
488                    if (len <= 0) {
489                        errmsg = "invalid base64 encoding";
490                        goto error;
491                    }
492
493                    if (ret->keyblob_len + len > ret->keyblob_size) {
494                        ret->keyblob_size = ret->keyblob_len + len + 256;
495                        ret->keyblob = sresize(ret->keyblob, ret->keyblob_size,
496                                               unsigned char);
497                    }
498
499                    memcpy(ret->keyblob + ret->keyblob_len, out, len);
500                    ret->keyblob_len += len;
501
502                    smemclr(out, sizeof(out));
503                }
504
505                p++;
506            }
507        }
508        smemclr(line, strlen(line));
509        sfree(line);
510        line = NULL;
511    }
512
513    fclose(fp);
514    fp = NULL;
515
516    if (ret->keyblob_len == 0 || !ret->keyblob) {
517        errmsg = "key body not present";
518        goto error;
519    }
520
521    if (ret->encrypted && ret->keyblob_len % 8 != 0) {
522        errmsg = "encrypted key blob is not a multiple of "
523            "cipher block size";
524        goto error;
525    }
526
527    smemclr(base64_bit, sizeof(base64_bit));
528    if (errmsg_p) *errmsg_p = NULL;
529    return ret;
530
531    error:
532    if (line) {
533        smemclr(line, strlen(line));
534        sfree(line);
535        line = NULL;
536    }
537    smemclr(base64_bit, sizeof(base64_bit));
538    if (ret) {
539        if (ret->keyblob) {
540            smemclr(ret->keyblob, ret->keyblob_size);
541            sfree(ret->keyblob);
542        }
543        smemclr(ret, sizeof(*ret));
544        sfree(ret);
545    }
546    if (errmsg_p) *errmsg_p = errmsg;
547    if (fp) fclose(fp);
548    return NULL;
549}
550
551int openssh_pem_encrypted(const Filename *filename)
552{
553    struct openssh_pem_key *key = load_openssh_pem_key(filename, NULL);
554    int ret;
555
556    if (!key)
557        return 0;
558    ret = key->encrypted;
559    smemclr(key->keyblob, key->keyblob_size);
560    sfree(key->keyblob);
561    smemclr(key, sizeof(*key));
562    sfree(key);
563    return ret;
564}
565
566struct ssh2_userkey *openssh_pem_read(const Filename *filename,
567                                      char *passphrase,
568                                      const char **errmsg_p)
569{
570    struct openssh_pem_key *key = load_openssh_pem_key(filename, errmsg_p);
571    struct ssh2_userkey *retkey;
572    unsigned char *p, *q;
573    int ret, id, len, flags;
574    int i, num_integers;
575    struct ssh2_userkey *retval = NULL;
576    const char *errmsg;
577    unsigned char *blob;
578    int blobsize = 0, blobptr, privptr;
579    char *modptr = NULL;
580    int modlen = 0;
581
582    blob = NULL;
583
584    if (!key)
585        return NULL;
586
587    if (key->encrypted) {
588        /*
589         * Derive encryption key from passphrase and iv/salt:
590         *
591         *  - let block A equal MD5(passphrase || iv)
592         *  - let block B equal MD5(A || passphrase || iv)
593         *  - block C would be MD5(B || passphrase || iv) and so on
594         *  - encryption key is the first N bytes of A || B
595         *
596         * (Note that only 8 bytes of the iv are used for key
597         * derivation, even when the key is encrypted with AES and
598         * hence there are 16 bytes available.)
599         */
600        struct MD5Context md5c;
601        unsigned char keybuf[32];
602
603        MD5Init(&md5c);
604        MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase));
605        MD5Update(&md5c, (unsigned char *)key->iv, 8);
606        MD5Final(keybuf, &md5c);
607
608        MD5Init(&md5c);
609        MD5Update(&md5c, keybuf, 16);
610        MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase));
611        MD5Update(&md5c, (unsigned char *)key->iv, 8);
612        MD5Final(keybuf+16, &md5c);
613
614        /*
615         * Now decrypt the key blob.
616         */
617        if (key->encryption == OP_E_3DES)
618            des3_decrypt_pubkey_ossh(keybuf, (unsigned char *)key->iv,
619                                     key->keyblob, key->keyblob_len);
620        else {
621            void *ctx;
622            assert(key->encryption == OP_E_AES);
623            ctx = aes_make_context();
624            aes128_key(ctx, keybuf);
625            aes_iv(ctx, (unsigned char *)key->iv);
626            aes_ssh2_decrypt_blk(ctx, key->keyblob, key->keyblob_len);
627            aes_free_context(ctx);
628        }
629
630        smemclr(&md5c, sizeof(md5c));
631        smemclr(keybuf, sizeof(keybuf));
632    }
633
634    /*
635     * Now we have a decrypted key blob, which contains an ASN.1
636     * encoded private key. We must now untangle the ASN.1.
637     *
638     * We expect the whole key blob to be formatted as a SEQUENCE
639     * (0x30 followed by a length code indicating that the rest of
640     * the blob is part of the sequence). Within that SEQUENCE we
641     * expect to see a bunch of INTEGERs. What those integers mean
642     * depends on the key type:
643     *
644     *  - For RSA, we expect the integers to be 0, n, e, d, p, q,
645     *    dmp1, dmq1, iqmp in that order. (The last three are d mod
646     *    (p-1), d mod (q-1), inverse of q mod p respectively.)
647     *
648     *  - For DSA, we expect them to be 0, p, q, g, y, x in that
649     *    order.
650     *
651     *  - In ECDSA the format is totally different: we see the
652     *    SEQUENCE, but beneath is an INTEGER 1, OCTET STRING priv
653     *    EXPLICIT [0] OID curve, EXPLICIT [1] BIT STRING pubPoint
654     */
655   
656    p = key->keyblob;
657
658    /* Expect the SEQUENCE header. Take its absence as a failure to
659     * decrypt, if the key was encrypted. */
660    ret = ber_read_id_len(p, key->keyblob_len, &id, &len, &flags);
661    p += ret;
662    if (ret < 0 || id != 16 || len < 0 ||
663        key->keyblob+key->keyblob_len-p < len) {
664        errmsg = "ASN.1 decoding failure";
665        retval = key->encrypted ? SSH2_WRONG_PASSPHRASE : NULL;
666        goto error;
667    }
668
669    /* Expect a load of INTEGERs. */
670    if (key->keytype == OP_RSA)
671        num_integers = 9;
672    else if (key->keytype == OP_DSA)
673        num_integers = 6;
674    else
675        num_integers = 0;              /* placate compiler warnings */
676
677
678    if (key->keytype == OP_ECDSA) {
679        /* And now for something completely different */
680        unsigned char *priv;
681        int privlen;
682        const struct ssh_signkey *alg;
683        const struct ec_curve *curve;
684        int algnamelen, curvenamelen;
685        /* Read INTEGER 1 */
686        ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,
687                              &id, &len, &flags);
688        p += ret;
689        if (ret < 0 || id != 2 || len != 1 ||
690            key->keyblob+key->keyblob_len-p < len || p[0] != 1) {
691            errmsg = "ASN.1 decoding failure";
692            retval = key->encrypted ? SSH2_WRONG_PASSPHRASE : NULL;
693            goto error;
694        }
695        p += 1;
696        /* Read private key OCTET STRING */
697        ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,
698                              &id, &len, &flags);
699        p += ret;
700        if (ret < 0 || id != 4 || len < 0 ||
701            key->keyblob+key->keyblob_len-p < len) {
702            errmsg = "ASN.1 decoding failure";
703            retval = key->encrypted ? SSH2_WRONG_PASSPHRASE : NULL;
704            goto error;
705        }
706        priv = p;
707        privlen = len;
708        p += len;
709        /* Read curve OID */
710        ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,
711                              &id, &len, &flags);
712        p += ret;
713        if (ret < 0 || id != 0 || len < 0 ||
714            key->keyblob+key->keyblob_len-p < len) {
715            errmsg = "ASN.1 decoding failure";
716            retval = key->encrypted ? SSH2_WRONG_PASSPHRASE : NULL;
717            goto error;
718        }
719        ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,
720                              &id, &len, &flags);
721        p += ret;
722        if (ret < 0 || id != 6 || len < 0 ||
723            key->keyblob+key->keyblob_len-p < len) {
724            errmsg = "ASN.1 decoding failure";
725            retval = key->encrypted ? SSH2_WRONG_PASSPHRASE : NULL;
726            goto error;
727        }
728        alg = ec_alg_by_oid(len, p, &curve);
729        if (!alg) {
730            errmsg = "Unsupported ECDSA curve.";
731            retval = NULL;
732            goto error;
733        }
734        p += len;
735        /* Read BIT STRING point */
736        ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,
737                              &id, &len, &flags);
738        p += ret;
739        if (ret < 0 || id != 1 || len < 0 ||
740            key->keyblob+key->keyblob_len-p < len) {
741            errmsg = "ASN.1 decoding failure";
742            retval = key->encrypted ? SSH2_WRONG_PASSPHRASE : NULL;
743            goto error;
744        }
745        ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,
746                              &id, &len, &flags);
747        p += ret;
748        if (ret < 0 || id != 3 || len < 0 ||
749            key->keyblob+key->keyblob_len-p < len ||
750            len != ((((curve->fieldBits + 7) / 8) * 2) + 2)) {
751            errmsg = "ASN.1 decoding failure";
752            retval = key->encrypted ? SSH2_WRONG_PASSPHRASE : NULL;
753            goto error;
754        }
755        p += 1; len -= 1; /* Skip 0x00 before point */
756
757        /* Construct the key */
758        retkey = snew(struct ssh2_userkey);
759        if (!retkey) {
760            errmsg = "out of memory";
761            goto error;
762        }
763        retkey->alg = alg;
764        blob = snewn((4+19 + 4+8 + 4+len) + (4+1+privlen), unsigned char);
765        if (!blob) {
766            sfree(retkey);
767            errmsg = "out of memory";
768            goto error;
769        }
770
771        q = blob;
772
773        algnamelen = strlen(alg->name);
774        PUT_32BIT(q, algnamelen); q += 4;
775        memcpy(q, alg->name, algnamelen); q += algnamelen;
776
777        curvenamelen = strlen(curve->name);
778        PUT_32BIT(q, curvenamelen); q += 4;
779        memcpy(q, curve->name, curvenamelen); q += curvenamelen;
780
781        PUT_32BIT(q, len); q += 4;
782        memcpy(q, p, len); q += len;
783
784        /*
785         * To be acceptable to our createkey(), the private blob must
786         * contain a valid mpint, i.e. without the top bit set. But
787         * the input private string may have the top bit set, so we
788         * prefix a zero byte to ensure createkey() doesn't fail for
789         * that reason.
790         */
791        PUT_32BIT(q, privlen+1);
792        q[4] = 0;
793        memcpy(q+5, priv, privlen);
794
795        retkey->data = retkey->alg->createkey(retkey->alg,
796                                              blob, q-blob,
797                                              q, 5+privlen);
798
799        if (!retkey->data) {
800            sfree(retkey);
801            errmsg = "unable to create key data structure";
802            goto error;
803        }
804
805    } else if (key->keytype == OP_RSA || key->keytype == OP_DSA) {
806
807        /*
808         * Space to create key blob in.
809         */
810        blobsize = 256+key->keyblob_len;
811        blob = snewn(blobsize, unsigned char);
812        PUT_32BIT(blob, 7);
813        if (key->keytype == OP_DSA)
814            memcpy(blob+4, "ssh-dss", 7);
815        else if (key->keytype == OP_RSA)
816            memcpy(blob+4, "ssh-rsa", 7);
817        blobptr = 4+7;
818        privptr = -1;
819
820        for (i = 0; i < num_integers; i++) {
821            ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,
822                                  &id, &len, &flags);
823            p += ret;
824            if (ret < 0 || id != 2 || len < 0 ||
825                key->keyblob+key->keyblob_len-p < len) {
826                errmsg = "ASN.1 decoding failure";
827                retval = key->encrypted ? SSH2_WRONG_PASSPHRASE : NULL;
828                goto error;
829            }
830
831            if (i == 0) {
832                /*
833                 * The first integer should be zero always (I think
834                 * this is some sort of version indication).
835                 */
836                if (len != 1 || p[0] != 0) {
837                    errmsg = "version number mismatch";
838                    goto error;
839                }
840            } else if (key->keytype == OP_RSA) {
841                /*
842                 * Integers 1 and 2 go into the public blob but in the
843                 * opposite order; integers 3, 4, 5 and 8 go into the
844                 * private blob. The other two (6 and 7) are ignored.
845                 */
846                if (i == 1) {
847                    /* Save the details for after we deal with number 2. */
848                    modptr = (char *)p;
849                    modlen = len;
850                } else if (i != 6 && i != 7) {
851                    PUT_32BIT(blob+blobptr, len);
852                    memcpy(blob+blobptr+4, p, len);
853                    blobptr += 4+len;
854                    if (i == 2) {
855                        PUT_32BIT(blob+blobptr, modlen);
856                        memcpy(blob+blobptr+4, modptr, modlen);
857                        blobptr += 4+modlen;
858                        privptr = blobptr;
859                    }
860                }
861            } else if (key->keytype == OP_DSA) {
862                /*
863                 * Integers 1-4 go into the public blob; integer 5 goes
864                 * into the private blob.
865                 */
866                PUT_32BIT(blob+blobptr, len);
867                memcpy(blob+blobptr+4, p, len);
868                blobptr += 4+len;
869                if (i == 4)
870                    privptr = blobptr;
871            }
872
873            /* Skip past the number. */
874            p += len;
875        }
876
877        /*
878         * Now put together the actual key. Simplest way to do this is
879         * to assemble our own key blobs and feed them to the createkey
880         * functions; this is a bit faffy but it does mean we get all
881         * the sanity checks for free.
882         */
883        assert(privptr > 0);          /* should have bombed by now if not */
884        retkey = snew(struct ssh2_userkey);
885        retkey->alg = (key->keytype == OP_RSA ? &ssh_rsa : &ssh_dss);
886        retkey->data = retkey->alg->createkey(retkey->alg, blob, privptr,
887                                              blob+privptr,
888                                              blobptr-privptr);
889        if (!retkey->data) {
890            sfree(retkey);
891            errmsg = "unable to create key data structure";
892            goto error;
893        }
894
895    } else {
896        assert(0 && "Bad key type from load_openssh_pem_key");
897        errmsg = "Bad key type from load_openssh_pem_key";
898        goto error;
899    }
900
901    /*
902     * The old key format doesn't include a comment in the private
903     * key file.
904     */
905    retkey->comment = dupstr("imported-openssh-key");
906
907    errmsg = NULL;                     /* no error */
908    retval = retkey;
909
910    error:
911    if (blob) {
912        smemclr(blob, blobsize);
913        sfree(blob);
914    }
915    smemclr(key->keyblob, key->keyblob_size);
916    sfree(key->keyblob);
917    smemclr(key, sizeof(*key));
918    sfree(key);
919    if (errmsg_p) *errmsg_p = errmsg;
920    return retval;
921}
922
923int openssh_pem_write(const Filename *filename, struct ssh2_userkey *key,
924                      char *passphrase)
925{
926    unsigned char *pubblob, *privblob, *spareblob;
927    int publen, privlen, sparelen = 0;
928    unsigned char *outblob;
929    int outlen;
930    struct mpint_pos numbers[9];
931    int nnumbers, pos, len, seqlen, i;
932    const char *header, *footer;
933    char zero[1];
934    unsigned char iv[8];
935    int ret = 0;
936    FILE *fp;
937
938    /*
939     * Fetch the key blobs.
940     */
941    pubblob = key->alg->public_blob(key->data, &publen);
942    privblob = key->alg->private_blob(key->data, &privlen);
943    spareblob = outblob = NULL;
944
945    outblob = NULL;
946    len = 0;
947
948    /*
949     * Encode the OpenSSH key blob, and also decide on the header
950     * line.
951     */
952    if (key->alg == &ssh_rsa || key->alg == &ssh_dss) {
953        /*
954         * The RSA and DSS handlers share some code because the two
955         * key types have very similar ASN.1 representations, as a
956         * plain SEQUENCE of big integers. So we set up a list of
957         * bignums per key type and then construct the actual blob in
958         * common code after that.
959         */
960        if (key->alg == &ssh_rsa) {
961            int pos;
962            struct mpint_pos n, e, d, p, q, iqmp, dmp1, dmq1;
963            Bignum bd, bp, bq, bdmp1, bdmq1;
964
965            /*
966             * These blobs were generated from inside PuTTY, so we needn't
967             * treat them as untrusted.
968             */
969            pos = 4 + GET_32BIT(pubblob);
970            pos += ssh2_read_mpint(pubblob+pos, publen-pos, &e);
971            pos += ssh2_read_mpint(pubblob+pos, publen-pos, &n);
972            pos = 0;
973            pos += ssh2_read_mpint(privblob+pos, privlen-pos, &d);
974            pos += ssh2_read_mpint(privblob+pos, privlen-pos, &p);
975            pos += ssh2_read_mpint(privblob+pos, privlen-pos, &q);
976            pos += ssh2_read_mpint(privblob+pos, privlen-pos, &iqmp);
977
978            assert(e.start && iqmp.start); /* can't go wrong */
979
980            /* We also need d mod (p-1) and d mod (q-1). */
981            bd = bignum_from_bytes(d.start, d.bytes);
982            bp = bignum_from_bytes(p.start, p.bytes);
983            bq = bignum_from_bytes(q.start, q.bytes);
984            decbn(bp);
985            decbn(bq);
986            bdmp1 = bigmod(bd, bp);
987            bdmq1 = bigmod(bd, bq);
988            freebn(bd);
989            freebn(bp);
990            freebn(bq);
991
992            dmp1.bytes = (bignum_bitcount(bdmp1)+8)/8;
993            dmq1.bytes = (bignum_bitcount(bdmq1)+8)/8;
994            sparelen = dmp1.bytes + dmq1.bytes;
995            spareblob = snewn(sparelen, unsigned char);
996            dmp1.start = spareblob;
997            dmq1.start = spareblob + dmp1.bytes;
998            for (i = 0; i < dmp1.bytes; i++)
999                spareblob[i] = bignum_byte(bdmp1, dmp1.bytes-1 - i);
1000            for (i = 0; i < dmq1.bytes; i++)
1001                spareblob[i+dmp1.bytes] = bignum_byte(bdmq1, dmq1.bytes-1 - i);
1002            freebn(bdmp1);
1003            freebn(bdmq1);
1004
1005            numbers[0].start = zero; numbers[0].bytes = 1; zero[0] = '\0';
1006            numbers[1] = n;
1007            numbers[2] = e;
1008            numbers[3] = d;
1009            numbers[4] = p;
1010            numbers[5] = q;
1011            numbers[6] = dmp1;
1012            numbers[7] = dmq1;
1013            numbers[8] = iqmp;
1014
1015            nnumbers = 9;
1016            header = "-----BEGIN RSA PRIVATE KEY-----\n";
1017            footer = "-----END RSA PRIVATE KEY-----\n";
1018        } else {                       /* ssh-dss */
1019            int pos;
1020            struct mpint_pos p, q, g, y, x;
1021
1022            /*
1023             * These blobs were generated from inside PuTTY, so we needn't
1024             * treat them as untrusted.
1025             */
1026            pos = 4 + GET_32BIT(pubblob);
1027            pos += ssh2_read_mpint(pubblob+pos, publen-pos, &p);
1028            pos += ssh2_read_mpint(pubblob+pos, publen-pos, &q);
1029            pos += ssh2_read_mpint(pubblob+pos, publen-pos, &g);
1030            pos += ssh2_read_mpint(pubblob+pos, publen-pos, &y);
1031            pos = 0;
1032            pos += ssh2_read_mpint(privblob+pos, privlen-pos, &x);
1033
1034            assert(y.start && x.start); /* can't go wrong */
1035
1036            numbers[0].start = zero; numbers[0].bytes = 1; zero[0] = '\0';
1037            numbers[1] = p;
1038            numbers[2] = q;
1039            numbers[3] = g;
1040            numbers[4] = y;
1041            numbers[5] = x;
1042
1043            nnumbers = 6;
1044            header = "-----BEGIN DSA PRIVATE KEY-----\n";
1045            footer = "-----END DSA PRIVATE KEY-----\n";
1046        }
1047
1048        /*
1049         * Now count up the total size of the ASN.1 encoded integers,
1050         * so as to determine the length of the containing SEQUENCE.
1051         */
1052        len = 0;
1053        for (i = 0; i < nnumbers; i++) {
1054            len += ber_write_id_len(NULL, 2, numbers[i].bytes, 0);
1055            len += numbers[i].bytes;
1056        }
1057        seqlen = len;
1058        /* Now add on the SEQUENCE header. */
1059        len += ber_write_id_len(NULL, 16, seqlen, ASN1_CONSTRUCTED);
1060
1061        /*
1062         * Now we know how big outblob needs to be. Allocate it.
1063         */
1064        outblob = snewn(len, unsigned char);
1065
1066        /*
1067         * And write the data into it.
1068         */
1069        pos = 0;
1070        pos += ber_write_id_len(outblob+pos, 16, seqlen, ASN1_CONSTRUCTED);
1071        for (i = 0; i < nnumbers; i++) {
1072            pos += ber_write_id_len(outblob+pos, 2, numbers[i].bytes, 0);
1073            memcpy(outblob+pos, numbers[i].start, numbers[i].bytes);
1074            pos += numbers[i].bytes;
1075        }
1076    } else if (key->alg == &ssh_ecdsa_nistp256 ||
1077               key->alg == &ssh_ecdsa_nistp384 ||
1078               key->alg == &ssh_ecdsa_nistp521) {
1079        const unsigned char *oid;
1080        int oidlen;
1081        int pointlen;
1082
1083        /*
1084         * Structure of asn1:
1085         * SEQUENCE
1086         *   INTEGER 1
1087         *   OCTET STRING (private key)
1088         *   [0]
1089         *     OID (curve)
1090         *   [1]
1091         *     BIT STRING (0x00 public key point)
1092         */
1093        oid = ec_alg_oid(key->alg, &oidlen);
1094        pointlen = (((struct ec_key *)key->data)->publicKey.curve->fieldBits
1095                    + 7) / 8 * 2;
1096
1097        len = ber_write_id_len(NULL, 2, 1, 0);
1098        len += 1;
1099        len += ber_write_id_len(NULL, 4, privlen - 4, 0);
1100        len+= privlen - 4;
1101        len += ber_write_id_len(NULL, 0, oidlen +
1102                                ber_write_id_len(NULL, 6, oidlen, 0),
1103                                ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED);
1104        len += ber_write_id_len(NULL, 6, oidlen, 0);
1105        len += oidlen;
1106        len += ber_write_id_len(NULL, 1, 2 + pointlen +
1107                                ber_write_id_len(NULL, 3, 2 + pointlen, 0),
1108                                ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED);
1109        len += ber_write_id_len(NULL, 3, 2 + pointlen, 0);
1110        len += 2 + pointlen;
1111
1112        seqlen = len;
1113        len += ber_write_id_len(NULL, 16, seqlen, ASN1_CONSTRUCTED);
1114
1115        outblob = snewn(len, unsigned char);
1116        assert(outblob);
1117
1118        pos = 0;
1119        pos += ber_write_id_len(outblob+pos, 16, seqlen, ASN1_CONSTRUCTED);
1120        pos += ber_write_id_len(outblob+pos, 2, 1, 0);
1121        outblob[pos++] = 1;
1122        pos += ber_write_id_len(outblob+pos, 4, privlen - 4, 0);
1123        memcpy(outblob+pos, privblob + 4, privlen - 4);
1124        pos += privlen - 4;
1125        pos += ber_write_id_len(outblob+pos, 0, oidlen +
1126                                ber_write_id_len(NULL, 6, oidlen, 0),
1127                                ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED);
1128        pos += ber_write_id_len(outblob+pos, 6, oidlen, 0);
1129        memcpy(outblob+pos, oid, oidlen);
1130        pos += oidlen;
1131        pos += ber_write_id_len(outblob+pos, 1, 2 + pointlen +
1132                                ber_write_id_len(NULL, 3, 2 + pointlen, 0),
1133                                ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED);
1134        pos += ber_write_id_len(outblob+pos, 3, 2 + pointlen, 0);
1135        outblob[pos++] = 0;
1136        memcpy(outblob+pos, pubblob+39, 1 + pointlen);
1137        pos += 1 + pointlen;
1138
1139        header = "-----BEGIN EC PRIVATE KEY-----\n";
1140        footer = "-----END EC PRIVATE KEY-----\n";
1141    } else {
1142        assert(0);                     /* zoinks! */
1143        exit(1); /* XXX: GCC doesn't understand assert() on some systems. */
1144    }
1145
1146    /*
1147     * Encrypt the key.
1148     *
1149     * For the moment, we still encrypt our OpenSSH keys using
1150     * old-style 3DES.
1151     */
1152    if (passphrase) {
1153        struct MD5Context md5c;
1154        unsigned char keybuf[32];
1155
1156        /*
1157         * Round up to the cipher block size, ensuring we have at
1158         * least one byte of padding (see below).
1159         */
1160        outlen = (len+8) &~ 7;
1161        {
1162            unsigned char *tmp = snewn(outlen, unsigned char);
1163            memcpy(tmp, outblob, len);
1164            smemclr(outblob, len);
1165            sfree(outblob);
1166            outblob = tmp;
1167        }
1168
1169        /*
1170         * Padding on OpenSSH keys is deterministic. The number of
1171         * padding bytes is always more than zero, and always at most
1172         * the cipher block length. The value of each padding byte is
1173         * equal to the number of padding bytes. So a plaintext that's
1174         * an exact multiple of the block size will be padded with 08
1175         * 08 08 08 08 08 08 08 (assuming a 64-bit block cipher); a
1176         * plaintext one byte less than a multiple of the block size
1177         * will be padded with just 01.
1178         *
1179         * This enables the OpenSSL key decryption function to strip
1180         * off the padding algorithmically and return the unpadded
1181         * plaintext to the next layer: it looks at the final byte, and
1182         * then expects to find that many bytes at the end of the data
1183         * with the same value. Those are all removed and the rest is
1184         * returned.
1185         */
1186        assert(pos == len);
1187        while (pos < outlen) {
1188            outblob[pos++] = outlen - len;
1189        }
1190
1191        /*
1192         * Invent an iv. Then derive encryption key from passphrase
1193         * and iv/salt:
1194         *
1195         *  - let block A equal MD5(passphrase || iv)
1196         *  - let block B equal MD5(A || passphrase || iv)
1197         *  - block C would be MD5(B || passphrase || iv) and so on
1198         *  - encryption key is the first N bytes of A || B
1199         */
1200        for (i = 0; i < 8; i++) iv[i] = random_byte();
1201
1202        MD5Init(&md5c);
1203        MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase));
1204        MD5Update(&md5c, iv, 8);
1205        MD5Final(keybuf, &md5c);
1206
1207        MD5Init(&md5c);
1208        MD5Update(&md5c, keybuf, 16);
1209        MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase));
1210        MD5Update(&md5c, iv, 8);
1211        MD5Final(keybuf+16, &md5c);
1212
1213        /*
1214         * Now encrypt the key blob.
1215         */
1216        des3_encrypt_pubkey_ossh(keybuf, iv, outblob, outlen);
1217
1218        smemclr(&md5c, sizeof(md5c));
1219        smemclr(keybuf, sizeof(keybuf));
1220    } else {
1221        /*
1222         * If no encryption, the blob has exactly its original
1223         * cleartext size.
1224         */
1225        outlen = len;
1226    }
1227
1228    /*
1229     * And save it. We'll use Unix line endings just in case it's
1230     * subsequently transferred in binary mode.
1231     */
1232    fp = f_open(filename, "wb", TRUE);      /* ensure Unix line endings */
1233    if (!fp)
1234        goto error;
1235    fputs(header, fp);
1236    if (passphrase) {
1237        fprintf(fp, "Proc-Type: 4,ENCRYPTED\nDEK-Info: DES-EDE3-CBC,");
1238        for (i = 0; i < 8; i++)
1239            fprintf(fp, "%02X", iv[i]);
1240        fprintf(fp, "\n\n");
1241    }
1242    base64_encode(fp, outblob, outlen, 64);
1243    fputs(footer, fp);
1244    fclose(fp);
1245    ret = 1;
1246
1247    error:
1248    if (outblob) {
1249        smemclr(outblob, outlen);
1250        sfree(outblob);
1251    }
1252    if (spareblob) {
1253        smemclr(spareblob, sparelen);
1254        sfree(spareblob);
1255    }
1256    if (privblob) {
1257        smemclr(privblob, privlen);
1258        sfree(privblob);
1259    }
1260    if (pubblob) {
1261        smemclr(pubblob, publen);
1262        sfree(pubblob);
1263    }
1264    return ret;
1265}
1266
1267/* ----------------------------------------------------------------------
1268 * Code to read and write OpenSSH private keys in the new-style format.
1269 */
1270
1271typedef enum {
1272    ON_E_NONE, ON_E_AES256CBC
1273} openssh_new_cipher;
1274typedef enum {
1275    ON_K_NONE, ON_K_BCRYPT
1276} openssh_new_kdf;
1277
1278struct openssh_new_key {
1279    openssh_new_cipher cipher;
1280    openssh_new_kdf kdf;
1281    union {
1282        struct {
1283            int rounds;
1284            /* This points to a position within keyblob, not a
1285             * separately allocated thing */
1286            const unsigned char *salt;
1287            int saltlen;
1288        } bcrypt;
1289    } kdfopts;
1290    int nkeys, key_wanted;
1291    /* This too points to a position within keyblob */
1292    unsigned char *privatestr;
1293    int privatelen;
1294
1295    unsigned char *keyblob;
1296    int keyblob_len, keyblob_size;
1297};
1298
1299static struct openssh_new_key *load_openssh_new_key(const Filename *filename,
1300                                                    const char **errmsg_p)
1301{
1302    struct openssh_new_key *ret;
1303    FILE *fp = NULL;
1304    char *line = NULL;
1305    const char *errmsg;
1306    char *p;
1307    char base64_bit[4];
1308    int base64_chars = 0;
1309    const void *filedata;
1310    int filelen;
1311    const void *string, *kdfopts, *bcryptsalt, *pubkey;
1312    int stringlen, kdfoptlen, bcryptsaltlen, pubkeylen;
1313    unsigned bcryptrounds, nkeys, key_index;
1314
1315    ret = snew(struct openssh_new_key);
1316    ret->keyblob = NULL;
1317    ret->keyblob_len = ret->keyblob_size = 0;
1318
1319    fp = f_open(filename, "r", FALSE);
1320    if (!fp) {
1321        errmsg = "unable to open key file";
1322        goto error;
1323    }
1324
1325    if (!(line = fgetline(fp))) {
1326        errmsg = "unexpected end of file";
1327        goto error;
1328    }
1329    strip_crlf(line);
1330    if (0 != strcmp(line, "-----BEGIN OPENSSH PRIVATE KEY-----")) {
1331        errmsg = "file does not begin with OpenSSH new-style key header";
1332        goto error;
1333    }
1334    smemclr(line, strlen(line));
1335    sfree(line);
1336    line = NULL;
1337
1338    while (1) {
1339        if (!(line = fgetline(fp))) {
1340            errmsg = "unexpected end of file";
1341            goto error;
1342        }
1343        strip_crlf(line);
1344        if (0 == strcmp(line, "-----END OPENSSH PRIVATE KEY-----")) {
1345            sfree(line);
1346            line = NULL;
1347            break;                     /* done */
1348        }
1349
1350        p = line;
1351        while (isbase64(*p)) {
1352            base64_bit[base64_chars++] = *p;
1353            if (base64_chars == 4) {
1354                unsigned char out[3];
1355                int len;
1356
1357                base64_chars = 0;
1358
1359                len = base64_decode_atom(base64_bit, out);
1360
1361                if (len <= 0) {
1362                    errmsg = "invalid base64 encoding";
1363                    goto error;
1364                }
1365
1366                if (ret->keyblob_len + len > ret->keyblob_size) {
1367                    ret->keyblob_size = ret->keyblob_len + len + 256;
1368                    ret->keyblob = sresize(ret->keyblob, ret->keyblob_size,
1369                                           unsigned char);
1370                }
1371
1372                memcpy(ret->keyblob + ret->keyblob_len, out, len);
1373                ret->keyblob_len += len;
1374
1375                smemclr(out, sizeof(out));
1376            }
1377
1378            p++;
1379        }
1380        smemclr(line, strlen(line));
1381        sfree(line);
1382        line = NULL;
1383    }
1384
1385    fclose(fp);
1386    fp = NULL;
1387
1388    if (ret->keyblob_len == 0 || !ret->keyblob) {
1389        errmsg = "key body not present";
1390        goto error;
1391    }
1392
1393    filedata = ret->keyblob;
1394    filelen = ret->keyblob_len;
1395
1396    if (filelen < 15 || 0 != memcmp(filedata, "openssh-key-v1\0", 15)) {
1397        errmsg = "new-style OpenSSH magic number missing\n";
1398        goto error;
1399    }
1400    filedata = (const char *)filedata + 15;
1401    filelen -= 15;
1402
1403    if (!(string = get_ssh_string(&filelen, &filedata, &stringlen))) {
1404        errmsg = "encountered EOF before cipher name\n";
1405        goto error;
1406    }
1407    if (match_ssh_id(stringlen, string, "none")) {
1408        ret->cipher = ON_E_NONE;
1409    } else if (match_ssh_id(stringlen, string, "aes256-cbc")) {
1410        ret->cipher = ON_E_AES256CBC;
1411    } else {
1412        errmsg = "unrecognised cipher name\n";
1413        goto error;
1414    }
1415
1416    if (!(string = get_ssh_string(&filelen, &filedata, &stringlen))) {
1417        errmsg = "encountered EOF before kdf name\n";
1418        goto error;
1419    }
1420    if (match_ssh_id(stringlen, string, "none")) {
1421        ret->kdf = ON_K_NONE;
1422    } else if (match_ssh_id(stringlen, string, "bcrypt")) {
1423        ret->kdf = ON_K_BCRYPT;
1424    } else {
1425        errmsg = "unrecognised kdf name\n";
1426        goto error;
1427    }
1428
1429    if (!(kdfopts = get_ssh_string(&filelen, &filedata, &kdfoptlen))) {
1430        errmsg = "encountered EOF before kdf options\n";
1431        goto error;
1432    }
1433    switch (ret->kdf) {
1434      case ON_K_NONE:
1435        if (kdfoptlen != 0) {
1436            errmsg = "expected empty options string for 'none' kdf";
1437            goto error;
1438        }
1439        break;
1440      case ON_K_BCRYPT:
1441        if (!(bcryptsalt = get_ssh_string(&kdfoptlen, &kdfopts,
1442                                          &bcryptsaltlen))) {
1443            errmsg = "bcrypt options string did not contain salt\n";
1444            goto error;
1445        }
1446        if (!get_ssh_uint32(&kdfoptlen, &kdfopts, &bcryptrounds)) {
1447            errmsg = "bcrypt options string did not contain round count\n";
1448            goto error;
1449        }
1450        ret->kdfopts.bcrypt.salt = bcryptsalt;
1451        ret->kdfopts.bcrypt.saltlen = bcryptsaltlen;
1452        ret->kdfopts.bcrypt.rounds = bcryptrounds;
1453        break;
1454    }
1455
1456    /*
1457     * At this point we expect a uint32 saying how many keys are
1458     * stored in this file. OpenSSH new-style key files can
1459     * contain more than one. Currently we don't have any user
1460     * interface to specify which one we're trying to extract, so
1461     * we just bomb out with an error if more than one is found in
1462     * the file. However, I've put in all the mechanism here to
1463     * extract the nth one for a given n, in case we later connect
1464     * up some UI to that mechanism. Just arrange that the
1465     * 'key_wanted' field is set to a value in the range [0,
1466     * nkeys) by some mechanism.
1467     */
1468    if (!get_ssh_uint32(&filelen, &filedata, &nkeys)) {
1469        errmsg = "encountered EOF before key count\n";
1470        goto error;
1471    }
1472    if (nkeys != 1) {
1473        errmsg = "multiple keys in new-style OpenSSH key file "
1474            "not supported\n";
1475        goto error;
1476    }
1477    ret->nkeys = nkeys;
1478    ret->key_wanted = 0;
1479
1480    for (key_index = 0; key_index < nkeys; key_index++) {
1481        if (!(pubkey = get_ssh_string(&filelen, &filedata, &pubkeylen))) {
1482            errmsg = "encountered EOF before kdf options\n";
1483            goto error;
1484        }
1485    }
1486
1487    /*
1488     * Now we expect a string containing the encrypted part of the
1489     * key file.
1490     */
1491    if (!(string = get_ssh_string(&filelen, &filedata, &stringlen))) {
1492        errmsg = "encountered EOF before private key container\n";
1493        goto error;
1494    }
1495    ret->privatestr = (unsigned char *)string;
1496    ret->privatelen = stringlen;
1497
1498    /*
1499     * And now we're done, until asked to actually decrypt.
1500     */
1501
1502    smemclr(base64_bit, sizeof(base64_bit));
1503    if (errmsg_p) *errmsg_p = NULL;
1504    return ret;
1505
1506    error:
1507    if (line) {
1508        smemclr(line, strlen(line));
1509        sfree(line);
1510        line = NULL;
1511    }
1512    smemclr(base64_bit, sizeof(base64_bit));
1513    if (ret) {
1514        if (ret->keyblob) {
1515            smemclr(ret->keyblob, ret->keyblob_size);
1516            sfree(ret->keyblob);
1517        }
1518        smemclr(ret, sizeof(*ret));
1519        sfree(ret);
1520    }
1521    if (errmsg_p) *errmsg_p = errmsg;
1522    if (fp) fclose(fp);
1523    return NULL;
1524}
1525
1526int openssh_new_encrypted(const Filename *filename)
1527{
1528    struct openssh_new_key *key = load_openssh_new_key(filename, NULL);
1529    int ret;
1530
1531    if (!key)
1532        return 0;
1533    ret = (key->cipher != ON_E_NONE);
1534    smemclr(key->keyblob, key->keyblob_size);
1535    sfree(key->keyblob);
1536    smemclr(key, sizeof(*key));
1537    sfree(key);
1538    return ret;
1539}
1540
1541struct ssh2_userkey *openssh_new_read(const Filename *filename,
1542                                      char *passphrase,
1543                                      const char **errmsg_p)
1544{
1545    struct openssh_new_key *key = load_openssh_new_key(filename, errmsg_p);
1546    struct ssh2_userkey *retkey;
1547    int i;
1548    struct ssh2_userkey *retval = NULL;
1549    const char *errmsg;
1550    unsigned char *blob;
1551    int blobsize = 0;
1552    unsigned checkint0, checkint1;
1553    const void *priv, *string;
1554    int privlen, stringlen, key_index;
1555    const struct ssh_signkey *alg;
1556
1557    blob = NULL;
1558
1559    if (!key)
1560        return NULL;
1561
1562    if (key->cipher != ON_E_NONE) {
1563        unsigned char keybuf[48];
1564        int keysize;
1565
1566        /*
1567         * Construct the decryption key, and decrypt the string.
1568         */
1569        switch (key->cipher) {
1570          case ON_E_NONE:
1571            keysize = 0;
1572            break;
1573          case ON_E_AES256CBC:
1574            keysize = 48;              /* 32 byte key + 16 byte IV */
1575            break;
1576          default:
1577            assert(0 && "Bad cipher enumeration value");
1578        }
1579        assert(keysize <= sizeof(keybuf));
1580        switch (key->kdf) {
1581          case ON_K_NONE:
1582            memset(keybuf, 0, keysize);
1583            break;
1584          case ON_K_BCRYPT:
1585            openssh_bcrypt(passphrase,
1586                           key->kdfopts.bcrypt.salt,
1587                           key->kdfopts.bcrypt.saltlen,
1588                           key->kdfopts.bcrypt.rounds,
1589                           keybuf, keysize);
1590            break;
1591          default:
1592            assert(0 && "Bad kdf enumeration value");
1593        }
1594        switch (key->cipher) {
1595          case ON_E_NONE:
1596            break;
1597          case ON_E_AES256CBC:
1598            if (key->privatelen % 16 != 0) {
1599                errmsg = "private key container length is not a"
1600                    " multiple of AES block size\n";
1601                goto error;
1602            }
1603            {
1604                void *ctx = aes_make_context();
1605                aes256_key(ctx, keybuf);
1606                aes_iv(ctx, keybuf + 32);
1607                aes_ssh2_decrypt_blk(ctx, key->privatestr,
1608                                     key->privatelen);
1609                aes_free_context(ctx);
1610            }
1611            break;
1612          default:
1613            assert(0 && "Bad cipher enumeration value");
1614        }
1615    }
1616
1617    /*
1618     * Now parse the entire encrypted section, and extract the key
1619     * identified by key_wanted.
1620     */
1621    priv = key->privatestr;
1622    privlen = key->privatelen;
1623
1624    if (!get_ssh_uint32(&privlen, &priv, &checkint0) ||
1625        !get_ssh_uint32(&privlen, &priv, &checkint1) ||
1626        checkint0 != checkint1) {
1627        errmsg = "decryption check failed";
1628        goto error;
1629    }
1630
1631    retkey = NULL;
1632    for (key_index = 0; key_index < key->nkeys; key_index++) {
1633        const unsigned char *thiskey;
1634        int thiskeylen;
1635
1636        /*
1637         * Read the key type, which will tell us how to scan over
1638         * the key to get to the next one.
1639         */
1640        if (!(string = get_ssh_string(&privlen, &priv, &stringlen))) {
1641            errmsg = "expected key type in private string";
1642            goto error;
1643        }
1644
1645        /*
1646         * Preliminary key type identification, and decide how
1647         * many pieces of key we expect to see. Currently
1648         * (conveniently) all key types can be seen as some number
1649         * of strings, so we just need to know how many of them to
1650         * skip over. (The numbers below exclude the key comment.)
1651         */
1652        {
1653            /* find_pubkey_alg needs a zero-terminated copy of the
1654             * algorithm name */
1655            char *name_zt = dupprintf("%.*s", stringlen, (char *)string);
1656            alg = find_pubkey_alg(name_zt);
1657            sfree(name_zt);
1658        }
1659
1660        if (!alg) {
1661            errmsg = "private key type not recognised\n";
1662            goto error;
1663        }
1664
1665        thiskey = priv;
1666
1667        /*
1668         * Skip over the pieces of key.
1669         */
1670        for (i = 0; i < alg->openssh_private_npieces; i++) {
1671            if (!(string = get_ssh_string(&privlen, &priv, &stringlen))) {
1672                errmsg = "ran out of data in mid-private-key";
1673                goto error;
1674            }
1675        }
1676
1677        thiskeylen = (int)((const unsigned char *)priv -
1678                           (const unsigned char *)thiskey);
1679        if (key_index == key->key_wanted) {
1680            retkey = snew(struct ssh2_userkey);
1681            retkey->alg = alg;
1682            retkey->data = alg->openssh_createkey(alg, &thiskey, &thiskeylen);
1683            if (!retkey->data) {
1684                sfree(retkey);
1685                errmsg = "unable to create key data structure";
1686                goto error;
1687            }
1688        }
1689
1690        /*
1691         * Read the key comment.
1692         */
1693        if (!(string = get_ssh_string(&privlen, &priv, &stringlen))) {
1694            errmsg = "ran out of data at key comment";
1695            goto error;
1696        }
1697        if (key_index == key->key_wanted) {
1698            assert(retkey);
1699            retkey->comment = dupprintf("%.*s", stringlen,
1700                                        (const char *)string);
1701        }
1702    }
1703
1704    if (!retkey) {
1705        errmsg = "key index out of range";
1706        goto error;
1707    }
1708
1709    /*
1710     * Now we expect nothing left but padding.
1711     */
1712    for (i = 0; i < privlen; i++) {
1713        if (((const unsigned char *)priv)[i] != (unsigned char)(i+1)) {
1714            errmsg = "padding at end of private string did not match";
1715            goto error;
1716        }
1717    }
1718
1719    errmsg = NULL;                     /* no error */
1720    retval = retkey;
1721
1722    error:
1723    if (blob) {
1724        smemclr(blob, blobsize);
1725        sfree(blob);
1726    }
1727    smemclr(key->keyblob, key->keyblob_size);
1728    sfree(key->keyblob);
1729    smemclr(key, sizeof(*key));
1730    sfree(key);
1731    if (errmsg_p) *errmsg_p = errmsg;
1732    return retval;
1733}
1734
1735int openssh_new_write(const Filename *filename, struct ssh2_userkey *key,
1736                      char *passphrase)
1737{
1738    unsigned char *pubblob, *privblob, *outblob, *p;
1739    unsigned char *private_section_start, *private_section_length_field;
1740    int publen, privlen, commentlen, maxsize, padvalue, i;
1741    unsigned checkint;
1742    int ret = 0;
1743    unsigned char bcrypt_salt[16];
1744    const int bcrypt_rounds = 16;
1745    FILE *fp;
1746
1747    /*
1748     * Fetch the key blobs and find out the lengths of things.
1749     */
1750    pubblob = key->alg->public_blob(key->data, &publen);
1751    i = key->alg->openssh_fmtkey(key->data, NULL, 0);
1752    privblob = snewn(i, unsigned char);
1753    privlen = key->alg->openssh_fmtkey(key->data, privblob, i);
1754    assert(privlen == i);
1755    commentlen = strlen(key->comment);
1756
1757    /*
1758     * Allocate enough space for the full binary key format. No need
1759     * to be absolutely precise here.
1760     */
1761    maxsize = (16 +                    /* magic number */
1762               32 +                    /* cipher name string */
1763               32 +                    /* kdf name string */
1764               64 +                    /* kdf options string */
1765               4 +                     /* key count */
1766               4+publen +              /* public key string */
1767               4 +                     /* string header for private section */
1768               8 +                     /* checkint x 2 */
1769               4+strlen(key->alg->name) + /* key type string */
1770               privlen +               /* private blob */
1771               4+commentlen +          /* comment string */
1772               16);                    /* padding at end of private section */
1773    outblob = snewn(maxsize, unsigned char);
1774
1775    /*
1776     * Construct the cleartext version of the blob.
1777     */
1778    p = outblob;
1779
1780    /* Magic number. */
1781    memcpy(p, "openssh-key-v1\0", 15);
1782    p += 15;
1783
1784    /* Cipher and kdf names, and kdf options. */
1785    if (!passphrase) {
1786        memset(bcrypt_salt, 0, sizeof(bcrypt_salt)); /* prevent warnings */
1787        p += put_string_z(p, "none");
1788        p += put_string_z(p, "none");
1789        p += put_string_z(p, "");
1790    } else {
1791        unsigned char *q;
1792        for (i = 0; i < (int)sizeof(bcrypt_salt); i++)
1793            bcrypt_salt[i] = random_byte();
1794        p += put_string_z(p, "aes256-cbc");
1795        p += put_string_z(p, "bcrypt");
1796        q = p;
1797        p += 4;
1798        p += put_string(p, bcrypt_salt, sizeof(bcrypt_salt));
1799        p += put_uint32(p, bcrypt_rounds);
1800        PUT_32BIT_MSB_FIRST(q, (unsigned)(p - (q+4)));
1801    }
1802
1803    /* Number of keys. */
1804    p += put_uint32(p, 1);
1805
1806    /* Public blob. */
1807    p += put_string(p, pubblob, publen);
1808
1809    /* Begin private section. */
1810    private_section_length_field = p;
1811    p += 4;
1812    private_section_start = p;
1813
1814    /* checkint. */
1815    checkint = 0;
1816    for (i = 0; i < 4; i++)
1817        checkint = (checkint << 8) + random_byte();
1818    p += put_uint32(p, checkint);
1819    p += put_uint32(p, checkint);
1820
1821    /* Private key. The main private blob goes inline, with no string
1822     * wrapper. */
1823    p += put_string_z(p, key->alg->name);
1824    memcpy(p, privblob, privlen);
1825    p += privlen;
1826
1827    /* Comment. */
1828    p += put_string_z(p, key->comment);
1829
1830    /* Pad out the encrypted section. */
1831    padvalue = 1;
1832    do {
1833        *p++ = padvalue++;
1834    } while ((p - private_section_start) & 15);
1835
1836    assert(p - outblob < maxsize);
1837
1838    /* Go back and fill in the length field for the private section. */
1839    PUT_32BIT_MSB_FIRST(private_section_length_field,
1840                        p - private_section_start);
1841
1842    if (passphrase) {
1843        /*
1844         * Encrypt the private section. We need 48 bytes of key
1845         * material: 32 bytes AES key + 16 bytes iv.
1846         */
1847        unsigned char keybuf[48];
1848        void *ctx;
1849
1850        openssh_bcrypt(passphrase,
1851                       bcrypt_salt, sizeof(bcrypt_salt), bcrypt_rounds,
1852                       keybuf, sizeof(keybuf));
1853
1854        ctx = aes_make_context();
1855        aes256_key(ctx, keybuf);
1856        aes_iv(ctx, keybuf + 32);
1857        aes_ssh2_encrypt_blk(ctx, private_section_start,
1858                             p - private_section_start);
1859        aes_free_context(ctx);
1860
1861        smemclr(keybuf, sizeof(keybuf));
1862    }
1863
1864    /*
1865     * And save it. We'll use Unix line endings just in case it's
1866     * subsequently transferred in binary mode.
1867     */
1868    fp = f_open(filename, "wb", TRUE);      /* ensure Unix line endings */
1869    if (!fp)
1870        goto error;
1871    fputs("-----BEGIN OPENSSH PRIVATE KEY-----\n", fp);
1872    base64_encode(fp, outblob, p - outblob, 64);
1873    fputs("-----END OPENSSH PRIVATE KEY-----\n", fp);
1874    fclose(fp);
1875    ret = 1;
1876
1877    error:
1878    if (outblob) {
1879        smemclr(outblob, maxsize);
1880        sfree(outblob);
1881    }
1882    if (privblob) {
1883        smemclr(privblob, privlen);
1884        sfree(privblob);
1885    }
1886    if (pubblob) {
1887        smemclr(pubblob, publen);
1888        sfree(pubblob);
1889    }
1890    return ret;
1891}
1892
1893/* ----------------------------------------------------------------------
1894 * The switch function openssh_auto_write(), which chooses one of the
1895 * concrete OpenSSH output formats based on the key type.
1896 */
1897int openssh_auto_write(const Filename *filename, struct ssh2_userkey *key,
1898                       char *passphrase)
1899{
1900    /*
1901     * The old OpenSSH format supports a fixed list of key types. We
1902     * assume that anything not in that fixed list is newer, and hence
1903     * will use the new format.
1904     */
1905    if (key->alg == &ssh_dss ||
1906        key->alg == &ssh_rsa ||
1907        key->alg == &ssh_ecdsa_nistp256 ||
1908        key->alg == &ssh_ecdsa_nistp384 ||
1909        key->alg == &ssh_ecdsa_nistp521)
1910        return openssh_pem_write(filename, key, passphrase);
1911    else
1912        return openssh_new_write(filename, key, passphrase);
1913}
1914
1915/* ----------------------------------------------------------------------
1916 * Code to read ssh.com private keys.
1917 */
1918
1919/*
1920 * The format of the base64 blob is largely SSH-2-packet-formatted,
1921 * except that mpints are a bit different: they're more like the
1922 * old SSH-1 mpint. You have a 32-bit bit count N, followed by
1923 * (N+7)/8 bytes of data.
1924 *
1925 * So. The blob contains:
1926 *
1927 *  - uint32 0x3f6ff9eb       (magic number)
1928 *  - uint32 size             (total blob size)
1929 *  - string key-type         (see below)
1930 *  - string cipher-type      (tells you if key is encrypted)
1931 *  - string encrypted-blob
1932 *
1933 * (The first size field includes the size field itself and the
1934 * magic number before it. All other size fields are ordinary SSH-2
1935 * strings, so the size field indicates how much data is to
1936 * _follow_.)
1937 *
1938 * The encrypted blob, once decrypted, contains a single string
1939 * which in turn contains the payload. (This allows padding to be
1940 * added after that string while still making it clear where the
1941 * real payload ends. Also it probably makes for a reasonable
1942 * decryption check.)
1943 *
1944 * The payload blob, for an RSA key, contains:
1945 *  - mpint e
1946 *  - mpint d
1947 *  - mpint n  (yes, the public and private stuff is intermixed)
1948 *  - mpint u  (presumably inverse of p mod q)
1949 *  - mpint p  (p is the smaller prime)
1950 *  - mpint q  (q is the larger)
1951 *
1952 * For a DSA key, the payload blob contains:
1953 *  - uint32 0
1954 *  - mpint p
1955 *  - mpint g
1956 *  - mpint q
1957 *  - mpint y
1958 *  - mpint x
1959 *
1960 * Alternatively, if the parameters are `predefined', that
1961 * (0,p,g,q) sequence can be replaced by a uint32 1 and a string
1962 * containing some predefined parameter specification. *shudder*,
1963 * but I doubt we'll encounter this in real life.
1964 *
1965 * The key type strings are ghastly. The RSA key I looked at had a
1966 * type string of
1967 *
1968 *   `if-modn{sign{rsa-pkcs1-sha1},encrypt{rsa-pkcs1v2-oaep}}'
1969 *
1970 * and the DSA key wasn't much better:
1971 *
1972 *   `dl-modp{sign{dsa-nist-sha1},dh{plain}}'
1973 *
1974 * It isn't clear that these will always be the same. I think it
1975 * might be wise just to look at the `if-modn{sign{rsa' and
1976 * `dl-modp{sign{dsa' prefixes.
1977 *
1978 * Finally, the encryption. The cipher-type string appears to be
1979 * either `none' or `3des-cbc'. Looks as if this is SSH-2-style
1980 * 3des-cbc (i.e. outer cbc rather than inner). The key is created
1981 * from the passphrase by means of yet another hashing faff:
1982 *
1983 *  - first 16 bytes are MD5(passphrase)
1984 *  - next 16 bytes are MD5(passphrase || first 16 bytes)
1985 *  - if there were more, they'd be MD5(passphrase || first 32),
1986 *    and so on.
1987 */
1988
1989#define SSHCOM_MAGIC_NUMBER 0x3f6ff9eb
1990
1991struct sshcom_key {
1992    char comment[256];                 /* allowing any length is overkill */
1993    unsigned char *keyblob;
1994    int keyblob_len, keyblob_size;
1995};
1996
1997static struct sshcom_key *load_sshcom_key(const Filename *filename,
1998                                          const char **errmsg_p)
1999{
2000    struct sshcom_key *ret;
2001    FILE *fp;
2002    char *line = NULL;
2003    int hdrstart, len;
2004    const char *errmsg;
2005    char *p;
2006    int headers_done;
2007    char base64_bit[4];
2008    int base64_chars = 0;
2009
2010    ret = snew(struct sshcom_key);
2011    ret->comment[0] = '\0';
2012    ret->keyblob = NULL;
2013    ret->keyblob_len = ret->keyblob_size = 0;
2014
2015    fp = f_open(filename, "r", FALSE);
2016    if (!fp) {
2017        errmsg = "unable to open key file";
2018        goto error;
2019    }
2020    if (!(line = fgetline(fp))) {
2021        errmsg = "unexpected end of file";
2022        goto error;
2023    }
2024    strip_crlf(line);
2025    if (0 != strcmp(line, "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----")) {
2026        errmsg = "file does not begin with ssh.com key header";
2027        goto error;
2028    }
2029    smemclr(line, strlen(line));
2030    sfree(line);
2031    line = NULL;
2032
2033    headers_done = 0;
2034    while (1) {
2035        if (!(line = fgetline(fp))) {
2036            errmsg = "unexpected end of file";
2037            goto error;
2038        }
2039        strip_crlf(line);
2040        if (!strcmp(line, "---- END SSH2 ENCRYPTED PRIVATE KEY ----")) {
2041            sfree(line);
2042            line = NULL;
2043            break;                     /* done */
2044        }
2045        if ((p = strchr(line, ':')) != NULL) {
2046            if (headers_done) {
2047                errmsg = "header found in body of key data";
2048                goto error;
2049            }
2050            *p++ = '\0';
2051            while (*p && isspace((unsigned char)*p)) p++;
2052            hdrstart = p - line;
2053
2054            /*
2055             * Header lines can end in a trailing backslash for
2056             * continuation.
2057             */
2058            len = hdrstart + strlen(line+hdrstart);
2059            assert(!line[len]);
2060            while (line[len-1] == '\\') {
2061                char *line2;
2062                int line2len;
2063
2064                line2 = fgetline(fp);
2065                if (!line2) {
2066                    errmsg = "unexpected end of file";
2067                    goto error;
2068                }
2069                strip_crlf(line2);
2070
2071                line2len = strlen(line2);
2072                line = sresize(line, len + line2len + 1, char);
2073                strcpy(line + len - 1, line2);
2074                len += line2len - 1;
2075                assert(!line[len]);
2076
2077                smemclr(line2, strlen(line2));
2078                sfree(line2);
2079                line2 = NULL;
2080            }
2081            p = line + hdrstart;
2082            strip_crlf(p);
2083            if (!strcmp(line, "Comment")) {
2084                /* Strip quotes in comment if present. */
2085                if (p[0] == '"' && p[strlen(p)-1] == '"') {
2086                    p++;
2087                    p[strlen(p)-1] = '\0';
2088                }
2089                strncpy(ret->comment, p, sizeof(ret->comment));
2090                ret->comment[sizeof(ret->comment)-1] = '\0';
2091            }
2092        } else {
2093            headers_done = 1;
2094
2095            p = line;
2096            while (isbase64(*p)) {
2097                base64_bit[base64_chars++] = *p;
2098                if (base64_chars == 4) {
2099                    unsigned char out[3];
2100
2101                    base64_chars = 0;
2102
2103                    len = base64_decode_atom(base64_bit, out);
2104
2105                    if (len <= 0) {
2106                        errmsg = "invalid base64 encoding";
2107                        goto error;
2108                    }
2109
2110                    if (ret->keyblob_len + len > ret->keyblob_size) {
2111                        ret->keyblob_size = ret->keyblob_len + len + 256;
2112                        ret->keyblob = sresize(ret->keyblob, ret->keyblob_size,
2113                                               unsigned char);
2114                    }
2115
2116                    memcpy(ret->keyblob + ret->keyblob_len, out, len);
2117                    ret->keyblob_len += len;
2118                }
2119
2120                p++;
2121            }
2122        }
2123        smemclr(line, strlen(line));
2124        sfree(line);
2125        line = NULL;
2126    }
2127
2128    if (ret->keyblob_len == 0 || !ret->keyblob) {
2129        errmsg = "key body not present";
2130        goto error;
2131    }
2132
2133    fclose(fp);
2134    if (errmsg_p) *errmsg_p = NULL;
2135    return ret;
2136
2137    error:
2138    if (fp)
2139        fclose(fp);
2140
2141    if (line) {
2142        smemclr(line, strlen(line));
2143        sfree(line);
2144        line = NULL;
2145    }
2146    if (ret) {
2147        if (ret->keyblob) {
2148            smemclr(ret->keyblob, ret->keyblob_size);
2149            sfree(ret->keyblob);
2150        }
2151        smemclr(ret, sizeof(*ret));
2152        sfree(ret);
2153    }
2154    if (errmsg_p) *errmsg_p = errmsg;
2155    return NULL;
2156}
2157
2158int sshcom_encrypted(const Filename *filename, char **comment)
2159{
2160    struct sshcom_key *key = load_sshcom_key(filename, NULL);
2161    int pos, len, answer;
2162
2163    answer = 0;
2164
2165    *comment = NULL;
2166    if (!key)
2167        goto done;
2168
2169    /*
2170     * Check magic number.
2171     */
2172    if (GET_32BIT(key->keyblob) != 0x3f6ff9eb) {
2173        goto done;                     /* key is invalid */
2174    }
2175
2176    /*
2177     * Find the cipher-type string.
2178     */
2179    pos = 8;
2180    if (key->keyblob_len < pos+4)
2181        goto done;                     /* key is far too short */
2182    len = toint(GET_32BIT(key->keyblob + pos));
2183    if (len < 0 || len > key->keyblob_len - pos - 4)
2184        goto done;                     /* key is far too short */
2185    pos += 4 + len;                    /* skip key type */
2186    len = toint(GET_32BIT(key->keyblob + pos)); /* find cipher-type length */
2187    if (len < 0 || len > key->keyblob_len - pos - 4)
2188        goto done;                     /* cipher type string is incomplete */
2189    if (len != 4 || 0 != memcmp(key->keyblob + pos + 4, "none", 4))
2190        answer = 1;
2191
2192    done:
2193    if (key) {
2194        *comment = dupstr(key->comment);
2195        smemclr(key->keyblob, key->keyblob_size);
2196        sfree(key->keyblob);
2197        smemclr(key, sizeof(*key));
2198        sfree(key);
2199    } else {
2200        *comment = dupstr("");
2201    }
2202    return answer;
2203}
2204
2205static int sshcom_read_mpint(void *data, int len, struct mpint_pos *ret)
2206{
2207    unsigned bits, bytes;
2208    unsigned char *d = (unsigned char *) data;
2209
2210    if (len < 4)
2211        goto error;
2212    bits = GET_32BIT(d);
2213
2214    bytes = (bits + 7) / 8;
2215    if (len < 4+bytes)
2216        goto error;
2217
2218    ret->start = d + 4;
2219    ret->bytes = bytes;
2220    return bytes+4;
2221
2222    error:
2223    ret->start = NULL;
2224    ret->bytes = -1;
2225    return len;                        /* ensure further calls fail as well */
2226}
2227
2228static int sshcom_put_mpint(void *target, void *data, int len)
2229{
2230    unsigned char *d = (unsigned char *)target;
2231    unsigned char *i = (unsigned char *)data;
2232    int bits = len * 8 - 1;
2233
2234    while (bits > 0) {
2235        if (*i & (1 << (bits & 7)))
2236            break;
2237        if (!(bits-- & 7))
2238            i++, len--;
2239    }
2240
2241    PUT_32BIT(d, bits+1);
2242    memcpy(d+4, i, len);
2243    return len+4;
2244}
2245
2246struct ssh2_userkey *sshcom_read(const Filename *filename, char *passphrase,
2247                                 const char **errmsg_p)
2248{
2249    struct sshcom_key *key = load_sshcom_key(filename, errmsg_p);
2250    const char *errmsg;
2251    int pos, len;
2252    const char prefix_rsa[] = "if-modn{sign{rsa";
2253    const char prefix_dsa[] = "dl-modp{sign{dsa";
2254    enum { RSA, DSA } type;
2255    int encrypted;
2256    char *ciphertext;
2257    int cipherlen;
2258    struct ssh2_userkey *ret = NULL, *retkey;
2259    const struct ssh_signkey *alg;
2260    unsigned char *blob = NULL;
2261    int blobsize = 0, publen, privlen;
2262
2263    if (!key)
2264        return NULL;
2265
2266    /*
2267     * Check magic number.
2268     */
2269    if (GET_32BIT(key->keyblob) != SSHCOM_MAGIC_NUMBER) {
2270        errmsg = "key does not begin with magic number";
2271        goto error;
2272    }
2273
2274    /*
2275     * Determine the key type.
2276     */
2277    pos = 8;
2278    if (key->keyblob_len < pos+4 ||
2279        (len = toint(GET_32BIT(key->keyblob + pos))) < 0 ||
2280        len > key->keyblob_len - pos - 4) {
2281        errmsg = "key blob does not contain a key type string";
2282        goto error;
2283    }
2284    if (len > sizeof(prefix_rsa) - 1 &&
2285        !memcmp(key->keyblob+pos+4, prefix_rsa, sizeof(prefix_rsa) - 1)) {
2286        type = RSA;
2287    } else if (len > sizeof(prefix_dsa) - 1 &&
2288        !memcmp(key->keyblob+pos+4, prefix_dsa, sizeof(prefix_dsa) - 1)) {
2289        type = DSA;
2290    } else {
2291        errmsg = "key is of unknown type";
2292        goto error;
2293    }
2294    pos += 4+len;
2295
2296    /*
2297     * Determine the cipher type.
2298     */
2299    if (key->keyblob_len < pos+4 ||
2300        (len = toint(GET_32BIT(key->keyblob + pos))) < 0 ||
2301        len > key->keyblob_len - pos - 4) {
2302        errmsg = "key blob does not contain a cipher type string";
2303        goto error;
2304    }
2305    if (len == 4 && !memcmp(key->keyblob+pos+4, "none", 4))
2306        encrypted = 0;
2307    else if (len == 8 && !memcmp(key->keyblob+pos+4, "3des-cbc", 8))
2308        encrypted = 1;
2309    else {
2310        errmsg = "key encryption is of unknown type";
2311        goto error;
2312    }
2313    pos += 4+len;
2314
2315    /*
2316     * Get hold of the encrypted part of the key.
2317     */
2318    if (key->keyblob_len < pos+4 ||
2319        (len = toint(GET_32BIT(key->keyblob + pos))) < 0 ||
2320        len > key->keyblob_len - pos - 4) {
2321        errmsg = "key blob does not contain actual key data";
2322        goto error;
2323    }
2324    ciphertext = (char *)key->keyblob + pos + 4;
2325    cipherlen = len;
2326    if (cipherlen == 0) {
2327        errmsg = "length of key data is zero";
2328        goto error;
2329    }
2330
2331    /*
2332     * Decrypt it if necessary.
2333     */
2334    if (encrypted) {
2335        /*
2336         * Derive encryption key from passphrase and iv/salt:
2337         *
2338         *  - let block A equal MD5(passphrase)
2339         *  - let block B equal MD5(passphrase || A)
2340         *  - block C would be MD5(passphrase || A || B) and so on
2341         *  - encryption key is the first N bytes of A || B
2342         */
2343        struct MD5Context md5c;
2344        unsigned char keybuf[32], iv[8];
2345
2346        if (cipherlen % 8 != 0) {
2347            errmsg = "encrypted part of key is not a multiple of cipher block"
2348                " size";
2349            goto error;
2350        }
2351
2352        MD5Init(&md5c);
2353        MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase));
2354        MD5Final(keybuf, &md5c);
2355
2356        MD5Init(&md5c);
2357        MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase));
2358        MD5Update(&md5c, keybuf, 16);
2359        MD5Final(keybuf+16, &md5c);
2360
2361        /*
2362         * Now decrypt the key blob.
2363         */
2364        memset(iv, 0, sizeof(iv));
2365        des3_decrypt_pubkey_ossh(keybuf, iv, (unsigned char *)ciphertext,
2366                                 cipherlen);
2367
2368        smemclr(&md5c, sizeof(md5c));
2369        smemclr(keybuf, sizeof(keybuf));
2370
2371        /*
2372         * Hereafter we return WRONG_PASSPHRASE for any parsing
2373         * error. (But only if we've just tried to decrypt it!
2374         * Returning WRONG_PASSPHRASE for an unencrypted key is
2375         * automatic doom.)
2376         */
2377        if (encrypted)
2378            ret = SSH2_WRONG_PASSPHRASE;
2379    }
2380
2381    /*
2382     * Strip away the containing string to get to the real meat.
2383     */
2384    len = toint(GET_32BIT(ciphertext));
2385    if (len < 0 || len > cipherlen-4) {
2386        errmsg = "containing string was ill-formed";
2387        goto error;
2388    }
2389    ciphertext += 4;
2390    cipherlen = len;
2391
2392    /*
2393     * Now we break down into RSA versus DSA. In either case we'll
2394     * construct public and private blobs in our own format, and
2395     * end up feeding them to alg->createkey().
2396     */
2397    blobsize = cipherlen + 256;
2398    blob = snewn(blobsize, unsigned char);
2399    privlen = 0;
2400    if (type == RSA) {
2401        struct mpint_pos n, e, d, u, p, q;
2402        int pos = 0;
2403        pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &e);
2404        pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &d);
2405        pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &n);
2406        pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &u);
2407        pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &p);
2408        pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &q);
2409        if (!q.start) {
2410            errmsg = "key data did not contain six integers";
2411            goto error;
2412        }
2413
2414        alg = &ssh_rsa;
2415        pos = 0;
2416        pos += put_string(blob+pos, "ssh-rsa", 7);
2417        pos += put_mp(blob+pos, e.start, e.bytes);
2418        pos += put_mp(blob+pos, n.start, n.bytes);
2419        publen = pos;
2420        pos += put_string(blob+pos, d.start, d.bytes);
2421        pos += put_mp(blob+pos, q.start, q.bytes);
2422        pos += put_mp(blob+pos, p.start, p.bytes);
2423        pos += put_mp(blob+pos, u.start, u.bytes);
2424        privlen = pos - publen;
2425    } else {
2426        struct mpint_pos p, q, g, x, y;
2427        int pos = 4;
2428
2429        assert(type == DSA); /* the only other option from the if above */
2430
2431        if (GET_32BIT(ciphertext) != 0) {
2432            errmsg = "predefined DSA parameters not supported";
2433            goto error;
2434        }
2435        pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &p);
2436        pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &g);
2437        pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &q);
2438        pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &y);
2439        pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &x);
2440        if (!x.start) {
2441            errmsg = "key data did not contain five integers";
2442            goto error;
2443        }
2444
2445        alg = &ssh_dss;
2446        pos = 0;
2447        pos += put_string(blob+pos, "ssh-dss", 7);
2448        pos += put_mp(blob+pos, p.start, p.bytes);
2449        pos += put_mp(blob+pos, q.start, q.bytes);
2450        pos += put_mp(blob+pos, g.start, g.bytes);
2451        pos += put_mp(blob+pos, y.start, y.bytes);
2452        publen = pos;
2453        pos += put_mp(blob+pos, x.start, x.bytes);
2454        privlen = pos - publen;
2455    }
2456
2457    assert(privlen > 0);               /* should have bombed by now if not */
2458
2459    retkey = snew(struct ssh2_userkey);
2460    retkey->alg = alg;
2461    retkey->data = alg->createkey(alg, blob, publen, blob+publen, privlen);
2462    if (!retkey->data) {
2463        sfree(retkey);
2464        errmsg = "unable to create key data structure";
2465        goto error;
2466    }
2467    retkey->comment = dupstr(key->comment);
2468
2469    errmsg = NULL; /* no error */
2470    ret = retkey;
2471
2472    error:
2473    if (blob) {
2474        smemclr(blob, blobsize);
2475        sfree(blob);
2476    }
2477    smemclr(key->keyblob, key->keyblob_size);
2478    sfree(key->keyblob);
2479    smemclr(key, sizeof(*key));
2480    sfree(key);
2481    if (errmsg_p) *errmsg_p = errmsg;
2482    return ret;
2483}
2484
2485int sshcom_write(const Filename *filename, struct ssh2_userkey *key,
2486                 char *passphrase)
2487{
2488    unsigned char *pubblob, *privblob;
2489    int publen, privlen;
2490    unsigned char *outblob;
2491    int outlen;
2492    struct mpint_pos numbers[6];
2493    int nnumbers, initial_zero, pos, lenpos, i;
2494    const char *type;
2495    char *ciphertext;
2496    int cipherlen;
2497    int ret = 0;
2498    FILE *fp;
2499
2500    /*
2501     * Fetch the key blobs.
2502     */
2503    pubblob = key->alg->public_blob(key->data, &publen);
2504    privblob = key->alg->private_blob(key->data, &privlen);
2505    outblob = NULL;
2506
2507    /*
2508     * Find the sequence of integers to be encoded into the OpenSSH
2509     * key blob, and also decide on the header line.
2510     */
2511    if (key->alg == &ssh_rsa) {
2512        int pos;
2513        struct mpint_pos n, e, d, p, q, iqmp;
2514
2515        /*
2516         * These blobs were generated from inside PuTTY, so we needn't
2517         * treat them as untrusted.
2518         */
2519        pos = 4 + GET_32BIT(pubblob);
2520        pos += ssh2_read_mpint(pubblob+pos, publen-pos, &e);
2521        pos += ssh2_read_mpint(pubblob+pos, publen-pos, &n);
2522        pos = 0;
2523        pos += ssh2_read_mpint(privblob+pos, privlen-pos, &d);
2524        pos += ssh2_read_mpint(privblob+pos, privlen-pos, &p);
2525        pos += ssh2_read_mpint(privblob+pos, privlen-pos, &q);
2526        pos += ssh2_read_mpint(privblob+pos, privlen-pos, &iqmp);
2527
2528        assert(e.start && iqmp.start); /* can't go wrong */
2529
2530        numbers[0] = e;
2531        numbers[1] = d;
2532        numbers[2] = n;
2533        numbers[3] = iqmp;
2534        numbers[4] = q;
2535        numbers[5] = p;
2536
2537        nnumbers = 6;
2538        initial_zero = 0;
2539        type = "if-modn{sign{rsa-pkcs1-sha1},encrypt{rsa-pkcs1v2-oaep}}";
2540    } else if (key->alg == &ssh_dss) {
2541        int pos;
2542        struct mpint_pos p, q, g, y, x;
2543
2544        /*
2545         * These blobs were generated from inside PuTTY, so we needn't
2546         * treat them as untrusted.
2547         */
2548        pos = 4 + GET_32BIT(pubblob);
2549        pos += ssh2_read_mpint(pubblob+pos, publen-pos, &p);
2550        pos += ssh2_read_mpint(pubblob+pos, publen-pos, &q);
2551        pos += ssh2_read_mpint(pubblob+pos, publen-pos, &g);
2552        pos += ssh2_read_mpint(pubblob+pos, publen-pos, &y);
2553        pos = 0;
2554        pos += ssh2_read_mpint(privblob+pos, privlen-pos, &x);
2555
2556        assert(y.start && x.start); /* can't go wrong */
2557
2558        numbers[0] = p;
2559        numbers[1] = g;
2560        numbers[2] = q;
2561        numbers[3] = y;
2562        numbers[4] = x;
2563
2564        nnumbers = 5;
2565        initial_zero = 1;
2566        type = "dl-modp{sign{dsa-nist-sha1},dh{plain}}";
2567    } else {
2568        assert(0);                     /* zoinks! */
2569        exit(1); /* XXX: GCC doesn't understand assert() on some systems. */
2570    }
2571
2572    /*
2573     * Total size of key blob will be somewhere under 512 plus
2574     * combined length of integers. We'll calculate the more
2575     * precise size as we construct the blob.
2576     */
2577    outlen = 512;
2578    for (i = 0; i < nnumbers; i++)
2579        outlen += 4 + numbers[i].bytes;
2580    outblob = snewn(outlen, unsigned char);
2581
2582    /*
2583     * Create the unencrypted key blob.
2584     */
2585    pos = 0;
2586    PUT_32BIT(outblob+pos, SSHCOM_MAGIC_NUMBER); pos += 4;
2587    pos += 4;                          /* length field, fill in later */
2588    pos += put_string(outblob+pos, type, strlen(type));
2589    {
2590        const char *ciphertype = passphrase ? "3des-cbc" : "none";
2591        pos += put_string(outblob+pos, ciphertype, strlen(ciphertype));
2592    }
2593    lenpos = pos;                      /* remember this position */
2594    pos += 4;                          /* encrypted-blob size */
2595    pos += 4;                          /* encrypted-payload size */
2596    if (initial_zero) {
2597        PUT_32BIT(outblob+pos, 0);
2598        pos += 4;
2599    }
2600    for (i = 0; i < nnumbers; i++)
2601        pos += sshcom_put_mpint(outblob+pos,
2602                                numbers[i].start, numbers[i].bytes);
2603    /* Now wrap up the encrypted payload. */
2604    PUT_32BIT(outblob+lenpos+4, pos - (lenpos+8));
2605    /* Pad encrypted blob to a multiple of cipher block size. */
2606    if (passphrase) {
2607        int padding = -(pos - (lenpos+4)) & 7;
2608        while (padding--)
2609            outblob[pos++] = random_byte();
2610    }
2611    ciphertext = (char *)outblob+lenpos+4;
2612    cipherlen = pos - (lenpos+4);
2613    assert(!passphrase || cipherlen % 8 == 0);
2614    /* Wrap up the encrypted blob string. */
2615    PUT_32BIT(outblob+lenpos, cipherlen);
2616    /* And finally fill in the total length field. */
2617    PUT_32BIT(outblob+4, pos);
2618
2619    assert(pos < outlen);
2620
2621    /*
2622     * Encrypt the key.
2623     */
2624    if (passphrase) {
2625        /*
2626         * Derive encryption key from passphrase and iv/salt:
2627         *
2628         *  - let block A equal MD5(passphrase)
2629         *  - let block B equal MD5(passphrase || A)
2630         *  - block C would be MD5(passphrase || A || B) and so on
2631         *  - encryption key is the first N bytes of A || B
2632         */
2633        struct MD5Context md5c;
2634        unsigned char keybuf[32], iv[8];
2635
2636        MD5Init(&md5c);
2637        MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase));
2638        MD5Final(keybuf, &md5c);
2639
2640        MD5Init(&md5c);
2641        MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase));
2642        MD5Update(&md5c, keybuf, 16);
2643        MD5Final(keybuf+16, &md5c);
2644
2645        /*
2646         * Now decrypt the key blob.
2647         */
2648        memset(iv, 0, sizeof(iv));
2649        des3_encrypt_pubkey_ossh(keybuf, iv, (unsigned char *)ciphertext,
2650                                 cipherlen);
2651
2652        smemclr(&md5c, sizeof(md5c));
2653        smemclr(keybuf, sizeof(keybuf));
2654    }
2655
2656    /*
2657     * And save it. We'll use Unix line endings just in case it's
2658     * subsequently transferred in binary mode.
2659     */
2660    fp = f_open(filename, "wb", TRUE);      /* ensure Unix line endings */
2661    if (!fp)
2662        goto error;
2663    fputs("---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----\n", fp);
2664    fprintf(fp, "Comment: \"");
2665    /*
2666     * Comment header is broken with backslash-newline if it goes
2667     * over 70 chars. Although it's surrounded by quotes, it
2668     * _doesn't_ escape backslashes or quotes within the string.
2669     * Don't ask me, I didn't design it.
2670     */
2671    {
2672        int slen = 60;                 /* starts at 60 due to "Comment: " */
2673        char *c = key->comment;
2674        while ((int)strlen(c) > slen) {
2675            fprintf(fp, "%.*s\\\n", slen, c);
2676            c += slen;
2677            slen = 70;                 /* allow 70 chars on subsequent lines */
2678        }
2679        fprintf(fp, "%s\"\n", c);
2680    }
2681    base64_encode(fp, outblob, pos, 70);
2682    fputs("---- END SSH2 ENCRYPTED PRIVATE KEY ----\n", fp);
2683    fclose(fp);
2684    ret = 1;
2685
2686    error:
2687    if (outblob) {
2688        smemclr(outblob, outlen);
2689        sfree(outblob);
2690    }
2691    if (privblob) {
2692        smemclr(privblob, privlen);
2693        sfree(privblob);
2694    }
2695    if (pubblob) {
2696        smemclr(pubblob, publen);
2697        sfree(pubblob);
2698    }
2699    return ret;
2700}
Note: See TracBrowser for help on using the repository browser.