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 6117 - (show annotations) (download) (as text)
Wed Nov 11 22:38:30 2015 UTC (8 years, 5 months ago) by maya
Original Path: trunk/ttssh2/ttxssh/key.c
File MIME type: text/x-csrc
File size: 55543 byte(s)
SSH key fingerprint の hex 形式の出力を関数に移動(OpenSSH と同じ)
ダイジェストの形式を引数に追加

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

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