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