[Ttssh2-commit] [6985] SSH2 暗号化アルゴリズムとして aes{128 , 256}-gcm****@opens***** に対応した。

Back to archive index

scmno****@osdn***** scmno****@osdn*****
2017年 11月 26日 (日) 00:26:45 JST


Revision: 6985
          http://sourceforge.jp/projects/ttssh2/scm/svn/commits/6985
Author:   doda
Date:     2017-11-26 00:26:45 +0900 (Sun, 26 Nov 2017)
Log Message:
-----------
SSH2 暗号化アルゴリズムとして aes{128,256}-gcm****@opens***** に対応した。

Modified Paths:
--------------
    trunk/installer/release/TERATERM.INI
    trunk/ttssh2/ttxssh/cipher.h
    trunk/ttssh2/ttxssh/crypt.c
    trunk/ttssh2/ttxssh/crypt.h
    trunk/ttssh2/ttxssh/keyfiles.c
    trunk/ttssh2/ttxssh/pkt.c
    trunk/ttssh2/ttxssh/ssh.c
    trunk/ttssh2/ttxssh/ssh.h
    trunk/ttssh2/ttxssh/ttxssh.c

-------------- next part --------------
Modified: trunk/installer/release/TERATERM.INI
===================================================================
--- trunk/installer/release/TERATERM.INI	2017-11-25 15:26:39 UTC (rev 6984)
+++ trunk/installer/release/TERATERM.INI	2017-11-25 15:26:45 UTC (rev 6985)
@@ -797,9 +797,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
+;  J...Camellia192-CTR, K...Camellia256-CTR  L...A****@opens*****
+;  M...A****@opens*****
 ;  0...Ciphers below this line are disabled.
-CipherOrder=K>H:J=G9I<F8C7D;EB30A@?62
+CipherOrder=MLK>H:J=G9I<F8C7D;EB30A@?62
 
 ; KEX algorithm order(SSH2)
 ;  1...diffie-hellman-group1-sha1

Modified: trunk/ttssh2/ttxssh/cipher.h
===================================================================
--- trunk/ttssh2/ttxssh/cipher.h	2017-11-25 15:26:39 UTC (rev 6984)
+++ trunk/ttssh2/ttxssh/cipher.h	2017-11-25 15:26:45 UTC (rev 6985)
@@ -95,6 +95,7 @@
 		int encrypt,
 		const EVP_CIPHER *type,
 		int discard_len,
+		unsigned int authlen,
 		PTInstVar pvar
 );
 

Modified: trunk/ttssh2/ttxssh/crypt.c
===================================================================
--- trunk/ttssh2/ttxssh/crypt.c	2017-11-25 15:26:39 UTC (rev 6984)
+++ trunk/ttssh2/ttxssh/crypt.c	2017-11-25 15:26:45 UTC (rev 6985)
@@ -198,6 +198,113 @@
 	}
 }
 
+BOOL CRYPT_encrypt_aead(PTInstVar pvar, unsigned char *data, unsigned int bytes, unsigned int aadlen, unsigned int authlen)
+{
+	unsigned char *newbuf = NULL;
+	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];
+
+	if (bytes == 0)
+		return TRUE;
+
+	if (bytes % block_size) {
+		UTIL_get_lang_msg("MSG_ENCRYPT_ERROR1", pvar, "%s encrypt error(1): bytes %d (%d)");
+		_snprintf_s(tmp, sizeof(tmp), _TRUNCATE, pvar->ts->UIMsg,
+		            get_cipher_name(pvar->crypt_state.sender_cipher),
+		            bytes, block_size);
+		notify_fatal_error(pvar, tmp, TRUE);
+		return FALSE;
+	}
+
+	if ((newbuf = malloc(bytes)) == NULL)
+		goto err;
+
+	if (!EVP_CIPHER_CTX_ctrl(evp, EVP_CTRL_GCM_IV_GEN, 1, lastiv))
+		goto err;
+
+	if (aadlen && !EVP_Cipher(evp, NULL, data, aadlen) < 0)
+		goto err;
+
+	if (EVP_Cipher(evp, newbuf, data+aadlen, bytes) < 0)
+		goto err;
+
+	memcpy(data+aadlen, newbuf, bytes);
+
+	if (EVP_Cipher(evp, NULL, NULL, 0) < 0)
+		goto err;
+
+	if (!EVP_CIPHER_CTX_ctrl(evp, EVP_CTRL_GCM_GET_TAG, authlen, data+aadlen+bytes))
+		goto err;
+
+	free(newbuf);
+
+	return TRUE;
+
+err:
+	free(newbuf);
+
+	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));
+	notify_fatal_error(pvar, tmp, TRUE);
+	return FALSE;
+}
+
+BOOL CRYPT_decrypt_aead(PTInstVar pvar, unsigned char *data, unsigned int bytes, unsigned int aadlen, unsigned int authlen)
+{
+	unsigned char *newbuf = NULL;
+	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];
+
+	if (bytes == 0)
+		return TRUE;
+
+	if (bytes % block_size) {
+		UTIL_get_lang_msg("MSG_DECRYPT_ERROR1", pvar, "%s decrypt error(1): bytes %d (%d)");
+		_snprintf_s(tmp, sizeof(tmp), _TRUNCATE, pvar->ts->UIMsg,
+		            get_cipher_name(pvar->crypt_state.receiver_cipher),
+		            bytes, block_size);
+		notify_fatal_error(pvar, tmp, TRUE);
+		return FALSE;
+	}
+
+	if ((newbuf = malloc(bytes)) == NULL)
+		goto err;
+
+	if (!EVP_CIPHER_CTX_ctrl(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))
+		goto err;
+
+	if (aadlen && !EVP_Cipher(evp, NULL, data, aadlen) < 0)
+		goto err;
+
+	if (EVP_Cipher(evp, newbuf, data+aadlen, bytes) < 0)
+		goto err;
+
+	memcpy(data+aadlen, newbuf, bytes);
+	free(newbuf);
+
+	if (EVP_Cipher(evp, NULL, NULL, 0) < 0)
+		return FALSE;
+	else
+		return TRUE;
+
+err:
+	free(newbuf);
+
+	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));
+	notify_fatal_error(pvar, tmp, TRUE);
+	return FALSE;
+}
+
 static void no_encrypt(PTInstVar pvar, unsigned char *buf, int bytes)
 {
 }
