Develop and Download Open Source Software

Browse Subversion Repository

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6817 - (show annotations) (download) (as text)
Fri Jun 23 14:58:54 2017 UTC (6 years, 9 months ago) by maya
Original Path: trunk/ttssh2/ttxssh/key.c
File MIME type: text/x-csrc
File size: 61099 byte(s)
関数を移動
1 /*
2 (C) 2011 TeraTerm Project
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
7
8 Redistributions of source code must retain the above copyright notice, this list of
9 conditions and the following disclaimer.
10
11 Redistributions in binary form must reproduce the above copyright notice, this list
12 of conditions and the following disclaimer in the documentation and/or other materials
13 provided with the distribution.
14
15 The name of Robert O'Callahan may not be used to endorse or promote products derived from
16 this software without specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
19 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28 #include "key.h"
29 #include "resource.h"
30
31 #include <openssl/rsa.h>
32 #include <openssl/dsa.h>
33 #include <openssl/ecdsa.h>
34 #include <openssl/buffer.h>
35
36 #define INTBLOB_LEN 20
37 #define SIGBLOB_LEN (2*INTBLOB_LEN)
38
39
40 struct hostkeys_update_ctx {
41 /* The hostname and (optionally) IP address string for the server */
42 char *host_str, *ip_str;
43
44 /*
45 * Keys received from the server and a flag for each indicating
46 * whether they already exist in known_hosts.
47 * keys_seen is filled in by hostkeys_find() and later (for new
48 * keys) by client_global_hostkeys_private_confirm().
49 */
50 Key **keys;
51 int *keys_seen;
52 size_t nkeys;
53
54 size_t nnew;
55
56 /*
57 * Keys that are in known_hosts, but were not present in the update
58 * from the server (i.e. scheduled to be deleted).
59 * Filled in by hostkeys_find().
60 */
61 Key **old_keys;
62 size_t nold;
63 };
64
65
66 //////////////////////////////////////////////////////////////////////////////
67 //
68 // Key verify function
69 //
70 //////////////////////////////////////////////////////////////////////////////
71
72 //
73 // DSS
74 //
75
76 int ssh_dss_verify(DSA *key,
77 u_char *signature, u_int signaturelen,
78 u_char *data, u_int datalen)
79 {
80 DSA_SIG *sig;
81 const EVP_MD *evp_md = EVP_sha1();
82 EVP_MD_CTX md;
83 unsigned char digest[EVP_MAX_MD_SIZE], *sigblob;
84 unsigned int len, dlen;
85 int ret;
86 char *ptr;
87
88 OpenSSL_add_all_digests();
89
90 if (key == NULL) {
91 return -2;
92 }
93
94 ptr = signature;
95
96 // step1
97 if (signaturelen == 0x28) {
98 // workaround for SSH-2.0-2.0* and SSH-2.0-2.1* (2006.11.18 maya)
99 ptr -= 4;
100 }
101 else {
102 len = get_uint32_MSBfirst(ptr);
103 ptr += 4;
104 if (strncmp("ssh-dss", ptr, len) != 0) {
105 return -3;
106 }
107 ptr += len;
108 }
109
110 // step2
111 len = get_uint32_MSBfirst(ptr);
112 ptr += 4;
113 sigblob = ptr;
114 ptr += len;
115
116 if (len != SIGBLOB_LEN) {
117 return -4;
118 }
119
120 /* parse signature */
121 if ((sig = DSA_SIG_new()) == NULL)
122 return -5;
123 if ((sig->r = BN_new()) == NULL)
124 return -6;
125 if ((sig->s = BN_new()) == NULL)
126 return -7;
127 BN_bin2bn(sigblob, INTBLOB_LEN, sig->r);
128 BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s);
129
130 /* sha1 the data */
131 EVP_DigestInit(&md, evp_md);
132 EVP_DigestUpdate(&md, data, datalen);
133 EVP_DigestFinal(&md, digest, &dlen);
134
135 ret = DSA_do_verify(digest, dlen, sig, key);
136 SecureZeroMemory(digest, sizeof(digest));
137
138 DSA_SIG_free(sig);
139
140 return ret;
141 }
142
143
144 //
145 // RSA
146 //
147
148 /*
149 * See:
150 * http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/
151 * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.asn
152 */
153 /*
154 * id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
155 * oiw(14) secsig(3) algorithms(2) 26 }
156 */
157 static const u_char id_sha1[] = {
158 0x30, 0x21, /* type Sequence, length 0x21 (33) */
159 0x30, 0x09, /* type Sequence, length 0x09 */
160 0x06, 0x05, /* type OID, length 0x05 */
161 0x2b, 0x0e, 0x03, 0x02, 0x1a, /* id-sha1 OID */
162 0x05, 0x00, /* NULL */
163 0x04, 0x14 /* Octet string, length 0x14 (20), followed by sha1 hash */
164 };
165 /*
166 * id-md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840)
167 * rsadsi(113549) digestAlgorithm(2) 5 }
168 */
169 static const u_char id_md5[] = {
170 0x30, 0x20, /* type Sequence, length 0x20 (32) */
171 0x30, 0x0c, /* type Sequence, length 0x09 */
172 0x06, 0x08, /* type OID, length 0x05 */
173 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, /* id-md5 */
174 0x05, 0x00, /* NULL */
175 0x04, 0x10 /* Octet string, length 0x10 (16), followed by md5 hash */
176 };
177
178 static int openssh_RSA_verify(int type, u_char *hash, u_int hashlen,
179 u_char *sigbuf, u_int siglen, RSA *rsa)
180 {
181 u_int ret, rsasize, oidlen = 0, hlen = 0;
182 int len;
183 const u_char *oid = NULL;
184 u_char *decrypted = NULL;
185
186 ret = 0;
187 switch (type) {
188 case NID_sha1:
189 oid = id_sha1;
190 oidlen = sizeof(id_sha1);
191 hlen = 20;
192 break;
193 case NID_md5:
194 oid = id_md5;
195 oidlen = sizeof(id_md5);
196 hlen = 16;
197 break;
198 default:
199 goto done;
200 break;
201 }
202 if (hashlen != hlen) {
203 //error("bad hashlen");
204 goto done;
205 }
206 rsasize = RSA_size(rsa);
207 if (siglen == 0 || siglen > rsasize) {
208 //error("bad siglen");
209 goto done;
210 }
211 decrypted = malloc(rsasize);
212 if (decrypted == NULL)
213 return 1; // error
214
215 if ((len = RSA_public_decrypt(siglen, sigbuf, decrypted, rsa,
216 RSA_PKCS1_PADDING)) < 0) {
217 //error("RSA_public_decrypt failed: %s",
218 // ERR_error_string(ERR_get_error(), NULL));
219 goto done;
220 }
221 if (len != hlen + oidlen) {
222 //error("bad decrypted len: %d != %d + %d", len, hlen, oidlen);
223 goto done;
224 }
225 if (memcmp(decrypted, oid, oidlen) != 0) {
226 //error("oid mismatch");
227 goto done;
228 }
229 if (memcmp(decrypted + oidlen, hash, hlen) != 0) {
230 //error("hash mismatch");
231 goto done;
232 }
233 ret = 1;
234 done:
235 if (decrypted)
236 free(decrypted);
237 return ret;
238 }
239
240 int ssh_rsa_verify(RSA *key,
241 u_char *signature, u_int signaturelen,
242 u_char *data, u_int datalen)
243 {
244 const EVP_MD *evp_md;
245 EVP_MD_CTX md;
246 // char *ktype;
247 u_char digest[EVP_MAX_MD_SIZE], *sigblob;
248 u_int len, dlen, modlen;
249 // int rlen, ret, nid;
250 int ret, nid;
251 char *ptr;
252
253 OpenSSL_add_all_digests();
254
255 if (key == NULL) {
256 return -2;
257 }
258 if (BN_num_bits(key->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
259 return -3;
260 }
261 //debug_print(41, signature, signaturelen);
262 ptr = signature;
263
264 // step1
265 len = get_uint32_MSBfirst(ptr);
266 ptr += 4;
267 if (strncmp("ssh-rsa", ptr, len) != 0) {
268 return -4;
269 }
270 ptr += len;
271
272 // step2
273 len = get_uint32_MSBfirst(ptr);
274 ptr += 4;
275 sigblob = ptr;
276 ptr += len;
277 #if 0
278 rlen = get_uint32_MSBfirst(ptr);
279 if (rlen != 0) {
280 return -1;
281 }
282 #endif
283
284 /* RSA_verify expects a signature of RSA_size */
285 modlen = RSA_size(key);
286 if (len > modlen) {
287 return -5;
288
289 } else if (len < modlen) {
290 u_int diff = modlen - len;
291 sigblob = realloc(sigblob, modlen);
292 memmove(sigblob + diff, sigblob, len);
293 memset(sigblob, 0, diff);
294 len = modlen;
295 }
296
297 /* sha1 the data */
298 // nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1;
299 nid = NID_sha1;
300 if ((evp_md = EVP_get_digestbynid(nid)) == NULL) {
301 //error("ssh_rsa_verify: EVP_get_digestbynid %d failed", nid);
302 return -6;
303 }
304 EVP_DigestInit(&md, evp_md);
305 EVP_DigestUpdate(&md, data, datalen);
306 EVP_DigestFinal(&md, digest, &dlen);
307
308 ret = openssh_RSA_verify(nid, digest, dlen, sigblob, len, key);
309
310 SecureZeroMemory(digest, sizeof(digest));
311 SecureZeroMemory(sigblob, len);
312 //free(sigblob);
313 //debug("ssh_rsa_verify: signature %scorrect", (ret==0) ? "in" : "");
314
315 return ret;
316 }
317
318 int ssh_ecdsa_verify(EC_KEY *key, ssh_keytype keytype,
319 u_char *signature, u_int signaturelen,
320 u_char *data, u_int datalen)
321 {
322 ECDSA_SIG *sig;
323 const EVP_MD *evp_md;
324 EVP_MD_CTX md;
325 unsigned char digest[EVP_MAX_MD_SIZE], *sigblob;
326 unsigned int len, dlen;
327 int ret, nid = NID_undef;
328 char *ptr;
329
330 OpenSSL_add_all_digests();
331
332 if (key == NULL) {
333 return -2;
334 }
335
336 ptr = signature;
337
338 len = get_uint32_MSBfirst(ptr);
339 ptr += 4;
340 if (strncmp(get_ssh_keytype_name(keytype), ptr, len) != 0) {
341 return -3;
342 }
343 ptr += len;
344
345 len = get_uint32_MSBfirst(ptr);
346 ptr += 4;
347 sigblob = ptr;
348 ptr += len;
349
350 /* parse signature */
351 if ((sig = ECDSA_SIG_new()) == NULL)
352 return -4;
353 if ((sig->r = BN_new()) == NULL)
354 return -5;
355 if ((sig->s = BN_new()) == NULL)
356 return -6;
357
358 buffer_get_bignum2(&sigblob, sig->r);
359 buffer_get_bignum2(&sigblob, sig->s);
360 if (sigblob != ptr) {
361 return -7;
362 }
363
364 /* hash the data */
365 nid = keytype_to_hash_nid(keytype);
366 if ((evp_md = EVP_get_digestbynid(nid)) == NULL) {
367 return -8;
368 }
369 EVP_DigestInit(&md, evp_md);
370 EVP_DigestUpdate(&md, data, datalen);
371 EVP_DigestFinal(&md, digest, &dlen);
372
373 ret = ECDSA_do_verify(digest, dlen, sig, key);
374 SecureZeroMemory(digest, sizeof(digest));
375
376 ECDSA_SIG_free(sig);
377
378 return ret;
379 }
380
381 static int ssh_ed25519_verify(Key *key, unsigned char *signature, unsigned int signaturelen,
382 unsigned char *data, unsigned int datalen)
383 {
384 buffer_t *b;
385 char *ktype = NULL;
386 unsigned char *sigblob = NULL, *sm = NULL, *m = NULL;
387 unsigned int len;
388 unsigned long long smlen, mlen;
389 int rlen, ret;
390 char *bptr;
391
392 ret = -1;
393 b = buffer_init();
394 if (b == NULL)
395 goto error;
396
397 buffer_append(b, signature, signaturelen);
398 bptr = buffer_ptr(b);
399 ktype = buffer_get_string(&bptr, NULL);
400 if (strcmp("ssh-ed25519", ktype) != 0) {
401 goto error;
402 }
403 sigblob = buffer_get_string(&bptr, &len);
404 rlen = buffer_remain_len(b);
405 if (rlen != 0) {
406 goto error;
407 }
408 if (len > crypto_sign_ed25519_BYTES) {
409 goto error;
410 }
411
412 smlen = len + datalen;
413 sm = malloc((size_t)smlen);
414 memcpy(sm, sigblob, len);
415 memcpy(sm+len, data, datalen);
416 mlen = smlen;
417 m = malloc((size_t)mlen);
418
419 if ((ret = crypto_sign_ed25519_open(m, &mlen, sm, smlen,
420 key->ed25519_pk)) != 0) {
421 //debug2("%s: crypto_sign_ed25519_open failed: %d",
422 // __func__, ret);
423 }
424 if (ret == 0 && mlen != datalen) {
425 //debug2("%s: crypto_sign_ed25519_open "
426 // "mlen != datalen (%llu != %u)", __func__, mlen, datalen);
427 ret = -1;
428 }
429 /* XXX compare 'm' and 'data' ? */
430
431 error:
432 buffer_free(b);
433 free(ktype);
434
435 if (sigblob) {
436 SecureZeroMemory(sigblob, len);
437 free(sigblob);
438 }
439 if (sm) {
440 SecureZeroMemory(sm, (size_t)smlen);
441 free(sm);
442 }
443 if (m) {
444 SecureZeroMemory(m, (size_t)smlen); /* NB. mlen may be invalid if ret != 0 */
445 free(m);
446 }
447
448 /* translate return code carefully */
449 return (ret == 0) ? 1 : -1;
450 }
451
452 int key_verify(Key *key,
453 unsigned char *signature, unsigned int signaturelen,
454 unsigned char *data, unsigned int datalen)
455 {
456 int ret = 0;
457
458 switch (key->type) {
459 case KEY_RSA:
460 ret = ssh_rsa_verify(key->rsa, signature, signaturelen, data, datalen);
461 break;
462 case KEY_DSA:
463 ret = ssh_dss_verify(key->dsa, signature, signaturelen, data, datalen);
464 break;
465 case KEY_ECDSA256:
466 case KEY_ECDSA384:
467 case KEY_ECDSA521:
468 ret = ssh_ecdsa_verify(key->ecdsa, key->type, signature, signaturelen, data, datalen);
469 break;
470 case KEY_ED25519:
471 ret = ssh_ed25519_verify(key, signature, signaturelen, data, datalen);
472 break;
473 default:
474 return -1;
475 }
476
477 return (ret); // success
478 }
479
480 static char *copy_mp_int(char *num)
481 {
482 int len = (get_ushort16_MSBfirst(num) + 7) / 8 + 2;
483 char *result = (char *) malloc(len);
484
485 if (result != NULL) {
486 memcpy(result, num, len);
487 }
488
489 return result;
490 }
491
492 //
493 // RSA�\����������
494 //
495 RSA *duplicate_RSA(RSA *src)
496 {
497 RSA *rsa = NULL;
498
499 rsa = RSA_new();
500 if (rsa == NULL)
501 goto error;
502 rsa->n = BN_new();
503 rsa->e = BN_new();
504 if (rsa->n == NULL || rsa->e == NULL) {
505 RSA_free(rsa);
506 goto error;
507 }
508
509 // �[���R�s�[(deep copy)���s���B�����R�s�[(shallow copy)��NG�B
510 BN_copy(rsa->n, src->n);
511 BN_copy(rsa->e, src->e);
512
513 error:
514 return (rsa);
515 }
516
517
518 //
519 // DSA�\����������
520 //
521 DSA *duplicate_DSA(DSA *src)
522 {
523 DSA *dsa = NULL;
524
525 dsa = DSA_new();
526 if (dsa == NULL)
527 goto error;
528 dsa->p = BN_new();
529 dsa->q = BN_new();
530 dsa->g = BN_new();
531 dsa->pub_key = BN_new();
532 if (dsa->p == NULL ||
533 dsa->q == NULL ||
534 dsa->g == NULL ||
535 dsa->pub_key == NULL) {
536 DSA_free(dsa);
537 goto error;
538 }
539
540 // �[���R�s�[(deep copy)���s���B�����R�s�[(shallow copy)��NG�B
541 BN_copy(dsa->p, src->p);
542 BN_copy(dsa->q, src->q);
543 BN_copy(dsa->g, src->g);
544 BN_copy(dsa->pub_key, src->pub_key);
545
546 error:
547 return (dsa);
548 }
549
550 unsigned char *duplicate_ED25519_PK(unsigned char *src)
551 {
552 unsigned char *ptr = NULL;
553
554 ptr = malloc(ED25519_PK_SZ);
555 if (ptr) {
556 memcpy(ptr, src, ED25519_PK_SZ);
557 }
558 return (ptr);
559 }
560
561 BOOL key_copy(Key *dest, Key *src)
562 {
563 key_init(dest);
564 switch (src->type) {
565 case KEY_RSA1: // SSH1
566 dest->type = KEY_RSA1;
567 dest->bits = src->bits;
568 dest->exp = copy_mp_int(src->exp);
569 dest->mod = copy_mp_int(src->mod);
570 break;
571 case KEY_RSA: // SSH2 RSA
572 dest->type = KEY_RSA;
573 dest->rsa = duplicate_RSA(src->rsa);
574 break;
575 case KEY_DSA: // SSH2 DSA
576 dest->type = KEY_DSA;
577 dest->dsa = duplicate_DSA(src->dsa);
578 break;
579 case KEY_ECDSA256:
580 case KEY_ECDSA384:
581 case KEY_ECDSA521:
582 dest->type = src->type;
583 dest->ecdsa = EC_KEY_dup(src->ecdsa);
584 break;
585 case KEY_ED25519:
586 dest->type = src->type;
587 dest->ed25519_pk = duplicate_ED25519_PK(src->ed25519_pk);
588 break;
589 default:
590 return FALSE;
591 }
592 return TRUE;
593 }
594
595 char* key_fingerprint_raw(Key *k, enum digest_algorithm dgst_alg, int *dgst_raw_length)
596 {
597 const EVP_MD *md = NULL;
598 EVP_MD_CTX ctx;
599 char *blob = NULL;
600 char *retval = NULL;
601 int len = 0;
602 int nlen, elen;
603 RSA *rsa;
604
605 *dgst_raw_length = 0;
606
607 switch (dgst_alg) {
608 case SSH_DIGEST_MD5:
609 md = EVP_md5();
610 break;
611 case SSH_DIGEST_SHA1:
612 md = EVP_sha1();
613 break;
614 case SSH_DIGEST_SHA256:
615 md = EVP_sha256();
616 break;
617 default:
618 md = EVP_md5();
619 }
620
621 switch (k->type) {
622 case KEY_RSA1:
623 rsa = make_key(NULL, k->bits, k->exp, k->mod);
624 nlen = BN_num_bytes(rsa->n);
625 elen = BN_num_bytes(rsa->e);
626 len = nlen + elen;
627 blob = malloc(len);
628 if (blob == NULL) {
629 // TODO:
630 }
631 BN_bn2bin(rsa->n, blob);
632 BN_bn2bin(rsa->e, blob + nlen);
633 RSA_free(rsa);
634 break;
635
636 case KEY_DSA:
637 case KEY_RSA:
638 case KEY_ECDSA256:
639 case KEY_ECDSA384:
640 case KEY_ECDSA521:
641 case KEY_ED25519:
642 key_to_blob(k, &blob, &len);
643 break;
644
645 case KEY_UNSPEC:
646 return retval;
647 break;
648
649 default:
650 //fatal("key_fingerprint_raw: bad key type %d", dgst_alg);
651 break;
652 }
653
654 if (blob != NULL) {
655 retval = malloc(EVP_MAX_MD_SIZE);
656 if (retval == NULL) {
657 // TODO:
658 }
659 EVP_DigestInit(&ctx, md);
660 EVP_DigestUpdate(&ctx, blob, len);
661 EVP_DigestFinal(&ctx, retval, dgst_raw_length);
662 SecureZeroMemory(blob, len);
663 free(blob);
664 } else {
665 //fatal("key_fingerprint_raw: blob is null");
666 }
667 return retval;
668 }
669
670
671 const char *
672 ssh_key_type(ssh_keytype type)
673 {
674 switch (type) {
675 case KEY_RSA1:
676 return "RSA1";
677 case KEY_RSA:
678 return "RSA";
679 case KEY_DSA:
680 return "DSA";
681 case KEY_ECDSA256:
682 case KEY_ECDSA384:
683 case KEY_ECDSA521:
684 return "ECDSA";
685 case KEY_ED25519:
686 return "ED25519";
687 }
688 return "unknown";
689 }
690
691 unsigned int
692 key_size(const Key *k)
693 {
694 switch (k->type) {
695 case KEY_RSA1:
696 // SSH1�������� key->rsa �� key->dsa �� NULL �����������A�g�������B
697 return k->bits;
698 case KEY_RSA:
699 return BN_num_bits(k->rsa->n);
700 case KEY_DSA:
701 return BN_num_bits(k->dsa->p);
702 case KEY_ECDSA256:
703 return 256;
704 case KEY_ECDSA384:
705 return 384;
706 case KEY_ECDSA521:
707 return 521;
708 case KEY_ED25519:
709 return 256; /* XXX */
710 }
711 return 0;
712 }
713
714 // based on OpenSSH 7.1
715 static char *
716 key_fingerprint_b64(const char *alg, u_char *dgst_raw, u_int dgst_raw_len)
717 {
718 char *retval;
719 unsigned int i, retval_len;
720 BIO *bio, *b64;
721 BUF_MEM *bufferPtr;
722
723 retval_len = strlen(alg) + 1 + ((dgst_raw_len + 2) / 3) * 4 + 1;
724 retval = malloc(retval_len);
725 retval[0] = '\0';
726
727 strncat_s(retval, retval_len, alg, _TRUNCATE);
728 strncat_s(retval, retval_len, ":", _TRUNCATE);
729
730 b64 = BIO_new(BIO_f_base64());
731 bio = BIO_new(BIO_s_mem());
732 bio = BIO_push(b64, bio);
733
734 BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
735 BIO_write(bio, dgst_raw, dgst_raw_len);
736 BIO_flush(bio);
737 BIO_get_mem_ptr(bio, &bufferPtr);
738 strncat_s(retval, retval_len, bufferPtr->data, _TRUNCATE);
739 BIO_set_close(bio, BIO_NOCLOSE);
740 BIO_free_all(bio);
741
742 /* Remove the trailing '=' character */
743 for (i = strlen(retval) - 1; retval[i] == '='; i--) {
744 retval[i] = '\0';
745 }
746
747 return (retval);
748 }
749
750 static char *
751 key_fingerprint_hex(const char *alg, u_char *dgst_raw, u_int dgst_raw_len)
752 {
753 char *retval;
754 unsigned int i, retval_len;
755
756 retval_len = strlen(alg) + 1 + dgst_raw_len * 3 + 1;
757 retval = malloc(retval_len);
758 retval[0] = '\0';
759
760 strncat_s(retval, retval_len, alg, _TRUNCATE);
761 strncat_s(retval, retval_len, ":", _TRUNCATE);
762
763 for (i = 0; i < dgst_raw_len; i++) {
764 char hex[4];
765 _snprintf_s(hex, sizeof(hex), _TRUNCATE, "%02x:", dgst_raw[i]);
766 strncat_s(retval, retval_len, hex, _TRUNCATE);
767 }
768
769 /* Remove the trailing ':' character */
770 retval[retval_len - 2] = '\0';
771
772 return (retval);
773 }
774
775 #define FLDBASE 8
776 #define FLDSIZE_Y (FLDBASE + 1)
777 #define FLDSIZE_X (FLDBASE * 2 + 1)
778 static char *
779 key_fingerprint_randomart(const char *alg, u_char *dgst_raw, u_int dgst_raw_len, const Key *k)
780 {
781 /*
782 * Chars to be used after each other every time the worm
783 * intersects with itself. Matter of taste.
784 */
785 char *augmentation_string = " .o+=*BOX@%&#/^SE";
786 char *retval, *p, title[FLDSIZE_X], hash[FLDSIZE_X];
787 unsigned char field[FLDSIZE_X][FLDSIZE_Y];
788 size_t i, tlen, hlen;
789 unsigned int b;
790 int x, y, r;
791 size_t len = strlen(augmentation_string) - 1;
792
793 retval = calloc((FLDSIZE_X + 3 + 1), (FLDSIZE_Y + 2));
794
795 /* initialize field */
796 memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char));
797 x = FLDSIZE_X / 2;
798 y = FLDSIZE_Y / 2;
799
800 /* process raw key */
801 for (i = 0; i < dgst_raw_len; i++) {
802 int input;
803 /* each byte conveys four 2-bit move commands */
804 input = dgst_raw[i];
805 for (b = 0; b < 4; b++) {
806 /* evaluate 2 bit, rest is shifted later */
807 x += (input & 0x1) ? 1 : -1;
808 y += (input & 0x2) ? 1 : -1;
809
810 /* assure we are still in bounds */
811 x = max(x, 0);
812 y = max(y, 0);
813 x = min(x, FLDSIZE_X - 1);
814 y = min(y, FLDSIZE_Y - 1);
815
816 /* augment the field */
817 if (field[x][y] < len - 2)
818 field[x][y]++;
819 input = input >> 2;
820 }
821 }
822
823 /* mark starting point and end point*/
824 field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = (unsigned char)(len - 1);
825 field[x][y] = (unsigned char)len;
826
827 /* assemble title */
828 r = _snprintf_s(title, sizeof(title), _TRUNCATE, "[%s %u]",
829 ssh_key_type(k->type), key_size(k));
830 /* If [type size] won't fit, then try [type]; fits "[ED25519-CERT]" */
831 if (r < 0 || r >(int)sizeof(title))
832 r = _snprintf_s(title, sizeof(title), _TRUNCATE, "[%s]",
833 ssh_key_type(k->type));
834 tlen = (r <= 0) ? 0 : strlen(title);
835
836 /* assemble hash ID. */
837 r = _snprintf_s(hash, sizeof(hash), _TRUNCATE, "[%s]", alg);
838 hlen = (r <= 0) ? 0 : strlen(hash);
839
840 /* output upper border */
841 p = retval;
842 *p++ = '+';
843 for (i = 0; i < (FLDSIZE_X - tlen) / 2; i++)
844 *p++ = '-';
845 memcpy(p, title, tlen);
846 p += tlen;
847 for (i += tlen; i < FLDSIZE_X; i++)
848 *p++ = '-';
849 *p++ = '+';
850 *p++ = '\r';
851 *p++ = '\n';
852
853 /* output content */
854 for (y = 0; y < FLDSIZE_Y; y++) {
855 *p++ = '|';
856 for (x = 0; x < FLDSIZE_X; x++)
857 *p++ = augmentation_string[min(field[x][y], len)];
858 *p++ = '|';
859 *p++ = '\r';
860 *p++ = '\n';
861 }
862
863 /* output lower border */
864 *p++ = '+';
865 for (i = 0; i < (FLDSIZE_X - hlen) / 2; i++)
866 *p++ = '-';
867 memcpy(p, hash, hlen);
868 p += hlen;
869 for (i += hlen; i < FLDSIZE_X; i++)
870 *p++ = '-';
871 *p++ = '+';
872
873 return retval;
874 }
875 #undef FLDBASE
876 #undef FLDSIZE_Y
877 #undef FLDSIZE_X
878
879 //
880 // fingerprint�i�w���F�z�X�g���J�����n�b�V���j����������
881 //
882 char *key_fingerprint(Key *key, enum fp_rep dgst_rep, enum digest_algorithm dgst_alg)
883 {
884 char *retval = NULL, *alg;
885 unsigned char *dgst_raw;
886 int dgst_raw_len;
887
888 // fingerprint���n�b�V���l�i�o�C�i���j��������
889 dgst_raw = key_fingerprint_raw(key, dgst_alg, &dgst_raw_len);
890 if (dgst_raw == NULL)
891 return NULL;
892
893 alg = get_digest_algorithm_name(dgst_alg);
894
895 switch (dgst_rep) {
896 case SSH_FP_HEX:
897 retval = key_fingerprint_hex(alg, dgst_raw, dgst_raw_len);
898 break;
899 case SSH_FP_BASE64:
900 retval = key_fingerprint_b64(alg, dgst_raw, dgst_raw_len);
901 break;
902 case SSH_FP_RANDOMART:
903 retval = key_fingerprint_randomart(alg, dgst_raw, dgst_raw_len, key);
904 break;
905 }
906
907 SecureZeroMemory(dgst_raw, dgst_raw_len);
908 free(dgst_raw);
909
910 return (retval);
911 }
912
913 //
914 // �L�[�������������m��
915 //
916 static void key_add_private(Key *k)
917 {
918 switch (k->type) {
919 case KEY_RSA1:
920 case KEY_RSA:
921 k->rsa->d = BN_new();
922 k->rsa->iqmp = BN_new();
923 k->rsa->q = BN_new();
924 k->rsa->p = BN_new();
925 k->rsa->dmq1 = BN_new();
926 k->rsa->dmp1 = BN_new();
927 if (k->rsa->d == NULL || k->rsa->iqmp == NULL || k->rsa->q == NULL ||
928 k->rsa->p == NULL || k->rsa->dmq1 == NULL || k->rsa->dmp1 == NULL)
929 goto error;
930 break;
931
932 case KEY_DSA:
933 k->dsa->priv_key = BN_new();
934 if (k->dsa->priv_key == NULL)
935 goto error;
936 break;
937
938 case KEY_ECDSA256:
939 case KEY_ECDSA384:
940 case KEY_ECDSA521:
941 /* Cannot do anything until we know the group */
942 break;
943
944 case KEY_ED25519:
945 /* no need to prealloc */
946 break;
947
948 case KEY_UNSPEC:
949 break;
950
951 default:
952 goto error;
953 break;
954 }
955 return;
956
957 error:
958 if (k->rsa->d) {
959 BN_free(k->rsa->d);
960 k->rsa->d = NULL;
961 }
962 if (k->rsa->iqmp) {
963 BN_free(k->rsa->iqmp);
964 k->rsa->iqmp = NULL;
965 }
966 if (k->rsa->q) {
967 BN_free(k->rsa->q);
968 k->rsa->q = NULL;
969 }
970 if (k->rsa->p) {
971 BN_free(k->rsa->p);
972 k->rsa->p = NULL;
973 }
974 if (k->rsa->dmq1) {
975 BN_free(k->rsa->dmq1);
976 k->rsa->dmq1 = NULL;
977 }
978 if (k->rsa->dmp1) {
979 BN_free(k->rsa->dmp1);
980 k->rsa->dmp1 = NULL;
981 }
982
983
984 if (k->dsa->priv_key == NULL) {
985 BN_free(k->dsa->priv_key);
986 k->dsa->priv_key = NULL;
987 }
988
989 }
990
991 Key *key_new_private(int type)
992 {
993 Key *k = key_new(type);
994
995 key_add_private(k);
996 return (k);
997 }
998
999
1000 Key *key_new(int type)
1001 {
1002 int success = 0;
1003 Key *k = NULL;
1004 RSA *rsa;
1005 DSA *dsa;
1006
1007 k = calloc(1, sizeof(Key));
1008 if (k == NULL)
1009 goto error;
1010 k->type = type;
1011 k->ecdsa = NULL;
1012 k->dsa = NULL;
1013 k->rsa = NULL;
1014 k->ed25519_pk = NULL;
1015 k->ed25519_sk = NULL;
1016
1017 switch (k->type) {
1018 case KEY_RSA1:
1019 case KEY_RSA:
1020 rsa = RSA_new();
1021 if (rsa == NULL)
1022 goto error;
1023 rsa->n = BN_new();
1024 rsa->e = BN_new();
1025 if (rsa->n == NULL || rsa->e == NULL)
1026 goto error;
1027 k->rsa = rsa;
1028 break;
1029
1030 case KEY_DSA:
1031 dsa = DSA_new();
1032 if (dsa == NULL)
1033 goto error;
1034 dsa->p = BN_new();
1035 dsa->q = BN_new();
1036 dsa->g = BN_new();
1037 dsa->pub_key = BN_new();
1038 if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL || dsa->pub_key == NULL)
1039 goto error;
1040 k->dsa = dsa;
1041 break;
1042
1043 case KEY_ECDSA256:
1044 case KEY_ECDSA384:
1045 case KEY_ECDSA521:
1046 /* Cannot do anything until we know the group */
1047 break;
1048
1049 case KEY_ED25519:
1050 /* no need to prealloc */
1051 break;
1052
1053 case KEY_UNSPEC:
1054 break;
1055
1056 default:
1057 goto error;
1058 break;
1059 }
1060 success = 1;
1061
1062 error:
1063 if (success == 0) {
1064 key_free(k);
1065 k = NULL;
1066 }
1067 return (k);
1068 }
1069
1070
1071 //
1072 // Key �\�����������o�������������� key ��������������
1073 // key_new() ������ malloc �������������|�C���^���n��
1074 // Key �\�������n��������������
1075 //
1076 void key_free(Key *key)
1077 {
1078 if (key == NULL) {
1079 return;
1080 }
1081
1082 key_init(key);
1083
1084 free(key);
1085 }
1086
1087 //
1088 // Key �\�����������o����������������
1089 // �����o�������������Akey ����������������
1090 //
1091 void key_init(Key *key)
1092 {
1093 key->type = KEY_UNSPEC;
1094
1095 // SSH1
1096 key->bits = 0;
1097 if (key->exp != NULL) {
1098 free(key->exp);
1099 key->exp = NULL;
1100 }
1101 if (key->mod != NULL) {
1102 free(key->mod);
1103 key->mod = NULL;
1104 }
1105
1106 // SSH2
1107 if (key->dsa != NULL) {
1108 DSA_free(key->dsa);
1109 key->dsa = NULL;
1110 }
1111 if (key->rsa != NULL) {
1112 RSA_free(key->rsa);
1113 key->rsa = NULL;
1114 }
1115 if (key->ecdsa != NULL) {
1116 EC_KEY_free(key->ecdsa);
1117 key->ecdsa = NULL;
1118 }
1119 if (key->ed25519_pk != NULL) {
1120 SecureZeroMemory(key->ed25519_pk, ED25519_PK_SZ);
1121 free(key->ed25519_pk);
1122 key->ed25519_pk = NULL;
1123 }
1124 if (key->ed25519_sk) {
1125 SecureZeroMemory(key->ed25519_sk, ED25519_SK_SZ);
1126 free(key->ed25519_sk);
1127 key->ed25519_sk = NULL;
1128 }
1129 }
1130
1131 //
1132 // �L�[���������������p����
1133 //
1134 char *get_sshname_from_key(Key *key)
1135 {
1136 return get_ssh_keytype_name(key->type);
1137 }
1138
1139 //
1140 // �L�[������������������������
1141 //
1142 ssh_keytype get_keytype_from_name(char *name)
1143 {
1144 if (strcmp(name, "rsa1") == 0) {
1145 return KEY_RSA1;
1146 } else if (strcmp(name, "rsa") == 0) {
1147 return KEY_RSA;
1148 } else if (strcmp(name, "dsa") == 0) {
1149 return KEY_DSA;
1150 } else if (strcmp(name, "ssh-rsa") == 0) {
1151 return KEY_RSA;
1152 } else if (strcmp(name, "ssh-dss") == 0) {
1153 return KEY_DSA;
1154 } else if (strcmp(name, "ecdsa-sha2-nistp256") == 0) {
1155 return KEY_ECDSA256;
1156 } else if (strcmp(name, "ecdsa-sha2-nistp384") == 0) {
1157 return KEY_ECDSA384;
1158 } else if (strcmp(name, "ecdsa-sha2-nistp521") == 0) {
1159 return KEY_ECDSA521;
1160 } else if (strcmp(name, "ssh-ed25519") == 0) {
1161 return KEY_ED25519;
1162 }
1163 return KEY_UNSPEC;
1164 }
1165
1166
1167 ssh_keytype key_curve_name_to_keytype(char *name)
1168 {
1169 if (strcmp(name, "nistp256") == 0) {
1170 return KEY_ECDSA256;
1171 } else if (strcmp(name, "nistp384") == 0) {
1172 return KEY_ECDSA384;
1173 } else if (strcmp(name, "nistp521") == 0) {
1174 return KEY_ECDSA521;
1175 }
1176 return KEY_UNSPEC;
1177 }
1178
1179 char *curve_keytype_to_name(ssh_keytype type)
1180 {
1181 switch (type) {
1182 case KEY_ECDSA256:
1183 return "nistp256";
1184 break;
1185 case KEY_ECDSA384:
1186 return "nistp384";
1187 break;
1188 case KEY_ECDSA521:
1189 return "nistp521";
1190 break;
1191 }
1192 return NULL;
1193 }
1194
1195 //
1196 // �L�[���������o�b�t�@���������� (for SSH2)
1197 // NOTE:
1198 //
1199 int key_to_blob(Key *key, char **blobp, int *lenp)
1200 {
1201 buffer_t *b;
1202 char *sshname, *tmp;
1203 int len;
1204 int ret = 1; // success
1205
1206 b = buffer_init();
1207 sshname = get_sshname_from_key(key);
1208
1209 switch (key->type) {
1210 case KEY_RSA:
1211 buffer_put_string(b, sshname, strlen(sshname));
1212 buffer_put_bignum2(b, key->rsa->e);
1213 buffer_put_bignum2(b, key->rsa->n);
1214 break;
1215 case KEY_DSA:
1216 buffer_put_string(b, sshname, strlen(sshname));
1217 buffer_put_bignum2(b, key->dsa->p);
1218 buffer_put_bignum2(b, key->dsa->q);
1219 buffer_put_bignum2(b, key->dsa->g);
1220 buffer_put_bignum2(b, key->dsa->pub_key);
1221 break;
1222 case KEY_ECDSA256:
1223 case KEY_ECDSA384:
1224 case KEY_ECDSA521:
1225 buffer_put_string(b, sshname, strlen(sshname));
1226 tmp = curve_keytype_to_name(key->type);
1227 buffer_put_string(b, tmp, strlen(tmp));
1228 buffer_put_ecpoint(b, EC_KEY_get0_group(key->ecdsa),
1229 EC_KEY_get0_public_key(key->ecdsa));
1230 break;
1231 case KEY_ED25519:
1232 buffer_put_cstring(b, sshname);
1233 buffer_put_string(b, key->ed25519_pk, ED25519_PK_SZ);
1234 break;
1235
1236 default:
1237 ret = 0;
1238 goto error;
1239 }
1240
1241 len = buffer_len(b);
1242 if (lenp != NULL)
1243 *lenp = len;
1244 if (blobp != NULL) {
1245 *blobp = malloc(len);
1246 if (*blobp == NULL) {
1247 ret = 0;
1248 goto error;
1249 }
1250 memcpy(*blobp, buffer_ptr(b), len);
1251 }
1252
1253 error:
1254 buffer_free(b);
1255
1256 return (ret);
1257 }
1258
1259
1260 //
1261 // �o�b�t�@�����L�[�����������o��(for SSH2)
1262 // NOTE: ���l���A���P�[�g���������������A�����o�������������������B
1263 //
1264 Key *key_from_blob(char *data, int blen)
1265 {
1266 int keynamelen, len;
1267 char key[128];
1268 RSA *rsa = NULL;
1269 DSA *dsa = NULL;
1270 EC_KEY *ecdsa = NULL;
1271 EC_POINT *q = NULL;
1272 char *curve = NULL;
1273 Key *hostkey = NULL; // hostkey
1274 ssh_keytype type;
1275 unsigned char *pk = NULL;
1276
1277 if (data == NULL)
1278 goto error;
1279
1280 hostkey = malloc(sizeof(Key));
1281 if (hostkey == NULL)
1282 goto error;
1283
1284 memset(hostkey, 0, sizeof(Key));
1285
1286 keynamelen = get_uint32_MSBfirst(data);
1287 if (keynamelen >= sizeof(key)) {
1288 goto error;
1289 }
1290 data += 4;
1291 memcpy(key, data, keynamelen);
1292 key[keynamelen] = 0;
1293 data += keynamelen;
1294
1295 type = get_keytype_from_name(key);
1296
1297 switch (type) {
1298 case KEY_RSA: // RSA key
1299 rsa = RSA_new();
1300 if (rsa == NULL) {
1301 goto error;
1302 }
1303 rsa->n = BN_new();
1304 rsa->e = BN_new();
1305 if (rsa->n == NULL || rsa->e == NULL) {
1306 goto error;
1307 }
1308
1309 buffer_get_bignum2(&data, rsa->e);
1310 buffer_get_bignum2(&data, rsa->n);
1311
1312 hostkey->type = type;
1313 hostkey->rsa = rsa;
1314 break;
1315
1316 case KEY_DSA: // DSA key
1317 dsa = DSA_new();
1318 if (dsa == NULL) {
1319 goto error;
1320 }
1321 dsa->p = BN_new();
1322 dsa->q = BN_new();
1323 dsa->g = BN_new();
1324 dsa->pub_key = BN_new();
1325 if (dsa->p == NULL ||
1326 dsa->q == NULL ||
1327 dsa->g == NULL ||
1328 dsa->pub_key == NULL) {
1329 goto error;
1330 }
1331
1332 buffer_get_bignum2(&data, dsa->p);
1333 buffer_get_bignum2(&data, dsa->q);
1334 buffer_get_bignum2(&data, dsa->g);
1335 buffer_get_bignum2(&data, dsa->pub_key);
1336
1337 hostkey->type = type;
1338 hostkey->dsa = dsa;
1339 break;
1340
1341 case KEY_ECDSA256: // ECDSA
1342 case KEY_ECDSA384:
1343 case KEY_ECDSA521:
1344 curve = buffer_get_string(&data, NULL);
1345 if (type != key_curve_name_to_keytype(curve)) {
1346 goto error;
1347 }
1348
1349 ecdsa = EC_KEY_new_by_curve_name(keytype_to_cipher_nid(type));
1350 if (ecdsa == NULL) {
1351 goto error;
1352 }
1353
1354 q = EC_POINT_new(EC_KEY_get0_group(ecdsa));
1355 if (q == NULL) {
1356 goto error;
1357 }
1358
1359 buffer_get_ecpoint(&data, EC_KEY_get0_group(ecdsa), q);
1360 if (key_ec_validate_public(EC_KEY_get0_group(ecdsa), q) == -1) {
1361 goto error;
1362 }
1363
1364 if (EC_KEY_set_public_key(ecdsa, q) != 1) {
1365 goto error;
1366 }
1367
1368 hostkey->type = type;
1369 hostkey->ecdsa = ecdsa;
1370 break;
1371
1372 case KEY_ED25519:
1373 pk = buffer_get_string(&data, &len);
1374 if (pk == NULL)
1375 goto error;
1376 if (len != ED25519_PK_SZ)
1377 goto error;
1378
1379 hostkey->type = type;
1380 hostkey->ed25519_pk = pk;
1381 pk = NULL;
1382 break;
1383
1384 default: // unknown key
1385 goto error;
1386 }
1387
1388 return (hostkey);
1389
1390 error:
1391 if (rsa != NULL)
1392 RSA_free(rsa);
1393 if (dsa != NULL)
1394 DSA_free(dsa);
1395 if (ecdsa != NULL)
1396 EC_KEY_free(ecdsa);
1397
1398 free(hostkey);
1399
1400 return NULL;
1401 }
1402
1403
1404 static int ssh_ed25519_sign(Key *key, char **sigp, int *lenp, char *data, int datalen)
1405 {
1406 char *sig;
1407 int slen, len;
1408 unsigned long long smlen;
1409 int ret;
1410 buffer_t *b;
1411
1412 smlen = slen = datalen + crypto_sign_ed25519_BYTES;
1413 sig = malloc(slen);
1414
1415 if ((ret = crypto_sign_ed25519(sig, &smlen, data, datalen,
1416 key->ed25519_sk)) != 0 || smlen <= datalen) {
1417 //error("%s: crypto_sign_ed25519 failed: %d", __func__, ret);
1418 free(sig);
1419 return -1;
1420 }
1421 /* encode signature */
1422 b = buffer_init();
1423 buffer_put_cstring(b, "ssh-ed25519");
1424 buffer_put_string(b, sig, (int)(smlen - datalen));
1425 len = buffer_len(b);
1426 if (lenp != NULL)
1427 *lenp = len;
1428 if (sigp != NULL) {
1429 *sigp = malloc(len);
1430 memcpy(*sigp, buffer_ptr(b), len);
1431 }
1432 buffer_free(b);
1433 SecureZeroMemory(sig, slen);
1434 free(sig);
1435
1436 return 0;
1437 }
1438
1439
1440 BOOL generate_SSH2_keysign(Key *keypair, char **sigptr, int *siglen, char *data, int datalen)
1441 {
1442 buffer_t *msg = NULL;
1443 char *s;
1444 int ret;
1445
1446 msg = buffer_init();
1447 if (msg == NULL) {
1448 // TODO: error check
1449 return FALSE;
1450 }
1451
1452 switch (keypair->type) {
1453 case KEY_RSA: // RSA
1454 {
1455 const EVP_MD *evp_md = EVP_sha1();
1456 EVP_MD_CTX md;
1457 u_char digest[EVP_MAX_MD_SIZE], *sig;
1458 u_int slen, dlen, len;
1459 int ok, nid = NID_sha1;
1460
1461 // �_�C�W�F�X�g�l���v�Z
1462 EVP_DigestInit(&md, evp_md);
1463 EVP_DigestUpdate(&md, data, datalen);
1464 EVP_DigestFinal(&md, digest, &dlen);
1465
1466 slen = RSA_size(keypair->rsa);
1467 sig = malloc(slen);
1468 if (sig == NULL)
1469 goto error;
1470
1471 // �d�q�������v�Z
1472 ok = RSA_sign(nid, digest, dlen, sig, &len, keypair->rsa);
1473 SecureZeroMemory(digest, sizeof(digest));
1474 if (ok != 1) { // error
1475 free(sig);
1476 goto error;
1477 }
1478 // �������T�C�Y���o�b�t�@���������������A�������������B�������[�����������B
1479 if (len < slen) {
1480 u_int diff = slen - len;
1481 memmove(sig + diff, sig, len);
1482 memset(sig, 0, diff);
1483
1484 } else if (len > slen) {
1485 free(sig);
1486 goto error;
1487
1488 } else {
1489 // do nothing
1490
1491 }
1492
1493 s = get_sshname_from_key(keypair);
1494 buffer_put_string(msg, s, strlen(s));
1495 buffer_append_length(msg, sig, slen);
1496 len = buffer_len(msg);
1497
1498 // setting
1499 *siglen = len;
1500 *sigptr = malloc(len);
1501 if (*sigptr == NULL) {
1502 free(sig);
1503 goto error;
1504 }
1505 memcpy(*sigptr, buffer_ptr(msg), len);
1506 free(sig);
1507
1508 break;
1509 }
1510 case KEY_DSA: // DSA
1511 {
1512 DSA_SIG *sig;
1513 const EVP_MD *evp_md = EVP_sha1();
1514 EVP_MD_CTX md;
1515 u_char digest[EVP_MAX_MD_SIZE], sigblob[SIGBLOB_LEN];
1516 u_int rlen, slen, len, dlen;
1517
1518 // �_�C�W�F�X�g���v�Z
1519 EVP_DigestInit(&md, evp_md);
1520 EVP_DigestUpdate(&md, data, datalen);
1521 EVP_DigestFinal(&md, digest, &dlen);
1522
1523 // DSA�d�q�������v�Z
1524 sig = DSA_do_sign(digest, dlen, keypair->dsa);
1525 SecureZeroMemory(digest, sizeof(digest));
1526 if (sig == NULL) {
1527 goto error;
1528 }
1529
1530 // BIGNUM�����o�C�i���l��������
1531 rlen = BN_num_bytes(sig->r);
1532 slen = BN_num_bytes(sig->s);
1533 if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) {
1534 DSA_SIG_free(sig);
1535 goto error;
1536 }
1537 memset(sigblob, 0, SIGBLOB_LEN);
1538 BN_bn2bin(sig->r, sigblob+ SIGBLOB_LEN - INTBLOB_LEN - rlen);
1539 BN_bn2bin(sig->s, sigblob+ SIGBLOB_LEN - slen);
1540 DSA_SIG_free(sig);
1541
1542 // setting
1543 s = get_sshname_from_key(keypair);
1544 buffer_put_string(msg, s, strlen(s));
1545 buffer_append_length(msg, sigblob, sizeof(sigblob));
1546 len = buffer_len(msg);
1547
1548 // setting
1549 *siglen = len;
1550 *sigptr = malloc(len);
1551 if (*sigptr == NULL) {
1552 goto error;
1553 }
1554 memcpy(*sigptr, buffer_ptr(msg), len);
1555
1556 break;
1557 }
1558 case KEY_ECDSA256: // ECDSA
1559 case KEY_ECDSA384:
1560 case KEY_ECDSA521:
1561 {
1562 ECDSA_SIG *sig;
1563 const EVP_MD *evp_md;
1564 EVP_MD_CTX md;
1565 u_char digest[EVP_MAX_MD_SIZE];
1566 u_int len, dlen, nid;
1567 buffer_t *buf2 = NULL;
1568
1569 nid = keytype_to_hash_nid(keypair->type);
1570 if ((evp_md = EVP_get_digestbynid(nid)) == NULL) {
1571 goto error;
1572 }
1573 EVP_DigestInit(&md, evp_md);
1574 EVP_DigestUpdate(&md, data, datalen);
1575 EVP_DigestFinal(&md, digest, &dlen);
1576
1577 sig = ECDSA_do_sign(digest, dlen, keypair->ecdsa);
1578 SecureZeroMemory(digest, sizeof(digest));
1579
1580 if (sig == NULL) {
1581 goto error;
1582 }
1583
1584 buf2 = buffer_init();
1585 if (buf2 == NULL) {
1586 // TODO: error check
1587 goto error;
1588 }
1589 buffer_put_bignum2(buf2, sig->r);
1590 buffer_put_bignum2(buf2, sig->s);
1591 ECDSA_SIG_free(sig);
1592
1593 s = get_sshname_from_key(keypair);
1594 buffer_put_string(msg, s, strlen(s));
1595 buffer_put_string(msg, buffer_ptr(buf2), buffer_len(buf2));
1596 buffer_free(buf2);
1597 len = buffer_len(msg);
1598
1599 *siglen = len;
1600 *sigptr = malloc(len);
1601 if (*sigptr == NULL) {
1602 goto error;
1603 }
1604 memcpy(*sigptr, buffer_ptr(msg), len);
1605
1606 break;
1607 }
1608
1609 case KEY_ED25519:
1610 ret = ssh_ed25519_sign(keypair, sigptr, siglen, data, datalen);
1611 if (ret != 0)
1612 goto error;
1613 break;
1614
1615 default:
1616 buffer_free(msg);
1617 return FALSE;
1618 break;
1619 }
1620
1621 buffer_free(msg);
1622 return TRUE;
1623
1624 error:
1625 buffer_free(msg);
1626
1627 return FALSE;
1628 }
1629
1630
1631 BOOL get_SSH2_publickey_blob(PTInstVar pvar, buffer_t **blobptr, int *bloblen)
1632 {
1633 buffer_t *msg = NULL;
1634 Key *keypair;
1635 char *s, *tmp;
1636
1637 msg = buffer_init();
1638 if (msg == NULL) {
1639 // TODO: error check
1640 return FALSE;
1641 }
1642
1643 keypair = pvar->auth_state.cur_cred.key_pair;
1644
1645 switch (keypair->type) {
1646 case KEY_RSA: // RSA
1647 s = get_sshname_from_key(keypair);
1648 buffer_put_string(msg, s, strlen(s));
1649 buffer_put_bignum2(msg, keypair->rsa->e); // ���J�w��
1650 buffer_put_bignum2(msg, keypair->rsa->n); // p�~q
1651 break;
1652 case KEY_DSA: // DSA
1653 s = get_sshname_from_key(keypair);
1654 buffer_put_string(msg, s, strlen(s));
1655 buffer_put_bignum2(msg, keypair->dsa->p); // �f��
1656 buffer_put_bignum2(msg, keypair->dsa->q); // (p-1)���f����
1657 buffer_put_bignum2(msg, keypair->dsa->g); // ����
1658 buffer_put_bignum2(msg, keypair->dsa->pub_key); // ���J��
1659 break;
1660 case KEY_ECDSA256: // ECDSA
1661 case KEY_ECDSA384:
1662 case KEY_ECDSA521:
1663 s = get_sshname_from_key(keypair);
1664 buffer_put_string(msg, s, strlen(s));
1665 tmp = curve_keytype_to_name(keypair->type);
1666 buffer_put_string(msg, tmp, strlen(tmp));
1667 buffer_put_ecpoint(msg, EC_KEY_get0_group(keypair->ecdsa),
1668 EC_KEY_get0_public_key(keypair->ecdsa));
1669 break;
1670 case KEY_ED25519:
1671 s = get_sshname_from_key(keypair);
1672 buffer_put_cstring(msg, s);
1673 buffer_put_string(msg, keypair->ed25519_pk, ED25519_PK_SZ);
1674 break;
1675 default:
1676 return FALSE;
1677 }
1678
1679 *blobptr = msg;
1680 *bloblen = buffer_len(msg);
1681
1682 return TRUE;
1683 }
1684
1685 int kextype_to_cipher_nid(kex_algorithm type)
1686 {
1687 switch (type) {
1688 case KEX_ECDH_SHA2_256:
1689 return NID_X9_62_prime256v1;
1690 case KEX_ECDH_SHA2_384:
1691 return NID_secp384r1;
1692 case KEX_ECDH_SHA2_521:
1693 return NID_secp521r1;
1694 }
1695 return NID_undef;
1696 }
1697
1698 int keytype_to_hash_nid(ssh_keytype type)
1699 {
1700 switch (type) {
1701 case KEY_ECDSA256:
1702 return NID_sha256;
1703 case KEY_ECDSA384:
1704 return NID_sha384;
1705 case KEY_ECDSA521:
1706 return NID_sha512;
1707 }
1708 return NID_undef;
1709 }
1710
1711 int keytype_to_cipher_nid(ssh_keytype type)
1712 {
1713 switch (type) {
1714 case KEY_ECDSA256:
1715 return NID_X9_62_prime256v1;
1716 case KEY_ECDSA384:
1717 return NID_secp384r1;
1718 case KEY_ECDSA521:
1719 return NID_secp521r1;
1720 }
1721 return NID_undef;
1722 }
1723
1724 ssh_keytype nid_to_keytype(int nid)
1725 {
1726 switch (nid) {
1727 case NID_X9_62_prime256v1:
1728 return KEY_ECDSA256;
1729 case NID_secp384r1:
1730 return KEY_ECDSA384;
1731 case NID_secp521r1:
1732 return KEY_ECDSA521;
1733 }
1734 return KEY_UNSPEC;
1735 }
1736
1737 void key_private_serialize(Key *key, buffer_t *b)
1738 {
1739 char *s;
1740
1741 s = get_sshname_from_key(key);
1742 buffer_put_cstring(b, s);
1743
1744 switch (key->type) {
1745 case KEY_RSA:
1746 buffer_put_bignum2(b, key->rsa->n);
1747 buffer_put_bignum2(b, key->rsa->e);
1748 buffer_put_bignum2(b, key->rsa->d);
1749 buffer_put_bignum2(b, key->rsa->iqmp);
1750 buffer_put_bignum2(b, key->rsa->p);
1751 buffer_put_bignum2(b, key->rsa->q);
1752 break;
1753
1754 case KEY_DSA:
1755 buffer_put_bignum2(b, key->dsa->p);
1756 buffer_put_bignum2(b, key->dsa->q);
1757 buffer_put_bignum2(b, key->dsa->g);
1758 buffer_put_bignum2(b, key->dsa->pub_key);
1759 buffer_put_bignum2(b, key->dsa->priv_key);
1760 break;
1761
1762 case KEY_ECDSA256:
1763 case KEY_ECDSA384:
1764 case KEY_ECDSA521:
1765 buffer_put_cstring(b, curve_keytype_to_name(key->type));
1766 buffer_put_ecpoint(b, EC_KEY_get0_group(key->ecdsa),
1767 EC_KEY_get0_public_key(key->ecdsa));
1768 buffer_put_bignum2(b, (BIGNUM *)EC_KEY_get0_private_key(key->ecdsa));
1769 break;
1770
1771 case KEY_ED25519:
1772 buffer_put_string(b, key->ed25519_pk, ED25519_PK_SZ);
1773 buffer_put_string(b, key->ed25519_sk, ED25519_SK_SZ);
1774 break;
1775
1776 default:
1777 break;
1778 }
1779 }
1780
1781 /* calculate p-1 and q-1 */
1782 static void rsa_generate_additional_parameters(RSA *rsa)
1783 {
1784 BIGNUM *aux = NULL;
1785 BN_CTX *ctx = NULL;
1786
1787 if ((aux = BN_new()) == NULL)
1788 goto error;
1789 if ((ctx = BN_CTX_new()) == NULL)
1790 goto error;
1791
1792 if ((BN_sub(aux, rsa->q, BN_value_one()) == 0) ||
1793 (BN_mod(rsa->dmq1, rsa->d, aux, ctx) == 0) ||
1794 (BN_sub(aux, rsa->p, BN_value_one()) == 0) ||
1795 (BN_mod(rsa->dmp1, rsa->d, aux, ctx) == 0))
1796 goto error;
1797
1798 error:
1799 if (aux)
1800 BN_clear_free(aux);
1801 if (ctx)
1802 BN_CTX_free(ctx);
1803 }
1804
1805 Key *key_private_deserialize(buffer_t *blob)
1806 {
1807 int success = 0;
1808 char *type_name = NULL;
1809 Key *k = NULL;
1810 unsigned int pklen, sklen;
1811 int type;
1812
1813 type_name = buffer_get_string_msg(blob, NULL);
1814 if (type_name == NULL)
1815 goto error;
1816 type = get_keytype_from_name(type_name);
1817
1818 k = key_new_private(type);
1819
1820 switch (type) {
1821 case KEY_RSA:
1822 buffer_get_bignum2_msg(blob, k->rsa->n);
1823 buffer_get_bignum2_msg(blob, k->rsa->e);
1824 buffer_get_bignum2_msg(blob, k->rsa->d);
1825 buffer_get_bignum2_msg(blob, k->rsa->iqmp);
1826 buffer_get_bignum2_msg(blob, k->rsa->p);
1827 buffer_get_bignum2_msg(blob, k->rsa->q);
1828
1829 /* Generate additional parameters */
1830 rsa_generate_additional_parameters(k->rsa);
1831 break;
1832
1833 case KEY_DSA:
1834 buffer_get_bignum2_msg(blob, k->dsa->p);
1835 buffer_get_bignum2_msg(blob, k->dsa->q);
1836 buffer_get_bignum2_msg(blob, k->dsa->g);
1837 buffer_get_bignum2_msg(blob, k->dsa->pub_key);
1838 buffer_get_bignum2_msg(blob, k->dsa->priv_key);
1839 break;
1840
1841 case KEY_ECDSA256:
1842 case KEY_ECDSA384:
1843 case KEY_ECDSA521:
1844 {
1845 int success = 0;
1846 unsigned int nid;
1847 char *curve = NULL;
1848 ssh_keytype skt;
1849 BIGNUM *exponent = NULL;
1850 EC_POINT *q = NULL;
1851
1852 nid = keytype_to_cipher_nid(type);
1853 curve = buffer_get_string_msg(blob, NULL);
1854 skt = key_curve_name_to_keytype(curve);
1855 if (nid != keytype_to_cipher_nid(skt))
1856 goto ecdsa_error;
1857
1858 if ((k->ecdsa = EC_KEY_new_by_curve_name(nid)) == NULL)
1859 goto ecdsa_error;
1860 if ((q = EC_POINT_new(EC_KEY_get0_group(k->ecdsa))) == NULL)
1861 goto ecdsa_error;
1862 if ((exponent = BN_new()) == NULL)
1863 goto ecdsa_error;
1864
1865 buffer_get_ecpoint_msg(blob, EC_KEY_get0_group(k->ecdsa), q);
1866 buffer_get_bignum2_msg(blob, exponent);
1867 if (EC_KEY_set_public_key(k->ecdsa, q) != 1)
1868 goto ecdsa_error;
1869 if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1)
1870 goto ecdsa_error;
1871 if (key_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
1872 EC_KEY_get0_public_key(k->ecdsa)) != 0)
1873 goto ecdsa_error;
1874 if (key_ec_validate_private(k->ecdsa) != 0)
1875 goto ecdsa_error;
1876
1877 success = 1;
1878
1879 ecdsa_error:
1880 free(curve);
1881 if (exponent)
1882 BN_clear_free(exponent);
1883 if (q)
1884 EC_POINT_free(q);
1885 if (success == 0)
1886 goto error;
1887 }
1888 break;
1889
1890 case KEY_ED25519:
1891 k->ed25519_pk = buffer_get_string_msg(blob, &pklen);
1892 k->ed25519_sk = buffer_get_string_msg(blob, &sklen);
1893 if (pklen != ED25519_PK_SZ)
1894 goto error;
1895 if (sklen != ED25519_SK_SZ)
1896 goto error;
1897 break;
1898
1899 default:
1900 goto error;
1901 break;
1902 }
1903
1904 /* enable blinding */
1905 switch (k->type) {
1906 case KEY_RSA1:
1907 case KEY_RSA:
1908 if (RSA_blinding_on(k->rsa, NULL) != 1)
1909 goto error;
1910 break;
1911 }
1912
1913 success = 1;
1914
1915 error:
1916 free(type_name);
1917
1918 if (success == 0) {
1919 key_free(k);
1920 k = NULL;
1921 }
1922
1923 return (k);
1924 }
1925
1926
1927 int key_ec_validate_private(EC_KEY *key)
1928 {
1929 BN_CTX *bnctx = NULL;
1930 BIGNUM *order, *tmp;
1931 int ret = -1;
1932
1933 if ((bnctx = BN_CTX_new()) == NULL)
1934 goto out;
1935 BN_CTX_start(bnctx);
1936
1937 if ((order = BN_CTX_get(bnctx)) == NULL ||
1938 (tmp = BN_CTX_get(bnctx)) == NULL)
1939 goto out;
1940
1941 /* log2(private) > log2(order)/2 */
1942 if (EC_GROUP_get_order(EC_KEY_get0_group(key), order, bnctx) != 1)
1943 goto out;
1944 if (BN_num_bits(EC_KEY_get0_private_key(key)) <=
1945 BN_num_bits(order) / 2) {
1946 goto out;
1947 }
1948
1949 /* private < order - 1 */
1950 if (!BN_sub(tmp, order, BN_value_one()))
1951 goto out;
1952 if (BN_cmp(EC_KEY_get0_private_key(key), tmp) >= 0) {
1953 goto out;
1954 }
1955 ret = 0;
1956
1957 out:
1958 if (bnctx)
1959 BN_CTX_free(bnctx);
1960 return ret;
1961 }
1962
1963 // from openssh 5.8p1 key.c
1964 int key_ec_validate_public(const EC_GROUP *group, const EC_POINT *public)
1965 {
1966 BN_CTX *bnctx;
1967 EC_POINT *nq = NULL;
1968 BIGNUM *order, *x, *y, *tmp;
1969 int ret = -1;
1970
1971 if ((bnctx = BN_CTX_new()) == NULL) {
1972 return ret;
1973 }
1974 BN_CTX_start(bnctx);
1975
1976 /*
1977 * We shouldn't ever hit this case because bignum_get_ecpoint()
1978 * refuses to load GF2m points.
1979 */
1980 if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
1981 NID_X9_62_prime_field) {
1982 goto out;
1983 }
1984
1985 /* Q != infinity */
1986 if (EC_POINT_is_at_infinity(group, public)) {
1987 goto out;
1988 }
1989
1990 if ((x = BN_CTX_get(bnctx)) == NULL ||
1991 (y = BN_CTX_get(bnctx)) == NULL ||
1992 (order = BN_CTX_get(bnctx)) == NULL ||
1993 (tmp = BN_CTX_get(bnctx)) == NULL) {
1994 goto out;
1995 }
1996
1997 /* log2(x) > log2(order)/2, log2(y) > log2(order)/2 */
1998 if (EC_GROUP_get_order(group, order, bnctx) != 1) {
1999 goto out;
2000 }
2001 if (EC_POINT_get_affine_coordinates_GFp(group, public,
2002 x, y, bnctx) != 1) {
2003 goto out;
2004 }
2005 if (BN_num_bits(x) <= BN_num_bits(order) / 2) {
2006 goto out;
2007 }
2008 if (BN_num_bits(y) <= BN_num_bits(order) / 2) {
2009 goto out;
2010 }
2011
2012 /* nQ == infinity (n == order of subgroup) */
2013 if ((nq = EC_POINT_new(group)) == NULL) {
2014 goto out;
2015 }
2016 if (EC_POINT_mul(group, nq, NULL, public, order, bnctx) != 1) {
2017 goto out;
2018 }
2019 if (EC_POINT_is_at_infinity(group, nq) != 1) {
2020 goto out;
2021 }
2022
2023 /* x < order - 1, y < order - 1 */
2024 if (!BN_sub(tmp, order, BN_value_one())) {
2025 goto out;
2026 }
2027 if (BN_cmp(x, tmp) >= 0) {
2028 goto out;
2029 }
2030 if (BN_cmp(y, tmp) >= 0) {
2031 goto out;
2032 }
2033 ret = 0;
2034 out:
2035 BN_CTX_free(bnctx);
2036 EC_POINT_free(nq);
2037 return ret;
2038 }
2039
2040 static void hostkeys_update_ctx_free(struct hostkeys_update_ctx *ctx)
2041 {
2042 size_t i;
2043
2044 if (ctx == NULL)
2045 return;
2046 for (i = 0; i < ctx->nkeys; i++)
2047 key_free(ctx->keys[i]);
2048 free(ctx->keys);
2049 free(ctx->keys_seen);
2050 for (i = 0; i < ctx->nold; i++)
2051 key_free(ctx->old_keys[i]);
2052 free(ctx->old_keys);
2053 free(ctx->host_str);
2054 free(ctx->ip_str);
2055 free(ctx);
2056 }
2057
2058
2059 // �����������z�X�g���A���S���Y�������`�F�b�N�����B
2060 //
2061 // return 1: matched
2062 // 0: not matched
2063 //
2064 static int check_hostkey_algorithm(PTInstVar pvar, Key *key)
2065 {
2066 int ret = 0;
2067 int i, index;
2068
2069 for (i = 0; pvar->settings.HostKeyOrder[i] != 0; i++) {
2070 index = pvar->settings.HostKeyOrder[i] - '0';
2071 if (index == KEY_NONE) // disabled line
2072 break;
2073
2074 if (strcmp(get_sshname_from_key(key), get_ssh_keytype_name(index)) == 0)
2075 return 1;
2076 }
2077
2078 return (ret);
2079 }
2080
2081 // Callback function
2082 //
2083 // argument:
2084 // key: known_hosts���o�^������������
2085 // _ctx: �T�[�o�����������������������Q
2086 //
2087 // return:
2088 // 1: deprecated key�������A��������key�������������~�B
2089 // 0: ����������key�������������K�v�B
2090 static int hostkeys_find(Key *key, void *_ctx)
2091 {
2092 struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx;
2093 int ret = 0;
2094 size_t i;
2095 Key **tmp;
2096
2097 // SSH1�������O�B
2098 if (key->type == KEY_RSA1)
2099 goto error;
2100
2101 // �������o�^�������������������T���B
2102 for (i = 0; i < ctx->nkeys; i++) {
2103 if (HOSTS_compare_public_key(key, ctx->keys[i]) == 1) {
2104 ctx->keys_seen[i] = 1;
2105 goto error;
2106 }
2107 }
2108
2109 // deprecated�������A�����������X�g�������������B
2110 tmp = realloc(ctx->old_keys, (ctx->nold + 1)*sizeof(*ctx->old_keys));
2111 if (tmp != NULL) {
2112 ctx->old_keys = tmp;
2113 ctx->old_keys[ctx->nold++] = key;
2114 }
2115
2116 ret = 1;
2117
2118 error:
2119 return (ret);
2120 }
2121
2122 static void hosts_updatekey_dlg_set_fingerprint(PTInstVar pvar, HWND dlg, digest_algorithm dgst_alg)
2123 {
2124 char *fp, *buf;
2125 size_t i;
2126 int buf_len;
2127 struct hostkeys_update_ctx *ctx;
2128
2129 ctx = pvar->hostkey_ctx;
2130
2131 if (ctx->nkeys > 0) {
2132 buf_len = 100 * ctx->nkeys;
2133 buf = calloc(100, ctx->nkeys);
2134 for (i = 0; i < ctx->nkeys; i++) {
2135 if (ctx->keys_seen[i])
2136 continue;
2137 switch (dgst_alg) {
2138 case SSH_DIGEST_MD5:
2139 fp = key_fingerprint(ctx->keys[i], SSH_FP_HEX, dgst_alg);
2140 break;
2141 case SSH_DIGEST_SHA256:
2142 default:
2143 fp = key_fingerprint(ctx->keys[i], SSH_FP_BASE64, SSH_DIGEST_SHA256);
2144 break;
2145 }
2146 strncat_s(buf, buf_len, get_sshname_from_key(ctx->keys[i]), _TRUNCATE);
2147 strncat_s(buf, buf_len, " ", _TRUNCATE);
2148 if (fp != NULL) {
2149 strncat_s(buf, buf_len, fp, _TRUNCATE);
2150 free(fp);
2151 }
2152 if (i < ctx->nkeys - 1) {
2153 strncat_s(buf, buf_len, "\r\n", _TRUNCATE);
2154 }
2155 }
2156 SendDlgItemMessage(dlg, IDC_ADDKEY_EDIT, WM_SETTEXT, 0, (LPARAM)(char *)buf);
2157 free(buf);
2158 }
2159
2160 if (ctx->nold > 0) {
2161 buf_len = 100 * ctx->nold;
2162 buf = calloc(100, ctx->nold);
2163 SendDlgItemMessage(dlg, IDC_REMOVEKEY_EDIT, WM_SETTEXT, 0, (LPARAM)(char *)"");
2164 for (i = 0; i < ctx->nold; i++) {
2165 switch (dgst_alg) {
2166 case SSH_DIGEST_MD5:
2167 fp = key_fingerprint(ctx->old_keys[i], SSH_FP_HEX, dgst_alg);
2168 break;
2169 case SSH_DIGEST_SHA256:
2170 default:
2171 fp = key_fingerprint(ctx->old_keys[i], SSH_FP_BASE64, SSH_DIGEST_SHA256);
2172 break;
2173 }
2174 strncat_s(buf, buf_len, get_sshname_from_key(ctx->old_keys[i]), _TRUNCATE);
2175 strncat_s(buf, buf_len, " ", _TRUNCATE);
2176 if (fp != NULL) {
2177 strncat_s(buf, buf_len, fp, _TRUNCATE);
2178 free(fp);
2179 }
2180 if (i < ctx->nold - 1) {
2181 strncat_s(buf, buf_len, "\r\n", _TRUNCATE);
2182 }
2183 }
2184 SendDlgItemMessage(dlg, IDC_REMOVEKEY_EDIT, WM_SETTEXT, 0, (LPARAM)(char *)buf);
2185 free(buf);
2186 }
2187 }
2188
2189 static BOOL CALLBACK hosts_updatekey_dlg_proc(HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam)
2190 {
2191 static HFONT DlgHostsAddFont;
2192 PTInstVar pvar;
2193 LOGFONT logfont;
2194 HFONT font;
2195 char buf[1024];
2196 char *host;
2197 struct hostkeys_update_ctx *ctx;
2198 char uimsg[MAX_UIMSG];
2199
2200 switch (msg) {
2201 case WM_INITDIALOG:
2202 pvar = (PTInstVar)lParam;
2203 SetWindowLong(dlg, DWL_USER, lParam);
2204
2205 GetWindowText(dlg, uimsg, sizeof(uimsg));
2206 UTIL_get_lang_msg("DLG_HOSTKEY_ROTATION_TITLE", pvar, uimsg);
2207 SetWindowText(dlg, pvar->ts->UIMsg);
2208
2209 host = pvar->ssh_state.hostname;
2210 ctx = pvar->hostkey_ctx;
2211
2212 GetDlgItemText(dlg, IDC_HOSTKEY_MESSAGE, uimsg, sizeof(uimsg));
2213 UTIL_get_lang_msg("DLG_HOSTKEY_ROTATION_WARNING", pvar, uimsg);
2214 _snprintf_s(buf, sizeof(buf), _TRUNCATE,
2215 pvar->ts->UIMsg, host, ctx->nnew, ctx->nold
2216 );
2217 SetDlgItemText(dlg, IDC_HOSTKEY_MESSAGE, buf);
2218
2219 GetDlgItemText(dlg, IDC_FP_HASH_ALG, uimsg, sizeof(uimsg));
2220 UTIL_get_lang_msg("DLG_HOSTKEY_ROTATION_FP_HASH_ALGORITHM", pvar, uimsg);
2221 SetDlgItemText(dlg, IDC_FP_HASH_ALG, pvar->ts->UIMsg);
2222
2223 GetDlgItemText(dlg, IDC_ADDKEY_TEXT, uimsg, sizeof(uimsg));
2224 UTIL_get_lang_msg("DLG_HOSTKEY_ROTATION_ADD", pvar, uimsg);
2225 _snprintf_s(buf, sizeof(buf), _TRUNCATE, pvar->ts->UIMsg, ctx->nnew);
2226 SetDlgItemText(dlg, IDC_ADDKEY_TEXT, buf);
2227
2228 GetDlgItemText(dlg, IDC_REMOVEKEY_TEXT, uimsg, sizeof(uimsg));
2229 UTIL_get_lang_msg("DLG_HOSTKEY_ROTATION_REMOVE", pvar, uimsg);
2230 _snprintf_s(buf, sizeof(buf), _TRUNCATE, pvar->ts->UIMsg, ctx->nold);
2231 SetDlgItemText(dlg, IDC_REMOVEKEY_TEXT, buf);
2232
2233 CheckDlgButton(dlg, IDC_FP_HASH_ALG_SHA256, TRUE);
2234 hosts_updatekey_dlg_set_fingerprint(pvar, dlg, SSH_DIGEST_SHA256);
2235
2236 GetDlgItemText(dlg, IDOK, uimsg, sizeof(uimsg));
2237 UTIL_get_lang_msg("BTN_YES", pvar, uimsg);
2238 SetDlgItemText(dlg, IDOK, pvar->ts->UIMsg);
2239 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
2240 UTIL_get_lang_msg("BTN_NO", pvar, uimsg);
2241 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
2242
2243 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
2244 GetObject(font, sizeof(LOGFONT), &logfont);
2245 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsAddFont, pvar)) {
2246 SendDlgItemMessage(dlg, IDC_HOSTKEY_MESSAGE, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
2247 SendDlgItemMessage(dlg, IDC_ADDKEY_TEXT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
2248 SendDlgItemMessage(dlg, IDC_FP_HASH_ALG, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
2249 SendDlgItemMessage(dlg, IDC_FP_HASH_ALG_MD5, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
2250 SendDlgItemMessage(dlg, IDC_FP_HASH_ALG_SHA256, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
2251 SendDlgItemMessage(dlg, IDC_ADDKEY_EDIT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
2252 SendDlgItemMessage(dlg, IDC_REMOVEKEY_TEXT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
2253 SendDlgItemMessage(dlg, IDC_REMOVEKEY_EDIT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
2254 SendDlgItemMessage(dlg, IDOK, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
2255 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
2256 }
2257 else {
2258 DlgHostsAddFont = NULL;
2259 }
2260
2261 return TRUE; /* because we do not set the focus */
2262
2263 case WM_COMMAND:
2264 pvar = (PTInstVar)GetWindowLong(dlg, DWL_USER);
2265
2266 switch (LOWORD(wParam)) {
2267 case IDOK:
2268
2269 EndDialog(dlg, 1);
2270
2271 if (DlgHostsAddFont != NULL) {
2272 DeleteObject(DlgHostsAddFont);
2273 }
2274
2275 return TRUE;
2276
2277 case IDCANCEL: /* kill the connection */
2278 EndDialog(dlg, 0);
2279
2280 if (DlgHostsAddFont != NULL) {
2281 DeleteObject(DlgHostsAddFont);
2282 }
2283
2284 return TRUE;
2285
2286 case IDC_FP_HASH_ALG_MD5:
2287 hosts_updatekey_dlg_set_fingerprint(pvar, dlg, SSH_DIGEST_MD5);
2288 return TRUE;
2289
2290 case IDC_FP_HASH_ALG_SHA256:
2291 hosts_updatekey_dlg_set_fingerprint(pvar, dlg, SSH_DIGEST_SHA256);
2292 return TRUE;
2293
2294 default:
2295 return FALSE;
2296 }
2297
2298 default:
2299 return FALSE;
2300 }
2301 }
2302
2303 static void update_known_hosts(PTInstVar pvar, struct hostkeys_update_ctx *ctx)
2304 {
2305 size_t i;
2306 int dlgresult;
2307 char *host;
2308
2309 host = pvar->ssh_state.hostname;
2310
2311 // "/nosecuritywarning"���w�����������������A�X�V�������s�������B
2312 if (pvar->nocheck_known_hosts) {
2313 logputs(LOG_LEVEL_VERBOSE, "Hostkey was not updated because `/nosecuritywarning' option was specified.");
2314 goto error;
2315 }
2316
2317 // known_hosts�t�@�C�����X�V���s�������A���[�U���������������s���B
2318 if (pvar->settings.UpdateHostkeys == SSH_UPDATE_HOSTKEYS_ASK) {
2319 HWND cur_active = GetActiveWindow();
2320
2321 pvar->hostkey_ctx = ctx;
2322 dlgresult = DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHUPDATE_HOSTKEY),
2323 cur_active != NULL ? cur_active : pvar->NotificationWindow,
2324 hosts_updatekey_dlg_proc, (LPARAM)pvar);
2325 if (dlgresult != 1) {
2326 logputs(LOG_LEVEL_VERBOSE, "Hostkey was not updated because a user cancelled.");
2327 goto error;
2328 }
2329 }
2330
2331 // �����L�[�����������������B
2332 HOSTS_delete_all_hostkeys(pvar);
2333
2334 // �V�����L�[���������o�^�����B
2335 for (i = 0; i < ctx->nkeys; i++) {
2336 HOSTS_add_host_key(pvar, ctx->keys[i]);
2337 }
2338 logputs(LOG_LEVEL_VERBOSE, "Hostkey was successfully updated to known_hosts file.");
2339
2340 error:
2341 return;
2342 }
2343
2344 static void client_global_hostkeys_private_confirm(PTInstVar pvar, int type, u_int32_t seq, void *_ctx)
2345 {
2346 struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx;
2347 char *data;
2348 int len;
2349 unsigned char *blob = NULL;
2350 int bloblen;
2351 buffer_t *b = NULL;
2352 buffer_t *bsig = NULL;
2353 char *cp, *sig;
2354 size_t i, ndone, siglen;
2355 int ret;
2356
2357 // SSH2 packet format:
2358 // [size(4) + padding size(1) + type(1)] + [payload(N) + padding(X)]
2359 // header body
2360 // ^data
2361 // <-----------------size------------------------------->
2362 // <---------len-------->
2363 //
2364 // data = payload(N) + padding(X): �p�f�B���O���������{�f�B���������w���B
2365 data = pvar->ssh_state.payload;
2366 // len = size - (padding size + 1): �p�f�B���O�������{�f�B�Btype�����������������B
2367 len = pvar->ssh_state.payloadlen;
2368 len--; // type ��������
2369
2370 bsig = buffer_init();
2371 if (bsig == NULL)
2372 goto error;
2373 cp = buffer_append_space(bsig, len);
2374 memcpy(cp, data, len);
2375
2376 if (ctx->nnew == 0) {
2377 logprintf(LOG_LEVEL_FATAL,
2378 "Hostkey can not be updated because ctx->nnew %d(program bug).", ctx->nnew);
2379 goto error;
2380 }
2381 if (type != SSH2_MSG_REQUEST_SUCCESS) {
2382 logprintf(LOG_LEVEL_ERROR,
2383 "Server failed to confirm ownership of private host keys(type %d)", type);
2384 goto error;
2385 }
2386 if (pvar->session_id_len == 0) {
2387 logprintf(LOG_LEVEL_FATAL,
2388 "Hostkey can not be updated because pvar->session_id_len %d(program bug).",
2389 pvar->session_id_len);
2390 goto error;
2391 }
2392
2393 b = buffer_init();
2394 if (b == NULL)
2395 goto error;
2396
2397 ndone = 0;
2398 for (i = 0; i < ctx->nkeys; i++) {
2399 if (ctx->keys_seen[i])
2400 continue;
2401
2402 buffer_clear(b);
2403 buffer_put_cstring(b, "hostkeys-prove-00@openssh.com");
2404 buffer_put_string(b, pvar->session_id, pvar->session_id_len);
2405 key_to_blob(ctx->keys[i], &blob, &bloblen);
2406 buffer_put_string(b, blob, bloblen);
2407 free(blob);
2408 blob = NULL;
2409
2410 sig = buffer_get_string_msg(bsig, &siglen);
2411 // Verify signature
2412 ret = key_verify(ctx->keys[i], sig, siglen, buffer_ptr(b), buffer_len(b));
2413 free(sig);
2414 sig = NULL;
2415 if (ret != 1) {
2416 logprintf(LOG_LEVEL_ERROR,
2417 "server gave bad signature for %s key %u",
2418 get_sshname_from_key(ctx->keys[i]), i);
2419 goto error;
2420 }
2421 ndone++;
2422 }
2423
2424 if (ndone != ctx->nnew) {
2425 logprintf(LOG_LEVEL_FATAL,
2426 "Hostkey can not be updated because ndone != ctx->nnew (%u / %u)(program bug).",
2427 ndone, ctx->nnew);
2428 goto error;
2429 }
2430
2431 update_known_hosts(pvar, ctx);
2432
2433 error:
2434 buffer_free(b);
2435 buffer_free(bsig);
2436 hostkeys_update_ctx_free(ctx);
2437 }
2438
2439 //
2440 // SSH�T�[�o�z�X�g��(known_hosts)�������X�V(OpenSSH 6.8 or later: host key rotation support)
2441 //
2442 // return 1: success
2443 // 0: fail
2444 //
2445 int update_client_input_hostkeys(PTInstVar pvar, char *dataptr, int datalen)
2446 {
2447 int success = 1; // OpenSSH 6.8�����������A�����������������������������������A
2448 // �������������� Tera Term �������������������������B
2449 int len;
2450 size_t i;
2451 char *cp, *fp;
2452 unsigned char *blob = NULL;
2453 buffer_t *b = NULL;
2454 struct hostkeys_update_ctx *ctx = NULL;
2455 Key *key = NULL, **tmp;
2456 unsigned char *outmsg;
2457
2458 // Tera Term���������A���Y�@�\���I���I�t�����������������������B
2459 if (pvar->settings.UpdateHostkeys == SSH_UPDATE_HOSTKEYS_NO) {
2460 logputs(LOG_LEVEL_VERBOSE, "Hostkey was not updated because ts.UpdateHostkeys is disabled.");
2461 return 1;
2462 }
2463
2464 ctx = calloc(1, sizeof(struct hostkeys_update_ctx));
2465 if (ctx == NULL)
2466 goto error;
2467
2468 b = buffer_init();
2469 if (b == NULL)
2470 goto error;
2471
2472 cp = buffer_append_space(b, datalen);
2473 memcpy(cp, dataptr, datalen);
2474
2475 while (buffer_remain_len(b) > 0) {
2476 key_free(key);
2477 key = NULL;
2478
2479 blob = buffer_get_string_msg(b, &len);
2480 key = key_from_blob(blob, len);
2481 if (key == NULL) {
2482 logprintf(LOG_LEVEL_ERROR, "Not found host key into blob %p (%d)", blob, len);
2483 goto error;
2484 }
2485 free(blob);
2486 blob = NULL;
2487
2488 fp = key_fingerprint(key, SSH_FP_HEX, SSH_DIGEST_MD5);
2489 logprintf(LOG_LEVEL_VERBOSE, "Received %s host key %s", get_sshname_from_key(key), fp);
2490 free(fp);
2491
2492 // �����������z�X�g�L�[�A���S���Y�������`�F�b�N�����B
2493 if (check_hostkey_algorithm(pvar, key) == 0) {
2494 logprintf(LOG_LEVEL_VERBOSE, "%s host key is not permitted by ts.HostKeyOrder",
2495 get_sshname_from_key(key));
2496 continue;
2497 }
2498
2499 // Skip certs: Tera Term�����������F�������T�|�[�g�B
2500
2501 // �d�������L�[�����M�������G���[�������B
2502 for (i = 0; i < ctx->nkeys; i++) {
2503 if (HOSTS_compare_public_key(key, ctx->keys[i]) == 1) {
2504 logprintf(LOG_LEVEL_ERROR, "Received duplicated %s host key",
2505 get_sshname_from_key(key));
2506 goto error;
2507 }
2508 }
2509
2510 // �L�[���o�^�����B
2511 tmp = realloc(ctx->keys, (ctx->nkeys + 1)*sizeof(*ctx->keys));
2512 if (tmp == NULL) {
2513 logprintf(LOG_LEVEL_FATAL, "Not memory: realloc ctx->keys %d",
2514 ctx->nkeys);
2515 goto error;
2516 }
2517 ctx->keys = tmp;
2518 ctx->keys[ctx->nkeys++] = key;
2519 key = NULL;
2520 }
2521
2522 if (ctx->nkeys == 0) {
2523 logputs(LOG_LEVEL_VERBOSE, "No host rotation key");
2524 goto error;
2525 }
2526
2527 if ((ctx->keys_seen = calloc(ctx->nkeys, sizeof(*ctx->keys_seen))) == NULL) {
2528 logprintf(LOG_LEVEL_FATAL, "Not memory: calloc ctx->keys %d",
2529 ctx->nkeys);
2530 goto error;
2531 }
2532
2533 HOSTS_hostkey_foreach(pvar, hostkeys_find, ctx);
2534
2535 // �T�[�o�������������������Q�����A�������������V�K���������������������B
2536 ctx->nnew = 0;
2537 for (i = 0; i < ctx->nkeys; i++) {
2538 if (!ctx->keys_seen[i])
2539 ctx->nnew++;
2540 }
2541 logprintf(LOG_LEVEL_VERBOSE, "%u keys from server: %u new, %u retained. %u to remove",
2542 ctx->nkeys, ctx->nnew, ctx->nkeys - ctx->nnew, ctx->nold);
2543
2544 // �V�K�������������[�������Adeprecated���������������B
2545 if (ctx->nnew == 0 && ctx->nold != 0) {
2546 update_known_hosts(pvar, ctx);
2547
2548 }
2549 else if (ctx->nnew != 0) { // �V�K�������������������������B
2550 buffer_clear(b);
2551
2552 buffer_put_cstring(b, "hostkeys-prove-00@openssh.com");
2553 buffer_put_char(b, 1); /* bool: want reply */
2554
2555 for (i = 0; i < ctx->nkeys; i++) {
2556 if (ctx->keys_seen[i])
2557 continue;
2558 key_to_blob(ctx->keys[i], &blob, &len);
2559 buffer_put_string(b, blob, len);
2560 free(blob);
2561 blob = NULL;
2562 }
2563
2564 len = buffer_len(b);
2565 outmsg = begin_send_packet(pvar, SSH2_MSG_GLOBAL_REQUEST, len);
2566 memcpy(outmsg, buffer_ptr(b), len);
2567 finish_send_packet(pvar);
2568
2569 // SSH2_MSG_GLOBAL_REQUEST�����X�|���X�����������n���h�����o�^�����B
2570 client_register_global_confirm(client_global_hostkeys_private_confirm, ctx);
2571 ctx = NULL; // callback���������������A��������NULL���������������B
2572 }
2573
2574 success = 1;
2575
2576 error:
2577 buffer_free(b);
2578 hostkeys_update_ctx_free(ctx);
2579 free(blob);
2580
2581 return (success);
2582 }

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