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

Last change on this file since 130 was 130, checked in by jrpelegrina, 3 years ago

First release to xenial

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