From fd23b23e56874f22fe522bd4be68c49325037d24 Mon Sep 17 00:00:00 2001 From: zzz Date: Tue, 11 Dec 2018 12:19:46 +0000 Subject: [PATCH] Crypto: HMAC-SHA256 cleanup Add byte[] key method to reduce object churn in NTCP2 Un-deprecate in context --- core/java/src/net/i2p/I2PAppContext.java | 5 +++-- .../src/net/i2p/crypto/HMAC256Generator.java | 22 ++++++++++++++++--- .../transport/ntcp/OutboundNTCP2State.java | 22 +++++++------------ 3 files changed, 30 insertions(+), 19 deletions(-) diff --git a/core/java/src/net/i2p/I2PAppContext.java b/core/java/src/net/i2p/I2PAppContext.java index 39b388443a..8a442f07dc 100644 --- a/core/java/src/net/i2p/I2PAppContext.java +++ b/core/java/src/net/i2p/I2PAppContext.java @@ -746,8 +746,9 @@ public class I2PAppContext { } } - /** @deprecated used only by syndie */ - @Deprecated + /** + * Un-deprecated in 0.9.38 + */ public HMAC256Generator hmac256() { if (!_hmac256Initialized) initializeHMAC256(); diff --git a/core/java/src/net/i2p/crypto/HMAC256Generator.java b/core/java/src/net/i2p/crypto/HMAC256Generator.java index 816d488d1e..93dc724ded 100644 --- a/core/java/src/net/i2p/crypto/HMAC256Generator.java +++ b/core/java/src/net/i2p/crypto/HMAC256Generator.java @@ -4,6 +4,7 @@ import java.security.GeneralSecurityException; import java.security.Key; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import net.i2p.I2PAppContext; @@ -19,7 +20,7 @@ import org.bouncycastle.oldcrypto.macs.I2PHMac; * * As of 0.9.12, uses javax.crypto.Mac. * - * Deprecated, used only by Syndie. + * Warning - used by Syndie, don't break it. */ public final class HMAC256Generator extends HMACGenerator { @@ -33,6 +34,7 @@ public final class HMAC256Generator extends HMACGenerator { * @throws UnsupportedOperationException since 0.9.12 */ @Override + @Deprecated protected I2PHMac acquire() { throw new UnsupportedOperationException(); } @@ -46,6 +48,7 @@ public final class HMAC256Generator extends HMACGenerator { * @since 0.9.12 overrides HMACGenerator */ @Override + @Deprecated public Hash calculate(SessionKey key, byte data[]) { throw new UnsupportedOperationException(); } @@ -60,9 +63,22 @@ public final class HMAC256Generator extends HMACGenerator { */ @Override public void calculate(SessionKey key, byte data[], int offset, int length, byte target[], int targetOffset) { + calculate(key.getData(), data, offset, length, target, targetOffset); + } + + /** + * Calculate the HMAC of the data with the given key. + * Outputs 32 bytes to target starting at targetOffset. + * + * @param key 32 bytes + * @throws UnsupportedOperationException if the JVM does not support it + * @throws IllegalArgumentException for bad key or target too small + * @since 0.9.38 + */ + public void calculate(byte[] key, byte data[], int offset, int length, byte target[], int targetOffset) { try { - javax.crypto.Mac mac = javax.crypto.Mac.getInstance("HmacSHA256"); - Key keyObj = new SecretKeySpec(key.getData(), "HmacSHA256"); + Mac mac = Mac.getInstance("HmacSHA256"); + Key keyObj = new SecretKeySpec(key, "HmacSHA256"); mac.init(keyObj); mac.update(data, offset, length); mac.doFinal(target, targetOffset); diff --git a/router/java/src/net/i2p/router/transport/ntcp/OutboundNTCP2State.java b/router/java/src/net/i2p/router/transport/ntcp/OutboundNTCP2State.java index a27d7c5f37..3d20586113 100644 --- a/router/java/src/net/i2p/router/transport/ntcp/OutboundNTCP2State.java +++ b/router/java/src/net/i2p/router/transport/ntcp/OutboundNTCP2State.java @@ -436,34 +436,28 @@ class OutboundNTCP2State implements EstablishState { static byte[][] generateSipHashKeys(RouterContext ctx, HandshakeState state) { // TODO use noise HMAC or HKDF method instead? // ask_master = HKDF(ck, zerolen, info="ask") - SessionKey tk = new SessionKey(state.getChainingKey()); - byte[] temp_key = doHMAC(ctx, tk, ZEROLEN); - tk = new SessionKey(temp_key); - byte[] ask_master = doHMAC(ctx, tk, ASK); + byte[] temp_key = doHMAC(ctx, state.getChainingKey(), ZEROLEN); + byte[] ask_master = doHMAC(ctx, temp_key, ASK); byte[] tmp = new byte[32 + SIPHASH.length]; byte[] hash = state.getHandshakeHash(); System.arraycopy(hash, 0, tmp, 0, 32); System.arraycopy(SIPHASH, 0, tmp, 32, SIPHASH.length); - tk = new SessionKey(ask_master); - temp_key = doHMAC(ctx, tk, tmp); - tk = new SessionKey(temp_key); - byte[] sip_master = doHMAC(ctx, tk, ONE); - tk = new SessionKey(sip_master); - temp_key = doHMAC(ctx, tk, ZEROLEN); - tk = new SessionKey(temp_key); + temp_key = doHMAC(ctx, ask_master, tmp); + byte[] sip_master = doHMAC(ctx, temp_key, ONE); + temp_key = doHMAC(ctx, sip_master, ZEROLEN); // Output 1 - byte[] sip_ab = doHMAC(ctx, tk, ONE); + byte[] sip_ab = doHMAC(ctx, temp_key, ONE); // Output 2 tmp = new byte[KEY_SIZE + 1]; System.arraycopy(sip_ab, 0, tmp, 0, 32); tmp[32] = 2; - byte[] sip_ba = doHMAC(ctx, tk, tmp); + byte[] sip_ba = doHMAC(ctx, temp_key, tmp); Arrays.fill(temp_key, (byte) 0); Arrays.fill(tmp, (byte) 0); return new byte[][] { sip_ab, sip_ba }; } - private static byte[] doHMAC(RouterContext ctx, SessionKey key, byte data[]) { + private static byte[] doHMAC(RouterContext ctx, byte[] key, byte[] data) { byte[] rv = new byte[32]; ctx.hmac256().calculate(key, data, 0, data.length, rv, 0); return rv;