diff --git a/router/java/src/net/i2p/router/crypto/ratchet/ECIESAEADEngine.java b/router/java/src/net/i2p/router/crypto/ratchet/ECIESAEADEngine.java index 42248f2dba5aa9b8c200a520920ecfc04bd506e0..7acb5400c12a694d8c71c0a048b09e046151dd56 100644 --- a/router/java/src/net/i2p/router/crypto/ratchet/ECIESAEADEngine.java +++ b/router/java/src/net/i2p/router/crypto/ratchet/ECIESAEADEngine.java @@ -482,15 +482,15 @@ public final class ECIESAEADEngine { private CloveSet decryptExistingSession(byte[] tag, byte[] data, SessionKeyAndNonce key, PrivateKey targetPrivateKey, RatchetSKM keyManager) throws DataFormatException { -// TODO decrypt in place? int nonce = key.getNonce(); - byte decrypted[] = decryptAEADBlock(tag, data, TAGLEN, data.length - TAGLEN, key, nonce); - if (decrypted == null) { + // this decrypts in-place + boolean ok = decryptAEADBlock(tag, data, TAGLEN, data.length - TAGLEN, key, nonce); + if (!ok) { if (_log.shouldWarn()) _log.warn("Decrypt of ES failed"); return null; } - if (decrypted.length == 0) { + if (data.length == TAGLEN + MACLEN) { if (_log.shouldWarn()) _log.warn("Zero length payload in ES"); return null; @@ -498,7 +498,7 @@ public final class ECIESAEADEngine { PublicKey remote = key.getRemoteKey(); PLCallback pc = new PLCallback(keyManager, remote); try { - int blocks = RatchetPayload.processPayload(_context, pc, decrypted, 0, decrypted.length, false); + int blocks = RatchetPayload.processPayload(_context, pc, data, TAGLEN, data.length - (TAGLEN + MACLEN), false); if (_log.shouldDebug()) _log.debug("Processed " + blocks + " blocks in IB ES"); } catch (DataFormatException e) { @@ -526,39 +526,27 @@ public final class ECIESAEADEngine { return rv; } - /** - * No AD - * - * @return decrypted data or null on failure - */ - private byte[] decryptAEADBlock(byte encrypted[], int offset, int len, SessionKey key, - long n) throws DataFormatException { -// TODO decrypt in place? - return decryptAEADBlock(null, encrypted, offset, len, key, n); - } - /* - * With optional AD + * With optional AD. + * Decrypts IN PLACE. Decrypted data will be at encrypted[offset:offset + len - 16]. * * @param ad may be null - * @return decrypted data or null on failure + * @return success */ - private byte[] decryptAEADBlock(byte[] ad, byte encrypted[], int offset, int encryptedLen, SessionKey key, + private boolean decryptAEADBlock(byte[] ad, byte encrypted[], int offset, int encryptedLen, SessionKey key, long n) throws DataFormatException { -// TODO decrypt in place? - byte decrypted[] = new byte[encryptedLen - MACLEN]; ChaChaPolyCipherState chacha = new ChaChaPolyCipherState(); chacha.initializeKey(key.getData(), 0); chacha.setNonce(n); try { - chacha.decryptWithAd(ad, encrypted, offset, decrypted, 0, encryptedLen); + // this is safe to do in-place, it checks the mac before starting decryption + chacha.decryptWithAd(ad, encrypted, offset, encrypted, offset, encryptedLen); } catch (GeneralSecurityException e) { if (_log.shouldWarn()) _log.warn("Unable to decrypt AEAD block", e); - return null; + return false; } -//// - return decrypted; + return true; } //// end decrypt, start encrypt ////