[Ttssh2-commit] [9254] SSH2 暗号化方式 chach****@opens***** をサポート

Back to archive index
scmno****@osdn***** scmno****@osdn*****
2021年 5月 19日 (水) 23:11:13 JST


Revision: 9254
          https://osdn.net/projects/ttssh2/scm/svn/commits/9254
Author:   nmaya
Date:     2021-05-19 23:11:12 +0900 (Wed, 19 May 2021)
Log Message:
-----------
SSH2 暗号化方式 chach****@opens***** をサポート

merge from branches/ssh_chacha20poly1305
r9209, r9210, r9211, r9212, r9217, r9229, r9248, r9249, r9250, r9251, r9252, r9253

Revision Links:
--------------
    https://osdn.net/projects/ttssh2/scm/svn/commits/9209
    https://osdn.net/projects/ttssh2/scm/svn/commits/9210
    https://osdn.net/projects/ttssh2/scm/svn/commits/9211
    https://osdn.net/projects/ttssh2/scm/svn/commits/9212
    https://osdn.net/projects/ttssh2/scm/svn/commits/9217
    https://osdn.net/projects/ttssh2/scm/svn/commits/9229
    https://osdn.net/projects/ttssh2/scm/svn/commits/9248
    https://osdn.net/projects/ttssh2/scm/svn/commits/9249
    https://osdn.net/projects/ttssh2/scm/svn/commits/9250
    https://osdn.net/projects/ttssh2/scm/svn/commits/9251
    https://osdn.net/projects/ttssh2/scm/svn/commits/9252
    https://osdn.net/projects/ttssh2/scm/svn/commits/9253

Modified Paths:
--------------
    branches/4-stable/doc/en/html/about/history.html
    branches/4-stable/doc/en/html/menu/setup-ssh.html
    branches/4-stable/doc/ja/html/about/history.html
    branches/4-stable/doc/ja/html/menu/setup-ssh.html
    branches/4-stable/installer/release/TERATERM.INI
    branches/4-stable/ttssh2/ttxssh/CMakeLists.txt
    branches/4-stable/ttssh2/ttxssh/auth.c
    branches/4-stable/ttssh2/ttxssh/auth.h
    branches/4-stable/ttssh2/ttxssh/cipher.h
    branches/4-stable/ttssh2/ttxssh/crypt.c
    branches/4-stable/ttssh2/ttxssh/hosts.c
    branches/4-stable/ttssh2/ttxssh/kex.c
    branches/4-stable/ttssh2/ttxssh/kex.h
    branches/4-stable/ttssh2/ttxssh/key.c
    branches/4-stable/ttssh2/ttxssh/key.h
    branches/4-stable/ttssh2/ttxssh/keyfiles.c
    branches/4-stable/ttssh2/ttxssh/pkt.c
    branches/4-stable/ttssh2/ttxssh/ssh.c
    branches/4-stable/ttssh2/ttxssh/ssh.h
    branches/4-stable/ttssh2/ttxssh/ttxssh.c
    branches/4-stable/ttssh2/ttxssh/ttxssh.h
    branches/4-stable/ttssh2/ttxssh/ttxssh.v16.vcxproj
    branches/4-stable/ttssh2/ttxssh/ttxssh.v16.vcxproj.filters
    branches/4-stable/ttssh2/ttxssh/ttxssh.v8.vcproj

Added Paths:
-----------
    branches/4-stable/ttssh2/ttxssh/cipher-3des1.c
    branches/4-stable/ttssh2/ttxssh/cipher-chachapoly-libcrypto.c
    branches/4-stable/ttssh2/ttxssh/cipher-chachapoly.h
    branches/4-stable/ttssh2/ttxssh/cipher.c
    branches/4-stable/ttssh2/ttxssh/comp.c
    branches/4-stable/ttssh2/ttxssh/comp.h
    branches/4-stable/ttssh2/ttxssh/hostkey.c
    branches/4-stable/ttssh2/ttxssh/hostkey.h
    branches/4-stable/ttssh2/ttxssh/mac.c
    branches/4-stable/ttssh2/ttxssh/mac.h
    branches/4-stable/ttssh2/ttxssh/poly1305.c
    branches/4-stable/ttssh2/ttxssh/poly1305.h
    branches/4-stable/ttssh2/ttxssh/ssherr.c
    branches/4-stable/ttssh2/ttxssh/ssherr.h

Property Changed:
----------------
    branches/4-stable/
    branches/4-stable/TTProxy/
    branches/4-stable/TTXKanjiMenu/
    branches/4-stable/TTXSamples/
    branches/4-stable/cygterm/
    branches/4-stable/teraterm/
    branches/4-stable/ttpmenu/

-------------- next part --------------
Index: branches/4-stable
===================================================================
--- branches/4-stable	2021-05-19 14:05:07 UTC (rev 9253)
+++ branches/4-stable	2021-05-19 14:11:12 UTC (rev 9254)

Property changes on: branches/4-stable
___________________________________________________________________
Modified: svn:mergeinfo
## -4,6 +4,7 ##
 /branches/openssl_1_1_1_v3:8258,8264-8265
 /branches/portfwd_memleak:7732,7736-7737,7764
 /branches/serial_port_improved:8119,8140-8141,8144,8150,8158-8160,8163,8170-8172,8183,8185,8204,8209,8212-8215
+/branches/ssh_chacha20poly1305:9209-9253
 /branches/ssh_ed25519:5495-5544
 /branches/ttproxy_improved:8041,8055-8056
 /branches/ttssh_improved:8027,8036,8040,8044,8053-8054,8058,8060,8063,8081,8085
Index: branches/4-stable/TTProxy
===================================================================
--- branches/4-stable/TTProxy	2021-05-19 14:05:07 UTC (rev 9253)
+++ branches/4-stable/TTProxy	2021-05-19 14:11:12 UTC (rev 9254)

Property changes on: branches/4-stable/TTProxy
___________________________________________________________________
Modified: svn:mergeinfo
## -1,5 +1,6 ##
 /branches/openssl_1_1_1_v2/TTProxy:7785-7786,7788-7808,7861-7863,7898,7900,7902-7903,7909,7924,7934,7954-7957,7959,7973,7975,7979-7980
 /branches/openssl_1_1_1_v3/TTProxy:8258
+/branches/ssh_chacha20poly1305/TTProxy:9209-9253
 /branches/ttproxy_improved/TTProxy:8041,8055-8056
 /branches/ttssh_improved/TTProxy:8040
 /branches/vs2015_warn/TTProxy:6194-6285
Index: branches/4-stable/TTXKanjiMenu
===================================================================
--- branches/4-stable/TTXKanjiMenu	2021-05-19 14:05:07 UTC (rev 9253)
+++ branches/4-stable/TTXKanjiMenu	2021-05-19 14:11:12 UTC (rev 9254)

Property changes on: branches/4-stable/TTXKanjiMenu
___________________________________________________________________
Modified: svn:mergeinfo
## -1,2 +1,3 ##
+/branches/ssh_chacha20poly1305/TTXKanjiMenu:9209-9253
 /branches/vs2015_warn/TTXKanjiMenu:6194-6285
 /trunk/TTXKanjiMenu:8867
\ No newline at end of property
Index: branches/4-stable/TTXSamples
===================================================================
--- branches/4-stable/TTXSamples	2021-05-19 14:05:07 UTC (rev 9253)
+++ branches/4-stable/TTXSamples	2021-05-19 14:11:12 UTC (rev 9254)

Property changes on: branches/4-stable/TTXSamples
___________________________________________________________________
Modified: svn:mergeinfo
## -1,2 +1,3 ##
+/branches/ssh_chacha20poly1305/TTXSamples:9209-9253
 /branches/vs2015_warn/TTXSamples:6194-6285
 /trunk/TTXSamples:8867
\ No newline at end of property
Index: branches/4-stable/cygterm
===================================================================
--- branches/4-stable/cygterm	2021-05-19 14:05:07 UTC (rev 9253)
+++ branches/4-stable/cygterm	2021-05-19 14:11:12 UTC (rev 9254)

Property changes on: branches/4-stable/cygterm
___________________________________________________________________
Modified: svn:mergeinfo
## -1,2 +1,3 ##
 /branches/openssl_1_1_1_v3/cygterm:8284
+/branches/ssh_chacha20poly1305/cygterm:9209-9253
 /trunk/cygterm:8867
\ No newline at end of property
Modified: branches/4-stable/doc/en/html/about/history.html
===================================================================
--- branches/4-stable/doc/en/html/about/history.html	2021-05-19 14:05:07 UTC (rev 9253)
+++ branches/4-stable/doc/en/html/about/history.html	2021-05-19 14:11:12 UTC (rev 9254)
@@ -3278,11 +3278,11 @@
 
 <h3 id="ttssh_2.92">2021.xx.xx (Ver 2.92)</h3>
 <ul class="history">
-  <!-- li>Changes
+  <li>Changes
     <ul>
-      <li></li>
+      <li>added chach****@opens***** symmetric key cipher algorithm for SSH2 protocol.</li>
     </ul>
-  </li -->
+  </li>
 
   <li>Bug fixes
     <ul>

Modified: branches/4-stable/doc/en/html/menu/setup-ssh.html
===================================================================
--- branches/4-stable/doc/en/html/menu/setup-ssh.html	2021-05-19 14:05:07 UTC (rev 9253)
+++ branches/4-stable/doc/en/html/menu/setup-ssh.html	2021-05-19 14:11:12 UTC (rev 9254)
@@ -23,14 +23,14 @@
 	    <td>not RFC5647, PROTOCOL of OpenSSH</td>
 	  </tr>
 	  <tr>
-	    <td>aes12****@opens*****</td>
-	    <td>not RFC5647, PROTOCOL of OpenSSH</td>
-	  </tr>
-	  <tr>
 	    <td>camellia256-ctr</td>
 	    <td>draft-kanno-secsh-camellia-02</td>
 	  </tr>
 	  <tr>
+	    <td>chach****@opens*****</td>
+	    <td>PROTOCOL.chacha20poly1305 of OpenSSH</td>
+	  </tr>
+	  <tr>
 	    <td>aes256-ctr</td>
 	    <td>RFC4344</td>
 	  </tr>
@@ -59,6 +59,10 @@
 	    <td>RFC4253</td>
 	  </tr>
 	  <tr>
+	    <td>aes12****@opens*****</td>
+	    <td>not RFC5647, PROTOCOL of OpenSSH</td>
+	  </tr>
+	  <tr>
 	    <td>camellia128-ctr</td>
 	    <td>draft-kanno-secsh-camellia-02</td>
 	  </tr>
@@ -116,11 +120,11 @@
 	  </tr>
 	  <tr>
 	    <td>Blowfish(SSH1)</td>
-	    <td></td>	    
+	    <td></td>
 	  </tr>
 	  <tr>
 	    <td>DES(SSH1)</td>
-	    <td></td>	    
+	    <td></td>
 	  </tr>
 	</table>
       </dd>

Modified: branches/4-stable/doc/ja/html/about/history.html
===================================================================
--- branches/4-stable/doc/ja/html/about/history.html	2021-05-19 14:05:07 UTC (rev 9253)
+++ branches/4-stable/doc/ja/html/about/history.html	2021-05-19 14:11:12 UTC (rev 9254)
@@ -3284,11 +3284,11 @@
 
 <h3 id="ttssh_2.92">2021.xx.xx (Ver 2.92)</h3>
 <ul class="history">
-  <!-- li>\x95ύX
+  <li>\x95ύX
     <ul>
-      <li></a>
+      <li>SSH2 \x82̋\xA4\x92ʌ\xAE\x88Í\x86\x95\xFB\x8E\xAE\x82\xC9 chach****@opens***** \x82\xF0\x92lj\xC1\x82\xB5\x82\xBD\x81B</li>
     </ul>
-  </li -->
+  </li>
 
   <li>\x83o\x83O\x8FC\x90\xB3
     <ul>

Modified: branches/4-stable/doc/ja/html/menu/setup-ssh.html
===================================================================
--- branches/4-stable/doc/ja/html/menu/setup-ssh.html	2021-05-19 14:05:07 UTC (rev 9253)
+++ branches/4-stable/doc/ja/html/menu/setup-ssh.html	2021-05-19 14:11:12 UTC (rev 9254)
@@ -23,14 +23,14 @@
 	    <td>not RFC5647, PROTOCOL of OpenSSH</td>
 	  </tr>
 	  <tr>
-	    <td>aes12****@opens*****</td>
-	    <td>not RFC5647, PROTOCOL of OpenSSH</td>
-	  </tr>
-	  <tr>
 	    <td>camellia256-ctr</td>
 	    <td>draft-kanno-secsh-camellia-02</td>
 	  </tr>
 	  <tr>
+	    <td>chach****@opens*****</td>
+	    <td>PROTOCOL.chacha20poly1305 of OpenSSH</td>
+	  </tr>
+	  <tr>
 	    <td>aes256-ctr</td>
 	    <td>RFC4344</td>
 	  </tr>
@@ -59,6 +59,10 @@
 	    <td>RFC4253</td>
 	  </tr>
 	  <tr>
+	    <td>aes12****@opens*****</td>
+	    <td>not RFC5647, PROTOCOL of OpenSSH</td>
+	  </tr>
+	  <tr>
 	    <td>camellia128-ctr</td>
 	    <td>draft-kanno-secsh-camellia-02</td>
 	  </tr>

Modified: branches/4-stable/installer/release/TERATERM.INI
===================================================================
--- branches/4-stable/installer/release/TERATERM.INI	2021-05-19 14:05:07 UTC (rev 9253)
+++ branches/4-stable/installer/release/TERATERM.INI	2021-05-19 14:11:12 UTC (rev 9254)
@@ -823,10 +823,10 @@
 ;  @...arcfour128,   A...arcfour256,   B...cast128-cbc,    C...3des-ctr,
 ;  D...blowfish-ctr, E...cast128-ctr,  F...camellia128-cbc,
 ;  G...camellia192-cbc, H...camellia256-cbc, I...camellia128-ctr,
-;  J...camellia192-ctr, K...camellia256-ctr  L...a****@opens*****
-;  M...a****@opens*****
+;  J...camellia192-ctr, K...camellia256-ctr, L...a****@opens*****
+;  M...a****@opens*****, N...c****@opens*****
 ;  0...Ciphers below this line are disabled.
-CipherOrder=MLK>H:J=G9I<F8C7D;EB30A@?62
+CipherOrder=MKN>H:J=G9LI<F8C7D;EB30A@?62
 
 ; KEX algorithm order(SSH2)
 ;  1...diffie-hellman-group1-sha1

Index: branches/4-stable/teraterm
===================================================================
--- branches/4-stable/teraterm	2021-05-19 14:05:07 UTC (rev 9253)
+++ branches/4-stable/teraterm	2021-05-19 14:11:12 UTC (rev 9254)

Property changes on: branches/4-stable/teraterm
___________________________________________________________________
Modified: svn:mergeinfo
## -3,5 +3,6 ##
 /branches/openssl_1_1_1_v2/teraterm:7819-7822,7829,7832-7834,7838-7843,7846-7847,7855-7856,7858,7861-7863,7979-7980
 /branches/openssl_1_1_1_v3/teraterm:8258
 /branches/serial_port_improved/teraterm:8119,8140-8141,8144,8150,8158-8160,8163,8170,8172,8183,8185,8204,8209,8212-8215
+/branches/ssh_chacha20poly1305/teraterm:9209-9253
 /branches/vs2015_warn/teraterm:6194-6285
 /trunk/teraterm:8867
\ No newline at end of property
Index: branches/4-stable/ttpmenu
===================================================================
--- branches/4-stable/ttpmenu	2021-05-19 14:05:07 UTC (rev 9253)
+++ branches/4-stable/ttpmenu	2021-05-19 14:11:12 UTC (rev 9254)

Property changes on: branches/4-stable/ttpmenu
___________________________________________________________________
Modified: svn:mergeinfo
## -1,2 +1,3 ##
+/branches/ssh_chacha20poly1305/ttpmenu:9209-9253
 /branches/vs2015_warn/ttpmenu:6194-6285
 /trunk/ttpmenu:8867
\ No newline at end of property
Modified: branches/4-stable/ttssh2/ttxssh/CMakeLists.txt
===================================================================
--- branches/4-stable/ttssh2/ttxssh/CMakeLists.txt	2021-05-19 14:05:07 UTC (rev 9253)
+++ branches/4-stable/ttssh2/ttxssh/CMakeLists.txt	2021-05-19 14:11:12 UTC (rev 9254)
@@ -26,8 +26,14 @@
   buffer.h
   chacha.c
   chacha.h
+  cipher-3des1.c
+  cipher-chachapoly-libcrypto.c
+  cipher-chachapoly.h
+  cipher-ctr.c
+  cipher.c
   cipher.h
-  cipher-ctr.c
+  comp.c
+  comp.h
   config.h
   crypt.c
   crypt.h
@@ -47,12 +53,14 @@
   ed25519_sc25519.c
   ed25519_sc25519.h
   ed25519_verify.c
+  fwd-socks.c
+  fwd-socks.h
   fwd.c
   fwd.h
-  fwd-socks.c
-  fwd-socks.h
   fwdui.c
   fwdui.h
+  hostkey.c
+  hostkey.h
   hosts.c
   hosts.h
   kex.c
@@ -61,19 +69,25 @@
   key.h
   keyfiles.c
   keyfiles.h
+  mac.c
+  mac.h
   pkt.c
   pkt.h
+  poly1305.c
+  poly1305.h
   resource.h
   sftp.c
   sftp.h
   ssh.c
   ssh.h
+  ssherr.c
+  ssherr.h
+  ttxssh-version.h
+  ttxssh-version.rc
   ttxssh.c
   ttxssh.def
   ttxssh.h
   ttxssh.rc
-  ttxssh-version.h
-  ttxssh-version.rc
   util.c
   util.h
   x11util.c

Modified: branches/4-stable/ttssh2/ttxssh/auth.c
===================================================================
--- branches/4-stable/ttssh2/ttxssh/auth.c	2021-05-19 14:05:07 UTC (rev 9253)
+++ branches/4-stable/ttssh2/ttxssh/auth.c	2021-05-19 14:11:12 UTC (rev 9254)
@@ -94,7 +94,7 @@
 }
 
 static LRESULT CALLBACK password_wnd_proc(HWND control, UINT msg,
-										  WPARAM wParam, LPARAM lParam)
+                                          WPARAM wParam, LPARAM lParam)
 {
 	LRESULT result;
 	TPasswordControlData *data = (TPasswordControlData *)GetWindowLongPtr(control, GWLP_USERDATA);
@@ -797,7 +797,7 @@
 
 
 static INT_PTR CALLBACK auth_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
-									  LPARAM lParam)
+                                      LPARAM lParam)
 {
 	const int IDC_TIMER1 = 300; // \x8E\xA9\x93\xAE\x83\x8D\x83O\x83C\x83\x93\x82\xAA\x97L\x8C\xF8\x82ȂƂ\xAB
 	const int IDC_TIMER2 = 301; // \x83T\x83|\x81[\x83g\x82\xB3\x82\xEA\x82Ă\xA2\x82郁\x83\\x83b\x83h\x82\xF0\x8E\xA9\x93\xAE\x83`\x83F\x83b\x83N(CheckAuthListFirst)
@@ -1406,7 +1406,7 @@
 }
 
 static INT_PTR CALLBACK TIS_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
-									 LPARAM lParam)
+                                     LPARAM lParam)
 {
 	PTInstVar pvar;
 
@@ -1618,7 +1618,7 @@
 }
 
 static INT_PTR CALLBACK default_auth_dlg_proc(HWND dlg, UINT msg,
-											  WPARAM wParam, LPARAM lParam)
+                                              WPARAM wParam, LPARAM lParam)
 {
 	PTInstVar pvar;
 
@@ -1811,7 +1811,7 @@
 				s[key_len] = '\0';
 				UTIL_get_lang_msg("DLG_ABOUT_AUTH_INFO3", pvar, " with %s key from Pageant");
 				_snprintf_s(buf, sizeof(buf), _TRUNCATE, pvar->ts->UIMsg,
-				            ssh_key_type(get_keytype_from_name(s)));
+				            ssh_key_type(get_hostkey_type_from_name(s)));
 				strncat_s(dest, len, buf, _TRUNCATE);
 
 				free(s);

Modified: branches/4-stable/ttssh2/ttxssh/auth.h
===================================================================
--- branches/4-stable/ttssh2/ttxssh/auth.h	2021-05-19 14:05:07 UTC (rev 9253)
+++ branches/4-stable/ttssh2/ttxssh/auth.h	2021-05-19 14:11:12 UTC (rev 9254)
@@ -41,7 +41,7 @@
   SSHAuthMethod method;
   char *password;
   char *rhosts_client_user;
-  struct Key *key_pair;
+  Key *key_pair;
 } AUTHCred;
 
 typedef enum { GENERIC_AUTH_MODE, TIS_AUTH_MODE } AuthMode;

Copied: branches/4-stable/ttssh2/ttxssh/cipher-3des1.c (from rev 9252, branches/ssh_chacha20poly1305/ttssh2/ttxssh/cipher-3des1.c)
===================================================================
--- branches/4-stable/ttssh2/ttxssh/cipher-3des1.c	                        (rev 0)
+++ branches/4-stable/ttssh2/ttxssh/cipher-3des1.c	2021-05-19 14:11:12 UTC (rev 9254)
@@ -0,0 +1,172 @@
+/* Imported from OpenSSH-7.5p1, TeraTerm Project */
+
+/* $OpenBSD: cipher-3des1.c,v 1.12 2015/01/14 10:24:42 markus Exp $ */
+/*
+ * Copyright (c) 2003 Markus Friedl.  All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// #include "includes.h"
+
+#include <sys/types.h>
+#include <string.h>
+#include <openssl/evp.h>
+#include <windows.h>
+
+typedef unsigned int u_int;
+typedef unsigned char u_char;
+
+#include "ssherr.h"
+
+/*
+ * This is used by SSH1:
+ *
+ * What kind of triple DES are these 2 routines?
+ *
+ * Why is there a redundant initialization vector?
+ *
+ * If only iv3 was used, then, this would till effect have been
+ * outer-cbc. However, there is also a private iv1 == iv2 which
+ * perhaps makes differential analysis easier. On the other hand, the
+ * private iv1 probably makes the CRC-32 attack ineffective. This is a
+ * result of that there is no longer any known iv1 to use when
+ * choosing the X block.
+ */
+struct ssh1_3des_ctx
+{
+	EVP_CIPHER_CTX  *k1, *k2, *k3;
+};
+
+const EVP_CIPHER * evp_ssh1_3des(void);
+int ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int);
+
+static int ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, int enc)
+{
+	struct ssh1_3des_ctx *c;
+	u_char *k1, *k2, *k3;
+
+	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
+		if ((c = calloc(1, sizeof(*c))) == NULL)
+			return 0;
+		EVP_CIPHER_CTX_set_app_data(ctx, c);
+	}
+	if (key == NULL)
+		return 1;
+	if (enc == -1)
+		enc = EVP_CIPHER_CTX_encrypting(ctx); // ctx->encrypt
+	k1 = k2 = k3 = (u_char *) key;
+	k2 += 8;
+	if (EVP_CIPHER_CTX_key_length(ctx) >= 16+8) {
+		if (enc)
+			k3 += 16;
+		else
+			k1 += 16;
+	}
+	c->k1 = EVP_CIPHER_CTX_new();
+	c->k2 = EVP_CIPHER_CTX_new();
+	c->k3 = EVP_CIPHER_CTX_new();
+	/*** TODO: OPENSSL1.1.1 ERROR CHECK(ticket#39335\x82ŏ\x88\x92u\x97\\x92\xE8) ***/
+	if (EVP_CipherInit(c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 ||
+	    EVP_CipherInit(c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 ||
+	    EVP_CipherInit(c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) {
+		EVP_CIPHER_CTX_free(c->k1);
+		EVP_CIPHER_CTX_free(c->k2);
+		EVP_CIPHER_CTX_free(c->k3);
+		SecureZeroMemory(c, sizeof(*c));
+		free(c);
+		EVP_CIPHER_CTX_set_app_data(ctx, NULL);
+		return 0;
+	}
+	return 1;
+}
+
+static int ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, u_int len)
+{
+	struct ssh1_3des_ctx *c;
+
+	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
+		//error("ssh1_3des_cbc: no context");
+		return 0;
+	}
+	if (EVP_Cipher(c->k1, dest, (u_char *)src, len) == 0 ||
+	    EVP_Cipher(c->k2, dest, dest, len) == 0 ||
+	    EVP_Cipher(c->k3, dest, dest, len) == 0)
+		return 0;
+	return 1;
+}
+
+static int ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx)
+{
+	struct ssh1_3des_ctx *c;
+
+	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
+		EVP_CIPHER_CTX_free(c->k1);
+		EVP_CIPHER_CTX_free(c->k2);
+		EVP_CIPHER_CTX_free(c->k3);
+		SecureZeroMemory(c, sizeof(*c));
+		free(c);
+		EVP_CIPHER_CTX_set_app_data(ctx, NULL);
+	}
+	return 1;
+}
+
+// ssh1_3des_iv \x82͖\xA2\x8Eg\x97p\x81B
+int ssh1_3des_iv(EVP_CIPHER_CTX *evp, int doset, u_char *iv, int len)
+{
+	struct ssh1_3des_ctx *c;
+
+	if (len != 24) {
+		//fatal("%s: bad 3des iv length: %d", __func__, len);
+		return SSH_ERR_INVALID_ARGUMENT;
+	}
+
+	if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL) {
+		//fatal("%s: no 3des context", __func__);
+		return SSH_ERR_INTERNAL_ERROR;
+	}
+
+	if (doset) {
+		//debug3("%s: Installed 3DES IV", __func__);
+		memcpy(EVP_CIPHER_CTX_iv_noconst(c->k1), iv, 8);
+		memcpy(EVP_CIPHER_CTX_iv_noconst(c->k2), iv + 8, 8);
+		memcpy(EVP_CIPHER_CTX_iv_noconst(c->k3), iv + 16, 8);
+	} else {
+		//debug3("%s: Copying 3DES IV", __func__);
+		memcpy(iv, EVP_CIPHER_CTX_iv(c->k1), 8);
+		memcpy(iv + 8, EVP_CIPHER_CTX_iv(c->k2), 8);
+		memcpy(iv + 16, EVP_CIPHER_CTX_iv(c->k3), 8);
+	}
+	return 0;
+}
+
+const EVP_CIPHER *evp_ssh1_3des(void)
+{
+	static EVP_CIPHER *p = NULL;
+
+	if (p == NULL) {
+		p = EVP_CIPHER_meth_new(NID_undef, /*block_size*/8, /*key_len*/16);
+		/*** TODO: OPENSSL1.1.1 ERROR CHECK(ticket#39335\x82ŏ\x88\x92u\x97\\x92\xE8) ***/
+	}
+	if (p) {
+		EVP_CIPHER_meth_set_iv_length(p, 0);
+		EVP_CIPHER_meth_set_init(p, ssh1_3des_init);
+		EVP_CIPHER_meth_set_cleanup(p, ssh1_3des_cleanup);
+		EVP_CIPHER_meth_set_do_cipher(p, ssh1_3des_cbc);
+		EVP_CIPHER_meth_set_flags(p, EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH);
+	}
+	return (p);
+}

Copied: branches/4-stable/ttssh2/ttxssh/cipher-chachapoly-libcrypto.c (from rev 9252, branches/ssh_chacha20poly1305/ttssh2/ttxssh/cipher-chachapoly-libcrypto.c)
===================================================================
--- branches/4-stable/ttssh2/ttxssh/cipher-chachapoly-libcrypto.c	                        (rev 0)
+++ branches/4-stable/ttssh2/ttxssh/cipher-chachapoly-libcrypto.c	2021-05-19 14:11:12 UTC (rev 9254)
@@ -0,0 +1,199 @@
+/* Imported from OpenSSH-8.5p1, TeraTerm Project */
+
+/*
+ * Copyright (c) 2013 Damien Miller <djm****@mindr*****>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $OpenBSD: cipher-chachapoly-libcrypto.c,v 1.1 2020/04/03 04:32:21 djm Exp $ */
+
+// for Visual Studio 2005
+#pragma warning(disable : 4244)
+
+#include <sys/types.h>
+
+#include <stdarg.h> /* needed for log.h */
+#include <string.h>
+#include <stdio.h>  /* needed for misc.h */
+#include <windows.h>
+
+#include <openssl/evp.h>
+
+#include "ssherr.h"
+#include "cipher-chachapoly.h"
+
+
+// import from sshbuf.h
+/*	$OpenBSD: sshbuf.h,v 1.23 2020/06/22 05:54:10 djm Exp $	*/
+#define PEEK_U32(p) \
+	(((u_int32_t)(((const u_char *)(p))[0]) << 24) | \
+	 ((u_int32_t)(((const u_char *)(p))[1]) << 16) | \
+	 ((u_int32_t)(((const u_char *)(p))[2]) << 8) | \
+	  (u_int32_t)(((const u_char *)(p))[3]))
+#define POKE_U64(p, v) \
+	do { \
+		const u_int64_t __v = (v); \
+		((u_char *)(p))[0] = (__v >> 56) & 0xff; \
+		((u_char *)(p))[1] = (__v >> 48) & 0xff; \
+		((u_char *)(p))[2] = (__v >> 40) & 0xff; \
+		((u_char *)(p))[3] = (__v >> 32) & 0xff; \
+		((u_char *)(p))[4] = (__v >> 24) & 0xff; \
+		((u_char *)(p))[5] = (__v >> 16) & 0xff; \
+		((u_char *)(p))[6] = (__v >> 8) & 0xff; \
+		((u_char *)(p))[7] = __v & 0xff; \
+	} while (0)
+
+
+// import from openbsd-compat/timingsafe_bcmp.c
+/*	$OpenBSD: timingsafe_bcmp.c,v 1.1 2010/09/24 13:33:00 matthew Exp $	*/
+int
+timingsafe_bcmp(const void* b1, const void* b2, size_t n)
+{
+	const unsigned char* p1 = b1, * p2 = b2;
+	int ret = 0;
+
+	for (; n > 0; n--)
+		ret |= *p1++ ^ *p2++;
+	return (ret != 0);
+}
+
+
+struct chachapoly_ctx {
+	EVP_CIPHER_CTX *main_evp, *header_evp;
+};
+
+struct chachapoly_ctx *
+chachapoly_new(const u_char *key, u_int keylen)
+{
+	struct chachapoly_ctx *ctx;
+
+	if (keylen != (32 + 32)) /* 2 x 256 bit keys */
+		return NULL;
+	if ((ctx = calloc(1, sizeof(*ctx))) == NULL)
+		return NULL;
+	if ((ctx->main_evp = EVP_CIPHER_CTX_new()) == NULL ||
+	    (ctx->header_evp = EVP_CIPHER_CTX_new()) == NULL)
+		goto fail;
+	if (!EVP_CipherInit(ctx->main_evp, EVP_chacha20(), key, NULL, 1))
+		goto fail;
+	if (!EVP_CipherInit(ctx->header_evp, EVP_chacha20(), key + 32, NULL, 1))
+		goto fail;
+	if (EVP_CIPHER_CTX_iv_length(ctx->header_evp) != 16)
+		goto fail;
+	return ctx;
+ fail:
+	chachapoly_free(ctx);
+	return NULL;
+}
+
+void
+chachapoly_free(struct chachapoly_ctx *cpctx)
+{
+	if (cpctx == NULL)
+		return;
+	EVP_CIPHER_CTX_free(cpctx->main_evp);
+	EVP_CIPHER_CTX_free(cpctx->header_evp);
+	SecureZeroMemory(cpctx, sizeof(*cpctx));
+}
+
+/*
+ * chachapoly_crypt() operates as following:
+ * En/decrypt with header key 'aadlen' bytes from 'src', storing result
+ * to 'dest'. The ciphertext here is treated as additional authenticated
+ * data for MAC calculation.
+ * En/decrypt 'len' bytes at offset 'aadlen' from 'src' to 'dest'. Use
+ * POLY1305_TAGLEN bytes at offset 'len'+'aadlen' as the authentication
+ * tag. This tag is written on encryption and verified on decryption.
+ */
+int
+chachapoly_crypt(struct chachapoly_ctx *ctx, u_int seqnr, u_char *dest,
+    const u_char *src, u_int len, u_int aadlen, u_int authlen, int do_encrypt)
+{
+	u_char seqbuf[16]; /* layout: u64 counter || u64 seqno */
+	int r = SSH_ERR_INTERNAL_ERROR;
+	u_char expected_tag[POLY1305_TAGLEN], poly_key[POLY1305_KEYLEN];
+
+	/*
+	 * Run ChaCha20 once to generate the Poly1305 key. The IV is the
+	 * packet sequence number.
+	 */
+	memset(seqbuf, 0, sizeof(seqbuf));
+	POKE_U64(seqbuf + 8, seqnr);
+	memset(poly_key, 0, sizeof(poly_key));
+	if (!EVP_CipherInit(ctx->main_evp, NULL, NULL, seqbuf, 1) ||
+	    EVP_Cipher(ctx->main_evp, poly_key,
+	    poly_key, sizeof(poly_key)) < 0) {
+		r = SSH_ERR_LIBCRYPTO_ERROR;
+		goto out;
+	}
+
+	/* If decrypting, check tag before anything else */
+	if (!do_encrypt) {
+		const u_char *tag = src + aadlen + len;
+
+		poly1305_auth(expected_tag, src, aadlen + len, poly_key);
+		if (timingsafe_bcmp(expected_tag, tag, POLY1305_TAGLEN) != 0) {
+			r = SSH_ERR_MAC_INVALID;
+			goto out;
+		}
+	}
+
+	/* Crypt additional data */
+	if (aadlen) {
+		if (!EVP_CipherInit(ctx->header_evp, NULL, NULL, seqbuf, 1) ||
+		    EVP_Cipher(ctx->header_evp, dest, src, aadlen) < 0) {
+			r = SSH_ERR_LIBCRYPTO_ERROR;
+			goto out;
+		}
+	}
+
+	/* Set Chacha's block counter to 1 */
+	seqbuf[0] = 1;
+	if (!EVP_CipherInit(ctx->main_evp, NULL, NULL, seqbuf, 1) ||
+	    EVP_Cipher(ctx->main_evp, dest + aadlen, src + aadlen, len) < 0) {
+		r = SSH_ERR_LIBCRYPTO_ERROR;
+		goto out;
+	}
+
+	/* If encrypting, calculate and append tag */
+	if (do_encrypt) {
+		poly1305_auth(dest + aadlen + len, dest, aadlen + len,
+		    poly_key);
+	}
+	r = 0;
+ out:
+	SecureZeroMemory(expected_tag, sizeof(expected_tag));
+	SecureZeroMemory(seqbuf, sizeof(seqbuf));
+	SecureZeroMemory(poly_key, sizeof(poly_key));
+	return r;
+}
+
+/* Decrypt and extract the encrypted packet length */
+int
+chachapoly_get_length(struct chachapoly_ctx *ctx,
+    u_int *plenp, u_int seqnr, const u_char *cp, u_int len)
+{
+	u_char buf[4], seqbuf[16];
+
+	if (len < 4)
+		return SSH_ERR_MESSAGE_INCOMPLETE;
+	memset(seqbuf, 0, sizeof(seqbuf));
+	POKE_U64(seqbuf + 8, seqnr);
+	if (!EVP_CipherInit(ctx->header_evp, NULL, NULL, seqbuf, 0))
+		return SSH_ERR_LIBCRYPTO_ERROR;
+	if (EVP_Cipher(ctx->header_evp, buf, (u_char *)cp, sizeof(buf)) < 0)
+		return SSH_ERR_LIBCRYPTO_ERROR;
+	*plenp = PEEK_U32(buf);
+	return 0;
+}

Copied: branches/4-stable/ttssh2/ttxssh/cipher-chachapoly.h (from rev 9252, branches/ssh_chacha20poly1305/ttssh2/ttxssh/cipher-chachapoly.h)
===================================================================
--- branches/4-stable/ttssh2/ttxssh/cipher-chachapoly.h	                        (rev 0)
+++ branches/4-stable/ttssh2/ttxssh/cipher-chachapoly.h	2021-05-19 14:11:12 UTC (rev 9254)
@@ -0,0 +1,44 @@
+/* Imported from OpenSSH-8.5p1, TeraTerm Project */
+
+/* $OpenBSD: cipher-chachapoly.h,v 1.5 2020/04/03 04:27:03 djm Exp $ */
+
+/*
+ * Copyright (c) Damien Miller 2013 <djm****@mindr*****>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef CHACHA_POLY_AEAD_H
+#define CHACHA_POLY_AEAD_H
+
+#include <sys/types.h>
+typedef unsigned int u_int32_t;
+typedef unsigned long long u_int64_t;
+
+#include "chacha.h"
+#include "poly1305.h"
+
+#define CHACHA_KEYLEN	32 /* Only 256 bit keys used here */
+
+struct chachapoly_ctx;
+typedef struct chachapoly_ctx chachapoly_ctx;
+
+struct chachapoly_ctx* chachapoly_new(const u_char* key, u_int keylen);
+void chachapoly_free(struct chachapoly_ctx* cpctx);
+
+int	chachapoly_crypt(struct chachapoly_ctx* cpctx, u_int seqnr,
+    u_char* dest, const u_char* src, u_int len, u_int aadlen, u_int authlen,
+    int do_encrypt);
+int	chachapoly_get_length(struct chachapoly_ctx* cpctx,
+    u_int* plenp, u_int seqnr, const u_char* cp, u_int len);
+
+#endif /* CHACHA_POLY_AEAD_H */

