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 10618 - (show annotations) (download) (as text)
Fri Mar 3 15:15:16 2023 UTC (12 months ago) by zmatsuo
File MIME type: text/x-csrc
File size: 52253 byte(s)
ttxsshで tttset.UIMsg[] ではなく TInstVar.UIMsg[] を使用するよう修正

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

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