From 62fce859b9f29d79f8b8f4a10f6bdbf54f8158e7 Mon Sep 17 00:00:00 2001 From: zzz <zzz@i2pmail.org> Date: Tue, 29 Dec 2020 14:15:00 -0500 Subject: [PATCH] Ratchet: mixHash() not required after message for N pattern --- .../noise/protocol/HandshakeState.java | 24 +++++++++++++++---- .../noise/protocol/SymmetricState.java | 19 +++++++++++++++ 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/router/java/src/com/southernstorm/noise/protocol/HandshakeState.java b/router/java/src/com/southernstorm/noise/protocol/HandshakeState.java index cd6a414e8d..2297ae2529 100644 --- a/router/java/src/com/southernstorm/noise/protocol/HandshakeState.java +++ b/router/java/src/com/southernstorm/noise/protocol/HandshakeState.java @@ -648,10 +648,19 @@ public class HandshakeState implements Destroyable, Cloneable { } // Add the payload to the message buffer and encrypt it. - if (payload != null) - messagePosn += symmetric.encryptAndHash(payload, payloadOffset, message, messagePosn, payloadLength); - else - messagePosn += symmetric.encryptAndHash(message, messagePosn, message, messagePosn, 0); + if (payload != null) { + // no need to hash for N, we don't split() and no more messages follow + if (patternId.equals(PATTERN_ID_N)) + messagePosn += symmetric.encryptOnly(payload, payloadOffset, message, messagePosn, payloadLength); + else + messagePosn += symmetric.encryptAndHash(payload, payloadOffset, message, messagePosn, payloadLength); + } else { + // no need to hash for N, we don't split() and no more messages follow + if (patternId.equals(PATTERN_ID_N)) + messagePosn += symmetric.encryptOnly(message, messagePosn, message, messagePosn, 0); + else + messagePosn += symmetric.encryptAndHash(message, messagePosn, message, messagePosn, 0); + } success = true; } finally { // If we failed, then clear any sensitive data that may have @@ -819,7 +828,12 @@ public class HandshakeState implements Destroyable, Cloneable { } // Decrypt the message payload. - int payloadLength = symmetric.decryptAndHash(message, messageOffset, payload, payloadOffset, messageEnd - messageOffset); + int payloadLength; + // no need to hash for N, we don't split() and no more messages follow + if (patternId.equals(PATTERN_ID_N)) + payloadLength = symmetric.decryptOnly(message, messageOffset, payload, payloadOffset, messageEnd - messageOffset); + else + payloadLength = symmetric.decryptAndHash(message, messageOffset, payload, payloadOffset, messageEnd - messageOffset); success = true; return payloadLength; } finally { diff --git a/router/java/src/com/southernstorm/noise/protocol/SymmetricState.java b/router/java/src/com/southernstorm/noise/protocol/SymmetricState.java index 4b6341b1eb..4c7f09ee5f 100644 --- a/router/java/src/com/southernstorm/noise/protocol/SymmetricState.java +++ b/router/java/src/com/southernstorm/noise/protocol/SymmetricState.java @@ -273,6 +273,16 @@ class SymmetricState implements Destroyable, Cloneable { return ciphertextLength; } + /** + * I2P - Same as encryptAndHash() but without the post-mixHash(), for N only. + * @since 0.9.49 + */ + public int encryptOnly(byte[] plaintext, int plaintextOffset, byte[] ciphertext, int ciphertextOffset, int length) throws ShortBufferException + { + int ciphertextLength = cipher.encryptWithAd(h, plaintext, plaintextOffset, ciphertext, ciphertextOffset, length); + return ciphertextLength; + } + /** * Decrypts a block of ciphertext and mixes it into the handshake hash. * @@ -302,6 +312,15 @@ class SymmetricState implements Destroyable, Cloneable { return cipher.decryptWithAd(prev_h, ciphertext, ciphertextOffset, plaintext, plaintextOffset, length); } + /** + * I2P - Same as decryptAndHash() but without the post-mixHash(), for N only. + * @since 0.9.49 + */ + public int decryptOnly(byte[] ciphertext, int ciphertextOffset, byte[] plaintext, int plaintextOffset, int length) throws ShortBufferException, BadPaddingException + { + return cipher.decryptWithAd(h, ciphertext, ciphertextOffset, plaintext, plaintextOffset, length); + } + /** * Splits the symmetric state into two ciphers for session encryption. * -- GitLab