Copied: branches/4-stable/ttssh2/ttxssh/cipher.c (from rev 9252, branches/ssh_chacha20poly1305/ttssh2/ttxssh/cipher.c)
===================================================================
--- branches/4-stable/ttssh2/ttxssh/cipher.c	                        (rev 0)
+++ branches/4-stable/ttssh2/ttxssh/cipher.c	2021-05-19 14:11:12 UTC (rev 9254)
@@ -0,0 +1,634 @@
+/*
+ * Copyright (c) 1998-2001, Robert O'Callahan
+ * (C) 2004- TeraTerm Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ttxssh.h"
+#include "ssh.h"
+#include "ssherr.h"
+#include "cipher.h"
+#include "kex.h"
+
+#include <openssl/evp.h>
+
+// from cipher-3des.c
+extern const EVP_CIPHER* evp_ssh1_3des(void);
+
+static const struct ssh2cipher ssh2_ciphers[] = {
+	{SSH2_CIPHER_3DES_CBC,        "3des-cbc",         8, 24,    0, 0, 0, EVP_des_ede3_cbc},     // RFC4253
+	{SSH2_CIPHER_AES128_CBC,      "aes128-cbc",      16, 16,    0, 0, 0, EVP_aes_128_cbc},      // RFC4253
+	{SSH2_CIPHER_AES192_CBC,      "aes192-cbc",      16, 24,    0, 0, 0, EVP_aes_192_cbc},      // RFC4253
+	{SSH2_CIPHER_AES256_CBC,      "aes256-cbc",      16, 32,    0, 0, 0, EVP_aes_256_cbc},      // RFC4253
+	{SSH2_CIPHER_BLOWFISH_CBC,    "blowfish-cbc",     8, 16,    0, 0, 0, EVP_bf_cbc},           // RFC4253
+	{SSH2_CIPHER_AES128_CTR,      "aes128-ctr",      16, 16,    0, 0, 0, evp_aes_128_ctr},      // RFC4344
+	{SSH2_CIPHER_AES192_CTR,      "aes192-ctr",      16, 24,    0, 0, 0, evp_aes_128_ctr},      // RFC4344
+	{SSH2_CIPHER_AES256_CTR,      "aes256-ctr",      16, 32,    0, 0, 0, evp_aes_128_ctr},      // RFC4344
+	{SSH2_CIPHER_ARCFOUR,         "arcfour",          8, 16,    0, 0, 0, EVP_rc4},              // RFC4253
+	{SSH2_CIPHER_ARCFOUR128,      "arcfour128",       8, 16, 1536, 0, 0, EVP_rc4},              // RFC4345
+	{SSH2_CIPHER_ARCFOUR256,      "arcfour256",       8, 32, 1536, 0, 0, EVP_rc4},              // RFC4345
+	{SSH2_CIPHER_CAST128_CBC,     "cast128-cbc",      8, 16,    0, 0, 0, EVP_cast5_cbc},        // RFC4253
+	{SSH2_CIPHER_3DES_CTR,        "3des-ctr",         8, 24,    0, 0, 0, evp_des3_ctr},         // RFC4344
+	{SSH2_CIPHER_BLOWFISH_CTR,    "blowfish-ctr",     8, 32,    0, 0, 0, evp_bf_ctr},           // RFC4344
+	{SSH2_CIPHER_CAST128_CTR,     "cast128-ctr",      8, 16,    0, 0, 0, evp_cast5_ctr},        // RFC4344
+	{SSH2_CIPHER_CAMELLIA128_CBC, "camellia128-cbc", 16, 16,    0, 0, 0, EVP_camellia_128_cbc}, // draft-kanno-secsh-camellia-02
+	{SSH2_CIPHER_CAMELLIA192_CBC, "camellia192-cbc", 16, 24,    0, 0, 0, EVP_camellia_192_cbc}, // draft-kanno-secsh-camellia-02
+	{SSH2_CIPHER_CAMELLIA256_CBC, "camellia256-cbc", 16, 32,    0, 0, 0, EVP_camellia_256_cbc}, // draft-kanno-secsh-camellia-02
+	{SSH2_CIPHER_CAMELLIA128_CTR, "camellia128-ctr", 16, 16,    0, 0, 0, evp_camellia_128_ctr}, // draft-kanno-secsh-camellia-02
+	{SSH2_CIPHER_CAMELLIA192_CTR, "camellia192-ctr", 16, 24,    0, 0, 0, evp_camellia_128_ctr}, // draft-kanno-secsh-camellia-02
+	{SSH2_CIPHER_CAMELLIA256_CTR, "camellia256-ctr", 16, 32,    0, 0, 0, evp_camellia_128_ctr}, // draft-kanno-secsh-camellia-02
+#ifdef WITH_CAMELLIA_PRIVATE
+	{SSH2_CIPHER_CAMELLIA128_CBC, "camel****@opens*****", 16, 16, 0,  0,  0, EVP_camellia_128_cbc},
+	{SSH2_CIPHER_CAMELLIA192_CBC, "camel****@opens*****", 16, 24, 0,  0,  0, EVP_camellia_192_cbc},
+	{SSH2_CIPHER_CAMELLIA256_CBC, "camel****@opens*****", 16, 32, 0,  0,  0, EVP_camellia_256_cbc},
+	{SSH2_CIPHER_CAMELLIA128_CTR, "camel****@opens*****", 16, 16, 0,  0,  0, evp_camellia_128_ctr},
+	{SSH2_CIPHER_CAMELLIA192_CTR, "camel****@opens*****", 16, 24, 0,  0,  0, evp_camellia_128_ctr},
+	{SSH2_CIPHER_CAMELLIA256_CTR, "camel****@opens*****", 16, 32, 0,  0,  0, evp_camellia_128_ctr},
+#endif // WITH_CAMELLIA_PRIVATE
+	{SSH2_CIPHER_AES128_GCM,      "aes12****@opens*****",      16, 16, 0, 12, 16, EVP_aes_128_gcm}, // not RFC5647, PROTOCOL of OpenSSH
+	{SSH2_CIPHER_AES256_GCM,      "aes25****@opens*****",      16, 32, 0, 12, 16, EVP_aes_256_gcm}, // not RFC5647, PROTOCOL of OpenSSH
+	{SSH2_CIPHER_CHACHAPOLY,      "chach****@opens*****",  8, 64, 0, 0, 16, EVP_enc_null},
+	{SSH_CIPHER_NONE,             "none",             8,  0,    0, 0, 0, EVP_enc_null},         // for no passphrase key file
+	{SSH_CIPHER_3DES,             "3des",             8, 16,    0, 0, 0, evp_ssh1_3des},        // for RSA1 key file
+};
+
+
+int get_cipher_id(const struct ssh2cipher *cipher)
+{
+	if (cipher) {
+		return cipher->id;
+	}
+	else {
+		return 0;
+	}
+}
+
+u_int get_cipher_block_size(const struct ssh2cipher *cipher)
+{
+	u_int blocksize = 0;
+	
+	if (cipher) {
+		blocksize = cipher->block_size;
+	}
+
+	return max(blocksize, 8);
+}
+
+u_int get_cipher_key_len(const struct ssh2cipher *cipher)
+{
+	if (cipher) {
+		return cipher->key_len;
+	}
+	else {
+		return 0;
+	}
+}
+
+u_int get_cipher_discard_len(const struct ssh2cipher *cipher)
+{
+	if (cipher) {
+		return cipher->discard_len;
+	}
+	else {
+		return 0;
+	}
+}
+
+u_int get_cipher_iv_len(const struct ssh2cipher *cipher)
+{
+	if (cipher) {
+		if (cipher->iv_len != 0 || cipher->id == SSH2_CIPHER_CHACHAPOLY) {
+			return cipher->iv_len;
+		}
+		else {
+			return cipher->block_size;
+		}
+	}
+	else {
+		return 8; // block_size
+	}
+}
+
+u_int get_cipher_auth_len(const struct ssh2cipher *cipher)
+{
+	if (cipher) {
+		return cipher->auth_len;
+	}
+	else {
+		return 0;
+	}
+}
+
+const EVP_CIPHER *get_cipher_EVP_CIPHER(const struct ssh2cipher *cipher)
+{
+	if (cipher) {
+		return cipher->func();
+	}
+	else {
+		return EVP_enc_null();
+	}
+}
+
+char *get_cipher_string(const struct ssh2cipher *cipher)
+{
+	if (cipher) {
+		return cipher->name;
+	}
+	else {
+		return "unknown";
+	}
+}
+
+// \x88Í\x86\x83A\x83\x8B\x83S\x83\x8A\x83Y\x83\x80\x96\xBC\x82\xA9\x82猟\x8D\x{142DC2}\xE9\x81B
+const struct ssh2cipher *get_cipher_by_name(char *name)
+{
+	const struct ssh2cipher *ptr = ssh2_ciphers;
+
+	if (name == NULL || name[0] == '\0')
+		return NULL;
+
+	while (ptr->name != NULL) {
+		if (strcmp(ptr->name, name) == 0) {
+			return ptr;
+		}
+		ptr++;
+	}
+
+	// not found.
+	return NULL;
+}
+
+// \x95\\x8E\xA6\x96\xBC
+char *get_cipher_name(int cipher_id)
+{
+	switch (cipher_id) {
+	case SSH_CIPHER_NONE:
+		return "None";
+	case SSH_CIPHER_3DES:
+		return "3DES (168 key bits)";
+	case SSH_CIPHER_DES:
+		return "DES (56 key bits)";
+	case SSH_CIPHER_BLOWFISH:
+		return "Blowfish (256 key bits)";
+
+	// SSH2 
+	case SSH2_CIPHER_3DES_CBC:
+		return "3des-cbc";
+	case SSH2_CIPHER_AES128_CBC:
+		return "aes128-cbc";
+	case SSH2_CIPHER_AES192_CBC:
+		return "aes192-cbc";
+	case SSH2_CIPHER_AES256_CBC:
+		return "aes256-cbc";
+	case SSH2_CIPHER_BLOWFISH_CBC:
+		return "blowfish-cbc";
+	case SSH2_CIPHER_AES128_CTR:
+		return "aes128-ctr";
+	case SSH2_CIPHER_AES192_CTR:
+		return "aes192-ctr";
+	case SSH2_CIPHER_AES256_CTR:
+		return "aes256-ctr";
+	case SSH2_CIPHER_ARCFOUR:
+		return "arcfour";
+	case SSH2_CIPHER_ARCFOUR128:
+		return "arcfour128";
+	case SSH2_CIPHER_ARCFOUR256:
+		return "arcfour256";
+	case SSH2_CIPHER_CAST128_CBC:
+		return "cast-128-cbc";
+	case SSH2_CIPHER_3DES_CTR:
+		return "3des-ctr";
+	case SSH2_CIPHER_BLOWFISH_CTR:
+		return "blowfish-ctr";
+	case SSH2_CIPHER_CAST128_CTR:
+		return "cast-128-ctr";
+	case SSH2_CIPHER_CAMELLIA128_CBC:
+		return "camellia128-cbc";
+	case SSH2_CIPHER_CAMELLIA192_CBC:
+		return "camellia192-cbc";
+	case SSH2_CIPHER_CAMELLIA256_CBC:
+		return "camellia256-cbc";
+	case SSH2_CIPHER_CAMELLIA128_CTR:
+		return "camellia128-ctr";
+	case SSH2_CIPHER_CAMELLIA192_CTR:
+		return "camellia192-ctr";
+	case SSH2_CIPHER_CAMELLIA256_CTR:
+		return "camellia256-ctr";
+	case SSH2_CIPHER_AES128_GCM:
+		return "aes12****@opens*****";
+	case SSH2_CIPHER_AES256_GCM:
+		return "aes25****@opens*****";
+	case SSH2_CIPHER_CHACHAPOLY:
+		return "chach****@opens*****(SSH2)";
+
+	default:
+		return "Unknown";
+	}
+}
+
+// \x83\x8A\x83X\x83g\x83{\x83b\x83N\x83X\x95\\x8E\xA6\x96\xBC
+char *get_listbox_cipher_name(int cipher_id, PTInstVar pvar)
+{
+	switch (cipher_id) {
+	case SSH_CIPHER_NONE:
+		UTIL_get_lang_msg("DLG_SSHSETUP_CIPHER_BORDER", pvar,
+		                  "<ciphers below this line are disabled>");
+		return pvar->ts->UIMsg;
+	case SSH_CIPHER_3DES:
+		return "3DES(SSH1)";
+	case SSH_CIPHER_DES:
+		return "DES(SSH1)";
+	case SSH_CIPHER_BLOWFISH:
+		return "Blowfish(SSH1)";
+
+	// for SSH2(yutaka)
+	case SSH2_CIPHER_AES128_CBC:
+		return "aes128-cbc(SSH2)";
+	case SSH2_CIPHER_AES192_CBC:
+		return "aes192-cbc(SSH2)";
+	case SSH2_CIPHER_AES256_CBC:
+		return "aes256-cbc(SSH2)";
+	case SSH2_CIPHER_3DES_CBC:
+		return "3des-cbc(SSH2)";
+	case SSH2_CIPHER_BLOWFISH_CBC:
+		return "blowfish-cbc(SSH2)";
+	case SSH2_CIPHER_AES128_CTR:
+		return "aes128-ctr(SSH2)";
+	case SSH2_CIPHER_AES192_CTR:
+		return "aes192-ctr(SSH2)";
+	case SSH2_CIPHER_AES256_CTR:
+		return "aes256-ctr(SSH2)";
+	case SSH2_CIPHER_ARCFOUR:
+		return "arcfour(SSH2)";
+	case SSH2_CIPHER_ARCFOUR128:
+		return "arcfour128(SSH2)";
+	case SSH2_CIPHER_ARCFOUR256:
+		return "arcfour256(SSH2)";
+	case SSH2_CIPHER_CAST128_CBC:
+		return "cast128-cbc(SSH2)";
+	case SSH2_CIPHER_3DES_CTR:
+		return "3des-ctr(SSH2)";
+	case SSH2_CIPHER_BLOWFISH_CTR:
+		return "blowfish-ctr(SSH2)";
+	case SSH2_CIPHER_CAST128_CTR:
+		return "cast128-ctr(SSH2)";
+	case SSH2_CIPHER_CAMELLIA128_CBC:
+		return "camellia128-cbc(SSH2)";
+	case SSH2_CIPHER_CAMELLIA192_CBC:
+		return "camellia192-cbc(SSH2)";
+	case SSH2_CIPHER_CAMELLIA256_CBC:
+		return "camellia256-cbc(SSH2)";
+	case SSH2_CIPHER_CAMELLIA128_CTR:
+		return "camellia128-ctr(SSH2)";
+	case SSH2_CIPHER_CAMELLIA192_CTR:
+		return "camellia192-ctr(SSH2)";
+	case SSH2_CIPHER_CAMELLIA256_CTR:
+		return "camellia256-ctr(SSH2)";
+	case SSH2_CIPHER_AES128_GCM:
+		return "aes12****@opens*****(SSH2)";
+	case SSH2_CIPHER_AES256_GCM:
+		return "aes25****@opens*****(SSH2)";
+	case SSH2_CIPHER_CHACHAPOLY:
+		return "chach****@opens*****(SSH2)";
+
+	default:
+		return NULL;
+	}
+}
+
+/*
+ * Remove unsupported cipher or duplicated cipher.
+ * Add unspecified ciphers at the end of list.
+ */
+void normalize_cipher_order(char *buf)
+{
+	/* SSH_CIPHER_NONE means that all ciphers below that one are disabled.
+	   We *never* allow no encryption. */
+	static char default_strings[] = {
+		SSH2_CIPHER_AES256_GCM,
+		SSH2_CIPHER_CAMELLIA256_CTR,
+		SSH2_CIPHER_CHACHAPOLY,
+		SSH2_CIPHER_AES256_CTR,
+		SSH2_CIPHER_CAMELLIA256_CBC,
+		SSH2_CIPHER_AES256_CBC,
+		SSH2_CIPHER_CAMELLIA192_CTR,
+		SSH2_CIPHER_AES192_CTR,
+		SSH2_CIPHER_CAMELLIA192_CBC,
+		SSH2_CIPHER_AES192_CBC,
+		SSH2_CIPHER_AES128_GCM,
+		SSH2_CIPHER_CAMELLIA128_CTR,
+		SSH2_CIPHER_AES128_CTR,
+		SSH2_CIPHER_CAMELLIA128_CBC,
+		SSH2_CIPHER_AES128_CBC,
+		SSH2_CIPHER_3DES_CTR,
+		SSH2_CIPHER_3DES_CBC,
+		SSH2_CIPHER_BLOWFISH_CTR,
+		SSH2_CIPHER_BLOWFISH_CBC,
+		SSH2_CIPHER_CAST128_CTR,
+		SSH2_CIPHER_CAST128_CBC,
+		SSH_CIPHER_3DES,
+		SSH_CIPHER_NONE,
+		SSH2_CIPHER_ARCFOUR256,
+		SSH2_CIPHER_ARCFOUR128,
+		SSH2_CIPHER_ARCFOUR,
+		SSH_CIPHER_BLOWFISH,
+		SSH_CIPHER_DES,
+		0, 0, 0 // Dummy for SSH_CIPHER_IDEA, SSH_CIPHER_TSS, SSH_CIPHER_RC4
+	};
+
+	normalize_generic_order(buf, default_strings, NUM_ELEM(default_strings));
+}
+
+const struct ssh2cipher *choose_SSH2_cipher_algorithm(char *server_proposal, char *my_proposal)
+{
+	char str_cipher[32];
+	const struct ssh2cipher *ptr = ssh2_ciphers;
+
+	choose_SSH2_proposal(server_proposal, my_proposal, str_cipher, sizeof(str_cipher));
+	return get_cipher_by_name(str_cipher);
+}
+
+void SSH2_update_cipher_myproposal(PTInstVar pvar)
+{
+	static char buf[512]; // TODO: malloc()\x82ɂ\xB7\x82ׂ\xAB
+	int cipher;
+	int len, i;
+	char *c_str;
+
+	// \x92ʐM\x92\x86\x82ɂ͌Ă΂\xEA\x82Ȃ\xA2\x82͂\xB8\x82\xBE\x82\xAA\x81A\x94O\x82̂\xBD\x82߁B(2006.6.26 maya)
+	if (pvar->socket != INVALID_SOCKET) {
+		return;
+	}
+
+	// \x88Í\x86\x83A\x83\x8B\x83S\x83\x8A\x83Y\x83\x80\x97D\x90揇\x88ʂɉ\x9E\x82\xB6\x82āAmyproposal[]\x82\xF0\x8F\x91\x82\xAB\x8A\xB7\x82\xA6\x82\xE9\x81B(2004.11.6 yutaka)
+	buf[0] = '\0';
+	for (i = 0 ; pvar->settings.CipherOrder[i] != 0 ; i++) {
+		cipher = pvar->settings.CipherOrder[i] - '0';
+		if (cipher == 0) // disabled line
+			break;
+		switch (cipher) {
+			case SSH2_CIPHER_3DES_CBC:
+				c_str = "3des-cbc,";
+				break;
+			case SSH2_CIPHER_3DES_CTR:
+				c_str = "3des-ctr,";
+				break;
+			case SSH2_CIPHER_BLOWFISH_CBC:
+				c_str = "blowfish-cbc,";
+				break;
+			case SSH2_CIPHER_BLOWFISH_CTR:
+				c_str = "blowfish-ctr,";
+				break;
+			case SSH2_CIPHER_AES128_CBC:
+				c_str = "aes128-cbc,";
+				break;
+			case SSH2_CIPHER_AES192_CBC:
+				c_str = "aes192-cbc,";
+				break;
+			case SSH2_CIPHER_AES256_CBC:
+				c_str = "aes256-cbc,";
+				break;
+			case SSH2_CIPHER_AES128_CTR:
+				c_str = "aes128-ctr,";
+				break;
+			case SSH2_CIPHER_AES192_CTR:
+				c_str = "aes192-ctr,";
+				break;
+			case SSH2_CIPHER_AES256_CTR:
+				c_str = "aes256-ctr,";
+				break;
+			case SSH2_CIPHER_ARCFOUR:
+				c_str = "arcfour,";
+				break;
+			case SSH2_CIPHER_ARCFOUR128:
+				c_str = "arcfour128,";
+				break;
+			case SSH2_CIPHER_ARCFOUR256:
+				c_str = "arcfour256,";
+				break;
+			case SSH2_CIPHER_CAST128_CBC:
+				c_str = "cast128-cbc,";
+				break;
+			case SSH2_CIPHER_CAST128_CTR:
+				c_str = "cast128-ctr,";
+				break;
+#ifdef WITH_CAMELLIA_PRIVATE
+			case SSH2_CIPHER_CAMELLIA128_CBC:
+				c_str = "camellia128-cbc,camel****@opens*****,";
+				break;
+			case SSH2_CIPHER_CAMELLIA192_CBC:
+				c_str = "camellia192-cbc,camel****@opens*****,";
+				break;
+			case SSH2_CIPHER_CAMELLIA256_CBC:
+				c_str = "camellia256-cbc,camel****@opens*****,";
+				break;
+			case SSH2_CIPHER_CAMELLIA128_CTR:
+				c_str = "camellia128-ctr,camel****@opens*****,";
+				break;
+			case SSH2_CIPHER_CAMELLIA192_CTR:
+				c_str = "camellia192-ctr,camel****@opens*****,";
+				break;
+			case SSH2_CIPHER_CAMELLIA256_CTR:
+				c_str = "camellia256-ctr,camel****@opens*****,";
+				break;
+#endif // WITH_CAMELLIA_PRIVATE
+			case SSH2_CIPHER_CAMELLIA128_CBC:
+				c_str = "camellia128-cbc,";
+				break;
+			case SSH2_CIPHER_CAMELLIA192_CBC:
+				c_str = "camellia192-cbc,";
+				break;
+			case SSH2_CIPHER_CAMELLIA256_CBC:
+				c_str = "camellia256-cbc,";
+				break;
+			case SSH2_CIPHER_CAMELLIA128_CTR:
+				c_str = "camellia128-ctr,";
+				break;
+			case SSH2_CIPHER_CAMELLIA192_CTR:
+				c_str = "camellia192-ctr,";
+				break;
+			case SSH2_CIPHER_CAMELLIA256_CTR:
+				c_str = "camellia256-ctr,";
+				break;
+			case SSH2_CIPHER_AES128_GCM:
+				c_str = "aes12****@opens*****,";
+				break;
+			case SSH2_CIPHER_AES256_GCM:
+				c_str = "aes25****@opens*****,";
+				break;
+			case SSH2_CIPHER_CHACHAPOLY:
+				c_str = "chach****@opens*****,";
+				break;
+			default:
+				continue;
+		}
+		strncat_s(buf, sizeof(buf), c_str, _TRUNCATE);
+	}
+	len = strlen(buf);
+	if (len > 0)
+		buf[len - 1] = '\0';  // get rid of comma
+	myproposal[PROPOSAL_ENC_ALGS_CTOS] = buf;  // Client To Server
+	myproposal[PROPOSAL_ENC_ALGS_STOC] = buf;  // Server To Client
+}
+
+
+//
+// SSH2\x97p\x83A\x83\x8B\x83S\x83\x8A\x83Y\x83\x80\x82̏\x89\x8A\xFA\x89\xBB
+//
+int cipher_init_SSH2(
+	struct sshcipher_ctx **ccp, const struct ssh2cipher *cipher,
+	const u_char *key, u_int keylen,
+	const u_char *iv, u_int ivlen,
+	int do_encrypt,
+	PTInstVar pvar)
+{
+	struct sshcipher_ctx *cc = NULL;
+	int ret = SSH_ERR_INTERNAL_ERROR;
+	const EVP_CIPHER *type;
+	int klen;
+	unsigned char *junk = NULL, *discard = NULL;
+	char tmp[80];
+
+	*ccp = NULL;
+	if ((cc = calloc(sizeof(*cc), 1)) == NULL) {
+		UTIL_get_lang_msg("MSG_CIPHER_INIT_ERROR", pvar, "Cipher initialize error(%d)");
+		_snprintf_s(tmp, sizeof(tmp), _TRUNCATE, pvar->ts->UIMsg, 1);
+		notify_fatal_error(pvar, tmp, TRUE);
+		return SSH_ERR_ALLOC_FAIL;
+	}
+
+	if (keylen < cipher->key_len) {
+		UTIL_get_lang_msg("MSG_CIPHER_INIT_ERROR", pvar, "Cipher initialize error(%d)");
+		_snprintf_s(tmp, sizeof(tmp), _TRUNCATE, pvar->ts->UIMsg, 2);
+		notify_fatal_error(pvar, tmp, TRUE);
+		ret = SSH_ERR_INVALID_ARGUMENT;
+		goto out;
+	}
+	if (iv != NULL && ivlen < get_cipher_iv_len(cipher)) {
+		UTIL_get_lang_msg("MSG_CIPHER_INIT_ERROR", pvar, "Cipher initialize error(%d)");
+		_snprintf_s(tmp, sizeof(tmp), _TRUNCATE, pvar->ts->UIMsg, 3);
+		notify_fatal_error(pvar, tmp, TRUE);
+		ret = SSH_ERR_INVALID_ARGUMENT;
+		goto out;
+	}
+
+	cc->cipher = cipher;
+	if (cipher->id == SSH2_CIPHER_CHACHAPOLY) {
+		cc->cp_ctx = chachapoly_new(key, keylen);
+		ret = cc->cp_ctx != NULL ? 0 : SSH_ERR_INVALID_ARGUMENT;
+		if (ret == SSH_ERR_INVALID_ARGUMENT) {
+			UTIL_get_lang_msg("MSG_CIPHER_INIT_ERROR", pvar, "Cipher initialize error(%d)");
+			_snprintf_s(tmp, sizeof(tmp), _TRUNCATE, pvar->ts->UIMsg, 4);
+			notify_fatal_error(pvar, tmp, TRUE);
+		}
+		goto out;
+	}
+	type = (*cipher->func)();
+	if ((cc->evp = EVP_CIPHER_CTX_new()) == NULL) {
+		UTIL_get_lang_msg("MSG_CIPHER_INIT_ERROR", pvar, "Cipher initialize error(%d)");
+		_snprintf_s(tmp, sizeof(tmp), _TRUNCATE, pvar->ts->UIMsg, 5);
+		notify_fatal_error(pvar, tmp, TRUE);
+		ret = SSH_ERR_ALLOC_FAIL;
+		goto out;
+	}
+	if (EVP_CipherInit(cc->evp, type, NULL, (u_char *)iv, (do_encrypt == CIPHER_ENCRYPT)) == 0) {
+		UTIL_get_lang_msg("MSG_CIPHER_INIT_ERROR", pvar, "Cipher initialize error(%d)");
+		_snprintf_s(tmp, sizeof(tmp), _TRUNCATE, pvar->ts->UIMsg, 6);
+		notify_fatal_error(pvar, tmp, TRUE);
+		ret = SSH_ERR_LIBCRYPTO_ERROR;
+		goto out;
+	}
+	if (get_cipher_auth_len(cipher) &&
+	    !EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_SET_IV_FIXED, -1, (u_char *)iv)) {
+		UTIL_get_lang_msg("MSG_CIPHER_INIT_ERROR", pvar, "Cipher initialize error(%d)");
+		_snprintf_s(tmp, sizeof(tmp), _TRUNCATE, pvar->ts->UIMsg, 7);
+		notify_fatal_error(pvar, tmp, TRUE);
+		ret = SSH_ERR_LIBCRYPTO_ERROR;
+		goto out;
+	}
+	klen = EVP_CIPHER_CTX_key_length(cc->evp);
+	if (klen > 0 && keylen != (u_int)klen) {
+		if (EVP_CIPHER_CTX_set_key_length(cc->evp, keylen) == 0) {
+			UTIL_get_lang_msg("MSG_CIPHER_INIT_ERROR", pvar, "Cipher initialize error(%d)");
+			_snprintf_s(tmp, sizeof(tmp), _TRUNCATE, pvar->ts->UIMsg, 8);
+			notify_fatal_error(pvar, tmp, TRUE);
+			ret = SSH_ERR_LIBCRYPTO_ERROR;
+			goto out;
+		}
+	}
+	if (EVP_CipherInit(cc->evp, NULL, (u_char *)key, NULL, -1) == 0) {
+		UTIL_get_lang_msg("MSG_CIPHER_INIT_ERROR", pvar, "Cipher initialize error(%d)");
+		_snprintf_s(tmp, sizeof(tmp), _TRUNCATE, pvar->ts->UIMsg, 9);
+		notify_fatal_error(pvar, tmp, TRUE);
+		ret = SSH_ERR_LIBCRYPTO_ERROR;
+		goto out;
+	}
+
+	if (cipher->discard_len > 0) {
+		junk = malloc(cipher->discard_len);
+		discard = malloc(cipher->discard_len);
+		if (junk == NULL || discard == NULL ||
+		    EVP_Cipher(cc->evp, discard, junk, cipher->discard_len) == 0) {
+			UTIL_get_lang_msg("MSG_CIPHER_INIT_ERROR", pvar, "Cipher initialize error(%d)");
+			_snprintf_s(tmp, sizeof(tmp), _TRUNCATE, pvar->ts->UIMsg, 10);
+			notify_fatal_error(pvar, tmp, TRUE);
+		}
+		else {
+			SecureZeroMemory(discard, cipher->discard_len);
+		}
+		free(junk);
+		free(discard);
+	}
+	ret = 0;
+
+out:
+	if (ret == 0) {
+		*ccp = cc;
+	}
+	else {
+		if (cc != NULL) {
+			EVP_CIPHER_CTX_free(cc->evp);
+			SecureZeroMemory(cc, sizeof(*cc));
+		}
+	}
+	return ret;
+}
+
+//
+// SSH2\x97p\x83A\x83\x8B\x83S\x83\x8A\x83Y\x83\x80\x82̔j\x8A\xFC
+///
+void cipher_free_SSH2(struct sshcipher_ctx *cc)
+{
+	if (cc == NULL)
+		return;
+	if (cc->cipher->id == SSH2_CIPHER_CHACHAPOLY) {
+		chachapoly_free(cc->cp_ctx);
+		cc->cp_ctx = NULL;
+	}
+	EVP_CIPHER_CTX_free(cc->evp);
+	cc->evp = NULL;
+	SecureZeroMemory(cc, sizeof(*cc));
+}

Modified: branches/4-stable/ttssh2/ttxssh/cipher.h
===================================================================
--- branches/4-stable/ttssh2/ttxssh/cipher.h	2021-05-19 14:05:07 UTC (rev 9253)
+++ branches/4-stable/ttssh2/ttxssh/cipher.h	2021-05-19 14:11:12 UTC (rev 9254)
@@ -1,5 +1,7 @@
-/*	$OpenBSD: cipher.h,v 1.34 2003/11/10 16:23:41 jakob Exp $	*/
+/* Imported from OpenSSH-8.5p1, TeraTerm Project */
 
+/* $OpenBSD: cipher.h,v 1.44 2014/01/25 10:12:50 dtucker Exp $ */
+
 /*
  * Author: Tatu Ylonen <ylo****@cs*****>
  * Copyright (c) 1995 Tatu Ylonen <ylo****@cs*****>, Espoo, Finland
@@ -37,7 +39,12 @@
 #ifndef CIPHER_H
 #define CIPHER_H
 
+typedef unsigned int u_int;
+typedef unsigned char u_char;
+
 #include <openssl/evp.h>
+#include "cipher-chachapoly.h"
+
 /*
  * Cipher types for SSH-1.  New types can be added, but old types should not
  * be removed for compatibility.  The maximum allowed value is 31.
@@ -45,60 +52,89 @@
 #define SSH_CIPHER_SSH2		-3
 #define SSH_CIPHER_ILLEGAL	-2	/* No valid cipher selected. */
 #define SSH_CIPHER_NOT_SET	-1	/* None selected (invalid number). */
-#define SSH_CIPHER_NONE		0	/* no encryption */
-#define SSH_CIPHER_IDEA		1	/* IDEA CFB */
-#define SSH_CIPHER_DES		2	/* DES CBC */
-#define SSH_CIPHER_3DES		3	/* 3DES CBC */
-#define SSH_CIPHER_BROKEN_TSS	4	/* TRI's Simple Stream encryption CBC */
-#define SSH_CIPHER_BROKEN_RC4	5	/* Alleged RC4 */
-#define SSH_CIPHER_BLOWFISH	6
-#define SSH_CIPHER_RESERVED	7
+//#define SSH_CIPHER_NONE		0	/* no encryption */
+//#define SSH_CIPHER_IDEA		1	/* IDEA CFB */
+//#define SSH_CIPHER_DES		2	/* DES CBC */
+//#define SSH_CIPHER_3DES		3	/* 3DES CBC */
+//#define SSH_CIPHER_BROKEN_TSS	4	/* TRI's Simple Stream encryption CBC */
+//#define SSH_CIPHER_BROKEN_RC4	5	/* Alleged RC4 */
+//#define SSH_CIPHER_BLOWFISH	6
+//#define SSH_CIPHER_RESERVED	7
 
 #define CIPHER_ENCRYPT		1
 #define CIPHER_DECRYPT		0
 
-typedef struct Cipher Cipher;
-typedef struct CipherContext CipherContext;
 
