Develop and Download Open Source Software

Browse Subversion Repository

Contents of /branches/ssh_chacha20poly1305/ttssh2/ttxssh/keyfiles.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 9248 - (show annotations) (download) (as text)
Thu May 13 13:02:31 2021 UTC (2 years, 10 months ago) by nmaya
File MIME type: text/x-csrc
File size: 50296 byte(s)
関数の途中で変数宣言したせいでビルドできない問題を修正
1 /*
2 * Copyright (c) 1998-2001, Robert O'Callahan
3 * (C) 2004- TeraTerm Project
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 /*
31 This code is copyright (C) 1998-1999 Robert O'Callahan.
32 See LICENSE.TXT for the license.
33 */
34
35 #include "ttxssh.h"
36 #include "keyfiles.h"
37 #include "key.h"
38
39 #include <io.h>
40 #include <fcntl.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <errno.h>
44 #include <openssl/rsa.h>
45 #include <openssl/dsa.h>
46 #include <openssl/evp.h>
47 #include <openssl/pem.h>
48 #include <openssl/md5.h>
49 #include <openssl/err.h>
50
51 #include "cipher.h"
52
53 static char ID_string[] = "SSH PRIVATE KEY FILE FORMAT 1.1\n";
54
55 static BIGNUM *get_bignum(unsigned char *bytes)
56 {
57 int bits = get_ushort16_MSBfirst(bytes);
58
59 return BN_bin2bn(bytes + 2, (bits + 7) / 8, NULL);
60 }
61
62 /* normalize the RSA key by precomputing various bits of it.
63 This code is adapted from libeay's rsa_gen.c
64 It's needed to work around "issues" with LIBEAY/RSAREF.
65 If this function returns 0, then something went wrong and the
66 key must be discarded. */
67 static BOOL normalize_key(RSA *key)
68 {
69 BOOL OK = FALSE;
70 BIGNUM *r = BN_new();
71 BN_CTX *ctx = BN_CTX_new();
72 BIGNUM *e, *n, *d, *dmp1, *dmq1, *iqmp, *p, *q;
73
74 e = n = d = dmp1 = dmq1 = iqmp = p = q = NULL;
75
76 RSA_get0_key(key, &n, &e, &d);
77 RSA_get0_factors(key, &p, &q);
78 RSA_get0_crt_params(key, &dmp1, &dmq1, &iqmp);
79
80 if (BN_cmp(p, q) < 0) {
81 BN_swap(p, q);
82 }
83
84 if (r != NULL && ctx != NULL) {
85 dmp1 = BN_new();
86 dmq1 = BN_new();
87 iqmp = BN_mod_inverse(NULL, q, p, ctx);
88 RSA_set0_crt_params(key, dmp1, dmq1, iqmp);
89
90 if (dmp1 != NULL && dmq1 != NULL && iqmp != NULL) {
91 OK = BN_sub(r, p, BN_value_one())
92 && BN_mod(dmp1, d, r, ctx)
93 && BN_sub(r, q, BN_value_one())
94 && BN_mod(dmq1, d, r, ctx);
95 }
96 }
97
98 BN_free(r);
99 BN_CTX_free(ctx);
100
101 return OK;
102 }
103
104 static RSA *read_RSA_private_key(PTInstVar pvar,
105 char * relative_name,
106 char * passphrase,
107 BOOL * invalid_passphrase,
108 BOOL is_auto_login)
109 {
110 char filename[2048];
111 int fd;
112 unsigned int length, amount_read;
113 unsigned char *keyfile_data;
114 unsigned int index;
115 int cipher;
116 RSA *key;
117 unsigned int E_index, N_index, D_index, U_index, P_index, Q_index = 0;
118 BIGNUM *e, *n, *d, *p, *q;
119
120 *invalid_passphrase = FALSE;
121
122 get_teraterm_dir_relative_name(filename, sizeof(filename),
123 relative_name);
124
125 fd = _open(filename, _O_RDONLY | _O_SEQUENTIAL | _O_BINARY);
126 if (fd == -1) {
127 if (errno == ENOENT) {
128 UTIL_get_lang_msg("MSG_KEYFILES_READ_ENOENT_ERROR", pvar,
129 "An error occurred while trying to read the key file.\n"
130 "The specified filename does not exist.");
131 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
132 } else {
133 UTIL_get_lang_msg("MSG_KEYFILES_READ_ERROR", pvar,
134 "An error occurred while trying to read the key file.");
135 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
136 }
137 return NULL;
138 }
139
140 length = (int) _lseek(fd, 0, SEEK_END);
141 _lseek(fd, 0, SEEK_SET);
142
143 if (length >= 0 && length < 0x7FFFFFFF) {
144 keyfile_data = malloc(length + 1);
145 if (keyfile_data == NULL) {
146 UTIL_get_lang_msg("MSG_KEYFILES_READ_ALLOC_ERROR", pvar,
147 "Memory ran out while trying to allocate space to read the key file.");
148 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
149 _close(fd);
150 return NULL;
151 }
152 } else {
153 UTIL_get_lang_msg("MSG_KEYFILES_READ_ERROR", pvar,
154 "An error occurred while trying to read the key file.");
155 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
156 _close(fd);
157 return NULL;
158 }
159
160 amount_read = _read(fd, keyfile_data, length);
161 /* terminate it with 0 so that the strncmp below is guaranteed not to
162 crash */
163 keyfile_data[length] = 0;
164
165 _close(fd);
166
167 if (amount_read != length) {
168 UTIL_get_lang_msg("MSG_KEYFILES_READ_ERROR", pvar,
169 "An error occurred while trying to read the key file.");
170 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
171 free(keyfile_data);
172 return NULL;
173 }
174
175 if (strcmp(keyfile_data, ID_string) != 0) {
176 UTIL_get_lang_msg("MSG_KEYFILES_PRIVATEKEY_NOTCONTAIN_ERROR", pvar,
177 "The specified key file does not contain an SSH private key.");
178 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
179 free(keyfile_data);
180 return NULL;
181 }
182
183 index = NUM_ELEM(ID_string);
184
185 if (length < index + 9) {
186 UTIL_get_lang_msg("MSG_KEYFILES_PRIVATEKEY_TRUNCATE_ERROR", pvar,
187 "The specified key file has been truncated and does not contain a valid private key.");
188 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
189 free(keyfile_data);
190 return NULL;
191 }
192
193 cipher = keyfile_data[index];
194 /* skip reserved int32, public key bits int32 */
195 index += 9;
196 /* skip public key e and n mp_ints */
197 if (length < index + 2) {
198 UTIL_get_lang_msg("MSG_KEYFILES_PRIVATEKEY_TRUNCATE_ERROR", pvar,
199 "The specified key file has been truncated and does not contain a valid private key.");
200 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
201 free(keyfile_data);
202 return NULL;
203 }
204 N_index = index;
205 index += (get_ushort16_MSBfirst(keyfile_data + index) + 7) / 8 + 2;
206 if (length < index + 2) {
207 UTIL_get_lang_msg("MSG_KEYFILES_PRIVATEKEY_TRUNCATE_ERROR", pvar,
208 "The specified key file has been truncated and does not contain a valid private key.");
209 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
210 free(keyfile_data);
211 return NULL;
212 }
213 E_index = index;
214 index += (get_ushort16_MSBfirst(keyfile_data + index) + 7) / 8 + 2;
215 /* skip comment */
216 if (length < index + 4) {
217 UTIL_get_lang_msg("MSG_KEYFILES_PRIVATEKEY_TRUNCATE_ERROR", pvar,
218 "The specified key file has been truncated and does not contain a valid private key.");
219 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
220 free(keyfile_data);
221 return NULL;
222 }
223 index += get_uint32_MSBfirst(keyfile_data + index) + 4;
224
225 if (length < index + 6) {
226 UTIL_get_lang_msg("MSG_KEYFILES_PRIVATEKEY_TRUNCATE_ERROR", pvar,
227 "The specified key file has been truncated and does not contain a valid private key.");
228 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
229 free(keyfile_data);
230 return NULL;
231 }
232 if (cipher != SSH_CIPHER_NONE) {
233 if ((length - index) % 8 != 0) {
234 UTIL_get_lang_msg("MSG_KEYFILES_PRIVATEKEY_LENGTH_ERROR", pvar,
235 "The specified key file cannot be decrypted using the passphrase.\n"
236 "The file does not have the correct length.");
237 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
238 free(keyfile_data);
239 return NULL;
240 }
241 if (!CRYPT_passphrase_decrypt
242 (cipher, passphrase, keyfile_data + index, length - index)) {
243 UTIL_get_lang_msg("MSG_KEYFILES_PRIVATEKEY_NOCIPHER_ERROR", pvar,
244 "The specified key file cannot be decrypted using the passphrase.\n"
245 "The cipher type used to encrypt the file is not supported by TTSSH for this purpose.");
246 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
247 free(keyfile_data);
248 return NULL;
249 }
250 }
251
252 if (keyfile_data[index] != keyfile_data[index + 2]
253 || keyfile_data[index + 1] != keyfile_data[index + 3]) {
254 *invalid_passphrase = TRUE;
255 if (is_auto_login) {
256 UTIL_get_lang_msg("MSG_KEYFILES_PASSPHRASE_EMPTY_ERROR", pvar,
257 "The specified key file cannot be decrypted using the empty passphrase.\n"
258 "For auto-login, you must create a key file with no passphrase.\n"
259 "BEWARE: This means the key can easily be stolen.");
260 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
261 }
262 else {
263 UTIL_get_lang_msg("MSG_KEYFILES_PASSPHRASE_ERROR", pvar,
264 "The specified key file cannot be decrypted using the passphrase.\n"
265 "The passphrase is incorrect.");
266 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
267 }
268 SecureZeroMemory(keyfile_data, length);
269 free(keyfile_data);
270 return NULL;
271 }
272 index += 4;
273
274 D_index = index;
275 if (length >= D_index + 2) {
276 U_index =
277 D_index + (get_ushort16_MSBfirst(keyfile_data + D_index) +
278 7) / 8 + 2;
279 if (length >= U_index + 2) {
280 P_index =
281 U_index + (get_ushort16_MSBfirst(keyfile_data + U_index) +
282 7) / 8 + 2;
283 if (length >= P_index + 2) {
284 Q_index =
285 P_index +
286 (get_ushort16_MSBfirst(keyfile_data + P_index) +
287 7) / 8 + 2;
288 }
289 }
290 }
291 if (Q_index == 0
292 || length <
293 Q_index + (get_ushort16_MSBfirst(keyfile_data + Q_index) + 7) / 8 + 2) {
294 UTIL_get_lang_msg("MSG_KEYFILES_PRIVATEKEY_TRUNCATE_ERROR", pvar,
295 "The specified key file has been truncated and does not contain a valid private key.");
296 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
297 SecureZeroMemory(keyfile_data, length);
298 free(keyfile_data);
299 return NULL;
300 }
301
302 key = RSA_new();
303 n = get_bignum(keyfile_data + N_index);
304 e = get_bignum(keyfile_data + E_index);
305 d = get_bignum(keyfile_data + D_index);
306 RSA_set0_key(key, n, e, d);
307 p = get_bignum(keyfile_data + P_index);
308 q = get_bignum(keyfile_data + Q_index);
309 RSA_set0_factors(key, p, q);
310
311 if (!normalize_key(key)) {
312 UTIL_get_lang_msg("MSG_KEYFILES_CRYPTOLIB_ERROR", pvar,
313 "Error in cryptography library.\n"
314 "Perhaps the stored key is invalid.");
315 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
316
317 RSA_free(key);
318 key = NULL;
319 }
320
321 SecureZeroMemory(keyfile_data, length);
322 free(keyfile_data);
323 return key;
324 }
325
326 Key *KEYFILES_read_private_key(PTInstVar pvar,
327 char * relative_name,
328 char * passphrase,
329 BOOL * invalid_passphrase,
330 BOOL is_auto_login)
331 {
332 RSA *RSA_key = read_RSA_private_key(pvar, relative_name,
333 passphrase, invalid_passphrase,
334 is_auto_login);
335
336 if (RSA_key == NULL) {
337 return FALSE;
338 } else {
339 Key *result = (Key *) malloc(sizeof(Key));
340
341 // �t���[���������� 0 ���������������������������B(2004.12.20 yutaka)
342 ZeroMemory(result, sizeof(Key));
343
344 result->rsa = RSA_key;
345 return result;
346 }
347 }
348
349
350 //
351 // SSH2
352 //
353
354 // bcrypt KDF �`��������
355 // based on key_parse_private2() @ OpenSSH 6.5
356 static Key *read_SSH2_private2_key(PTInstVar pvar,
357 FILE * fp,
358 char * passphrase,
359 BOOL * invalid_passphrase,
360 BOOL is_auto_login,
361 char *errmsg,
362 int errmsg_len)
363 {
364 /* (A)
365 * buffer_consume�n�������g���������Abuffer_len��buffer_ptr���g�����������A
366 * buffer_len -> buffer_remain_len
367 * buffer_ptr -> buffer_tail_ptr
368 * �������g�p���������B
369 */
370 buffer_t *blob = NULL;
371 buffer_t *b = NULL;
372 buffer_t *kdf = NULL;
373 buffer_t *encoded = NULL;
374 buffer_t *copy_consumed = NULL; // (A)
375 Key *keyfmt = NULL;
376 unsigned char buf[1024];
377 unsigned char *cp, last, pad;
378 char *ciphername = NULL, *kdfname = NULL, *kdfp = NULL, *key = NULL, *salt = NULL, *comment = NULL;
379 unsigned int len, klen, nkeys, blocksize, keylen, ivlen, slen, rounds;
380 unsigned int check1, check2, m1len, m2len;
381 int dlen, i;
382 const struct ssh2cipher *cipher;
383 size_t authlen;
384 struct sshcipher_ctx *cc = NULL;
385 int ret;
386
387 blob = buffer_init();
388 b = buffer_init();
389 kdf = buffer_init();
390 encoded = buffer_init();
391 copy_consumed = buffer_init();
392
393 if (blob == NULL || b == NULL || kdf == NULL || encoded == NULL || copy_consumed == NULL)
394 goto error;
395
396 // �t�@�C������������������
397 for (;;) {
398 len = fread(buf, 1, sizeof(buf), fp);
399 buffer_append(blob, buf, len);
400 if (buffer_len(blob) > MAX_KEY_FILE_SIZE) {
401 logprintf(LOG_LEVEL_WARNING, "%s: key file too large.", __FUNCTION__);
402 goto error;
403 }
404 if (len < sizeof(buf))
405 break;
406 }
407
408 /* base64 decode */
409 m1len = sizeof(MARK_BEGIN) - 1;
410 m2len = sizeof(MARK_END) - 1;
411 cp = buffer_ptr(blob);
412 len = buffer_len(blob);
413 if (len < m1len || memcmp(cp, MARK_BEGIN, m1len)) {
414 logprintf(LOG_LEVEL_VERBOSE, "%s: missing begin marker", __FUNCTION__);
415 goto error;
416 }
417 cp += m1len;
418 len -= m1len;
419 while (len) {
420 if (*cp != '\n' && *cp != '\r')
421 buffer_put_char(encoded, *cp);
422 last = *cp;
423 len--;
424 cp++;
425 if (last == '\n') {
426 if (len >= m2len && !memcmp(cp, MARK_END, m2len)) {
427 buffer_put_char(encoded, '\0');
428 break;
429 }
430 }
431 }
432 if (!len) {
433 logprintf(LOG_LEVEL_VERBOSE, "%s: no end marker", __FUNCTION__);
434 goto error;
435 }
436
437 // �t�@�C�����X�L�������I�����������Abase64 decode�����B
438 len = buffer_len(encoded);
439 if ((cp = buffer_append_space(copy_consumed, len)) == NULL) {
440 logprintf(LOG_LEVEL_ERROR, "%s: buffer_append_space", __FUNCTION__);
441 goto error;
442 }
443 if ((dlen = b64decode(cp, len, buffer_ptr(encoded))) < 0) {
444 logprintf(LOG_LEVEL_ERROR, "%s: base64 decode failed", __FUNCTION__);
445 goto error;
446 }
447 if ((unsigned int)dlen > len) {
448 logprintf(LOG_LEVEL_ERROR, "%s: crazy base64 length %d > %u", __FUNCTION__, dlen, len);
449 goto error;
450 }
451
452 buffer_consume_end(copy_consumed, len - dlen);
453 if (buffer_remain_len(copy_consumed) < sizeof(AUTH_MAGIC) ||
454 memcmp(buffer_tail_ptr(copy_consumed), AUTH_MAGIC, sizeof(AUTH_MAGIC))) {
455 logprintf(LOG_LEVEL_ERROR, "%s: bad magic", __FUNCTION__);
456 goto error;
457 }
458 buffer_consume(copy_consumed, sizeof(AUTH_MAGIC));
459
460 /*
461 * �f�R�[�h�����f�[�^�����������B
462 */
463 // �������A���S���Y�������O
464 ciphername = buffer_get_string_msg(copy_consumed, NULL);
465 cipher = get_cipher_by_name(ciphername);
466 if (cipher == NULL && strcmp(ciphername, "none") != 0) {
467 logprintf(LOG_LEVEL_ERROR, "%s: unknown cipher name", __FUNCTION__);
468 goto error;
469 }
470 // �p�X�t���[�Y���`�F�b�N�B�������� none �����������������p�X���[�h���F�������B
471 if ((passphrase == NULL || strlen(passphrase) == 0) &&
472 strcmp(ciphername, "none") != 0) {
473 /* passphrase required */
474 goto error;
475 }
476
477 kdfname = buffer_get_string_msg(copy_consumed, NULL);
478 if (kdfname == NULL ||
479 (!strcmp(kdfname, "none") && !strcmp(kdfname, KDFNAME))) {
480 logprintf(LOG_LEVEL_ERROR, "%s: unknown kdf name", __FUNCTION__ );
481 goto error;
482 }
483 if (!strcmp(kdfname, "none") && strcmp(ciphername, "none") != 0) {
484 logprintf(LOG_LEVEL_ERROR, "%s: cipher %s requires kdf", __FUNCTION__, ciphername);
485 goto error;
486 }
487
488 /* kdf options */
489 kdfp = buffer_get_string_msg(copy_consumed, &klen);
490 if (kdfp == NULL) {
491 logprintf(LOG_LEVEL_ERROR, "%s: kdf options not set", __FUNCTION__);
492 goto error;
493 }
494 if (klen > 0) {
495 if ((cp = buffer_append_space(kdf, klen)) == NULL) {
496 logprintf(LOG_LEVEL_ERROR, "%s: kdf alloc failed", __FUNCTION__);
497 goto error;
498 }
499 memcpy(cp, kdfp, klen);
500 }
501
502 /* number of keys */
503 if (buffer_get_int_ret(&nkeys, copy_consumed) < 0) {
504 logprintf(LOG_LEVEL_ERROR, "%s: key counter missing", __FUNCTION__);
505 goto error;
506 }
507 if (nkeys != 1) {
508 logprintf(LOG_LEVEL_ERROR, "%s: only one key supported", __FUNCTION__);
509 goto error;
510 }
511
512 /* pubkey */
513 cp = buffer_get_string_msg(copy_consumed, &len);
514 if (cp == NULL) {
515 logprintf(LOG_LEVEL_ERROR, "%s: pubkey not found", __FUNCTION__);
516 goto error;
517 }
518 free(cp); /* XXX check pubkey against decrypted private key */
519
520 /* size of encrypted key blob */
521 len = buffer_get_int(copy_consumed);
522 blocksize = get_cipher_block_size(cipher);
523 authlen = 0; // TODO: ����������������
524 if (len < blocksize) {
525 logprintf(LOG_LEVEL_ERROR, "%s: encrypted data too small", __FUNCTION__);
526 goto error;
527 }
528 if (len % blocksize) {
529 logprintf(LOG_LEVEL_ERROR, "%s: length not multiple of blocksize", __FUNCTION__);
530 goto error;
531 }
532
533 /* setup key */
534 keylen = get_cipher_key_len(cipher);
535 ivlen = blocksize;
536 key = calloc(1, keylen + ivlen);
537 if (!strcmp(kdfname, KDFNAME)) {
538 salt = buffer_get_string_msg(kdf, &slen);
539 if (salt == NULL) {
540 logprintf(LOG_LEVEL_ERROR, "%s: salt not set", __FUNCTION__);
541 goto error;
542 }
543 rounds = buffer_get_int(kdf);
544 // TODO: error check
545 if (bcrypt_pbkdf(passphrase, strlen(passphrase), salt, slen,
546 key, keylen + ivlen, rounds) < 0) {
547 logprintf(LOG_LEVEL_ERROR, "%s: bcrypt_pbkdf failed", __FUNCTION__);
548 goto error;
549 }
550 }
551
552 // ������
553 cp = buffer_append_space(b, len);
554 cipher_init_SSH2(&cc, cipher, key, keylen, key + keylen, ivlen, CIPHER_DECRYPT, pvar);
555 ret = EVP_Cipher(cc->evp, cp, buffer_tail_ptr(copy_consumed), len);
556 if (ret == 0) {
557 goto error;
558 }
559 buffer_consume(copy_consumed, len);
560
561 if (buffer_remain_len(copy_consumed) != 0) {
562 logprintf(LOG_LEVEL_ERROR, "%s: key blob has trailing data (len = %u)", __FUNCTION__,
563 buffer_remain_len(copy_consumed));
564 goto error;
565 }
566
567 /* check bytes */
568 if (buffer_get_int_ret(&check1, b) < 0 ||
569 buffer_get_int_ret(&check2, b) < 0) {
570 logprintf(LOG_LEVEL_ERROR, "%s: check bytes missing", __FUNCTION__);
571 goto error;
572 }
573 if (check1 != check2) {
574 logprintf(LOG_LEVEL_VERBOSE, "%s: decrypt failed: 0x%08x != 0x%08x", __FUNCTION__,
575 check1, check2);
576 goto error;
577 }
578
579 keyfmt = key_private_deserialize(b);
580 if (keyfmt == NULL)
581 goto error;
582
583 /* comment */
584 comment = buffer_get_string_msg(b, NULL);
585
586 i = 0;
587 while (buffer_remain_len(b)) {
588 if (buffer_get_char_ret(&pad, b) == -1 ||
589 pad != (++i & 0xff)) {
590 logprintf(LOG_LEVEL_ERROR, "%s: bad padding", __FUNCTION__);
591 key_free(keyfmt);
592 keyfmt = NULL;
593 goto error;
594 }
595 }
596
597 /* success */
598 keyfmt->bcrypt_kdf = 1;
599
600 error:
601 buffer_free(blob);
602 buffer_free(b);
603 buffer_free(kdf);
604 buffer_free(encoded);
605 buffer_free(copy_consumed);
606 cipher_free_SSH2(cc);
607
608 free(ciphername);
609 free(kdfname);
610 free(kdfp);
611 free(key);
612 free(salt);
613 free(comment);
614
615 // KDF ������������
616 if (keyfmt == NULL) {
617 fseek(fp, 0, SEEK_SET);
618
619 } else {
620 fclose(fp);
621
622 }
623
624 return (keyfmt);
625 }
626
627
628 // OpenSSL format
629 Key *read_SSH2_private_key(PTInstVar pvar,
630 FILE * fp,
631 char * passphrase,
632 BOOL * invalid_passphrase,
633 BOOL is_auto_login,
634 char *errmsg,
635 int errmsg_len)
636 {
637 Key *result = NULL;
638 EVP_PKEY *pk = NULL;
639 unsigned long err = 0;
640 int pk_type;
641
642 OpenSSL_add_all_algorithms();
643 ERR_load_crypto_strings();
644 //seed_prng();
645
646 result = read_SSH2_private2_key(pvar, fp, passphrase, invalid_passphrase, is_auto_login, errmsg, errmsg_len);
647 if (result)
648 return (result);
649
650 result = (Key *)malloc(sizeof(Key));
651 ZeroMemory(result, sizeof(Key));
652
653 // �t�@�C�������p�X�t���[�Y�����������������������B
654 pk = PEM_read_PrivateKey(fp, NULL, NULL, passphrase);
655 if (pk == NULL) {
656 err = ERR_get_error();
657 ERR_error_string_n(err, errmsg, errmsg_len);
658 *invalid_passphrase = TRUE;
659 goto error;
660 }
661
662 pk_type = EVP_PKEY_id(pk);
663 switch (pk_type) {
664 case EVP_PKEY_RSA: // RSA key
665 result->type = KEY_RSA;
666 result->rsa = EVP_PKEY_get1_RSA(pk);
667 result->dsa = NULL;
668 result->ecdsa = NULL;
669
670 // RSA�������������L���������i�^�C�~���O�U���������h���j
671 if (RSA_blinding_on(result->rsa, NULL) != 1) {
672 err = ERR_get_error();
673 ERR_error_string_n(err, errmsg, errmsg_len);
674 goto error;
675 }
676 break;
677
678 case EVP_PKEY_DSA: // DSA key
679 result->type = KEY_DSA;
680 result->rsa = NULL;
681 result->dsa = EVP_PKEY_get1_DSA(pk);
682 result->ecdsa = NULL;
683 break;
684
685 case EVP_PKEY_EC: // ECDSA key
686 result->rsa = NULL;
687 result->dsa = NULL;
688 result->ecdsa = EVP_PKEY_get1_EC_KEY(pk);
689 {
690 const EC_GROUP *g = EC_KEY_get0_group(result->ecdsa);
691 result->type = nid_to_keytype(EC_GROUP_get_curve_name(g));
692 if (result->type == KEY_UNSPEC) {
693 goto error;
694 }
695 }
696 break;
697
698 default:
699 goto error;
700 break;
701 }
702
703 if (pk != NULL)
704 EVP_PKEY_free(pk);
705
706 fclose(fp);
707 return (result);
708
709 error:
710 if (pk != NULL)
711 EVP_PKEY_free(pk);
712
713 if (result != NULL)
714 key_free(result);
715
716 if (fp != NULL)
717 fclose(fp);
718
719 return (NULL);
720 }
721
722 // PuTTY format
723 /*
724 * PuTTY-User-Key-File-2: ssh-dss
725 * Encryption: aes256-cbc
726 * Comment: imported-openssh-key
727 * Public-Lines: 10
728 * Base64...
729 * Private-Lines: 1
730 * Base64...
731 * Private-MAC: Base16...
732 * Private-Hash: Base16... (PuTTY-User-Key-File-1) ???
733 *
734 * for "ssh-rsa", it will be composed of
735 *
736 * "Public-Lines: " plus a number N.
737 *
738 * string "ssh-rsa"
739 * mpint exponent
740 * mpint modulus
741 *
742 * "Private-Lines: " plus a number N,
743 *
744 * mpint private_exponent
745 * mpint p (the larger of the two primes)
746 * mpint q (the smaller prime)
747 * mpint iqmp (the inverse of q modulo p)
748 * data padding (to reach a multiple of the cipher block size)
749 *
750 * for "ssh-dss", it will be composed of
751 *
752 * "Public-Lines: " plus a number N.
753 *
754 * string "ssh-rsa"
755 * mpint p
756 * mpint q
757 * mpint g
758 * mpint y
759 *
760 * "Private-Lines: " plus a number N,
761 *
762 * mpint x (the private key parameter)
763 *
764 * for "ecdsa-sha2-nistp256" or
765 * "ecdsa-sha2-nistp384" or
766 * "ecdsa-sha2-nistp521", it will be composed of
767 *
768 * "Public-Lines: " plus a number N.
769 *
770 * string "ecdsa-sha2-[identifier]" ("ecdsa-sha2-nistp256" or
771 * "ecdsa-sha2-nistp384" or
772 * "ecdsa-sha2-nistp521")
773 * string [identifier] ("nistp256" or "nistp384" or "nistp521")
774 * string Q (EC_POINT)
775 *
776 * "Private-Lines: " plus a number N,
777 *
778 * mpint n
779 *
780 * for "ssh-ed25519", it will be composed of
781 *
782 * "Public-Lines: " plus a number N.
783 *
784 * string "ssh-ed25519"
785 * string key
786 *
787 * "Private-Lines: " plus a number N,
788 *
789 * string key
790 *
791 * "Private-MAC: " plus a hex, HMAC-SHA-1 of:
792 *
793 * string name of algorithm ("ssh-dss", "ssh-rsa")
794 * string encryption type
795 * string comment
796 * string public-blob
797 * string private-plaintext
798 */
799 Key *read_SSH2_PuTTY_private_key(PTInstVar pvar,
800 FILE * fp,
801 char * passphrase,
802 BOOL * invalid_passphrase,
803 BOOL is_auto_login,
804 char *errmsg,
805 int errmsg_len)
806 {
807 Key *result = NULL;
808 EVP_PKEY *pk = NULL;
809 unsigned long err = 0;
810 int i, len, len2;
811 char *encname = NULL, *comment = NULL, *private_mac = NULL;
812 buffer_t *pubkey = NULL, *prikey = NULL;
813 const struct ssh2cipher *cipher = NULL;
814 struct sshcipher_ctx *cc = NULL;
815
816 result = (Key *)malloc(sizeof(Key));
817 ZeroMemory(result, sizeof(Key));
818 result->type = KEY_NONE;
819 result->rsa = NULL;
820 result->dsa = NULL;
821 result->ecdsa = NULL;
822
823 pubkey = buffer_init();
824 prikey = buffer_init();
825
826 // parse keyfile & decode blob
827 {
828 char line[200], buf[100];
829 BIO *bmem, *b64, *chain;
830 while (fgets(line, sizeof(line), fp) != NULL) {
831 if (strncmp(line, "PuTTY-User-Key-File-2: ", strlen("PuTTY-User-Key-File-2: ")) == 0) {
832 if (strncmp(line + strlen("PuTTY-User-Key-File-2: "), "ssh-dss", strlen("ssh-dss")) == 0) {
833 result->type = KEY_DSA;
834 }
835 else if (strncmp(line + strlen("PuTTY-User-Key-File-2: "), "ssh-rsa", strlen("ssh-rsa")) == 0) {
836 result->type = KEY_RSA;
837 }
838 else if (strncmp(line + strlen("PuTTY-User-Key-File-2: "), "ecdsa-sha2-nistp256", strlen("ecdsa-sha2-nistp256")) == 0) {
839 result->type = KEY_ECDSA256;
840 }
841 else if (strncmp(line + strlen("PuTTY-User-Key-File-2: "), "ecdsa-sha2-nistp384", strlen("ecdsa-sha2-nistp384")) == 0) {
842 result->type = KEY_ECDSA384;
843 }
844 else if (strncmp(line + strlen("PuTTY-User-Key-File-2: "), "ecdsa-sha2-nistp521", strlen("ecdsa-sha2-nistp521")) == 0) {
845 result->type = KEY_ECDSA521;
846 }
847 else if (strncmp(line + strlen("PuTTY-User-Key-File-2: "), "ssh-ed25519", strlen("ssh-ed25519")) == 0) {
848 result->type = KEY_ED25519;
849 }
850 else {
851 strncpy_s(errmsg, errmsg_len, "not a PuTTY SSH-2 private key", _TRUNCATE);
852 goto error;
853 }
854 }
855 else if (strncmp(line, "Encryption: ", strlen("Encryption: ")) == 0) {
856 len = strlen(line + strlen("Encryption: "));
857 encname = (char *)malloc(len); // trim \n
858 strncpy_s(encname, len, line + strlen("Encryption: "), _TRUNCATE);
859 if (strcmp(encname, "aes256-cbc") == 0) {
860 // NOP
861 }
862 else if (strcmp(encname, "none") == 0) {
863 // NOP
864 }
865 else {
866 strncpy_s(errmsg, errmsg_len, "unknown encryption type", _TRUNCATE);
867 goto error;
868 }
869 }
870 else if (strncmp(line, "Comment: ", strlen("Comment: ")) == 0) {
871 len = strlen(line + strlen("Comment: "));
872 comment = (char *)malloc(len); // trim \n
873 strncpy_s(comment, len, line + strlen("Comment: "), _TRUNCATE);
874 }
875 else if (strncmp(line, "Private-MAC: ", strlen("Private-MAC: ")) == 0) {
876 len = strlen(line + strlen("Private-MAC: "));
877 private_mac = (char *)malloc(len); // trim \n
878 strncpy_s(private_mac, len, line + strlen("Private-MAC: "), _TRUNCATE);
879 }
880 else if (strncmp(line, "Private-HASH: ", strlen("Private-HASH: ")) == 0) {
881 strncpy_s(errmsg, errmsg_len, "not a PuTTY SSH-2 private key", _TRUNCATE);
882 goto error;
883 }
884 else if (strncmp(line, "Public-Lines: ", strlen("Public-Lines: ")) == 0) {
885 len = atoi(line + strlen("Public-Lines: "));
886 b64 = BIO_new(BIO_f_base64());
887 bmem = BIO_new(BIO_s_mem());
888 for (i=0; i<len && fgets(line, sizeof(line), fp)!=NULL; i++) {
889 BIO_write(bmem, line, strlen(line));
890 }
891 BIO_flush(bmem);
892 chain = BIO_push(b64, bmem);
893 BIO_set_mem_eof_return(chain, 0);
894 while ((len2 = BIO_read(chain, buf, sizeof(buf))) > 0) {
895 buffer_append(pubkey, buf, len2);
896 }
897 BIO_free_all(chain);
898 }
899 else if (strncmp(line, "Private-Lines: ", strlen("Private-Lines: ")) == 0) {
900 len = atoi(line + strlen("Private-Lines: "));
901 b64 = BIO_new(BIO_f_base64());
902 bmem = BIO_new(BIO_s_mem());
903 for (i=0; i<len && fgets(line, sizeof(line), fp)!=NULL; i++) {
904 BIO_write(bmem, line, strlen(line));
905 }
906 BIO_flush(bmem);
907 chain = BIO_push(b64, bmem);
908 BIO_set_mem_eof_return(chain, 0);
909 while ((len2 = BIO_read(chain, buf, sizeof(buf))) > 0) {
910 buffer_append(prikey, buf, len2);
911 }
912 BIO_free_all(chain);
913 }
914 else {
915 strncpy_s(errmsg, errmsg_len, "not a PuTTY SSH-2 private key", _TRUNCATE);
916 goto error;
917 }
918 }
919 }
920
921 if (result->type == KEY_NONE || strlen(encname) == 0 || buffer_len(pubkey) == 0 || buffer_len(prikey) == 0) {
922 strncpy_s(errmsg, errmsg_len, "key file format error", _TRUNCATE);
923 goto error;
924 }
925
926 // decrypt prikey with aes256-cbc
927 if (strcmp(encname, "aes256-cbc") == 0) {
928 const EVP_MD *md = EVP_sha1();
929 EVP_MD_CTX *ctx = NULL;
930 unsigned char key[40], iv[32];
931 EVP_CIPHER_CTX *cipher_ctx = NULL;
932 char *decrypted = NULL;
933 int ret;
934
935 ctx = EVP_MD_CTX_new();
936 if (ctx == NULL) {
937 goto error;
938 }
939
940 cipher_ctx = EVP_CIPHER_CTX_new();
941 if (cipher_ctx == NULL) {
942 EVP_MD_CTX_free(ctx);
943 goto error;
944 }
945
946 EVP_DigestInit(ctx, md);
947 EVP_DigestUpdate(ctx, "\0\0\0\0", 4);
948 EVP_DigestUpdate(ctx, passphrase, strlen(passphrase));
949 EVP_DigestFinal(ctx, key, &len);
950
951 EVP_DigestInit(ctx, md);
952 EVP_DigestUpdate(ctx, "\0\0\0\1", 4);
953 EVP_DigestUpdate(ctx, passphrase, strlen(passphrase));
954 EVP_DigestFinal(ctx, key + 20, &len);
955
956 EVP_MD_CTX_free(ctx);
957
958 memset(iv, 0, sizeof(iv));
959
960 // decrypt
961 cipher = get_cipher_by_name("aes256-cbc");
962 cipher_init_SSH2(&cc, cipher, key, 32, iv, 16, CIPHER_DECRYPT, pvar);
963 len = buffer_len(prikey);
964 decrypted = (char *)malloc(len);
965 ret = EVP_Cipher(cc->evp, decrypted, prikey->buf, len);
966 if (ret == 0) {
967 strncpy_s(errmsg, errmsg_len, "Key decrypt error", _TRUNCATE);
968 free(decrypted);
969 cipher_free_SSH2(cc);
970 goto error;
971 }
972 buffer_clear(prikey);
973 buffer_append(prikey, decrypted, len);
974 free(decrypted);
975 cipher_free_SSH2(cc);
976 }
977
978 // verity MAC
979 {
980 char realmac[41];
981 unsigned char binary[20];
982 buffer_t *macdata;
983
984 macdata = buffer_init();
985
986 len = strlen(get_ssh2_hostkey_type_name(result->type));
987 buffer_put_int(macdata, len);
988 buffer_append(macdata, get_ssh2_hostkey_type_name(result->type), len);
989 len = strlen(encname);
990 buffer_put_int(macdata, len);
991 buffer_append(macdata, encname, len);
992 len = strlen(comment);
993 buffer_put_int(macdata, len);
994 buffer_append(macdata, comment, len);
995 buffer_put_int(macdata, pubkey->len);
996 buffer_append(macdata, pubkey->buf, pubkey->len);
997 buffer_put_int(macdata, prikey->len);
998 buffer_append(macdata, prikey->buf, prikey->len);
999
1000 if (private_mac != NULL) {
1001 unsigned char mackey[20];
1002 char header[] = "putty-private-key-file-mac-key";
1003 const EVP_MD *md = EVP_sha1();
1004 EVP_MD_CTX *ctx = NULL;
1005
1006 ctx = EVP_MD_CTX_new();
1007 if (ctx == NULL) {
1008 goto error;
1009 }
1010
1011 EVP_DigestInit(ctx, md);
1012 EVP_DigestUpdate(ctx, header, sizeof(header)-1);
1013 len = strlen(passphrase);
1014 if (strcmp(encname, "aes256-cbc") == 0 && len > 0) {
1015 EVP_DigestUpdate(ctx, passphrase, len);
1016 }
1017 EVP_DigestFinal(ctx, mackey, &len);
1018 EVP_MD_CTX_free(ctx);
1019
1020 //hmac_sha1_simple(mackey, sizeof(mackey), macdata->buf, macdata->len, binary);
1021 {
1022 EVP_MD_CTX *ctx[2] = {0, 0};
1023 unsigned char intermediate[20];
1024 unsigned char foo[64];
1025 int i;
1026
1027 ctx[0] = EVP_MD_CTX_new();
1028 if (ctx[0] == NULL) {
1029 goto error;
1030 }
1031 ctx[1] = EVP_MD_CTX_new();
1032 if (ctx[1] == NULL) {
1033 EVP_MD_CTX_free(ctx[0]);
1034 goto error;
1035 }
1036
1037 memset(foo, 0x36, sizeof(foo));
1038 for (i = 0; i < sizeof(mackey) && i < sizeof(foo); i++) {
1039 foo[i] ^= mackey[i];
1040 }
1041 EVP_DigestInit(ctx[0], md);
1042 EVP_DigestUpdate(ctx[0], foo, sizeof(foo));
1043
1044 memset(foo, 0x5C, sizeof(foo));
1045 for (i = 0; i < sizeof(mackey) && i < sizeof(foo); i++) {
1046 foo[i] ^= mackey[i];
1047 }
1048 EVP_DigestInit(ctx[1], md);
1049 EVP_DigestUpdate(ctx[1], foo, sizeof(foo));
1050
1051 memset(foo, 0, sizeof(foo));
1052
1053 EVP_DigestUpdate(ctx[0], macdata->buf, macdata->len);
1054 EVP_DigestFinal(ctx[0], intermediate, &len);
1055
1056 EVP_DigestUpdate(ctx[1], intermediate, sizeof(intermediate));
1057 EVP_DigestFinal(ctx[1], binary, &len);
1058
1059 EVP_MD_CTX_free(ctx[0]);
1060 EVP_MD_CTX_free(ctx[1]);
1061 }
1062
1063 memset(mackey, 0, sizeof(mackey));
1064
1065 }
1066 else {
1067 strncpy_s(errmsg, errmsg_len, "key file format error", _TRUNCATE);
1068 buffer_free(macdata);
1069 goto error;
1070 }
1071
1072 buffer_free(macdata);
1073
1074 for (i=0; i<20; i++) {
1075 sprintf(realmac + 2*i, "%02x", binary[i]);
1076 }
1077
1078 if (strcmp(private_mac, realmac) != 0) {
1079 if (strcmp(encname, "aes256-cbc") == 0) {
1080 strncpy_s(errmsg, errmsg_len, "wrong passphrase", _TRUNCATE);
1081 *invalid_passphrase = TRUE;
1082 goto error;
1083 }
1084 else {
1085 strncpy_s(errmsg, errmsg_len, "MAC verify failed", _TRUNCATE);
1086 goto error;
1087 }
1088 }
1089 }
1090
1091 switch (result->type) {
1092 case KEY_RSA:
1093 {
1094 char *pubkey_type, *pub, *pri;
1095 BIGNUM *e, *n, *d, *iqmp, *p, *q;
1096
1097 pub = pubkey->buf;
1098 pri = prikey->buf;
1099 pubkey_type = buffer_get_string(&pub, NULL);
1100 if (strcmp(pubkey_type, "ssh-rsa") != 0) {
1101 strncpy_s(errmsg, errmsg_len, "key type error", _TRUNCATE);
1102 free(pubkey_type);
1103 goto error;
1104 }
1105 free(pubkey_type);
1106
1107 result->rsa = RSA_new();
1108 if (result->rsa == NULL) {
1109 strncpy_s(errmsg, errmsg_len, "key init error", _TRUNCATE);
1110 goto error;
1111 }
1112 e = BN_new();
1113 n = BN_new();
1114 d = BN_new();
1115 RSA_set0_key(result->rsa, n, e, d);
1116 p = BN_new();
1117 q = BN_new();
1118 RSA_set0_factors(result->rsa, p, q);
1119 iqmp = BN_new();
1120 RSA_set0_crt_params(result->rsa, NULL, NULL, iqmp);
1121 if (e == NULL ||
1122 n == NULL ||
1123 d == NULL ||
1124 p == NULL ||
1125 q == NULL ||
1126 iqmp == NULL) {
1127 strncpy_s(errmsg, errmsg_len, "key init error", _TRUNCATE);
1128 goto error;
1129 }
1130
1131 buffer_get_bignum2(&pub, e);
1132 buffer_get_bignum2(&pub, n);
1133
1134 buffer_get_bignum2(&pri, d);
1135 buffer_get_bignum2(&pri, p);
1136 buffer_get_bignum2(&pri, q);
1137 buffer_get_bignum2(&pri, iqmp);
1138
1139 break;
1140 }
1141 case KEY_DSA:
1142 {
1143 char *pubkey_type, *pub, *pri;
1144 BIGNUM *p, *q, *g, *pub_key, *priv_key;
1145
1146 pub = pubkey->buf;
1147 pri = prikey->buf;
1148 pubkey_type = buffer_get_string(&pub, NULL);
1149 if (strcmp(pubkey_type, "ssh-dss") != 0) {
1150 strncpy_s(errmsg, errmsg_len, "key type error", _TRUNCATE);
1151 free(pubkey_type);
1152 goto error;
1153 }
1154 free(pubkey_type);
1155
1156 result->dsa = DSA_new();
1157 if (result->dsa == NULL) {
1158 strncpy_s(errmsg, errmsg_len, "key init error", _TRUNCATE);
1159 goto error;
1160 }
1161 p = BN_new();
1162 q = BN_new();
1163 g = BN_new();
1164 DSA_set0_pqg(result->dsa, p, q, g);
1165 pub_key = BN_new();
1166 priv_key = BN_new();
1167 DSA_set0_key(result->dsa, pub_key, priv_key);
1168 if (p == NULL ||
1169 q == NULL ||
1170 g == NULL ||
1171 pub_key == NULL ||
1172 priv_key == NULL) {
1173 strncpy_s(errmsg, errmsg_len, "key init error", _TRUNCATE);
1174 goto error;
1175 }
1176
1177 buffer_get_bignum2(&pub, p);
1178 buffer_get_bignum2(&pub, q);
1179 buffer_get_bignum2(&pub, g);
1180 buffer_get_bignum2(&pub, pub_key);
1181
1182 buffer_get_bignum2(&pri, priv_key);
1183
1184 break;
1185 }
1186 case KEY_ECDSA256:
1187 case KEY_ECDSA384:
1188 case KEY_ECDSA521:
1189 {
1190 char *pubkey_type, *pub, *pri;
1191 int success = 0;
1192 unsigned int nid;
1193 char *curve = NULL;
1194 ssh_keytype skt;
1195 BIGNUM *exponent = NULL;
1196 EC_POINT *q = NULL;
1197
1198 pub = pubkey->buf;
1199 pri = prikey->buf;
1200 pubkey_type = buffer_get_string(&pub, NULL);
1201 if ((result->type == KEY_ECDSA256 && strcmp(pubkey_type, "ecdsa-sha2-nistp256") != 0) ||
1202 (result->type == KEY_ECDSA384 && strcmp(pubkey_type, "ecdsa-sha2-nistp384") != 0) ||
1203 (result->type == KEY_ECDSA521 && strcmp(pubkey_type, "ecdsa-sha2-nistp521") != 0)) {
1204 strncpy_s(errmsg, errmsg_len, "key type error", _TRUNCATE);
1205 free(pubkey_type);
1206 goto error;
1207 }
1208 free(pubkey_type);
1209
1210 nid = keytype_to_cipher_nid(result->type);
1211 curve = buffer_get_string(&pub, NULL);
1212 skt = key_curve_name_to_keytype(curve);
1213 if (nid != keytype_to_cipher_nid(skt))
1214 goto ecdsa_error;
1215
1216 if ((result->ecdsa = EC_KEY_new_by_curve_name(nid)) == NULL)
1217 goto ecdsa_error;
1218 if ((q = EC_POINT_new(EC_KEY_get0_group(result->ecdsa))) == NULL)
1219 goto ecdsa_error;
1220 if ((exponent = BN_new()) == NULL)
1221 goto ecdsa_error;
1222
1223 buffer_get_ecpoint(&pub, EC_KEY_get0_group(result->ecdsa), q);
1224 buffer_get_bignum2(&pri, exponent);
1225 if (EC_KEY_set_public_key(result->ecdsa, q) != 1)
1226 goto ecdsa_error;
1227 if (EC_KEY_set_private_key(result->ecdsa, exponent) != 1)
1228 goto ecdsa_error;
1229 if (key_ec_validate_public(EC_KEY_get0_group(result->ecdsa),
1230 EC_KEY_get0_public_key(result->ecdsa)) != 0)
1231 goto ecdsa_error;
1232 if (key_ec_validate_private(result->ecdsa) != 0)
1233 goto ecdsa_error;
1234
1235 success = 1;
1236
1237 ecdsa_error:
1238 free(curve);
1239 if (exponent)
1240 BN_clear_free(exponent);
1241 if (q)
1242 EC_POINT_free(q);
1243 if (success == 0)
1244 goto error;
1245
1246 break;
1247 }
1248 case KEY_ED25519:
1249 {
1250 char *pubkey_type, *pub, *pri;
1251 unsigned int pklen, sklen;
1252 char *sk;
1253 pub = pubkey->buf;
1254 pri = prikey->buf;
1255 pubkey_type = buffer_get_string(&pub, NULL);
1256 if (strcmp(pubkey_type, "ssh-ed25519") != 0) {
1257 strncpy_s(errmsg, errmsg_len, "key type error", _TRUNCATE);
1258 free(pubkey_type);
1259 goto error;
1260 }
1261 free(pubkey_type);
1262
1263 result->ed25519_pk = buffer_get_string(&pub, &pklen);
1264 sk = buffer_get_string(&pri, &sklen);
1265 result->ed25519_sk = malloc(pklen + sklen + 1);
1266 memcpy(result->ed25519_sk, sk, sklen);
1267 memcpy(result->ed25519_sk + sklen, result->ed25519_pk, pklen);
1268 result->ed25519_sk[sklen + pklen] = '\0';
1269 free(sk);
1270
1271 if (pklen != ED25519_PK_SZ)
1272 goto error;
1273 if (sklen + pklen != ED25519_SK_SZ)
1274 goto error;
1275
1276 break;
1277 }
1278 default:
1279 strncpy_s(errmsg, errmsg_len, "key type error", _TRUNCATE);
1280 goto error;
1281 break;
1282 }
1283
1284 fclose(fp);
1285
1286 if (encname != NULL)
1287 free(encname);
1288
1289 if (comment != NULL)
1290 free(comment);
1291
1292 if (pubkey != NULL)
1293 buffer_free(pubkey);
1294
1295 if (prikey != NULL)
1296 buffer_free(prikey);
1297
1298 if (private_mac != NULL)
1299 free(private_mac);
1300
1301 return (result);
1302
1303 error:
1304 if (result != NULL)
1305 key_free(result);
1306
1307 if (fp != NULL)
1308 fclose(fp);
1309
1310 if (encname != NULL)
1311 free(encname);
1312
1313 if (comment != NULL)
1314 free(comment);
1315
1316 if (pubkey != NULL)
1317 buffer_free(pubkey);
1318
1319 if (prikey != NULL)
1320 buffer_free(prikey);
1321
1322 if (private_mac != NULL)
1323 free(private_mac);
1324
1325 return (NULL);
1326 }
1327
1328 // SECSH(ssh.com) format
1329 /*
1330 * Code to read ssh.com private keys.
1331 *
1332 * "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----"
1333 * "Comment:..."
1334 * "Base64..."
1335 * "---- END SSH2 ENCRYPTED PRIVATE KEY ----"
1336 *
1337 * Body of key data
1338 *
1339 * - uint32 0x3f6ff9eb (magic number)
1340 * - uint32 size (total blob size)
1341 * - string key-type (see below)
1342 * - string cipher-type (tells you if key is encrypted)
1343 * - string encrypted-blob
1344 *
1345 * The key type strings are ghastly. The RSA key I looked at had a type string of
1346 *
1347 * `if-modn{sign{rsa-pkcs1-sha1},encrypt{rsa-pkcs1v2-oaep}}'
1348 * `dl-modp{sign{dsa-nist-sha1},dh{plain}}'
1349 * `ec-modp'
1350 *
1351 * The encryption. The cipher-type string appears to be either
1352 *
1353 * `none'
1354 * `3des-cbc'
1355 *
1356 * The payload blob, for an RSA key, contains:
1357 * - mpint e
1358 * - mpint d
1359 * - mpint n (yes, the public and private stuff is intermixed)
1360 * - mpint u (presumably inverse of p mod q)
1361 * - mpint p (p is the smaller prime)
1362 * - mpint q (q is the larger)
1363 *
1364 * For a DSA key, the payload blob contains:
1365 * - uint32 0
1366 * - mpint p
1367 * - mpint g
1368 * - mpint q
1369 * - mpint y
1370 * - mpint x
1371 *
1372 * For a ECDSA key, the payload blob contains:
1373 * - uint32 1
1374 * - string [identifier] ("nistp256" or "nistp384" or "nistp521")
1375 * - mpint n
1376 */
1377 Key *read_SSH2_SECSH_private_key(PTInstVar pvar,
1378 FILE * fp,
1379 char * passphrase,
1380 BOOL * invalid_passphrase,
1381 BOOL is_auto_login,
1382 char *errmsg,
1383 int errmsg_len)
1384 {
1385 Key *result = NULL;
1386 unsigned long err = 0;
1387 int i, len2;
1388 unsigned int len;
1389 int encflag;
1390 char *encname = NULL;
1391 buffer_t *blob = NULL, *blob2 = NULL;
1392 const struct ssh2cipher *cipher = NULL;
1393 struct sshcipher_ctx *cc = NULL;
1394
1395 result = (Key *)malloc(sizeof(Key));
1396 ZeroMemory(result, sizeof(Key));
1397 result->type = KEY_NONE;
1398 result->rsa = NULL;
1399 result->dsa = NULL;
1400 result->ecdsa = NULL;
1401
1402 blob = buffer_init();
1403 blob2 = buffer_init();
1404
1405 // parse keyfile & decode blob
1406 {
1407 char line[200], buf[100];
1408 BIO *bmem, *b64, *chain;
1409 int st = 0;
1410
1411 b64 = BIO_new(BIO_f_base64());
1412 bmem = BIO_new(BIO_s_mem());
1413
1414 while (fgets(line, sizeof(line), fp) != NULL) {
1415 if (strncmp(line, "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----", strlen("---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----")) == 0) {
1416 if (st == 0) {
1417 st = 1;
1418 continue;
1419 }
1420 else {
1421 break;
1422 }
1423 }
1424 else if (strncmp(line, "---- END SSH2 ENCRYPTED PRIVATE KEY ----", strlen("---- END SSH2 ENCRYPTED PRIVATE KEY ----")) == 0) {
1425 break;
1426 }
1427
1428 if (st == 0) {
1429 continue;
1430 }
1431
1432 if (strchr(line, ':') != NULL) {
1433 if (st == 1) {
1434 continue;
1435 }
1436 strncpy_s(errmsg, errmsg_len, "header found in body of key data", _TRUNCATE);
1437 BIO_free_all(bmem);
1438 goto error;
1439 }
1440 else if (st == 1) {
1441 st = 2;
1442 }
1443
1444 BIO_write(bmem, line, strlen(line));
1445 }
1446
1447 BIO_flush(bmem);
1448 chain = BIO_push(b64, bmem);
1449 BIO_set_mem_eof_return(chain, 0);
1450 while ((len2 = BIO_read(chain, buf, sizeof(buf))) > 0) {
1451 buffer_append(blob, buf, len2);
1452 }
1453 BIO_free_all(chain);
1454 buffer_rewind(blob);
1455 }
1456
1457 if (blob->len < 8) {
1458 strncpy_s(errmsg, errmsg_len, "key body not present", _TRUNCATE);
1459 goto error;
1460 }
1461 i = buffer_get_int(blob);
1462 if (i != 0x3f6ff9eb) {
1463 strncpy_s(errmsg, errmsg_len, "magic number error", _TRUNCATE);
1464 goto error;
1465 }
1466 len = buffer_get_int(blob);
1467 if (len == 0 || len > blob->len) {
1468 strncpy_s(errmsg, errmsg_len, "body size error", _TRUNCATE);
1469 goto error;
1470 }
1471
1472 len = buffer_get_int(blob);
1473 if (strncmp(blob->buf + blob->offset, "if-modn{sign{rsa", strlen("if-modn{sign{rsa") - 1) == 0) {
1474 result->type = KEY_RSA;
1475 }
1476 else if (strncmp(blob->buf + blob->offset, "dl-modp{sign{dsa", strlen("dl-modp{sign{dsa") - 1) == 0) {
1477 result->type = KEY_DSA;
1478 }
1479 else if (strncmp(blob->buf + blob->offset, "ec-modp", strlen("ec-modp") - 1) == 0) {
1480 result->type = KEY_ECDSA256;
1481 }
1482 else {
1483 strncpy_s(errmsg, errmsg_len, "unknown key type", _TRUNCATE);
1484 goto error;
1485 }
1486 buffer_consume(blob, len);
1487
1488 len = buffer_get_int(blob);
1489 encname = (char *)malloc(len + 1);
1490 strncpy_s(encname, len + 1, blob->buf + blob->offset, _TRUNCATE);
1491 if (strcmp(encname, "3des-cbc") == 0) {
1492 encflag = 1;
1493 }
1494 else if (strcmp(encname, "none") == 0) {
1495 encflag = 0;
1496 }
1497 else {
1498 strncpy_s(errmsg, errmsg_len, "unknown encryption type", _TRUNCATE);
1499 goto error;
1500 }
1501 buffer_consume(blob, len);
1502
1503 len = buffer_get_int(blob);
1504 if (len > (blob->len - blob->offset)) {
1505 strncpy_s(errmsg, errmsg_len, "body size error", _TRUNCATE);
1506 goto error;
1507 }
1508
1509 // decrypt privkey with 3des-cbc
1510 if (strcmp(encname, "3des-cbc") == 0) {
1511 MD5_CTX md;
1512 unsigned char key[32], iv[16];
1513 EVP_CIPHER_CTX *cipher_ctx = NULL;
1514 char *decrypted = NULL;
1515 int ret;
1516
1517 cipher_ctx = EVP_CIPHER_CTX_new();
1518 if (cipher_ctx == NULL) {
1519 strncpy_s(errmsg, errmsg_len, "Out of memory: EVP_CIPHER_CTX_new()", _TRUNCATE);
1520 goto error;
1521 }
1522
1523 MD5_Init(&md);
1524 MD5_Update(&md, passphrase, strlen(passphrase));
1525 MD5_Final(key, &md);
1526
1527 MD5_Init(&md);
1528 MD5_Update(&md, passphrase, strlen(passphrase));
1529 MD5_Update(&md, key, 16);
1530 MD5_Final(key + 16, &md);
1531
1532 memset(iv, 0, sizeof(iv));
1533
1534 // decrypt
1535 cipher = get_cipher_by_name("3des-cbc");
1536 cipher_init_SSH2(&cc, cipher, key, 24, iv, 8, CIPHER_DECRYPT, pvar);
1537 decrypted = (char *)malloc(len);
1538 ret = EVP_Cipher(cc->evp, decrypted, blob->buf + blob->offset, len);
1539 if (ret == 0) {
1540 strncpy_s(errmsg, errmsg_len, "Key decrypt error", _TRUNCATE);
1541 cipher_free_SSH2(cc);
1542 goto error;
1543 }
1544 buffer_append(blob2, decrypted, len);
1545 free(decrypted);
1546 cipher_free_SSH2(cc);
1547
1548 *invalid_passphrase = TRUE;
1549 }
1550 else { // none
1551 buffer_append(blob2, blob->buf + blob->offset, len);
1552 }
1553 buffer_rewind(blob2);
1554
1555 len = buffer_get_int(blob2);
1556 if (len <= 0 || len > (blob2->len - blob2->offset)) {
1557 strncpy_s(errmsg, errmsg_len, "blob size error", _TRUNCATE);
1558 goto error;
1559 }
1560
1561 switch (result->type) {
1562 case KEY_RSA:
1563 {
1564 BIGNUM *e, *n, *d, *iqmp, *p, *q;
1565
1566 result->rsa = RSA_new();
1567 if (result->rsa == NULL) {
1568 strncpy_s(errmsg, errmsg_len, "key init error", _TRUNCATE);
1569 goto error;
1570 }
1571 e = BN_new();
1572 n = BN_new();
1573 d = BN_new();
1574 RSA_set0_key(result->rsa, n, e, d);
1575 p = BN_new();
1576 q = BN_new();
1577 RSA_set0_factors(result->rsa, p, q);
1578 iqmp = BN_new();
1579 RSA_set0_crt_params(result->rsa, NULL, NULL, iqmp);
1580 if (e == NULL ||
1581 n == NULL ||
1582 d == NULL ||
1583 p == NULL ||
1584 q == NULL ||
1585 iqmp == NULL) {
1586 strncpy_s(errmsg, errmsg_len, "key init error", _TRUNCATE);
1587 goto error;
1588 }
1589
1590 buffer_get_bignum_SECSH(blob2, e);
1591 buffer_get_bignum_SECSH(blob2, d);
1592 buffer_get_bignum_SECSH(blob2, n);
1593 buffer_get_bignum_SECSH(blob2, iqmp);
1594 buffer_get_bignum_SECSH(blob2, p);
1595 buffer_get_bignum_SECSH(blob2, q);
1596
1597 break;
1598 }
1599 case KEY_DSA:
1600 {
1601 int param;
1602 BIGNUM *p, *q, *g, *pub_key, *priv_key;
1603
1604 result->dsa = DSA_new();
1605 if (result->dsa == NULL) {
1606 strncpy_s(errmsg, errmsg_len, "key init error", _TRUNCATE);
1607 goto error;
1608 }
1609 p = BN_new();
1610 q = BN_new();
1611 g = BN_new();
1612 DSA_set0_pqg(result->dsa, p, q, g);
1613 pub_key = BN_new();
1614 priv_key = BN_new();
1615 DSA_set0_key(result->dsa, pub_key, priv_key);
1616 if (p == NULL ||
1617 q == NULL ||
1618 g == NULL ||
1619 pub_key == NULL ||
1620 priv_key == NULL) {
1621 strncpy_s(errmsg, errmsg_len, "key init error", _TRUNCATE);
1622 goto error;
1623 }
1624
1625 param = buffer_get_int(blob2);
1626 if (param != 0) {
1627 strncpy_s(errmsg, errmsg_len, "predefined DSA parameters not supported", _TRUNCATE);
1628 goto error;
1629 }
1630 buffer_get_bignum_SECSH(blob2, p);
1631 buffer_get_bignum_SECSH(blob2, g);
1632 buffer_get_bignum_SECSH(blob2, q);
1633 buffer_get_bignum_SECSH(blob2, pub_key);
1634 buffer_get_bignum_SECSH(blob2, priv_key);
1635
1636 break;
1637 }
1638 case KEY_ECDSA256:
1639 {
1640 unsigned int dummy, nid;
1641 int success = 0;
1642 char *curve = NULL;
1643 BIGNUM *exponent = NULL;
1644 EC_POINT *q = NULL;
1645 BN_CTX *ctx = NULL;
1646
1647 dummy = buffer_get_int(blob2);
1648 curve = buffer_get_string_msg(blob2, NULL);
1649
1650 if (strncmp(curve, "nistp256", strlen("nistp256")) == 0) {
1651 result->type = KEY_ECDSA256;
1652 }
1653 else if (strncmp(curve, "nistp384", strlen("nistp384")) == 0) {
1654 result->type = KEY_ECDSA384;
1655 }
1656 else if (strncmp(curve, "nistp521", strlen("nistp521")) == 0) {
1657 result->type = KEY_ECDSA521;
1658 }
1659 else {
1660 strncpy_s(errmsg, errmsg_len, "key type error", _TRUNCATE);
1661 goto error;
1662 }
1663
1664 nid = keytype_to_cipher_nid(result->type);
1665 if ((result->ecdsa = EC_KEY_new_by_curve_name(nid)) == NULL)
1666 goto ecdsa_error;
1667 if ((q = EC_POINT_new(EC_KEY_get0_group(result->ecdsa))) == NULL)
1668 goto ecdsa_error;
1669 if ((exponent = BN_new()) == NULL)
1670 goto ecdsa_error;
1671
1672 buffer_get_bignum_SECSH(blob2, exponent);
1673 if (EC_KEY_set_private_key(result->ecdsa, exponent) != 1)
1674 goto ecdsa_error;
1675 if (key_ec_validate_private(result->ecdsa) != 0)
1676 goto ecdsa_error;
1677
1678 // �t�@�C�����������������i�[�������������������J�����v�Z��������
1679 if ((ctx = BN_CTX_new()) == NULL)
1680 goto ecdsa_error;
1681 if (!EC_POINT_mul(EC_KEY_get0_group(result->ecdsa), q, exponent, NULL, NULL, ctx)) {
1682 goto ecdsa_error;
1683 }
1684 if (EC_KEY_set_public_key(result->ecdsa, q) != 1)
1685 goto ecdsa_error;
1686 if (key_ec_validate_public(EC_KEY_get0_group(result->ecdsa),
1687 EC_KEY_get0_public_key(result->ecdsa)) != 0)
1688 goto ecdsa_error;
1689
1690 success = 1;
1691
1692 ecdsa_error:
1693 free(curve);
1694 if (exponent)
1695 BN_clear_free(exponent);
1696 if (q)
1697 EC_POINT_free(q);
1698 if (ctx)
1699 BN_CTX_free(ctx);
1700 if (success == 0)
1701 goto error;
1702
1703 break;
1704 }
1705 default:
1706 strncpy_s(errmsg, errmsg_len, "key type error", _TRUNCATE);
1707 goto error;
1708 break;
1709 }
1710
1711 *invalid_passphrase = FALSE;
1712
1713 fclose(fp);
1714
1715 if (encname != NULL)
1716 free(encname);
1717
1718 if (blob != NULL)
1719 buffer_free(blob);
1720
1721 if (blob2 != NULL)
1722 buffer_free(blob2);
1723
1724 return (result);
1725
1726 error:
1727 if (result != NULL)
1728 key_free(result);
1729
1730 if (fp != NULL)
1731 fclose(fp);
1732
1733 if (encname != NULL)
1734 free(encname);
1735
1736 if (blob != NULL)
1737 buffer_free(blob);
1738
1739 if (blob2 != NULL)
1740 buffer_free(blob2);
1741
1742 return (NULL);
1743 }
1744
1745 ssh2_keyfile_type get_ssh2_keytype(char *relative_name,
1746 FILE **fp,
1747 char *errmsg,
1748 int errmsg_len) {
1749 ssh2_keyfile_type ret = SSH2_KEYFILE_TYPE_NONE;
1750 char filename[2048];
1751 char line[200];
1752 int i;
1753
1754 // �����p�X�������p�X�����������B�������������������A�u�h�b�g���n�����v�f�B���N�g����
1755 // �����t�@�C�������������������������B(2005.2.7 yutaka)
1756 get_teraterm_dir_relative_name(filename, sizeof(filename),
1757 relative_name);
1758
1759 *fp = fopen(filename, "r");
1760 if (*fp == NULL) {
1761 strncpy_s(errmsg, errmsg_len, strerror(errno), _TRUNCATE);
1762 return ret;
1763 }
1764
1765 while (fgets(line, sizeof(line), *fp) != NULL) {
1766 for (i=0; keyfile_headers[i].type != SSH2_KEYFILE_TYPE_NONE; i++) {
1767 if ( strncmp(line, keyfile_headers[i].header, strlen(keyfile_headers[i].header)) == 0) {
1768 ret = keyfile_headers[i].type;
1769 break;
1770 }
1771 }
1772 if (ret != SSH2_KEYFILE_TYPE_NONE)
1773 break;
1774 }
1775
1776 if (ret == SSH2_KEYFILE_TYPE_NONE) {
1777 strncpy_s(errmsg, errmsg_len, "Unknown key file type.", _TRUNCATE);
1778 fseek(*fp, 0, SEEK_SET);
1779 return ret;
1780 }
1781
1782 fseek(*fp, 0, SEEK_SET);
1783 return ret;
1784 }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26