Develop and Download Open Source Software

Browse Subversion Repository

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 9211 - (hide annotations) (download) (as text)
Sat Apr 17 09:52:01 2021 UTC (2 years, 11 months ago) by nmaya
File MIME type: text/x-csrc
File size: 50300 byte(s)
cipher_init_SSH2() に渡すのを EVP_CIPHER_CTX から sshcipher_ctx に変更

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

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