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

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