-struct Cipher;
-struct CipherContext {
-	int	plaintext;
+typedef enum {
+	// SSH1
+	SSH_CIPHER_NONE, SSH_CIPHER_IDEA, SSH_CIPHER_DES, SSH_CIPHER_3DES,
+	SSH_CIPHER_TSS, SSH_CIPHER_RC4, SSH_CIPHER_BLOWFISH,
+	// SSH2
+	SSH2_CIPHER_3DES_CBC, SSH2_CIPHER_AES128_CBC,
+	SSH2_CIPHER_AES192_CBC, SSH2_CIPHER_AES256_CBC,
+	SSH2_CIPHER_BLOWFISH_CBC, SSH2_CIPHER_AES128_CTR,
+	SSH2_CIPHER_AES192_CTR, SSH2_CIPHER_AES256_CTR,
+	SSH2_CIPHER_ARCFOUR, SSH2_CIPHER_ARCFOUR128, SSH2_CIPHER_ARCFOUR256,
+	SSH2_CIPHER_CAST128_CBC,
+	SSH2_CIPHER_3DES_CTR, SSH2_CIPHER_BLOWFISH_CTR, SSH2_CIPHER_CAST128_CTR,
+	SSH2_CIPHER_CAMELLIA128_CBC, SSH2_CIPHER_CAMELLIA192_CBC, SSH2_CIPHER_CAMELLIA256_CBC,
+	SSH2_CIPHER_CAMELLIA128_CTR, SSH2_CIPHER_CAMELLIA192_CTR, SSH2_CIPHER_CAMELLIA256_CTR,
+	SSH2_CIPHER_AES128_GCM, SSH2_CIPHER_AES256_GCM, SSH2_CIPHER_CHACHAPOLY,
+	SSH_CIPHER_MAX = SSH2_CIPHER_CHACHAPOLY,
+} SSHCipherId;
+
+struct ssh2cipher {
+	SSHCipherId id;
+	char *name;
+	u_int block_size;
+	u_int key_len;
+	u_int discard_len;
+	u_int iv_len;
+	u_int auth_len;
+	const EVP_CIPHER *(*func)(void);
+};
+
+struct sshcipher_ctx {
+	// TTSSH \x82ł\xCD SSH_CIPHER_NONE \x82\xAA\x96\xB3\x8C\xF8\x82Ȃ̂ŁAplaintext \x82͎g\x97p\x82\xB3\x82\xEA\x82Ȃ\xA2
+	// int	plaintext;
+	
+	// TTSSH \x82ł\xCD CRYPT_encrypt_aead(), CRYPT_decrypt_aead() \x82\xAA\x95ʂ\xEA\x82Ă\xA2\x82\xC4 encrypt \x82Ő؂\xE8\x91ւ\xA6\x82Ȃ\xA2\x82̂Ŏg\x97p\x82\xB3\x82\xEA\x82Ȃ\xA2
+	// int	encrypt;
+	
 	EVP_CIPHER_CTX *evp;
-	Cipher *cipher;
+	struct chachapoly_ctx *cp_ctx;
+	
+	// OpenSSH \x82\xC5 ifndef WITH_OPENSSL \x82̎\x9E\x82Ɏg\x97p\x82\xB3\x82\xEA\x82\xE9\x82\xE0\x82̂Ȃ̂ŁAac_ctx \x82͎g\x97p\x82\xB3\x82\xEA\x82Ȃ\xA2
+	// aesctr_ctx ac_ctx; /* XXX union with evp? */
+	
+	// OpenSSH \x82ł\xCD const struct sshcipher *cipher;
+	const struct ssh2cipher *cipher;
 };
 
-u_int	 cipher_mask_ssh1(int);
-Cipher	*cipher_by_name(const char *);
-Cipher	*cipher_by_number(int);
-int	 cipher_number(const char *);
-char	*cipher_name(int);
-int	 ciphers_valid(const char *);
-void	 cipher_init(CipherContext *, Cipher *, const u_char *, u_int,
-    const u_char *, u_int, int);
-void	 cipher_crypt(CipherContext *, u_char *, const u_char *, u_int);
-void	 cipher_cleanup(CipherContext *);
-void	 cipher_set_key_string(CipherContext *, Cipher *, const char *, int);
-u_int	 cipher_blocksize(const Cipher *);
-u_int	 cipher_keylen(const Cipher *);
 
-u_int	 cipher_get_number(const Cipher *);
-void	 cipher_get_keyiv(CipherContext *, u_char *, u_int);
-void	 cipher_set_keyiv(CipherContext *, u_char *);
-int	 cipher_get_keyiv_len(const CipherContext *);
-int	 cipher_get_keycontext(const CipherContext *, u_char *);
-void	 cipher_set_keycontext(CipherContext *, u_char *);
+int get_cipher_id(const struct ssh2cipher *cipher);
+u_int get_cipher_block_size(const struct ssh2cipher *cipher);
+u_int get_cipher_key_len(const struct ssh2cipher *cipher);
+u_int get_cipher_discard_len(const struct ssh2cipher *cipher);
+u_int get_cipher_iv_len(const struct ssh2cipher *cipher);
+u_int get_cipher_auth_len(const struct ssh2cipher *cipher);
+const EVP_CIPHER *get_cipher_EVP_CIPHER(const struct ssh2cipher *cipher);
+char *get_cipher_string(const struct ssh2cipher *cipher);
+const struct ssh2cipher* get_cipher_by_name(char *name);
+char *get_cipher_name(int cipher_id);
+char *get_listbox_cipher_name(int cipher_id, PTInstVar pvar);
 
-void cipher_init_SSH2(
-		EVP_CIPHER_CTX *evp,
-		const u_char *key, u_int keylen,
-		const u_char *iv, u_int ivlen,
-		int encrypt,
-		const EVP_CIPHER *type,
-		int discard_len,
-		unsigned int authlen,
-		PTInstVar pvar
+void normalize_cipher_order(char *buf);
+const struct ssh2cipher *choose_SSH2_cipher_algorithm(char *server_proposal, char *my_proposal);
+void SSH2_update_cipher_myproposal(PTInstVar pvar);
+
+int cipher_init_SSH2(
+	struct sshcipher_ctx **ccp, const struct ssh2cipher *cipher,
+	const u_char *key, u_int keylen,
+	const u_char *iv, u_int ivlen,
+	int do_encrypt,
+	PTInstVar pvar
 );
+void cipher_free_SSH2(struct sshcipher_ctx *cc);
 
-void cipher_cleanup_SSH2(EVP_CIPHER_CTX *evp);
-
 #endif				/* CIPHER_H */

Copied: branches/4-stable/ttssh2/ttxssh/comp.c (from rev 9252, branches/ssh_chacha20poly1305/ttssh2/ttxssh/comp.c)
===================================================================
--- branches/4-stable/ttssh2/ttxssh/comp.c	                        (rev 0)
+++ branches/4-stable/ttssh2/ttxssh/comp.c	2021-05-19 14:11:12 UTC (rev 9254)
@@ -0,0 +1,129 @@
+/*
+ * (C) 2021- TeraTerm Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ttxssh.h"
+#include "comp.h"
+#include "kex.h"
+
+
+struct ssh2_comp_t {
+	compression_type type;
+	char *name;
+};
+
+static const struct ssh2_comp_t ssh2_comps[] = {
+	{COMP_NOCOMP,  "none"},             // RFC4253
+	{COMP_ZLIB,    "zlib"},             // RFC4253
+	{COMP_DELAYED, "zlib****@opens*****"},
+	{COMP_NONE,    NULL},
+};
+
+
+char* get_ssh2_comp_name(compression_type type)
+{
+	const struct ssh2_comp_t *ptr = ssh2_comps;
+
+	while (ptr->name != NULL) {
+		if (type == ptr->type) {
+			return ptr->name;
+		}
+		ptr++;
+	}
+
+	// not found.
+	return "unknown";
+}
+
+void normalize_comp_order(char *buf)
+{
+	static char default_strings[] = {
+		COMP_DELAYED,
+		COMP_ZLIB,
+		COMP_NOCOMP,
+		COMP_NONE,
+	};
+
+	normalize_generic_order(buf, default_strings, NUM_ELEM(default_strings));
+}
+
+compression_type choose_SSH2_compression_algorithm(char *server_proposal, char *my_proposal)
+{
+	compression_type type = COMP_UNKNOWN;
+	char str_comp[20];
+	const struct ssh2_comp_t *ptr = ssh2_comps;
+
+	choose_SSH2_proposal(server_proposal, my_proposal, str_comp, sizeof(str_comp));
+
+	while (ptr->name != NULL) {
+		if (strcmp(ptr->name, str_comp) == 0) {
+			type = ptr->type;
+			break;
+		}
+		ptr++;
+	}
+
+	return (type);
+}
+
+void SSH2_update_compression_myproposal(PTInstVar pvar)
+{
+	static char buf[128]; // TODO: malloc()\x82ɂ\xB7\x82ׂ\xAB
+	int index;
+	int len, i;
+
+	// \x92ʐM\x92\x86\x82ɂ͌Ă΂\xEA\x82Ȃ\xA2\x82͂\xB8\x82\xBE\x82\xAA\x81A\x94O\x82̂\xBD\x82߁B(2006.6.26 maya)
+	if (pvar->socket != INVALID_SOCKET) {
+		return;
+	}
+
+	// \x88\xB3\x8Fk\x83\x8C\x83x\x83\x8B\x82ɉ\x9E\x82\xB6\x82āAmyproposal[]\x82\xF0\x8F\x91\x82\xAB\x8A\xB7\x82\xA6\x82\xE9\x81B(2005.7.9 yutaka)
+	buf[0] = '\0';
+	for (i = 0 ; pvar->settings.CompOrder[i] != 0 ; i++) {
+		index = pvar->settings.CompOrder[i] - '0';
+		if (index == COMP_NONE) // disabled line
+			break;
+		strncat_s(buf, sizeof(buf), get_ssh2_comp_name(index), _TRUNCATE);
+		strncat_s(buf, sizeof(buf), ",", _TRUNCATE);
+	}
+	len = strlen(buf);
+	if (len > 0)
+		buf[len - 1] = '\0';  // get rid of comma
+
+	// \x88\xB3\x8Fk\x8Ew\x92肪\x82Ȃ\xA2\x8Fꍇ\x82́A\x88\xB3\x8Fk\x83\x8C\x83x\x83\x8B\x82𖳏\xF0\x8C\x8F\x82Ƀ[\x83\x8D\x82ɂ\xB7\x82\xE9\x81B
+	if (buf[0] == '\0') {
+		pvar->settings.CompressionLevel = 0;
+	}
+
+	if (pvar->settings.CompressionLevel == 0) {
+		_snprintf_s(buf, sizeof(buf), _TRUNCATE, get_ssh2_comp_name(COMP_NOCOMP));
+	}
+	if (buf[0] != '\0') {
+		myproposal[PROPOSAL_COMP_ALGS_CTOS] = buf;  // Client To Server
+		myproposal[PROPOSAL_COMP_ALGS_STOC] = buf;  // Server To Client
+	}
+}

Copied: branches/4-stable/ttssh2/ttxssh/comp.h (from rev 9252, branches/ssh_chacha20poly1305/ttssh2/ttxssh/comp.h)
===================================================================
--- branches/4-stable/ttssh2/ttxssh/comp.h	                        (rev 0)
+++ branches/4-stable/ttssh2/ttxssh/comp.h	2021-05-19 14:11:12 UTC (rev 9254)
@@ -0,0 +1,49 @@
+/*
+ * (C) 2021- TeraTerm Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SSHCOMP_H
+#define SSHCOMP_H
+
+#include "ttxssh.h"
+
+typedef enum {
+	COMP_NONE,      /* disabled line */
+	COMP_NOCOMP,
+	COMP_ZLIB,
+	COMP_DELAYED,
+	COMP_UNKNOWN,
+	COMP_MAX = COMP_UNKNOWN,
+} compression_type;
+
+char* get_ssh2_comp_name(compression_type type);
+
+void normalize_comp_order(char *buf);
+compression_type choose_SSH2_compression_algorithm(char *server_proposal, char *my_proposal);
+void SSH2_update_compression_myproposal(PTInstVar pvar);
+
+#endif /* SSHCOMP_H */

Modified: branches/4-stable/ttssh2/ttxssh/crypt.c
===================================================================
--- branches/4-stable/ttssh2/ttxssh/crypt.c	2021-05-19 14:05:07 UTC (rev 9253)
+++ branches/4-stable/ttssh2/ttxssh/crypt.c	2021-05-19 14:11:12 UTC (rev 9254)
@@ -75,8 +75,6 @@
 static unsigned char *encbuff = NULL;
 static unsigned int encbufflen = 0;
 
-static char *get_cipher_name(int cipher);
-
 static void crc_update(uint32 *a, uint32 b)
 {
 	b ^= *a;
@@ -206,7 +204,8 @@
 	unsigned int block_size = pvar->ssh2_keys[MODE_OUT].enc.block_size;
 	unsigned char lastiv[1];
 	char tmp[80];
-	EVP_CIPHER_CTX *evp = pvar->evpcip[MODE_OUT];
+	struct sshcipher_ctx *cc = pvar->cc[MODE_OUT];
+	unsigned int newbuff_len = bytes;
 
 	if (bytes == 0)
 		return TRUE;
@@ -220,28 +219,44 @@
 		return FALSE;
 	}
 
-	if (bytes > encbufflen) {
-		if ((newbuff = realloc(encbuff, bytes)) == NULL)
+	if (cc->cipher->id == SSH2_CIPHER_CHACHAPOLY) {
+		// chacha20-poly1305 \x82ł\xCD aadlen \x82\xE0\x88Í\x86\x89\xBB\x82̑Ώ\xDB
+		//   aadlen \x82\xC6 bytes \x82͕ʁX\x82ɈÍ\x86\x89\xBB\x82\xB3\x82\xEA\x82\xE9
+		// chachapoly_crypt \x82̒\x86\x82ŔF\x8F؃f\x81[\x83^(AEAD tag)\x82\xE0\x90\xB6\x90\xAC\x82\xB3\x82\xEA\x82\xE9
+		newbuff_len += aadlen + authlen;
+	}
+	if (newbuff_len > encbufflen) {
+		if ((newbuff = realloc(encbuff, newbuff_len)) == NULL)
 			goto err;
 		encbuff = newbuff;
-		encbufflen = bytes;
+		encbufflen = newbuff_len;
 	}
 
-	if (!EVP_CIPHER_CTX_ctrl(evp, EVP_CTRL_GCM_IV_GEN, 1, lastiv))
+	if (cc->cipher->id == SSH2_CIPHER_CHACHAPOLY) {
+		if (chachapoly_crypt(cc->cp_ctx, pvar->ssh_state.sender_sequence_number,
+		                     encbuff, data, bytes, aadlen, authlen, 1) != 0) {
+			goto err;
+		}
+		memcpy(data, encbuff, aadlen + bytes + authlen);
+		return TRUE;
+	}
+
+	if (!EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_IV_GEN, 1, lastiv))
 		goto err;
 
-	if (aadlen && !EVP_Cipher(evp, NULL, data, aadlen) < 0)
+	if (aadlen && !EVP_Cipher(cc->evp, NULL, data, aadlen) < 0)
 		goto err;
 
-	if (EVP_Cipher(evp, encbuff, data+aadlen, bytes) < 0)
+	// AES-GCM \x82ł\xCD aadlen \x82\xF0\x88Í\x86\x89\xBB\x82\xB5\x82Ȃ\xA2\x82̂ŁA\x82\xBB\x82̐悾\x82\xAF\x88Í\x86\x89\xBB\x82\xB7\x82\xE9
+	if (EVP_Cipher(cc->evp, encbuff, data+aadlen, bytes) < 0)
 		goto err;
 
 	memcpy(data+aadlen, encbuff, bytes);
 
-	if (EVP_Cipher(evp, NULL, NULL, 0) < 0)
+	if (EVP_Cipher(cc->evp, NULL, NULL, 0) < 0)
 		goto err;
 
-	if (!EVP_CIPHER_CTX_ctrl(evp, EVP_CTRL_GCM_GET_TAG, authlen, data+aadlen+bytes))
+	if (!EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_GET_TAG, authlen, data+aadlen+bytes))
 		goto err;
 
 	return TRUE;
@@ -260,7 +275,8 @@
 	unsigned int block_size = pvar->ssh2_keys[MODE_IN].enc.block_size;
 	unsigned char lastiv[1];
 	char tmp[80];
-	EVP_CIPHER_CTX *evp = pvar->evpcip[MODE_IN];
+	struct sshcipher_ctx *cc = pvar->cc[MODE_IN];
+	unsigned int newbuff_len = bytes;
 
 	if (bytes == 0)
 		return TRUE;
@@ -274,32 +290,46 @@
 		return FALSE;
 	}
 
-	if (bytes > encbufflen) {
-		if ((newbuff = realloc(encbuff, bytes)) == NULL)
+	if (cc->cipher->id == SSH2_CIPHER_CHACHAPOLY) {
+		// chacha20-poly1305 \x82ł\xCD aadlen \x82\xE0\x88Í\x86\x89\xBB\x82\xB3\x82\xEA\x82Ă\xA2\x82\xE9
+		newbuff_len += aadlen;
+	}
+	if (newbuff_len > encbufflen) {
+		if ((newbuff = realloc(encbuff, newbuff_len)) == NULL)
 			goto err;
 		encbuff = newbuff;
-		encbufflen = bytes;
+		encbufflen = newbuff_len;
 	}
 
-	if (!EVP_CIPHER_CTX_ctrl(evp, EVP_CTRL_GCM_IV_GEN, 1, lastiv))
+	if (cc->cipher->id == SSH2_CIPHER_CHACHAPOLY) {
+		if (chachapoly_crypt(cc->cp_ctx, pvar->ssh_state.receiver_sequence_number,
+		                     encbuff, data, bytes, aadlen, authlen, 0) != 0) {
+			goto err;
+		}
+		memcpy(data, encbuff, aadlen + bytes);
+		return TRUE;
+	}
+
+	if (!EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_IV_GEN, 1, lastiv))
 		goto err;
 
-	if (!EVP_CIPHER_CTX_ctrl(evp, EVP_CTRL_GCM_SET_TAG, authlen, data+aadlen+bytes))
+	if (!EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_SET_TAG, authlen, data+aadlen+bytes))
 		goto err;
 
-	if (aadlen && !EVP_Cipher(evp, NULL, data, aadlen) < 0)
+	if (aadlen && !EVP_Cipher(cc->evp, NULL, data, aadlen) < 0)
 		goto err;
 
-	if (EVP_Cipher(evp, encbuff, data+aadlen, bytes) < 0)
+	// AES-GCM \x82ł\xCD aadlen \x82\xF0\x88Í\x86\x89\xBB\x82\xB5\x82Ȃ\xA2\x82̂ŁA\x82\xBB\x82̐悾\x82\xAF\x95\x9C\x8D\x86\x82\xB7\x82\xE9
+	if (EVP_Cipher(cc->evp, encbuff, data+aadlen, bytes) < 0)
 		goto err;
 
 	memcpy(data+aadlen, encbuff, bytes);
 
-	if (EVP_Cipher(evp, NULL, NULL, 0) < 0)
-		return FALSE;
-	else
-		return TRUE;
+	if (EVP_Cipher(cc->evp, NULL, NULL, 0) < 0)
+		goto err;
 
+	return TRUE;
+
 err:
 	UTIL_get_lang_msg("MSG_DECRYPT_ERROR2", pvar, "%s decrypt error(2)");
 	_snprintf_s(tmp, sizeof(tmp), _TRUNCATE, pvar->ts->UIMsg,
@@ -338,7 +368,7 @@
 		encbufflen = bytes;
 	}
 
-	if (EVP_Cipher(pvar->evpcip[MODE_OUT], encbuff, buf, bytes) == 0) {
+	if (EVP_Cipher(pvar->cc[MODE_OUT]->evp, encbuff, buf, bytes) == 0) {
 		UTIL_get_lang_msg("MSG_ENCRYPT_ERROR2", pvar, "%s encrypt error(2)");
 		_snprintf_s(tmp, sizeof(tmp), _TRUNCATE, pvar->ts->UIMsg,
 		            get_cipher_name(pvar->crypt_state.sender_cipher));
@@ -374,7 +404,7 @@
 		encbufflen = bytes;
 	}
 
-	if (EVP_Cipher(pvar->evpcip[MODE_IN], encbuff, buf, bytes) == 0) {
+	if (EVP_Cipher(pvar->cc[MODE_IN]->evp, encbuff, buf, bytes) == 0) {
 		UTIL_get_lang_msg("MSG_DECRYPT_ERROR2", pvar, "%s decrypt error(2)");
 		_snprintf_s(tmp, sizeof(tmp), _TRUNCATE, pvar->ts->UIMsg,
 		            get_cipher_name(pvar->crypt_state.receiver_cipher));
@@ -489,8 +519,8 @@
 
 // make_key()\x82\xF0 fingerprint \x90\xB6\x90\xAC\x82ł\xE0\x97\x98\x97p\x82\xB7\x82\xE9\x82̂ŁAstatic\x82\xF0\x8D폜\x81B(2006.3.27 yutaka)
 RSA *make_key(PTInstVar pvar,
-                  int bits, unsigned char *exp,
-                  unsigned char *mod)
+              int bits, unsigned char *exp,
+              unsigned char *mod)
 {
 	RSA *key = RSA_new();
 	BIGNUM *e = NULL, *n = NULL;
@@ -595,6 +625,7 @@
 		            | (1 << SSH2_CIPHER_CAMELLIA256_CTR)
 		            | (1 << SSH2_CIPHER_AES128_GCM)
 		            | (1 << SSH2_CIPHER_AES256_GCM)
+		            | (1 << SSH2_CIPHER_CHACHAPOLY)
 		);
 	}
 
@@ -665,7 +696,7 @@
 // \x81\xA6\x96{\x8A֐\x94\x82\xCD SSH2 \x82ł̂ݎg\x97p\x82\xB3\x82\xEA\x82\xE9\x81B
 // (2004.12.17 yutaka)
 BOOL CRYPT_verify_receiver_MAC(PTInstVar pvar, uint32 sequence_number,
-	char *data, int len, char *MAC)
+                               char *data, int len, char *MAC)
 {
 	HMAC_CTX *c = NULL;
 	unsigned char m[EVP_MAX_MD_SIZE];
@@ -685,7 +716,7 @@
 
 	if ((u_int)mac->mac_len > sizeof(m)) {
 		logprintf(LOG_LEVEL_VERBOSE, "HMAC len(%d) is larger than %d bytes(seq %lu len %d)", 
-			mac->mac_len, sizeof(m), sequence_number, len);
+		          mac->mac_len, sizeof(m), sequence_number, len);
 		goto error;
 	}
 
@@ -802,13 +833,13 @@
 			pvar->crypt_state.sender_cipher = SSH_CIPHER_NONE;
 		}
 		else {
-			pvar->crypt_state.sender_cipher = pvar->ciphers[MODE_OUT]->id;
+			pvar->crypt_state.sender_cipher = get_cipher_id(pvar->ciphers[MODE_OUT]);
 		}
 		if (pvar->ciphers[MODE_IN] == NULL) {
 			pvar->crypt_state.receiver_cipher = SSH_CIPHER_NONE;
 		}
 		else {
-			pvar->crypt_state.receiver_cipher = pvar->ciphers[MODE_IN]->id;
+			pvar->crypt_state.receiver_cipher = get_cipher_id(pvar->ciphers[MODE_IN]);
 		}
 	}
 
@@ -1003,7 +1034,7 @@
 		       SSH_RSA_CHALLENGE_LENGTH, SSH_RSA_CHALLENGE_LENGTH);
 	} else {
 		SecureZeroMemory(decrypted_challenge,
-		       SSH_RSA_CHALLENGE_LENGTH - decrypted_challenge_len);
+		                 SSH_RSA_CHALLENGE_LENGTH - decrypted_challenge_len);
 		memcpy(decrypted_challenge + SSH_RSA_CHALLENGE_LENGTH -
 		       decrypted_challenge_len, challenge,
 		       decrypted_challenge_len);
@@ -1046,98 +1077,12 @@
 	SecureZeroMemory(state->ivec, 8);
 }
 
-
-//
-// SSH2\x97p\x83A\x83\x8B\x83S\x83\x8A\x83Y\x83\x80\x82̏\x89\x8A\xFA\x89\xBB
-//
-void cipher_init_SSH2(EVP_CIPHER_CTX *evp,
-                      const u_char *key, u_int keylen,
-                      const u_char *iv, u_int ivlen,
-                      int encrypt,
-                      const EVP_CIPHER *type,
-                      int discard_len,
-                      unsigned int authlen,
-                      PTInstVar pvar)
-{
-	int klen;
-	char tmp[80];
-	unsigned char *junk = NULL, *discard = NULL;
-
-	EVP_CIPHER_CTX_init(evp);
-	if (EVP_CipherInit(evp, type, NULL, NULL, (encrypt == CIPHER_ENCRYPT)) == 0) {
-		UTIL_get_lang_msg("MSG_CIPHER_INIT_ERROR", pvar, "Cipher initialize error(%d)");
-		_snprintf_s(tmp, sizeof(tmp), _TRUNCATE, pvar->ts->UIMsg, 1);
-		notify_fatal_error(pvar, tmp, TRUE);
-		return;
-	}
-
-	if (authlen > 0 && !EVP_CIPHER_CTX_ctrl(evp, EVP_CTRL_GCM_SET_IVLEN, ivlen, NULL)) {
-		UTIL_get_lang_msg("MSG_CIPHER_INIT_ERROR", pvar, "Cipher initialize error(%d)");
-		_snprintf_s(tmp, sizeof(tmp), _TRUNCATE, pvar->ts->UIMsg, 2);
-		notify_fatal_error(pvar, tmp, TRUE);
-		return;
-	}
-	if (EVP_CipherInit(evp, NULL, NULL, (u_char *)iv, -1) == 0) {
-		UTIL_get_lang_msg("MSG_CIPHER_INIT_ERROR", pvar, "Cipher initialize error(%d)");
-		_snprintf_s(tmp, sizeof(tmp), _TRUNCATE, pvar->ts->UIMsg, 3);
-		notify_fatal_error(pvar, tmp, TRUE);
-		return;
-	}
-	if (authlen > 0 && !EVP_CIPHER_CTX_ctrl(evp, EVP_CTRL_GCM_SET_IV_FIXED, -1, (u_char *)iv)) {
-		UTIL_get_lang_msg("MSG_CIPHER_INIT_ERROR", pvar, "Cipher initialize error(%d)");
-		_snprintf_s(tmp, sizeof(tmp), _TRUNCATE, pvar->ts->UIMsg, 4);
-		notify_fatal_error(pvar, tmp, TRUE);
-		return;
-	}
-
-	klen = EVP_CIPHER_CTX_key_length(evp);
-	if (klen > 0 && keylen != klen) {
-		if (EVP_CIPHER_CTX_set_key_length(evp, keylen) == 0) {
-			UTIL_get_lang_msg("MSG_CIPHER_INIT_ERROR", pvar, "Cipher initialize error(%d)");
-			_snprintf_s(tmp, sizeof(tmp), _TRUNCATE, pvar->ts->UIMsg, 5);
-			notify_fatal_error(pvar, tmp, TRUE);
-			return;
-		}
-	}
-	if (EVP_CipherInit(evp, NULL, (u_char *)key, NULL, -1) == 0) {
-		UTIL_get_lang_msg("MSG_CIPHER_INIT_ERROR", pvar, "Cipher initialize error(%d)");
-		_snprintf_s(tmp, sizeof(tmp), _TRUNCATE, pvar->ts->UIMsg, 6);
-		notify_fatal_error(pvar, tmp, TRUE);
-		return;
-	}
-
-	if (discard_len > 0) {
-		junk = malloc(discard_len);
-		discard = malloc(discard_len);
-		if (junk == NULL || discard == NULL ||
-		    EVP_Cipher(evp, discard, junk, discard_len) == 0) {
-			UTIL_get_lang_msg("MSG_CIPHER_INIT_ERROR", pvar, "Cipher initialize error(%d)");
-			_snprintf_s(tmp, sizeof(tmp), _TRUNCATE, pvar->ts->UIMsg, 7);
-			notify_fatal_error(pvar, tmp, TRUE);
-		}
-		else {
-			SecureZeroMemory(discard, discard_len);
-		}
-		free(junk);
-		free(discard);
-	}
-}
-
-//
-// SSH2\x97p\x83A\x83\x8B\x83S\x83\x8A\x83Y\x83\x80\x82̔j\x8A\xFC
-//
-void cipher_cleanup_SSH2(EVP_CIPHER_CTX *evp)
-{
-	EVP_CIPHER_CTX_cleanup(evp);
-}
-
-
 BOOL CRYPT_start_encryption(PTInstVar pvar, int sender_flag, int receiver_flag)
 {
 	struct Enc *enc;
 	char *encryption_key = pvar->crypt_state.sender_cipher_key;
 	char *decryption_key = pvar->crypt_state.receiver_cipher_key;
-	SSH2Cipher *cipher;
+	const struct ssh2cipher *cipher;
 	BOOL isOK = TRUE;
 
 	if (sender_flag) {
@@ -1171,15 +1116,11 @@
 			cipher = pvar->ciphers[MODE_OUT];
 			if (cipher) {
 				enc = &pvar->ssh2_keys[MODE_OUT].enc;
-				cipher_init_SSH2(pvar->evpcip[MODE_OUT],
-				                 enc->key, get_cipher_key_len(cipher),
-				                 enc->iv, get_cipher_iv_len(cipher),
+				cipher_init_SSH2(&pvar->cc[MODE_OUT], cipher,
+				                 enc->key, enc->key_len,
+				                 enc->iv, enc->iv_len,
 				                 CIPHER_ENCRYPT,
-				                 get_cipher_EVP_CIPHER(cipher),
-				                 get_cipher_discard_len(cipher),
-				                 get_cipher_auth_len(cipher),
 				                 pvar);
-
 				pvar->crypt_state.encrypt = crypt_SSH2_encrypt;
 			}
 			else {
@@ -1219,15 +1160,11 @@
 			cipher = pvar->ciphers[MODE_IN];
 			if (cipher) {
 				enc = &pvar->ssh2_keys[MODE_IN].enc;
-				cipher_init_SSH2(pvar->evpcip[MODE_IN],
-				                 enc->key, get_cipher_key_len(cipher),
-				                 enc->iv, get_cipher_iv_len(cipher),
+				cipher_init_SSH2(&pvar->cc[MODE_IN], cipher,
+				                 enc->key, enc->key_len,
+				                 enc->iv, enc->iv_len,
 				                 CIPHER_DECRYPT,
-				                 get_cipher_EVP_CIPHER(cipher),
-				                 get_cipher_discard_len(cipher),
-				                 get_cipher_auth_len(cipher),
 				                 pvar);
-
 				pvar->crypt_state.decrypt = crypt_SSH2_decrypt;
 			}
 			else {
@@ -1262,71 +1199,6 @@
 		HASH_MINSIZE / HASH_ENTRYSIZE;
 }
 
-static char *get_cipher_name(int cipher)
-{
-	switch (cipher) {
-	case SSH_CIPHER_NONE:
-		return "None";
-	case SSH_CIPHER_3DES:
-		return "3DES (168 key bits)";
-	case SSH_CIPHER_DES:
-		return "DES (56 key bits)";
-	case SSH_CIPHER_BLOWFISH:
-		return "Blowfish (256 key bits)";
-
-	// SSH2 
-	case SSH2_CIPHER_3DES_CBC:
-		return "3des-cbc";
-	case SSH2_CIPHER_AES128_CBC:
-		return "aes128-cbc";
-	case SSH2_CIPHER_AES192_CBC:
-		return "aes192-cbc";
-	case SSH2_CIPHER_AES256_CBC:
-		return "aes256-cbc";
-	case SSH2_CIPHER_BLOWFISH_CBC:
-		return "blowfish-cbc";
-	case SSH2_CIPHER_AES128_CTR:
-		return "aes128-ctr";
-	case SSH2_CIPHER_AES192_CTR:
-		return "aes192-ctr";
-	case SSH2_CIPHER_AES256_CTR:
-		return "aes256-ctr";
-	case SSH2_CIPHER_ARCFOUR:
-		return "arcfour";
-	case SSH2_CIPHER_ARCFOUR128:
-		return "arcfour128";
-	case SSH2_CIPHER_ARCFOUR256:
-		return "arcfour256";
-	case SSH2_CIPHER_CAST128_CBC:
-		return "cast-128-cbc";
-	case SSH2_CIPHER_3DES_CTR:
-		return "3des-ctr";
-	case SSH2_CIPHER_BLOWFISH_CTR:
-		return "blowfish-ctr";
-	case SSH2_CIPHER_CAST128_CTR:
-		return "cast-128-ctr";
-	case SSH2_CIPHER_CAMELLIA128_CBC:
-		return "camellia128-cbc";
-	case SSH2_CIPHER_CAMELLIA192_CBC:
-		return "camellia192-cbc";
-	case SSH2_CIPHER_CAMELLIA256_CBC:
-		return "camellia256-cbc";
-	case SSH2_CIPHER_CAMELLIA128_CTR:
-		return "camellia128-ctr";
-	case SSH2_CIPHER_CAMELLIA192_CTR:
-		return "camellia192-ctr";
-	case SSH2_CIPHER_CAMELLIA256_CTR:
-		return "camellia256-ctr";
-	case SSH2_CIPHER_AES128_GCM:
-		return "aes12****@opens*****";
-	case SSH2_CIPHER_AES256_GCM:
-		return "aes25****@opens*****";
-
-	default:
-		return "Unknown";
-	}
-}
-
 void CRYPT_get_cipher_info(PTInstVar pvar, char *dest, int len)
 {
 	UTIL_get_lang_msg("DLG_ABOUT_CIPHER_INFO", pvar,
@@ -1392,18 +1264,18 @@
 
 	if (pvar->crypt_state.detect_attack_statics.h != NULL) {
 		SecureZeroMemory(pvar->crypt_state.detect_attack_statics.h, 
-		       pvar->crypt_state.detect_attack_statics.n * HASH_ENTRYSIZE);
+		                 pvar->crypt_state.detect_attack_statics.n * HASH_ENTRYSIZE);
 		free(pvar->crypt_state.detect_attack_statics.h);
 	}
 
 	SecureZeroMemory(pvar->crypt_state.sender_cipher_key,
-	       sizeof(pvar->crypt_state.sender_cipher_key));
+	                 sizeof(pvar->crypt_state.sender_cipher_key));
 	SecureZeroMemory(pvar->crypt_state.receiver_cipher_key, 
-	       sizeof(pvar->crypt_state.receiver_cipher_key));
+	                 sizeof(pvar->crypt_state.receiver_cipher_key));
 	SecureZeroMemory(pvar->crypt_state.server_cookie, 
-	       sizeof(pvar->crypt_state.server_cookie));
+	                 sizeof(pvar->crypt_state.server_cookie));
 	SecureZeroMemory(pvar->crypt_state.client_cookie, 
-	       sizeof(pvar->crypt_state.client_cookie));
+	                 sizeof(pvar->crypt_state.client_cookie));
 	SecureZeroMemory(&pvar->crypt_state.enc, sizeof(pvar->crypt_state.enc));
 	SecureZeroMemory(&pvar->crypt_state.dec, sizeof(pvar->crypt_state.dec));
 }
@@ -1453,7 +1325,7 @@
 			SecureZeroMemory(state.ivec, 8);
 			flip_endianness(buf, bytes);
 			BF_cbc_encrypt(buf, buf, bytes, &state.k, state.ivec,
-						   BF_DECRYPT);
+			               BF_DECRYPT);
 			flip_endianness(buf, bytes);
 			break;
 		}

Copied: branches/4-stable/ttssh2/ttxssh/hostkey.c (from rev 9252, branches/ssh_chacha20poly1305/ttssh2/ttxssh/hostkey.c)
===================================================================
--- branches/4-stable/ttssh2/ttxssh/hostkey.c	                        (rev 0)
+++ branches/4-stable/ttssh2/ttxssh/hostkey.c	2021-05-19 14:11:12 UTC (rev 9254)
@@ -0,0 +1,186 @@
+/*
+ * (C) 2021- TeraTerm Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ttxssh.h"
+#include "hostkey.h"
+#include "kex.h"
+
+
+struct ssh2_host_key_t {
+	ssh_keytype type;
+	char *name;
+};
+
+static const struct ssh2_host_key_t ssh2_host_key[] = {
+	{KEY_RSA1,     "ssh-rsa1"},            // for SSH1 only
+	{KEY_RSA,      "ssh-rsa"},             // RFC4253
+	{KEY_DSA,      "ssh-dss"},             // RFC4253
+	{KEY_ECDSA256, "ecdsa-sha2-nistp256"}, // RFC5656
+	{KEY_ECDSA384, "ecdsa-sha2-nistp384"}, // RFC5656
+	{KEY_ECDSA521, "ecdsa-sha2-nistp521"}, // RFC5656
+	{KEY_ED25519,  "ssh-ed25519"},         // draft-bjh21-ssh-ed25519-02
+	{KEY_UNSPEC,   "ssh-unknown"},
+	{KEY_NONE,     NULL},
+};
+
+struct ssh_digest_t {
+	digest_algorithm id;
+	char *name;
+};
+
+/* NB. Indexed directly by algorithm number */
+static const struct ssh_digest_t ssh_digests[] = {
+	{ SSH_DIGEST_MD5,       "MD5" },
+	{ SSH_DIGEST_RIPEMD160, "RIPEMD160" },
+	{ SSH_DIGEST_SHA1,      "SHA1" },
+	{ SSH_DIGEST_SHA256,    "SHA256" },
+	{ SSH_DIGEST_SHA384,    "SHA384" },
+	{ SSH_DIGEST_SHA512,    "SHA512" },
+	{ SSH_DIGEST_MAX,       NULL },
+};
+
+
+ssh_keytype get_hostkey_type_from_name(char *name)
+{
+	if (strcmp(name, "rsa1") == 0) {
+		return KEY_RSA1;
+	} else if (strcmp(name, "rsa") == 0) {
+		return KEY_RSA;
+	} else if (strcmp(name, "dsa") == 0) {
+		return KEY_DSA;
+	} else if (strcmp(name, "ssh-rsa") == 0) {
+		return KEY_RSA;
+	} else if (strcmp(name, "ssh-dss") == 0) {
+		return KEY_DSA;
+	} else if (strcmp(name, "ecdsa-sha2-nistp256") == 0) {
+		return KEY_ECDSA256;
+	} else if (strcmp(name, "ecdsa-sha2-nistp384") == 0) {
+		return KEY_ECDSA384;
+	} else if (strcmp(name, "ecdsa-sha2-nistp521") == 0) {
+		return KEY_ECDSA521;
+	} else if (strcmp(name, "ssh-ed25519") == 0) {
+		return KEY_ED25519;
+	}
+	return KEY_UNSPEC;
+}
+
+char* get_ssh2_hostkey_type_name(ssh_keytype type)
+{
+	const struct ssh2_host_key_t *ptr = ssh2_host_key;
+
+	while (ptr->name != NULL) {
+		if (type == ptr->type) {
+			return ptr->name;
+		}
+		ptr++;
+	}
+
+	// not found.
+	return "ssh-unknown";
+}
+
+char *get_ssh2_hostkey_type_name_from_key(Key *key)
+{
+	return get_ssh2_hostkey_type_name(key->type);
+}
+
+char* get_digest_algorithm_name(digest_algorithm id)
+{
+	const struct ssh_digest_t *ptr = ssh_digests;
+
+	while (ptr->name != NULL) {
+		if (id == ptr->id) {
+			return ptr->name;
+		}
+		ptr++;
+	}
+
+	// not found.
+	return "unknown";
+}
+
+void normalize_host_key_order(char *buf)
+{
+	static char default_strings[] = {
+		KEY_ECDSA256,
+		KEY_ECDSA384,
+		KEY_ECDSA521,
+		KEY_ED25519,
+		KEY_RSA,
+		KEY_DSA,
+		KEY_NONE,
+	};
+
+	normalize_generic_order(buf, default_strings, NUM_ELEM(default_strings));
+}
+
+ssh_keytype choose_SSH2_host_key_algorithm(char *server_proposal, char *my_proposal)
+{
+	ssh_keytype type = KEY_UNSPEC;
+	char str_keytype[20];
+	const struct ssh2_host_key_t *ptr = ssh2_host_key;
+
+	choose_SSH2_proposal(server_proposal, my_proposal, str_keytype, sizeof(str_keytype));
+
+	while (ptr->name != NULL) {
+		if (strcmp(ptr->name, str_keytype) == 0) {
+			type = ptr->type;
+			break;
+		}
+		ptr++;
+	}
+
+	return (type);
+}
+
+// Host Key\x83A\x83\x8B\x83S\x83\x8A\x83Y\x83\x80\x97D\x90揇\x88ʂɉ\x9E\x82\xB6\x82āAmyproposal[]\x82\xF0\x8F\x91\x82\xAB\x8A\xB7\x82\xA6\x82\xE9\x81B
+// (2011.2.28 yutaka)
+void SSH2_update_host_key_myproposal(PTInstVar pvar)
+{
+	static char buf[256]; // TODO: malloc()\x82ɂ\xB7\x82ׂ\xAB
+	int index;
+	int len, i;
+
+	// \x92ʐM\x92\x86\x82ɂ͌Ă΂\xEA\x82Ȃ\xA2\x82͂\xB8\x82\xBE\x82\xAA\x81A\x94O\x82̂\xBD\x82߁B(2006.6.26 maya)
+	if (pvar->socket != INVALID_SOCKET) {
+		return;
+	}
+
+	buf[0] = '\0';
+	for (i = 0 ; pvar->settings.HostKeyOrder[i] != 0 ; i++) {
+		index = pvar->settings.HostKeyOrder[i] - '0';
+		if (index == KEY_NONE) // disabled line
+			break;
+		strncat_s(buf, sizeof(buf), get_ssh2_hostkey_type_name(index), _TRUNCATE);
+		strncat_s(buf, sizeof(buf), ",", _TRUNCATE);
+	}
+	len = strlen(buf);
+	if (len > 0)
+		buf[len - 1] = '\0';  // get rid of comma
+	myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = buf; 
+}

Copied: branches/4-stable/ttssh2/ttxssh/hostkey.h (from rev 9252, branches/ssh_chacha20poly1305/ttssh2/ttxssh/hostkey.h)
===================================================================
--- branches/4-stable/ttssh2/ttxssh/hostkey.h	                        (rev 0)
+++ branches/4-stable/ttssh2/ttxssh/hostkey.h	2021-05-19 14:11:12 UTC (rev 9254)
@@ -0,0 +1,85 @@
+/*
+ * (C) 2021- TeraTerm Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef HOSTKEY_H
+#define HOSTKEY_H
+
+typedef struct Key Key;
+
+typedef enum {
+	KEY_NONE,
+	KEY_RSA1,
+	KEY_RSA,
+	KEY_DSA,
+	KEY_ECDSA256,
+	KEY_ECDSA384,
+	KEY_ECDSA521,
+	KEY_ED25519,
+	KEY_UNSPEC,
+	KEY_MAX = KEY_UNSPEC,
+} ssh_keytype;
+#define isFixedLengthKey(type)	((type) >= KEY_DSA && (type) <= KEY_ED25519)
+
+// fingerprint\x82̎\xED\x95\xCA
+typedef enum {
+	SSH_FP_DEFAULT = 0,
+	SSH_FP_HEX,
+	SSH_FP_BASE64,
+	SSH_FP_BUBBLEBABBLE,
+	SSH_FP_RANDOMART
+} fp_rep;
+
+/*
+enum fp_type {
+	SSH_FP_MD5,
+	SSH_FP_SHA1,
+	SSH_FP_SHA256
+};
+*/
+
+typedef enum {
+	SSH_DIGEST_MD5,
+	SSH_DIGEST_RIPEMD160,
+	SSH_DIGEST_SHA1,
+	SSH_DIGEST_SHA256,
+	SSH_DIGEST_SHA384,
+	SSH_DIGEST_SHA512,
+	SSH_DIGEST_MAX,
+} digest_algorithm;
+
+
+ssh_keytype get_hostkey_type_from_name(char *name);
+char* get_ssh2_hostkey_type_name(ssh_keytype type);
+char *get_ssh2_hostkey_type_name_from_key(Key *key);
+char* get_digest_algorithm_name(digest_algorithm id);
+
+void normalize_host_key_order(char *buf);
+ssh_keytype choose_SSH2_host_key_algorithm(char *server_proposal, char *my_proposal);
+void SSH2_update_host_key_myproposal(PTInstVar pvar);
+
+#endif /* SSHCMAC_H */

Modified: branches/4-stable/ttssh2/ttxssh/hosts.c
===================================================================
--- branches/4-stable/ttssh2/ttxssh/hosts.c	2021-05-19 14:05:07 UTC (rev 9253)
+++ branches/4-stable/ttssh2/ttxssh/hosts.c	2021-05-19 14:11:12 UTC (rev 9254)
@@ -485,7 +485,7 @@
 			}
 			index += (p - cp);  // setup index
 			*p = '\0';
