Develop and Download Open Source Software

Browse Subversion Repository

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6132 - (hide annotations) (download) (as text)
Sun Nov 15 10:25:50 2015 UTC (8 years, 4 months ago) by maya
Original Path: trunk/ttssh2/ttxssh/key.c
File MIME type: text/x-csrc
File size: 59046 byte(s)
SSH ホスト鍵の fingerprint の表示を、MD5 形式か SHA256 形式か選択できるようにした
  https://osdn.jp/ticket/browse.php?group_id=1412&tid=35602
1 maya 4304 /*
2 maya 6064 (C) 2011 TeraTerm Project
3 maya 4304 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 maya 4321 #include "kex.h"
30 yutakapon 5931 #include "resource.h"
31 maya 4304
32     #include <openssl/rsa.h>
33     #include <openssl/dsa.h>
34 maya 4321 #include <openssl/ecdsa.h>
35 maya 6118 #include <openssl/buffer.h>
36 maya 4304
37     #define INTBLOB_LEN 20
38     #define SIGBLOB_LEN (2*INTBLOB_LEN)
39    
40 yutakapon 5838
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 maya 4304 //////////////////////////////////////////////////////////////////////////////
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 maya 4378 int ssh_ecdsa_verify(EC_KEY *key, ssh_keytype keytype,
320 maya 4321 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 maya 4378 if (strncmp(get_ssh_keytype_name(keytype), ptr, len) != 0) {
342 maya 4321 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 maya 4327 nid = keytype_to_hash_nid(keytype);
367 maya 4321 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 yutakapon 5545 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 maya 4307 int key_verify(Key *key,
454 maya 4304 unsigned char *signature, unsigned int signaturelen,
455     unsigned char *data, unsigned int datalen)
456     {
457     int ret = 0;
458    
459 maya 4321 switch (key->type) {
460     case KEY_RSA:
461 maya 4307 ret = ssh_rsa_verify(key->rsa, signature, signaturelen, data, datalen);
462 maya 4321 break;
463     case KEY_DSA:
464 maya 4307 ret = ssh_dss_verify(key->dsa, signature, signaturelen, data, datalen);
465 maya 4321 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 yutakapon 5545 case KEY_ED25519:
472     ret = ssh_ed25519_verify(key, signature, signaturelen, data, datalen);
473     break;
474 maya 4321 default:
475 maya 4304 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 yutakapon 5545 unsigned char *duplicate_ED25519_PK(unsigned char *src)
540     {
541     unsigned char *ptr = NULL;
542 maya 4304
543 yutakapon 5545 ptr = malloc(ED25519_PK_SZ);
544     if (ptr) {
545     memcpy(ptr, src, ED25519_PK_SZ);
546     }
547     return (ptr);
548     }
549    
550    
551 maya 6120 char* key_fingerprint_raw(Key *k, enum digest_algorithm dgst_alg, int *dgst_raw_length)
552 maya 4304 {
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 maya 6120 switch (dgst_alg) {
564     case SSH_DIGEST_MD5:
565 doda 4531 md = EVP_md5();
566     break;
567 maya 6120 case SSH_DIGEST_SHA1:
568 doda 4531 md = EVP_sha1();
569     break;
570 maya 6120 case SSH_DIGEST_SHA256:
571 doda 4539 md = EVP_sha256();
572     break;
573 doda 4531 default:
574     md = EVP_md5();
575     }
576 maya 4304
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 maya 4321 case KEY_ECDSA256:
595     case KEY_ECDSA384:
596     case KEY_ECDSA521:
597 yutakapon 5545 case KEY_ED25519:
598 maya 4304 key_to_blob(k, &blob, &len);
599     break;
600    
601     case KEY_UNSPEC:
602     return retval;
603     break;
604    
605     default:
606 maya 6120 //fatal("key_fingerprint_raw: bad key type %d", dgst_alg);
607 maya 4304 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 maya 5550 ssh_key_type(ssh_keytype type)
629 maya 4304 {
630 maya 5550 switch (type) {
631 maya 4304 case KEY_RSA1:
632     return "RSA1";
633     case KEY_RSA:
634     return "RSA";
635     case KEY_DSA:
636     return "DSA";
637 maya 4321 case KEY_ECDSA256:
638     case KEY_ECDSA384:
639     case KEY_ECDSA521:
640     return "ECDSA";
641 yutakapon 5545 case KEY_ED25519:
642     return "ED25519";
643 maya 4304 }
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 maya 4321 case KEY_ECDSA256:
659     return 256;
660     case KEY_ECDSA384:
661     return 384;
662     case KEY_ECDSA521:
663     return 521;
664 yutakapon 5545 case KEY_ED25519:
665     return 256; /* XXX */
666 maya 4304 }
667     return 0;
668     }
669    
670 maya 6120 // based on OpenSSH 7.1
671 maya 6117 static char *
672 maya 6120 key_fingerprint_b64(const char *alg, u_char *dgst_raw, u_int dgst_raw_len)
673 maya 6117 {
674     char *retval;
675     unsigned int i, retval_len;
676 maya 6118 BIO *bio, *b64;
677     BUF_MEM *bufferPtr;
678 maya 6117
679 maya 6120 retval_len = strlen(alg) + 1 + ((dgst_raw_len + 2) / 3) * 4 + 1;
680 maya 6118 retval = malloc(retval_len);
681     retval[0] = '\0';
682    
683 maya 6120 strncat_s(retval, retval_len, alg, _TRUNCATE);
684     strncat_s(retval, retval_len, ":", _TRUNCATE);
685    
686 maya 6118 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 maya 6120 key_fingerprint_hex(const char *alg, u_char *dgst_raw, u_int dgst_raw_len)
708 maya 6118 {
709     char *retval;
710     unsigned int i, retval_len;
711    
712 maya 6120 retval_len = strlen(alg) + 1 + dgst_raw_len * 3 + 1;
713 maya 6117 retval = malloc(retval_len);
714     retval[0] = '\0';
715 maya 6120
716     strncat_s(retval, retval_len, alg, _TRUNCATE);
717     strncat_s(retval, retval_len, ":", _TRUNCATE);
718    
719 maya 6117 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 maya 6129 retval[retval_len - 2] = '\0';
727 maya 6117
728     return (retval);
729     }
730    
731 maya 4304 #define FLDBASE 8
732     #define FLDSIZE_Y (FLDBASE + 1)
733     #define FLDSIZE_X (FLDBASE * 2 + 1)
734     static char *
735 maya 6120 key_fingerprint_randomart(const char *alg, u_char *dgst_raw, u_int dgst_raw_len, const Key *k)
736 maya 4304 {
737     /*
738 maya 6120 * Chars to be used after each other every time the worm
739     * intersects with itself. Matter of taste.
740     */
741 maya 4304 char *augmentation_string = " .o+=*BOX@%&#/^SE";
742 maya 6120 char *retval, *p, title[FLDSIZE_X], hash[FLDSIZE_X];
743 maya 4304 unsigned char field[FLDSIZE_X][FLDSIZE_Y];
744 maya 6120 size_t i, tlen, hlen;
745     unsigned int b;
746     int x, y, r;
747 maya 4304 size_t len = strlen(augmentation_string) - 1;
748    
749 maya 6120 retval = calloc((FLDSIZE_X + 3 + 1), (FLDSIZE_Y + 2));
750 maya 4304
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 maya 6120 if (field[x][y] < len - 2)
774     field[x][y]++;
775 maya 4304 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 maya 6120 /* 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 maya 4304
792 maya 6120 /* assemble hash ID. */
793     r = _snprintf_s(hash, sizeof(hash), _TRUNCATE, "[%s]", alg);
794     hlen = (r <= 0) ? 0 : strlen(hash);
795    
796 maya 4304 /* output upper border */
797 maya 6120 p = retval;
798     *p++ = '+';
799     for (i = 0; i < (FLDSIZE_X - tlen) / 2; i++)
800 maya 4304 *p++ = '-';
801 maya 6120 memcpy(p, title, tlen);
802     p += tlen;
803     for (i += tlen; i < FLDSIZE_X; i++)
804     *p++ = '-';
805 maya 4304 *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 maya 6120 for (i = 0; i < (FLDSIZE_X - hlen) / 2; i++)
822 maya 4304 *p++ = '-';
823 maya 6120 memcpy(p, hash, hlen);
824     p += hlen;
825     for (i += hlen; i < FLDSIZE_X; i++)
826     *p++ = '-';
827 maya 4304 *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 maya 6120 char *key_fingerprint(Key *key, enum fp_rep dgst_rep, enum digest_algorithm dgst_alg)
839 maya 4304 {
840 maya 6120 char *retval = NULL, *alg;
841 maya 4304 unsigned char *dgst_raw;
842     int dgst_raw_len;
843    
844     // fingerprint���n�b�V���l�i�o�C�i���j��������
845 maya 6120 dgst_raw = key_fingerprint_raw(key, dgst_alg, &dgst_raw_len);
846 yutakapon 5941 if (dgst_raw == NULL)
847     return NULL;
848 maya 4304
849 maya 6120 alg = get_digest_algorithm_name(dgst_alg);
850    
851 maya 6118 switch (dgst_rep) {
852     case SSH_FP_HEX:
853 maya 6120 retval = key_fingerprint_hex(alg, dgst_raw, dgst_raw_len);
854 maya 6118 break;
855     case SSH_FP_BASE64:
856 maya 6120 retval = key_fingerprint_b64(alg, dgst_raw, dgst_raw_len);
857 maya 6118 break;
858     case SSH_FP_RANDOMART:
859 maya 6120 retval = key_fingerprint_randomart(alg, dgst_raw, dgst_raw_len, key);
860 maya 6118 break;
861 maya 4304 }
862    
863     memset(dgst_raw, 0, dgst_raw_len);
864     free(dgst_raw);
865    
866     return (retval);
867     }
868    
869 yutakapon 5545 //
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 maya 4304
888 yutakapon 5545 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 maya 4304 //
1028     // �L�[����������������
1029     //
1030     void key_free(Key *key)
1031     {
1032 maya 4321 if (key == NULL) {
1033     return;
1034     }
1035    
1036 maya 4304 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 maya 4321
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 yutakapon 5545
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 maya 4304 }
1071     free(key);
1072     }
1073    
1074     //
1075     // �L�[���������������p����
1076     //
1077 maya 4321 char *get_sshname_from_key(Key *key)
1078     {
1079 maya 4378 return get_ssh_keytype_name(key->type);
1080 maya 4321 }
1081 maya 4304
1082     //
1083     // �L�[������������������������
1084     //
1085 maya 4378 ssh_keytype get_keytype_from_name(char *name)
1086 maya 4304 {
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 maya 4321 } 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 yutakapon 5545 } else if (strcmp(name, "ssh-ed25519") == 0) {
1104     return KEY_ED25519;
1105 maya 4304 }
1106     return KEY_UNSPEC;
1107     }
1108    
1109    
1110 maya 4378 ssh_keytype key_curve_name_to_keytype(char *name)
1111 maya 4321 {
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 maya 4378 char *curve_keytype_to_name(ssh_keytype type)
1123 maya 4321 {
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 maya 4304 //
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 maya 4321 char *sshname, *tmp;
1146 maya 4304 int len;
1147     int ret = 1; // success
1148    
1149     b = buffer_init();
1150     sshname = get_sshname_from_key(key);
1151    
1152 maya 4321 switch (key->type) {
1153     case KEY_RSA:
1154 maya 4304 buffer_put_string(b, sshname, strlen(sshname));
1155     buffer_put_bignum2(b, key->rsa->e);
1156     buffer_put_bignum2(b, key->rsa->n);
1157 maya 4321 break;
1158     case KEY_DSA:
1159 maya 4304 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 maya 4321 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 yutakapon 5545 case KEY_ED25519:
1175     buffer_put_cstring(b, sshname);
1176     buffer_put_string(b, key->ed25519_pk, ED25519_PK_SZ);
1177     break;
1178 maya 4304
1179 maya 4321 default:
1180 maya 4304 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 yutakapon 5545 int keynamelen, len;
1210 maya 4304 char key[128];
1211     RSA *rsa = NULL;
1212     DSA *dsa = NULL;
1213 maya 4321 EC_KEY *ecdsa = NULL;
1214     EC_POINT *q = NULL;
1215     char *curve = NULL;
1216 yutakapon 5838 Key *hostkey = NULL; // hostkey
1217 maya 4378 ssh_keytype type;
1218 yutakapon 5545 unsigned char *pk = NULL;
1219 maya 4304
1220 yutakapon 5838 if (data == NULL)
1221     goto error;
1222    
1223 maya 4304 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 maya 4321 switch (type) {
1241     case KEY_RSA: // RSA key
1242 maya 4304 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 maya 4321 break;
1258 maya 4304
1259 maya 4321 case KEY_DSA: // DSA key
1260 maya 4304 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 maya 4321 break;
1283 maya 4304
1284 maya 4321 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 maya 4327 ecdsa = EC_KEY_new_by_curve_name(keytype_to_cipher_nid(type));
1293 maya 4321 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 yutakapon 5545 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 maya 4321 default: // unknown key
1328 maya 4304 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 maya 4321 if (ecdsa != NULL)
1339     EC_KEY_free(ecdsa);
1340 maya 4304
1341 yutakapon 5545 free(hostkey);
1342    
1343 maya 4304 return NULL;
1344     }
1345    
1346    
1347 yutakapon 5545 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 maya 4307 BOOL generate_SSH2_keysign(Key *keypair, char **sigptr, int *siglen, char *data, int datalen)
1384 maya 4304 {
1385     buffer_t *msg = NULL;
1386     char *s;
1387 yutakapon 5545 int ret;
1388 maya 4304
1389     msg = buffer_init();
1390     if (msg == NULL) {
1391     // TODO: error check
1392     return FALSE;
1393     }
1394    
1395 maya 4324 switch (keypair->type) {
1396     case KEY_RSA: // RSA
1397     {
1398 maya 4307 const EVP_MD *evp_md = EVP_sha1();
1399 maya 4304 EVP_MD_CTX md;
1400     u_char digest[EVP_MAX_MD_SIZE], *sig;
1401     u_int slen, dlen, len;
1402 maya 4307 int ok, nid = NID_sha1;
1403 maya 4304
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 maya 4307 slen = RSA_size(keypair->rsa);
1410 maya 4304 sig = malloc(slen);
1411     if (sig == NULL)
1412     goto error;
1413    
1414     // �d�q�������v�Z
1415 maya 4307 ok = RSA_sign(nid, digest, dlen, sig, &len, keypair->rsa);
1416 maya 4304 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 maya 4307 s = get_sshname_from_key(keypair);
1437 maya 4304 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 maya 4324
1451     break;
1452 maya 4307 }
1453 maya 4324 case KEY_DSA: // DSA
1454     {
1455 maya 4304 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 maya 4307 sig = DSA_do_sign(digest, dlen, keypair->dsa);
1468 maya 4304 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 maya 4307 s = get_sshname_from_key(keypair);
1487 maya 4304 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 maya 4324 break;
1500 maya 4304 }
1501 maya 4324 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 maya 4327 nid = keytype_to_hash_nid(keypair->type);
1513 maya 4324 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 yutakapon 5545
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 maya 4324 default:
1559 maya 4307 buffer_free(msg);
1560     return FALSE;
1561 maya 4324 break;
1562 maya 4307 }
1563 maya 4304
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 maya 4307 Key *keypair;
1578 maya 4324 char *s, *tmp;
1579 maya 4304
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 maya 4324 switch (keypair->type) {
1589     case KEY_RSA: // RSA
1590 maya 4307 s = get_sshname_from_key(keypair);
1591 maya 4304 buffer_put_string(msg, s, strlen(s));
1592 maya 4307 buffer_put_bignum2(msg, keypair->rsa->e); // ���J�w��
1593     buffer_put_bignum2(msg, keypair->rsa->n); // p�~q
1594 maya 4324 break;
1595     case KEY_DSA: // DSA
1596 maya 4307 s = get_sshname_from_key(keypair);
1597 maya 4304 buffer_put_string(msg, s, strlen(s));
1598 maya 4307 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 maya 4324 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 yutakapon 5545 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 maya 4324 default:
1619 maya 4307 return FALSE;
1620     }
1621    
1622 maya 4304 *blobptr = msg;
1623     *bloblen = buffer_len(msg);
1624    
1625     return TRUE;
1626     }
1627 maya 4327
1628 maya 4378 int kextype_to_cipher_nid(kex_algorithm type)
1629 maya 4327 {
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 maya 4378 int keytype_to_hash_nid(ssh_keytype type)
1642 maya 4327 {
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 maya 4378 int keytype_to_cipher_nid(ssh_keytype type)
1655 maya 4327 {
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 maya 4378 ssh_keytype nid_to_keytype(int nid)
1668 maya 4327 {
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 yutakapon 5545
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 yutakapon 5838
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 yutakapon 5841
1929     // �����������z�X�g���A���S���Y�������`�F�b�N�����B
1930 yutakapon 5838 //
1931 yutakapon 5841 // 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 yutakapon 5847 // Callback function
1952 yutakapon 5841 //
1953 yutakapon 5847 // 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 maya 6132 static void hosts_updatekey_dlg_set_fingerprint(PTInstVar pvar, HWND dlg, digest_algorithm dgst_alg)
1993     {
1994     char buf[1024];
1995     char *fp;
1996     size_t i;
1997     struct hostkeys_update_ctx *ctx;
1998    
1999     ctx = pvar->hostkey_ctx;
2000    
2001     SendDlgItemMessage(dlg, IDC_ADDKEY_EDIT, WM_SETTEXT, 0, (LPARAM)(char FAR *)"");
2002     for (i = 0; i < ctx->nkeys; i++) {
2003     if (ctx->keys_seen[i])
2004     continue;
2005     switch (dgst_alg) {
2006     case SSH_DIGEST_MD5:
2007     fp = key_fingerprint(ctx->keys[i], SSH_FP_HEX, dgst_alg);
2008     break;
2009     case SSH_DIGEST_SHA256:
2010     fp = key_fingerprint(ctx->keys[i], SSH_FP_BASE64, dgst_alg);
2011     break;
2012     }
2013     buf[0] = 0;
2014     strcat_s(buf, sizeof(buf), get_sshname_from_key(ctx->keys[i]));
2015     strcat_s(buf, sizeof(buf), " ");
2016     strcat_s(buf, sizeof(buf), fp);
2017     SendDlgItemMessage(dlg, IDC_ADDKEY_EDIT, EM_REPLACESEL, 0, (LPARAM)buf);
2018     SendDlgItemMessage(dlg, IDC_ADDKEY_EDIT, EM_REPLACESEL, 0, (LPARAM)"\r\n");
2019     free(fp);
2020     }
2021    
2022     SendDlgItemMessage(dlg, IDC_REMOVEKEY_EDIT, WM_SETTEXT, 0, (LPARAM)(char FAR *)"");
2023     for (i = 0; i < ctx->nold; i++) {
2024     switch (dgst_alg) {
2025     case SSH_DIGEST_MD5:
2026     fp = key_fingerprint(ctx->old_keys[i], SSH_FP_HEX, dgst_alg);
2027     break;
2028     case SSH_DIGEST_SHA256:
2029     fp = key_fingerprint(ctx->old_keys[i], SSH_FP_BASE64, dgst_alg);
2030     break;
2031     }
2032     buf[0] = 0;
2033     strcat_s(buf, sizeof(buf), get_sshname_from_key(ctx->old_keys[i]));
2034     strcat_s(buf, sizeof(buf), " ");
2035     strcat_s(buf, sizeof(buf), fp);
2036     SendDlgItemMessage(dlg, IDC_REMOVEKEY_EDIT, EM_REPLACESEL, 0, (LPARAM)buf);
2037     SendDlgItemMessage(dlg, IDC_REMOVEKEY_EDIT, EM_REPLACESEL, 0, (LPARAM)"\r\n");
2038     free(fp);
2039     }
2040     }
2041    
2042 yutakapon 5931 static BOOL CALLBACK hosts_updatekey_dlg_proc(HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam)
2043 yutakapon 5849 {
2044 yutakapon 5931 static HFONT DlgHostsAddFont;
2045     PTInstVar pvar;
2046     LOGFONT logfont;
2047     HFONT font;
2048     char buf[1024];
2049     char *host;
2050     struct hostkeys_update_ctx *ctx;
2051 maya 5964 char uimsg[MAX_UIMSG];
2052 yutakapon 5849
2053 yutakapon 5931 switch (msg) {
2054     case WM_INITDIALOG:
2055     pvar = (PTInstVar)lParam;
2056     SetWindowLong(dlg, DWL_USER, lParam);
2057 yutakapon 5854
2058 maya 5964 GetWindowText(dlg, uimsg, sizeof(uimsg));
2059     UTIL_get_lang_msg("DLG_HOSTKEY_ROTATION_TITLE", pvar, uimsg);
2060     SetWindowText(dlg, pvar->ts->UIMsg);
2061    
2062 yutakapon 5931 host = pvar->ssh_state.hostname;
2063     ctx = pvar->hostkey_ctx;
2064 maya 5964
2065     GetDlgItemText(dlg, IDC_HOSTKEY_MESSAGE, uimsg, sizeof(uimsg));
2066     UTIL_get_lang_msg("DLG_HOSTKEY_ROTATION_WARNING", pvar, uimsg);
2067 yutakapon 5931 _snprintf_s(buf, sizeof(buf), _TRUNCATE,
2068 yutakapon 5855 pvar->ts->UIMsg, host, ctx->nnew, ctx->nold
2069     );
2070 yutakapon 5931 SetDlgItemText(dlg, IDC_HOSTKEY_MESSAGE, buf);
2071 yutakapon 5853
2072 maya 6132 GetDlgItemText(dlg, IDC_FP_HASH_ALG, uimsg, sizeof(uimsg));
2073     UTIL_get_lang_msg("DLG_HOSTKEY_ROTATION_FP_HASH_ALGORITHM", pvar, uimsg);
2074     SetDlgItemText(dlg, IDC_FP_HASH_ALG, pvar->ts->UIMsg);
2075    
2076 maya 5964 GetDlgItemText(dlg, IDC_ADDKEY_TEXT, uimsg, sizeof(uimsg));
2077     UTIL_get_lang_msg("DLG_HOSTKEY_ROTATION_ADD", pvar, uimsg);
2078     _snprintf_s(buf, sizeof(buf), _TRUNCATE, pvar->ts->UIMsg, ctx->nnew);
2079 yutakapon 5931 SetDlgItemText(dlg, IDC_ADDKEY_TEXT, buf);
2080 yutakapon 5853
2081 maya 5964 GetDlgItemText(dlg, IDC_REMOVEKEY_TEXT, uimsg, sizeof(uimsg));
2082     UTIL_get_lang_msg("DLG_HOSTKEY_ROTATION_REMOVE", pvar, uimsg);
2083     _snprintf_s(buf, sizeof(buf), _TRUNCATE, pvar->ts->UIMsg, ctx->nold);
2084 yutakapon 5931 SetDlgItemText(dlg, IDC_REMOVEKEY_TEXT, buf);
2085 yutakapon 5857
2086 maya 6132 CheckDlgButton(dlg, IDC_FP_HASH_ALG_MD5, TRUE);
2087     hosts_updatekey_dlg_set_fingerprint(pvar, dlg, SSH_DIGEST_MD5);
2088    
2089 maya 5969 GetDlgItemText(dlg, IDOK, uimsg, sizeof(uimsg));
2090     UTIL_get_lang_msg("BTN_YES", pvar, uimsg);
2091     SetDlgItemText(dlg, IDOK, pvar->ts->UIMsg);
2092     GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
2093     UTIL_get_lang_msg("BTN_NO", pvar, uimsg);
2094     SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
2095    
2096 yutakapon 5931 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
2097     GetObject(font, sizeof(LOGFONT), &logfont);
2098     if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsAddFont, pvar)) {
2099     SendDlgItemMessage(dlg, IDC_HOSTKEY_MESSAGE, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
2100     SendDlgItemMessage(dlg, IDC_ADDKEY_TEXT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
2101 maya 6132 SendDlgItemMessage(dlg, IDC_FP_HASH_ALG, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
2102     SendDlgItemMessage(dlg, IDC_FP_HASH_ALG_MD5, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
2103     SendDlgItemMessage(dlg, IDC_FP_HASH_ALG_SHA256, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
2104 yutakapon 5931 SendDlgItemMessage(dlg, IDC_ADDKEY_EDIT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
2105     SendDlgItemMessage(dlg, IDC_REMOVEKEY_TEXT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
2106     SendDlgItemMessage(dlg, IDC_REMOVEKEY_EDIT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
2107 maya 5969 SendDlgItemMessage(dlg, IDOK, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
2108     SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
2109 yutakapon 5931 }
2110     else {
2111     DlgHostsAddFont = NULL;
2112     }
2113    
2114     return TRUE; /* because we do not set the focus */
2115    
2116     case WM_COMMAND:
2117     pvar = (PTInstVar)GetWindowLong(dlg, DWL_USER);
2118    
2119     switch (LOWORD(wParam)) {
2120     case IDOK:
2121    
2122     EndDialog(dlg, 1);
2123    
2124     if (DlgHostsAddFont != NULL) {
2125     DeleteObject(DlgHostsAddFont);
2126 yutakapon 5857 }
2127 yutakapon 5931
2128     return TRUE;
2129    
2130     case IDCANCEL: /* kill the connection */
2131     EndDialog(dlg, 0);
2132    
2133     if (DlgHostsAddFont != NULL) {
2134     DeleteObject(DlgHostsAddFont);
2135     }
2136    
2137     return TRUE;
2138    
2139 maya 6132 case IDC_FP_HASH_ALG_MD5:
2140     hosts_updatekey_dlg_set_fingerprint(pvar, dlg, SSH_DIGEST_MD5);
2141     return TRUE;
2142    
2143     case IDC_FP_HASH_ALG_SHA256:
2144     hosts_updatekey_dlg_set_fingerprint(pvar, dlg, SSH_DIGEST_SHA256);
2145     return TRUE;
2146    
2147 yutakapon 5931 default:
2148     return FALSE;
2149 yutakapon 5857 }
2150    
2151 yutakapon 5931 default:
2152     return FALSE;
2153     }
2154     }
2155    
2156     static void update_known_hosts(PTInstVar pvar, struct hostkeys_update_ctx *ctx)
2157     {
2158     size_t i;
2159     int dlgresult;
2160     char msg[1024];
2161     char *host;
2162    
2163     host = pvar->ssh_state.hostname;
2164    
2165     // "/nosecuritywarning"���w�����������������A�X�V�������s�������B
2166     if (pvar->nocheck_known_hosts) {
2167     _snprintf_s(msg, sizeof(msg), _TRUNCATE, "Hostkey was not updated because `/nosecuritywarning' option was specified.");
2168     notify_verbose_message(pvar, msg, LOG_LEVEL_VERBOSE);
2169     goto error;
2170     }
2171    
2172     // known_hosts�t�@�C�����X�V���s�������A���[�U���������������s���B
2173     if (pvar->settings.UpdateHostkeys == SSH_UPDATE_HOSTKEYS_ASK) {
2174     HWND cur_active = GetActiveWindow();
2175    
2176     pvar->hostkey_ctx = ctx;
2177     dlgresult = DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHUPDATE_HOSTKEY),
2178     cur_active != NULL ? cur_active : pvar->NotificationWindow,
2179     hosts_updatekey_dlg_proc, (LPARAM)pvar);
2180     if (dlgresult != 1) {
2181 yutakapon 5849 _snprintf_s(msg, sizeof(msg), _TRUNCATE, "Hostkey was not updated because a user cancelled.");
2182     notify_verbose_message(pvar, msg, LOG_LEVEL_VERBOSE);
2183     goto error;
2184     }
2185     }
2186    
2187     // �����L�[�����������������B
2188     HOSTS_delete_all_hostkeys(pvar);
2189    
2190     // �V�����L�[���������o�^�����B
2191     for (i = 0; i < ctx->nkeys; i++) {
2192     HOSTS_add_host_key(pvar, ctx->keys[i]);
2193     }
2194     _snprintf_s(msg, sizeof(msg), _TRUNCATE, "Hostkey was successfully updated to known_hosts file.");
2195     notify_verbose_message(pvar, msg, LOG_LEVEL_VERBOSE);
2196    
2197     error:
2198     return;
2199     }
2200    
2201 yutakapon 5853 static void client_global_hostkeys_private_confirm(PTInstVar pvar, int type, u_int32_t seq, void *_ctx)
2202 yutakapon 5850 {
2203 yutakapon 5853 struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx;
2204 yutakapon 5851 char msg[128];
2205     char *data;
2206     int len;
2207     unsigned char *blob = NULL;
2208     int bloblen;
2209     buffer_t *b = NULL;
2210     buffer_t *bsig = NULL;
2211     char *cp, *sig;
2212 yutakapon 5853 size_t i, ndone, siglen;
2213     int ret;
2214 yutakapon 5850
2215 yutakapon 5851 // SSH2 packet format:
2216     // [size(4) + padding size(1) + type(1)] + [payload(N) + padding(X)]
2217     // header body
2218     // ^data
2219     // <-----------------size------------------------------->
2220     // <---------len-------->
2221     //
2222     // data = payload(N) + padding(X): �p�f�B���O���������{�f�B���������w���B
2223     data = pvar->ssh_state.payload;
2224     // len = size - (padding size + 1): �p�f�B���O�������{�f�B�Btype�����������������B
2225     len = pvar->ssh_state.payloadlen;
2226 yutakapon 5853 len--; // type ��������
2227    
2228 yutakapon 5851 bsig = buffer_init();
2229     if (bsig == NULL)
2230     goto error;
2231     cp = buffer_append_space(bsig, len);
2232     memcpy(cp, data, len);
2233 yutakapon 5853
2234     if (ctx->nnew == 0) {
2235 yutakapon 5851 _snprintf_s(msg, sizeof(msg), _TRUNCATE, "Hostkey can not be updated because ctx->nnew %d(program bug).", ctx->nnew);
2236     notify_verbose_message(pvar, msg, LOG_LEVEL_FATAL);
2237 yutakapon 5853 goto error;
2238     }
2239     if (type != SSH2_MSG_REQUEST_SUCCESS) {
2240 yutakapon 5851 _snprintf_s(msg, sizeof(msg), _TRUNCATE, "Server failed to confirm ownership of private host keys(type %d)", type);
2241     notify_verbose_message(pvar, msg, LOG_LEVEL_ERROR);
2242 yutakapon 5853 goto error;
2243     }
2244     if (pvar->session_id_len == 0) {
2245 yutakapon 5851 _snprintf_s(msg, sizeof(msg), _TRUNCATE, "Hostkey can not be updated because pvar->session_id_len %d(program bug).", pvar->session_id_len);
2246     notify_verbose_message(pvar, msg, LOG_LEVEL_FATAL);
2247 yutakapon 5853 goto error;
2248     }
2249    
2250 yutakapon 5851 b = buffer_init();
2251     if (b == NULL)
2252     goto error;
2253    
2254     ndone = 0;
2255 yutakapon 5853 for (i = 0; i < ctx->nkeys; i++) {
2256     if (ctx->keys_seen[i])
2257     continue;
2258    
2259     buffer_clear(b);
2260 yutakapon 5851 buffer_put_cstring(b, "hostkeys-prove-00@openssh.com");
2261     buffer_put_string(b, pvar->session_id, pvar->session_id_len);
2262 yutakapon 5853 key_to_blob(ctx->keys[i], &blob, &bloblen);
2263     buffer_put_string(b, blob, bloblen);
2264     free(blob);
2265     blob = NULL;
2266    
2267 yutakapon 5851 sig = buffer_get_string_msg(bsig, &siglen);
2268     // Verify signature
2269     ret = key_verify(ctx->keys[i], sig, siglen, buffer_ptr(b), buffer_len(b));
2270 yutakapon 5853 free(sig);
2271     sig = NULL;
2272 yutakapon 5851 if (ret != 1) {
2273     _snprintf_s(msg, sizeof(msg), _TRUNCATE, "server gave bad signature for %s key %u",
2274     get_sshname_from_key(ctx->keys[i]), i);
2275     notify_verbose_message(pvar, msg, LOG_LEVEL_ERROR);
2276 yutakapon 5853 goto error;
2277 yutakapon 5851 }
2278     ndone++;
2279     }
2280    
2281 yutakapon 5853 if (ndone != ctx->nnew) {
2282 yutakapon 5851 _snprintf_s(msg, sizeof(msg), _TRUNCATE, "Hostkey can not be updated because ndone != ctx->nnew (%u / %u)(program bug).",
2283     ndone, ctx->nnew);
2284     notify_verbose_message(pvar, msg, LOG_LEVEL_FATAL);
2285 yutakapon 5853 goto error;
2286     }
2287 yutakapon 5851
2288 yutakapon 5850 update_known_hosts(pvar, ctx);
2289    
2290 yutakapon 5851 error:
2291     buffer_free(b);
2292     buffer_free(bsig);
2293 yutakapon 5853 hostkeys_update_ctx_free(ctx);
2294 yutakapon 5850 }
2295    
2296 yutakapon 5847 //
2297 yutakapon 5838 // SSH�T�[�o�z�X�g��(known_hosts)�������X�V(OpenSSH 6.8 or later: host key rotation support)
2298     //
2299     // return 1: success
2300     // 0: fail
2301     //
2302     int update_client_input_hostkeys(PTInstVar pvar, char *dataptr, int datalen)
2303     {
2304     int success = 1; // OpenSSH 6.8�����������A�����������������������������������A
2305     // �������������� Tera Term �������������������������B
2306     int len;
2307 yutakapon 5843 size_t i;
2308 yutakapon 5838 char *cp, *fp;
2309     char msg[128];
2310     unsigned char *blob = NULL;
2311     buffer_t *b = NULL;
2312     struct hostkeys_update_ctx *ctx = NULL;
2313 yutakapon 5843 Key *key = NULL, **tmp;
2314 yutakapon 5850 unsigned char *outmsg;
2315 yutakapon 5838
2316 yutakapon 5839 // Tera Term���������A���Y�@�\���I���I�t�����������������������B
2317 yutakapon 5849 if (pvar->settings.UpdateHostkeys == SSH_UPDATE_HOSTKEYS_NO) {
2318 yutakapon 5839 _snprintf_s(msg, sizeof(msg), _TRUNCATE, "Hostkey was not updated because ts.UpdateHostkeys is disabled.");
2319     notify_verbose_message(pvar, msg, LOG_LEVEL_VERBOSE);
2320 yutakapon 5843 return 1;
2321 yutakapon 5839 }
2322 yutakapon 5838
2323     ctx = calloc(1, sizeof(struct hostkeys_update_ctx));
2324     if (ctx == NULL)
2325     goto error;
2326    
2327     b = buffer_init();
2328     if (b == NULL)
2329     goto error;
2330    
2331     cp = buffer_append_space(b, datalen);
2332     memcpy(cp, dataptr, datalen);
2333    
2334     while (buffer_remain_len(b) > 0) {
2335     key_free(key);
2336     key = NULL;
2337    
2338     blob = buffer_get_string_msg(b, &len);
2339     key = key_from_blob(blob, len);
2340     if (key == NULL) {
2341 yutakapon 5841 _snprintf_s(msg, sizeof(msg), _TRUNCATE, "Not found host key into blob %p (%d)", blob, len);
2342 yutakapon 5843 notify_verbose_message(pvar, msg, LOG_LEVEL_ERROR);
2343 yutakapon 5838 goto error;
2344     }
2345     free(blob);
2346     blob = NULL;
2347    
2348 maya 6120 fp = key_fingerprint(key, SSH_FP_HEX, SSH_DIGEST_MD5);
2349 yutakapon 5841 _snprintf_s(msg, sizeof(msg), _TRUNCATE, "Received %s host key %s",
2350 yutakapon 5838 get_sshname_from_key(key), fp);
2351     notify_verbose_message(pvar, msg, LOG_LEVEL_VERBOSE);
2352     free(fp);
2353 yutakapon 5841
2354     // �����������z�X�g�L�[�A���S���Y�������`�F�b�N�����B
2355     if (check_hostkey_algorithm(pvar, key) == 0) {
2356     _snprintf_s(msg, sizeof(msg), _TRUNCATE, "%s host key is not permitted by ts.HostKeyOrder",
2357     get_sshname_from_key(key));
2358     notify_verbose_message(pvar, msg, LOG_LEVEL_VERBOSE);
2359     continue;
2360     }
2361    
2362 yutakapon 5843 // Skip certs: Tera Term�����������F�������T�|�[�g�B
2363 yutakapon 5841
2364 yutakapon 5843 // �d�������L�[�����M�������G���[�������B
2365     for (i = 0; i < ctx->nkeys; i++) {
2366     if (HOSTS_compare_public_key(key, ctx->keys[i]) == 1) {
2367     _snprintf_s(msg, sizeof(msg), _TRUNCATE, "Received duplicated %s host key",
2368     get_sshname_from_key(key));
2369     notify_verbose_message(pvar, msg, LOG_LEVEL_ERROR);
2370     goto error;
2371     }
2372     }
2373    
2374     // �L�[���o�^�����B
2375     tmp = realloc(ctx->keys, (ctx->nkeys + 1)*sizeof(*ctx->keys));
2376     if (tmp == NULL) {
2377     _snprintf_s(msg, sizeof(msg), _TRUNCATE, "Not memory: realloc ctx->keys %d",
2378     ctx->nkeys);
2379     notify_verbose_message(pvar, msg, LOG_LEVEL_FATAL);
2380     goto error;
2381     }
2382     ctx->keys = tmp;
2383     ctx->keys[ctx->nkeys++] = key;
2384     key = NULL;
2385 yutakapon 5838 }
2386    
2387 yutakapon 5843 if (ctx->nkeys == 0) {
2388     _snprintf_s(msg, sizeof(msg), _TRUNCATE, "No host rotation key");
2389     notify_verbose_message(pvar, msg, LOG_LEVEL_VERBOSE);
2390     goto error;
2391     }
2392    
2393 yutakapon 5849 if ((ctx->keys_seen = calloc(ctx->nkeys, sizeof(*ctx->keys_seen))) == NULL) {
2394 yutakapon 5847 _snprintf_s(msg, sizeof(msg), _TRUNCATE, "Not memory: calloc ctx->keys %d",
2395     ctx->nkeys);
2396     notify_verbose_message(pvar, msg, LOG_LEVEL_FATAL);
2397     goto error;
2398 yutakapon 5849 }
2399 yutakapon 5846
2400 yutakapon 5847 HOSTS_hostkey_foreach(pvar, hostkeys_find, ctx);
2401    
2402 yutakapon 5848 // �T�[�o�������������������Q�����A�������������V�K���������������������B
2403 yutakapon 5849 ctx->nnew = 0;
2404     for (i = 0; i < ctx->nkeys; i++) {
2405     if (!ctx->keys_seen[i])
2406     ctx->nnew++;
2407 yutakapon 5848 }
2408 yutakapon 5849 _snprintf_s(msg, sizeof(msg), _TRUNCATE, "%u keys from server: %u new, %u retained. %u to remove",
2409     ctx->nkeys, ctx->nnew, ctx->nkeys - ctx->nnew, ctx->nold);
2410 yutakapon 5848 notify_verbose_message(pvar, msg, LOG_LEVEL_VERBOSE);
2411    
2412     // �V�K�������������[�������Adeprecated���������������B
2413     if (ctx->nnew == 0 && ctx->nold != 0) {
2414 yutakapon 5849 update_known_hosts(pvar, ctx);
2415 yutakapon 5848
2416     }
2417     else if (ctx->nnew != 0) { // �V�K�������������������������B
2418 yutakapon 5850 buffer_clear(b);
2419 yutakapon 5848
2420 yutakapon 5850 buffer_put_cstring(b, "hostkeys-prove-00@openssh.com");
2421     buffer_put_char(b, 1); /* bool: want reply */
2422    
2423 yutakapon 5853 for (i = 0; i < ctx->nkeys; i++) {
2424     if (ctx->keys_seen[i])
2425     continue;
2426     key_to_blob(ctx->keys[i], &blob, &len);
2427     buffer_put_string(b, blob, len);
2428     free(blob);
2429     blob = NULL;
2430     }
2431    
2432 yutakapon 5850 len = buffer_len(b);
2433     outmsg = begin_send_packet(pvar, SSH2_MSG_GLOBAL_REQUEST, len);
2434     memcpy(outmsg, buffer_ptr(b), len);
2435     finish_send_packet(pvar);
2436    
2437     // SSH2_MSG_GLOBAL_REQUEST�����X�|���X�����������n���h�����o�^�����B
2438     client_register_global_confirm(client_global_hostkeys_private_confirm, ctx);
2439     ctx = NULL; // callback���������������A��������NULL���������������B
2440 yutakapon 5848 }
2441    
2442 yutakapon