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

Back to archive index
scmno****@osdn***** scmno****@osdn*****
2021年 4月 25日 (日) 11:18:41 JST


Revision: 9217
          https://osdn.net/projects/ttssh2/scm/svn/commits/9217
Author:   nmaya
Date:     2021-04-25 11:18:41 +0900 (Sun, 25 Apr 2021)
Log Message:
-----------
SSH2 暗号化方式 chach****@opens***** をサポート

Modified Paths:
--------------
    branches/ssh_chacha20poly1305/ttssh2/ttxssh/cipher.c
    branches/ssh_chacha20poly1305/ttssh2/ttxssh/cipher.h
    branches/ssh_chacha20poly1305/ttssh2/ttxssh/crypt.c
    branches/ssh_chacha20poly1305/ttssh2/ttxssh/pkt.c
    branches/ssh_chacha20poly1305/ttssh2/ttxssh/ssh.c

-------------- next part --------------
Modified: branches/ssh_chacha20poly1305/ttssh2/ttxssh/cipher.c
===================================================================
--- branches/ssh_chacha20poly1305/ttssh2/ttxssh/cipher.c	2021-04-24 12:28:27 UTC (rev 9216)
+++ branches/ssh_chacha20poly1305/ttssh2/ttxssh/cipher.c	2021-04-25 02:18:41 UTC (rev 9217)
@@ -70,6 +70,7 @@
 #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
 };
@@ -119,7 +120,7 @@
 u_int get_cipher_iv_len(const struct ssh2cipher *cipher)
 {
 	if (cipher) {
-		if (cipher->iv_len != 0) {
+		if (cipher->iv_len != 0 || cipher->id != SSH2_CIPHER_CHACHAPOLY) {
 			return cipher->iv_len;
 		}
 		else {
@@ -240,6 +241,8 @@
 		return "aes12****@opens*****";
 	case SSH2_CIPHER_AES256_GCM:
 		return "aes25****@opens*****";
+	case SSH2_CIPHER_CHACHAPOLY:
+		return "chach****@opens*****(SSH2)";
 
 	default:
 		return "Unknown";
@@ -308,6 +311,8 @@
 		return "aes12****@opens*****(SSH2)";
 	case SSH2_CIPHER_AES256_GCM:
 		return "aes25****@opens*****(SSH2)";
+	case SSH2_CIPHER_CHACHAPOLY:
+		return "chach****@opens*****(SSH2)";
 
 	default:
 		return NULL;
@@ -325,6 +330,7 @@
 	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,
@@ -473,6 +479,9 @@
 			case SSH2_CIPHER_AES256_GCM:
 				c_str = "aes25****@opens*****,";
 				break;
+			case SSH2_CIPHER_CHACHAPOLY:
+				c_str = "chach****@opens*****,";
+				break;
 			default:
 				continue;
 		}
@@ -527,10 +536,20 @@
 	}
 
 	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, 4);
+		_snprintf_s(tmp, sizeof(tmp), _TRUNCATE, pvar->ts->UIMsg, 5);
 		notify_fatal_error(pvar, tmp, TRUE);
 		ret = SSH_ERR_ALLOC_FAIL;
 		goto out;
@@ -537,7 +556,7 @@
 	}
 	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, 5);
+		_snprintf_s(tmp, sizeof(tmp), _TRUNCATE, pvar->ts->UIMsg, 6);
 		notify_fatal_error(pvar, tmp, TRUE);
 		ret = SSH_ERR_LIBCRYPTO_ERROR;
 		goto out;
@@ -545,7 +564,7 @@
 	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, 6);
+		_snprintf_s(tmp, sizeof(tmp), _TRUNCATE, pvar->ts->UIMsg, 7);
 		notify_fatal_error(pvar, tmp, TRUE);
 		ret = SSH_ERR_LIBCRYPTO_ERROR;
 		goto out;
@@ -554,7 +573,7 @@
 	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, 7);
+			_snprintf_s(tmp, sizeof(tmp), _TRUNCATE, pvar->ts->UIMsg, 8);
 			notify_fatal_error(pvar, tmp, TRUE);
 			ret = SSH_ERR_LIBCRYPTO_ERROR;
 			goto out;
@@ -562,7 +581,7 @@
 	}
 	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, 8);
+		_snprintf_s(tmp, sizeof(tmp), _TRUNCATE, pvar->ts->UIMsg, 9);
 		notify_fatal_error(pvar, tmp, TRUE);
 		ret = SSH_ERR_LIBCRYPTO_ERROR;
 		goto out;
@@ -574,7 +593,7 @@
 		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, 9);