-			key_type = get_keytype_from_name(cp);
+			key_type = get_hostkey_type_from_name(cp);
 			*p = ' ';
 
 			index += eat_spaces(data + index);  // update index
@@ -763,7 +763,7 @@
 			}
 			index += (p - cp);  // setup index
 			*p = '\0';
-			ktype = get_keytype_from_name(cp);
+			ktype = get_hostkey_type_from_name(cp);
 			*p = ' ';
 
 			index += eat_spaces(data + index);  // update index
@@ -1117,13 +1117,13 @@
 			if (pvar->ssh_state.tcpport == 22) {
 				_snprintf_s(result, msize, _TRUNCATE, "%s %s %s\r\n",
 				            pvar->hosts_state.prefetched_hostname, 
-				            get_sshname_from_key(key),
+				            get_ssh2_hostkey_type_name_from_key(key),
 				            uu);
 			} else {
 				_snprintf_s(result, msize, _TRUNCATE, "[%s]:%d %s %s\r\n",
 				            pvar->hosts_state.prefetched_hostname,
 				            pvar->ssh_state.tcpport,
-				            get_sshname_from_key(key),
+				            get_ssh2_hostkey_type_name_from_key(key),
 				            uu);
 			}
 		}
@@ -1213,7 +1213,7 @@
 			if (tcpport == 22) {
 				_snprintf_s(result, msize, _TRUNCATE, "%s %s %s\r\n",
 					hostname,
-					get_sshname_from_key(key),
+					get_ssh2_hostkey_type_name_from_key(key),
 					uu);
 			}
 			else {
@@ -1220,7 +1220,7 @@
 				_snprintf_s(result, msize, _TRUNCATE, "[%s]:%d %s %s\r\n",
 					hostname,
 					tcpport,
-					get_sshname_from_key(key),
+					get_ssh2_hostkey_type_name_from_key(key),
 					uu);
 			}
 		}

Modified: branches/4-stable/ttssh2/ttxssh/kex.c
===================================================================
--- branches/4-stable/ttssh2/ttxssh/kex.c	2021-05-19 14:05:07 UTC (rev 9253)
+++ branches/4-stable/ttssh2/ttxssh/kex.c	2021-05-19 14:11:12 UTC (rev 9254)
@@ -29,8 +29,140 @@
 #include "ttxssh.h"
 #include "kex.h"
 
+
+char *myproposal[PROPOSAL_MAX] = {
+	KEX_DEFAULT_KEX,
+	KEX_DEFAULT_PK_ALG,
+	KEX_DEFAULT_ENCRYPT,
+	KEX_DEFAULT_ENCRYPT,
+	KEX_DEFAULT_MAC,
+	KEX_DEFAULT_MAC,
+	KEX_DEFAULT_COMP,
+	KEX_DEFAULT_COMP,
+	KEX_DEFAULT_LANG,
+	KEX_DEFAULT_LANG,
+};
+
+struct ssh2_kex_algorithm_t {
+	kex_algorithm kextype;
+	char *name;
+	const EVP_MD *(*evp_md)(void);
+};
+
+static const struct ssh2_kex_algorithm_t ssh2_kex_algorithms[] = {
+	{KEX_DH_GRP1_SHA1,  "diffie-hellman-group1-sha1",           EVP_sha1},   // RFC4253
+	{KEX_DH_GRP14_SHA1, "diffie-hellman-group14-sha1",          EVP_sha1},   // RFC4253
+	{KEX_DH_GEX_SHA1,   "diffie-hellman-group-exchange-sha1",   EVP_sha1},   // RFC4419
+	{KEX_DH_GEX_SHA256, "diffie-hellman-group-exchange-sha256", EVP_sha256}, // RFC4419
+	{KEX_ECDH_SHA2_256, "ecdh-sha2-nistp256",                   EVP_sha256}, // RFC5656
+	{KEX_ECDH_SHA2_384, "ecdh-sha2-nistp384",                   EVP_sha384}, // RFC5656
+	{KEX_ECDH_SHA2_521, "ecdh-sha2-nistp521",                   EVP_sha512}, // RFC5656
+	{KEX_DH_GRP14_SHA256, "diffie-hellman-group14-sha256",      EVP_sha256}, // RFC8268
+	{KEX_DH_GRP16_SHA512, "diffie-hellman-group16-sha512",      EVP_sha512}, // RFC8268
+	{KEX_DH_GRP18_SHA512, "diffie-hellman-group18-sha512",      EVP_sha512}, // RFC8268
+	{KEX_DH_NONE      , NULL,                                   NULL},
+};
+
+
 extern SSHKeys current_keys[MODE_MAX];
 
+
+char* get_kex_algorithm_name(kex_algorithm kextype)
+{
+	const struct ssh2_kex_algorithm_t *ptr = ssh2_kex_algorithms;
+
+	while (ptr->name != NULL) {
+		if (kextype == ptr->kextype) {
+			return ptr->name;
+		}
+		ptr++;
+	}
+
+	// not found.
+	return "unknown";
+}
+
+const EVP_MD* get_kex_algorithm_EVP_MD(kex_algorithm kextype)
+{
+	const struct ssh2_kex_algorithm_t *ptr = ssh2_kex_algorithms;
+
+	while (ptr->name != NULL) {
+		if (kextype == ptr->kextype) {
+			return ptr->evp_md();
+		}
+		ptr++;
+	}
+
+	// not found.
+	return EVP_md_null();
+}
+
+void normalize_kex_order(char *buf)
+{
+	static char default_strings[] = {
+		KEX_ECDH_SHA2_256,
+		KEX_ECDH_SHA2_384,
+		KEX_ECDH_SHA2_521,
+		KEX_DH_GRP18_SHA512,
+		KEX_DH_GRP16_SHA512,
+		KEX_DH_GRP14_SHA256,
+		KEX_DH_GEX_SHA256,
+		KEX_DH_GEX_SHA1,
+		KEX_DH_GRP14_SHA1,
+		KEX_DH_GRP1_SHA1,
+		KEX_DH_NONE,
+	};
+
+	normalize_generic_order(buf, default_strings, NUM_ELEM(default_strings));
+}
+
+kex_algorithm choose_SSH2_kex_algorithm(char *server_proposal, char *my_proposal)
+{
+	kex_algorithm type = KEX_DH_UNKNOWN;
+	char str_kextype[40];
+	const struct ssh2_kex_algorithm_t *ptr = ssh2_kex_algorithms;
+
+	choose_SSH2_proposal(server_proposal, my_proposal, str_kextype, sizeof(str_kextype));
+
+	while (ptr->name != NULL) {
+		if (strcmp(ptr->name, str_kextype) == 0) {
+			type = ptr->kextype;
+			break;
+		}
+		ptr++;
+	}
+
+	return (type);
+}
+
+// KEX\x83A\x83\x8B\x83S\x83\x8A\x83Y\x83\x80\x97D\x90揇\x88ʂɉ\x9E\x82\xB6\x82āAmyproposal[]\x82\xF0\x8F\x91\x82\xAB\x8A\xB7\x82\xA6\x82\xE9\x81B
+// (2011.2.28 yutaka)
+void SSH2_update_kex_myproposal(PTInstVar pvar)
+{
+	static char buf[512]; // TODO: malloc()\x82ɂ\xB7\x82ׂ\xAB
+	int index;
+	int len, i;
+
+	// \x92ʐM\x92\x86\x82ɂ͌Ă΂\xEA\x82Ȃ\xA2\x82͂\xB8\x82\xBE\x82\xAA\x81A\x94O\x82̂\xBD\x82߁B(2006.6.26 maya)
+	if (pvar->socket != INVALID_SOCKET) {
+		return;
+	}
+
+	buf[0] = '\0';
+	for (i = 0 ; pvar->settings.KexOrder[i] != 0 ; i++) {
+		index = pvar->settings.KexOrder[i] - '0';
+		if (index == KEX_DH_NONE) // disabled line
+			break;
+		strncat_s(buf, sizeof(buf), get_kex_algorithm_name(index), _TRUNCATE);
+		strncat_s(buf, sizeof(buf), ",", _TRUNCATE);
+	}
+	len = strlen(buf);
+	if (len > 0)
+		buf[len - 1] = '\0';  // get rid of comma
+	myproposal[PROPOSAL_KEX_ALGS] = buf; 
+}
+
+
 static DH *dh_new_group_asc(const char *gen, const char *modulus)
 {
 	DH *dh = NULL;

Modified: branches/4-stable/ttssh2/ttxssh/kex.h
===================================================================
--- branches/4-stable/ttssh2/ttxssh/kex.h	2021-05-19 14:05:07 UTC (rev 9253)
+++ branches/4-stable/ttssh2/ttxssh/kex.h	2021-05-19 14:11:12 UTC (rev 9254)
@@ -26,8 +26,59 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#ifndef KEX_H
+#define KEX_H
+
 #include "ttxssh.h"
 
+// \x83N\x83\x89\x83C\x83A\x83\x93\x83g\x82\xA9\x82\xE7\x83T\x81[\x83o\x82ւ̒\xF1\x88Ď\x96\x8D\x80
+enum kex_init_proposals {
+	PROPOSAL_KEX_ALGS,
+	PROPOSAL_SERVER_HOST_KEY_ALGS,
+	PROPOSAL_ENC_ALGS_CTOS,
+	PROPOSAL_ENC_ALGS_STOC,
+	PROPOSAL_MAC_ALGS_CTOS,
+	PROPOSAL_MAC_ALGS_STOC,
+	PROPOSAL_COMP_ALGS_CTOS,
+	PROPOSAL_COMP_ALGS_STOC,
+	PROPOSAL_LANG_CTOS,
+	PROPOSAL_LANG_STOC,
+	PROPOSAL_MAX
+};
+
+#define KEX_DEFAULT_KEX     ""
+#define KEX_DEFAULT_PK_ALG  ""
+#define KEX_DEFAULT_ENCRYPT ""
+#define KEX_DEFAULT_MAC     ""
+#define KEX_DEFAULT_COMP    ""
+#define KEX_DEFAULT_LANG    ""
+
+extern char *myproposal[PROPOSAL_MAX];
+
+typedef enum {
+	KEX_DH_NONE,       /* disabled line */
+	KEX_DH_GRP1_SHA1,
+	KEX_DH_GRP14_SHA1,
+	KEX_DH_GEX_SHA1,
+	KEX_DH_GEX_SHA256,
+	KEX_ECDH_SHA2_256,
+	KEX_ECDH_SHA2_384,
+	KEX_ECDH_SHA2_521,
+	KEX_DH_GRP14_SHA256,
+	KEX_DH_GRP16_SHA512,
+	KEX_DH_GRP18_SHA512,
+	KEX_DH_UNKNOWN,
+	KEX_DH_MAX = KEX_DH_UNKNOWN,
+} kex_algorithm;
+
+char* get_kex_algorithm_name(kex_algorithm kextype);
+const EVP_MD* get_kex_algorithm_EVP_MD(kex_algorithm kextype);
+
+void normalize_kex_order(char *buf);
+kex_algorithm choose_SSH2_kex_algorithm(char *server_proposal, char *my_proposal);
+void SSH2_update_kex_myproposal(PTInstVar pvar);
+
+
 // SSH_MSG_KEY_DH_GEX_REQUEST \x82ł\xCC min, n, max \x82\xAA\x82Ƃ蓾\x82\xE9\x94͈͂̏\xE3\x8C\xC0/\x89\xBA\x8C\xC0 (RFC 4419)
 #define GEX_GRP_LIMIT_MIN   1024
 #define GEX_GRP_LIMIT_MAX   8192
@@ -85,3 +136,5 @@
 int dh_pub_is_valid(DH *dh, BIGNUM *dh_pub);
 void kex_derive_keys(PTInstVar pvar, int need, u_char *hash, BIGNUM *shared_secret,
                      char *session_id, int session_id_len);
+
+#endif				/* KEX_H */

Modified: branches/4-stable/ttssh2/ttxssh/key.c
===================================================================
--- branches/4-stable/ttssh2/ttxssh/key.c	2021-05-19 14:05:07 UTC (rev 9253)
+++ branches/4-stable/ttssh2/ttxssh/key.c	2021-05-19 14:11:12 UTC (rev 9254)
@@ -392,7 +392,7 @@
 
 	len = get_uint32_MSBfirst(ptr);
 	ptr += 4;
-	if (strncmp(get_ssh_keytype_name(keytype), ptr, len) != 0) {
+	if (strncmp(get_ssh2_hostkey_type_name(keytype), ptr, len) != 0) {
 		ret = -3;
 		goto error;
 	}
@@ -448,7 +448,7 @@
 }
 
 static int ssh_ed25519_verify(Key *key, unsigned char *signature, unsigned int signaturelen, 
-							  unsigned char *data, unsigned int datalen)
+                              unsigned char *data, unsigned int datalen)
 {
 	buffer_t *b;
 	char *ktype = NULL;
@@ -979,7 +979,7 @@
 //
 // fingerprint\x81i\x8Ew\x96\xE4\x81F\x83z\x83X\x83g\x8C\xF6\x8AJ\x8C\xAE\x82̃n\x83b\x83V\x83\x85\x81j\x82𐶐\xAC\x82\xB7\x82\xE9
 //
-char *key_fingerprint(Key *key, enum fp_rep dgst_rep, digest_algorithm dgst_alg)
+char *key_fingerprint(Key *key, fp_rep dgst_rep, digest_algorithm dgst_alg)
 {
 	char *retval = NULL, *alg;
 	unsigned char *dgst_raw;
@@ -1240,42 +1240,6 @@
 	}
 }
 
-//
-// \x83L\x81[\x82\xA9\x82當\x8E\x9A\x97\xF1\x82\xF0\x95ԋp\x82\xB7\x82\xE9
-//
-char *get_sshname_from_key(Key *key)
-{
-	return get_ssh_keytype_name(key->type);
-}
-
-//
-// \x83L\x81[\x95\xB6\x8E\x9A\x97񂩂\xE7\x8E\xED\x95ʂ𔻒肷\x82\xE9
-//
-ssh_keytype get_keytype_from_name(char *name)
-{
-	if (strcmp(name, "rsa1") == 0) {
-		return KEY_RSA1;
-	} else if (strcmp(name, "rsa") == 0) {
-		return KEY_RSA;
-	} else if (strcmp(name, "dsa") == 0) {
-		return KEY_DSA;
-	} else if (strcmp(name, "ssh-rsa") == 0) {
-		return KEY_RSA;
-	} else if (strcmp(name, "ssh-dss") == 0) {
-		return KEY_DSA;
-	} else if (strcmp(name, "ecdsa-sha2-nistp256") == 0) {
-		return KEY_ECDSA256;
-	} else if (strcmp(name, "ecdsa-sha2-nistp384") == 0) {
-		return KEY_ECDSA384;
-	} else if (strcmp(name, "ecdsa-sha2-nistp521") == 0) {
-		return KEY_ECDSA521;
-	} else if (strcmp(name, "ssh-ed25519") == 0) {
-		return KEY_ED25519;
-	}
-	return KEY_UNSPEC;
-}
-
-
 ssh_keytype key_curve_name_to_keytype(char *name)
 {
 	if (strcmp(name, "nistp256") == 0) {
@@ -1318,7 +1282,7 @@
 	BIGNUM *p, *q, *g, *pub_key;
 
 	b = buffer_init();
-	sshname = get_sshname_from_key(key);
+	sshname = get_ssh2_hostkey_type_name_from_key(key);
 
 	switch (key->type) {
 	case KEY_RSA:
@@ -1411,7 +1375,7 @@
 	key[keynamelen] = 0;
 	data += keynamelen;
 
-	type = get_keytype_from_name(key);
+	type = get_hostkey_type_from_name(key);
 
 	switch (type) {
 	case KEY_RSA: // RSA key
@@ -1618,7 +1582,7 @@
 
 		}
 
-		s = get_sshname_from_key(keypair);
+		s = get_ssh2_hostkey_type_name_from_key(keypair);
 		buffer_put_string(msg, s, strlen(s));
 		buffer_append_length(msg, sig, slen);
 		len = buffer_len(msg);
@@ -1676,7 +1640,7 @@
 		DSA_SIG_free(sig);
 
 		// setting
-		s = get_sshname_from_key(keypair);
+		s = get_ssh2_hostkey_type_name_from_key(keypair);
 		buffer_put_string(msg, s, strlen(s));
 		buffer_append_length(msg, sigblob, sizeof(sigblob));
 		len = buffer_len(msg);
@@ -1735,7 +1699,7 @@
 		buffer_put_bignum2(buf2, bs);
 		ECDSA_SIG_free(sig);
 
-		s = get_sshname_from_key(keypair);
+		s = get_ssh2_hostkey_type_name_from_key(keypair);
 		buffer_put_string(msg, s, strlen(s));
 		buffer_put_string(msg, buffer_ptr(buf2), buffer_len(buf2));
 		buffer_free(buf2);
@@ -1791,7 +1755,7 @@
 
 	switch (keypair->type) {
 	case KEY_RSA: // RSA
-		s = get_sshname_from_key(keypair);
+		s = get_ssh2_hostkey_type_name_from_key(keypair);
 		RSA_get0_key(keypair->rsa, &n, &e, NULL);
 		buffer_put_string(msg, s, strlen(s));
 		buffer_put_bignum2(msg, e); // \x8C\xF6\x8AJ\x8Ew\x90\x94
@@ -1800,7 +1764,7 @@
 	case KEY_DSA: // DSA
 		DSA_get0_pqg(keypair->dsa, &p, &q, &g);
 		DSA_get0_key(keypair->dsa, &pub_key, NULL);
-		s = get_sshname_from_key(keypair);
+		s = get_ssh2_hostkey_type_name_from_key(keypair);
 		buffer_put_string(msg, s, strlen(s));
 		buffer_put_bignum2(msg, p); // \x91f\x90\x94
 		buffer_put_bignum2(msg, q); // (p-1)\x82̑f\x88\xF6\x90\x94
@@ -1810,7 +1774,7 @@
 	case KEY_ECDSA256: // ECDSA
 	case KEY_ECDSA384:
 	case KEY_ECDSA521:
-		s = get_sshname_from_key(keypair);
+		s = get_ssh2_hostkey_type_name_from_key(keypair);
 		buffer_put_string(msg, s, strlen(s));
 		tmp = curve_keytype_to_name(keypair->type);
 		buffer_put_string(msg, tmp, strlen(tmp));
@@ -1818,7 +1782,7 @@
 		                        EC_KEY_get0_public_key(keypair->ecdsa));
 		break;
 	case KEY_ED25519:
-		s = get_sshname_from_key(keypair);
+		s = get_ssh2_hostkey_type_name_from_key(keypair);
 		buffer_put_cstring(msg, s);
 		buffer_put_string(msg, keypair->ed25519_pk, ED25519_PK_SZ);
 		break;
@@ -1890,7 +1854,7 @@
 	BIGNUM *e, *n, *d, *iqmp, *p, *q;
 	BIGNUM *g, *pub_key, *priv_key;
 	
-	s = get_sshname_from_key(key);
+	s = get_ssh2_hostkey_type_name_from_key(key);
 	buffer_put_cstring(b, s);
 
 	switch (key->type) {
@@ -1978,7 +1942,7 @@
 	type_name = buffer_get_string_msg(blob, NULL);
 	if (type_name == NULL)
 		goto error;
-	type = get_keytype_from_name(type_name);
+	type = get_hostkey_type_from_name(type_name);
 
 	k = key_new_private(type);
 
@@ -2242,7 +2206,8 @@
 		if (index == KEY_NONE) // disabled line
 			break;
 
-		if (strcmp(get_sshname_from_key(key), get_ssh_keytype_name(index)) == 0)
+		if (strcmp(get_ssh2_hostkey_type_name_from_key(key),
+		           get_ssh2_hostkey_type_name(index)) == 0)
 			return 1;
 	}
 
@@ -2314,7 +2279,7 @@
 				fp = key_fingerprint(ctx->keys[i], SSH_FP_BASE64, SSH_DIGEST_SHA256);
 				break;
 			}
-			strncat_s(buf, buf_len, get_sshname_from_key(ctx->keys[i]), _TRUNCATE);
+			strncat_s(buf, buf_len, get_ssh2_hostkey_type_name_from_key(ctx->keys[i]), _TRUNCATE);
 			strncat_s(buf, buf_len, " ", _TRUNCATE);
 			if (fp != NULL) {
 				strncat_s(buf, buf_len, fp, _TRUNCATE);
@@ -2342,7 +2307,7 @@
 				fp = key_fingerprint(ctx->old_keys[i], SSH_FP_BASE64, SSH_DIGEST_SHA256);
 				break;
 			}
-			strncat_s(buf, buf_len, get_sshname_from_key(ctx->old_keys[i]), _TRUNCATE);
+			strncat_s(buf, buf_len, get_ssh2_hostkey_type_name_from_key(ctx->old_keys[i]), _TRUNCATE);
 			strncat_s(buf, buf_len, " ", _TRUNCATE);
 			if (fp != NULL) {
 				strncat_s(buf, buf_len, fp, _TRUNCATE);
@@ -2557,7 +2522,7 @@
 		if (ret != 1) {
 			logprintf(LOG_LEVEL_ERROR,
 				"server gave bad signature for %s key %u",
-				get_sshname_from_key(ctx->keys[i]), i);
+				get_ssh2_hostkey_type_name_from_key(ctx->keys[i]), i);
 			goto error;
 		}
 		ndone++;
@@ -2628,13 +2593,14 @@
 		blob = NULL;
 
 		fp = key_fingerprint(key, SSH_FP_HEX, SSH_DIGEST_MD5);
-		logprintf(LOG_LEVEL_VERBOSE, "Received %s host key %s", get_sshname_from_key(key), fp);
+		logprintf(LOG_LEVEL_VERBOSE, "Received %s host key %s",
+		          get_ssh2_hostkey_type_name_from_key(key), fp);
 		free(fp);
 
 		// \x8B\x96\x89‚\xB3\x82ꂽ\x83z\x83X\x83g\x83L\x81[\x83A\x83\x8B\x83S\x83\x8A\x83Y\x83\x80\x82\xA9\x82\xF0\x83`\x83F\x83b\x83N\x82\xB7\x82\xE9\x81B
 		if (check_hostkey_algorithm(pvar, key) == 0) {
 			logprintf(LOG_LEVEL_VERBOSE, "%s host key is not permitted by ts.HostKeyOrder",
-				get_sshname_from_key(key));
+			          get_ssh2_hostkey_type_name_from_key(key));
 			continue;
 		}
 
@@ -2644,7 +2610,7 @@
 		for (i = 0; i < ctx->nkeys; i++) {
 			if (HOSTS_compare_public_key(key, ctx->keys[i]) == 1) {
 				logprintf(LOG_LEVEL_ERROR, "Received duplicated %s host key",
-					get_sshname_from_key(key));
+				          get_ssh2_hostkey_type_name_from_key(key));
 				goto error;
 			}
 		}

Modified: branches/4-stable/ttssh2/ttxssh/key.h
===================================================================
--- branches/4-stable/ttssh2/ttxssh/key.h	2021-05-19 14:05:07 UTC (rev 9253)
+++ branches/4-stable/ttssh2/ttxssh/key.h	2021-05-19 14:11:12 UTC (rev 9254)
@@ -44,11 +44,9 @@
 BOOL key_copy(Key *dest, Key *src);
 
 char *key_fingerprint_raw(Key *k, digest_algorithm dgst_alg, int *dgst_raw_length);
-char *key_fingerprint(Key *key, enum fp_rep dgst_rep, digest_algorithm dgst_alg);
+char *key_fingerprint(Key *key, fp_rep dgst_rep, digest_algorithm dgst_alg);
 
 const char *ssh_key_type(ssh_keytype type);
-char *get_sshname_from_key(Key *key);
-ssh_keytype get_keytype_from_name(char *name);
 char *curve_keytype_to_name(ssh_keytype type);
 ssh_keytype key_curve_name_to_keytype(char *name);
 
@@ -74,4 +72,4 @@
 
 int update_client_input_hostkeys(PTInstVar pvar, char *dataptr, int datalen);
 
-#endif
+#endif /* __KEY_H_ */

Modified: branches/4-stable/ttssh2/ttxssh/keyfiles.c
===================================================================
--- branches/4-stable/ttssh2/ttxssh/keyfiles.c	2021-05-19 14:05:07 UTC (rev 9253)
+++ branches/4-stable/ttssh2/ttxssh/keyfiles.c	2021-05-19 14:11:12 UTC (rev 9254)
@@ -354,12 +354,12 @@
 // bcrypt KDF \x8C`\x8E\xAE\x82œǂ\xDE
 // based on key_parse_private2() @ OpenSSH 6.5
 static Key *read_SSH2_private2_key(PTInstVar pvar,
-                           FILE * fp,
-                           char * passphrase,
-                           BOOL * invalid_passphrase,
-                           BOOL is_auto_login,
-                           char *errmsg,
-                           int errmsg_len)
+                                   FILE * fp,
+                                   char * passphrase,
+                                   BOOL * invalid_passphrase,
+                                   BOOL is_auto_login,
+                                   char *errmsg,
+                                   int errmsg_len)
 {
 	/* (A) 
 	 * buffer_consume\x8Cn\x8A֐\x94\x82\xF0\x8Eg\x82\xA4\x8Fꍇ\x82́Abuffer_len\x82\xC6buffer_ptr\x82\xAA\x8Eg\x82\xA6\x82Ȃ\xA2\x82̂ŁA
@@ -379,9 +379,9 @@
 	unsigned int len, klen, nkeys, blocksize, keylen, ivlen, slen, rounds;
 	unsigned int check1, check2, m1len, m2len; 
 	int dlen, i;
-	SSH2Cipher *cipher;
+	const struct ssh2cipher *cipher;
 	size_t authlen;
-	EVP_CIPHER_CTX *cipher_ctx = NULL;
+	struct sshcipher_ctx *cc = NULL;
 	int ret;
 
 	blob = buffer_init();
@@ -389,9 +389,8 @@
 	kdf = buffer_init();
 	encoded = buffer_init();
 	copy_consumed = buffer_init();
-	cipher_ctx = EVP_CIPHER_CTX_new();
 
-	if (blob == NULL || b == NULL || kdf == NULL || encoded == NULL || copy_consumed == NULL || cipher_ctx == NULL)
+	if (blob == NULL || b == NULL || kdf == NULL || encoded == NULL || copy_consumed == NULL)
 		goto error;
 
 	// \x83t\x83@\x83C\x83\x8B\x82\xF0\x82\xB7\x82ׂēǂݍ\x9E\x82\xDE
@@ -552,14 +551,11 @@
 
 	// \x95\x9C\x8D\x86\x89\xBB
 	cp = buffer_append_space(b, len);
-	cipher_init_SSH2(cipher_ctx, key, keylen, key + keylen, ivlen, CIPHER_DECRYPT, 
-		get_cipher_EVP_CIPHER(cipher), 0, 0, pvar);
-	ret = EVP_Cipher(cipher_ctx, cp, buffer_tail_ptr(copy_consumed), len);
+	cipher_init_SSH2(&cc, cipher, key, keylen, key + keylen, ivlen, CIPHER_DECRYPT, pvar);
+	ret = EVP_Cipher(cc->evp, cp, buffer_tail_ptr(copy_consumed), len);
 	if (ret == 0) {
-		cipher_cleanup_SSH2(cipher_ctx);
 		goto error;
 	}
-	cipher_cleanup_SSH2(cipher_ctx);
 	buffer_consume(copy_consumed, len);
 
 	if (buffer_remain_len(copy_consumed) != 0) {
@@ -607,6 +603,7 @@
 	buffer_free(kdf);
 	buffer_free(encoded);
 	buffer_free(copy_consumed);
+	cipher_free_SSH2(cc);
 
 	free(ciphername);
 	free(kdfname);
@@ -615,10 +612,6 @@
 	free(salt);
 	free(comment);
 
-	if (cipher_ctx) {
-		EVP_CIPHER_CTX_free(cipher_ctx);
-	}
-
 	// KDF \x82ł͂Ȃ\xA9\x82\xC1\x82\xBD
 	if (keyfmt == NULL) {
 		fseek(fp, 0, SEEK_SET);
@@ -817,6 +810,8 @@
 	int i, len, len2;
 	char *encname = NULL, *comment = NULL, *private_mac = NULL;
 	buffer_t *pubkey = NULL, *prikey = NULL;
+	const struct ssh2cipher *cipher = NULL;
+	struct sshcipher_ctx *cc = NULL;
 
 	result = (Key *)malloc(sizeof(Key));
 	ZeroMemory(result, sizeof(Key)); 
@@ -943,7 +938,7 @@
 		}
 
 		cipher_ctx = EVP_CIPHER_CTX_new();
-		if (ctx == NULL) {
+		if (cipher_ctx == NULL) {
 			EVP_MD_CTX_free(ctx);
 			goto error;
 		}
@@ -963,22 +958,21 @@
 		memset(iv, 0, sizeof(iv));
 
 		// decrypt
-		cipher_init_SSH2(cipher_ctx, key, 32, iv, 16, CIPHER_DECRYPT, EVP_aes_256_cbc(), 0, 0, pvar);
+		cipher = get_cipher_by_name("aes256-cbc");
+		cipher_init_SSH2(&cc, cipher, key, 32, iv, 16, CIPHER_DECRYPT, pvar);
 		len = buffer_len(prikey);
 		decrypted = (char *)malloc(len);
-		ret = EVP_Cipher(cipher_ctx, decrypted, prikey->buf, len);
+		ret = EVP_Cipher(cc->evp, decrypted, prikey->buf, len);
 		if (ret == 0) {
 			strncpy_s(errmsg, errmsg_len, "Key decrypt error", _TRUNCATE);
 			free(decrypted);
-			cipher_cleanup_SSH2(cipher_ctx);
-			EVP_CIPHER_CTX_free(cipher_ctx);
+			cipher_free_SSH2(cc);
 			goto error;
 		}
 		buffer_clear(prikey);
 		buffer_append(prikey, decrypted, len);
 		free(decrypted);
-		cipher_cleanup_SSH2(cipher_ctx);
-		EVP_CIPHER_CTX_free(cipher_ctx);
+		cipher_free_SSH2(cc);
 	}
 
 	// verity MAC
@@ -989,9 +983,9 @@
 
 	macdata = buffer_init();
 
-	len = strlen(get_ssh_keytype_name(result->type));
+	len = strlen(get_ssh2_hostkey_type_name(result->type));
 	buffer_put_int(macdata, len);
-	buffer_append(macdata, get_ssh_keytype_name(result->type), len);
+	buffer_append(macdata, get_ssh2_hostkey_type_name(result->type), len);
 	len = strlen(encname);
 	buffer_put_int(macdata, len);
 	buffer_append(macdata, encname, len);
@@ -1395,6 +1389,8 @@
 	int encflag;
 	char *encname = NULL;
 	buffer_t *blob = NULL, *blob2 = NULL;
+	const struct ssh2cipher *cipher = NULL;
+	struct sshcipher_ctx *cc = NULL;
 
 	result = (Key *)malloc(sizeof(Key));
 	ZeroMemory(result, sizeof(Key)); 
@@ -1536,19 +1532,18 @@
 		memset(iv, 0, sizeof(iv));
 
 		// decrypt
-		cipher_init_SSH2(cipher_ctx, key, 24, iv, 8, CIPHER_DECRYPT, EVP_des_ede3_cbc(), 0, 0, pvar);
+		cipher = get_cipher_by_name("3des-cbc");
+		cipher_init_SSH2(&cc, cipher, key, 24, iv, 8, CIPHER_DECRYPT, pvar);
 		decrypted = (char *)malloc(len);
-		ret = EVP_Cipher(cipher_ctx, decrypted, blob->buf + blob->offset, len);
+		ret = EVP_Cipher(cc->evp, decrypted, blob->buf + blob->offset, len);
 		if (ret == 0) {
 			strncpy_s(errmsg, errmsg_len, "Key decrypt error", _TRUNCATE);
-			cipher_cleanup_SSH2(cipher_ctx);
-			EVP_CIPHER_CTX_free(cipher_ctx);
+			cipher_free_SSH2(cc);
 			goto error;
 		}
 		buffer_append(blob2, decrypted, len);
 		free(decrypted);
-		cipher_cleanup_SSH2(cipher_ctx);
-		EVP_CIPHER_CTX_free(cipher_ctx);
+		cipher_free_SSH2(cc);
 
 		*invalid_passphrase = TRUE;
 	}

Copied: branches/4-stable/ttssh2/ttxssh/mac.c (from rev 9252, branches/ssh_chacha20poly1305/ttssh2/ttxssh/mac.c)
===================================================================
--- branches/4-stable/ttssh2/ttxssh/mac.c	                        (rev 0)
+++ branches/4-stable/ttssh2/ttxssh/mac.c	2021-05-19 14:11:12 UTC (rev 9254)
@@ -0,0 +1,191 @@
+/*
+ * (C) 2021- TeraTerm Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ttxssh.h"
+#include "mac.h"
+#include "kex.h"
+
+
+struct SSH2Mac {
+	SSH2MacId id;
+	char *name;
+	const EVP_MD *(*evp_md)(void);
+	int truncatebits;
+	int etm;
+};
+
+static const struct SSH2Mac ssh2_macs[] = {
+	{HMAC_SHA1,         "hmac-sha1",                     EVP_sha1,      0,  0}, // RFC4253
+	{HMAC_MD5,          "hmac-md5",                      EVP_md5,       0,  0}, // RFC4253
+	{HMAC_SHA1_96,      "hmac-sha1-96",                  EVP_sha1,      96, 0}, // RFC4253
+	{HMAC_MD5_96,       "hmac-md5-96",                   EVP_md5,       96, 0}, // RFC4253
+	{HMAC_RIPEMD160,    "hmac-****@opens*****",    EVP_ripemd160, 0,  0},
+	{HMAC_SHA2_256,     "hmac-sha2-256",                 EVP_sha256,    0,  0}, // RFC6668
+//	{HMAC_SHA2_256_96,  "hmac-sha2-256-96",              EVP_sha256,    96, 0}, // draft-dbider-sha2-mac-for-ssh-05, deleted at 06
+	{HMAC_SHA2_512,     "hmac-sha2-512",                 EVP_sha512,    0,  0}, // RFC6668
+//	{HMAC_SHA2_512_96,  "hmac-sha2-512-96",              EVP_sha512,    96, 0}, // draft-dbider-sha2-mac-for-ssh-05, deleted at 06
+	{HMAC_SHA1_EtM,     "hmac-****@opens*****",     EVP_sha1,      0,  1},
+	{HMAC_MD5_EtM,      "hmac-****@opens*****",      EVP_md5,       0,  1},
+	{HMAC_SHA1_96_EtM,  "hmac-****@opens*****",  EVP_sha1,      96, 1},
+	{HMAC_MD5_96_EtM,   "hmac-****@opens*****",   EVP_md5,       96, 1},
+	{HMAC_RIPEMD160_EtM,"hmac-****@opens*****",EVP_ripemd160, 0,  1},
+	{HMAC_SHA2_256_EtM, "hmac-****@opens*****", EVP_sha256,    0,  1},
+	{HMAC_SHA2_512_EtM, "hmac-****@opens*****", EVP_sha512,    0,  1},
+	{HMAC_IMPLICIT,     "<implicit>",                    EVP_md_null,   0,  0}, // for AEAD cipher
+	{HMAC_NONE,         NULL,                            NULL,          0,  0},
+};
+
+
+char* get_ssh2_mac_name(const struct SSH2Mac *mac)
+{
+	if (mac) {
+		return mac->name;
+	}
+	else {
+		return "unknown";
+	}
+}
+
+char* get_ssh2_mac_name_by_id(const SSH2MacId id)
+{
+	return get_ssh2_mac_name(get_ssh2_mac(id));
+}
+
+const EVP_MD* get_ssh2_mac_EVP_MD(const struct SSH2Mac *mac)
+{
+	if (mac) {
+		return mac->evp_md();
+	}
+	else {
+		return EVP_md_null();
+	}
+}
+
+const struct SSH2Mac *get_ssh2_mac(SSH2MacId id)
+{
+	const struct SSH2Mac *ptr = ssh2_macs;
+
+	while (ptr->name != NULL) {
+		if (ptr->id == id) {
+			return ptr;
+		}
+		ptr++;
+	}
+
+	return NULL;
+}
+
+int get_ssh2_mac_truncatebits(const struct SSH2Mac *mac)
+{
+	if (mac) {
+		return mac->truncatebits;
+	}
+	else {
+		return 0;
+	}
+}
+
+int get_ssh2_mac_etm(const struct SSH2Mac *mac)
+{
+	if (mac) {
+		return mac->etm;
+	}
+	else {
+		return 0;
+	}
+}
+
+void normalize_mac_order(char *buf)
+{
+	static char default_strings[] = {
+		HMAC_SHA2_512_EtM,
+		HMAC_SHA2_256_EtM,
+		HMAC_SHA1_EtM,
+		HMAC_SHA2_512,
+		HMAC_SHA2_256,
+		HMAC_SHA1,
+		HMAC_RIPEMD160_EtM,
+		HMAC_RIPEMD160,
+		HMAC_MD5_EtM,
+		HMAC_MD5,
+		HMAC_NONE,
+		HMAC_SHA1_96_EtM,
+		HMAC_MD5_96_EtM,
+		HMAC_SHA1_96,
+		HMAC_MD5_96,
+		0, // Dummy for HMAC_SHA2_512_96,
+		0, // Dummy for HMAC_SHA2_256_96,
+	};
+
+	normalize_generic_order(buf, default_strings, NUM_ELEM(default_strings));
+}
+
+const struct SSH2Mac *choose_SSH2_mac_algorithm(char *server_proposal, char *my_proposal)
+{
+	char str_hmac[64];
+	const struct SSH2Mac *ptr = ssh2_macs;
+
+	choose_SSH2_proposal(server_proposal, my_proposal, str_hmac, sizeof(str_hmac));
+
+	while (ptr->name != NULL) {
+		if (strcmp(ptr->name, str_hmac) == 0) {
+			return ptr;
+		}
+		ptr++;
+	}
+
+	return (NULL);
+}
+
+// HMAC\x83A\x83\x8B\x83S\x83\x8A\x83Y\x83\x80\x97D\x90揇\x88ʂɉ\x9E\x82\xB6\x82āAmyproposal[]\x82\xF0\x8F\x91\x82\xAB\x8A\xB7\x82\xA6\x82\xE9\x81B
+// (2011.2.28 yutaka)
+void SSH2_update_hmac_myproposal(PTInstVar pvar)
+{
+	static char buf[256]; // TODO: malloc()\x82ɂ\xB7\x82ׂ\xAB
+	int index;
+	int len, i;
+
+	// \x92ʐM\x92\x86\x82ɂ͌Ă΂\xEA\x82Ȃ\xA2\x82͂\xB8\x82\xBE\x82\xAA\x81A\x94O\x82̂\xBD\x82߁B(2006.6.26 maya)
+	if (pvar->socket != INVALID_SOCKET) {
+		return;
+	}
+
+	buf[0] = '\0';
+	for (i = 0 ; pvar->settings.MacOrder[i] != 0 ; i++) {
+		index = pvar->settings.MacOrder[i] - '0';
+		if (index == HMAC_NONE) // disabled line
+			break;
+		strncat_s(buf, sizeof(buf), get_ssh2_mac_name_by_id(index), _TRUNCATE);
+		strncat_s(buf, sizeof(buf), ",", _TRUNCATE);
+	}
+	len = strlen(buf);
+	if (len > 0)
+		buf[len - 1] = '\0';  // get rid of comma
+	myproposal[PROPOSAL_MAC_ALGS_CTOS] = buf; 
+	myproposal[PROPOSAL_MAC_ALGS_STOC] = buf; 
+}

Copied: branches/4-stable/ttssh2/ttxssh/mac.h (from rev 9252, branches/ssh_chacha20poly1305/ttssh2/ttxssh/mac.h)
===================================================================
--- branches/4-stable/ttssh2/ttxssh/mac.h	                        (rev 0)
+++ branches/4-stable/ttssh2/ttxssh/mac.h	2021-05-19 14:11:12 UTC (rev 9254)
@@ -0,0 +1,69 @@
+/*
+ * (C) 2021- TeraTerm Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SSHMAC_H
+#define SSHMAC_H
+
+#include "ttxssh.h"
+
+struct SSH2Mac;
+
+typedef enum {
+	HMAC_NONE,      /* disabled line */
+	HMAC_SHA1,
+	HMAC_MD5,
+	HMAC_SHA1_96,
+	HMAC_MD5_96,
+	HMAC_RIPEMD160,
+	HMAC_SHA2_256,
+	HMAC_SHA2_256_96,
+	HMAC_SHA2_512,
+	HMAC_SHA2_512_96,
+	HMAC_SHA1_EtM,
+	HMAC_MD5_EtM,
+	HMAC_SHA1_96_EtM,
+	HMAC_MD5_96_EtM,
+	HMAC_RIPEMD160_EtM,
+	HMAC_SHA2_256_EtM,
+	HMAC_SHA2_512_EtM,
+	HMAC_IMPLICIT,
+	HMAC_UNKNOWN,
+	HMAC_MAX = HMAC_UNKNOWN,
+} SSH2MacId;
+
+char* get_ssh2_mac_name(const struct SSH2Mac *mac);
+char* get_ssh2_mac_name_by_id(SSH2MacId id);
+const EVP_MD* get_ssh2_mac_EVP_MD(const struct SSH2Mac *mac);
+const struct SSH2Mac *get_ssh2_mac(SSH2MacId id);
+int get_ssh2_mac_truncatebits(const struct SSH2Mac *mac);
+int get_ssh2_mac_etm(const struct SSH2Mac *mac);
+void normalize_mac_order(char *buf);
+const struct SSH2Mac *choose_SSH2_mac_algorithm(char *server_proposal, char *my_proposal);
+void SSH2_update_hmac_myproposal(PTInstVar pvar);
+
+#endif /* SSHCMAC_H */

