From c5c4e3c7cef927870c686bc7901c92f8c17b589e Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Thu, 2 Jun 2011 13:33:03 +0000 Subject: [PATCH] * ElGamalAESEngine: Fixups required after SessionKey enforcement * SessionKey: Enforce data size and prevent reuse like the other SimpleDataStructures --- .../src/net/i2p/crypto/ElGamalAESEngine.java | 35 ++++++++++--------- core/java/src/net/i2p/data/SessionKey.java | 2 +- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/core/java/src/net/i2p/crypto/ElGamalAESEngine.java b/core/java/src/net/i2p/crypto/ElGamalAESEngine.java index df4867574d..4e6e634ca5 100644 --- a/core/java/src/net/i2p/crypto/ElGamalAESEngine.java +++ b/core/java/src/net/i2p/crypto/ElGamalAESEngine.java @@ -91,14 +91,12 @@ public class ElGamalAESEngine { SessionTag st = new SessionTag(tag); SessionKey key = keyManager.consumeTag(st); SessionKey foundKey = new SessionKey(); - foundKey.setData(null); SessionKey usedKey = new SessionKey(); Set foundTags = new HashSet(); byte decrypted[] = null; boolean wasExisting = false; if (key != null) { //if (_log.shouldLog(Log.DEBUG)) _log.debug("Key is known for tag " + st); - usedKey.setData(key.getData()); long id = _context.random().nextLong(); if (_log.shouldLog(Log.DEBUG)) _log.debug(id + ": Decrypting existing session encrypted with tag: " + st.toString() + ": key: " + key.toBase64() + ": " + data.length + " bytes: " + Base64.encode(data, 0, 64)); @@ -138,7 +136,7 @@ public class ElGamalAESEngine { if (_log.shouldLog(Log.DEBUG)) _log.debug("Found key: " + foundKey.toBase64() + " tags: " + foundTags + " wasExisting? " + wasExisting); keyManager.tagsReceived(foundKey, foundTags); - } else { + } else if (usedKey.getData() != null) { if (_log.shouldLog(Log.DEBUG)) _log.debug("Used key: " + usedKey.toBase64() + " tags: " + foundTags + " wasExisting? " + wasExisting); keyManager.tagsReceived(usedKey, foundTags); @@ -160,11 +158,12 @@ public class ElGamalAESEngine { * the decryptAESBlock method & structure. * * @param foundTags set which is filled with any sessionTags found during decryption - * @param foundKey session key which may be filled with a new sessionKey found during decryption + * @param foundKey out parameter. Data must be unset when called; may be filled with a new sessionKey found during decryption + * @param usedKey out parameter. Data must be unset when called; usedKey.setData() will be called by this method on success. * * @return null if decryption fails */ - byte[] decryptNewSession(byte data[], PrivateKey targetPrivateKey, Set foundTags, SessionKey usedKey, + private byte[] decryptNewSession(byte data[], PrivateKey targetPrivateKey, Set foundTags, SessionKey usedKey, SessionKey foundKey) throws DataFormatException { if (data == null) { //if (_log.shouldLog(Log.WARN)) _log.warn("Data is null, unable to decrypt new session"); @@ -231,19 +230,19 @@ public class ElGamalAESEngine { * If anything doesn't match up in decryption, it falls back to decryptNewSession * * @param foundTags set which is filled with any sessionTags found during decryption - * @param foundKey session key which may be filled with a new sessionKey found during decryption + * @param foundKey out parameter. Data must be unset when called; may be filled with a new sessionKey found during decryption + * @param usedKey out parameter. Data must be unset when called; usedKey.setData() will be called by this method on success. + * * @return decrypted data or null on failure * */ - byte[] decryptExistingSession(byte data[], SessionKey key, PrivateKey targetPrivateKey, Set foundTags, + private byte[] decryptExistingSession(byte data[], SessionKey key, PrivateKey targetPrivateKey, Set foundTags, SessionKey usedKey, SessionKey foundKey) throws DataFormatException { byte preIV[] = new byte[32]; System.arraycopy(data, 0, preIV, 0, preIV.length); Hash ivHash = _context.sha().calculateHash(preIV); byte iv[] = new byte[16]; System.arraycopy(ivHash.getData(), 0, iv, 0, 16); - - usedKey.setData(key.getData()); //_log.debug("Pre IV for decryptExistingSession: " + DataHelper.toString(preIV, 32)); //_log.debug("SessionKey for decryptNewSession: " + DataHelper.toString(key.getData(), 32)); @@ -267,6 +266,7 @@ public class ElGamalAESEngine { //if (_log.shouldLog(Log.DEBUG)) // _log.debug("Decrypt with an EXISTING session tag successfull, # tags read: " + foundTags.size(), // new Exception("Decrypted by")); + usedKey.setData(key.getData()); return decrypted; } @@ -287,14 +287,15 @@ public class ElGamalAESEngine { * consume it, but if it is null, record the keys, etc as part of a new session. * * @param foundTags set which is filled with any sessionTags found during decryption - * @param foundKey session key which may be filled with a new sessionKey found during decryption + * @param foundKey out parameter. Data must be unset when called; may be filled with a new sessionKey found during decryption * @return decrypted data or null on failure */ - byte[] decryptAESBlock(byte encrypted[], SessionKey key, byte iv[], + private byte[] decryptAESBlock(byte encrypted[], SessionKey key, byte iv[], byte sentTag[], Set foundTags, SessionKey foundKey) throws DataFormatException { return decryptAESBlock(encrypted, 0, encrypted.length, key, iv, sentTag, foundTags, foundKey); } - byte[] decryptAESBlock(byte encrypted[], int offset, int encryptedLen, SessionKey key, byte iv[], + + private byte[] decryptAESBlock(byte encrypted[], int offset, int encryptedLen, SessionKey key, byte iv[], byte sentTag[], Set foundTags, SessionKey foundKey) throws DataFormatException { //_log.debug("iv for decryption: " + DataHelper.toString(iv, 16)); //_log.debug("decrypting AES block. encr.length = " + (encrypted == null? -1 : encrypted.length) + " sentTag: " + DataHelper.toString(sentTag, 32)); @@ -448,7 +449,7 @@ public class ElGamalAESEngine { * </pre> * */ - byte[] encryptNewSession(byte data[], PublicKey target, SessionKey key, Set tagsForDelivery, + private byte[] encryptNewSession(byte data[], PublicKey target, SessionKey key, Set tagsForDelivery, SessionKey newKey, long paddedSize) { //_log.debug("Encrypting to a NEW session"); byte elgSrcData[] = new byte[SessionKey.KEYSIZE_BYTES+32+158]; @@ -511,7 +512,7 @@ public class ElGamalAESEngine { * </pre> * */ - byte[] encryptExistingSession(byte data[], PublicKey target, SessionKey key, Set tagsForDelivery, + private byte[] encryptExistingSession(byte data[], PublicKey target, SessionKey key, Set tagsForDelivery, SessionTag currentTag, SessionKey newKey, long paddedSize) { //_log.debug("Encrypting to an EXISTING session"); byte rawTag[] = currentTag.getData(); @@ -543,11 +544,12 @@ public class ElGamalAESEngine { * </pre> * */ - final byte[] encryptAESBlock(byte data[], SessionKey key, byte[] iv, Set tagsForDelivery, SessionKey newKey, + private final byte[] encryptAESBlock(byte data[], SessionKey key, byte[] iv, Set tagsForDelivery, SessionKey newKey, long paddedSize) { return encryptAESBlock(data, key, iv, tagsForDelivery, newKey, paddedSize, 0); } - final byte[] encryptAESBlock(byte data[], SessionKey key, byte[] iv, Set tagsForDelivery, SessionKey newKey, + + private final byte[] encryptAESBlock(byte data[], SessionKey key, byte[] iv, Set tagsForDelivery, SessionKey newKey, long paddedSize, int prefixBytes) { //_log.debug("iv for encryption: " + DataHelper.toString(iv, 16)); //_log.debug("Encrypting AES"); @@ -616,6 +618,7 @@ public class ElGamalAESEngine { context.random().nextBytes(rv); return rv; } + final static int getPaddingSize(int curSize, long minPaddedSize) { int diff = 0; if (curSize < minPaddedSize) { diff --git a/core/java/src/net/i2p/data/SessionKey.java b/core/java/src/net/i2p/data/SessionKey.java index 7621c2b8a7..bbe1e533c5 100644 --- a/core/java/src/net/i2p/data/SessionKey.java +++ b/core/java/src/net/i2p/data/SessionKey.java @@ -41,7 +41,7 @@ public class SessionKey extends SimpleDataStructure { */ @Override public void setData(byte[] data) { - _data = data; + super.setData(data); _preparedKey = null; } -- GitLab