+			_snprintf_s(tmp, sizeof(tmp), _TRUNCATE, pvar->ts->UIMsg, 10);
 			notify_fatal_error(pvar, tmp, TRUE);
 		}
 		else {
@@ -605,6 +624,10 @@
 {
 	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/ssh_chacha20poly1305/ttssh2/ttxssh/cipher.h
===================================================================
--- branches/ssh_chacha20poly1305/ttssh2/ttxssh/cipher.h	2021-04-24 12:28:27 UTC (rev 9216)
+++ branches/ssh_chacha20poly1305/ttssh2/ttxssh/cipher.h	2021-04-25 02:18:41 UTC (rev 9217)
@@ -43,6 +43,8 @@
 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.
@@ -95,12 +97,16 @@
 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;
-	// struct chachapoly_ctx *cp_ctx;
+	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;
 };

Modified: branches/ssh_chacha20poly1305/ttssh2/ttxssh/crypt.c
===================================================================
--- branches/ssh_chacha20poly1305/ttssh2/ttxssh/crypt.c	2021-04-24 12:28:27 UTC (rev 9216)
+++ branches/ssh_chacha20poly1305/ttssh2/ttxssh/crypt.c	2021-04-25 02:18:41 UTC (rev 9217)
@@ -205,6 +205,7 @@
 	unsigned char lastiv[1];
 	char tmp[80];
 	struct sshcipher_ctx *cc = pvar->cc[MODE_OUT];
+	unsigned int newbuff_len = bytes;
 
 	if (bytes == 0)
 		return TRUE;
@@ -218,13 +219,28 @@
 		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 (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;
 
@@ -231,6 +247,7 @@
 	if (aadlen && !EVP_Cipher(cc->evp, NULL, data, aadlen) < 0)
 		goto err;
 
+	// 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;
 
@@ -258,7 +275,8 @@
 	unsigned int block_size = pvar->ssh2_keys[MODE_IN].enc.block_size;
 	unsigned char lastiv[1];
 	char tmp[80];
-	struct sshcipher_ctx *cc = pvar->cc[MODE_OUT];
+	struct sshcipher_ctx *cc = pvar->cc[MODE_IN];
+	unsigned int newbuff_len = bytes;
 
 	if (bytes == 0)
 		return TRUE;
@@ -272,13 +290,26 @@
 		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 (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;
 
@@ -288,6 +319,7 @@
 	if (aadlen && !EVP_Cipher(cc->evp, NULL, data, aadlen) < 0)
 		goto err;
 
+	// 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;
 
@@ -593,6 +625,7 @@
 		            | (1 << SSH2_CIPHER_CAMELLIA256_CTR)
 		            | (1 << SSH2_CIPHER_AES128_GCM)
 		            | (1 << SSH2_CIPHER_AES256_GCM)
+		            | (1 << SSH2_CIPHER_CHACHAPOLY)
 		);
 	}
 

Modified: branches/ssh_chacha20poly1305/ttssh2/ttxssh/pkt.c
===================================================================
--- branches/ssh_chacha20poly1305/ttssh2/ttxssh/pkt.c	2021-04-24 12:28:27 UTC (rev 9216)
+++ branches/ssh_chacha20poly1305/ttssh2/ttxssh/pkt.c	2021-04-25 02:18:41 UTC (rev 9217)
@@ -176,59 +176,111 @@
 		}
 		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;
 
 			/*
+			 *                      |          | 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) aadlen is 4, but lead 4 bytes are encrypted separately from main part.
+			 * (2) implicit MAC type is EtM
+			 */
+
+			if (enc && enc->auth_len > 0) {
+				authlen = enc->auth_len;
+			}
+
+			/*
 			 * 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
+			 *     \x82܂\xBD\x82\xCD AEAD \x82\xCC 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
 			 *
-			 * 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
+			 * EtM \x95\xFB\x8E\xAE\x82\xCC MAC \x82\xE2\x81AAEAD \x82\xCC AES-GCM \x82ł̓p\x83P\x83b\x83g\x82̐擪\x82̃p\x83P\x83b\x83g\x92\xB7\x95\x94\x95\xAA\x82\xCD
+			 * \x88Í\x86\x89\xBB\x82\xB3\x82\xEA\x82Ă\xA8\x82炸\x94F\x8F؂݂̂\xAA\x8Ds\x82\xED\x82\xEA\x82\xE9\x81B
+			 * AEAD \x82\xCC chacha20-poly1305 \x82ł̓p\x83P\x83b\x83g\x92\xB7\x95\x94\x95\xAA\x82͈Í\x86\x89\xBB\x82\xB3\x82\xEA\x82Ă\xA2\x82邪\x81A
+			 * \x91\xB1\x82\xAD\x95\x94\x95\xAA\x82Ƃ͕ʁX\x82ɈÍ\x86\x89\xBB\x82\xB3\x82\xEA\x82Ă\xA2\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))) {
+			if (SSHv2(pvar) && ((mac && mac->etm) || authlen > 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 (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\xE0\x88Í\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

Modified: branches/ssh_chacha20poly1305/ttssh2/ttxssh/ssh.c
===================================================================
--- branches/ssh_chacha20poly1305/ttssh2/ttxssh/ssh.c	2021-04-24 12:28:27 UTC (rev 9216)
+++ branches/ssh_chacha20poly1305/ttssh2/ttxssh/ssh.c	2021-04-25 02:18:41 UTC (rev 9217)
@@ -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);
@@ -6398,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);


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