Modified: branches/4-stable/ttssh2/ttxssh/pkt.c
===================================================================
--- branches/4-stable/ttssh2/ttxssh/pkt.c	2021-05-19 14:05:07 UTC (rev 9253)
+++ branches/4-stable/ttssh2/ttxssh/pkt.c	2021-05-19 14:11:12 UTC (rev 9254)
@@ -176,64 +176,115 @@
 		}
 		else if (pvar->pkt_state.seen_server_ID && pvar->pkt_state.datalen >= SSH_get_min_packet_size(pvar)) {
 			char *data = pvar->pkt_state.buf + pvar->pkt_state.datastart;
-			uint32 padding;
-			uint32 pktsize;
+			uint32 padding_size = 0;
+			uint32 pktsize = 0;
 			uint32 total_packet_size;
 			struct Mac *mac = &pvar->ssh2_keys[MODE_IN].mac;
 			struct Enc *enc = &pvar->ssh2_keys[MODE_IN].enc;
-			int aadlen;
+			int authlen = 0, aadlen = 0;
 
-			/*
-			 * aadlen: Additional Authenticated Data Length
-			 *   - \x88Í\x86\x89\xBB\x82\xB5\x82Ȃ\xA2\x82\xAA MAC \x82\xE2 AEAD \x82ł̔F\x8F؂̑ΏۂƂȂ\xE9\x83f\x81[\x83^\x82̒\xB7\x82\xB3
-			 *
-			 * EtM \x95\xFB\x8E\xAE\x82\xCC MAC \x82\xE2\x81AAEAD \x82ȈÍ\x86\x82ł̓p\x83P\x83b\x83g\x82̐擪\x82̃p\x83P\x83b\x83g\x92\xB7\x95\x94\x95\xAA\x82͈Í\x86\x89\xBB\x82\xB3\x82ꂸ
-			 * \x94F\x8F؂݂̂\xAA\x8Ds\x82\xED\x82\xEA\x82\xE9\x81B\x83p\x83P\x83b\x83g\x92\xB7\x82\xCD uint32 (4\x83o\x83C\x83g) \x82Ŋi\x94[\x82\xB3\x82\xEA\x82Ă\xA2\x82\xE9\x81B
-			 * \x92ʏ\xED\x82\xCC MAC \x95\xFB\x8E\xAE (E&M) \x82ŁA\x82\xA9\x82\xC2 AEAD \x82łȂ\xA2\x88Í\x86\x95\xFB\x8E\xAE\x82ł̓p\x83P\x83b\x83g\x92\xB7\x95\x94\x95\xAA\x82\xE0\x88Í\x86\x89\xBB
-			 * \x82\xB3\x82\xEA\x82\xE9\x82̂\xC5 aadlen \x82\xCD 0 \x82ƂȂ\xE9\x81B
-			 */
-			if (SSHv2(pvar) && ((mac && mac->etm) || (enc && enc->auth_len > 0))) {
-				aadlen = 4;
+			if (SSHv2(pvar)) {
+				/*
+				 * pktsize
+				 *   uint32   packet_length
+				 * \x82\xCD
+				 *   byte     padding_length
+				 *   byte[n1] payload; n1 = packet_length - padding_length - 1
+				 *   byte[n2] random padding; n2 = padding_length
+				 * \x82̒\xB7\x82\xB3\x82̍\x87\x8Cv\x82\xC5
+				 *   byte[m]  mac (Message Authentication Code - MAC); m = mac_length
+				 * \x82̒\xB7\x82\xB3\x82\xF0\x8A܂܂Ȃ\xA2\x81B
+				 * cf. RFC 4253 6. Binary Packet Protocol
+				 */
+
+				if (enc && enc->auth_len > 0) {
+					authlen = enc->auth_len;
+				}
+
+				/*
+				 *                      |          | lead 4 bytes are encrypted | aadlen |
+				 * Encryption type
+				 *   enc->auth_len >  0 | AEAD     | AES-GCM ... no             | 4      |     (2)
+				 *                      |          | chacha20-poly1305 ... yes  | 4      | (1) (2)
+				 *   enc->auth_len == 0 | not AEAD | depends on MAC type        | <-     |
+				 * MAC type
+				 *   mac->etm == true   | EtM      | no                         | 4      |
+				 *   mac->etm == false  | E&M      | yes                        | 0      |
+				 * (1) lead 4 bytes are encrypted separately from main part.
+				 * (2) implicit MAC type of AEAD is EtM
+				 */
+				/*
+				 * aadlen: Additional Authenticated Data Length
+				 *   MAC \x82̑ΏۂƂȂ\xE9\x83f\x81[\x83^\x82ƈꏏ\x82ɈÍ\x86\x89\xBB\x82\xB3\x82\xEA\x82Ȃ\xA2\x81A"MAC \x82̑ΏۂƂȂ\xE9\x83f\x81[\x83^\x82̒\xB7\x82\xB3"\x82̃T\x83C\x83Y
+				 *   \x82\xB1\x82̕\x94\x95\xAA\x82\xCD packet_length \x82ŁAuint32 (4\x83o\x83C\x83g)
+				 * 
+				 * - \x92ʏ\xED\x82\xCC MAC \x95\xFB\x8E\xAE (E&M) \x82ł̓p\x83P\x83b\x83g\x92\xB7\x95\x94\x95\xAA\x82\xAA\x88ꏏ\x82ɈÍ\x86\x89\xBB\x82\xB3\x82\xEA\x82\xE9\x82̂\xC5 aadlen \x82\xCD 0 \x82ƂȂ\xE9\x81B
+				 * - EtM \x95\xFB\x8E\xAE\x82\xCC MAC \x82\xE2 AEAD \x82\xCC AES-GCM \x82ł́A\x83p\x83P\x83b\x83g\x92\xB7\x95\x94\x95\xAA\x82\xAA\x88Í\x86\x89\xBB\x82\xB3\x82\xEA\x82Ȃ\xA2\x82̂\xC5
+				 * aadlen \x82\xCD 4 \x82ƂȂ\xE9\x81B
+				 * - AEAD \x82\xCC chacha20-poly1305 \x82ł̓p\x83P\x83b\x83g\x92\xB7\x95\x94\x95\xAA\x82\xAA\x88Í\x86\x89\xBB\x82\xB3\x82\xEA\x82邪\x81AMAC \x82̑ΏۂƂȂ\xE9\x83f\x81[\x83^
+				 * \x82Ƃ͕ʂɈÍ\x86\x89\xBB\x82\xB3\x82\xEA\x82\xE9\x82̂\xC5 aadlen \x82\xCD 4 \x82ƂȂ\xE9\x81B
+				 * 
+				 */
+				if ((mac && mac->etm) || authlen > 0) {
+					aadlen = 4;
+				}
+
+				if (authlen > 0 &&
+				    pvar->cc[MODE_IN]->cipher->id == SSH2_CIPHER_CHACHAPOLY) {
+					/*
+					 * AEAD \x82\xCC chacha20-poly1305 \x82ł̓p\x83P\x83b\x83g\x92\xB7\x95\x94\x95\xAA\x82\xAA\x95ʂɈÍ\x86\x89\xBB\x82\xB3\x82\xEA\x82Ă\xA2\x82\xE9\x81B
+					 * \x82\xB1\x82̏\x88\x97\x9D\x82͒\xB7\x82\xB3\x82\xF0\x8E擾\x82\xB7\x82邪\x81Adata \x82͈Í\x86\x89\xBB\x82\xB3\x82ꂽ\x82܂܂ƂȂ\xE9\x81B
+					 */
+					chachapoly_get_length(pvar->cc[MODE_IN]->cp_ctx, &pktsize,
+					                      pvar->ssh_state.receiver_sequence_number,
+					                      data, pvar->pkt_state.datalen);
+				}
+				else if (authlen == 0 &&
+				         aadlen == 0 &&
+				         !pvar->pkt_state.predecrypted_packet && aadlen == 0) {
+					/*
+					 * AEAD \x82łȂ\xAD E&M (aadlen \x82\xAA 0) \x82̎\x9E\x82́A\x88Í\x86\x89\xBB\x82\xB3\x82\xEA\x82Ă\xA2\x82\xE9\x83p\x83P\x83b\x83g\x92\xB7\x82\xF0
+					 * \x92m\x82\xE9\x95K\x97v\x82\xAA\x97L\x82邽\x82߁A\x90擪\x82\xCC 1 \x83u\x83\x8D\x83b\x83N\x82\xBE\x82\xAF\x8E\x96\x91O\x82ɕ\x9C\x8D\x86\x82\xB7\x82\xE9\x81B
+					 */
+					SSH_predecrypt_packet(pvar, data);
+					pvar->pkt_state.predecrypted_packet = TRUE;
+
+					pktsize = get_uint32_MSBfirst(data);
+				}
+				else {
+					/*
+					 * EtM \x95\xFB\x8E\xAE\x82\xCC MAC \x82\xE2\x81AAEAD \x82\xC5 AES-GCM \x82̂Ƃ\xAB\x82Ȃǂ͂\xBB\x82̂܂ܓǂ߂\xE9\x81B
+					 */
+					pktsize = get_uint32_MSBfirst(data);
+				}
 			}
 			else {
-				aadlen = 0;
+				pktsize = get_uint32_MSBfirst(data);
 			}
 
-			/*
-			 * aadlen \x82\xAA 0 \x82̎\x9E\x82̓p\x83P\x83b\x83g\x92\xB7\x95\x94\x95\xAA\x82\xAA\x88Í\x86\x89\xBB\x82\xB3\x82\xEA\x82Ă\xA2\x82\xE9\x81B\x83p\x83P\x83b\x83g\x91S\x91̂\xF0\x8E\xF3\x90M\x82\xB5\x82Ă\xA9\x82\xE7
-			 * \x8C\xE3\x92i\x82̏\x88\x97\x9D\x82\xF0\x8Ds\x82\xA4\x88ׂɃp\x83P\x83b\x83g\x92\xB7\x82\xF0\x92m\x82\xE9\x95K\x97v\x82\xAA\x97L\x82\xE9\x88ׁA\x90擪\x82\xCC 1 \x83u\x83\x8D\x83b\x83N\x82𕜍\x86\x82\xB7\x82\xE9\x81B
-			 */
-			if (SSHv2(pvar) && !pvar->pkt_state.predecrypted_packet && aadlen == 0) {
-				SSH_predecrypt_packet(pvar, data);
-				pvar->pkt_state.predecrypted_packet = TRUE;
-			}
-
-			// \x83p\x83P\x83b\x83g\x82̐擪\x82\xC9 uint32 (4\x83o\x83C\x83g) \x82̃p\x83P\x83b\x83g\x92\xB7\x82\xAA\x97\x88\x82\xE9
-			pktsize = get_uint32_MSBfirst(data);
-
 			if (SSHv1(pvar)) {
 				// SSH1 \x82ł̓p\x83P\x83b\x83g\x92\xB7\x82̒l\x82ɂ\xCD padding \x82̒\xB7\x82\xB3\x82\xAA\x8A܂܂\xEA\x82Ă\xA2\x82Ȃ\xA2\x81B
 				// \x82܂\xBD padding \x82̒\xB7\x82\xB3\x82̏\xEE\x95\xF1\x82\xE0\x83p\x83P\x83b\x83g\x8F\xE3\x82ɂ͖\xB3\x82\xA2\x82̂ŁA\x83p\x83P\x83b\x83g\x92\xB7\x82̒l\x82\xA9\x82\xE7\x8Cv\x8EZ\x82\xB7\x82\xE9\x81B
-				padding = 8 - (pktsize % 8);
+				padding_size = 8 - (pktsize % 8);
 
-				// \x88ȍ~\x82̏\x88\x97\x9D\x82\xCD pktsize \x82\xC9 padding \x82̒l\x82\xAA\x8A܂܂\xEA\x82Ă\xA2\x82鎖\x82\xAA\x91O\x92\xF1\x82ƂȂ\xC1\x82Ă\xA2\x82\xE9\x81B
-				pktsize += padding;
+				// \x88ȍ~\x82̏\x88\x97\x9D\x82\xCD pktsize \x82\xC9 padding_size \x82̒l\x82\xAA\x8A܂܂\xEA\x82Ă\xA2\x82鎖\x82\xAA\x91O\x92\xF1\x82ƂȂ\xC1\x82Ă\xA2\x82\xE9\x81B
+				pktsize += padding_size;
 			}
 
-			// \x83p\x83P\x83b\x83g(TCP\x83y\x83C\x83\x8D\x81[\x83h)\x82̑S\x91̂̃T\x83C\x83Y\x82́ASSH\x83y\x83C\x83\x8D\x81[\x83h+4\x81i+MAC\x81j\x82ƂȂ\xE9\x81B
-			// +4\x82́ASSH\x83y\x83C\x83\x8D\x81[\x83h\x82̃T\x83C\x83Y\x82\xF0\x8Ai\x94[\x82\xB5\x82Ă\xA2\x82镔\x95\xAA\x81iint\x8C^\x81j\x81B
-			total_packet_size = pktsize + 4 + SSH_get_authdata_size(pvar, MODE_IN);
+			// \x83p\x83P\x83b\x83g(TCP\x83y\x83C\x83\x8D\x81[\x83h)\x82̑S\x91̂̃T\x83C\x83Y\x82́A
+			// 4\x81i\x83p\x83P\x83b\x83g\x92\xB7\x82̃T\x83C\x83Y\x81j+\x83p\x83P\x83b\x83g\x92\xB7\x81i+MAC\x82̃T\x83C\x83Y\x81j\x82ƂȂ\xE9\x81B
+			total_packet_size = 4 + pktsize + SSH_get_authdata_size(pvar, MODE_IN);
 
 			if (total_packet_size <= pvar->pkt_state.datalen) {
 				// \x8E\xF3\x90M\x8Dς݃f\x81[\x83^\x82\xAA\x8F\\x95\xAA\x97L\x82\xE9\x8Fꍇ\x82̓p\x83P\x83b\x83g\x82̎\xC0\x8F\x88\x97\x9D\x82\xF0\x8Ds\x82\xA4
 				if (SSHv1(pvar)) {
 					// SSH1 \x82\xCD EtM \x94\xF1\x91Ή\x9E (\x82\xBB\x82\xE0\x82\xBB\x82\xE0 MAC \x82ł͂Ȃ\xAD CRC \x82\xF0\x8Eg\x82\xA4)
-					SSH1_handle_packet(pvar, data, pktsize, padding);
+					SSH1_handle_packet(pvar, data, pktsize, padding_size);
 				}
 				else {
 					// SSH2 \x82ł͂\xB1\x82̎\x9E\x93_\x82ł\xCD padding \x92\xB7\x95\x94\x95\xAA\x82\xAA\x95\x9C\x8D\x86\x82\xB3\x82\xEA\x82Ă\xA2\x82Ȃ\xA2\x8Fꍇ\x82\xAA\x82\xA0\x82\xE9\x82̂ŁA
 					// padding \x92\xB7\x82͓n\x82\xB3\x82\xB8\x82ɁA\x95K\x97v\x82ɂȂ\xC1\x82\xBD\x8E\x9E\x82ɓ\xE0\x95\x94\x82Ŏ擾\x82\xB7\x82\xE9\x81B
-					SSH2_handle_packet(pvar, data, pktsize, aadlen, enc->auth_len);
+					SSH2_handle_packet(pvar, data, pktsize, aadlen, authlen);
 				}
 
 				pvar->pkt_state.predecrypted_packet = FALSE;

Copied: branches/4-stable/ttssh2/ttxssh/poly1305.c (from rev 9252, branches/ssh_chacha20poly1305/ttssh2/ttxssh/poly1305.c)
===================================================================
--- branches/4-stable/ttssh2/ttxssh/poly1305.c	                        (rev 0)
+++ branches/4-stable/ttssh2/ttxssh/poly1305.c	2021-05-19 14:11:12 UTC (rev 9254)
@@ -0,0 +1,165 @@
+/* Imported from OpenSSH-8.5p1, TeraTerm Project */
+
+/* 
+ * Public Domain poly1305 from Andrew Moon
+ * poly1305-donna-unrolled.c from https://github.com/floodyberry/poly1305-donna
+ */
+
+/* $OpenBSD: poly1305.c,v 1.3 2013/12/19 22:57:13 djm Exp $ */
+
+// #include "includes.h"
+
+// for Visual Studio 2005
+#pragma warning(disable : 4244)
+
+#include <sys/types.h>
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+
+#include "poly1305.h"
+
+#define mul32x32_64(a,b) ((uint64_t)(a) * (b))
+
+#define U8TO32_LE(p) \
+	(((uint32_t)((p)[0])) | \
+	 ((uint32_t)((p)[1]) <<  8) | \
+	 ((uint32_t)((p)[2]) << 16) | \
+	 ((uint32_t)((p)[3]) << 24))
+
+#define U32TO8_LE(p, v) \
+	do { \
+		(p)[0] = (uint8_t)((v)); \
+		(p)[1] = (uint8_t)((v) >>  8); \
+		(p)[2] = (uint8_t)((v) >> 16); \
+		(p)[3] = (uint8_t)((v) >> 24); \
+	} while (0)
+
+void
+poly1305_auth(unsigned char out[POLY1305_TAGLEN], const unsigned char *m, size_t inlen, const unsigned char key[POLY1305_KEYLEN]) {
+	uint32_t t0,t1,t2,t3;
+	uint32_t h0,h1,h2,h3,h4;
+	uint32_t r0,r1,r2,r3,r4;
+	uint32_t s1,s2,s3,s4;
+	uint32_t b, nb;
+	size_t j;
+	uint64_t t[5];
+	uint64_t f0,f1,f2,f3;
+	uint32_t g0,g1,g2,g3,g4;
+	uint64_t c;
+	unsigned char mp[16];
+
+	/* clamp key */
+	t0 = U8TO32_LE(key+0);
+	t1 = U8TO32_LE(key+4);
+	t2 = U8TO32_LE(key+8);
+	t3 = U8TO32_LE(key+12);
+
+	/* precompute multipliers */
+	r0 = t0 & 0x3ffffff; t0 >>= 26; t0 |= t1 << 6;
+	r1 = t0 & 0x3ffff03; t1 >>= 20; t1 |= t2 << 12;
+	r2 = t1 & 0x3ffc0ff; t2 >>= 14; t2 |= t3 << 18;
+	r3 = t2 & 0x3f03fff; t3 >>= 8;
+	r4 = t3 & 0x00fffff;
+
+	s1 = r1 * 5;
+	s2 = r2 * 5;
+	s3 = r3 * 5;
+	s4 = r4 * 5;
+
+	/* init state */
+	h0 = 0;
+	h1 = 0;
+	h2 = 0;
+	h3 = 0;
+	h4 = 0;
+
+	/* full blocks */
+	if (inlen < 16) goto poly1305_donna_atmost15bytes;
+poly1305_donna_16bytes:
+	m += 16;
+	inlen -= 16;
+
+	t0 = U8TO32_LE(m-16);
+	t1 = U8TO32_LE(m-12);
+	t2 = U8TO32_LE(m-8);
+	t3 = U8TO32_LE(m-4);
+
+	h0 += t0 & 0x3ffffff;
+	h1 += ((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff;
+	h2 += ((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff;
+	h3 += ((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff;
+	h4 += (t3 >> 8) | (1 << 24);
+
+
+poly1305_donna_mul:
+	t[0]  = mul32x32_64(h0,r0) + mul32x32_64(h1,s4) + mul32x32_64(h2,s3) + mul32x32_64(h3,s2) + mul32x32_64(h4,s1);
+	t[1]  = mul32x32_64(h0,r1) + mul32x32_64(h1,r0) + mul32x32_64(h2,s4) + mul32x32_64(h3,s3) + mul32x32_64(h4,s2);
+	t[2]  = mul32x32_64(h0,r2) + mul32x32_64(h1,r1) + mul32x32_64(h2,r0) + mul32x32_64(h3,s4) + mul32x32_64(h4,s3);
+	t[3]  = mul32x32_64(h0,r3) + mul32x32_64(h1,r2) + mul32x32_64(h2,r1) + mul32x32_64(h3,r0) + mul32x32_64(h4,s4);
+	t[4]  = mul32x32_64(h0,r4) + mul32x32_64(h1,r3) + mul32x32_64(h2,r2) + mul32x32_64(h3,r1) + mul32x32_64(h4,r0);
+
+	                h0 = (uint32_t)t[0] & 0x3ffffff; c =           (t[0] >> 26);
+	t[1] += c;      h1 = (uint32_t)t[1] & 0x3ffffff; b = (uint32_t)(t[1] >> 26);
+	t[2] += b;      h2 = (uint32_t)t[2] & 0x3ffffff; b = (uint32_t)(t[2] >> 26);
+	t[3] += b;      h3 = (uint32_t)t[3] & 0x3ffffff; b = (uint32_t)(t[3] >> 26);
+	t[4] += b;      h4 = (uint32_t)t[4] & 0x3ffffff; b = (uint32_t)(t[4] >> 26);
+	h0 += b * 5;
+
+	if (inlen >= 16) goto poly1305_donna_16bytes;
+
+	/* final bytes */
+poly1305_donna_atmost15bytes:
+	if (!inlen) goto poly1305_donna_finish;
+
+	for (j = 0; j < inlen; j++) mp[j] = m[j];
+	mp[j++] = 1;
+	for (; j < 16; j++)	mp[j] = 0;
+	inlen = 0;
+
+	t0 = U8TO32_LE(mp+0);
+	t1 = U8TO32_LE(mp+4);
+	t2 = U8TO32_LE(mp+8);
+	t3 = U8TO32_LE(mp+12);
+
+	h0 += t0 & 0x3ffffff;
+	h1 += ((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff;
+	h2 += ((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff;
+	h3 += ((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff;
+	h4 += (t3 >> 8);
+
+	goto poly1305_donna_mul;
+
+poly1305_donna_finish:
+	             b = h0 >> 26; h0 = h0 & 0x3ffffff;
+	h1 +=     b; b = h1 >> 26; h1 = h1 & 0x3ffffff;
+	h2 +=     b; b = h2 >> 26; h2 = h2 & 0x3ffffff;
+	h3 +=     b; b = h3 >> 26; h3 = h3 & 0x3ffffff;
+	h4 +=     b; b = h4 >> 26; h4 = h4 & 0x3ffffff;
+	h0 += b * 5; b = h0 >> 26; h0 = h0 & 0x3ffffff;
+	h1 +=     b;
+
+	g0 = h0 + 5; b = g0 >> 26; g0 &= 0x3ffffff;
+	g1 = h1 + b; b = g1 >> 26; g1 &= 0x3ffffff;
+	g2 = h2 + b; b = g2 >> 26; g2 &= 0x3ffffff;
+	g3 = h3 + b; b = g3 >> 26; g3 &= 0x3ffffff;
+	g4 = h4 + b - (1 << 26);
+
+	b = (g4 >> 31) - 1;
+	nb = ~b;
+	h0 = (h0 & nb) | (g0 & b);
+	h1 = (h1 & nb) | (g1 & b);
+	h2 = (h2 & nb) | (g2 & b);
+	h3 = (h3 & nb) | (g3 & b);
+	h4 = (h4 & nb) | (g4 & b);
+
+	f0 = ((h0      ) | (h1 << 26)) + (uint64_t)U8TO32_LE(&key[16]);
+	f1 = ((h1 >>  6) | (h2 << 20)) + (uint64_t)U8TO32_LE(&key[20]);
+	f2 = ((h2 >> 12) | (h3 << 14)) + (uint64_t)U8TO32_LE(&key[24]);
+	f3 = ((h3 >> 18) | (h4 <<  8)) + (uint64_t)U8TO32_LE(&key[28]);
+
+	U32TO8_LE(&out[ 0], f0); f1 += (f0 >> 32);
+	U32TO8_LE(&out[ 4], f1); f2 += (f1 >> 32);
+	U32TO8_LE(&out[ 8], f2); f3 += (f2 >> 32);
+	U32TO8_LE(&out[12], f3);
+}

Copied: branches/4-stable/ttssh2/ttxssh/poly1305.h (from rev 9252, branches/ssh_chacha20poly1305/ttssh2/ttxssh/poly1305.h)
===================================================================
--- branches/4-stable/ttssh2/ttxssh/poly1305.h	                        (rev 0)
+++ branches/4-stable/ttssh2/ttxssh/poly1305.h	2021-05-19 14:11:12 UTC (rev 9254)
@@ -0,0 +1,26 @@
+/* Imported from OpenSSH-8.5p1, TeraTerm Project */
+
+/* $OpenBSD: poly1305.h,v 1.4 2014/05/02 03:27:54 djm Exp $ */
+
+/* 
+ * Public Domain poly1305 from Andrew Moon
+ * poly1305-donna-unrolled.c from https://github.com/floodyberry/poly1305-donna
+ */
+
+#ifndef POLY1305_H
+#define POLY1305_H
+
+#include <stdio.h>
+#include <sys/types.h>
+typedef unsigned char u_char;
+typedef unsigned char uint8_t;
+typedef unsigned int uint32_t;
+typedef unsigned long long uint64_t;
+
+#define POLY1305_KEYLEN		32
+#define POLY1305_TAGLEN		16
+
+void poly1305_auth(u_char out[POLY1305_TAGLEN], const u_char *m, size_t inlen,
+    const u_char key[POLY1305_KEYLEN]);
+
+#endif	/* POLY1305_H */

Modified: branches/4-stable/ttssh2/ttxssh/ssh.c
===================================================================
--- branches/4-stable/ttssh2/ttxssh/ssh.c	2021-05-19 14:05:07 UTC (rev 9253)
+++ branches/4-stable/ttssh2/ttxssh/ssh.c	2021-05-19 14:11:12 UTC (rev 9254)
@@ -931,6 +931,7 @@
  *   data - ssh \x83p\x83P\x83b\x83g\x82̐擪\x82\xF0\x8Ew\x82\xB7\x83|\x83C\x83\x93\x83^
  *   len - \x83p\x83P\x83b\x83g\x92\xB7 (\x90擪\x82̃p\x83P\x83b\x83g\x92\xB7\x97̈\xE6(4\x83o\x83C\x83g)\x82\xF0\x8F\x9C\x82\xA2\x82\xBD\x92l)
  *   aadlen - \x88Í\x86\x89\xBB\x82\xB3\x82\xEA\x82Ă\xA2\x82Ȃ\xA2\x82\xAA\x94F\x8F؂̑ΏۂƂȂ\xC1\x82Ă\xA2\x82\xE9\x83f\x81[\x83^\x82̒\xB7\x82\xB3
+ *            chacha20-poly1305 \x82ł͈Í\x86\x89\xBB\x82\xB3\x82\xEA\x82\xE9\x83p\x83P\x83b\x83g\x92\xB7\x95\x94\x95\xAA\x82̒\xB7\x82\xB3
  *   authlen - \x94F\x8F؃f\x81[\x83^(AEAD tag)\x92\xB7
  */
 
@@ -1175,8 +1176,9 @@
 		CRYPT_encrypt(pvar, data + 4, data_length - 4);
 	} else { //for SSH2(yutaka)
 		unsigned int block_size = CRYPT_get_encryption_block_size(pvar);
+		unsigned int packet_length;
 		unsigned int encryption_size;
-		unsigned int padding;
+		unsigned int padding_size;
 		BOOL ret;
 		struct Mac *mac = &pvar->ssh2_keys[MODE_OUT].mac;
 		struct Enc *enc = &pvar->ssh2_keys[MODE_OUT].enc;
@@ -1189,7 +1191,7 @@
 		         <--ignore---> ^^^^^^^^    <---- payload --->
 		                       packet length
 
-		                                ^^padding
+		                                ^^padding_size
 
 		                       <---------------------------->
 		                          SSH2 sending data on TCP
@@ -1238,32 +1240,37 @@
 		}
 
 		if (mac && mac->etm || authlen > 0) {
-			// \x88Í\x86\x89\xBB\x91Ώۂł͖\xB3\x82\xA2\x82\xAA\x81AMAC \x82̑ΏۂƂȂ镔\x95\xAA\x82̒\xB7\x82\xB3
+			// \x88Í\x86\x89\xBB\x91Ώۂł͂Ȃ\xA2\x82\xAA\x81AMAC \x82̑ΏۂƂȂ\xE9\x83p\x83P\x83b\x83g\x92\xB7\x95\x94\x95\xAA\x82̒\xB7\x82\xB3
+			// \x82܂\xBD\x82\xCD chacha20-poly1305 \x82ňÍ\x86\x89\xBB\x82\xB3\x82\xEA\x82\xE9\x83p\x83P\x83b\x83g\x92\xB7\x95\x94\x95\xAA\x82̒\xB7\x82\xB3
+			// cf. PKT_recv \x93\xE0\x82̃R\x83\x81\x83\x93\x83g
 			aadlen = 4;
 		}
 
-		encryption_size = 4 - aadlen + 1 + len;
-		padding = block_size - (encryption_size % block_size);
-		if (padding < 4)
-			padding += block_size;
-		encryption_size += padding;
-		set_uint32(data, encryption_size - 4 + aadlen);
-		data[4] = (unsigned char) padding;
+		packet_length = 1 + len; // \x83p\x83f\x83B\x83\x93\x83O\x92\xB7\x82̃T\x83C\x83Y + \x83y\x83C\x83\x8D\x81[\x83h\x92\xB7
+		encryption_size = 4 + packet_length - aadlen; // \x83p\x83P\x83b\x83g\x92\xB7\x82̃T\x83C\x83Y + packet_length - addlen
+		padding_size = block_size - (encryption_size % block_size);
+		if (padding_size < 4)
+			padding_size += block_size;
+		packet_length += padding_size;
+		encryption_size += padding_size;
+		set_uint32(data, packet_length);
+		data[4] = (unsigned char) padding_size;
 		if (msg) {
 			// \x83p\x83P\x83b\x83g\x88\xB3\x8Fk\x82̏ꍇ\x81A\x83o\x83b\x83t\x83@\x82\xF0\x8Ag\x92\xA3\x82\xB7\x82\xE9\x81B(2011.6.10 yutaka)
-			buffer_append_space(msg, padding + EVP_MAX_MD_SIZE);
+			buffer_append_space(msg, padding_size + EVP_MAX_MD_SIZE);
 			// realloc()\x82\xB3\x82\xEA\x82\xE9\x82ƁA\x83|\x83C\x83\x93\x83^\x82\xAA\x95ς\xED\x82\xE9\x89”\\x90\xAB\x82\xAA\x82\xA0\x82\xE9\x82̂ŁA\x8Dēx\x8E\xE6\x82蒼\x82\xB7\x81B
 			data = buffer_ptr(msg);
 		}
 
-		CRYPT_set_random_data(pvar, data + 5 + len, padding);
+		CRYPT_set_random_data(pvar, data + 5 + len, padding_size);
 
 		if (authlen > 0) {
+			// \x83p\x83P\x83b\x83g\x88Í\x86\x89\xBB\x82\xC6 MAC \x82̌v\x8EZ
 			CRYPT_encrypt_aead(pvar, data, encryption_size, aadlen, authlen);
 			maclen = authlen;
 		}
 		else if (aadlen) {
-			// \x83p\x83P\x83b\x83g\x88Í\x86\x89\xBB
+			// \x83p\x83P\x83b\x83g\x88Í\x86\x89\xBB\x81iaadlen\x82\xE6\x82\xE8\x8C\xE3\x82낾\x82\xAF\x81j
 			CRYPT_encrypt(pvar, data + aadlen, encryption_size);
 
 			// EtM \x82ł͈Í\x86\x89\xBB\x8C\xE3\x82\xC9 MAC \x82\xF0\x8Cv\x8EZ\x82\xB7\x82\xE9
@@ -1274,7 +1281,7 @@
 			}
 		}
 		else {
-			// E&M \x82ł͐\xE6\x82\xC9 MAC \x82\xF0\x8Cv\x8EZ\x82\xB7\x82\xE9
+			// E&M \x82ł͈Í\x86\x89\xBB\x91O\x82\xC9 MAC \x82\xF0\x8Cv\x8EZ\x82\xB7\x82\xE9
 			ret = CRYPT_build_sender_MAC(pvar, pvar->ssh_state.sender_sequence_number,
 			                             data, encryption_size, data + encryption_size);
 			if (ret) {
@@ -1288,9 +1295,12 @@
 		data_length = encryption_size + aadlen + maclen;
 
 		logprintf(150,
-				  "%s: built packet info: aadlen:%d, enclen:%d, padlen:%d, datalen:%d, maclen:%d, mode:%s",
-				  __FUNCTION__,
-				  aadlen, encryption_size, padding, data_length, maclen, aadlen ? "EtM" : "E&M");
+		          "%s: built packet info: "
+		          "aadlen:%d, enclen:%d, padlen:%d, datalen:%d, maclen:%d, "
+		          "Encrypt Mode:%s, MAC mode:%s",
+		          __FUNCTION__,
+		          aadlen, encryption_size, padding_size, data_length, maclen,
+		          authlen ? "AEAD" : "not AEAD", aadlen ? "EtM" : "E&M");
 	}
 
 	send_packet_blocking(pvar, data, data_length);
@@ -4339,239 +4349,6 @@
 #define write_buffer_file(buf,len) do_write_buffer_file(buf,len,__FILE__,__LINE__)
 
 
-//
-// general
-//
-
-int get_cipher_block_size(SSH2Cipher *cipher)
-{
-	int blocksize = 0;
-	
-	if (cipher) {
-		blocksize = cipher->block_size;
-	}
-
-	return max(blocksize, 8);
-}
-
-int get_cipher_key_len(SSH2Cipher *cipher)
-{
-	if (cipher) {
-		return cipher->key_len;
-	}
-	else {
-		return 0;
-	}
-}
-
-int get_cipher_discard_len(SSH2Cipher *cipher)
-{
-	if (cipher) {
-		return cipher->discard_len;
-	}
-	else {
-		return 0;
-	}
-}
-
-int get_cipher_iv_len(SSH2Cipher *cipher)
-{
-	if (cipher) {
-		if (cipher->iv_len != 0) {
-			return cipher->iv_len;
-		}
-		else {
-			return cipher->block_size;
-		}
-	}
-	else {
-		return 8; // block_size
-	}
-}
-
-int get_cipher_auth_len(SSH2Cipher *cipher)
-{
-	if (cipher) {
-		return cipher->auth_len;
-	}
-	else {
-		return 0;
-	}
-}
-
-// \x88Í\x86\x83A\x83\x8B\x83S\x83\x8A\x83Y\x83\x80\x96\xBC\x82\xA9\x82猟\x8D\x{142DC2}\xE9\x81B
-SSH2Cipher *get_cipher_by_name(char *name)
-{
-	SSH2Cipher *ptr = ssh2_ciphers;
-
-	if (name == NULL || name[0] == '\0')
-		return NULL;
-
-	while (ptr->name != NULL) {
-		if (strcmp(ptr->name, name) == 0) {
-			return ptr;
-		}
-		ptr++;
-	}
-
-	// not found.
-	return NULL;
-}
-
-static char * get_cipher_string(SSH2Cipher *cipher)
-{
-	if (cipher) {
-		return cipher->name;
-	}
-	else {
-		return "unknown";
-	}
-}
-
-const EVP_CIPHER* get_cipher_EVP_CIPHER(SSH2Cipher *cipher)
-{
-	if (cipher) {
-		return cipher->func();
-	}
-	else {
-		return EVP_enc_null();
-	}
-}
-
-char* get_kex_algorithm_name(kex_algorithm kextype)
-{
-	ssh2_kex_algorithm_t *ptr = ssh2_kex_algorithms;
-
-	while (ptr->name != NULL) {
-		if (kextype == ptr->kextype) {
-			return ptr->name;
-		}
-		ptr++;
-	}
-
-	// not found.
-	return "unknown";
-}
-
-const EVP_MD* get_kex_algorithm_EVP_MD(kex_algorithm kextype)
-{
-	ssh2_kex_algorithm_t *ptr = ssh2_kex_algorithms;
-
-	while (ptr->name != NULL) {
-		if (kextype == ptr->kextype) {
-			return ptr->evp_md();
-		}
-		ptr++;
-	}
-
-	// not found.
-	return EVP_md_null();
-}
-
-SSH2Mac *get_ssh2_mac(SSH2MacId id)
-{
-	SSH2Mac *ptr = ssh2_macs;
-
-	while (ptr->name != NULL) {
-		if (ptr->id == id) {
-			return ptr;
-		}
-		ptr++;
-	}
-
-	return NULL;
-}
-
-char* get_ssh2_mac_name(SSH2Mac *mac)
-{
-	if (mac) {
-		return mac->name;
-	}
-	else {
-		return "unknown";
-	}
-}
-
-char* get_ssh2_mac_name_by_id(SSH2MacId id)
-{
-	return get_ssh2_mac_name(get_ssh2_mac(id));
-}
-
-const EVP_MD* get_ssh2_mac_EVP_MD(SSH2Mac *mac)
-{
-	if (mac) {
-		return mac->evp_md();
-	}
-	else {
-		return EVP_md_null();
-	}
-}
-
-int get_ssh2_mac_truncatebits(SSH2Mac *mac)
-{
-	if (mac) {
-		return mac->truncatebits;
-	}
-	else {
-		return 0;
-	}
-}
-
-int get_ssh2_mac_etm(SSH2Mac *mac)
-{
-	if (mac) {
-		return mac->etm;
-	}
-	else {
-		return 0;
-	}
-}
-
-char* get_ssh2_comp_name(compression_type type)
-{
-	ssh2_comp_t *ptr = ssh2_comps;
-
-	while (ptr->name != NULL) {
-		if (type == ptr->type) {
-			return ptr->name;
-		}
-		ptr++;
-	}
-
-	// not found.
-	return "unknown";
-}
-
-char* get_ssh_keytype_name(ssh_keytype type)
-{
-	ssh2_host_key_t *ptr = ssh2_host_key;
-
-	while (ptr->name != NULL) {
-		if (type == ptr->type) {
-			return ptr->name;
-		}
-		ptr++;
-	}
-
-	// not found.
-	return "ssh-unknown";
-}
-
-char* get_digest_algorithm_name(digest_algorithm id)
-{
-	ssh_digest_t *ptr = ssh_digests;
-
-	while (ptr->name != NULL) {
-		if (id == ptr->id) {
-			return ptr->name;
-		}
-		ptr++;
-	}
-
-	// not found.
-	return "unknown";
-}
-
 static void do_write_buffer_file(void *buf, int len, char *file, int lineno)
 {
 	FILE *fp;
@@ -4599,248 +4376,6 @@
 	buffer_append(msg, buf, len);
 }
 
-// the caller is normalize_cipher_order()
-void SSH2_update_cipher_myproposal(PTInstVar pvar)
-{
-	static char buf[512]; // TODO: malloc()\x82ɂ\xB7\x82ׂ\xAB
-	int cipher;
-	int len, i;
-	char *c_str;
-
-	// \x92ʐM\x92\x86\x82ɂ͌Ă΂\xEA\x82Ȃ\xA2\x82͂\xB8\x82\xBE\x82\xAA\x81A\x94O\x82̂\xBD\x82߁B(2006.6.26 maya)
-	if (pvar->socket != INVALID_SOCKET) {
-		return;
-	}
-
-	// \x88Í\x86\x83A\x83\x8B\x83S\x83\x8A\x83Y\x83\x80\x97D\x90揇\x88ʂɉ\x9E\x82\xB6\x82āAmyproposal[]\x82\xF0\x8F\x91\x82\xAB\x8A\xB7\x82\xA6\x82\xE9\x81B(2004.11.6 yutaka)
-	buf[0] = '\0';
-	for (i = 0 ; pvar->settings.CipherOrder[i] != 0 ; i++) {
-		cipher = pvar->settings.CipherOrder[i] - '0';
-		if (cipher == 0) // disabled line
-			break;
-		switch (cipher) {
-			case SSH2_CIPHER_3DES_CBC:
-				c_str = "3des-cbc,";
-				break;
-			case SSH2_CIPHER_3DES_CTR:
-				c_str = "3des-ctr,";
-				break;
-			case SSH2_CIPHER_BLOWFISH_CBC:
-				c_str = "blowfish-cbc,";
-				break;
-			case SSH2_CIPHER_BLOWFISH_CTR:
-				c_str = "blowfish-ctr,";
-				break;
-			case SSH2_CIPHER_AES128_CBC:
-				c_str = "aes128-cbc,";
-				break;
-			case SSH2_CIPHER_AES192_CBC:
-				c_str = "aes192-cbc,";
-				break;
-			case SSH2_CIPHER_AES256_CBC:
-				c_str = "aes256-cbc,";
-				break;
-			case SSH2_CIPHER_AES128_CTR:
-				c_str = "aes128-ctr,";
-				break;
-			case SSH2_CIPHER_AES192_CTR:
-				c_str = "aes192-ctr,";
-				break;
-			case SSH2_CIPHER_AES256_CTR:
-				c_str = "aes256-ctr,";
-				break;
-			case SSH2_CIPHER_ARCFOUR:
-				c_str = "arcfour,";
-				break;
-			case SSH2_CIPHER_ARCFOUR128:
-				c_str = "arcfour128,";
-				break;
-			case SSH2_CIPHER_ARCFOUR256:
-				c_str = "arcfour256,";
-				break;
-			case SSH2_CIPHER_CAST128_CBC:
-				c_str = "cast128-cbc,";
-				break;
-			case SSH2_CIPHER_CAST128_CTR:
-				c_str = "cast128-ctr,";
-				break;
-#ifdef WITH_CAMELLIA_PRIVATE
-			case SSH2_CIPHER_CAMELLIA128_CBC:
-				c_str = "camellia128-cbc,camel****@opens*****,";
-				break;
-			case SSH2_CIPHER_CAMELLIA192_CBC:
-				c_str = "camellia192-cbc,camel****@opens*****,";
-				break;
-			case SSH2_CIPHER_CAMELLIA256_CBC:
-				c_str = "camellia256-cbc,camel****@opens*****,";
-				break;
-			case SSH2_CIPHER_CAMELLIA128_CTR:
-				c_str = "camellia128-ctr,camel****@opens*****,";
-				break;
-			case SSH2_CIPHER_CAMELLIA192_CTR:
-				c_str = "camellia192-ctr,camel****@opens*****,";
-				break;
-			case SSH2_CIPHER_CAMELLIA256_CTR:
-				c_str = "camellia256-ctr,camel****@opens*****,";
-				break;
-#endif // WITH_CAMELLIA_PRIVATE
-			case SSH2_CIPHER_CAMELLIA128_CBC:
-				c_str = "camellia128-cbc,";
-				break;
-			case SSH2_CIPHER_CAMELLIA192_CBC:
-				c_str = "camellia192-cbc,";
-				break;
-			case SSH2_CIPHER_CAMELLIA256_CBC:
-				c_str = "camellia256-cbc,";
-				break;
-			case SSH2_CIPHER_CAMELLIA128_CTR:
-				c_str = "camellia128-ctr,";
-				break;
-			case SSH2_CIPHER_CAMELLIA192_CTR:
-				c_str = "camellia192-ctr,";
-				break;
-			case SSH2_CIPHER_CAMELLIA256_CTR:
-				c_str = "camellia256-ctr,";
-				break;
-			case SSH2_CIPHER_AES128_GCM:
-				c_str = "aes12****@opens*****,";
-				break;
-			case SSH2_CIPHER_AES256_GCM:
-				c_str = "aes25****@opens*****,";
-				break;
-			default:
-				continue;
-		}
-		strncat_s(buf, sizeof(buf), c_str, _TRUNCATE);
-	}
-	len = strlen(buf);
-	if (len > 0)
-		buf[len - 1] = '\0';  // get rid of comma
-	myproposal[PROPOSAL_ENC_ALGS_CTOS] = buf;  // Client To Server
-	myproposal[PROPOSAL_ENC_ALGS_STOC] = buf;  // Server To Client
-}
-
-
-void SSH2_update_compression_myproposal(PTInstVar pvar)
-{
-	static char buf[128]; // TODO: malloc()\x82ɂ\xB7\x82ׂ\xAB
-	int index;
-	int len, i;
-
-	// \x92ʐM\x92\x86\x82ɂ͌Ă΂\xEA\x82Ȃ\xA2\x82͂\xB8\x82\xBE\x82\xAA\x81A\x94O\x82̂\xBD\x82߁B(2006.6.26 maya)
-	if (pvar->socket != INVALID_SOCKET) {
-		return;
-	}
-
-	// \x88\xB3\x8Fk\x83\x8C\x83x\x83\x8B\x82ɉ\x9E\x82\xB6\x82āAmyproposal[]\x82\xF0\x8F\x91\x82\xAB\x8A\xB7\x82\xA6\x82\xE9\x81B(2005.7.9 yutaka)
-	buf[0] = '\0';
-	for (i = 0 ; pvar->settings.CompOrder[i] != 0 ; i++) {
-		index = pvar->settings.CompOrder[i] - '0';
-		if (index == COMP_NONE) // disabled line
-			break;
-		strncat_s(buf, sizeof(buf), get_ssh2_comp_name(index), _TRUNCATE);
-		strncat_s(buf, sizeof(buf), ",", _TRUNCATE);
-	}
-	len = strlen(buf);
-	if (len > 0)
-		buf[len - 1] = '\0';  // get rid of comma
-
-	// \x88\xB3\x8Fk\x8Ew\x92肪\x82Ȃ\xA2\x8Fꍇ\x82́A\x88\xB3\x8Fk\x83\x8C\x83x\x83\x8B\x82𖳏\xF0\x8C\x8F\x82Ƀ[\x83\x8D\x82ɂ\xB7\x82\xE9\x81B
-	if (buf[0] == '\0') {
-		pvar->settings.CompressionLevel = 0;
-	}
-
-	if (pvar->settings.CompressionLevel == 0) {
-		_snprintf_s(buf, sizeof(buf), _TRUNCATE, get_ssh2_comp_name(COMP_NOCOMP));
-	}
-	if (buf[0] != '\0') {
-		myproposal[PROPOSAL_COMP_ALGS_CTOS] = buf;  // Client To Server
-		myproposal[PROPOSAL_COMP_ALGS_STOC] = buf;  // Server To Client
-	}
-}
-
-// KEX\x83A\x83\x8B\x83S\x83\x8A\x83Y\x83\x80\x97D\x90揇\x88ʂɉ\x9E\x82\xB6\x82āAmyproposal[]\x82\xF0\x8F\x91\x82\xAB\x8A\xB7\x82\xA6\x82\xE9\x81B
-// (2011.2.28 yutaka)
-void SSH2_update_kex_myproposal(PTInstVar pvar)
-{
-	static char buf[512]; // TODO: malloc()\x82ɂ\xB7\x82ׂ\xAB
-	int index;
-	int len, i;
-
-	// \x92ʐM\x92\x86\x82ɂ͌Ă΂\xEA\x82Ȃ\xA2\x82͂\xB8\x82\xBE\x82\xAA\x81A\x94O\x82̂\xBD\x82߁B(2006.6.26 maya)
-	if (pvar->socket != INVALID_SOCKET) {
-		return;
-	}
-
-	buf[0] = '\0';
-	for (i = 0 ; pvar->settings.KexOrder[i] != 0 ; i++) {
-		index = pvar->settings.KexOrder[i] - '0';
-		if (index == KEX_DH_NONE) // disabled line
-			break;
-		strncat_s(buf, sizeof(buf), get_kex_algorithm_name(index), _TRUNCATE);
-		strncat_s(buf, sizeof(buf), ",", _TRUNCATE);
-	}
-	len = strlen(buf);
-	if (len > 0)
-		buf[len - 1] = '\0';  // get rid of comma
-	myproposal[PROPOSAL_KEX_ALGS] = buf; 
-}
-
-// Host Key\x83A\x83\x8B\x83S\x83\x8A\x83Y\x83\x80\x97D\x90揇\x88ʂɉ\x9E\x82\xB6\x82āAmyproposal[]\x82\xF0\x8F\x91\x82\xAB\x8A\xB7\x82\xA6\x82\xE9\x81B
-// (2011.2.28 yutaka)
-void SSH2_update_host_key_myproposal(PTInstVar pvar)
-{
-	static char buf[256]; // TODO: malloc()\x82ɂ\xB7\x82ׂ\xAB
-	int index;
-	int len, i;
-
-	// \x92ʐM\x92\x86\x82ɂ͌Ă΂\xEA\x82Ȃ\xA2\x82͂\xB8\x82\xBE\x82\xAA\x81A\x94O\x82̂\xBD\x82߁B(2006.6.26 maya)
-	if (pvar->socket != INVALID_SOCKET) {
-		return;
-	}
-
-	buf[0] = '\0';
-	for (i = 0 ; pvar->settings.HostKeyOrder[i] != 0 ; i++) {
-		index = pvar->settings.HostKeyOrder[i] - '0';
-		if (index == KEY_NONE) // disabled line
-			break;
-		strncat_s(buf, sizeof(buf), get_ssh_keytype_name(index), _TRUNCATE);
-		strncat_s(buf, sizeof(buf), ",", _TRUNCATE);
-	}
-	len = strlen(buf);
-	if (len > 0)
-		buf[len - 1] = '\0';  // get rid of comma
-	myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = buf; 
-}
-
-// HMAC\x83A\x83\x8B\x83S\x83\x8A\x83Y\x83\x80\x97D\x90揇\x88ʂɉ\x9E\x82\xB6\x82āAmyproposal[]\x82\xF0\x8F\x91\x82\xAB\x8A\xB7\x82\xA6\x82\xE9\x81B
-// (2011.2.28 yutaka)
-void SSH2_update_hmac_myproposal(PTInstVar pvar)
-{
-	static char buf[256]; // TODO: malloc()\x82ɂ\xB7\x82ׂ\xAB
-	int index;
-	int len, i;
-
-	// \x92ʐM\x92\x86\x82ɂ͌Ă΂\xEA\x82Ȃ\xA2\x82͂\xB8\x82\xBE\x82\xAA\x81A\x94O\x82̂\xBD\x82߁B(2006.6.26 maya)
-	if (pvar->socket != INVALID_SOCKET) {
-		return;
-	}
-
-	buf[0] = '\0';
-	for (i = 0 ; pvar->settings.MacOrder[i] != 0 ; i++) {
-		index = pvar->settings.MacOrder[i] - '0';
-		if (index == HMAC_NONE) // disabled line
-			break;
-		strncat_s(buf, sizeof(buf), get_ssh2_mac_name_by_id(index), _TRUNCATE);
-		strncat_s(buf, sizeof(buf), ",", _TRUNCATE);
-	}
-	len = strlen(buf);
-	if (len > 0)
-		buf[len - 1] = '\0';  // get rid of comma
-	myproposal[PROPOSAL_MAC_ALGS_CTOS] = buf; 
-	myproposal[PROPOSAL_MAC_ALGS_STOC] = buf; 
-}
-
 // \x83N\x83\x89\x83C\x83A\x83\x93\x83g\x82\xA9\x82\xE7\x83T\x81[\x83o\x82ւ̃L\x81[\x8C\xF0\x8A\xB7\x8AJ\x8En\x97v\x8B\x81
 void SSH2_send_kexinit(PTInstVar pvar)
 {
@@ -4920,11 +4455,99 @@
 }
 
 
-static void choose_SSH2_proposal(char *server_proposal,
-                                 char *my_proposal,
-                                 char *dest,
-                                 int dest_len)
+void normalize_generic_order(char *buf, char default_strings[], int default_strings_len)
 {
+	char listed[max(KEX_DH_MAX,max(SSH_CIPHER_MAX,max(KEY_MAX,max(HMAC_MAX,COMP_MAX)))) + 1];
+	char allowed[max(KEX_DH_MAX,max(SSH_CIPHER_MAX,max(KEY_MAX,max(HMAC_MAX,COMP_MAX)))) + 1];
+	int i, j, k=-1;
+
+	memset(listed, 0, sizeof(listed));
+	memset(allowed, 0, sizeof(allowed));
+
+	// \x8B\x96\x89‚\xB3\x82\xEA\x82Ă\xA2\x82镶\x8E\x9A\x82̃\x8A\x83X\x83g\x82\xF0\x8D\xEC\x82\xE9\x81B
+	for (i = 0; i < default_strings_len ; i++) {
+		allowed[default_strings[i]] = 1;
+	}
+
+	// \x8Ew\x92肳\x82ꂽ\x95\xB6\x8E\x9A\x97\xF1\x82𑖍\xB8\x82\xB5\x81A\x8B\x96\x89‚\xB3\x82\xEA\x82Ă\xA2\x82Ȃ\xA2\x95\xB6\x8E\x9A\x81A\x8Fd\x95\xA1\x82\xB7\x82镶\x8E\x9A\x82͍폜\x82\xB7\x82\xE9\x81B
+	// 
+	// ex. (i=5 \x82̕\xB6\x8E\x9A\x82\xF0\x8D폜\x82\xB7\x82\xE9)
+	// i=012345
+	//   >:=9<87;A@?B3026(\0)
+	//         i+1
+	//         <------------>
+	//       \x81\xAB
+	//   >:=9<7;A@?B3026(\0)
+	//         
+	for (i = 0; buf[i] != 0; i++) {
+		int num = buf[i] - '0';
+
+		if (num < 0 || num > default_strings_len
+			|| !allowed[num]
+			|| listed[num]) {
+			memmove(buf + i, buf + i + 1, strlen(buf + i + 1) + 1);
+			i--;
+		} else {
+			listed[num] = 1;
+		}
+
+		// disabled line\x82\xAA\x82\xA0\x82\xEA\x82΁A\x88ʒu\x82\xF0\x8Ao\x82\xA6\x82Ă\xA8\x82\xAD\x81B
+		if (num == 0) {
+			k = i;
+		}
+	}
+
+	// \x8Ew\x92肳\x82\xEA\x82Ă\xA2\x82Ȃ\xA2\x95\xB6\x8E\x9A\x82\xAA\x82\xA0\x82\xEA\x82΁Adisabled line\x82̒\xBC\x91O\x82ɑ}\x93\xFC\x82\xB7\x82\xE9\x81B
+	// 
+	// ex. (Z\x82\xF0\x91}\x93\xFC\x82\xB7\x82\xE9)
+	//                k
+	//   >:=9<87;A@?B3026(\0)
+	//                 k+1
+	//                 <---->
+	//       \x81\xAB       k
+	//   >:=9<87;A@?B30026(\0)
+	//       \x81\xAB        k
+	//   >:=9<87;A@?B3Z026(\0)
+	//       
+	for (j = 0; j < default_strings_len && default_strings[j] != 0; j++) {
+		int num = default_strings[j];
+
+		if (!listed[num] && k >= 0) {
+			int copylen = strlen(buf + k + 1) + 1;
+
+			memmove(buf + k + 1, buf + k, copylen);
+			buf[k + 1 + copylen] = '\0';   // \x8FI\x92[\x82\xF0\x96Y\x82ꂸ\x82ɕt\x82\xAF\x82\xE9\x81B
+			buf[k] = num + '0';
+			k++;
+			i++;
+		}
+	}
+	if (k < 0) {
+		j = 0;
+	}
+	else {
+		j++;
+	}
+
+	// disabled line\x82\xAA\x91\xB6\x8D݂\xB5\x82Ȃ\xA2\x8Fꍇ\x82́A\x82\xBB\x82̂܂ܖ\x96\x94\xF6\x82ɒlj\xC1\x82\xB7\x82\xE9\x81B
+	for (; j < default_strings_len ; j++) {
+		int num = default_strings[j];
+
+		if (!listed[num]) {
+			buf[i] = num + '0';
+			listed[num] = 1;
+			i++;
+		}
+	}
+
+	buf[i] = 0;
+}
+
+void choose_SSH2_proposal(char *server_proposal,
+                          char *my_proposal,
+                          char *dest,
+                          int dest_len)
+{
 	char tmp_cli[1024], *ptr_cli, *ctc_cli;
 	char tmp_svr[1024], *ptr_svr, *ctc_svr;
 
@@ -4952,79 +4575,6 @@
 	}
 }
 
-static kex_algorithm choose_SSH2_kex_algorithm(char *server_proposal, char *my_proposal)
-{
-	kex_algorithm type = KEX_DH_UNKNOWN;
-	char str_kextype[40];
-	ssh2_kex_algorithm_t *ptr = ssh2_kex_algorithms;
-
-	choose_SSH2_proposal(server_proposal, my_proposal, str_kextype, sizeof(str_kextype));
-
-	while (ptr->name != NULL) {
-		if (strcmp(ptr->name, str_kextype) == 0) {
-			type = ptr->kextype;
-			break;
-		}
-		ptr++;
-	}
-
-	return (type);
-}
-
-static SSH2Cipher *choose_SSH2_cipher_algorithm(char *server_proposal, char *my_proposal)
-{
-	char str_cipher[32];
-	SSH2Cipher *ptr = ssh2_ciphers;
-
-	choose_SSH2_proposal(server_proposal, my_proposal, str_cipher, sizeof(str_cipher));
-	return get_cipher_by_name(str_cipher);
-}
-
-
-static SSH2Mac *choose_SSH2_mac_algorithm(char *server_proposal, char *my_proposal)
-{
-	char str_hmac[64];
-	SSH2Mac *ptr = ssh2_macs;
-
-	choose_SSH2_proposal(server_proposal, my_proposal, str_hmac, sizeof(str_hmac));
-
-	while (ptr->name != NULL) {
-		if (strcmp(ptr->name, str_hmac) == 0) {
-			return ptr;
-		}
-		ptr++;
-	}
-
-	return (NULL);
-}
-
-
-static compression_type choose_SSH2_compression_algorithm(char *server_proposal, char *my_proposal)
-{
-	compression_type type = COMP_UNKNOWN;
-	char str_comp[20];
-	ssh2_comp_t *ptr = ssh2_comps;
-
-	// OpenSSH 4.3\x82ł͒x\x89\x84\x83p\x83P\x83b\x83g\x88\xB3\x8Fk("zlib****@opens*****")\x82\xAA\x90V\x8BK\x92lj\xC1\x82\xB3\x82\xEA\x82Ă\xA2\x82邽\x82߁A
-	// \x83}\x83b\x83`\x82\xB5\x82Ȃ\xA2\x82悤\x82ɏC\x90\xB3\x82\xB5\x82\xBD\x81B
-	// \x8C\xBBTera Term\x82ł͒x\x89\x84\x83p\x83P\x83b\x83g\x88\xB3\x8Fk\x82͏\xAB\x97\x88\x93I\x82ɃT\x83|\x81[\x83g\x82\xB7\x82\xE9\x97\\x92\xE8\x81B
-	// (2006.6.14 yutaka)
-	// \x92x\x89\x84\x83p\x83P\x83b\x83g\x88\xB3\x8Fk\x82ɑΉ\x9E\x81B
-	// (2006.6.23 maya)
-
-	choose_SSH2_proposal(server_proposal, my_proposal, str_comp, sizeof(str_comp));
-
-	while (ptr->name != NULL) {
-		if (strcmp(ptr->name, str_comp) == 0) {
-			type = ptr->type;
-			break;
-		}
-		ptr++;
-	}
-
-	return (type);
-}
-
 // \x88Í\x86\x83A\x83\x8B\x83S\x83\x8A\x83Y\x83\x80\x82̃L\x81[\x83T\x83C\x83Y\x81A\x83u\x83\x8D\x83b\x83N\x83T\x83C\x83Y\x81AMAC\x83T\x83C\x83Y\x82̂\xA4\x82\xBF\x8Dő\xE5\x92l(we_need)\x82\xF0\x8C\x88\x92肷\x82\xE9\x81B
 static void choose_SSH2_key_maxlength(PTInstVar pvar)
 {
@@ -5031,8 +4581,8 @@
 	int mode, val;
 	unsigned int need = 0;
 	const EVP_MD *md;
-	SSH2Cipher *cipher;
-	SSH2Mac *mac;
+	const struct ssh2cipher *cipher;
+	const struct SSH2Mac *mac;
 
 	for (mode = 0; mode < MODE_MAX; mode++) {
 		cipher = pvar->ciphers[mode];
@@ -5097,7 +4647,6 @@
 	int len, size;
 	char *msg = NULL;
 	char tmp[1024+512];
-	char str_keytype[20];
 
 	logputs(LOG_LEVEL_VERBOSE, "SSH2_MSG_KEXINIT was received.");
 
@@ -5181,15 +4730,7 @@
 
 	logprintf(LOG_LEVEL_VERBOSE, "server proposal: server host key algorithm: %s", buf);
 
-	pvar->hostkey_type = KEY_UNSPEC;
-	choose_SSH2_proposal(buf, myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], str_keytype, sizeof(str_keytype));
-	if (strlen(str_keytype) == 0) { // not match
-		strncpy_s(tmp, sizeof(tmp), "unknown host KEY type: ", _TRUNCATE);
-		strncat_s(tmp, sizeof(tmp), buf, _TRUNCATE);
-		msg = tmp;
-		goto error;
-	}
-	pvar->hostkey_type = get_keytype_from_name(str_keytype);
+	pvar->hostkey_type = choose_SSH2_host_key_algorithm(buf, myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]);
 	if (pvar->hostkey_type == KEY_UNSPEC) {
 		strncpy_s(tmp, sizeof(tmp), "unknown host KEY type: ", _TRUNCATE);
 		strncat_s(tmp, sizeof(tmp), buf, _TRUNCATE);
@@ -5255,7 +4796,7 @@
 
 	logprintf(LOG_LEVEL_VERBOSE, "server proposal: MAC algorithm client to server: %s", buf);
 
-	if (pvar->ciphers[MODE_OUT]->auth_len > 0) {
+	if (get_cipher_auth_len(pvar->ciphers[MODE_OUT]) > 0) {
 		logputs(LOG_LEVEL_VERBOSE, "AEAD cipher is selected, ignoring MAC algorithms. (client to server)");
 		pvar->macs[MODE_OUT] = get_ssh2_mac(HMAC_IMPLICIT);
 	}
@@ -5283,7 +4824,7 @@
 
 	logprintf(LOG_LEVEL_VERBOSE, "server proposal: MAC algorithm server to client: %s", buf);
 
-	if (pvar->ciphers[MODE_IN]->auth_len > 0) {
+	if (get_cipher_auth_len(pvar->ciphers[MODE_IN]) > 0) {
 		logputs(LOG_LEVEL_VERBOSE, "AEAD cipher is selected, ignoring MAC algorithms. (server to client)");
 		pvar->macs[MODE_IN] = get_ssh2_mac(HMAC_IMPLICIT);
 	}
@@ -5400,7 +4941,7 @@
 		get_kex_algorithm_name(pvar->kex_type));
 
 	logprintf(LOG_LEVEL_VERBOSE, "server host key algorithm: %s",
-		get_ssh_keytype_name(pvar->hostkey_type));
+		get_ssh2_hostkey_type_name(pvar->hostkey_type));
 
 	logprintf(LOG_LEVEL_VERBOSE, "encryption algorithm client to server: %s",
 		get_cipher_string(pvar->ciphers[MODE_OUT]));
@@ -6028,7 +5569,7 @@
 	if (hostkey->type != pvar->hostkey_type) {  // \x83z\x83X\x83g\x83L\x81[\x82̎\xED\x95ʔ\xE4\x8Ar
 		_snprintf_s(emsg_tmp, sizeof(emsg_tmp), _TRUNCATE,
 		            "%s: type mismatch for decoded server_host_key_blob (kex:%s blob:%s)", /*__FUNCTION__*/"handle_SSH2_dh_kex_reply",
-		            get_ssh_keytype_name(pvar->hostkey_type), get_ssh_keytype_name(hostkey->type));
+		            get_ssh2_hostkey_type_name(pvar->hostkey_type), get_ssh2_hostkey_type_name(hostkey->type));
 		emsg = emsg_tmp;
 		goto error;
 	}
@@ -6130,7 +5671,7 @@
 	if (hostkey->type != pvar->hostkey_type) {  // \x83z\x83X\x83g\x83L\x81[\x82̎\xED\x95ʔ\xE4\x8Ar
 		_snprintf_s(emsg_tmp, sizeof(emsg_tmp), _TRUNCATE,
 		            "%s: type mismatch for decoded server_host_key_blob (kex:%s blob:%s)", /*__FUNCTION__*/"handle_SSH2_dh_kex_reply",
-		            get_ssh_keytype_name(pvar->hostkey_type), get_ssh_keytype_name(hostkey->type));
+		            get_ssh2_hostkey_type_name(pvar->hostkey_type), get_ssh2_hostkey_type_name(hostkey->type));
 		emsg = emsg_tmp;
 		goto error;
 	}
@@ -6293,7 +5834,7 @@
 	if (hostkey->type != pvar->hostkey_type) {  // \x83z\x83X\x83g\x83L\x81[\x82̎\xED\x95ʔ\xE4\x8Ar
 		_snprintf_s(emsg_tmp, sizeof(emsg_tmp), _TRUNCATE,
 		            "%s: type mismatch for decoded server_host_key_blob (kex:%s blob:%s)", /*__FUNCTION__*/"handle_SSH2_dh_gex_reply",
-		            get_ssh_keytype_name(pvar->hostkey_type), get_ssh_keytype_name(hostkey->type));
+		            get_ssh2_hostkey_type_name(pvar->hostkey_type), get_ssh2_hostkey_type_name(hostkey->type));
 		emsg = emsg_tmp;
 		goto error;
 	}
@@ -6402,7 +5943,7 @@
 	if (hostkey->type != pvar->hostkey_type) {  // \x83z\x83X\x83g\x83L\x81[\x82̎\xED\x95ʔ\xE4\x8Ar
 		_snprintf_s(emsg_tmp, sizeof(emsg_tmp), _TRUNCATE,
 		            "%s: type mismatch for decoded server_host_key_blob (kex:%s blob:%s)", /*__FUNCTION__*/"handle_SSH2_dh_gex_reply",
-		            get_ssh_keytype_name(pvar->hostkey_type), get_ssh_keytype_name(hostkey->type));
+		            get_ssh2_hostkey_type_name(pvar->hostkey_type), get_ssh2_hostkey_type_name(hostkey->type));
 		emsg = emsg_tmp;
 		goto error;
 	}
@@ -6566,7 +6107,7 @@
 	if (hostkey->type != pvar->hostkey_type) {  // \x83z\x83X\x83g\x83L\x81[\x82̎\xED\x95ʔ\xE4\x8Ar
 		_snprintf_s(emsg_tmp, sizeof(emsg_tmp), _TRUNCATE,
 		            "%s: type mismatch for decoded server_host_key_blob (kex:%s blob:%s)", /*__FUNCTION__*/"handle_SSH2_ecdh_kex_reply",
-		            get_ssh_keytype_name(pvar->hostkey_type), get_ssh_keytype_name(hostkey->type));
+		            get_ssh2_hostkey_type_name(pvar->hostkey_type), get_ssh2_hostkey_type_name(hostkey->type));
 		emsg = emsg_tmp;
 		goto error;
 	}
@@ -6674,7 +6215,7 @@
 	if (hostkey->type != pvar->hostkey_type) {  // \x83z\x83X\x83g\x83L\x81[\x82̎\xED\x95ʔ\xE4\x8Ar
 		_snprintf_s(emsg_tmp, sizeof(emsg_tmp), _TRUNCATE,
 		            "%s: type mismatch for decoded server_host_key_blob (kex:%s blob:%s)", /*__FUNCTION__*/"handle_SSH2_ecdh_kex_reply",
-		            get_ssh_keytype_name(pvar->hostkey_type), get_ssh_keytype_name(hostkey->type));
+		            get_ssh2_hostkey_type_name(pvar->hostkey_type), get_ssh2_hostkey_type_name(hostkey->type));
 		emsg = emsg_tmp;
 		goto error;
 	}
@@ -6867,6 +6408,7 @@
 	                       | 1 << SSH2_CIPHER_CAMELLIA256_CTR
 	                       | 1 << SSH2_CIPHER_AES128_GCM
 	                       | 1 << SSH2_CIPHER_AES256_GCM
+	                       | 1 << SSH2_CIPHER_CHACHAPOLY
 	);
 	int type = (1 << SSH_AUTH_PASSWORD) | (1 << SSH_AUTH_RSA) |
 	           (1 << SSH_AUTH_TIS) | (1 << SSH_AUTH_PAGEANT);
@@ -7091,7 +6633,7 @@
 		s = "publickey";
 		buffer_put_string(signbuf, s, strlen(s));
 		buffer_put_char(signbuf, 1); // true
-		s = get_sshname_from_key(keypair); // key type\x82ɉ\x9E\x82\xB6\x82\xBD\x95\xB6\x8E\x9A\x97\xF1\x82𓾂\xE9
+		s = get_ssh2_hostkey_type_name_from_key(keypair); // key type\x82ɉ\x9E\x82\xB6\x82\xBD\x95\xB6\x8E\x9A\x97\xF1\x82𓾂\xE9
 		buffer_put_string(signbuf, s, strlen(s));
 		s = buffer_ptr(blob);
 		buffer_append_length(signbuf, s, bloblen);
@@ -7109,7 +6651,7 @@
 		s = "publickey";
 		buffer_put_string(msg, s, strlen(s));
 		buffer_put_char(msg, 1); // true
-		s = get_sshname_from_key(keypair); // key type\x82ɉ\x9E\x82\xB6\x82\xBD\x95\xB6\x8E\x9A\x97\xF1\x82𓾂\xE9
+		s = get_ssh2_hostkey_type_name_from_key(keypair); // key type\x82ɉ\x9E\x82\xB6\x82\xBD\x95\xB6\x8E\x9A\x97\xF1\x82𓾂\xE9
 		buffer_put_string(msg, s, strlen(s));
 		s = buffer_ptr(blob);
 		buffer_append_length(msg, s, bloblen);

Modified: branches/4-stable/ttssh2/ttxssh/ssh.h
===================================================================
--- branches/4-stable/ttssh2/ttxssh/ssh.h	2021-05-19 14:05:07 UTC (rev 9253)
+++ branches/4-stable/ttssh2/ttxssh/ssh.h	2021-05-19 14:11:12 UTC (rev 9254)
@@ -40,6 +40,10 @@
 
 #include "buffer.h"
 #include "config.h"
+#include "cipher.h"
+#include "hostkey.h"
+#include "mac.h"
+#include "comp.h"
 #include <sys/types.h>
 #include <sys/stat.h>
 
@@ -82,24 +86,6 @@
 } SSHMessage;
 
 typedef enum {
-	// SSH1
-	SSH_CIPHER_NONE, SSH_CIPHER_IDEA, SSH_CIPHER_DES, SSH_CIPHER_3DES,
-	SSH_CIPHER_TSS, SSH_CIPHER_RC4, SSH_CIPHER_BLOWFISH,
-	// SSH2
-	SSH2_CIPHER_3DES_CBC, SSH2_CIPHER_AES128_CBC,
-	SSH2_CIPHER_AES192_CBC, SSH2_CIPHER_AES256_CBC,
-	SSH2_CIPHER_BLOWFISH_CBC, SSH2_CIPHER_AES128_CTR,
-	SSH2_CIPHER_AES192_CTR, SSH2_CIPHER_AES256_CTR,
-	SSH2_CIPHER_ARCFOUR, SSH2_CIPHER_ARCFOUR128, SSH2_CIPHER_ARCFOUR256,
-	SSH2_CIPHER_CAST128_CBC,
-	SSH2_CIPHER_3DES_CTR, SSH2_CIPHER_BLOWFISH_CTR, SSH2_CIPHER_CAST128_CTR,
-	SSH2_CIPHER_CAMELLIA128_CBC, SSH2_CIPHER_CAMELLIA192_CBC, SSH2_CIPHER_CAMELLIA256_CBC,
-	SSH2_CIPHER_CAMELLIA128_CTR, SSH2_CIPHER_CAMELLIA192_CTR, SSH2_CIPHER_CAMELLIA256_CTR,
-	SSH2_CIPHER_AES128_GCM, SSH2_CIPHER_AES256_GCM,
-	SSH_CIPHER_MAX = SSH2_CIPHER_AES256_GCM,
-} SSHCipherId;
-
-typedef enum {
 	SSH_AUTH_NONE, SSH_AUTH_RHOSTS, SSH_AUTH_RSA, SSH_AUTH_PASSWORD,
 	SSH_AUTH_RHOSTS_RSA, SSH_AUTH_TIS, SSH_AUTH_KERBEROS,
 	SSH_AUTH_PAGEANT = 16,
@@ -298,73 +284,8 @@
 } SSH2TTYMode;
 
 
-// \x83N\x83\x89\x83C\x83A\x83\x93\x83g\x82\xA9\x82\xE7\x83T\x81[\x83o\x82ւ̒\xF1\x88Ď\x96\x8D\x80
-enum kex_init_proposals {
-	PROPOSAL_KEX_ALGS,
-	PROPOSAL_SERVER_HOST_KEY_ALGS,
-	PROPOSAL_ENC_ALGS_CTOS,
-	PROPOSAL_ENC_ALGS_STOC,
-	PROPOSAL_MAC_ALGS_CTOS,
-	PROPOSAL_MAC_ALGS_STOC,
-	PROPOSAL_COMP_ALGS_CTOS,
-	PROPOSAL_COMP_ALGS_STOC,
-	PROPOSAL_LANG_CTOS,
-	PROPOSAL_LANG_STOC,
-	PROPOSAL_MAX
-};
-
-#define KEX_DEFAULT_KEX     ""
-#define KEX_DEFAULT_PK_ALG  ""
-#define KEX_DEFAULT_ENCRYPT ""
-#define KEX_DEFAULT_MAC     ""
-#define KEX_DEFAULT_COMP    ""
-#define KEX_DEFAULT_LANG    ""
-
-static char *myproposal[PROPOSAL_MAX] = {
-	KEX_DEFAULT_KEX,
-	KEX_DEFAULT_PK_ALG,
-	KEX_DEFAULT_ENCRYPT,
-	KEX_DEFAULT_ENCRYPT,
-	KEX_DEFAULT_MAC,
-	KEX_DEFAULT_MAC,
-	KEX_DEFAULT_COMP,
-	KEX_DEFAULT_COMP,
-	KEX_DEFAULT_LANG,
-	KEX_DEFAULT_LANG,
-};
-
-
-typedef enum {
-	KEY_NONE,
-	KEY_RSA1,
-	KEY_RSA,
-	KEY_DSA,
-	KEY_ECDSA256,
-	KEY_ECDSA384,
-	KEY_ECDSA521,
-	KEY_ED25519,
-	KEY_UNSPEC,
-	KEY_MAX = KEY_UNSPEC,
-} ssh_keytype;
 #define isFixedLengthKey(type)	((type) >= KEY_DSA && (type) <= KEY_ED25519)
 
-typedef struct ssh2_host_key {
-	ssh_keytype type;
-	char *name;
-} ssh2_host_key_t;
-
-static ssh2_host_key_t ssh2_host_key[] = {
-	{KEY_RSA1,     "ssh-rsa1"},            // for SSH1 only
-	{KEY_RSA,      "ssh-rsa"},             // RFC4253
-	{KEY_DSA,      "ssh-dss"},             // RFC4253
-	{KEY_ECDSA256, "ecdsa-sha2-nistp256"}, // RFC5656
-	{KEY_ECDSA384, "ecdsa-sha2-nistp384"}, // RFC5656
-	{KEY_ECDSA521, "ecdsa-sha2-nistp521"}, // RFC5656
-	{KEY_ED25519,  "ssh-ed25519"},         // draft-bjh21-ssh-ed25519-02
-	{KEY_UNSPEC,   "ssh-unknown"},
-	{KEY_NONE,     NULL},
-};
-
 /* Minimum modulus size (n) for RSA keys. */
 #define SSH_RSA_MINIMUM_MODULUS_SIZE    768
 
@@ -376,165 +297,6 @@
 #define SSH_KEYGEN_MAXIMUM_ROUNDS INT_MAX
 
 
-typedef struct ssh2_cipher {
-	SSHCipherId id;
-	char *name;
-	int block_size;
-	int key_len;
-	int discard_len;
-	int iv_len;
-	int auth_len;
-	const EVP_CIPHER *(*func)(void);
-} SSH2Cipher;
-
-static SSH2Cipher ssh2_ciphers[] = {
-	{SSH2_CIPHER_3DES_CBC,        "3des-cbc",         8, 24,    0, 0, 0, EVP_des_ede3_cbc},     // RFC4253
-	{SSH2_CIPHER_AES128_CBC,      "aes128-cbc",      16, 16,    0, 0, 0, EVP_aes_128_cbc},      // RFC4253
-	{SSH2_CIPHER_AES192_CBC,      "aes192-cbc",      16, 24,    0, 0, 0, EVP_aes_192_cbc},      // RFC4253
-	{SSH2_CIPHER_AES256_CBC,      "aes256-cbc",      16, 32,    0, 0, 0, EVP_aes_256_cbc},      // RFC4253
-	{SSH2_CIPHER_BLOWFISH_CBC,    "blowfish-cbc",     8, 16,    0, 0, 0, EVP_bf_cbc},           // RFC4253
-	{SSH2_CIPHER_AES128_CTR,      "aes128-ctr",      16, 16,    0, 0, 0, evp_aes_128_ctr},      // RFC4344
-	{SSH2_CIPHER_AES192_CTR,      "aes192-ctr",      16, 24,    0, 0, 0, evp_aes_128_ctr},      // RFC4344
-	{SSH2_CIPHER_AES256_CTR,      "aes256-ctr",      16, 32,    0, 0, 0, evp_aes_128_ctr},      // RFC4344
-	{SSH2_CIPHER_ARCFOUR,         "arcfour",          8, 16,    0, 0, 0, EVP_rc4},              // RFC4253
-	{SSH2_CIPHER_ARCFOUR128,      "arcfour128",       8, 16, 1536, 0, 0, EVP_rc4},              // RFC4345
-	{SSH2_CIPHER_ARCFOUR256,      "arcfour256",       8, 32, 1536, 0, 0, EVP_rc4},              // RFC4345
-	{SSH2_CIPHER_CAST128_CBC,     "cast128-cbc",      8, 16,    0, 0, 0, EVP_cast5_cbc},        // RFC4253
-	{SSH2_CIPHER_3DES_CTR,        "3des-ctr",         8, 24,    0, 0, 0, evp_des3_ctr},         // RFC4344
-	{SSH2_CIPHER_BLOWFISH_CTR,    "blowfish-ctr",     8, 32,    0, 0, 0, evp_bf_ctr},           // RFC4344
-	{SSH2_CIPHER_CAST128_CTR,     "cast128-ctr",      8, 16,    0, 0, 0, evp_cast5_ctr},        // RFC4344
-	{SSH2_CIPHER_CAMELLIA128_CBC, "camellia128-cbc", 16, 16,    0, 0, 0, EVP_camellia_128_cbc}, // draft-kanno-secsh-camellia-02
-	{SSH2_CIPHER_CAMELLIA192_CBC, "camellia192-cbc", 16, 24,    0, 0, 0, EVP_camellia_192_cbc}, // draft-kanno-secsh-camellia-02
-	{SSH2_CIPHER_CAMELLIA256_CBC, "camellia256-cbc", 16, 32,    0, 0, 0, EVP_camellia_256_cbc}, // draft-kanno-secsh-camellia-02
-	{SSH2_CIPHER_CAMELLIA128_CTR, "camellia128-ctr", 16, 16,    0, 0, 0, evp_camellia_128_ctr}, // draft-kanno-secsh-camellia-02
-	{SSH2_CIPHER_CAMELLIA192_CTR, "camellia192-ctr", 16, 24,    0, 0, 0, evp_camellia_128_ctr}, // draft-kanno-secsh-camellia-02
-	{SSH2_CIPHER_CAMELLIA256_CTR, "camellia256-ctr", 16, 32,    0, 0, 0, evp_camellia_128_ctr}, // draft-kanno-secsh-camellia-02
-#ifdef WITH_CAMELLIA_PRIVATE
-	{SSH2_CIPHER_CAMELLIA128_CBC, "camel****@opens*****", 16, 16, 0,  0,  0, EVP_camellia_128_cbc},
-	{SSH2_CIPHER_CAMELLIA192_CBC, "camel****@opens*****", 16, 24, 0,  0,  0, EVP_camellia_192_cbc},
-	{SSH2_CIPHER_CAMELLIA256_CBC, "camel****@opens*****", 16, 32, 0,  0,  0, EVP_camellia_256_cbc},
-	{SSH2_CIPHER_CAMELLIA128_CTR, "camel****@opens*****", 16, 16, 0,  0,  0, evp_camellia_128_ctr},
-	{SSH2_CIPHER_CAMELLIA192_CTR, "camel****@opens*****", 16, 24, 0,  0,  0, evp_camellia_128_ctr},
-	{SSH2_CIPHER_CAMELLIA256_CTR, "camel****@opens*****", 16, 32, 0,  0,  0, evp_camellia_128_ctr},
-#endif // WITH_CAMELLIA_PRIVATE
-	{SSH2_CIPHER_AES128_GCM,      "aes12****@opens*****",      16, 16, 0, 12, 16, EVP_aes_128_gcm}, // not RFC5647, PROTOCOL of OpenSSH
-	{SSH2_CIPHER_AES256_GCM,      "aes25****@opens*****",      16, 32, 0, 12, 16, EVP_aes_256_gcm}, // not RFC5647, PROTOCOL of OpenSSH
-	{SSH_CIPHER_NONE,             NULL,               0,  0,    0, 0, 0, NULL},
-};
-
-
-typedef enum {
-	KEX_DH_NONE,       /* disabled line */
-	KEX_DH_GRP1_SHA1,
-	KEX_DH_GRP14_SHA1,
-	KEX_DH_GEX_SHA1,
-	KEX_DH_GEX_SHA256,
-	KEX_ECDH_SHA2_256,
-	KEX_ECDH_SHA2_384,
-	KEX_ECDH_SHA2_521,
-	KEX_DH_GRP14_SHA256,
-	KEX_DH_GRP16_SHA512,
-	KEX_DH_GRP18_SHA512,
-	KEX_DH_UNKNOWN,
-	KEX_DH_MAX = KEX_DH_UNKNOWN,
-} kex_algorithm;
-
-typedef struct ssh2_kex_algorithm {
-	kex_algorithm kextype;
-	char *name;
-	const EVP_MD *(*evp_md)(void);
-} ssh2_kex_algorithm_t;
-
-static ssh2_kex_algorithm_t ssh2_kex_algorithms[] = {
-	{KEX_DH_GRP1_SHA1,  "diffie-hellman-group1-sha1",           EVP_sha1},   // RFC4253
-	{KEX_DH_GRP14_SHA1, "diffie-hellman-group14-sha1",          EVP_sha1},   // RFC4253
-	{KEX_DH_GEX_SHA1,   "diffie-hellman-group-exchange-sha1",   EVP_sha1},   // RFC4419
-	{KEX_DH_GEX_SHA256, "diffie-hellman-group-exchange-sha256", EVP_sha256}, // RFC4419
-	{KEX_ECDH_SHA2_256, "ecdh-sha2-nistp256",                   EVP_sha256}, // RFC5656
-	{KEX_ECDH_SHA2_384, "ecdh-sha2-nistp384",                   EVP_sha384}, // RFC5656
-	{KEX_ECDH_SHA2_521, "ecdh-sha2-nistp521",                   EVP_sha512}, // RFC5656
-	{KEX_DH_GRP14_SHA256, "diffie-hellman-group14-sha256",      EVP_sha256}, // RFC8268
-	{KEX_DH_GRP16_SHA512, "diffie-hellman-group16-sha512",      EVP_sha512}, // RFC8268
-	{KEX_DH_GRP18_SHA512, "diffie-hellman-group18-sha512",      EVP_sha512}, // RFC8268
-	{KEX_DH_NONE      , NULL,                                   NULL},
-};
-
-
-typedef enum {
-	HMAC_NONE,      /* disabled line */
-	HMAC_SHA1,
-	HMAC_MD5,
-	HMAC_SHA1_96,
-	HMAC_MD5_96,
-	HMAC_RIPEMD160,
-	HMAC_SHA2_256,
-	HMAC_SHA2_256_96,
-	HMAC_SHA2_512,
-	HMAC_SHA2_512_96,
-	HMAC_SHA1_EtM,
-	HMAC_MD5_EtM,
-	HMAC_SHA1_96_EtM,
-	HMAC_MD5_96_EtM,
-	HMAC_RIPEMD160_EtM,
-	HMAC_SHA2_256_EtM,
-	HMAC_SHA2_512_EtM,
-	HMAC_IMPLICIT,
-	HMAC_UNKNOWN,
-	HMAC_MAX = HMAC_UNKNOWN,
-} SSH2MacId;
-
-typedef struct ssh2_mac {
-	SSH2MacId id;
-	char *name;
-	const EVP_MD *(*evp_md)(void);
-	int truncatebits;
-	int etm;
-} SSH2Mac;
-
-static SSH2Mac ssh2_macs[] = {
-	{HMAC_SHA1,         "hmac-sha1",                     EVP_sha1,      0,  0}, // RFC4253
-	{HMAC_MD5,          "hmac-md5",                      EVP_md5,       0,  0}, // RFC4253
-	{HMAC_SHA1_96,      "hmac-sha1-96",                  EVP_sha1,      96, 0}, // RFC4253
-	{HMAC_MD5_96,       "hmac-md5-96",                   EVP_md5,       96, 0}, // RFC4253
-	{HMAC_RIPEMD160,    "hmac-****@opens*****",    EVP_ripemd160, 0,  0},
-	{HMAC_SHA2_256,     "hmac-sha2-256",                 EVP_sha256,    0,  0}, // RFC6668
-//	{HMAC_SHA2_256_96,  "hmac-sha2-256-96",              EVP_sha256,    96, 0}, // draft-dbider-sha2-mac-for-ssh-05, deleted at 06
-	{HMAC_SHA2_512,     "hmac-sha2-512",                 EVP_sha512,    0,  0}, // RFC6668
-//	{HMAC_SHA2_512_96,  "hmac-sha2-512-96",              EVP_sha512,    96, 0}, // draft-dbider-sha2-mac-for-ssh-05, deleted at 06
-	{HMAC_SHA1_EtM,     "hmac-****@opens*****",     EVP_sha1,      0,  1},
-	{HMAC_MD5_EtM,      "hmac-****@opens*****",      EVP_md5,       0,  1},
-	{HMAC_SHA1_96_EtM,  "hmac-****@opens*****",  EVP_sha1,      96, 1},
-	{HMAC_MD5_96_EtM,   "hmac-****@opens*****",   EVP_md5,       96, 1},
-	{HMAC_RIPEMD160_EtM,"hmac-****@opens*****",EVP_ripemd160, 0,  1},
-	{HMAC_SHA2_256_EtM, "hmac-****@opens*****", EVP_sha256,    0,  1},
-	{HMAC_SHA2_512_EtM, "hmac-****@opens*****", EVP_sha512,    0,  1},
-	{HMAC_IMPLICIT,     "<implicit>",                    EVP_md_null,   0,  0}, // for AEAD cipher
-	{HMAC_NONE,         NULL,                            NULL,          0,  0},
-};
-
-
-typedef enum {
-	COMP_NONE,      /* disabled line */
-	COMP_NOCOMP,
-	COMP_ZLIB,
-	COMP_DELAYED,
-	COMP_UNKNOWN,
-	COMP_MAX = COMP_UNKNOWN,
-} compression_type;
-
-typedef struct ssh2_comp {
-	compression_type type;
-	char *name;
-} ssh2_comp_t;
-
-static ssh2_comp_t ssh2_comps[] = {
-	{COMP_NOCOMP,  "none"},             // RFC4253
-	{COMP_ZLIB,    "zlib"},             // RFC4253
-	{COMP_DELAYED, "zlib****@opens*****"},
-	{COMP_NONE,    NULL},
-};
-
-
 struct Enc {
 	u_char          *key;
 	u_char          *iv;
@@ -595,47 +357,7 @@
 	int bcrypt_kdf;
 } Key;
 
-// fingerprint\x82̎\xED\x95\xCA
-enum fp_rep {
-	SSH_FP_DEFAULT = 0,
-	SSH_FP_HEX,
-	SSH_FP_BASE64,
-	SSH_FP_BUBBLEBABBLE,
-	SSH_FP_RANDOMART
-};
-/*
-enum fp_type {
-	SSH_FP_MD5,
-	SSH_FP_SHA1,
-	SSH_FP_SHA256
-};
-*/
-typedef enum {
-	SSH_DIGEST_MD5,
-	SSH_DIGEST_RIPEMD160,
-	SSH_DIGEST_SHA1,
-	SSH_DIGEST_SHA256,
-	SSH_DIGEST_SHA384,
-	SSH_DIGEST_SHA512,
-	SSH_DIGEST_MAX,
-} digest_algorithm;
 
-typedef struct ssh_digest {
-	digest_algorithm id;
-	char *name;
-} ssh_digest_t;
-
-/* NB. Indexed directly by algorithm number */
-static ssh_digest_t ssh_digests[] = {
-	{ SSH_DIGEST_MD5,       "MD5" },
-	{ SSH_DIGEST_RIPEMD160, "RIPEMD160" },
-	{ SSH_DIGEST_SHA1,      "SHA1" },
-	{ SSH_DIGEST_SHA256,    "SHA256" },
-	{ SSH_DIGEST_SHA384,    "SHA384" },
-	{ SSH_DIGEST_SHA512,    "SHA512" },
-	{ SSH_DIGEST_MAX,       NULL },
-};
-
 enum scp_dir {
 	TOREMOTE, FROMREMOTE,
 };
@@ -777,23 +499,6 @@
 BOOL do_SSH2_userauth(PTInstVar pvar);
 BOOL do_SSH2_authrequest(PTInstVar pvar);
 void debug_print(int no, char *msg, int len);
-int get_cipher_block_size(SSH2Cipher *cipher);
-int get_cipher_key_len(SSH2Cipher *cipher);
-int get_cipher_iv_len(SSH2Cipher *cipher);
-int get_cipher_auth_len(SSH2Cipher *cipher);
-SSH2Cipher *get_cipher_by_name(char *name);
-char* get_kex_algorithm_name(kex_algorithm kextype);
-const EVP_CIPHER* get_cipher_EVP_CIPHER(SSH2Cipher *cipher);
-const EVP_MD* get_kex_algorithm_EVP_MD(kex_algorithm kextype);
-SSH2Mac *get_ssh2_mac(SSH2MacId id);
-char* get_ssh2_mac_name(SSH2Mac *mac);
-char* get_ssh2_mac_name_by_id(SSH2MacId id);
-const EVP_MD* get_ssh2_mac_EVP_MD(SSH2Mac *mac);
-int get_ssh2_mac_truncatebits(SSH2Mac *mac);
-char* get_ssh2_comp_name(compression_type type);
-char* get_ssh_keytype_name(ssh_keytype type);
-char* get_digest_algorithm_name(digest_algorithm id);
-int get_cipher_discard_len(SSH2Cipher *cipher);
 void ssh_heartbeat_lock_initialize(void);
 void ssh_heartbeat_lock_finalize(void);
 void ssh_heartbeat_lock(void);
@@ -804,11 +509,6 @@
 BOOL handle_SSH2_userauth_inforeq(PTInstVar pvar);
 BOOL handle_SSH2_userauth_pkok(PTInstVar pvar);
 BOOL handle_SSH2_userauth_passwd_changereq(PTInstVar pvar);
-void SSH2_update_compression_myproposal(PTInstVar pvar);
-void SSH2_update_cipher_myproposal(PTInstVar pvar);
-void SSH2_update_kex_myproposal(PTInstVar pvar);
-void SSH2_update_host_key_myproposal(PTInstVar pvar);
-void SSH2_update_hmac_myproposal(PTInstVar pvar);
 int SSH_notify_break_signal(PTInstVar pvar);
 
 ///
@@ -896,6 +596,8 @@
 void finish_send_packet_special(PTInstVar pvar, int skip_compress);
 void SSH2_send_channel_data(PTInstVar pvar, Channel_t *c, unsigned char *buf, unsigned int buflen, int retry);
 Channel_t* ssh2_local_channel_lookup(int local_num);
+void normalize_generic_order(char *buf, char default_strings[], int default_strings_len);
+void choose_SSH2_proposal(char* server_proposal, char* my_proposal,char* dest, int dest_len);
 
 #define finish_send_packet(pvar) finish_send_packet_special((pvar), 0)
 #define get_payload_uint32(pvar, offset) get_uint32_MSBfirst((pvar)->ssh_state.payload + (offset))
@@ -944,4 +646,4 @@
 BOOL handle_SSH2_dh_gex_reply_after_known_hosts(PTInstVar pvar);
 BOOL handle_SSH2_ecdh_kex_reply_after_known_hosts(PTInstVar pvar);
 
-#endif
+#endif /* __SSH_H */

Copied: branches/4-stable/ttssh2/ttxssh/ssherr.c (from rev 9252, branches/ssh_chacha20poly1305/ttssh2/ttxssh/ssherr.c)
===================================================================
--- branches/4-stable/ttssh2/ttxssh/ssherr.c	                        (rev 0)
+++ branches/4-stable/ttssh2/ttxssh/ssherr.c	2021-05-19 14:11:12 UTC (rev 9254)
@@ -0,0 +1,153 @@
+/* Imported via OpenSSH-8.5p1, TeraTerm Project */
+
+/*	$OpenBSD: ssherr.c,v 1.10 2020/01/25 23:13:09 djm Exp $	*/
+/*
+ * Copyright (c) 2011 Damien Miller
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <errno.h>
+#include <string.h>
+#include "ssherr.h"
+
+const char *
+ssh_err(int n)
+{
+	switch (n) {
+	case SSH_ERR_SUCCESS:
+		return "success";
+	case SSH_ERR_INTERNAL_ERROR:
+		return "unexpected internal error";
+	case SSH_ERR_ALLOC_FAIL:
+		return "memory allocation failed";
+	case SSH_ERR_MESSAGE_INCOMPLETE:
+		return "incomplete message";
+	case SSH_ERR_INVALID_FORMAT:
+		return "invalid format";
+	case SSH_ERR_BIGNUM_IS_NEGATIVE:
+		return "bignum is negative";
+	case SSH_ERR_STRING_TOO_LARGE:
+		return "string is too large";
+	case SSH_ERR_BIGNUM_TOO_LARGE:
+		return "bignum is too large";
+	case SSH_ERR_ECPOINT_TOO_LARGE:
+		return "elliptic curve point is too large";
+	case SSH_ERR_NO_BUFFER_SPACE:
+		return "insufficient buffer space";
+	case SSH_ERR_INVALID_ARGUMENT:
+		return "invalid argument";
+	case SSH_ERR_KEY_BITS_MISMATCH:
+		return "key bits do not match";
+	case SSH_ERR_EC_CURVE_INVALID:
+		return "invalid elliptic curve";
+	case SSH_ERR_KEY_TYPE_MISMATCH:
+		return "key type does not match";
+	case SSH_ERR_KEY_TYPE_UNKNOWN:
+		return "unknown or unsupported key type";
+	case SSH_ERR_EC_CURVE_MISMATCH:
+		return "elliptic curve does not match";
+	case SSH_ERR_EXPECTED_CERT:
+		return "plain key provided where certificate required";
+	case SSH_ERR_KEY_LACKS_CERTBLOB:
+		return "key lacks certificate data";
+	case SSH_ERR_KEY_CERT_UNKNOWN_TYPE:
+		return "unknown/unsupported certificate type";
+	case SSH_ERR_KEY_CERT_INVALID_SIGN_KEY:
+		return "invalid certificate signing key";
+	case SSH_ERR_KEY_INVALID_EC_VALUE:
+		return "invalid elliptic curve value";
+	case SSH_ERR_SIGNATURE_INVALID:
+		return "incorrect signature";
+	case SSH_ERR_LIBCRYPTO_ERROR:
+		return "error in libcrypto";  /* XXX fetch and return */
+	case SSH_ERR_UNEXPECTED_TRAILING_DATA:
+		return "unexpected bytes remain after decoding";
+	case SSH_ERR_SYSTEM_ERROR:
+		return strerror(errno);
+	case SSH_ERR_KEY_CERT_INVALID:
+		return "invalid certificate";
+	case SSH_ERR_AGENT_COMMUNICATION:
+		return "communication with agent failed";
+	case SSH_ERR_AGENT_FAILURE:
+		return "agent refused operation";
+	case SSH_ERR_DH_GEX_OUT_OF_RANGE:
+		return "DH GEX group out of range";
+	case SSH_ERR_DISCONNECTED:
+		return "disconnected";
+	case SSH_ERR_MAC_INVALID:
+		return "message authentication code incorrect";
+	case SSH_ERR_NO_CIPHER_ALG_MATCH:
+		return "no matching cipher found";
+	case SSH_ERR_NO_MAC_ALG_MATCH:
+		return "no matching MAC found";
+	case SSH_ERR_NO_COMPRESS_ALG_MATCH:
+		return "no matching compression method found";
+	case SSH_ERR_NO_KEX_ALG_MATCH:
+		return "no matching key exchange method found";
+	case SSH_ERR_NO_HOSTKEY_ALG_MATCH:
+		return "no matching host key type found";
+	case SSH_ERR_PROTOCOL_MISMATCH:
+		return "protocol version mismatch";
+	case SSH_ERR_NO_PROTOCOL_VERSION:
+		return "could not read protocol version";
+	case SSH_ERR_NO_HOSTKEY_LOADED:
+		return "could not load host key";
+	case SSH_ERR_NEED_REKEY:
+		return "rekeying not supported by peer";
+	case SSH_ERR_PASSPHRASE_TOO_SHORT:
+		return "passphrase is too short (minimum five characters)";
+	case SSH_ERR_FILE_CHANGED:
+		return "file changed while reading";
+	case SSH_ERR_KEY_UNKNOWN_CIPHER:
+		return "key encrypted using unsupported cipher";
+	case SSH_ERR_KEY_WRONG_PASSPHRASE:
+		return "incorrect passphrase supplied to decrypt private key";
+	case SSH_ERR_KEY_BAD_PERMISSIONS:
+		return "bad permissions";
+	case SSH_ERR_KEY_CERT_MISMATCH:
+		return "certificate does not match key";
+	case SSH_ERR_KEY_NOT_FOUND:
+		return "key not found";
+	case SSH_ERR_AGENT_NOT_PRESENT:
+		return "agent not present";
+	case SSH_ERR_AGENT_NO_IDENTITIES:
+		return "agent contains no identities";
+	case SSH_ERR_BUFFER_READ_ONLY:
+		return "internal error: buffer is read-only";
+	case SSH_ERR_KRL_BAD_MAGIC:
+		return "KRL file has invalid magic number";
+	case SSH_ERR_KEY_REVOKED:
+		return "Key is revoked";
+	case SSH_ERR_CONN_CLOSED:
+		return "Connection closed";
+	case SSH_ERR_CONN_TIMEOUT:
+		return "Connection timed out";
+	case SSH_ERR_CONN_CORRUPT:
+		return "Connection corrupted";
+	case SSH_ERR_PROTOCOL_ERROR:
+		return "Protocol error";
+	case SSH_ERR_KEY_LENGTH:
+		return "Invalid key length";
+	case SSH_ERR_NUMBER_TOO_LARGE:
+		return "number is too large";
+	case SSH_ERR_SIGN_ALG_UNSUPPORTED:
+		return "signature algorithm not supported";
+	case SSH_ERR_FEATURE_UNSUPPORTED:
+		return "requested feature not supported";
+	case SSH_ERR_DEVICE_NOT_FOUND:
+		return "device not found";
+	default:
+		return "unknown error";
+	}
+}

Copied: branches/4-stable/ttssh2/ttxssh/ssherr.h (from rev 9252, branches/ssh_chacha20poly1305/ttssh2/ttxssh/ssherr.h)
===================================================================
--- branches/4-stable/ttssh2/ttxssh/ssherr.h	                        (rev 0)
+++ branches/4-stable/ttssh2/ttxssh/ssherr.h	2021-05-19 14:11:12 UTC (rev 9254)
@@ -0,0 +1,91 @@
+/* Imported via OpenSSH-8.5p1, TeraTerm Project */
+
+/*	$OpenBSD: ssherr.h,v 1.8 2020/01/25 23:13:09 djm Exp $	*/
+/*
+ * Copyright (c) 2011 Damien Miller
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _SSHERR_H
+#define _SSHERR_H
+
+/* XXX are these too granular? not granular enough? I can't decide - djm */
+
+/* Error codes */
+#define SSH_ERR_SUCCESS				0
+#define SSH_ERR_INTERNAL_ERROR			-1
+#define SSH_ERR_ALLOC_FAIL			-2
+#define SSH_ERR_MESSAGE_INCOMPLETE		-3
+#define SSH_ERR_INVALID_FORMAT			-4
+#define SSH_ERR_BIGNUM_IS_NEGATIVE		-5
+#define SSH_ERR_STRING_TOO_LARGE		-6
+#define SSH_ERR_BIGNUM_TOO_LARGE		-7
+#define SSH_ERR_ECPOINT_TOO_LARGE		-8
+#define SSH_ERR_NO_BUFFER_SPACE			-9
+#define SSH_ERR_INVALID_ARGUMENT		-10
+#define SSH_ERR_KEY_BITS_MISMATCH		-11
+#define SSH_ERR_EC_CURVE_INVALID		-12
+#define SSH_ERR_KEY_TYPE_MISMATCH		-13
+#define SSH_ERR_KEY_TYPE_UNKNOWN		-14 /* XXX UNSUPPORTED? */
+#define SSH_ERR_EC_CURVE_MISMATCH		-15
+#define SSH_ERR_EXPECTED_CERT			-16
+#define SSH_ERR_KEY_LACKS_CERTBLOB		-17
+#define SSH_ERR_KEY_CERT_UNKNOWN_TYPE		-18
+#define SSH_ERR_KEY_CERT_INVALID_SIGN_KEY	-19
+#define SSH_ERR_KEY_INVALID_EC_VALUE		-20
+#define SSH_ERR_SIGNATURE_INVALID		-21
+#define SSH_ERR_LIBCRYPTO_ERROR			-22
+#define SSH_ERR_UNEXPECTED_TRAILING_DATA	-23
+#define SSH_ERR_SYSTEM_ERROR			-24
+#define SSH_ERR_KEY_CERT_INVALID		-25
+#define SSH_ERR_AGENT_COMMUNICATION		-26
+#define SSH_ERR_AGENT_FAILURE			-27
+#define SSH_ERR_DH_GEX_OUT_OF_RANGE		-28
+#define SSH_ERR_DISCONNECTED			-29
+#define SSH_ERR_MAC_INVALID			-30
+#define SSH_ERR_NO_CIPHER_ALG_MATCH		-31
+#define SSH_ERR_NO_MAC_ALG_MATCH		-32
+#define SSH_ERR_NO_COMPRESS_ALG_MATCH		-33
+#define SSH_ERR_NO_KEX_ALG_MATCH		-34
+#define SSH_ERR_NO_HOSTKEY_ALG_MATCH		-35
+#define SSH_ERR_NO_HOSTKEY_LOADED		-36
+#define SSH_ERR_PROTOCOL_MISMATCH		-37
+#define SSH_ERR_NO_PROTOCOL_VERSION		-38
+#define SSH_ERR_NEED_REKEY			-39
+#define SSH_ERR_PASSPHRASE_TOO_SHORT		-40
+#define SSH_ERR_FILE_CHANGED			-41
+#define SSH_ERR_KEY_UNKNOWN_CIPHER		-42
+#define SSH_ERR_KEY_WRONG_PASSPHRASE		-43
+#define SSH_ERR_KEY_BAD_PERMISSIONS		-44
+#define SSH_ERR_KEY_CERT_MISMATCH		-45
+#define SSH_ERR_KEY_NOT_FOUND			-46
+#define SSH_ERR_AGENT_NOT_PRESENT		-47
+#define SSH_ERR_AGENT_NO_IDENTITIES		-48
+#define SSH_ERR_BUFFER_READ_ONLY		-49
+#define SSH_ERR_KRL_BAD_MAGIC			-50
+#define SSH_ERR_KEY_REVOKED			-51
+#define SSH_ERR_CONN_CLOSED			-52
+#define SSH_ERR_CONN_TIMEOUT			-53
+#define SSH_ERR_CONN_CORRUPT			-54
+#define SSH_ERR_PROTOCOL_ERROR			-55
+#define SSH_ERR_KEY_LENGTH			-56
+#define SSH_ERR_NUMBER_TOO_LARGE		-57
+#define SSH_ERR_SIGN_ALG_UNSUPPORTED		-58
+#define SSH_ERR_FEATURE_UNSUPPORTED		-59
+#define SSH_ERR_DEVICE_NOT_FOUND		-60
+
+/* Translate a numeric error code to a human-readable error string */
+const char *ssh_err(int n);
+
+#endif /* _SSHERR_H */

Modified: branches/4-stable/ttssh2/ttxssh/ttxssh.c
===================================================================
--- branches/4-stable/ttssh2/ttxssh/ttxssh.c	2021-05-19 14:05:07 UTC (rev 9253)
+++ branches/4-stable/ttssh2/ttxssh/ttxssh.c	2021-05-19 14:11:12 UTC (rev 9254)
@@ -78,6 +78,9 @@
 #include "buffer.h"
 #include "cipher.h"
 #include "key.h"
+#include "kex.h"
+#include "mac.h"
+#include "comp.h"
 #include "dlglib.h"
 
 #include "sftp.h"
@@ -87,6 +90,9 @@
 
 #include "libputty.h"
 
+// from cipher-3des.c
+extern const EVP_CIPHER* evp_ssh1_3des(void);
+
 #undef DialogBoxParam
 #define DialogBoxParam(p1,p2,p3,p4,p5) \
 	TTDialogBoxParam(p1,p2,p3,p4,p5)
@@ -155,10 +161,10 @@
 	FWDUI_init(pvar);
 
 	ssh_heartbeat_lock_initialize();
-
-	pvar->evpcip[MODE_IN] = EVP_CIPHER_CTX_new();
-	pvar->evpcip[MODE_OUT] = EVP_CIPHER_CTX_new();
-	/*** TODO: OPENSSL1.1.1 ERROR CHECK(ticket#39335\x82ŏ\x88\x92u\x97\\x92\xE8) ***/
+	
+	pvar->cc[MODE_IN] = NULL;
+	pvar->cc[MODE_OUT] = NULL;
+	// \x83\x81\x83\x82\x83\x8A\x8Am\x95ۂ\xCD CRYPT_start_encryption \x82̐\xE6\x82\xCC cipher_init_SSH2 \x82Ɉړ\xAE
 }
 
 static void uninit_TTSSH(PTInstVar pvar)
@@ -191,8 +197,12 @@
 
 	ssh_heartbeat_lock_finalize();
 
-	EVP_CIPHER_CTX_free(pvar->evpcip[MODE_IN]);
-	EVP_CIPHER_CTX_free(pvar->evpcip[MODE_OUT]);
+	cipher_free_SSH2(pvar->cc[MODE_IN]);
+	cipher_free_SSH2(pvar->cc[MODE_OUT]);
+
+	// CloseTCP \x82\xC6 TTXEnd \x82\xA9\x82\xE7 2 \x89\xF1\x8CĂ΂\xEA\x82\xE9\x8Fꍇ\x82\xAA\x82\xA0\x82邽\x82߁A2\x8Fd free \x82\xB5\x82Ȃ\xA2\x82悤\x82\xC9 NULL \x82\xF0\x83Z\x83b\x83g\x82\xB5\x82Ă\xA8\x82\xAD
+	pvar->cc[MODE_IN] = NULL;
+	pvar->cc[MODE_OUT] = NULL;
 }
 
 static void PASCAL TTXInit(PTTSet ts, PComVar cv)
@@ -207,208 +217,6 @@
 	init_TTSSH(pvar);
 }
 
-static void normalize_generic_order(char *buf, char default_strings[], int default_strings_len)
-{
-	char listed[max(KEX_DH_MAX,max(SSH_CIPHER_MAX,max(KEY_MAX,max(HMAC_MAX,COMP_MAX)))) + 1];
-	char allowed[max(KEX_DH_MAX,max(SSH_CIPHER_MAX,max(KEY_MAX,max(HMAC_MAX,COMP_MAX)))) + 1];
-	int i, j, k=-1;
-
-	memset(listed, 0, sizeof(listed));
-	memset(allowed, 0, sizeof(allowed));
-
-	// \x8B\x96\x89‚\xB3\x82\xEA\x82Ă\xA2\x82镶\x8E\x9A\x82̃\x8A\x83X\x83g\x82\xF0\x8D\xEC\x82\xE9\x81B
-	for (i = 0; i < default_strings_len ; i++) {
-		allowed[default_strings[i]] = 1;
-	}
-
-	// \x8Ew\x92肳\x82ꂽ\x95\xB6\x8E\x9A\x97\xF1\x82𑖍\xB8\x82\xB5\x81A\x8B\x96\x89‚\xB3\x82\xEA\x82Ă\xA2\x82Ȃ\xA2\x95\xB6\x8E\x9A\x81A\x8Fd\x95\xA1\x82\xB7\x82镶\x8E\x9A\x82͍폜\x82\xB7\x82\xE9\x81B
-	// 
-	// ex. (i=5 \x82̕\xB6\x8E\x9A\x82\xF0\x8D폜\x82\xB7\x82\xE9)
-	// i=012345
-	//   >:=9<87;A@?B3026(\0)
-	//         i+1
-	//         <------------>
-	//       \x81\xAB
-	//   >:=9<7;A@?B3026(\0)
-	//         
-	for (i = 0; buf[i] != 0; i++) {
-		int num = buf[i] - '0';
-
-		if (num < 0 || num > default_strings_len
-			|| !allowed[num]
-			|| listed[num]) {
-			memmove(buf + i, buf + i + 1, strlen(buf + i + 1) + 1);
-			i--;
-		} else {
-			listed[num] = 1;
-		}
-
-		// disabled line\x82\xAA\x82\xA0\x82\xEA\x82΁A\x88ʒu\x82\xF0\x8Ao\x82\xA6\x82Ă\xA8\x82\xAD\x81B
-		if (num == 0) {
-			k = i;
-		}
-	}
-
-	// \x8Ew\x92肳\x82\xEA\x82Ă\xA2\x82Ȃ\xA2\x95\xB6\x8E\x9A\x82\xAA\x82\xA0\x82\xEA\x82΁Adisabled line\x82̒\xBC\x91O\x82ɑ}\x93\xFC\x82\xB7\x82\xE9\x81B
-	// 
-	// ex. (Z\x82\xF0\x91}\x93\xFC\x82\xB7\x82\xE9)
-	//                k
-	//   >:=9<87;A@?B3026(\0)
-	//                 k+1
-	//                 <---->
-	//       \x81\xAB       k
-	//   >:=9<87;A@?B30026(\0)
-	//       \x81\xAB        k
-	//   >:=9<87;A@?B3Z026(\0)
-	//       
-	for (j = 0; j < default_strings_len && default_strings[j] != 0; j++) {
-		int num = default_strings[j];
-
-		if (!listed[num] && k >= 0) {
-			int copylen = strlen(buf + k + 1) + 1;
-
-			memmove(buf + k + 1, buf + k, copylen);
-			buf[k + 1 + copylen] = '\0';   // \x8FI\x92[\x82\xF0\x96Y\x82ꂸ\x82ɕt\x82\xAF\x82\xE9\x81B
-			buf[k] = num + '0';
-			k++;
-			i++;
-		}
-	}
-	if (k < 0) {
-		j = 0;
-	}
-	else {
-		j++;
-	}
-
-	// disabled line\x82\xAA\x91\xB6\x8D݂\xB5\x82Ȃ\xA2\x8Fꍇ\x82́A\x82\xBB\x82̂܂ܖ\x96\x94\xF6\x82ɒlj\xC1\x82\xB7\x82\xE9\x81B
-	for (; j < default_strings_len ; j++) {
-		int num = default_strings[j];
-
-		if (!listed[num]) {
-			buf[i] = num + '0';
-			listed[num] = 1;
-			i++;
-		}
-	}
-
-	buf[i] = 0;
-}
-
-/*
- * Remove unsupported cipher or duplicated cipher.
- * Add unspecified ciphers at the end of list.
- */
-static void normalize_cipher_order(char *buf)
-{
-	/* SSH_CIPHER_NONE means that all ciphers below that one are disabled.
-	   We *never* allow no encryption. */
-	static char default_strings[] = {
-		SSH2_CIPHER_AES256_GCM,
-		SSH2_CIPHER_CAMELLIA256_CTR,
-		SSH2_CIPHER_AES256_CTR,
-		SSH2_CIPHER_CAMELLIA256_CBC,
-		SSH2_CIPHER_AES256_CBC,
-		SSH2_CIPHER_CAMELLIA192_CTR,
-		SSH2_CIPHER_AES192_CTR,
-		SSH2_CIPHER_CAMELLIA192_CBC,
-		SSH2_CIPHER_AES192_CBC,
-		SSH2_CIPHER_AES128_GCM,
-		SSH2_CIPHER_CAMELLIA128_CTR,
-		SSH2_CIPHER_AES128_CTR,
-		SSH2_CIPHER_CAMELLIA128_CBC,
-		SSH2_CIPHER_AES128_CBC,
-		SSH2_CIPHER_3DES_CTR,
-		SSH2_CIPHER_3DES_CBC,
-		SSH2_CIPHER_BLOWFISH_CTR,
-		SSH2_CIPHER_BLOWFISH_CBC,
-		SSH2_CIPHER_CAST128_CTR,
-		SSH2_CIPHER_CAST128_CBC,
-		SSH_CIPHER_3DES,
-		SSH_CIPHER_NONE,
-		SSH2_CIPHER_ARCFOUR256,
-		SSH2_CIPHER_ARCFOUR128,
-		SSH2_CIPHER_ARCFOUR,
-		SSH_CIPHER_BLOWFISH,
-		SSH_CIPHER_DES,
-		0, 0, 0 // Dummy for SSH_CIPHER_IDEA, SSH_CIPHER_TSS, SSH_CIPHER_RC4
-	};
-
-	normalize_generic_order(buf, default_strings, NUM_ELEM(default_strings));
-}
-
-static void normalize_kex_order(char *buf)
-{
-	static char default_strings[] = {
-		KEX_ECDH_SHA2_256,
-		KEX_ECDH_SHA2_384,
-		KEX_ECDH_SHA2_521,
-		KEX_DH_GRP18_SHA512,
-		KEX_DH_GRP16_SHA512,
-		KEX_DH_GRP14_SHA256,
-		KEX_DH_GEX_SHA256,
-		KEX_DH_GEX_SHA1,
-		KEX_DH_GRP14_SHA1,
-		KEX_DH_GRP1_SHA1,
-		KEX_DH_NONE,
-	};
-
-	normalize_generic_order(buf, default_strings, NUM_ELEM(default_strings));
-}
-
-static void normalize_host_key_order(char *buf)
-{
-	static char default_strings[] = {
-		KEY_ECDSA256,
-		KEY_ECDSA384,
-		KEY_ECDSA521,
-		KEY_ED25519,
-		KEY_RSA,
-		KEY_DSA,
-		KEY_NONE,
-	};
-
-	normalize_generic_order(buf, default_strings, NUM_ELEM(default_strings));
-}
-
-static void normalize_mac_order(char *buf)
-{
-	static char default_strings[] = {
-		HMAC_SHA2_512_EtM,
-		HMAC_SHA2_256_EtM,
-		HMAC_SHA1_EtM,
-		HMAC_SHA2_512,
-		HMAC_SHA2_256,
-		HMAC_SHA1,
-		HMAC_RIPEMD160_EtM,
-		HMAC_RIPEMD160,
-		HMAC_MD5_EtM,
-		HMAC_MD5,
-		HMAC_NONE,
-		HMAC_SHA1_96_EtM,
-		HMAC_MD5_96_EtM,
-		HMAC_SHA1_96,
-		HMAC_MD5_96,
-		0, // Dummy for HMAC_SHA2_512_96,
-		0, // Dummy for HMAC_SHA2_256_96,
-	};
-
-	normalize_generic_order(buf, default_strings, NUM_ELEM(default_strings));
-}
-
-static void normalize_comp_order(char *buf)
-{
-	static char default_strings[] = {
-		COMP_DELAYED,
-		COMP_ZLIB,
-		COMP_NOCOMP,
-		COMP_NONE,
-	};
-
-	normalize_generic_order(buf, default_strings, NUM_ELEM(default_strings));
-}
-
-
 /* Remove local settings from the shared memory block. */
 static void clear_local_settings(PTInstVar pvar)
 {
@@ -645,8 +453,8 @@
 
 	// Remember password (2006.8.5 yutaka)
 	WritePrivateProfileString("TTSSH", "RememberPassword",
-	    settings->remember_password ? "1" : "0",
-	    fileName);
+	                          settings->remember_password ? "1" : "0",
+	                          fileName);
 
 	// \x8F\x89\x89\xF1\x82̔F\x8F؃_\x83C\x83A\x83\x8D\x83O\x82ŃT\x83|\x81[\x83g\x82\xB3\x82\xEA\x82Ă\xA2\x82郁\x83\\x83b\x83h\x82\xF0\x83`\x83F\x83b\x83N\x82\xB5\x81A
 	// \x96\xB3\x8C\xF8\x82ȃ\x81\x83\\x83b\x83h\x82\xF0\x83O\x83\x8C\x83C\x83A\x83E\x83g\x82\xB7\x82\xE9 (2007.9.24 maya)
@@ -1145,10 +953,10 @@
 		HOSTS_open(pvar);
 		FWDUI_open(pvar);
 
-		// \x90ݒ\xE8\x82\xF0 myproposal \x82ɔ\xBD\x89f\x82\xB7\x82\xE9\x82̂́A\x90ڑ\xB1\x92\xBC\x91O\x82̂\xB1\x82\xB1\x82\xBE\x82\xAF\x81B (2006.6.26 maya)
-		SSH2_update_cipher_myproposal(pvar);
+		// \x90ݒ\xE8\x82\xF0 myproposal \x82ɔ\xBD\x89f\x82\xB7\x82\xE9\x82̂́A\x90ڑ\xB1\x92\xBC\x91O\x82̂\xB1\x82\xB1\x82\xBE\x82\xAF\x81B
 		SSH2_update_kex_myproposal(pvar);
 		SSH2_update_host_key_myproposal(pvar);
+		SSH2_update_cipher_myproposal(pvar);
 		SSH2_update_hmac_myproposal(pvar);
 		SSH2_update_compression_myproposal(pvar);
 	}
@@ -1652,13 +1460,13 @@
 static void UTIL_SetDialogFont()
 {
 	SetDialogFont(pvar->ts->DialogFontName, pvar->ts->DialogFontPoint, pvar->ts->DialogFontCharSet,
-				  pvar->ts->UILanguageFile, "TTSSH", "DLG_TAHOMA_FONT");
+	              pvar->ts->UILanguageFile, "TTSSH", "DLG_TAHOMA_FONT");
 }
 
 static BOOL PASCAL TTXGetHostName(HWND parent, PGetHNRec rec)
 {
 	SetDialogFont(pvar->ts->DialogFontName, pvar->ts->DialogFontPoint, pvar->ts->DialogFontCharSet,
-				  pvar->ts->UILanguageFile, "TTSSH", "DLG_SYSTEM_FONT");
+	              pvar->ts->UILanguageFile, "TTSSH", "DLG_SYSTEM_FONT");
 	return (BOOL) DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_HOSTDLG),
 	                             parent, TTXHostDlg, (LPARAM)rec);
 }
