This is an automated email from the ASF dual-hosted git repository. twolf pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mina-sshd.git
commit 1c5987d4130f5883795d0098c69cf04cc619b11b Author: Thomas Wolf <tw...@apache.org> AuthorDate: Sun Jul 11 23:35:29 2021 +0200 [SSHD-1191] Abstract session: correct rekey block count limit Follow the recommendation from RFC 4344: if the cipher block size is smaller than 16, re-key after 1GB of data.[1] Otherwise, we'd re-key far too often; for instance with a block size of 8 after 64k blocks, i.e., after 512kB of data. Note that chacha20-poly1305 has a block size of 8. OpenSSH uses the same implementation.[2] [1] https://datatracker.ietf.org/doc/html/rfc4344#section-3.2 [2]https://github.com/openssh/openssh-portable/blob/99981d5f/packet.c#L940 --- .../common/session/helpers/AbstractSession.java | 49 ++++++++++++++++++---- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java index 14da167..ffd0d2c 100644 --- a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java +++ b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java @@ -1760,16 +1760,10 @@ public abstract class AbstractSession extends SessionHelper { // TODO add support for configurable compression level inCompression.init(Compression.Type.Inflater, -1); - // see https://tools.ietf.org/html/rfc4344#section-3.2 - // select the lowest cipher size - int avgCipherBlockSize = Math.min(inCipherSize, outCipherSize); - long recommendedByteRekeyBlocks = 1L << Math.min((avgCipherBlockSize * Byte.SIZE) / 4, - 63); // in case (block-size / 4) > 63 - long effectiveRekeyBlocksCount = CoreModuleProperties.REKEY_BLOCKS_LIMIT.getRequired(this); - maxRekeyBlocks.set(effectiveRekeyBlocksCount > 0 ? effectiveRekeyBlocksCount : recommendedByteRekeyBlocks); + maxRekeyBlocks.set(determineRekeyBlockLimit(inCipherSize, outCipherSize)); if (debugEnabled) { - log.debug("receiveNewKeys({}) inCipher={}, outCipher={}, recommended blocks limit={}, actual={}", - this, inCipher, outCipher, recommendedByteRekeyBlocks, maxRekeyBlocks); + log.debug("receiveNewKeys({}) inCipher={}, outCipher={}, blocks limit={}", this, inCipher, outCipher, + maxRekeyBlocks); } inBytesCount.set(0L); @@ -1783,6 +1777,43 @@ public abstract class AbstractSession extends SessionHelper { } /** + * Compute the number of blocks after which we should re-key again. See RFC 4344. + * + * @param inCipherBlockSize block size of the input cipher + * @param outCipherBlockSize block size of the output cipher + * @return the number of block after which re-keying occur at the latest + * @see <a href= "https://tools.ietf.org/html/rfc4344#section-3.2">RFC 4344, section 3.2</a> + */ + protected long determineRekeyBlockLimit(int inCipherBlockSize, int outCipherBlockSize) { + // see https://tools.ietf.org/html/rfc4344#section-3.2 + // select the lowest cipher size + long rekeyBlocksLimit = CoreModuleProperties.REKEY_BLOCKS_LIMIT.getRequired(this); + if (rekeyBlocksLimit <= 0) { + // Default per RFC 4344 + int minCipherBlockBytes = Math.min(inCipherSize, outCipherSize); + if (minCipherBlockBytes >= 16) { + rekeyBlocksLimit = 1L << Math.min(minCipherBlockBytes * 2, 63); + } else { + // With a block size of 8 we'd end up with 2^16. That would re-key very often. + // RFC 4344: "If L is less than 128 [...], then, although it may be too + // expensive to rekey every 2**(L/4) blocks, it is still advisable for SSH + // implementations to follow the original recommendation in [RFC4253]: rekey at + // least once for every gigabyte of transmitted data." + // + // Note that chacha20-poly1305 has a block size of 8. The OpenSSH recommendation + // is: "ChaCha20 must never reuse a {key, nonce} for encryption nor may it be + // used to encrypt more than 2^70 bytes under the same {key, nonce}. The + // SSH Transport protocol (RFC4253) recommends a far more conservative + // rekeying every 1GB of data sent or received. If this recommendation + // is followed, then chacha20-poly1...@openssh.com requires no special + // handling in this area." + rekeyBlocksLimit = (1L << 30) / minCipherBlockBytes; // 1GB + } + } + return rekeyBlocksLimit; + } + + /** * Send a {@code SSH_MSG_UNIMPLEMENTED} packet. This packet should contain the sequence id of the unsupported * packet: this number is assumed to be the last packet received. *