Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/ttssh2/ttxssh/keyfiles.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 9255 - (show annotations) (download) (as text)
Wed May 19 14:11:26 2021 UTC (2 years, 9 months ago) by nmaya
File MIME type: text/x-csrc
File size: 51019 byte(s)
SSH2 暗号化方式 chacha20-poly1305@openssh.com をサポート

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

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