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

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