@@ -468,6 +575,8 @@
 		            | (1 << SSH2_CIPHER_CAMELLIA128_CTR)
 		            | (1 << SSH2_CIPHER_CAMELLIA192_CTR)
 		            | (1 << SSH2_CIPHER_CAMELLIA256_CTR)
+		            | (1 << SSH2_CIPHER_AES128_GCM)
+		            | (1 << SSH2_CIPHER_AES256_GCM)
 		);
 	}
 
@@ -870,6 +979,7 @@
                       int encrypt,
                       const EVP_CIPHER *type,
                       int discard_len,
+                      unsigned int authlen,
                       PTInstVar pvar)
 {
 	int klen;
@@ -877,28 +987,44 @@
 	unsigned char *junk = NULL, *discard = NULL;
 
 	EVP_CIPHER_CTX_init(evp);
-	if (EVP_CipherInit(evp, type, NULL, (u_char *)iv, (encrypt == CIPHER_ENCRYPT)) == 0) {
-		UTIL_get_lang_msg("MSG_CIPHER_INIT_ERROR", pvar,
-		                  "Cipher initialize error(%d)");
+	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, 2);
+			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, 3);
+		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;
 	}
@@ -908,10 +1034,8 @@
 		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, 3);
+			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 {
@@ -969,10 +1093,11 @@
 				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_block_size(cipher),
+				                 enc->iv, get_cipher_iv_len(cipher),
 				                 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;
@@ -1014,10 +1139,11 @@
 				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_block_size(cipher),
+				                 enc->iv, get_cipher_iv_len(cipher),
 				                 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;
@@ -1110,6 +1236,10 @@
 		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";

Modified: trunk/ttssh2/ttxssh/crypt.h
===================================================================
--- trunk/ttssh2/ttxssh/crypt.h	2017-11-25 15:26:39 UTC (rev 6984)
+++ trunk/ttssh2/ttxssh/crypt.h	2017-11-25 15:26:45 UTC (rev 6985)
@@ -150,6 +150,9 @@
 #define CRYPT_decrypt(pvar, buf, bytes) \
     ((pvar)->crypt_state.decrypt((pvar), (buf), (bytes)))
 
+BOOL CRYPT_encrypt_aead(PTInstVar pvar, unsigned char *data, unsigned int len, unsigned int aadlen, unsigned int authlen);
+BOOL CRYPT_decrypt_aead(PTInstVar pvar, unsigned char *data, unsigned int len, unsigned int aadlen, unsigned int authlen);
+
 BOOL CRYPT_detect_attack(PTInstVar pvar, unsigned char *buf, int bytes);
 int CRYPT_passphrase_decrypt(int cipher, char *passphrase, char *buf, int len);
 RSA *make_key(PTInstVar pvar,

Modified: trunk/ttssh2/ttxssh/keyfiles.c
===================================================================
--- trunk/ttssh2/ttxssh/keyfiles.c	2017-11-25 15:26:39 UTC (rev 6984)
+++ trunk/ttssh2/ttxssh/keyfiles.c	2017-11-25 15:26:45 UTC (rev 6985)
@@ -542,7 +542,7 @@
 	// \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(ciphernameval), 0, pvar);
+		get_cipher_EVP_CIPHER(ciphernameval), 0, 0, pvar);
 	if (EVP_Cipher(&cipher_ctx, cp, buffer_tail_ptr(copy_consumed), len) == 0) {
 		cipher_cleanup_SSH2(&cipher_ctx);
 		goto error;
@@ -931,7 +931,7 @@
 		memset(iv, 0, sizeof(iv));
 
 		// decrypt
-		cipher_init_SSH2(&cipher_ctx, key, 32, iv, 16, CIPHER_DECRYPT, EVP_aes_256_cbc(), 0, pvar);
+		cipher_init_SSH2(&cipher_ctx, key, 32, iv, 16, CIPHER_DECRYPT, EVP_aes_256_cbc(), 0, 0, pvar);
 		len = buffer_len(prikey);
 		decrypted = (char *)malloc(len);
 		if (EVP_Cipher(&cipher_ctx, decrypted, prikey->buf, len) == 0) {
@@ -1466,7 +1466,7 @@
 		memset(iv, 0, sizeof(iv));
 
 		// decrypt
-		cipher_init_SSH2(&cipher_ctx, key, 24, iv, 8, CIPHER_DECRYPT, EVP_des_ede3_cbc(), 0, pvar);
+		cipher_init_SSH2(&cipher_ctx, key, 24, iv, 8, CIPHER_DECRYPT, EVP_des_ede3_cbc(), 0, 0, pvar);
 		decrypted = (char *)malloc(len);
 		if (EVP_Cipher(&cipher_ctx, decrypted, blob->buf + blob->offset, len) == 0) {
 			strncpy_s(errmsg, errmsg_len, "Key decrypt error", _TRUNCATE);

Modified: trunk/ttssh2/ttxssh/pkt.c
===================================================================
--- trunk/ttssh2/ttxssh/pkt.c	2017-11-25 15:26:39 UTC (rev 6984)
+++ trunk/ttssh2/ttxssh/pkt.c	2017-11-25 15:26:45 UTC (rev 6985)
@@ -180,16 +180,30 @@
 			uint32 pktsize;
 			uint32 total_packet_size;
 			struct Mac *mac = &pvar->ssh2_keys[MODE_IN].mac;
-			int etm;
+			struct Enc *enc = &pvar->ssh2_keys[MODE_IN].enc;
+			int aadlen;
 
-			etm = mac && mac->enabled && mac->etm;
+			/*
+			 * 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;
+			}
+			else {
+				aadlen = 0;
+			}
 
 			/*
-			 * \x92ʏ\xED\x82\xCC MAC \x95\xFB\x8E\xAE (E&M: Encrypt & MAC) \x82ł̓p\x83P\x83b\x83g\x92\xB7\x95\x94\x95\xAA\x82\xE0\x88Í\x86\x89\xBB\x82\xB3\x82\xEA\x82Ă\xA2\x82邽\x82߁A
-			 * \x90擪\x82\xCC 1 \x83u\x83\x8D\x83b\x83N\x82𕜍\x86\x82\xB7\x82\xE9\x81BMAC \x95\x{33AE0AA} EtM (Encrypt then MAC) \x82̎\x9E\x81A\x82\xA8\x82\xE6\x82\xD1 SSH1 \x82ł\xCD
-			 * \x83p\x83P\x83b\x83g\x92\xB7\x95\x94\x95\xAA\x82͈Í\x86\x89\xBB\x82\xB3\x82\xEA\x82Ă\xA2\x82Ȃ\xA2\x82̂ŕ\x9C\x8D\x86\x82͕K\x97v\x96\xB3\x82\xA2\x81B
+			 * 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 && !etm) {
+			if (SSHv2(pvar) && !pvar->pkt_state.predecrypted_packet && aadlen == 0) {
 				SSH_predecrpyt_packet(pvar, data);
 				pvar->pkt_state.predecrypted_packet = TRUE;
 			}
@@ -208,7 +222,7 @@
 
 			// \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_clear_MAC_size(pvar);
+			total_packet_size = pktsize + 4 + 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
@@ -219,7 +233,7 @@
 				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, etm);
+					SSH2_handle_packet(pvar, data, pktsize, aadlen, enc->auth_len);
 				}
 
 				pvar->pkt_state.predecrypted_packet = FALSE;

Modified: trunk/ttssh2/ttxssh/ssh.c
===================================================================
--- trunk/ttssh2/ttxssh/ssh.c	2017-11-25 15:26:39 UTC (rev 6984)
+++ trunk/ttssh2/ttxssh/ssh.c	2017-11-25 15:26:45 UTC (rev 6985)
@@ -784,14 +784,22 @@
  * \x88\xF8\x90\x94:
  *   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)
- *   etm - MAC \x95\x{33AE0AA} EtM \x82\xA9\x82ǂ\xA4\x82\xA9\x82̃t\x83\x89\x83O
+ *   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
+ *   authlen - \x94F\x8F؃f\x81[\x83^(AEAD tag)\x92\xB7
  */
 
-static int prep_packet_ssh2(PTInstVar pvar, char *data, unsigned int len, int etm)
+static int prep_packet_ssh2(PTInstVar pvar, char *data, unsigned int len, unsigned int aadlen, unsigned int authlen)
 {
 	unsigned int padding;
 
-	if (etm) {
+	if (authlen > 0) {
+		if (!CRYPT_decrypt_aead(pvar, data, len, aadlen, authlen)) {
+			UTIL_get_lang_msg("MSG_SSH_CORRUPTDATA_ERROR", pvar, "Detected corrupted data; connection terminating.");
+			notify_fatal_error(pvar, pvar->ts->UIMsg, TRUE);
+			return SSH_MSG_NONE;
+		}
+	}
+	else if (aadlen > 0) {
 		// EtM \x82̏ꍇ\x82͐\xE6\x82\xC9 MAC \x82̌\x9F\x8F؂\xF0\x8Ds\x82\xA4
 		if (!CRYPT_verify_receiver_MAC(pvar, pvar->ssh_state.receiver_sequence_number, data, len + 4, data + len + 4)) {
 			UTIL_get_lang_msg("MSG_SSH_CORRUPTDATA_ERROR", pvar, "Detected corrupted data; connection terminating.");
@@ -1025,7 +1033,8 @@
 		unsigned int padding;
 		BOOL ret;
 		struct Mac *mac = &pvar->ssh2_keys[MODE_OUT].mac;
-		unsigned int aadlen = 0, maclen = 0;
+		struct Enc *enc = &pvar->ssh2_keys[MODE_OUT].enc;
+		unsigned int aadlen = 0, maclen = 0, authlen = 0;
 
 		/*
 		 \x83f\x81[\x83^\x8D\\x91\xA2
@@ -1078,7 +1087,11 @@
 			block_size = 8;
 		}
 
-		if (mac && mac->etm) {
+		if (enc) {
+			authlen = enc->auth_len;
+		}
+
+		if (mac && mac->etm || authlen > 0) {
 			// \x88Í\x86\x89\xBB\x91Ώۂł͖\xB3\x82\xA2\x82\xAA\x81AMAC \x82̑ΏۂƂȂ镔\x95\xAA\x82̒\xB7\x82\xB3
 			aadlen = 4;
 		}
@@ -1099,25 +1112,31 @@
 
 		CRYPT_set_random_data(pvar, data + 5 + len, padding);
 
-		if (aadlen == 0) {
-			// E&M \x82ł͐\xE6\x82\xC9 MAC \x82\xF0\x8Cv\x8EZ\x82\xB7\x82\xE9
+		if (authlen > 0) {
+			CRYPT_encrypt_aead(pvar, data, encryption_size, aadlen, authlen);
+			maclen = authlen;
+		}
+		else if (aadlen) {
+			// \x83p\x83P\x83b\x83g\x88Í\x86\x89\xBB
+			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
 			ret = CRYPT_build_sender_MAC(pvar, pvar->ssh_state.sender_sequence_number,
-			                             data, encryption_size, data + encryption_size);
+			                             data, aadlen + encryption_size, data + aadlen + encryption_size);
 			if (ret) {
 				maclen = CRYPT_get_sender_MAC_size(pvar);
 			}
 		}
-
-		// \x83p\x83P\x83b\x83g\x82\xF0\x88Í\x86\x89\xBB\x82\xB7\x82\xE9\x81BMAC\x88ȍ~\x82͈Í\x86\x89\xBB\x91ΏۊO\x81B
-		CRYPT_encrypt(pvar, data + aadlen, encryption_size);
-
-		if (aadlen) {
-			// EtM \x82ł͈Í\x86\x89\xBB\x8C\xE3\x82\xC9 MAC \x82\xF0\x8Cv\x8EZ\x82\xB7\x82\xE9
+		else {
+			// E&M \x82ł͐\xE6\x82\xC9 MAC \x82\xF0\x8Cv\x8EZ\x82\xB7\x82\xE9
 			ret = CRYPT_build_sender_MAC(pvar, pvar->ssh_state.sender_sequence_number,
-			                             data, aadlen + encryption_size, data + aadlen + encryption_size);
+			                             data, encryption_size, data + encryption_size);
 			if (ret) {
 				maclen = CRYPT_get_sender_MAC_size(pvar);
 			}
+
+			// \x83p\x83P\x83b\x83g\x88Í\x86\x89\xBB
+			CRYPT_encrypt(pvar, data, encryption_size);
 		}
 
 		data_length = encryption_size + aadlen + maclen;
@@ -2115,9 +2134,9 @@
 	}
 }
 
-void SSH2_handle_packet(PTInstVar pvar, char *data, unsigned int len, int etm)
+void SSH2_handle_packet(PTInstVar pvar, char *data, unsigned int len, unsigned int aadlen, unsigned int authlen)
 {
-	unsigned char message = prep_packet_ssh2(pvar, data, len, etm);
+	unsigned char message = prep_packet_ssh2(pvar, data, len, aadlen, authlen);
 
 	// SSH\x82̃\x81\x83b\x83Z\x81[\x83W\x83^\x83C\x83v\x82\xF0\x83`\x83F\x83b\x83N
 	if (message != SSH_MSG_NONE) {
@@ -2925,6 +2944,28 @@
 	}
 }
 
+unsigned int SSH_get_authdata_size(PTInstVar pvar, int direction)
+{
+	if (SSHv1(pvar)) {
+		return 0;
+	}
+	else {
+		struct Mac *mac = &pvar->ssh2_keys[direction].mac;
+		struct Enc *enc = &pvar->ssh2_keys[direction].enc;
+
+		if (enc && enc->auth_len > 0) {
+			// AEAD
+			return enc->auth_len;
+		}
+		else if (mac && mac->enabled) {
+			return mac->mac_len;
+		}
+		else {
+			return 0;
+		}
+	}
+}
+
 void SSH_notify_user_name(PTInstVar pvar)
 {
 	try_send_user_name(pvar);
@@ -4095,6 +4136,41 @@
 	return 0;
 }
 
+int get_cipher_iv_len(SSHCipher cipher)
+{
+	ssh2_cipher_t *ptr = ssh2_ciphers;
+
+	while (ptr->name != NULL) {
+		if (cipher == ptr->cipher) {
+			if (ptr->iv_len != 0) {
+				return ptr->iv_len;
+			}
+			else {
+				return ptr->block_size;
+			}
+		}
+		ptr++;
+	}
+
+	// not found.
+	return 8; // block_size
+}
+
+int get_cipher_auth_len(SSHCipher cipher)
+{
+	ssh2_cipher_t *ptr = ssh2_ciphers;
+
+	while (ptr->name != NULL) {
+		if (cipher == ptr->cipher) {
+			return ptr->auth_len;
+		}
+		ptr++;
+	}
+
+	// not found.
+	return 0;
+}
+
 // \x88Í\x86\x83A\x83\x8B\x83S\x83\x8A\x83Y\x83\x80\x96\xBC\x82\xA9\x82猟\x8D\x{142DC2}\xE9\x81B
 SSHCipher get_cipher_by_name(char *name)
 {
@@ -4410,6 +4486,12 @@
 			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;
 		}
@@ -4772,6 +4854,9 @@
 		// \x83L\x81[\x83T\x83C\x83Y\x82ƃu\x83\x8D\x83b\x83N\x83T\x83C\x83Y\x82\xE0\x82\xB1\x82\xB1\x82Őݒ肵\x82Ă\xA8\x82\xAD (2004.11.7 yutaka)
 		current_keys[mode].enc.key_len = get_cipher_key_len(cipher);
 		current_keys[mode].enc.block_size = get_cipher_block_size(cipher);
+		current_keys[mode].enc.iv_len = get_cipher_iv_len(cipher);
+		current_keys[mode].enc.auth_len = get_cipher_auth_len(cipher);
+
 		current_keys[mode].mac.enabled = 0;
 		current_keys[mode].comp.enabled = 0; // (2005.7.9 yutaka)
 
@@ -4783,6 +4868,7 @@
 	for (mode = 0; mode < MODE_MAX; mode++) {
 		need = max(need, current_keys[mode].enc.key_len);
 		need = max(need, current_keys[mode].enc.block_size);
+		need = max(need, current_keys[mode].enc.iv_len);
 		need = max(need, current_keys[mode].mac.key_len);
 	}
 	pvar->we_need = need;
@@ -5645,7 +5731,6 @@
 	} else {
 		// \x8F\x89\x89\xF1\x90ڑ\xB1\x82̏ꍇ\x82͎\xC0\x8DۂɈÍ\x86\x83\x8B\x81[\x83`\x83\x93\x82\xAA\x90ݒ肳\x82\xEA\x82\xE9\x82̂́A\x82\xA0\x82ƂɂȂ\xC1\x82Ă\xA9\x82\xE7
 		// \x82Ȃ̂ŁiCRYPT_start_encryption\x8A֐\x94\x81j\x81A\x82\xB1\x82\xB1\x82Ō\xAE\x82̐ݒ\xE8\x82\xF0\x82\xB5\x82Ă\xB5\x82܂\xC1\x82Ă\xE0\x82悢\x81B
-		ssh2_set_newkeys(pvar, MODE_IN);
 		ssh2_set_newkeys(pvar, MODE_OUT);
 
 		// SSH2_MSG_NEWKEYS\x82𑗐M\x82\xB5\x82\xBD\x8E\x9E\x93_\x82ŁAMAC\x82\xF0\x97L\x8C\xF8\x82ɂ\xB7\x82\xE9\x81B(2006.10.30 yutaka)
@@ -5880,7 +5965,6 @@
 	} else {
 		// \x8F\x89\x89\xF1\x90ڑ\xB1\x82̏ꍇ\x82͎\xC0\x8DۂɈÍ\x86\x83\x8B\x81[\x83`\x83\x93\x82\xAA\x90ݒ肳\x82\xEA\x82\xE9\x82̂́A\x82\xA0\x82ƂɂȂ\xC1\x82Ă\xA9\x82\xE7
 		// \x82Ȃ̂ŁiCRYPT_start_encryption\x8A֐\x94\x81j\x81A\x82\xB1\x82\xB1\x82Ō\xAE\x82̐ݒ\xE8\x82\xF0\x82\xB5\x82Ă\xB5\x82܂\xC1\x82Ă\xE0\x82悢\x81B
-		ssh2_set_newkeys(pvar, MODE_IN);
 		ssh2_set_newkeys(pvar, MODE_OUT);
 
 		// SSH2_MSG_NEWKEYS\x82𑗐M\x82\xB5\x82\xBD\x8E\x9E\x93_\x82ŁAMAC\x82\xF0\x97L\x8C\xF8\x82ɂ\xB7\x82\xE9\x81B(2006.10.30 yutaka)
@@ -6112,7 +6196,6 @@
 	} else {
 		// \x8F\x89\x89\xF1\x90ڑ\xB1\x82̏ꍇ\x82͎\xC0\x8DۂɈÍ\x86\x83\x8B\x81[\x83`\x83\x93\x82\xAA\x90ݒ肳\x82\xEA\x82\xE9\x82̂́A\x82\xA0\x82ƂɂȂ\xC1\x82Ă\xA9\x82\xE7
 		// \x82Ȃ̂ŁiCRYPT_start_encryption\x8A֐\x94\x81j\x81A\x82\xB1\x82\xB1\x82Ō\xAE\x82̐ݒ\xE8\x82\xF0\x82\xB5\x82Ă\xB5\x82܂\xC1\x82Ă\xE0\x82悢\x81B
-		ssh2_set_newkeys(pvar, MODE_IN);
 		ssh2_set_newkeys(pvar, MODE_OUT);
 
 		// SSH2_MSG_NEWKEYS\x82𑗐M\x82\xB5\x82\xBD\x8E\x9E\x93_\x82ŁAMAC\x82\xF0\x97L\x8C\xF8\x82ɂ\xB7\x82\xE9\x81B(2006.10.30 yutaka)
@@ -6238,6 +6321,8 @@
 	                       | 1 << SSH2_CIPHER_CAMELLIA128_CTR
 	                       | 1 << SSH2_CIPHER_CAMELLIA192_CTR
 	                       | 1 << SSH2_CIPHER_CAMELLIA256_CTR
+	                       | 1 << SSH2_CIPHER_AES128_GCM
+	                       | 1 << SSH2_CIPHER_AES256_GCM
 	);
 	int type = (1 << SSH_AUTH_PASSWORD) | (1 << SSH_AUTH_RSA) |
 	           (1 << SSH_AUTH_TIS) | (1 << SSH_AUTH_PAGEANT);
@@ -6268,6 +6353,7 @@
 
 	} else {
 		// SSH2_MSG_NEWKEYS\x82\xF0\x8E󂯎\xE6\x82\xC1\x82\xBD\x8E\x9E\x93_\x82ŁAMAC\x82\xF0\x97L\x8C\xF8\x82ɂ\xB7\x82\xE9\x81B(2006.10.30 yutaka)
+		ssh2_set_newkeys(pvar, MODE_IN);
 		pvar->ssh2_keys[MODE_IN].mac.enabled = 1;
 		pvar->ssh2_keys[MODE_IN].comp.enabled = 1;
 

Modified: trunk/ttssh2/ttxssh/ssh.h
===================================================================
--- trunk/ttssh2/ttxssh/ssh.h	2017-11-25 15:26:39 UTC (rev 6984)
+++ trunk/ttssh2/ttxssh/ssh.h	2017-11-25 15:26:45 UTC (rev 6985)
@@ -95,7 +95,8 @@
 	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,
-	SSH_CIPHER_MAX = SSH2_CIPHER_CAMELLIA256_CTR,
+	SSH2_CIPHER_AES128_GCM, SSH2_CIPHER_AES256_GCM,
+	SSH_CIPHER_MAX = SSH2_CIPHER_AES256_GCM,
 } SSHCipher;
 
 typedef enum {
@@ -380,40 +381,44 @@
 	int block_size;
 	int key_len;
 	int discard_len;
+	int iv_len;
+	int auth_len;
 	const EVP_CIPHER *(*func)(void);
 } ssh2_cipher_t;
 
 static ssh2_cipher_t ssh2_ciphers[] = {
-	{SSH2_CIPHER_3DES_CBC,        "3des-cbc",         8, 24,    0, EVP_des_ede3_cbc},     // RFC4253
-	{SSH2_CIPHER_AES128_CBC,      "aes128-cbc",      16, 16,    0, EVP_aes_128_cbc},      // RFC4253
-	{SSH2_CIPHER_AES192_CBC,      "aes192-cbc",      16, 24,    0, EVP_aes_192_cbc},      // RFC4253
-	{SSH2_CIPHER_AES256_CBC,      "aes256-cbc",      16, 32,    0, EVP_aes_256_cbc},      // RFC4253
-	{SSH2_CIPHER_BLOWFISH_CBC,    "blowfish-cbc",     8, 16,    0, EVP_bf_cbc},           // RFC4253
-	{SSH2_CIPHER_AES128_CTR,      "aes128-ctr",      16, 16,    0, evp_aes_128_ctr},      // RFC4344
-	{SSH2_CIPHER_AES192_CTR,      "aes192-ctr",      16, 24,    0, evp_aes_128_ctr},      // RFC4344
-	{SSH2_CIPHER_AES256_CTR,      "aes256-ctr",      16, 32,    0, evp_aes_128_ctr},      // RFC4344
-	{SSH2_CIPHER_ARCFOUR,         "arcfour",          8, 16,    0, EVP_rc4},              // RFC4253
-	{SSH2_CIPHER_ARCFOUR128,      "arcfour128",       8, 16, 1536, EVP_rc4},              // RFC4345
-	{SSH2_CIPHER_ARCFOUR256,      "arcfour256",       8, 32, 1536, EVP_rc4},              // RFC4345
-	{SSH2_CIPHER_CAST128_CBC,     "cast128-cbc",      8, 16,    0, EVP_cast5_cbc},        // RFC4253
-	{SSH2_CIPHER_3DES_CTR,        "3des-ctr",         8, 24,    0, evp_des3_ctr},         // RFC4344
-	{SSH2_CIPHER_BLOWFISH_CTR,    "blowfish-ctr",     8, 32,    0, evp_bf_ctr},           // RFC4344
-	{SSH2_CIPHER_CAST128_CTR,     "cast128-ctr",      8, 16,    0, evp_cast5_ctr},        // RFC4344
-	{SSH2_CIPHER_CAMELLIA128_CBC, "camellia128-cbc", 16, 16,    0, EVP_camellia_128_cbc}, // draft-kanno-secsh-camellia-02
-	{SSH2_CIPHER_CAMELLIA192_CBC, "camellia192-cbc", 16, 24,    0, EVP_camellia_192_cbc}, // draft-kanno-secsh-camellia-02
-	{SSH2_CIPHER_CAMELLIA256_CBC, "camellia256-cbc", 16, 32,    0, EVP_camellia_256_cbc}, // draft-kanno-secsh-camellia-02
-	{SSH2_CIPHER_CAMELLIA128_CTR, "camellia128-ctr", 16, 16,    0, evp_camellia_128_ctr}, // draft-kanno-secsh-camellia-02
-	{SSH2_CIPHER_CAMELLIA192_CTR, "camellia192-ctr", 16, 24,    0, evp_camellia_128_ctr}, // draft-kanno-secsh-camellia-02
-	{SSH2_CIPHER_CAMELLIA256_CTR, "camellia256-ctr", 16, 32,    0, evp_camellia_128_ctr}, // draft-kanno-secsh-camellia-02
+	{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, EVP_camellia_128_cbc},
-	{SSH2_CIPHER_CAMELLIA192_CBC, "camel****@opens*****", 16, 24, 0, EVP_camellia_192_cbc},
-	{SSH2_CIPHER_CAMELLIA256_CBC, "camel****@opens*****", 16, 32, 0, EVP_camellia_256_cbc},
-	{SSH2_CIPHER_CAMELLIA128_CTR, "camel****@opens*****", 16, 16, 0, evp_camellia_128_ctr},
-	{SSH2_CIPHER_CAMELLIA192_CTR, "camel****@opens*****", 16, 24, 0, evp_camellia_128_ctr},
-	{SSH2_CIPHER_CAMELLIA256_CTR, "camel****@opens*****", 16, 32, 0, evp_camellia_128_ctr},
+	{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
-	{SSH_CIPHER_NONE,          NULL,            0,  0, 0,    NULL},
+	{SSH2_CIPHER_AES128_GCM,      "aes12****@opens*****",      16, 16, 0, 12, 16, EVP_aes_128_gcm},
+	{SSH2_CIPHER_AES256_GCM,      "aes25****@opens*****",      16, 32, 0, 12, 16, EVP_aes_256_gcm},
+	{SSH_CIPHER_NONE,             NULL,               0,  0,    0, 0, 0, NULL},
 };
 
 
@@ -532,6 +537,8 @@
 	u_char          *iv;
 	unsigned int    key_len;
 	unsigned int    block_size;
+	unsigned int    iv_len;
+	unsigned int    auth_len;
 };
 
 struct Mac {
@@ -713,7 +720,7 @@
    'data' points to the start of the packet data (the length field)
 */
 void SSH1_handle_packet(PTInstVar pvar, char *data, unsigned int len, unsigned int padding);
-void SSH2_handle_packet(PTInstVar pvar, char *data, unsigned int len, int etm);
+void SSH2_handle_packet(PTInstVar pvar, char *data, unsigned int len, unsigned int aadlen, unsigned int authlen);
 void SSH_notify_win_size(PTInstVar pvar, int cols, int rows);
 void SSH_notify_user_name(PTInstVar pvar);
 void SSH_notify_cred(PTInstVar pvar);
@@ -756,6 +763,7 @@
    at least 5 bytes must be decrypted */
 void SSH_predecrpyt_packet(PTInstVar pvar, char *data);
 unsigned int SSH_get_clear_MAC_size(PTInstVar pvar);
+unsigned int SSH_get_authdata_size(PTInstVar pvar, int direction);
 
 #define SSH_is_any_payload(pvar) ((pvar)->ssh_state.payload_datalen > 0)
 #define SSH_get_host_name(pvar) ((pvar)->ssh_state.hostname)
@@ -767,6 +775,8 @@
 void debug_print(int no, char *msg, int len);
 int get_cipher_block_size(SSHCipher cipher);
 int get_cipher_key_len(SSHCipher cipher);
+int get_cipher_iv_len(SSHCipher cipher);
+int get_cipher_auth_len(SSHCipher cipher);
 SSHCipher get_cipher_by_name(char *name);
 char* get_kex_algorithm_name(kex_algorithm kextype);
 const EVP_CIPHER* get_cipher_EVP_CIPHER(SSHCipher cipher);

Modified: trunk/ttssh2/ttxssh/ttxssh.c
===================================================================
--- trunk/ttssh2/ttxssh/ttxssh.c	2017-11-25 15:26:39 UTC (rev 6984)
+++ trunk/ttssh2/ttxssh/ttxssh.c	2017-11-25 15:26:45 UTC (rev 6985)
@@ -280,6 +280,7 @@
 	/* 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,
@@ -288,6 +289,7 @@
 		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,
@@ -2603,6 +2605,10 @@
 		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;
@@ -4170,7 +4176,7 @@
 	// 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(ciphernameval), 0, pvar);
+		get_cipher_EVP_CIPHER(ciphernameval), 0, 0, pvar);
 	SecureZeroMemory(key, keylen + ivlen);
 	free(key);
 
@@ -4983,9 +4989,9 @@
 				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, pvar);
+					cipher_init_SSH2(&cipher_ctx, digest, 16, NULL, 0, CIPHER_ENCRYPT, EVP_enc_null(), 0, 0, pvar);
 				} else {
-					cipher_init_SSH2(&cipher_ctx, digest, 16, NULL, 0, CIPHER_ENCRYPT, evp_ssh1_3des(), 0, pvar);
+					cipher_init_SSH2(&cipher_ctx, digest, 16, NULL, 0, CIPHER_ENCRYPT, evp_ssh1_3des(), 0, 0, pvar);
 				}
 				len = buffer_len(b);
 				if (len % 8) { // fatal error



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