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 9209 - (show annotations) (download) (as text)
Sat Apr 17 06:32:42 2021 UTC (2 years, 10 months ago) by nmaya
File MIME type: text/x-csrc
File size: 50242 byte(s)
OpenSSL 1.0.2 の API を使っているところを 1.1.0 の API に変更

- EVP_CIPHER_CTX_cleanup() -> EVP_CIPHER_CTX_free()
- EVP_CIPHER_CTX_init() -> EVP_CIPHER_CTX_reset()
- EVP_CIPHER_CTX_new() の中で 0 埋めされるので、EVP_CIPHER_CTX_init() を呼ばなくてよい所を削除

メモリの確保と解放を以下のような対応にした
- EVP_CIPHER_CTX_new() -> cipher_init_SSH2() したものは cipher_free_SSH2() で解放
- EVP_CIPHER_CTX_new() -> して cipher_init_SSH2() を通らないものは EVP_CIPHER_CTX_free() で解放
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 SSH2Cipher *cipher;
383 size_t authlen;
384 EVP_CIPHER_CTX *cipher_ctx = 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 cipher_ctx = EVP_CIPHER_CTX_new();
393
394 if (blob == NULL || b == NULL || kdf == NULL || encoded == NULL || copy_consumed == NULL || cipher_ctx == NULL)
395 goto error;
396
397 // �t�@�C������������������
398 for (;;) {
399 len = fread(buf, 1, sizeof(buf), fp);
400 buffer_append(blob, buf, len);
401 if (buffer_len(blob) > MAX_KEY_FILE_SIZE) {
402 logprintf(LOG_LEVEL_WARNING, "%s: key file too large.", __FUNCTION__);
403 goto error;
404 }
405 if (len < sizeof(buf))
406 break;
407 }
408
409 /* base64 decode */
410 m1len = sizeof(MARK_BEGIN) - 1;
411 m2len = sizeof(MARK_END) - 1;
412 cp = buffer_ptr(blob);
413 len = buffer_len(blob);
414 if (len < m1len || memcmp(cp, MARK_BEGIN, m1len)) {
415 logprintf(LOG_LEVEL_VERBOSE, "%s: missing begin marker", __FUNCTION__);
416 goto error;
417 }
418 cp += m1len;
419 len -= m1len;
420 while (len) {
421 if (*cp != '\n' && *cp != '\r')
422 buffer_put_char(encoded, *cp);
423 last = *cp;
424 len--;
425 cp++;
426 if (last == '\n') {
427 if (len >= m2len && !memcmp(cp, MARK_END, m2len)) {
428 buffer_put_char(encoded, '\0');
429 break;
430 }
431 }
432 }
433 if (!len) {
434 logprintf(LOG_LEVEL_VERBOSE, "%s: no end marker", __FUNCTION__);
435 goto error;
436 }
437
438 // �t�@�C�����X�L�������I�����������Abase64 decode�����B
439 len = buffer_len(encoded);
440 if ((cp = buffer_append_space(copy_consumed, len)) == NULL) {
441 logprintf(LOG_LEVEL_ERROR, "%s: buffer_append_space", __FUNCTION__);
442 goto error;
443 }
444 if ((dlen = b64decode(cp, len, buffer_ptr(encoded))) < 0) {
445 logprintf(LOG_LEVEL_ERROR, "%s: base64 decode failed", __FUNCTION__);
446 goto error;
447 }
448 if ((unsigned int)dlen > len) {
449 logprintf(LOG_LEVEL_ERROR, "%s: crazy base64 length %d > %u", __FUNCTION__, dlen, len);
450 goto error;
451 }
452
453 buffer_consume_end(copy_consumed, len - dlen);
454 if (buffer_remain_len(copy_consumed) < sizeof(AUTH_MAGIC) ||
455 memcmp(buffer_tail_ptr(copy_consumed), AUTH_MAGIC, sizeof(AUTH_MAGIC))) {
456 logprintf(LOG_LEVEL_ERROR, "%s: bad magic", __FUNCTION__);
457 goto error;
458 }
459 buffer_consume(copy_consumed, sizeof(AUTH_MAGIC));
460
461 /*
462 * �f�R�[�h�����f�[�^�����������B
463 */
464 // �������A���S���Y�������O
465 ciphername = buffer_get_string_msg(copy_consumed, NULL);
466 cipher = get_cipher_by_name(ciphername);
467 if (cipher == NULL && strcmp(ciphername, "none") != 0) {
468 logprintf(LOG_LEVEL_ERROR, "%s: unknown cipher name", __FUNCTION__);
469 goto error;
470 }
471 // �p�X�t���[�Y���`�F�b�N�B�������� none �����������������p�X���[�h���F�������B
472 if ((passphrase == NULL || strlen(passphrase) == 0) &&
473 strcmp(ciphername, "none") != 0) {
474 /* passphrase required */
475 goto error;
476 }
477
478 kdfname = buffer_get_string_msg(copy_consumed, NULL);
479 if (kdfname == NULL ||
480 (!strcmp(kdfname, "none") && !strcmp(kdfname, KDFNAME))) {
481 logprintf(LOG_LEVEL_ERROR, "%s: unknown kdf name", __FUNCTION__ );
482 goto error;
483 }
484 if (!strcmp(kdfname, "none") && strcmp(ciphername, "none") != 0) {
485 logprintf(LOG_LEVEL_ERROR, "%s: cipher %s requires kdf", __FUNCTION__, ciphername);
486 goto error;
487 }
488
489 /* kdf options */
490 kdfp = buffer_get_string_msg(copy_consumed, &klen);
491 if (kdfp == NULL) {
492 logprintf(LOG_LEVEL_ERROR, "%s: kdf options not set", __FUNCTION__);
493 goto error;
494 }
495 if (klen > 0) {
496 if ((cp = buffer_append_space(kdf, klen)) == NULL) {
497 logprintf(LOG_LEVEL_ERROR, "%s: kdf alloc failed", __FUNCTION__);
498 goto error;
499 }
500 memcpy(cp, kdfp, klen);
501 }
502
503 /* number of keys */
504 if (buffer_get_int_ret(&nkeys, copy_consumed) < 0) {
505 logprintf(LOG_LEVEL_ERROR, "%s: key counter missing", __FUNCTION__);
506 goto error;
507 }
508 if (nkeys != 1) {
509 logprintf(LOG_LEVEL_ERROR, "%s: only one key supported", __FUNCTION__);
510 goto error;
511 }
512
513 /* pubkey */
514 cp = buffer_get_string_msg(copy_consumed, &len);
515 if (cp == NULL) {
516 logprintf(LOG_LEVEL_ERROR, "%s: pubkey not found", __FUNCTION__);
517 goto error;
518 }
519 free(cp); /* XXX check pubkey against decrypted private key */
520
521 /* size of encrypted key blob */
522 len = buffer_get_int(copy_consumed);
523 blocksize = get_cipher_block_size(cipher);
524 authlen = 0; // TODO: ����������������
525 if (len < blocksize) {
526 logprintf(LOG_LEVEL_ERROR, "%s: encrypted data too small", __FUNCTION__);
527 goto error;
528 }
529 if (len % blocksize) {
530 logprintf(LOG_LEVEL_ERROR, "%s: length not multiple of blocksize", __FUNCTION__);
531 goto error;
532 }
533
534 /* setup key */
535 keylen = get_cipher_key_len(cipher);
536 ivlen = blocksize;
537 key = calloc(1, keylen + ivlen);
538 if (!strcmp(kdfname, KDFNAME)) {
539 salt = buffer_get_string_msg(kdf, &slen);
540 if (salt == NULL) {
541 logprintf(LOG_LEVEL_ERROR, "%s: salt not set", __FUNCTION__);
542 goto error;
543 }
544 rounds = buffer_get_int(kdf);
545 // TODO: error check
546 if (bcrypt_pbkdf(passphrase, strlen(passphrase), salt, slen,
547 key, keylen + ivlen, rounds) < 0) {
548 logprintf(LOG_LEVEL_ERROR, "%s: bcrypt_pbkdf failed", __FUNCTION__);
549 goto error;
550 }
551 }
552
553 // ������
554 cp = buffer_append_space(b, len);
555 cipher_init_SSH2(cipher_ctx, key, keylen, key + keylen, ivlen, CIPHER_DECRYPT,
556 get_cipher_EVP_CIPHER(cipher), 0, 0, pvar);
557 ret = EVP_Cipher(cipher_ctx, cp, buffer_tail_ptr(copy_consumed), len);
558 if (ret == 0) {
559 goto error;
560 }
561 buffer_consume(copy_consumed, len);
562
563 if (buffer_remain_len(copy_consumed) != 0) {
564 logprintf(LOG_LEVEL_ERROR, "%s: key blob has trailing data (len = %u)", __FUNCTION__,
565 buffer_remain_len(copy_consumed));
566 goto error;
567 }
568
569 /* check bytes */
570 if (buffer_get_int_ret(&check1, b) < 0 ||
571 buffer_get_int_ret(&check2, b) < 0) {
572 logprintf(LOG_LEVEL_ERROR, "%s: check bytes missing", __FUNCTION__);
573 goto error;
574 }
575 if (check1 != check2) {
576 logprintf(LOG_LEVEL_VERBOSE, "%s: decrypt failed: 0x%08x != 0x%08x", __FUNCTION__,
577 check1, check2);
578 goto error;
579 }
580
581 keyfmt = key_private_deserialize(b);
582 if (keyfmt == NULL)
583 goto error;
584
585 /* comment */
586 comment = buffer_get_string_msg(b, NULL);
587
588 i = 0;
589 while (buffer_remain_len(b)) {
590 if (buffer_get_char_ret(&pad, b) == -1 ||
591 pad != (++i & 0xff)) {
592 logprintf(LOG_LEVEL_ERROR, "%s: bad padding", __FUNCTION__);
593 key_free(keyfmt);
594 keyfmt = NULL;
595 goto error;
596 }
597 }
598
599 /* success */
600 keyfmt->bcrypt_kdf = 1;
601
602 error:
603 buffer_free(blob);
604 buffer_free(b);
605 buffer_free(kdf);
606 buffer_free(encoded);
607 buffer_free(copy_consumed);
608 cipher_free_SSH2(cipher_ctx);
609
610 free(ciphername);
611 free(kdfname);
612 free(kdfp);
613 free(key);
614 free(salt);
615 free(comment);
616
617 // KDF ������������
618 if (keyfmt == NULL) {
619 fseek(fp, 0, SEEK_SET);
620
621 } else {
622 fclose(fp);
623
624 }
625
626 return (keyfmt);
627 }
628
629
630 // OpenSSL format
631 Key *read_SSH2_private_key(PTInstVar pvar,
632 FILE * fp,
633 char * passphrase,
634 BOOL * invalid_passphrase,
635 BOOL is_auto_login,
636 char *errmsg,
637 int errmsg_len)
638 {
639 Key *result = NULL;
640 EVP_PKEY *pk = NULL;
641 unsigned long err = 0;
642 int pk_type;
643
644 OpenSSL_add_all_algorithms();
645 ERR_load_crypto_strings();
646 //seed_prng();
647
648 result = read_SSH2_private2_key(pvar, fp, passphrase, invalid_passphrase, is_auto_login, errmsg, errmsg_len);
649 if (result)
650 return (result);
651
652 result = (Key *)malloc(sizeof(Key));
653 ZeroMemory(result, sizeof(Key));
654
655 // �t�@�C�������p�X�t���[�Y�����������������������B
656 pk = PEM_read_PrivateKey(fp, NULL, NULL, passphrase);
657 if (pk == NULL) {
658 err = ERR_get_error();
659 ERR_error_string_n(err, errmsg, errmsg_len);
660 *invalid_passphrase = TRUE;
661 goto error;
662 }
663
664 pk_type = EVP_PKEY_id(pk);
665 switch (pk_type) {
666 case EVP_PKEY_RSA: // RSA key
667 result->type = KEY_RSA;
668 result->rsa = EVP_PKEY_get1_RSA(pk);
669 result->dsa = NULL;
670 result->ecdsa = NULL;
671
672 // RSA�������������L���������i�^�C�~���O�U���������h���j
673 if (RSA_blinding_on(result->rsa, NULL) != 1) {
674 err = ERR_get_error();
675 ERR_error_string_n(err, errmsg, errmsg_len);
676 goto error;
677 }
678 break;
679
680 case EVP_PKEY_DSA: // DSA key
681 result->type = KEY_DSA;
682 result->rsa = NULL;
683 result->dsa = EVP_PKEY_get1_DSA(pk);
684 result->ecdsa = NULL;
685 break;
686
687 case EVP_PKEY_EC: // ECDSA key
688 result->rsa = NULL;
689 result->dsa = NULL;
690 result->ecdsa = EVP_PKEY_get1_EC_KEY(pk);
691 {
692 const EC_GROUP *g = EC_KEY_get0_group(result->ecdsa);
693 result->type = nid_to_keytype(EC_GROUP_get_curve_name(g));
694 if (result->type == KEY_UNSPEC) {
695 goto error;
696 }
697 }
698 break;
699
700 default:
701 goto error;
702 break;
703 }
704
705 if (pk != NULL)
706 EVP_PKEY_free(pk);
707
708 fclose(fp);
709 return (result);
710
711 error:
712 if (pk != NULL)
713 EVP_PKEY_free(pk);
714
715 if (result != NULL)
716 key_free(result);
717
718 if (fp != NULL)
719 fclose(fp);
720
721 return (NULL);
722 }
723
724 // PuTTY format
725 /*
726 * PuTTY-User-Key-File-2: ssh-dss
727 * Encryption: aes256-cbc
728 * Comment: imported-openssh-key
729 * Public-Lines: 10
730 * Base64...
731 * Private-Lines: 1
732 * Base64...
733 * Private-MAC: Base16...
734 * Private-Hash: Base16... (PuTTY-User-Key-File-1) ???
735 *
736 * for "ssh-rsa", it will be composed of
737 *
738 * "Public-Lines: " plus a number N.
739 *
740 * string "ssh-rsa"
741 * mpint exponent
742 * mpint modulus
743 *
744 * "Private-Lines: " plus a number N,
745 *
746 * mpint private_exponent
747 * mpint p (the larger of the two primes)
748 * mpint q (the smaller prime)
749 * mpint iqmp (the inverse of q modulo p)
750 * data padding (to reach a multiple of the cipher block size)
751 *
752 * for "ssh-dss", it will be composed of
753 *
754 * "Public-Lines: " plus a number N.
755 *
756 * string "ssh-rsa"
757 * mpint p
758 * mpint q
759 * mpint g
760 * mpint y
761 *
762 * "Private-Lines: " plus a number N,
763 *
764 * mpint x (the private key parameter)
765 *
766 * for "ecdsa-sha2-nistp256" or
767 * "ecdsa-sha2-nistp384" or
768 * "ecdsa-sha2-nistp521", it will be composed of
769 *
770 * "Public-Lines: " plus a number N.
771 *
772 * string "ecdsa-sha2-[identifier]" ("ecdsa-sha2-nistp256" or
773 * "ecdsa-sha2-nistp384" or
774 * "ecdsa-sha2-nistp521")
775 * string [identifier] ("nistp256" or "nistp384" or "nistp521")
776 * string Q (EC_POINT)
777 *
778 * "Private-Lines: " plus a number N,
779 *
780 * mpint n
781 *
782 * for "ssh-ed25519", it will be composed of
783 *
784 * "Public-Lines: " plus a number N.
785 *
786 * string "ssh-ed25519"
787 * string key
788 *
789 * "Private-Lines: " plus a number N,
790 *
791 * string key
792 *
793 * "Private-MAC: " plus a hex, HMAC-SHA-1 of:
794 *
795 * string name of algorithm ("ssh-dss", "ssh-rsa")
796 * string encryption type
797 * string comment
798 * string public-blob
799 * string private-plaintext
800 */
801 Key *read_SSH2_PuTTY_private_key(PTInstVar pvar,
802 FILE * fp,
803 char * passphrase,
804 BOOL * invalid_passphrase,
805 BOOL is_auto_login,
806 char *errmsg,
807 int errmsg_len)
808 {
809 Key *result = NULL;
810 EVP_PKEY *pk = NULL;
811 unsigned long err = 0;
812 int i, len, len2;
813 char *encname = NULL, *comment = NULL, *private_mac = NULL;
814 buffer_t *pubkey = NULL, *prikey = 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_init_SSH2(cipher_ctx, key, 32, iv, 16, CIPHER_DECRYPT, EVP_aes_256_cbc(), 0, 0, pvar);
962 len = buffer_len(prikey);
963 decrypted = (char *)malloc(len);
964 ret = EVP_Cipher(cipher_ctx, decrypted, prikey->buf, len);
965 if (ret == 0) {
966 strncpy_s(errmsg, errmsg_len, "Key decrypt error", _TRUNCATE);
967 free(decrypted);
968 cipher_free_SSH2(cipher_ctx);
969 goto error;
970 }
971 buffer_clear(prikey);
972 buffer_append(prikey, decrypted, len);
973 free(decrypted);
974 cipher_free_SSH2(cipher_ctx);
975 }
976
977 // verity MAC
978 {
979 char realmac[41];
980 unsigned char binary[20];
981 buffer_t *macdata;
982
983 macdata = buffer_init();
984
985 len = strlen(get_ssh_keytype_name(result->type));
986 buffer_put_int(macdata, len);
987 buffer_append(macdata, get_ssh_keytype_name(result->type), len);
988 len = strlen(encname);
989 buffer_put_int(macdata, len);
990 buffer_append(macdata, encname, len);
991 len = strlen(comment);
992 buffer_put_int(macdata, len);
993 buffer_append(macdata, comment, len);
994 buffer_put_int(macdata, pubkey->len);
995 buffer_append(macdata, pubkey->buf, pubkey->len);
996 buffer_put_int(macdata, prikey->len);
997 buffer_append(macdata, prikey->buf, prikey->len);
998
999 if (private_mac != NULL) {
1000 unsigned char mackey[20];
1001 char header[] = "putty-private-key-file-mac-key";
1002 const EVP_MD *md = EVP_sha1();
1003 EVP_MD_CTX *ctx = NULL;
1004
1005 ctx = EVP_MD_CTX_new();
1006 if (ctx == NULL) {
1007 goto error;
1008 }
1009
1010 EVP_DigestInit(ctx, md);
1011 EVP_DigestUpdate(ctx, header, sizeof(header)-1);
1012 len = strlen(passphrase);
1013 if (strcmp(encname, "aes256-cbc") == 0 && len > 0) {
1014 EVP_DigestUpdate(ctx, passphrase, len);
1015 }
1016 EVP_DigestFinal(ctx, mackey, &len);
1017 EVP_MD_CTX_free(ctx);
1018
1019 //hmac_sha1_simple(mackey, sizeof(mackey), macdata->buf, macdata->len, binary);
1020 {
1021 EVP_MD_CTX *ctx[2] = {0, 0};
1022 unsigned char intermediate[20];
1023 unsigned char foo[64];
1024 int i;
1025
1026 ctx[0] = EVP_MD_CTX_new();
1027 if (ctx[0] == NULL) {
1028 goto error;
1029 }
1030 ctx[1] = EVP_MD_CTX_new();
1031 if (ctx[1] == NULL) {
1032 EVP_MD_CTX_free(ctx[0]);
1033 goto error;
1034 }
1035
1036 memset(foo, 0x36, sizeof(foo));
1037 for (i = 0; i < sizeof(mackey) && i < sizeof(foo); i++) {
1038 foo[i] ^= mackey[i];
1039 }
1040 EVP_DigestInit(ctx[0], md);
1041 EVP_DigestUpdate(ctx[0], foo, sizeof(foo));
1042
1043 memset(foo, 0x5C, sizeof(foo));
1044 for (i = 0; i < sizeof(mackey) && i < sizeof(foo); i++) {
1045 foo[i] ^= mackey[i];
1046 }
1047 EVP_DigestInit(ctx[1], md);
1048 EVP_DigestUpdate(ctx[1], foo, sizeof(foo));
1049
1050 memset(foo, 0, sizeof(foo));
1051
1052 EVP_DigestUpdate(ctx[0], macdata->buf, macdata->len);
1053 EVP_DigestFinal(ctx[0], intermediate, &len);
1054
1055 EVP_DigestUpdate(ctx[1], intermediate, sizeof(intermediate));
1056 EVP_DigestFinal(ctx[1], binary, &len);
1057
1058 EVP_MD_CTX_free(ctx[0]);
1059 EVP_MD_CTX_free(ctx[1]);
1060 }
1061
1062 memset(mackey, 0, sizeof(mackey));
1063
1064 }
1065 else {
1066 strncpy_s(errmsg, errmsg_len, "key file format error", _TRUNCATE);
1067 buffer_free(macdata);
1068 goto error;
1069 }
1070
1071 buffer_free(macdata);
1072
1073 for (i=0; i<20; i++) {
1074 sprintf(realmac + 2*i, "%02x", binary[i]);
1075 }
1076
1077 if (strcmp(private_mac, realmac) != 0) {
1078 if (strcmp(encname, "aes256-cbc") == 0) {
1079 strncpy_s(errmsg, errmsg_len, "wrong passphrase", _TRUNCATE);
1080 *invalid_passphrase = TRUE;
1081 goto error;
1082 }
1083 else {
1084 strncpy_s(errmsg, errmsg_len, "MAC verify failed", _TRUNCATE);
1085 goto error;
1086 }
1087 }
1088 }
1089
1090 switch (result->type) {
1091 case KEY_RSA:
1092 {
1093 char *pubkey_type, *pub, *pri;
1094 BIGNUM *e, *n, *d, *iqmp, *p, *q;
1095
1096 pub = pubkey->buf;
1097 pri = prikey->buf;
1098 pubkey_type = buffer_get_string(&pub, NULL);
1099 if (strcmp(pubkey_type, "ssh-rsa") != 0) {
1100 strncpy_s(errmsg, errmsg_len, "key type error", _TRUNCATE);
1101 free(pubkey_type);
1102 goto error;
1103 }
1104 free(pubkey_type);
1105
1106 result->rsa = RSA_new();
1107 if (result->rsa == NULL) {
1108 strncpy_s(errmsg, errmsg_len, "key init error", _TRUNCATE);
1109 goto error;
1110 }
1111 e = BN_new();
1112 n = BN_new();
1113 d = BN_new();
1114 RSA_set0_key(result->rsa, n, e, d);
1115 p = BN_new();
1116 q = BN_new();
1117 RSA_set0_factors(result->rsa, p, q);
1118 iqmp = BN_new();
1119 RSA_set0_crt_params(result->rsa, NULL, NULL, iqmp);
1120 if (e == NULL ||
1121 n == NULL ||
1122 d == NULL ||
1123 p == NULL ||
1124 q == NULL ||
1125 iqmp == NULL) {
1126 strncpy_s(errmsg, errmsg_len, "key init error", _TRUNCATE);
1127 goto error;
1128 }
1129
1130 buffer_get_bignum2(&pub, e);
1131 buffer_get_bignum2(&pub, n);
1132
1133 buffer_get_bignum2(&pri, d);
1134 buffer_get_bignum2(&pri, p);
1135 buffer_get_bignum2(&pri, q);
1136 buffer_get_bignum2(&pri, iqmp);
1137
1138 break;
1139 }
1140 case KEY_DSA:
1141 {
1142 char *pubkey_type, *pub, *pri;
1143 BIGNUM *p, *q, *g, *pub_key, *priv_key;
1144
1145 pub = pubkey->buf;
1146 pri = prikey->buf;
1147 pubkey_type = buffer_get_string(&pub, NULL);
1148 if (strcmp(pubkey_type, "ssh-dss") != 0) {
1149 strncpy_s(errmsg, errmsg_len, "key type error", _TRUNCATE);
1150 free(pubkey_type);
1151 goto error;
1152 }
1153 free(pubkey_type);
1154
1155 result->dsa = DSA_new();
1156 if (result->dsa == NULL) {
1157 strncpy_s(errmsg, errmsg_len, "key init error", _TRUNCATE);
1158 goto error;
1159 }
1160 p = BN_new();
1161 q = BN_new();
1162 g = BN_new();
1163 DSA_set0_pqg(result->dsa, p, q, g);
1164 pub_key = BN_new();
1165 priv_key = BN_new();
1166 DSA_set0_key(result->dsa, pub_key, priv_key);
1167 if (p == NULL ||
1168 q == NULL ||
1169 g == NULL ||
1170 pub_key == NULL ||
1171 priv_key == NULL) {
1172 strncpy_s(errmsg, errmsg_len, "key init error", _TRUNCATE);
1173 goto error;
1174 }
1175
1176 buffer_get_bignum2(&pub, p);
1177 buffer_get_bignum2(&pub, q);
1178 buffer_get_bignum2(&pub, g);
1179 buffer_get_bignum2(&pub, pub_key);
1180
1181 buffer_get_bignum2(&pri, priv_key);
1182
1183 break;
1184 }
1185 case KEY_ECDSA256:
1186 case KEY_ECDSA384:
1187 case KEY_ECDSA521:
1188 {
1189 char *pubkey_type, *pub, *pri;
1190 int success = 0;
1191 unsigned int nid;
1192 char *curve = NULL;
1193 ssh_keytype skt;
1194 BIGNUM *exponent = NULL;
1195 EC_POINT *q = NULL;
1196
1197 pub = pubkey->buf;
1198 pri = prikey->buf;
1199 pubkey_type = buffer_get_string(&pub, NULL);
1200 if ((result->type == KEY_ECDSA256 && strcmp(pubkey_type, "ecdsa-sha2-nistp256") != 0) ||
1201 (result->type == KEY_ECDSA384 && strcmp(pubkey_type, "ecdsa-sha2-nistp384") != 0) ||
1202 (result->type == KEY_ECDSA521 && strcmp(pubkey_type, "ecdsa-sha2-nistp521") != 0)) {
1203 strncpy_s(errmsg, errmsg_len, "key type error", _TRUNCATE);
1204 free(pubkey_type);
1205 goto error;
1206 }
1207 free(pubkey_type);
1208
1209 nid = keytype_to_cipher_nid(result->type);
1210 curve = buffer_get_string(&pub, NULL);
1211 skt = key_curve_name_to_keytype(curve);
1212 if (nid != keytype_to_cipher_nid(skt))
1213 goto ecdsa_error;
1214
1215 if ((result->ecdsa = EC_KEY_new_by_curve_name(nid)) == NULL)
1216 goto ecdsa_error;
1217 if ((q = EC_POINT_new(EC_KEY_get0_group(result->ecdsa))) == NULL)
1218 goto ecdsa_error;
1219 if ((exponent = BN_new()) == NULL)
1220 goto ecdsa_error;
1221
1222 buffer_get_ecpoint(&pub, EC_KEY_get0_group(result->ecdsa), q);
1223 buffer_get_bignum2(&pri, exponent);
1224 if (EC_KEY_set_public_key(result->ecdsa, q) != 1)
1225 goto ecdsa_error;
1226 if (EC_KEY_set_private_key(result->ecdsa, exponent) != 1)
1227 goto ecdsa_error;
1228 if (key_ec_validate_public(EC_KEY_get0_group(result->ecdsa),
1229 EC_KEY_get0_public_key(result->ecdsa)) != 0)
1230 goto ecdsa_error;
1231 if (key_ec_validate_private(result->ecdsa) != 0)
1232 goto ecdsa_error;
1233
1234 success = 1;
1235
1236 ecdsa_error:
1237 free(curve);
1238 if (exponent)
1239 BN_clear_free(exponent);
1240 if (q)
1241 EC_POINT_free(q);
1242 if (success == 0)
1243 goto error;
1244
1245 break;
1246 }
1247 case KEY_ED25519:
1248 {
1249 char *pubkey_type, *pub, *pri;
1250 unsigned int pklen, sklen;
1251 char *sk;
1252 pub = pubkey->buf;
1253 pri = prikey->buf;
1254 pubkey_type = buffer_get_string(&pub, NULL);
1255 if (strcmp(pubkey_type, "ssh-ed25519") != 0) {
1256 strncpy_s(errmsg, errmsg_len, "key type error", _TRUNCATE);
1257 free(pubkey_type);
1258 goto error;
1259 }
1260 free(pubkey_type);
1261
1262 result->ed25519_pk = buffer_get_string(&pub, &pklen);
1263 sk = buffer_get_string(&pri, &sklen);
1264 result->ed25519_sk = malloc(pklen + sklen + 1);
1265 memcpy(result->ed25519_sk, sk, sklen);
1266 memcpy(result->ed25519_sk + sklen, result->ed25519_pk, pklen);
1267 result->ed25519_sk[sklen + pklen] = '\0';
1268 free(sk);
1269
1270 if (pklen != ED25519_PK_SZ)
1271 goto error;
1272 if (sklen + pklen != ED25519_SK_SZ)
1273 goto error;
1274
1275 break;
1276 }
1277 default:
1278 strncpy_s(errmsg, errmsg_len, "key type error", _TRUNCATE);
1279 goto error;
1280 break;
1281 }
1282
1283 fclose(fp);
1284
1285 if (encname != NULL)
1286 free(encname);
1287
1288 if (comment != NULL)
1289 free(comment);
1290
1291 if (pubkey != NULL)
1292 buffer_free(pubkey);
1293
1294 if (prikey != NULL)
1295 buffer_free(prikey);
1296
1297 if (private_mac != NULL)
1298 free(private_mac);
1299
1300 return (result);
1301
1302 error:
1303 if (result != NULL)
1304 key_free(result);
1305
1306 if (fp != NULL)
1307 fclose(fp);
1308
1309 if (encname != NULL)
1310 free(encname);
1311
1312 if (comment != NULL)
1313 free(comment);
1314
1315 if (pubkey != NULL)
1316 buffer_free(pubkey);
1317
1318 if (prikey != NULL)
1319 buffer_free(prikey);
1320
1321 if (private_mac != NULL)
1322 free(private_mac);
1323
1324 return (NULL);
1325 }
1326
1327 // SECSH(ssh.com) format
1328 /*
1329 * Code to read ssh.com private keys.
1330 *
1331 * "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----"
1332 * "Comment:..."
1333 * "Base64..."
1334 * "---- END SSH2 ENCRYPTED PRIVATE KEY ----"
1335 *
1336 * Body of key data
1337 *
1338 * - uint32 0x3f6ff9eb (magic number)
1339 * - uint32 size (total blob size)
1340 * - string key-type (see below)
1341 * - string cipher-type (tells you if key is encrypted)
1342 * - string encrypted-blob
1343 *
1344 * The key type strings are ghastly. The RSA key I looked at had a type string of
1345 *
1346 * `if-modn{sign{rsa-pkcs1-sha1},encrypt{rsa-pkcs1v2-oaep}}'
1347 * `dl-modp{sign{dsa-nist-sha1},dh{plain}}'
1348 * `ec-modp'
1349 *
1350 * The encryption. The cipher-type string appears to be either
1351 *
1352 * `none'
1353 * `3des-cbc'
1354 *
1355 * The payload blob, for an RSA key, contains:
1356 * - mpint e
1357 * - mpint d
1358 * - mpint n (yes, the public and private stuff is intermixed)
1359 * - mpint u (presumably inverse of p mod q)
1360 * - mpint p (p is the smaller prime)
1361 * - mpint q (q is the larger)
1362 *
1363 * For a DSA key, the payload blob contains:
1364 * - uint32 0
1365 * - mpint p
1366 * - mpint g
1367 * - mpint q
1368 * - mpint y
1369 * - mpint x
1370 *
1371 * For a ECDSA key, the payload blob contains:
1372 * - uint32 1
1373 * - string [identifier] ("nistp256" or "nistp384" or "nistp521")
1374 * - mpint n
1375 */
1376 Key *read_SSH2_SECSH_private_key(PTInstVar pvar,
1377 FILE * fp,
1378 char * passphrase,
1379 BOOL * invalid_passphrase,
1380 BOOL is_auto_login,
1381 char *errmsg,
1382 int errmsg_len)
1383 {
1384 Key *result = NULL;
1385 unsigned long err = 0;
1386 int i, len2;
1387 unsigned int len;
1388 int encflag;
1389 char *encname = NULL;
1390 buffer_t *blob = NULL, *blob2 = NULL;
1391
1392 result = (Key *)malloc(sizeof(Key));
1393 ZeroMemory(result, sizeof(Key));
1394 result->type = KEY_NONE;
1395 result->rsa = NULL;
1396 result->dsa = NULL;
1397 result->ecdsa = NULL;
1398
1399 blob = buffer_init();
1400 blob2 = buffer_init();
1401
1402 // parse keyfile & decode blob
1403 {
1404 char line[200], buf[100];
1405 BIO *bmem, *b64, *chain;
1406 int st = 0;
1407
1408 b64 = BIO_new(BIO_f_base64());
1409 bmem = BIO_new(BIO_s_mem());
1410
1411 while (fgets(line, sizeof(line), fp) != NULL) {
1412 if (strncmp(line, "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----", strlen("---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----")) == 0) {
1413 if (st == 0) {
1414 st = 1;
1415 continue;
1416 }
1417 else {
1418 break;
1419 }
1420 }
1421 else if (strncmp(line, "---- END SSH2 ENCRYPTED PRIVATE KEY ----", strlen("---- END SSH2 ENCRYPTED PRIVATE KEY ----")) == 0) {
1422 break;
1423 }
1424
1425 if (st == 0) {
1426 continue;
1427 }
1428
1429 if (strchr(line, ':') != NULL) {
1430 if (st == 1) {
1431 continue;
1432 }
1433 strncpy_s(errmsg, errmsg_len, "header found in body of key data", _TRUNCATE);
1434 BIO_free_all(bmem);
1435 goto error;
1436 }
1437 else if (st == 1) {
1438 st = 2;
1439 }
1440
1441 BIO_write(bmem, line, strlen(line));
1442 }
1443
1444 BIO_flush(bmem);
1445 chain = BIO_push(b64, bmem);
1446 BIO_set_mem_eof_return(chain, 0);
1447 while ((len2 = BIO_read(chain, buf, sizeof(buf))) > 0) {
1448 buffer_append(blob, buf, len2);
1449 }
1450 BIO_free_all(chain);
1451 buffer_rewind(blob);
1452 }
1453
1454 if (blob->len < 8) {
1455 strncpy_s(errmsg, errmsg_len, "key body not present", _TRUNCATE);
1456 goto error;
1457 }
1458 i = buffer_get_int(blob);
1459 if (i != 0x3f6ff9eb) {
1460 strncpy_s(errmsg, errmsg_len, "magic number error", _TRUNCATE);
1461 goto error;
1462 }
1463 len = buffer_get_int(blob);
1464 if (len == 0 || len > blob->len) {
1465 strncpy_s(errmsg, errmsg_len, "body size error", _TRUNCATE);
1466 goto error;
1467 }
1468
1469 len = buffer_get_int(blob);
1470 if (strncmp(blob->buf + blob->offset, "if-modn{sign{rsa", strlen("if-modn{sign{rsa") - 1) == 0) {
1471 result->type = KEY_RSA;
1472 }
1473 else if (strncmp(blob->buf + blob->offset, "dl-modp{sign{dsa", strlen("dl-modp{sign{dsa") - 1) == 0) {
1474 result->type = KEY_DSA;
1475 }
1476 else if (strncmp(blob->buf + blob->offset, "ec-modp", strlen("ec-modp") - 1) == 0) {
1477 result->type = KEY_ECDSA256;
1478 }
1479 else {
1480 strncpy_s(errmsg, errmsg_len, "unknown key type", _TRUNCATE);
1481 goto error;
1482 }
1483 buffer_consume(blob, len);
1484
1485 len = buffer_get_int(blob);
1486 encname = (char *)malloc(len + 1);
1487 strncpy_s(encname, len + 1, blob->buf + blob->offset, _TRUNCATE);
1488 if (strcmp(encname, "3des-cbc") == 0) {
1489 encflag = 1;
1490 }
1491 else if (strcmp(encname, "none") == 0) {
1492 encflag = 0;
1493 }
1494 else {
1495 strncpy_s(errmsg, errmsg_len, "unknown encryption type", _TRUNCATE);
1496 goto error;
1497 }
1498 buffer_consume(blob, len);
1499
1500 len = buffer_get_int(blob);
1501 if (len > (blob->len - blob->offset)) {
1502 strncpy_s(errmsg, errmsg_len, "body size error", _TRUNCATE);
1503 goto error;
1504 }
1505
1506 // decrypt privkey with 3des-cbc
1507 if (strcmp(encname, "3des-cbc") == 0) {
1508 MD5_CTX md;
1509 unsigned char key[32], iv[16];
1510 EVP_CIPHER_CTX *cipher_ctx = NULL;
1511 char *decrypted = NULL;
1512 int ret;
1513
1514 cipher_ctx = EVP_CIPHER_CTX_new();
1515 if (cipher_ctx == NULL) {
1516 strncpy_s(errmsg, errmsg_len, "Out of memory: EVP_CIPHER_CTX_new()", _TRUNCATE);
1517 goto error;
1518 }
1519
1520 MD5_Init(&md);
1521 MD5_Update(&md, passphrase, strlen(passphrase));
1522 MD5_Final(key, &md);
1523
1524 MD5_Init(&md);
1525 MD5_Update(&md, passphrase, strlen(passphrase));
1526 MD5_Update(&md, key, 16);
1527 MD5_Final(key + 16, &md);
1528
1529 memset(iv, 0, sizeof(iv));
1530
1531 // decrypt
1532 cipher_init_SSH2(cipher_ctx, key, 24, iv, 8, CIPHER_DECRYPT, EVP_des_ede3_cbc(), 0, 0, pvar);
1533 decrypted = (char *)malloc(len);
1534 ret = EVP_Cipher(cipher_ctx, decrypted, blob->buf + blob->offset, len);
1535 if (ret == 0) {
1536 strncpy_s(errmsg, errmsg_len, "Key decrypt error", _TRUNCATE);
1537 cipher_free_SSH2(cipher_ctx);
1538 goto error;
1539 }
1540 buffer_append(blob2, decrypted, len);
1541 free(decrypted);
1542 cipher_free_SSH2(cipher_ctx);
1543
1544 *invalid_passphrase = TRUE;
1545 }
1546 else { // none
1547 buffer_append(blob2, blob->buf + blob->offset, len);
1548 }
1549 buffer_rewind(blob2);
1550
1551 len = buffer_get_int(blob2);
1552 if (len <= 0 || len > (blob2->len - blob2->offset)) {
1553 strncpy_s(errmsg, errmsg_len, "blob size error", _TRUNCATE);
1554 goto error;
1555 }
1556
1557 switch (result->type) {
1558 case KEY_RSA:
1559 {
1560 BIGNUM *e, *n, *d, *iqmp, *p, *q;
1561
1562 result->rsa = RSA_new();
1563 if (result->rsa == NULL) {
1564 strncpy_s(errmsg, errmsg_len, "key init error", _TRUNCATE);
1565 goto error;
1566 }
1567 e = BN_new();
1568 n = BN_new();
1569 d = BN_new();
1570 RSA_set0_key(result->rsa, n, e, d);
1571 p = BN_new();
1572 q = BN_new();
1573 RSA_set0_factors(result->rsa, p, q);
1574 iqmp = BN_new();
1575 RSA_set0_crt_params(result->rsa, NULL, NULL, iqmp);
1576 if (e == NULL ||
1577 n == NULL ||
1578 d == NULL ||
1579 p == NULL ||
1580 q == NULL ||
1581 iqmp == NULL) {
1582 strncpy_s(errmsg, errmsg_len, "key init error", _TRUNCATE);
1583 goto error;
1584 }
1585
1586 buffer_get_bignum_SECSH(blob2, e);
1587 buffer_get_bignum_SECSH(blob2, d);
1588 buffer_get_bignum_SECSH(blob2, n);
1589 buffer_get_bignum_SECSH(blob2, iqmp);
1590 buffer_get_bignum_SECSH(blob2, p);
1591 buffer_get_bignum_SECSH(blob2, q);
1592
1593 break;
1594 }
1595 case KEY_DSA:
1596 {
1597 int param;
1598 BIGNUM *p, *q, *g, *pub_key, *priv_key;
1599
1600 result->dsa = DSA_new();
1601 if (result->dsa == NULL) {
1602 strncpy_s(errmsg, errmsg_len, "key init error", _TRUNCATE);
1603 goto error;
1604 }
1605 p = BN_new();
1606 q = BN_new();
1607 g = BN_new();
1608 DSA_set0_pqg(result->dsa, p, q, g);
1609 pub_key = BN_new();
1610 priv_key = BN_new();
1611 DSA_set0_key(result->dsa, pub_key, priv_key);
1612 if (p == NULL ||
1613 q == NULL ||
1614 g == NULL ||
1615 pub_key == NULL ||
1616 priv_key == NULL) {
1617 strncpy_s(errmsg, errmsg_len, "key init error", _TRUNCATE);
1618 goto error;
1619 }
1620
1621 param = buffer_get_int(blob2);
1622 if (param != 0) {
1623 strncpy_s(errmsg, errmsg_len, "predefined DSA parameters not supported", _TRUNCATE);
1624 goto error;
1625 }
1626 buffer_get_bignum_SECSH(blob2, p);
1627 buffer_get_bignum_SECSH(blob2, g);
1628 buffer_get_bignum_SECSH(blob2, q);
1629 buffer_get_bignum_SECSH(blob2, pub_key);
1630 buffer_get_bignum_SECSH(blob2, priv_key);
1631
1632 break;
1633 }
1634 case KEY_ECDSA256:
1635 {
1636 unsigned int dummy, nid;
1637 int success = 0;
1638 char *curve = NULL;
1639 BIGNUM *exponent = NULL;
1640 EC_POINT *q = NULL;
1641 BN_CTX *ctx = NULL;
1642
1643 dummy = buffer_get_int(blob2);
1644 curve = buffer_get_string_msg(blob2, NULL);
1645
1646 if (strncmp(curve, "nistp256", strlen("nistp256")) == 0) {
1647 result->type = KEY_ECDSA256;
1648 }
1649 else if (strncmp(curve, "nistp384", strlen("nistp384")) == 0) {
1650 result->type = KEY_ECDSA384;
1651 }
1652 else if (strncmp(curve, "nistp521", strlen("nistp521")) == 0) {
1653 result->type = KEY_ECDSA521;
1654 }
1655 else {
1656 strncpy_s(errmsg, errmsg_len, "key type error", _TRUNCATE);
1657 goto error;
1658 }
1659
1660 nid = keytype_to_cipher_nid(result->type);
1661 if ((result->ecdsa = EC_KEY_new_by_curve_name(nid)) == NULL)
1662 goto ecdsa_error;
1663 if ((q = EC_POINT_new(EC_KEY_get0_group(result->ecdsa))) == NULL)
1664 goto ecdsa_error;
1665 if ((exponent = BN_new()) == NULL)
1666 goto ecdsa_error;
1667
1668 buffer_get_bignum_SECSH(blob2, exponent);
1669 if (EC_KEY_set_private_key(result->ecdsa, exponent) != 1)
1670 goto ecdsa_error;
1671 if (key_ec_validate_private(result->ecdsa) != 0)
1672 goto ecdsa_error;
1673
1674 // �t�@�C�����������������i�[�������������������J�����v�Z��������
1675 if ((ctx = BN_CTX_new()) == NULL)
1676 goto ecdsa_error;
1677 if (!EC_POINT_mul(EC_KEY_get0_group(result->ecdsa), q, exponent, NULL, NULL, ctx)) {
1678 goto ecdsa_error;
1679 }
1680 if (EC_KEY_set_public_key(result->ecdsa, q) != 1)
1681 goto ecdsa_error;
1682 if (key_ec_validate_public(EC_KEY_get0_group(result->ecdsa),
1683 EC_KEY_get0_public_key(result->ecdsa)) != 0)
1684 goto ecdsa_error;
1685
1686 success = 1;
1687
1688 ecdsa_error:
1689 free(curve);
1690 if (exponent)
1691 BN_clear_free(exponent);
1692 if (q)
1693 EC_POINT_free(q);
1694 if (ctx)
1695 BN_CTX_free(ctx);
1696 if (success == 0)
1697 goto error;
1698
1699 break;
1700 }
1701 default:
1702 strncpy_s(errmsg, errmsg_len, "key type error", _TRUNCATE);
1703 goto error;
1704 break;
1705 }
1706
1707 *invalid_passphrase = FALSE;
1708
1709 fclose(fp);
1710
1711 if (encname != NULL)
1712 free(encname);
1713
1714 if (blob != NULL)
1715 buffer_free(blob);
1716
1717 if (blob2 != NULL)
1718 buffer_free(blob2);
1719
1720 return (result);
1721
1722 error:
1723 if (result != NULL)
1724 key_free(result);
1725
1726 if (fp != NULL)
1727 fclose(fp);
1728
1729 if (encname != NULL)
1730 free(encname);
1731
1732 if (blob != NULL)
1733 buffer_free(blob);
1734
1735 if (blob2 != NULL)
1736 buffer_free(blob2);
1737
1738 return (NULL);
1739 }
1740
1741 ssh2_keyfile_type get_ssh2_keytype(char *relative_name,
1742 FILE **fp,
1743 char *errmsg,
1744 int errmsg_len) {
1745 ssh2_keyfile_type ret = SSH2_KEYFILE_TYPE_NONE;
1746 char filename[2048];
1747 char line[200];
1748 int i;
1749
1750 // �����p�X�������p�X�����������B�������������������A�u�h�b�g���n�����v�f�B���N�g����
1751 // �����t�@�C�������������������������B(2005.2.7 yutaka)
1752 get_teraterm_dir_relative_name(filename, sizeof(filename),
1753 relative_name);
1754
1755 *fp = fopen(filename, "r");
1756 if (*fp == NULL) {
1757 strncpy_s(errmsg, errmsg_len, strerror(errno), _TRUNCATE);
1758 return ret;
1759 }
1760
1761 while (fgets(line, sizeof(line), *fp) != NULL) {
1762 for (i=0; keyfile_headers[i].type != SSH2_KEYFILE_TYPE_NONE; i++) {
1763 if ( strncmp(line, keyfile_headers[i].header, strlen(keyfile_headers[i].header)) == 0) {
1764 ret = keyfile_headers[i].type;
1765 break;
1766 }
1767 }
1768 if (ret != SSH2_KEYFILE_TYPE_NONE)
1769 break;
1770 }
1771
1772 if (ret == SSH2_KEYFILE_TYPE_NONE) {
1773 strncpy_s(errmsg, errmsg_len, "Unknown key file type.", _TRUNCATE);
1774 fseek(*fp, 0, SEEK_SET);
1775 return ret;
1776 }
1777
1778 fseek(*fp, 0, SEEK_SET);
1779 return ret;
1780 }

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