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