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 5969 - (show annotations) (download) (as text)
Sat Aug 29 03:34:59 2015 UTC (8 years, 7 months ago) by maya
Original Path: trunk/ttssh2/ttxssh/key.c
File MIME type: text/x-csrc
File size: 55341 byte(s)
ホスト公開鍵更新の確認ダイアログを調整
1 /*
2 Copyright (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 "kex.h"
30 #include "resource.h"
31
32 #include <openssl/rsa.h>
33 #include <openssl/dsa.h>
34 #include <openssl/ecdsa.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 memset(digest, 'd', 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 memset(digest, 'd', sizeof(digest));
311 memset(sigblob, 's', 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 memset(digest, 'd', 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 memset(sigblob, 's', len);
437 free(sigblob);
438 }
439 if (sm) {
440 memset(sm, 'S', (size_t)smlen);
441 free(sm);
442 }
443 if (m) {
444 memset(m, '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 //
481 // RSA�\����������
482 //
483 RSA *duplicate_RSA(RSA *src)
484 {
485 RSA *rsa = NULL;
486
487 rsa = RSA_new();
488 if (rsa == NULL)
489 goto error;
490 rsa->n = BN_new();
491 rsa->e = BN_new();
492 if (rsa->n == NULL || rsa->e == NULL) {
493 RSA_free(rsa);
494 goto error;
495 }
496
497 // �[���R�s�[(deep copy)���s���B�����R�s�[(shallow copy)��NG�B
498 BN_copy(rsa->n, src->n);
499 BN_copy(rsa->e, src->e);
500
501 error:
502 return (rsa);
503 }
504
505
506 //
507 // DSA�\����������
508 //
509 DSA *duplicate_DSA(DSA *src)
510 {
511 DSA *dsa = NULL;
512
513 dsa = DSA_new();
514 if (dsa == NULL)
515 goto error;
516 dsa->p = BN_new();
517 dsa->q = BN_new();
518 dsa->g = BN_new();
519 dsa->pub_key = BN_new();
520 if (dsa->p == NULL ||
521 dsa->q == NULL ||
522 dsa->g == NULL ||
523 dsa->pub_key == NULL) {
524 DSA_free(dsa);
525 goto error;
526 }
527
528 // �[���R�s�[(deep copy)���s���B�����R�s�[(shallow copy)��NG�B
529 BN_copy(dsa->p, src->p);
530 BN_copy(dsa->q, src->q);
531 BN_copy(dsa->g, src->g);
532 BN_copy(dsa->pub_key, src->pub_key);
533
534 error:
535 return (dsa);
536 }
537
538 unsigned char *duplicate_ED25519_PK(unsigned char *src)
539 {
540 unsigned char *ptr = NULL;
541
542 ptr = malloc(ED25519_PK_SZ);
543 if (ptr) {
544 memcpy(ptr, src, ED25519_PK_SZ);
545 }
546 return (ptr);
547 }
548
549
550 char* key_fingerprint_raw(Key *k, enum fp_type dgst_type, int *dgst_raw_length)
551 {
552 const EVP_MD *md = NULL;
553 EVP_MD_CTX ctx;
554 char *blob = NULL;
555 char *retval = NULL;
556 int len = 0;
557 int nlen, elen;
558 RSA *rsa;
559
560 *dgst_raw_length = 0;
561
562 switch (dgst_type) {
563 case SSH_FP_MD5:
564 md = EVP_md5();
565 break;
566 case SSH_FP_SHA1:
567 md = EVP_sha1();
568 break;
569 case SSH_FP_SHA256:
570 md = EVP_sha256();
571 break;
572 default:
573 md = EVP_md5();
574 }
575
576 switch (k->type) {
577 case KEY_RSA1:
578 rsa = make_key(NULL, k->bits, k->exp, k->mod);
579 nlen = BN_num_bytes(rsa->n);
580 elen = BN_num_bytes(rsa->e);
581 len = nlen + elen;
582 blob = malloc(len);
583 if (blob == NULL) {
584 // TODO:
585 }
586 BN_bn2bin(rsa->n, blob);
587 BN_bn2bin(rsa->e, blob + nlen);
588 RSA_free(rsa);
589 break;
590
591 case KEY_DSA:
592 case KEY_RSA:
593 case KEY_ECDSA256:
594 case KEY_ECDSA384:
595 case KEY_ECDSA521:
596 case KEY_ED25519:
597 key_to_blob(k, &blob, &len);
598 break;
599
600 case KEY_UNSPEC:
601 return retval;
602 break;
603
604 default:
605 //fatal("key_fingerprint_raw: bad key type %d", k->type);
606 break;
607 }
608
609 if (blob != NULL) {
610 retval = malloc(EVP_MAX_MD_SIZE);
611 if (retval == NULL) {
612 // TODO:
613 }
614 EVP_DigestInit(&ctx, md);
615 EVP_DigestUpdate(&ctx, blob, len);
616 EVP_DigestFinal(&ctx, retval, dgst_raw_length);
617 memset(blob, 0, len);
618 free(blob);
619 } else {
620 //fatal("key_fingerprint_raw: blob is null");
621 }
622 return retval;
623 }
624
625
626 const char *
627 ssh_key_type(ssh_keytype type)
628 {
629 switch (type) {
630 case KEY_RSA1:
631 return "RSA1";
632 case KEY_RSA:
633 return "RSA";
634 case KEY_DSA:
635 return "DSA";
636 case KEY_ECDSA256:
637 case KEY_ECDSA384:
638 case KEY_ECDSA521:
639 return "ECDSA";
640 case KEY_ED25519:
641 return "ED25519";
642 }
643 return "unknown";
644 }
645
646 unsigned int
647 key_size(const Key *k)
648 {
649 switch (k->type) {
650 case KEY_RSA1:
651 // SSH1�������� key->rsa �� key->dsa �� NULL �����������A�g�������B
652 return k->bits;
653 case KEY_RSA:
654 return BN_num_bits(k->rsa->n);
655 case KEY_DSA:
656 return BN_num_bits(k->dsa->p);
657 case KEY_ECDSA256:
658 return 256;
659 case KEY_ECDSA384:
660 return 384;
661 case KEY_ECDSA521:
662 return 521;
663 case KEY_ED25519:
664 return 256; /* XXX */
665 }
666 return 0;
667 }
668
669 // based on OpenSSH 5.1
670 #define FLDBASE 8
671 #define FLDSIZE_Y (FLDBASE + 1)
672 #define FLDSIZE_X (FLDBASE * 2 + 1)
673 static char *
674 key_fingerprint_randomart(u_char *dgst_raw, u_int dgst_raw_len, const Key *k)
675 {
676 /*
677 * Chars to be used after each other every time the worm
678 * intersects with itself. Matter of taste.
679 */
680 char *augmentation_string = " .o+=*BOX@%&#/^SE";
681 char *retval, *p;
682 unsigned char field[FLDSIZE_X][FLDSIZE_Y];
683 unsigned int i, b;
684 int x, y;
685 size_t len = strlen(augmentation_string) - 1;
686
687 retval = calloc(1, (FLDSIZE_X + 3 + 1) * (FLDSIZE_Y + 2));
688
689 /* initialize field */
690 memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char));
691 x = FLDSIZE_X / 2;
692 y = FLDSIZE_Y / 2;
693
694 /* process raw key */
695 for (i = 0; i < dgst_raw_len; i++) {
696 int input;
697 /* each byte conveys four 2-bit move commands */
698 input = dgst_raw[i];
699 for (b = 0; b < 4; b++) {
700 /* evaluate 2 bit, rest is shifted later */
701 x += (input & 0x1) ? 1 : -1;
702 y += (input & 0x2) ? 1 : -1;
703
704 /* assure we are still in bounds */
705 x = max(x, 0);
706 y = max(y, 0);
707 x = min(x, FLDSIZE_X - 1);
708 y = min(y, FLDSIZE_Y - 1);
709
710 /* augment the field */
711 field[x][y]++;
712 input = input >> 2;
713 }
714 }
715
716 /* mark starting point and end point*/
717 field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1;
718 field[x][y] = len;
719
720 /* fill in retval */
721 _snprintf_s(retval, FLDSIZE_X, _TRUNCATE, "+--[%4s %4u]", ssh_key_type(k->type), key_size(k));
722 p = strchr(retval, '\0');
723
724 /* output upper border */
725 for (i = p - retval - 1; i < FLDSIZE_X; i++)
726 *p++ = '-';
727 *p++ = '+';
728 *p++ = '\r';
729 *p++ = '\n';
730
731 /* output content */
732 for (y = 0; y < FLDSIZE_Y; y++) {
733 *p++ = '|';
734 for (x = 0; x < FLDSIZE_X; x++)
735 *p++ = augmentation_string[min(field[x][y], len)];
736 *p++ = '|';
737 *p++ = '\r';
738 *p++ = '\n';
739 }
740
741 /* output lower border */
742 *p++ = '+';
743 for (i = 0; i < FLDSIZE_X; i++)
744 *p++ = '-';
745 *p++ = '+';
746
747 return retval;
748 }
749 #undef FLDBASE
750 #undef FLDSIZE_Y
751 #undef FLDSIZE_X
752
753 //
754 // fingerprint�i�w���F�z�X�g���J�����n�b�V���j����������
755 //
756 char *key_fingerprint(Key *key, enum fp_rep dgst_rep)
757 {
758 char *retval = NULL;
759 unsigned char *dgst_raw;
760 int dgst_raw_len;
761 int i, retval_len;
762
763 // fingerprint���n�b�V���l�i�o�C�i���j��������
764 dgst_raw = key_fingerprint_raw(key, SSH_FP_MD5, &dgst_raw_len);
765 if (dgst_raw == NULL)
766 return NULL;
767
768 if (dgst_rep == SSH_FP_HEX) {
769 // 16�i�\�L����������
770 retval_len = dgst_raw_len * 3 + 1;
771 retval = malloc(retval_len);
772 retval[0] = '\0';
773 for (i = 0; i < dgst_raw_len; i++) {
774 char hex[4];
775 _snprintf_s(hex, sizeof(hex), _TRUNCATE, "%02x:", dgst_raw[i]);
776 strncat_s(retval, retval_len, hex, _TRUNCATE);
777 }
778
779 /* Remove the trailing ':' character */
780 retval[(dgst_raw_len * 3) - 1] = '\0';
781
782 } else if (dgst_rep == SSH_FP_RANDOMART) {
783 retval = key_fingerprint_randomart(dgst_raw, dgst_raw_len, key);
784
785 } else {
786
787 }
788
789 memset(dgst_raw, 0, dgst_raw_len);
790 free(dgst_raw);
791
792 return (retval);
793 }
794
795 //
796 // �L�[�������������m��
797 //
798 static void key_add_private(Key *k)
799 {
800 switch (k->type) {
801 case KEY_RSA1:
802 case KEY_RSA:
803 k->rsa->d = BN_new();
804 k->rsa->iqmp = BN_new();
805 k->rsa->q = BN_new();
806 k->rsa->p = BN_new();
807 k->rsa->dmq1 = BN_new();
808 k->rsa->dmp1 = BN_new();
809 if (k->rsa->d == NULL || k->rsa->iqmp == NULL || k->rsa->q == NULL ||
810 k->rsa->p == NULL || k->rsa->dmq1 == NULL || k->rsa->dmp1 == NULL)
811 goto error;
812 break;
813
814 case KEY_DSA:
815 k->dsa->priv_key = BN_new();
816 if (k->dsa->priv_key == NULL)
817 goto error;
818 break;
819
820 case KEY_ECDSA256:
821 case KEY_ECDSA384:
822 case KEY_ECDSA521:
823 /* Cannot do anything until we know the group */
824 break;
825
826 case KEY_ED25519:
827 /* no need to prealloc */
828 break;
829
830 case KEY_UNSPEC:
831 break;
832
833 default:
834 goto error;
835 break;
836 }
837 return;
838
839 error:
840 if (k->rsa->d) {
841 BN_free(k->rsa->d);
842 k->rsa->d = NULL;
843 }
844 if (k->rsa->iqmp) {
845 BN_free(k->rsa->iqmp);
846 k->rsa->iqmp = NULL;
847 }
848 if (k->rsa->q) {
849 BN_free(k->rsa->q);
850 k->rsa->q = NULL;
851 }
852 if (k->rsa->p) {
853 BN_free(k->rsa->p);
854 k->rsa->p = NULL;
855 }
856 if (k->rsa->dmq1) {
857 BN_free(k->rsa->dmq1);
858 k->rsa->dmq1 = NULL;
859 }
860 if (k->rsa->dmp1) {
861 BN_free(k->rsa->dmp1);
862 k->rsa->dmp1 = NULL;
863 }
864
865
866 if (k->dsa->priv_key == NULL) {
867 BN_free(k->dsa->priv_key);
868 k->dsa->priv_key = NULL;
869 }
870
871 }
872
873 Key *key_new_private(int type)
874 {
875 Key *k = key_new(type);
876
877 key_add_private(k);
878 return (k);
879 }
880
881
882 Key *key_new(int type)
883 {
884 int success = 0;
885 Key *k = NULL;
886 RSA *rsa;
887 DSA *dsa;
888
889 k = calloc(1, sizeof(Key));
890 if (k == NULL)
891 goto error;
892 k->type = type;
893 k->ecdsa = NULL;
894 k->dsa = NULL;
895 k->rsa = NULL;
896 k->ed25519_pk = NULL;
897 k->ed25519_sk = NULL;
898
899 switch (k->type) {
900 case KEY_RSA1:
901 case KEY_RSA:
902 rsa = RSA_new();
903 if (rsa == NULL)
904 goto error;
905 rsa->n = BN_new();
906 rsa->e = BN_new();
907 if (rsa->n == NULL || rsa->e == NULL)
908 goto error;
909 k->rsa = rsa;
910 break;
911
912 case KEY_DSA:
913 dsa = DSA_new();
914 if (dsa == NULL)
915 goto error;
916 dsa->p = BN_new();
917 dsa->q = BN_new();
918 dsa->g = BN_new();
919 dsa->pub_key = BN_new();
920 if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL || dsa->pub_key == NULL)
921 goto error;
922 k->dsa = dsa;
923 break;
924
925 case KEY_ECDSA256:
926 case KEY_ECDSA384:
927 case KEY_ECDSA521:
928 /* Cannot do anything until we know the group */
929 break;
930
931 case KEY_ED25519:
932 /* no need to prealloc */
933 break;
934
935 case KEY_UNSPEC:
936 break;
937
938 default:
939 goto error;
940 break;
941 }
942 success = 1;
943
944 error:
945 if (success == 0) {
946 key_free(k);
947 k = NULL;
948 }
949 return (k);
950 }
951
952
953 //
954 // �L�[����������������
955 //
956 void key_free(Key *key)
957 {
958 if (key == NULL) {
959 return;
960 }
961
962 switch (key->type) {
963 case KEY_RSA1:
964 case KEY_RSA:
965 if (key->rsa != NULL)
966 RSA_free(key->rsa);
967 key->rsa = NULL;
968 break;
969
970 case KEY_DSA:
971 if (key->dsa != NULL)
972 DSA_free(key->dsa);
973 key->dsa = NULL;
974 break;
975
976 case KEY_ECDSA256:
977 case KEY_ECDSA384:
978 case KEY_ECDSA521:
979 if (key->ecdsa != NULL)
980 EC_KEY_free(key->ecdsa);
981 key->ecdsa = NULL;
982 break;
983
984 case KEY_ED25519:
985 if (key->ed25519_pk) {
986 memset(key->ed25519_pk, 0, ED25519_PK_SZ);
987 free(key->ed25519_pk);
988 key->ed25519_pk = NULL;
989 }
990 if (key->ed25519_sk) {
991 memset(key->ed25519_sk, 0, ED25519_SK_SZ);
992 free(key->ed25519_sk);
993 key->ed25519_sk = NULL;
994 }
995 break;
996 }
997 free(key);
998 }
999
1000 //
1001 // �L�[���������������p����
1002 //
1003 char *get_sshname_from_key(Key *key)
1004 {
1005 return get_ssh_keytype_name(key->type);
1006 }
1007
1008 //
1009 // �L�[������������������������
1010 //
1011 ssh_keytype get_keytype_from_name(char *name)
1012 {
1013 if (strcmp(name, "rsa1") == 0) {
1014 return KEY_RSA1;
1015 } else if (strcmp(name, "rsa") == 0) {
1016 return KEY_RSA;
1017 } else if (strcmp(name, "dsa") == 0) {
1018 return KEY_DSA;
1019 } else if (strcmp(name, "ssh-rsa") == 0) {
1020 return KEY_RSA;
1021 } else if (strcmp(name, "ssh-dss") == 0) {
1022 return KEY_DSA;
1023 } else if (strcmp(name, "ecdsa-sha2-nistp256") == 0) {
1024 return KEY_ECDSA256;
1025 } else if (strcmp(name, "ecdsa-sha2-nistp384") == 0) {
1026 return KEY_ECDSA384;
1027 } else if (strcmp(name, "ecdsa-sha2-nistp521") == 0) {
1028 return KEY_ECDSA521;
1029 } else if (strcmp(name, "ssh-ed25519") == 0) {
1030 return KEY_ED25519;
1031 }
1032 return KEY_UNSPEC;
1033 }
1034
1035
1036 ssh_keytype key_curve_name_to_keytype(char *name)
1037 {
1038 if (strcmp(name, "nistp256") == 0) {
1039 return KEY_ECDSA256;
1040 } else if (strcmp(name, "nistp384") == 0) {
1041 return KEY_ECDSA384;
1042 } else if (strcmp(name, "nistp521") == 0) {
1043 return KEY_ECDSA521;
1044 }
1045 return KEY_UNSPEC;
1046 }
1047
1048 char *curve_keytype_to_name(ssh_keytype type)
1049 {
1050 switch (type) {
1051 case KEY_ECDSA256:
1052 return "nistp256";
1053 break;
1054 case KEY_ECDSA384:
1055 return "nistp384";
1056 break;
1057 case KEY_ECDSA521:
1058 return "nistp521";
1059 break;
1060 }
1061 return NULL;
1062 }
1063
1064 //
1065 // �L�[���������o�b�t�@���������� (for SSH2)
1066 // NOTE:
1067 //
1068 int key_to_blob(Key *key, char **blobp, int *lenp)
1069 {
1070 buffer_t *b;
1071 char *sshname, *tmp;
1072 int len;
1073 int ret = 1; // success
1074
1075 b = buffer_init();
1076 sshname = get_sshname_from_key(key);
1077
1078 switch (key->type) {
1079 case KEY_RSA:
1080 buffer_put_string(b, sshname, strlen(sshname));
1081 buffer_put_bignum2(b, key->rsa->e);
1082 buffer_put_bignum2(b, key->rsa->n);
1083 break;
1084 case KEY_DSA:
1085 buffer_put_string(b, sshname, strlen(sshname));
1086 buffer_put_bignum2(b, key->dsa->p);
1087 buffer_put_bignum2(b, key->dsa->q);
1088 buffer_put_bignum2(b, key->dsa->g);
1089 buffer_put_bignum2(b, key->dsa->pub_key);
1090 break;
1091 case KEY_ECDSA256:
1092 case KEY_ECDSA384:
1093 case KEY_ECDSA521:
1094 buffer_put_string(b, sshname, strlen(sshname));
1095 tmp = curve_keytype_to_name(key->type);
1096 buffer_put_string(b, tmp, strlen(tmp));
1097 buffer_put_ecpoint(b, EC_KEY_get0_group(key->ecdsa),
1098 EC_KEY_get0_public_key(key->ecdsa));
1099 break;
1100 case KEY_ED25519:
1101 buffer_put_cstring(b, sshname);
1102 buffer_put_string(b, key->ed25519_pk, ED25519_PK_SZ);
1103 break;
1104
1105 default:
1106 ret = 0;
1107 goto error;
1108 }
1109
1110 len = buffer_len(b);
1111 if (lenp != NULL)
1112 *lenp = len;
1113 if (blobp != NULL) {
1114 *blobp = malloc(len);
1115 if (*blobp == NULL) {
1116 ret = 0;
1117 goto error;
1118 }
1119 memcpy(*blobp, buffer_ptr(b), len);
1120 }
1121
1122 error:
1123 buffer_free(b);
1124
1125 return (ret);
1126 }
1127
1128
1129 //
1130 // �o�b�t�@�����L�[�����������o��(for SSH2)
1131 // NOTE: ���l���A���P�[�g���������������A�����o�������������������B
1132 //
1133 Key *key_from_blob(char *data, int blen)
1134 {
1135 int keynamelen, len;
1136 char key[128];
1137 RSA *rsa = NULL;
1138 DSA *dsa = NULL;
1139 EC_KEY *ecdsa = NULL;
1140 EC_POINT *q = NULL;
1141 char *curve = NULL;
1142 Key *hostkey = NULL; // hostkey
1143 ssh_keytype type;
1144 unsigned char *pk = NULL;
1145
1146 if (data == NULL)
1147 goto error;
1148
1149 hostkey = malloc(sizeof(Key));
1150 if (hostkey == NULL)
1151 goto error;
1152
1153 memset(hostkey, 0, sizeof(Key));
1154
1155 keynamelen = get_uint32_MSBfirst(data);
1156 if (keynamelen >= sizeof(key)) {
1157 goto error;
1158 }
1159 data += 4;
1160 memcpy(key, data, keynamelen);
1161 key[keynamelen] = 0;
1162 data += keynamelen;
1163
1164 type = get_keytype_from_name(key);
1165
1166 switch (type) {
1167 case KEY_RSA: // RSA key
1168 rsa = RSA_new();
1169 if (rsa == NULL) {
1170 goto error;
1171 }
1172 rsa->n = BN_new();
1173 rsa->e = BN_new();
1174 if (rsa->n == NULL || rsa->e == NULL) {
1175 goto error;
1176 }
1177
1178 buffer_get_bignum2(&data, rsa->e);
1179 buffer_get_bignum2(&data, rsa->n);
1180
1181 hostkey->type = type;
1182 hostkey->rsa = rsa;
1183 break;
1184
1185 case KEY_DSA: // DSA key
1186 dsa = DSA_new();
1187 if (dsa == NULL) {
1188 goto error;
1189 }
1190 dsa->p = BN_new();
1191 dsa->q = BN_new();
1192 dsa->g = BN_new();
1193 dsa->pub_key = BN_new();
1194 if (dsa->p == NULL ||
1195 dsa->q == NULL ||
1196 dsa->g == NULL ||
1197 dsa->pub_key == NULL) {
1198 goto error;
1199 }
1200
1201 buffer_get_bignum2(&data, dsa->p);
1202 buffer_get_bignum2(&data, dsa->q);
1203 buffer_get_bignum2(&data, dsa->g);
1204 buffer_get_bignum2(&data, dsa->pub_key);
1205
1206 hostkey->type = type;
1207 hostkey->dsa = dsa;
1208 break;
1209
1210 case KEY_ECDSA256: // ECDSA
1211 case KEY_ECDSA384:
1212 case KEY_ECDSA521:
1213 curve = buffer_get_string(&data, NULL);
1214 if (type != key_curve_name_to_keytype(curve)) {
1215 goto error;
1216 }
1217
1218 ecdsa = EC_KEY_new_by_curve_name(keytype_to_cipher_nid(type));
1219 if (ecdsa == NULL) {
1220 goto error;
1221 }
1222
1223 q = EC_POINT_new(EC_KEY_get0_group(ecdsa));
1224 if (q == NULL) {
1225 goto error;
1226 }
1227
1228 buffer_get_ecpoint(&data, EC_KEY_get0_group(ecdsa), q);
1229 if (key_ec_validate_public(EC_KEY_get0_group(ecdsa), q) == -1) {
1230 goto error;
1231 }
1232
1233 if (EC_KEY_set_public_key(ecdsa, q) != 1) {
1234 goto error;
1235 }
1236
1237 hostkey->type = type;
1238 hostkey->ecdsa = ecdsa;
1239 break;
1240
1241 case KEY_ED25519:
1242 pk = buffer_get_string(&data, &len);
1243 if (pk == NULL)
1244 goto error;
1245 if (len != ED25519_PK_SZ)
1246 goto error;
1247
1248 hostkey->type = type;
1249 hostkey->ed25519_pk = pk;
1250 pk = NULL;
1251 break;
1252
1253 default: // unknown key
1254 goto error;
1255 }
1256
1257 return (hostkey);
1258
1259 error:
1260 if (rsa != NULL)
1261 RSA_free(rsa);
1262 if (dsa != NULL)
1263 DSA_free(dsa);
1264 if (ecdsa != NULL)
1265 EC_KEY_free(ecdsa);
1266
1267 free(hostkey);
1268
1269 return NULL;
1270 }
1271
1272
1273 static int ssh_ed25519_sign(Key *key, char **sigp, int *lenp, char *data, int datalen)
1274 {
1275 char *sig;
1276 int slen, len;
1277 unsigned long long smlen;
1278 int ret;
1279 buffer_t *b;
1280
1281 smlen = slen = datalen + crypto_sign_ed25519_BYTES;
1282 sig = malloc(slen);
1283
1284 if ((ret = crypto_sign_ed25519(sig, &smlen, data, datalen,
1285 key->ed25519_sk)) != 0 || smlen <= datalen) {
1286 //error("%s: crypto_sign_ed25519 failed: %d", __func__, ret);
1287 free(sig);
1288 return -1;
1289 }
1290 /* encode signature */
1291 b = buffer_init();
1292 buffer_put_cstring(b, "ssh-ed25519");
1293 buffer_put_string(b, sig, (int)(smlen - datalen));
1294 len = buffer_len(b);
1295 if (lenp != NULL)
1296 *lenp = len;
1297 if (sigp != NULL) {
1298 *sigp = malloc(len);
1299 memcpy(*sigp, buffer_ptr(b), len);
1300 }
1301 buffer_free(b);
1302 memset(sig, 's', slen);
1303 free(sig);
1304
1305 return 0;
1306 }
1307
1308
1309 BOOL generate_SSH2_keysign(Key *keypair, char **sigptr, int *siglen, char *data, int datalen)
1310 {
1311 buffer_t *msg = NULL;
1312 char *s;
1313 int ret;
1314
1315 msg = buffer_init();
1316 if (msg == NULL) {
1317 // TODO: error check
1318 return FALSE;
1319 }
1320
1321 switch (keypair->type) {
1322 case KEY_RSA: // RSA
1323 {
1324 const EVP_MD *evp_md = EVP_sha1();
1325 EVP_MD_CTX md;
1326 u_char digest[EVP_MAX_MD_SIZE], *sig;
1327 u_int slen, dlen, len;
1328 int ok, nid = NID_sha1;
1329
1330 // �_�C�W�F�X�g�l���v�Z
1331 EVP_DigestInit(&md, evp_md);
1332 EVP_DigestUpdate(&md, data, datalen);
1333 EVP_DigestFinal(&md, digest, &dlen);
1334
1335 slen = RSA_size(keypair->rsa);
1336 sig = malloc(slen);
1337 if (sig == NULL)
1338 goto error;
1339
1340 // �d�q�������v�Z
1341 ok = RSA_sign(nid, digest, dlen, sig, &len, keypair->rsa);
1342 memset(digest, 'd', sizeof(digest));
1343 if (ok != 1) { // error
1344 free(sig);
1345 goto error;
1346 }
1347 // �������T�C�Y���o�b�t�@���������������A�������������B�������[�����������B
1348 if (len < slen) {
1349 u_int diff = slen - len;
1350 memmove(sig + diff, sig, len);
1351 memset(sig, 0, diff);
1352
1353 } else if (len > slen) {
1354 free(sig);
1355 goto error;
1356
1357 } else {
1358 // do nothing
1359
1360 }
1361
1362 s = get_sshname_from_key(keypair);
1363 buffer_put_string(msg, s, strlen(s));
1364 buffer_append_length(msg, sig, slen);
1365 len = buffer_len(msg);
1366
1367 // setting
1368 *siglen = len;
1369 *sigptr = malloc(len);
1370 if (*sigptr == NULL) {
1371 free(sig);
1372 goto error;
1373 }
1374 memcpy(*sigptr, buffer_ptr(msg), len);
1375 free(sig);
1376
1377 break;
1378 }
1379 case KEY_DSA: // DSA
1380 {
1381 DSA_SIG *sig;
1382 const EVP_MD *evp_md = EVP_sha1();
1383 EVP_MD_CTX md;
1384 u_char digest[EVP_MAX_MD_SIZE], sigblob[SIGBLOB_LEN];
1385 u_int rlen, slen, len, dlen;
1386
1387 // �_�C�W�F�X�g���v�Z
1388 EVP_DigestInit(&md, evp_md);
1389 EVP_DigestUpdate(&md, data, datalen);
1390 EVP_DigestFinal(&md, digest, &dlen);
1391
1392 // DSA�d�q�������v�Z
1393 sig = DSA_do_sign(digest, dlen, keypair->dsa);
1394 memset(digest, 'd', sizeof(digest));
1395 if (sig == NULL) {
1396 goto error;
1397 }
1398
1399 // BIGNUM�����o�C�i���l��������
1400 rlen = BN_num_bytes(sig->r);
1401 slen = BN_num_bytes(sig->s);
1402 if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) {
1403 DSA_SIG_free(sig);
1404 goto error;
1405 }
1406 memset(sigblob, 0, SIGBLOB_LEN);
1407 BN_bn2bin(sig->r, sigblob+ SIGBLOB_LEN - INTBLOB_LEN - rlen);
1408 BN_bn2bin(sig->s, sigblob+ SIGBLOB_LEN - slen);
1409 DSA_SIG_free(sig);
1410
1411 // setting
1412 s = get_sshname_from_key(keypair);
1413 buffer_put_string(msg, s, strlen(s));
1414 buffer_append_length(msg, sigblob, sizeof(sigblob));
1415 len = buffer_len(msg);
1416
1417 // setting
1418 *siglen = len;
1419 *sigptr = malloc(len);
1420 if (*sigptr == NULL) {
1421 goto error;
1422 }
1423 memcpy(*sigptr, buffer_ptr(msg), len);
1424
1425 break;
1426 }
1427 case KEY_ECDSA256: // ECDSA
1428 case KEY_ECDSA384:
1429 case KEY_ECDSA521:
1430 {
1431 ECDSA_SIG *sig;
1432 const EVP_MD *evp_md;
1433 EVP_MD_CTX md;
1434 u_char digest[EVP_MAX_MD_SIZE];
1435 u_int len, dlen, nid;
1436 buffer_t *buf2 = NULL;
1437
1438 nid = keytype_to_hash_nid(keypair->type);
1439 if ((evp_md = EVP_get_digestbynid(nid)) == NULL) {
1440 goto error;
1441 }
1442 EVP_DigestInit(&md, evp_md);
1443 EVP_DigestUpdate(&md, data, datalen);
1444 EVP_DigestFinal(&md, digest, &dlen);
1445
1446 sig = ECDSA_do_sign(digest, dlen, keypair->ecdsa);
1447 memset(digest, 'd', sizeof(digest));
1448
1449 if (sig == NULL) {
1450 goto error;
1451 }
1452
1453 buf2 = buffer_init();
1454 if (buf2 == NULL) {
1455 // TODO: error check
1456 goto error;
1457 }
1458 buffer_put_bignum2(buf2, sig->r);
1459 buffer_put_bignum2(buf2, sig->s);
1460 ECDSA_SIG_free(sig);
1461
1462 s = get_sshname_from_key(keypair);
1463 buffer_put_string(msg, s, strlen(s));
1464 buffer_put_string(msg, buffer_ptr(buf2), buffer_len(buf2));
1465 buffer_free(buf2);
1466 len = buffer_len(msg);
1467
1468 *siglen = len;
1469 *sigptr = malloc(len);
1470 if (*sigptr == NULL) {
1471 goto error;
1472 }
1473 memcpy(*sigptr, buffer_ptr(msg), len);
1474
1475 break;
1476 }
1477
1478 case KEY_ED25519:
1479 ret = ssh_ed25519_sign(keypair, sigptr, siglen, data, datalen);
1480 if (ret != 0)
1481 goto error;
1482 break;
1483
1484 default:
1485 buffer_free(msg);
1486 return FALSE;
1487 break;
1488 }
1489
1490 buffer_free(msg);
1491 return TRUE;
1492
1493 error:
1494 buffer_free(msg);
1495
1496 return FALSE;
1497 }
1498
1499
1500 BOOL get_SSH2_publickey_blob(PTInstVar pvar, buffer_t **blobptr, int *bloblen)
1501 {
1502 buffer_t *msg = NULL;
1503 Key *keypair;
1504 char *s, *tmp;
1505
1506 msg = buffer_init();
1507 if (msg == NULL) {
1508 // TODO: error check
1509 return FALSE;
1510 }
1511
1512 keypair = pvar->auth_state.cur_cred.key_pair;
1513
1514 switch (keypair->type) {
1515 case KEY_RSA: // RSA
1516 s = get_sshname_from_key(keypair);
1517 buffer_put_string(msg, s, strlen(s));
1518 buffer_put_bignum2(msg, keypair->rsa->e); // ���J�w��
1519 buffer_put_bignum2(msg, keypair->rsa->n); // p�~q
1520 break;
1521 case KEY_DSA: // DSA
1522 s = get_sshname_from_key(keypair);
1523 buffer_put_string(msg, s, strlen(s));
1524 buffer_put_bignum2(msg, keypair->dsa->p); // �f��
1525 buffer_put_bignum2(msg, keypair->dsa->q); // (p-1)���f����
1526 buffer_put_bignum2(msg, keypair->dsa->g); // ����
1527 buffer_put_bignum2(msg, keypair->dsa->pub_key); // ���J��
1528 break;
1529 case KEY_ECDSA256: // ECDSA
1530 case KEY_ECDSA384:
1531 case KEY_ECDSA521:
1532 s = get_sshname_from_key(keypair);
1533 buffer_put_string(msg, s, strlen(s));
1534 tmp = curve_keytype_to_name(keypair->type);
1535 buffer_put_string(msg, tmp, strlen(tmp));
1536 buffer_put_ecpoint(msg, EC_KEY_get0_group(keypair->ecdsa),
1537 EC_KEY_get0_public_key(keypair->ecdsa));
1538 break;
1539 case KEY_ED25519:
1540 s = get_sshname_from_key(keypair);
1541 buffer_put_cstring(msg, s);
1542 buffer_put_string(msg, keypair->ed25519_pk, ED25519_PK_SZ);
1543 break;
1544 default:
1545 return FALSE;
1546 }
1547
1548 *blobptr = msg;
1549 *bloblen = buffer_len(msg);
1550
1551 return TRUE;
1552 }
1553
1554 int kextype_to_cipher_nid(kex_algorithm type)
1555 {
1556 switch (type) {
1557 case KEX_ECDH_SHA2_256:
1558 return NID_X9_62_prime256v1;
1559 case KEX_ECDH_SHA2_384:
1560 return NID_secp384r1;
1561 case KEX_ECDH_SHA2_521:
1562 return NID_secp521r1;
1563 }
1564 return NID_undef;
1565 }
1566
1567 int keytype_to_hash_nid(ssh_keytype type)
1568 {
1569 switch (type) {
1570 case KEY_ECDSA256:
1571 return NID_sha256;
1572 case KEY_ECDSA384:
1573 return NID_sha384;
1574 case KEY_ECDSA521:
1575 return NID_sha512;
1576 }
1577 return NID_undef;
1578 }
1579
1580 int keytype_to_cipher_nid(ssh_keytype type)
1581 {
1582 switch (type) {
1583 case KEY_ECDSA256:
1584 return NID_X9_62_prime256v1;
1585 case KEY_ECDSA384:
1586 return NID_secp384r1;
1587 case KEY_ECDSA521:
1588 return NID_secp521r1;
1589 }
1590 return NID_undef;
1591 }
1592
1593 ssh_keytype nid_to_keytype(int nid)
1594 {
1595 switch (nid) {
1596 case NID_X9_62_prime256v1:
1597 return KEY_ECDSA256;
1598 case NID_secp384r1:
1599 return KEY_ECDSA384;
1600 case NID_secp521r1:
1601 return KEY_ECDSA521;
1602 }
1603 return KEY_UNSPEC;
1604 }
1605
1606 void key_private_serialize(Key *key, buffer_t *b)
1607 {
1608 char *s;
1609
1610 s = get_sshname_from_key(key);
1611 buffer_put_cstring(b, s);
1612
1613 switch (key->type) {
1614 case KEY_RSA:
1615 buffer_put_bignum2(b, key->rsa->n);
1616 buffer_put_bignum2(b, key->rsa->e);
1617 buffer_put_bignum2(b, key->rsa->d);
1618 buffer_put_bignum2(b, key->rsa->iqmp);
1619 buffer_put_bignum2(b, key->rsa->p);
1620 buffer_put_bignum2(b, key->rsa->q);
1621 break;
1622
1623 case KEY_DSA:
1624 buffer_put_bignum2(b, key->dsa->p);
1625 buffer_put_bignum2(b, key->dsa->q);
1626 buffer_put_bignum2(b, key->dsa->g);
1627 buffer_put_bignum2(b, key->dsa->pub_key);
1628 buffer_put_bignum2(b, key->dsa->priv_key);
1629 break;
1630
1631 case KEY_ECDSA256:
1632 case KEY_ECDSA384:
1633 case KEY_ECDSA521:
1634 buffer_put_cstring(b, curve_keytype_to_name(key->type));
1635 buffer_put_ecpoint(b, EC_KEY_get0_group(key->ecdsa),
1636 EC_KEY_get0_public_key(key->ecdsa));
1637 buffer_put_bignum2(b, (BIGNUM *)EC_KEY_get0_private_key(key->ecdsa));
1638 break;
1639
1640 case KEY_ED25519:
1641 buffer_put_string(b, key->ed25519_pk, ED25519_PK_SZ);
1642 buffer_put_string(b, key->ed25519_sk, ED25519_SK_SZ);
1643 break;
1644
1645 default:
1646 break;
1647 }
1648 }
1649
1650 /* calculate p-1 and q-1 */
1651 static void rsa_generate_additional_parameters(RSA *rsa)
1652 {
1653 BIGNUM *aux = NULL;
1654 BN_CTX *ctx = NULL;
1655
1656 if ((aux = BN_new()) == NULL)
1657 goto error;
1658 if ((ctx = BN_CTX_new()) == NULL)
1659 goto error;
1660
1661 if ((BN_sub(aux, rsa->q, BN_value_one()) == 0) ||
1662 (BN_mod(rsa->dmq1, rsa->d, aux, ctx) == 0) ||
1663 (BN_sub(aux, rsa->p, BN_value_one()) == 0) ||
1664 (BN_mod(rsa->dmp1, rsa->d, aux, ctx) == 0))
1665 goto error;
1666
1667 error:
1668 if (aux)
1669 BN_clear_free(aux);
1670 if (ctx)
1671 BN_CTX_free(ctx);
1672 }
1673
1674 static int key_ec_validate_private(EC_KEY *key)
1675 {
1676 BN_CTX *bnctx = NULL;
1677 BIGNUM *order, *tmp;
1678 int ret = -1;
1679
1680 if ((bnctx = BN_CTX_new()) == NULL)
1681 goto out;
1682 BN_CTX_start(bnctx);
1683
1684 if ((order = BN_CTX_get(bnctx)) == NULL ||
1685 (tmp = BN_CTX_get(bnctx)) == NULL)
1686 goto out;
1687
1688 /* log2(private) > log2(order)/2 */
1689 if (EC_GROUP_get_order(EC_KEY_get0_group(key), order, bnctx) != 1)
1690 goto out;
1691 if (BN_num_bits(EC_KEY_get0_private_key(key)) <=
1692 BN_num_bits(order) / 2) {
1693 goto out;
1694 }
1695
1696 /* private < order - 1 */
1697 if (!BN_sub(tmp, order, BN_value_one()))
1698 goto out;
1699 if (BN_cmp(EC_KEY_get0_private_key(key), tmp) >= 0) {
1700 goto out;
1701 }
1702 ret = 0;
1703
1704 out:
1705 if (bnctx)
1706 BN_CTX_free(bnctx);
1707 return ret;
1708 }
1709
1710 Key *key_private_deserialize(buffer_t *blob)
1711 {
1712 int success = 0;
1713 char *type_name = NULL;
1714 Key *k = NULL;
1715 unsigned int pklen, sklen;
1716 int type;
1717
1718 type_name = buffer_get_string_msg(blob, NULL);
1719 if (type_name == NULL)
1720 goto error;
1721 type = get_keytype_from_name(type_name);
1722
1723 k = key_new_private(type);
1724
1725 switch (type) {
1726 case KEY_RSA:
1727 buffer_get_bignum2_msg(blob, k->rsa->n);
1728 buffer_get_bignum2_msg(blob, k->rsa->e);
1729 buffer_get_bignum2_msg(blob, k->rsa->d);
1730 buffer_get_bignum2_msg(blob, k->rsa->iqmp);
1731 buffer_get_bignum2_msg(blob, k->rsa->p);
1732 buffer_get_bignum2_msg(blob, k->rsa->q);
1733
1734 /* Generate additional parameters */
1735 rsa_generate_additional_parameters(k->rsa);
1736 break;
1737
1738 case KEY_DSA:
1739 buffer_get_bignum2_msg(blob, k->dsa->p);
1740 buffer_get_bignum2_msg(blob, k->dsa->q);
1741 buffer_get_bignum2_msg(blob, k->dsa->g);
1742 buffer_get_bignum2_msg(blob, k->dsa->pub_key);
1743 buffer_get_bignum2_msg(blob, k->dsa->priv_key);
1744 break;
1745
1746 case KEY_ECDSA256:
1747 case KEY_ECDSA384:
1748 case KEY_ECDSA521:
1749 {
1750 int success = 0;
1751 unsigned int nid;
1752 char *curve = NULL;
1753 ssh_keytype skt;
1754 BIGNUM *exponent = NULL;
1755 EC_POINT *q = NULL;
1756
1757 nid = keytype_to_cipher_nid(type);
1758 curve = buffer_get_string_msg(blob, NULL);
1759 skt = key_curve_name_to_keytype(curve);
1760 if (nid != keytype_to_cipher_nid(skt))
1761 goto ecdsa_error;
1762
1763 k->ecdsa = EC_KEY_new_by_curve_name(nid);
1764 if (k->ecdsa == NULL)
1765 goto ecdsa_error;
1766
1767 q = EC_POINT_new(EC_KEY_get0_group(k->ecdsa));
1768 if (q == NULL)
1769 goto ecdsa_error;
1770
1771 if ((exponent = BN_new()) == NULL)
1772 goto ecdsa_error;
1773 buffer_get_ecpoint_msg(blob,
1774 EC_KEY_get0_group(k->ecdsa), q);
1775 buffer_get_bignum2_msg(blob, exponent);
1776 if (EC_KEY_set_public_key(k->ecdsa, q) != 1)
1777 goto ecdsa_error;
1778 if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1)
1779 goto ecdsa_error;
1780 if (key_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
1781 EC_KEY_get0_public_key(k->ecdsa)) != 0)
1782 goto ecdsa_error;
1783 if (key_ec_validate_private(k->ecdsa) != 0)
1784 goto ecdsa_error;
1785
1786 success = 1;
1787
1788 ecdsa_error:
1789 free(curve);
1790 if (exponent)
1791 BN_clear_free(exponent);
1792 if (q)
1793 EC_POINT_free(q);
1794 if (success == 0)
1795 goto error;
1796 }
1797 break;
1798
1799 case KEY_ED25519:
1800 k->ed25519_pk = buffer_get_string_msg(blob, &pklen);
1801 k->ed25519_sk = buffer_get_string_msg(blob, &sklen);
1802 if (pklen != ED25519_PK_SZ)
1803 goto error;
1804 if (sklen != ED25519_SK_SZ)
1805 goto error;
1806 break;
1807
1808 default:
1809 goto error;
1810 break;
1811 }
1812
1813 /* enable blinding */
1814 switch (k->type) {
1815 case KEY_RSA1:
1816 case KEY_RSA:
1817 if (RSA_blinding_on(k->rsa, NULL) != 1)
1818 goto error;
1819 break;
1820 }
1821
1822 success = 1;
1823
1824 error:
1825 free(type_name);
1826
1827 if (success == 0) {
1828 key_free(k);
1829 k = NULL;
1830 }
1831
1832 return (k);
1833 }
1834
1835
1836 static void hostkeys_update_ctx_free(struct hostkeys_update_ctx *ctx)
1837 {
1838 size_t i;
1839
1840 if (ctx == NULL)
1841 return;
1842 for (i = 0; i < ctx->nkeys; i++)
1843 key_free(ctx->keys[i]);
1844 free(ctx->keys);
1845 free(ctx->keys_seen);
1846 for (i = 0; i < ctx->nold; i++)
1847 key_free(ctx->old_keys[i]);
1848 free(ctx->old_keys);
1849 free(ctx->host_str);
1850 free(ctx->ip_str);
1851 free(ctx);
1852 }
1853
1854
1855 // �����������z�X�g���A���S���Y�������`�F�b�N�����B
1856 //
1857 // return 1: matched
1858 // 0: not matched
1859 //
1860 static int check_hostkey_algorithm(PTInstVar pvar, Key *key)
1861 {
1862 int ret = 0;
1863 int i, index;
1864
1865 for (i = 0; pvar->settings.HostKeyOrder[i] != 0; i++) {
1866 index = pvar->settings.HostKeyOrder[i] - '0';
1867 if (index == KEY_NONE) // disabled line
1868 break;
1869
1870 if (strcmp(get_sshname_from_key(key), get_ssh_keytype_name(index)) == 0)
1871 return 1;
1872 }
1873
1874 return (ret);
1875 }
1876
1877 // Callback function
1878 //
1879 // argument:
1880 // key: known_hosts���o�^������������
1881 // _ctx: �T�[�o�����������������������Q
1882 //
1883 // return:
1884 // 1: deprecated key�������A��������key�������������~�B
1885 // 0: ����������key�������������K�v�B
1886 static int hostkeys_find(Key *key, void *_ctx)
1887 {
1888 struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx;
1889 int ret = 0;
1890 size_t i;
1891 Key **tmp;
1892
1893 // SSH1�������O�B
1894 if (key->type == KEY_RSA1)
1895 goto error;
1896
1897 // �������o�^�������������������T���B
1898 for (i = 0; i < ctx->nkeys; i++) {
1899 if (HOSTS_compare_public_key(key, ctx->keys[i]) == 1) {
1900 ctx->keys_seen[i] = 1;
1901 goto error;
1902 }
1903 }
1904
1905 // deprecated�������A�����������X�g�������������B
1906 tmp = realloc(ctx->old_keys, (ctx->nold + 1)*sizeof(*ctx->old_keys));
1907 if (tmp != NULL) {
1908 ctx->old_keys = tmp;
1909 ctx->old_keys[ctx->nold++] = key;
1910 }
1911
1912 ret = 1;
1913
1914 error:
1915 return (ret);
1916 }
1917
1918 static BOOL CALLBACK hosts_updatekey_dlg_proc(HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam)
1919 {
1920 static HFONT DlgHostsAddFont;
1921 PTInstVar pvar;
1922 LOGFONT logfont;
1923 HFONT font;
1924 char buf[1024];
1925 char *host;
1926 struct hostkeys_update_ctx *ctx;
1927 char *fp;
1928 size_t i;
1929 char uimsg[MAX_UIMSG];
1930
1931 switch (msg) {
1932 case WM_INITDIALOG:
1933 pvar = (PTInstVar)lParam;
1934 SetWindowLong(dlg, DWL_USER, lParam);
1935
1936 GetWindowText(dlg, uimsg, sizeof(uimsg));
1937 UTIL_get_lang_msg("DLG_HOSTKEY_ROTATION_TITLE", pvar, uimsg);
1938 SetWindowText(dlg, pvar->ts->UIMsg);
1939
1940 host = pvar->ssh_state.hostname;
1941 ctx = pvar->hostkey_ctx;
1942
1943 GetDlgItemText(dlg, IDC_HOSTKEY_MESSAGE, uimsg, sizeof(uimsg));
1944 UTIL_get_lang_msg("DLG_HOSTKEY_ROTATION_WARNING", pvar, uimsg);
1945 _snprintf_s(buf, sizeof(buf), _TRUNCATE,
1946 pvar->ts->UIMsg, host, ctx->nnew, ctx->nold
1947 );
1948 SetDlgItemText(dlg, IDC_HOSTKEY_MESSAGE, buf);
1949
1950 GetDlgItemText(dlg, IDC_ADDKEY_TEXT, uimsg, sizeof(uimsg));
1951 UTIL_get_lang_msg("DLG_HOSTKEY_ROTATION_ADD", pvar, uimsg);
1952 _snprintf_s(buf, sizeof(buf), _TRUNCATE, pvar->ts->UIMsg, ctx->nnew);
1953 SetDlgItemText(dlg, IDC_ADDKEY_TEXT, buf);
1954 for (i = 0; i < ctx->nkeys; i++) {
1955 if (ctx->keys_seen[i])
1956 continue;
1957 fp = key_fingerprint(ctx->keys[i], SSH_FP_HEX);
1958 buf[0] = 0;
1959 strcat_s(buf, sizeof(buf), get_sshname_from_key(ctx->keys[i]));
1960 strcat_s(buf, sizeof(buf), " ");
1961 strcat_s(buf, sizeof(buf), fp);
1962 SendDlgItemMessage(dlg, IDC_ADDKEY_EDIT, EM_REPLACESEL, 0, (LPARAM)buf);
1963 SendDlgItemMessage(dlg, IDC_ADDKEY_EDIT, EM_REPLACESEL, 0, (LPARAM)"\r\n");
1964 free(fp);
1965 }
1966
1967 GetDlgItemText(dlg, IDC_REMOVEKEY_TEXT, uimsg, sizeof(uimsg));
1968 UTIL_get_lang_msg("DLG_HOSTKEY_ROTATION_REMOVE", pvar, uimsg);
1969 _snprintf_s(buf, sizeof(buf), _TRUNCATE, pvar->ts->UIMsg, ctx->nold);
1970 SetDlgItemText(dlg, IDC_REMOVEKEY_TEXT, buf);
1971 for (i = 0; i < ctx->nold; i++) {
1972 fp = key_fingerprint(ctx->old_keys[i], SSH_FP_HEX);
1973 buf[0] = 0;
1974 strcat_s(buf, sizeof(buf), get_sshname_from_key(ctx->old_keys[i]));
1975 strcat_s(buf, sizeof(buf), " ");
1976 strcat_s(buf, sizeof(buf), fp);
1977 SendDlgItemMessage(dlg, IDC_REMOVEKEY_EDIT, EM_REPLACESEL, 0, (LPARAM)buf);
1978 SendDlgItemMessage(dlg, IDC_REMOVEKEY_EDIT, EM_REPLACESEL, 0, (LPARAM)"\r\n");
1979 free(fp);
1980 }
1981
1982 GetDlgItemText(dlg, IDOK, uimsg, sizeof(uimsg));
1983 UTIL_get_lang_msg("BTN_YES", pvar, uimsg);
1984 SetDlgItemText(dlg, IDOK, pvar->ts->UIMsg);
1985 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1986 UTIL_get_lang_msg("BTN_NO", pvar, uimsg);
1987 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1988
1989 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1990 GetObject(font, sizeof(LOGFONT), &logfont);
1991 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsAddFont, pvar)) {
1992 SendDlgItemMessage(dlg, IDC_HOSTKEY_MESSAGE, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
1993 SendDlgItemMessage(dlg, IDC_ADDKEY_TEXT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
1994 SendDlgItemMessage(dlg, IDC_ADDKEY_EDIT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
1995 SendDlgItemMessage(dlg, IDC_REMOVEKEY_TEXT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
1996 SendDlgItemMessage(dlg, IDC_REMOVEKEY_EDIT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
1997 SendDlgItemMessage(dlg, IDOK, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
1998 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
1999 }
2000 else {
2001 DlgHostsAddFont = NULL;
2002 }
2003
2004 return TRUE; /* because we do not set the focus */
2005
2006 case WM_COMMAND:
2007 pvar = (PTInstVar)GetWindowLong(dlg, DWL_USER);
2008
2009 switch (LOWORD(wParam)) {
2010 case IDOK:
2011
2012 EndDialog(dlg, 1);
2013
2014 if (DlgHostsAddFont != NULL) {
2015 DeleteObject(DlgHostsAddFont);
2016 }
2017
2018 return TRUE;
2019
2020 case IDCANCEL: /* kill the connection */
2021 EndDialog(dlg, 0);
2022
2023 if (DlgHostsAddFont != NULL) {
2024 DeleteObject(DlgHostsAddFont);
2025 }
2026
2027 return TRUE;
2028
2029 default:
2030 return FALSE;
2031 }
2032
2033 default:
2034 return FALSE;
2035 }
2036 }
2037
2038 static void update_known_hosts(PTInstVar pvar, struct hostkeys_update_ctx *ctx)
2039 {
2040 size_t i;
2041 int dlgresult;
2042 char msg[1024];
2043 char *host;
2044
2045 host = pvar->ssh_state.hostname;
2046
2047 // "/nosecuritywarning"���w�����������������A�X�V�������s�������B
2048 if (pvar->nocheck_known_hosts) {
2049 _snprintf_s(msg, sizeof(msg), _TRUNCATE, "Hostkey was not updated because `/nosecuritywarning' option was specified.");
2050 notify_verbose_message(pvar, msg, LOG_LEVEL_VERBOSE);
2051 goto error;
2052 }
2053
2054 // known_hosts�t�@�C�����X�V���s�������A���[�U���������������s���B
2055 if (pvar->settings.UpdateHostkeys == SSH_UPDATE_HOSTKEYS_ASK) {
2056 HWND cur_active = GetActiveWindow();
2057
2058 pvar->hostkey_ctx = ctx;
2059 dlgresult = DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHUPDATE_HOSTKEY),
2060 cur_active != NULL ? cur_active : pvar->NotificationWindow,
2061 hosts_updatekey_dlg_proc, (LPARAM)pvar);
2062 if (dlgresult != 1) {
2063 _snprintf_s(msg, sizeof(msg), _TRUNCATE, "Hostkey was not updated because a user cancelled.");
2064 notify_verbose_message(pvar, msg, LOG_LEVEL_VERBOSE);
2065 goto error;
2066 }
2067 }
2068
2069 // �����L�[�����������������B
2070 HOSTS_delete_all_hostkeys(pvar);
2071
2072 // �V�����L�[���������o�^�����B
2073 for (i = 0; i < ctx->nkeys; i++) {
2074 HOSTS_add_host_key(pvar, ctx->keys[i]);
2075 }
2076 _snprintf_s(msg, sizeof(msg), _TRUNCATE, "Hostkey was successfully updated to known_hosts file.");
2077 notify_verbose_message(pvar, msg, LOG_LEVEL_VERBOSE);
2078
2079 error:
2080 return;
2081 }
2082
2083 static void client_global_hostkeys_private_confirm(PTInstVar pvar, int type, u_int32_t seq, void *_ctx)
2084 {
2085 struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx;
2086 char msg[128];
2087 char *data;
2088 int len;
2089 unsigned char *blob = NULL;
2090 int bloblen;
2091 buffer_t *b = NULL;
2092 buffer_t *bsig = NULL;
2093 char *cp, *sig;
2094 size_t i, ndone, siglen;
2095 int ret;
2096
2097 // SSH2 packet format:
2098 // [size(4) + padding size(1) + type(1)] + [payload(N) + padding(X)]
2099 // header body
2100 // ^data
2101 // <-----------------size------------------------------->
2102 // <---------len-------->
2103 //
2104 // data = payload(N) + padding(X): �p�f�B���O���������{�f�B���������w���B
2105 data = pvar->ssh_state.payload;
2106 // len = size - (padding size + 1): �p�f�B���O�������{�f�B�Btype�����������������B
2107 len = pvar->ssh_state.payloadlen;
2108 len--; // type ��������
2109
2110 bsig = buffer_init();
2111 if (bsig == NULL)
2112 goto error;
2113 cp = buffer_append_space(bsig, len);
2114 memcpy(cp, data, len);
2115
2116 if (ctx->nnew == 0) {
2117 _snprintf_s(msg, sizeof(msg), _TRUNCATE, "Hostkey can not be updated because ctx->nnew %d(program bug).", ctx->nnew);
2118 notify_verbose_message(pvar, msg, LOG_LEVEL_FATAL);
2119 goto error;
2120 }
2121 if (type != SSH2_MSG_REQUEST_SUCCESS) {
2122 _snprintf_s(msg, sizeof(msg), _TRUNCATE, "Server failed to confirm ownership of private host keys(type %d)", type);
2123 notify_verbose_message(pvar, msg, LOG_LEVEL_ERROR);
2124 goto error;
2125 }
2126 if (pvar->session_id_len == 0) {
2127 _snprintf_s(msg, sizeof(msg), _TRUNCATE, "Hostkey can not be updated because pvar->session_id_len %d(program bug).", pvar->session_id_len);
2128 notify_verbose_message(pvar, msg, LOG_LEVEL_FATAL);
2129 goto error;
2130 }
2131
2132 b = buffer_init();
2133 if (b == NULL)
2134 goto error;
2135
2136 ndone = 0;
2137 for (i = 0; i < ctx->nkeys; i++) {
2138 if (ctx->keys_seen[i])
2139 continue;
2140
2141 buffer_clear(b);
2142 buffer_put_cstring(b, "hostkeys-prove-00@openssh.com");
2143 buffer_put_string(b, pvar->session_id, pvar->session_id_len);
2144 key_to_blob(ctx->keys[i], &blob, &bloblen);
2145 buffer_put_string(b, blob, bloblen);
2146 free(blob);
2147 blob = NULL;
2148
2149 sig = buffer_get_string_msg(bsig, &siglen);
2150 // Verify signature
2151 ret = key_verify(ctx->keys[i], sig, siglen, buffer_ptr(b), buffer_len(b));
2152 free(sig);
2153 sig = NULL;
2154 if (ret != 1) {
2155 _snprintf_s(msg, sizeof(msg), _TRUNCATE, "server gave bad signature for %s key %u",
2156 get_sshname_from_key(ctx->keys[i]), i);
2157 notify_verbose_message(pvar, msg, LOG_LEVEL_ERROR);
2158 goto error;
2159 }
2160 ndone++;
2161 }
2162
2163 if (ndone != ctx->nnew) {
2164 _snprintf_s(msg, sizeof(msg), _TRUNCATE, "Hostkey can not be updated because ndone != ctx->nnew (%u / %u)(program bug).",
2165 ndone, ctx->nnew);
2166 notify_verbose_message(pvar, msg, LOG_LEVEL_FATAL);
2167 goto error;
2168 }
2169
2170 update_known_hosts(pvar, ctx);
2171
2172 error:
2173 buffer_free(b);
2174 buffer_free(bsig);
2175 hostkeys_update_ctx_free(ctx);
2176 }
2177
2178 //
2179 // SSH�T�[�o�z�X�g��(known_hosts)�������X�V(OpenSSH 6.8 or later: host key rotation support)
2180 //
2181 // return 1: success
2182 // 0: fail
2183 //
2184 int update_client_input_hostkeys(PTInstVar pvar, char *dataptr, int datalen)
2185 {
2186 int success = 1; // OpenSSH 6.8�����������A�����������������������������������A
2187 // �������������� Tera Term �������������������������B
2188 int len;
2189 size_t i;
2190 char *cp, *fp;
2191 char msg[128];
2192 unsigned char *blob = NULL;
2193 buffer_t *b = NULL;
2194 struct hostkeys_update_ctx *ctx = NULL;
2195 Key *key = NULL, **tmp;
2196 unsigned char *outmsg;
2197
2198 // Tera Term���������A���Y�@�\���I���I�t�����������������������B
2199 if (pvar->settings.UpdateHostkeys == SSH_UPDATE_HOSTKEYS_NO) {
2200 _snprintf_s(msg, sizeof(msg), _TRUNCATE, "Hostkey was not updated because ts.UpdateHostkeys is disabled.");
2201 notify_verbose_message(pvar, msg, LOG_LEVEL_VERBOSE);
2202 return 1;
2203 }
2204
2205 ctx = calloc(1, sizeof(struct hostkeys_update_ctx));
2206 if (ctx == NULL)
2207 goto error;
2208
2209 b = buffer_init();
2210 if (b == NULL)
2211 goto error;
2212
2213 cp = buffer_append_space(b, datalen);
2214 memcpy(cp, dataptr, datalen);
2215
2216 while (buffer_remain_len(b) > 0) {
2217 key_free(key);
2218 key = NULL;
2219
2220 blob = buffer_get_string_msg(b, &len);
2221 key = key_from_blob(blob, len);
2222 if (key == NULL) {
2223 _snprintf_s(msg, sizeof(msg), _TRUNCATE, "Not found host key into blob %p (%d)", blob, len);
2224 notify_verbose_message(pvar, msg, LOG_LEVEL_ERROR);
2225 goto error;
2226 }
2227 free(blob);
2228 blob = NULL;
2229
2230 fp = key_fingerprint(key, SSH_FP_HEX);
2231 _snprintf_s(msg, sizeof(msg), _TRUNCATE, "Received %s host key %s",
2232 get_sshname_from_key(key), fp);
2233 notify_verbose_message(pvar, msg, LOG_LEVEL_VERBOSE);
2234 free(fp);
2235
2236 // �����������z�X�g�L�[�A���S���Y�������`�F�b�N�����B
2237 if (check_hostkey_algorithm(pvar, key) == 0) {
2238 _snprintf_s(msg, sizeof(msg), _TRUNCATE, "%s host key is not permitted by ts.HostKeyOrder",
2239 get_sshname_from_key(key));
2240 notify_verbose_message(pvar, msg, LOG_LEVEL_VERBOSE);
2241 continue;
2242 }
2243
2244 // Skip certs: Tera Term�����������F�������T�|�[�g�B
2245
2246 // �d�������L�[�����M�������G���[�������B
2247 for (i = 0; i < ctx->nkeys; i++) {
2248 if (HOSTS_compare_public_key(key, ctx->keys[i]) == 1) {
2249 _snprintf_s(msg, sizeof(msg), _TRUNCATE, "Received duplicated %s host key",
2250 get_sshname_from_key(key));
2251 notify_verbose_message(pvar, msg, LOG_LEVEL_ERROR);
2252 goto error;
2253 }
2254 }
2255
2256 // �L�[���o�^�����B
2257 tmp = realloc(ctx->keys, (ctx->nkeys + 1)*sizeof(*ctx->keys));
2258 if (tmp == NULL) {
2259 _snprintf_s(msg, sizeof(msg), _TRUNCATE, "Not memory: realloc ctx->keys %d",
2260 ctx->nkeys);
2261 notify_verbose_message(pvar, msg, LOG_LEVEL_FATAL);
2262 goto error;
2263 }
2264 ctx->keys = tmp;
2265 ctx->keys[ctx->nkeys++] = key;
2266 key = NULL;
2267 }
2268
2269 if (ctx->nkeys == 0) {
2270 _snprintf_s(msg, sizeof(msg), _TRUNCATE, "No host rotation key");
2271 notify_verbose_message(pvar, msg, LOG_LEVEL_VERBOSE);
2272 goto error;
2273 }
2274
2275 if ((ctx->keys_seen = calloc(ctx->nkeys, sizeof(*ctx->keys_seen))) == NULL) {
2276 _snprintf_s(msg, sizeof(msg), _TRUNCATE, "Not memory: calloc ctx->keys %d",
2277 ctx->nkeys);
2278 notify_verbose_message(pvar, msg, LOG_LEVEL_FATAL);
2279 goto error;
2280 }
2281
2282 HOSTS_hostkey_foreach(pvar, hostkeys_find, ctx);
2283
2284 // �T�[�o�������������������Q�����A�������������V�K���������������������B
2285 ctx->nnew = 0;
2286 for (i = 0; i < ctx->nkeys; i++) {
2287 if (!ctx->keys_seen[i])
2288 ctx->nnew++;
2289 }
2290 _snprintf_s(msg, sizeof(msg), _TRUNCATE, "%u keys from server: %u new, %u retained. %u to remove",
2291 ctx->nkeys, ctx->nnew, ctx->nkeys - ctx->nnew, ctx->nold);
2292 notify_verbose_message(pvar, msg, LOG_LEVEL_VERBOSE);
2293
2294 // �V�K�������������[�������Adeprecated���������������B
2295 if (ctx->nnew == 0 && ctx->nold != 0) {
2296 update_known_hosts(pvar, ctx);
2297
2298 }
2299 else if (ctx->nnew != 0) { // �V�K�������������������������B
2300 buffer_clear(b);
2301
2302 buffer_put_cstring(b, "hostkeys-prove-00@openssh.com");
2303 buffer_put_char(b, 1); /* bool: want reply */
2304
2305 for (i = 0; i < ctx->nkeys; i++) {
2306 if (ctx->keys_seen[i])
2307 continue;
2308 key_to_blob(ctx->keys[i], &blob, &len);
2309 buffer_put_string(b, blob, len);
2310 free(blob);
2311 blob = NULL;
2312 }
2313
2314 len = buffer_len(b);
2315 outmsg = begin_send_packet(pvar, SSH2_MSG_GLOBAL_REQUEST, len);
2316 memcpy(outmsg, buffer_ptr(b), len);
2317 finish_send_packet(pvar);
2318
2319 // SSH2_MSG_GLOBAL_REQUEST�����X�|���X�����������n���h�����o�^�����B
2320 client_register_global_confirm(client_global_hostkeys_private_confirm, ctx);
2321 ctx = NULL; // callback���������������A��������NULL���������������B
2322 }
2323
2324 success = 1;
2325
2326 error:
2327 buffer_free(b);
2328 hostkeys_update_ctx_free(ctx);
2329 free(blob);
2330
2331 return (success);
2332 }

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