@@ -2292,7 +2100,7 @@
 			UTIL_get_lang_msg("DLG_ABOUT_HOSTKEY", pvar, "Host Key:");
 			strncat_s(buf2, sizeof(buf2), pvar->ts->UIMsg, _TRUNCATE);
 			strncat_s(buf2, sizeof(buf2), " ", _TRUNCATE);
-			strncat_s(buf2, sizeof(buf2), get_ssh_keytype_name(pvar->hostkey_type), _TRUNCATE);
+			strncat_s(buf2, sizeof(buf2), get_ssh2_hostkey_type_name(pvar->hostkey_type), _TRUNCATE);
 			strncat_s(buf2, sizeof(buf2), "\r\n", _TRUNCATE);
 
 			UTIL_get_lang_msg("DLG_ABOUT_ENCRYPTION", pvar, "Encryption:");
@@ -2531,73 +2339,6 @@
 	return FALSE;
 }
 
-static char *get_cipher_name(int cipher)
-{
-	switch (cipher) {
-	case SSH_CIPHER_NONE:
-		UTIL_get_lang_msg("DLG_SSHSETUP_CIPHER_BORDER", pvar,
-		                  "<ciphers below this line are disabled>");
-		return pvar->ts->UIMsg;
-	case SSH_CIPHER_3DES:
-		return "3DES(SSH1)";
-	case SSH_CIPHER_DES:
-		return "DES(SSH1)";
-	case SSH_CIPHER_BLOWFISH:
-		return "Blowfish(SSH1)";
-
-	// for SSH2(yutaka)
-	case SSH2_CIPHER_AES128_CBC:
-		return "aes128-cbc(SSH2)";
-	case SSH2_CIPHER_AES192_CBC:
-		return "aes192-cbc(SSH2)";
-	case SSH2_CIPHER_AES256_CBC:
-		return "aes256-cbc(SSH2)";
-	case SSH2_CIPHER_3DES_CBC:
-		return "3des-cbc(SSH2)";
-	case SSH2_CIPHER_BLOWFISH_CBC:
-		return "blowfish-cbc(SSH2)";
-	case SSH2_CIPHER_AES128_CTR:
-		return "aes128-ctr(SSH2)";
-	case SSH2_CIPHER_AES192_CTR:
-		return "aes192-ctr(SSH2)";
-	case SSH2_CIPHER_AES256_CTR:
-		return "aes256-ctr(SSH2)";
-	case SSH2_CIPHER_ARCFOUR:
-		return "arcfour(SSH2)";
-	case SSH2_CIPHER_ARCFOUR128:
-		return "arcfour128(SSH2)";
-	case SSH2_CIPHER_ARCFOUR256:
-		return "arcfour256(SSH2)";
-	case SSH2_CIPHER_CAST128_CBC:
-		return "cast128-cbc(SSH2)";
-	case SSH2_CIPHER_3DES_CTR:
-		return "3des-ctr(SSH2)";
-	case SSH2_CIPHER_BLOWFISH_CTR:
-		return "blowfish-ctr(SSH2)";
-	case SSH2_CIPHER_CAST128_CTR:
-		return "cast128-ctr(SSH2)";
-	case SSH2_CIPHER_CAMELLIA128_CBC:
-		return "camellia128-cbc(SSH2)";
-	case SSH2_CIPHER_CAMELLIA192_CBC:
-		return "camellia192-cbc(SSH2)";
-	case SSH2_CIPHER_CAMELLIA256_CBC:
-		return "camellia256-cbc(SSH2)";
-	case SSH2_CIPHER_CAMELLIA128_CTR:
-		return "camellia128-ctr(SSH2)";
-	case SSH2_CIPHER_CAMELLIA192_CTR:
-		return "camellia192-ctr(SSH2)";
-	case SSH2_CIPHER_CAMELLIA256_CTR:
-		return "camellia256-ctr(SSH2)";
-	case SSH2_CIPHER_AES128_GCM:
-		return "aes12****@opens*****(SSH2)";
-	case SSH2_CIPHER_AES256_GCM:
-		return "aes25****@opens*****(SSH2)";
-
-	default:
-		return NULL;
-	}
-}
-
 static void set_move_button_status(HWND dlg, int type, int up, int down)
 {
 	HWND cipherControl = GetDlgItem(dlg, type);
@@ -2690,7 +2431,7 @@
 
 	for (i = 0; pvar->settings.CipherOrder[i] != 0; i++) {
 		int cipher = pvar->settings.CipherOrder[i] - '0';
-		char *name = get_cipher_name(cipher);
+		char *name = get_listbox_cipher_name(cipher, pvar);
 
 		if (name != NULL) {
 			SendMessage(cipherControl, LB_ADDSTRING, 0, (LPARAM) name);
@@ -2706,9 +2447,9 @@
 		int index = pvar->settings.KexOrder[i] - '0';
 		char *name = NULL;
 
-		if (index == 0)	{
+		if (index == 0) {
 			UTIL_get_lang_msg("DLG_SSHSETUP_KEX_BORDER", pvar,
-							  "<KEXs below this line are disabled>");
+			                  "<KEXs below this line are disabled>");
 			name = pvar->ts->UIMsg;
 		} else {
 			name = get_kex_algorithm_name(index);
@@ -2727,12 +2468,12 @@
 		int index = pvar->settings.HostKeyOrder[i] - '0';
 		char *name = NULL;
 
-		if (index == 0)	{
+		if (index == 0) {
 			UTIL_get_lang_msg("DLG_SSHSETUP_HOST_KEY_BORDER", pvar,
-							  "<Host Keys below this line are disabled>");
+			                  "<Host Keys below this line are disabled>");
 			name = pvar->ts->UIMsg;
 		} else {
-			name = get_ssh_keytype_name(index);
+			name = get_ssh2_hostkey_type_name(index);
 		}
 
 		if (name != NULL) {
@@ -2748,9 +2489,9 @@
 		int index = pvar->settings.MacOrder[i] - '0';
 		char *name = NULL;
 
-		if (index == 0)	{
+		if (index == 0) {
 			UTIL_get_lang_msg("DLG_SSHSETUP_MAC_BORDER", pvar,
-							  "<MACs below this line are disabled>");
+			                  "<MACs below this line are disabled>");
 			name = pvar->ts->UIMsg;
 		} else {
 			name = get_ssh2_mac_name_by_id(index);
@@ -2769,9 +2510,9 @@
 		int index = pvar->settings.CompOrder[i] - '0';
 		char *name = NULL;
 
-		if (index == 0)	{
+		if (index == 0) {
 			UTIL_get_lang_msg("DLG_SSHSETUP_COMP_BORDER", pvar,
-							  "<Compression methods below this line are disabled>");
+			                  "<Compression methods below this line are disabled>");
 			name = pvar->ts->UIMsg;
 		} else {
 			name = get_ssh2_comp_name(index);
@@ -2941,7 +2682,7 @@
 			buf[0] = 0;
 			SendMessage(cipherControl, LB_GETTEXT, i, (LPARAM) buf);
 			for (j = 0; j <= SSH_CIPHER_MAX; j++) {
-				char *cipher_name = get_cipher_name(j);
+				char *cipher_name = get_listbox_cipher_name(j, pvar);
 				if (cipher_name != NULL && strcmp(buf, cipher_name) == 0) {
 					break;
 				}
@@ -2995,7 +2736,7 @@
 			SendMessage(cipherControl, LB_GETTEXT, i, (LPARAM) buf);
 			for (j = 0;
 				j <= KEY_MAX
-				 && strcmp(buf, get_ssh_keytype_name(j)) != 0; j++) {
+				 && strcmp(buf, get_ssh2_hostkey_type_name(j)) != 0; j++) {
 			}
 			if (j <= KEY_MAX) {
 				buf2[buf2index] = '0' + j;
@@ -3216,7 +2957,7 @@
 }
 
 static INT_PTR CALLBACK TTXSetupDlg(HWND dlg, UINT msg, WPARAM wParam,
-									LPARAM lParam)
+                                    LPARAM lParam)
 {
 	switch (msg) {
 	case WM_INITDIALOG:
@@ -3538,144 +3279,6 @@
 }
 
 
-//
-// SSH1 3DES
-//
-/*
- * This is used by SSH1:
- *
- * What kind of triple DES are these 2 routines?
- *
- * Why is there a redundant initialization vector?
- *
- * If only iv3 was used, then, this would till effect have been
- * outer-cbc. However, there is also a private iv1 == iv2 which
- * perhaps makes differential analysis easier. On the other hand, the
- * private iv1 probably makes the CRC-32 attack ineffective. This is a
- * result of that there is no longer any known iv1 to use when
- * choosing the X block.
- */
-struct ssh1_3des_ctx
-{
-	EVP_CIPHER_CTX  *k1, *k2, *k3;
-};
-
-static int ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, int enc)
-{
-	struct ssh1_3des_ctx *c;
-	u_char *k1, *k2, *k3;
-
-	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
-		c = malloc(sizeof(*c));
-		c->k1 = EVP_CIPHER_CTX_new();
-		c->k2 = EVP_CIPHER_CTX_new();
-		c->k3 = EVP_CIPHER_CTX_new();
-		/*** TODO: OPENSSL1.1.1 ERROR CHECK(ticket#39335\x82ŏ\x88\x92u\x97\\x92\xE8) ***/
-		EVP_CIPHER_CTX_set_app_data(ctx, c);
-	}
-	if (key == NULL)
-		return (1);
-	if (enc == -1)
-		enc = EVP_CIPHER_CTX_encrypting(ctx); // ctx->encrypt
-	k1 = k2 = k3 = (u_char *) key;
-	k2 += 8;
-	if (EVP_CIPHER_CTX_key_length(ctx) >= 16+8) {
-		if (enc)
-			k3 += 16;
-		else
-			k1 += 16;
-	}
-	EVP_CIPHER_CTX_init(c->k1);
-	EVP_CIPHER_CTX_init(c->k2);
-	EVP_CIPHER_CTX_init(c->k3);
-	if (EVP_CipherInit(c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 ||
-		EVP_CipherInit(c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 ||
-		EVP_CipherInit(c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) {
-			EVP_CIPHER_CTX_free(c->k1);
-			EVP_CIPHER_CTX_free(c->k2);
-			EVP_CIPHER_CTX_free(c->k3);
-			SecureZeroMemory(c, sizeof(*c));
-			free(c);
-			EVP_CIPHER_CTX_set_app_data(ctx, NULL);
-			return (0);
-	}
-	return (1);
-}
-
-static int ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, u_int len)
-{
-	struct ssh1_3des_ctx *c;
-
-	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
-		//error("ssh1_3des_cbc: no context");
-		return (0);
-	}
-	if (EVP_Cipher(c->k1, dest, (u_char *)src, len) == 0 ||
-		EVP_Cipher(c->k2, dest, dest, len) == 0 ||
-		EVP_Cipher(c->k3, dest, dest, len) == 0)
-		return (0);
-	return (1);
-}
-
-static int ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx)
-{
-	struct ssh1_3des_ctx *c;
-
-	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
-		EVP_CIPHER_CTX_cleanup(c->k1);
-		EVP_CIPHER_CTX_cleanup(c->k2);
-		EVP_CIPHER_CTX_cleanup(c->k3);
-		SecureZeroMemory(c, sizeof(*c));
-		free(c);
-		EVP_CIPHER_CTX_set_app_data(ctx, NULL);
-	}
-	return (1);
-}
-
-// \x89\xBA\x8BL\x8A֐\x94\x82͖\xA2\x8Eg\x97p\x81B
-void ssh1_3des_iv(EVP_CIPHER_CTX *evp, int doset, u_char *iv, int len)
-{
-	struct ssh1_3des_ctx *c;
-
-	if (len != 24)
-		//fatal("%s: bad 3des iv length: %d", __func__, len);
-		;
-
-	if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL)
-		//fatal("%s: no 3des context", __func__);
-		;
-
-	if (doset) {
-		//debug3("%s: Installed 3DES IV", __func__);
-		memcpy(EVP_CIPHER_CTX_iv_noconst(c->k1), iv, 8);
-		memcpy(EVP_CIPHER_CTX_iv_noconst(c->k2), iv + 8, 8);
-		memcpy(EVP_CIPHER_CTX_iv_noconst(c->k3), iv + 16, 8);
-	} else {
-		//debug3("%s: Copying 3DES IV", __func__);
-		memcpy(iv, EVP_CIPHER_CTX_iv(c->k1), 8);
-		memcpy(iv + 8, EVP_CIPHER_CTX_iv(c->k2), 8);
-		memcpy(iv + 16, EVP_CIPHER_CTX_iv(c->k3), 8);
-	}
-}
-
-const EVP_CIPHER *evp_ssh1_3des(void)
-{
-	static EVP_CIPHER *p = NULL;
-
-	if (p == NULL) {
-		p = EVP_CIPHER_meth_new(NID_undef, /*block_size*/8, /*key_len*/16);
-		/*** TODO: OPENSSL1.1.1 ERROR CHECK(ticket#39335\x82ŏ\x88\x92u\x97\\x92\xE8) ***/
-	}
-	if (p) {
-		EVP_CIPHER_meth_set_iv_length(p, 0);
-		EVP_CIPHER_meth_set_init(p, ssh1_3des_init);
-		EVP_CIPHER_meth_set_cleanup(p, ssh1_3des_cleanup);
-		EVP_CIPHER_meth_set_do_cipher(p, ssh1_3des_cbc);
-		EVP_CIPHER_meth_set_flags(p, EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH);
-	}
-	return (p);
-}
-
 static void ssh_make_comment(char *comment, int maxlen)
 {
 	char user[UNLEN + 1], host[128];
@@ -4035,7 +3638,7 @@
 // based on OpenSSH 6.5:key_save_private(), key_private_to_blob2()
 static void save_bcrypt_private_key(char *passphrase, char *filename, char *comment, HWND dlg, PTInstVar pvar, int rounds)
 {
-	SSH2Cipher *cipher = NULL;
+	const struct ssh2cipher *cipher = NULL;
 	char *ciphername = DEFAULT_CIPHERNAME;
 	buffer_t *b = NULL;
 	buffer_t *kdf = NULL;
@@ -4044,7 +3647,7 @@
 	int blocksize, keylen, ivlen, authlen, i, n; 
 	unsigned char *key = NULL, salt[SALT_LEN];
 	char *kdfname = KDFNAME;
-	EVP_CIPHER_CTX *cipher_ctx = NULL;
+	struct sshcipher_ctx *cc = NULL;
 	Key keyblob;
 	unsigned char *cp = NULL;
 	unsigned int len, check;
@@ -4055,8 +3658,7 @@
 	kdf = buffer_init();
 	encoded = buffer_init();
 	blob = buffer_init();
-	cipher_ctx = EVP_CIPHER_CTX_new();
-	if (b == NULL || kdf == NULL || encoded == NULL || blob == NULL || cipher_ctx == NULL)
+	if (b == NULL || kdf == NULL || encoded == NULL || blob == NULL)
 		goto ed25519_error;
 
 	if (passphrase == NULL || !strlen(passphrase)) {
@@ -4083,8 +3685,8 @@
 	// \x88Í\x86\x89\xBB\x82̏\x80\x94\xF5
 	// TODO: OpenSSH 6.5\x82ł\xCD -Z \x83I\x83v\x83V\x83\x87\x83\x93\x82ŁA\x88Í\x86\x89\xBB\x83A\x83\x8B\x83S\x83\x8A\x83Y\x83\x80\x82\xF0\x8Ew\x92\xE8\x89”\\x82\xBE\x82\xAA\x81A
 	// \x82\xB1\x82\xB1\x82ł\xCD"AES256-CBC"\x82ɌŒ\xE8\x82Ƃ\xB7\x82\xE9\x81B
-	cipher_init_SSH2(cipher_ctx, key, keylen, key + keylen, ivlen, CIPHER_ENCRYPT, 
-		get_cipher_EVP_CIPHER(cipher), 0, 0, pvar);
+	cipher = get_cipher_by_name(ciphername);
+	cipher_init_SSH2(&cc, cipher, key, keylen, key + keylen, ivlen, CIPHER_ENCRYPT, pvar);
 	SecureZeroMemory(key, keylen + ivlen);
 	free(key);
 
@@ -4127,12 +3729,12 @@
 
 	/* encrypt */
 	cp = buffer_append_space(encoded, buffer_len(b) + authlen);
-	if (EVP_Cipher(cipher_ctx, cp, buffer_ptr(b), buffer_len(b)) == 0) {
+	if (EVP_Cipher(cc->evp, cp, buffer_ptr(b), buffer_len(b)) == 0) {
 		//strncpy_s(errmsg, errmsg_len, "Key decrypt error", _TRUNCATE);
 		//free(decrypted);
 		//goto error;
 	}
-	cipher_cleanup_SSH2(cipher_ctx);
+	cipher_free_SSH2(cc);
 
 	len = 2 * buffer_len(encoded);
 	cp = malloc(len);
@@ -4182,14 +3784,10 @@
 	buffer_free(kdf);
 	buffer_free(encoded);
 	buffer_free(blob);
-
-	if (cipher_ctx) {
-		EVP_CIPHER_CTX_free(cipher_ctx);
-	}
 }
 
 static INT_PTR CALLBACK TTXKeyGenerator(HWND dlg, UINT msg, WPARAM wParam,
-										LPARAM lParam)
+                                        LPARAM lParam)
 {
 	static ssh_keytype key_type;
 	static int saved_key_bits;
@@ -4637,7 +4235,7 @@
 				case KEY_ECDSA256: // ECDSA
 				case KEY_ECDSA384:
 				case KEY_ECDSA521:
-					keyname = get_ssh_keytype_name(public_key.type);
+					keyname = get_ssh2_hostkey_type_name(public_key.type);
 					buffer_put_string(b, keyname, strlen(keyname));
 					s = curve_keytype_to_name(public_key.type);
 					buffer_put_string(b, s, strlen(s));
@@ -4646,7 +4244,7 @@
 					break;
 
 				case KEY_ED25519:
-					keyname = get_ssh_keytype_name(public_key.type);
+					keyname = get_ssh2_hostkey_type_name(public_key.type);
 					buffer_put_cstring(b, keyname);
 					buffer_put_string(b, public_key.ed25519_pk, ED25519_PK_SZ);
 					break;
@@ -4802,7 +4400,8 @@
 				MD5_CTX md;
 				unsigned char digest[16];
 				char *passphrase = buf;
-				EVP_CIPHER_CTX *cipher_ctx = NULL;
+				const struct ssh2cipher *cipher = NULL;
+				struct sshcipher_ctx *cc = NULL;
 				FILE *fp;
 				char wrapped[4096];
 				BIGNUM *e, *n, *d, *dmp1, *dmq1, *iqmp, *p, *q;
@@ -4810,7 +4409,7 @@
 				if (passphrase[0] == '\0') { // passphrase is empty
 					cipher_num = SSH_CIPHER_NONE;
 				} else {
-					cipher_num = SSH_CIPHER_3DES; // 3DES-CBC
+					cipher_num = SSH_CIPHER_3DES; // 3DES
 				}
 
 				b = buffer_init();
@@ -4822,9 +4421,6 @@
 					break;
 				}
 
-				cipher_ctx = EVP_CIPHER_CTX_new();
-				/*** TODO: OPENSSL1.1.1 ERROR CHECK(ticket#39335\x82ŏ\x88\x92u\x97\\x92\xE8) ***/
-
 				// set random value
 				rnd = arc4random();
 				tmp[0] = rnd & 0xff;
@@ -4874,9 +4470,11 @@
 				MD5_Update(&md, (const unsigned char *)passphrase, strlen(passphrase));
 				MD5_Final(digest, &md);
 				if (cipher_num == SSH_CIPHER_NONE) {
-					cipher_init_SSH2(cipher_ctx, digest, 16, NULL, 0, CIPHER_ENCRYPT, EVP_enc_null(), 0, 0, pvar);
+					cipher = get_cipher_by_name("none");
+					cipher_init_SSH2(&cc, cipher, digest, 16, NULL, 0, CIPHER_ENCRYPT, pvar);
 				} else {
-					cipher_init_SSH2(cipher_ctx, digest, 16, NULL, 0, CIPHER_ENCRYPT, evp_ssh1_3des(), 0, 0, pvar);
+					cipher = get_cipher_by_name("3des");
+					cipher_init_SSH2(&cc, cipher, digest, 16, NULL, 0, CIPHER_ENCRYPT, pvar);
 				}
 				len = buffer_len(b);
 				if (len % 8) { // fatal error
@@ -4888,12 +4486,9 @@
 					goto error;
 				}
 
-				if (EVP_Cipher(cipher_ctx, wrapped, buffer_ptr(b), len) == 0) {
+				if (EVP_Cipher(cc->evp, wrapped, buffer_ptr(b), len) == 0) {
 					goto error;
 				}
-				if (EVP_CIPHER_CTX_cleanup(cipher_ctx) == 0) {
-					goto error;
-				}
 
 				buffer_append(enc, wrapped, len);
 
@@ -4914,14 +4509,12 @@
 error:;
 				buffer_free(b);
 				buffer_free(enc);
-				if (cipher_ctx) {
-					EVP_CIPHER_CTX_free(cipher_ctx);
-				}
+				cipher_free_SSH2(cc);
 
 			} else if (private_key.type == KEY_ED25519) { // SSH2 ED25519 
 				save_bcrypt_private_key(buf, filename, comment, dlg, pvar, rounds);
 
-			} else { // SSH2 RSA, DSA, ECDSA			
+			} else { // SSH2 RSA, DSA, ECDSA
 				int len;
 				FILE *fp;
 				const EVP_CIPHER *cipher;
@@ -5082,7 +4675,7 @@
 			pvar->showing_err = TRUE;
 			pvar->err_msg = NULL;
 			MessageBox(NULL, msg, "TTSSH",
-					   MB_TASKMODAL | MB_ICONEXCLAMATION);
+			           MB_TASKMODAL | MB_ICONEXCLAMATION);
 			free(msg);
 			pvar->showing_err = FALSE;
 

Modified: branches/4-stable/ttssh2/ttxssh/ttxssh.h
===================================================================
--- branches/4-stable/ttssh2/ttxssh/ttxssh.h	2021-05-19 14:05:07 UTC (rev 9253)
+++ branches/4-stable/ttssh2/ttxssh/ttxssh.h	2021-05-19 14:11:12 UTC (rev 9254)
@@ -74,6 +74,11 @@
 #include "ssh.h"
 #include "auth.h"
 #include "crypt.h"
+#include "cipher.h"
+#include "comp.h"
+#include "kex.h"
+#include "hostkey.h"
+#include "key.h"
 #include "hosts.h"
 #include "fwd.h"
 
@@ -268,8 +273,8 @@
 	buffer_t *peer_kex;
 	kex_algorithm kex_type; // KEX algorithm
 	ssh_keytype hostkey_type;
-	SSH2Cipher *ciphers[MODE_MAX];
-	SSH2Mac *macs[MODE_MAX];
+	const struct ssh2cipher *ciphers[MODE_MAX];
+	const struct SSH2Mac *macs[MODE_MAX];
 	compression_type ctos_compression;
 	compression_type stoc_compression;
 	int we_need;
@@ -278,7 +283,7 @@
 	char *session_id;
 	int session_id_len;
 	SSHKeys ssh2_keys[MODE_MAX];
-	EVP_CIPHER_CTX *evpcip[MODE_MAX];
+	struct sshcipher_ctx *cc[MODE_MAX];
 	int userauth_success;
 	int shell_id;
 	int session_nego_status;

Modified: branches/4-stable/ttssh2/ttxssh/ttxssh.v16.vcxproj
===================================================================
--- branches/4-stable/ttssh2/ttxssh/ttxssh.v16.vcxproj	2021-05-19 14:05:07 UTC (rev 9253)
+++ branches/4-stable/ttssh2/ttxssh/ttxssh.v16.vcxproj	2021-05-19 14:11:12 UTC (rev 9254)
@@ -153,7 +153,11 @@
     <ClCompile Include="auth.c" />
     <ClCompile Include="buffer.c" />
     <ClCompile Include="chacha.c" />
+    <ClCompile Include="cipher.c" />
+    <ClCompile Include="cipher-3des1.c" />
+    <ClCompile Include="cipher-chachapoly-libcrypto.c" />
     <ClCompile Include="cipher-ctr.c" />
+    <ClCompile Include="comp.c" />
     <ClCompile Include="crypt.c" />
     <ClCompile Include="dns.c" />
     <ClCompile Include="ed25519.c" />
@@ -168,13 +172,17 @@
     <ClCompile Include="fwd-socks.c" />
     <ClCompile Include="fwd.c" />
     <ClCompile Include="fwdui.c" />
+    <ClCompile Include="hostkey.c" />
     <ClCompile Include="hosts.c" />
     <ClCompile Include="kex.c" />
     <ClCompile Include="key.c" />
     <ClCompile Include="keyfiles.c" />
+    <ClCompile Include="mac.c" />
     <ClCompile Include="pkt.c" />
+    <ClCompile Include="poly1305.c" />
     <ClCompile Include="sftp.c" />
     <ClCompile Include="ssh.c" />
+    <ClCompile Include="ssherr.c" />
     <ClCompile Include="ttxssh.c" />
     <ClCompile Include="util.c" />
     <ClCompile Include="x11util.c" />
@@ -186,6 +194,8 @@
     <ClInclude Include="buffer.h" />
     <ClInclude Include="chacha.h" />
     <ClInclude Include="cipher.h" />
+    <ClInclude Include="cipher-chachapoly.h" />
+    <ClInclude Include="comp.h" />
     <ClInclude Include="config.h" />
     <ClInclude Include="crypt.h" />
     <ClInclude Include="dns.h" />
@@ -197,14 +207,18 @@
     <ClInclude Include="fwd-socks.h" />
     <ClInclude Include="fwd.h" />
     <ClInclude Include="fwdui.h" />
+    <ClInclude Include="hostkey.h" />
     <ClInclude Include="hosts.h" />
     <ClInclude Include="kex.h" />
     <ClInclude Include="key.h" />
     <ClInclude Include="keyfiles.h" />
+    <ClInclude Include="mac.h" />
     <ClInclude Include="pkt.h" />
+    <ClInclude Include="poly1305.h" />
     <ClInclude Include="resource.h" />
     <ClInclude Include="sftp.h" />
     <ClInclude Include="ssh.h" />
+    <ClInclude Include="ssherr.h" />
     <ClInclude Include="ttxssh-version.h" />
     <ClInclude Include="ttxssh.h" />
     <ClInclude Include="util.h" />

Modified: branches/4-stable/ttssh2/ttxssh/ttxssh.v16.vcxproj.filters
===================================================================
--- branches/4-stable/ttssh2/ttxssh/ttxssh.v16.vcxproj.filters	2021-05-19 14:05:07 UTC (rev 9253)
+++ branches/4-stable/ttssh2/ttxssh/ttxssh.v16.vcxproj.filters	2021-05-19 14:11:12 UTC (rev 9254)
@@ -13,9 +13,21 @@
     <ClCompile Include="chacha.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="cipher.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="cipher-3des1.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="cipher-chachapoly-libcrypto.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="cipher-ctr.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="comp.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="crypt.c">
       <Filter>Source Files</Filter>
     </ClCompile>
@@ -58,6 +70,9 @@
     <ClCompile Include="fwdui.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="hostkey.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="hosts.c">
       <Filter>Source Files</Filter>
     </ClCompile>
@@ -70,6 +85,9 @@
     <ClCompile Include="keyfiles.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="mac.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="..\matcher\matcher.c">
       <Filter>Source Files</Filter>
     </ClCompile>
@@ -76,6 +94,9 @@
     <ClCompile Include="pkt.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="poly1305.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="sftp.c">
       <Filter>Source Files</Filter>
     </ClCompile>
@@ -82,6 +103,9 @@
     <ClCompile Include="ssh.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="ssherr.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="ttxssh.c">
       <Filter>Source Files</Filter>
     </ClCompile>
@@ -141,9 +165,15 @@
     <ClInclude Include="cipher.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="cipher-chachapoly.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
     <ClInclude Include="config.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="comp.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
     <ClInclude Include="crypt.h">
       <Filter>Header Files</Filter>
     </ClInclude>
@@ -171,6 +201,9 @@
     <ClInclude Include="fwdui.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="hostkey.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
     <ClInclude Include="hosts.h">
       <Filter>Header Files</Filter>
     </ClInclude>
@@ -183,9 +216,15 @@
     <ClInclude Include="keyfiles.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="mac.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
     <ClInclude Include="pkt.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="poly1305.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
     <ClInclude Include="sftp.h">
       <Filter>Header Files</Filter>
     </ClInclude>
@@ -192,6 +231,9 @@
     <ClInclude Include="ssh.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="ssherr.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
     <ClInclude Include="util.h">
       <Filter>Header Files</Filter>
     </ClInclude>

Modified: branches/4-stable/ttssh2/ttxssh/ttxssh.v8.vcproj
===================================================================
--- branches/4-stable/ttssh2/ttxssh/ttxssh.v8.vcproj	2021-05-19 14:05:07 UTC (rev 9253)
+++ branches/4-stable/ttssh2/ttxssh/ttxssh.v8.vcproj	2021-05-19 14:11:12 UTC (rev 9254)
@@ -236,10 +236,18 @@
 				>
 			</File>
 			<File
+				RelativePath="cipher-chachapoly.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\teraterm\common\codeconv.h"
 				>
 			</File>
 			<File
+				RelativePath="comp.h"
+				>
+			</File>
+			<File
 				RelativePath="config.h"
 				>
 			</File>
@@ -284,6 +292,10 @@
 				>
 			</File>
 			<File
+				RelativePath="hostkey.h"
+				>
+			</File>
+			<File
 				RelativePath="hosts.h"
 				>
 			</File>
@@ -300,10 +312,18 @@
 				>
 			</File>
 			<File
+				RelativePath="mac.h"
+				>
+			</File>
+			<File
 				RelativePath="pkt.h"
 				>
 			</File>
 			<File
+				RelativePath="poly1305.h"
+				>
+			</File>
+			<File
 				RelativePath="resource.h"
 				>
 			</File>
@@ -316,6 +336,10 @@
 				>
 			</File>
 			<File
+				RelativePath="ssherr.h"
+				>
+			</File>
+			<File
 				RelativePath="ttxssh-version.h"
 				>
 			</File>
@@ -352,6 +376,18 @@
 				>
 			</File>
 			<File
+				RelativePath="cipher.c"
+				>
+			</File>
+			<File
+				RelativePath="cipher-3des1.c"
+				>
+			</File>
+			<File
+				RelativePath="cipher-chachapoly-libcrypto.c"
+				>
+			</File>
+			<File
 				RelativePath="cipher-ctr.c"
 				>
 			</File>
@@ -360,6 +396,10 @@
 				>
 			</File>
 			<File
+				RelativePath="comp.c"
+				>
+			</File>
+			<File
 				RelativePath="crypt.c"
 				>
 			</File>
@@ -428,6 +468,10 @@
 				>
 			</File>
 			<File
+				RelativePath="hostkey.c"
+				>
+			</File>
+			<File
 				RelativePath="hosts.c"
 				>
 			</File>
@@ -444,6 +488,10 @@
 				>
 			</File>
 			<File
+				RelativePath="mac.c"
+				>
+			</File>
+			<File
 				RelativePath="..\matcher\matcher.c"
 				>
 			</File>
@@ -452,6 +500,10 @@
 				>
 			</File>
 			<File
+				RelativePath="poly1305.c"
+				>
+			</File>
+			<File
 				RelativePath="sftp.c"
 				>
 			</File>
@@ -460,6 +512,10 @@
 				>
 			</File>
 			<File
+				RelativePath="ssherr.c"
+				>
+			</File>
+			<File
 				RelativePath="..\..\teraterm\common\tipwin.cpp"
 				>
 			</File>


Ttssh2-commit メーリングリストの案内
Back to archive index