Ratchet: Decrypt ES messages in-place

This commit is contained in:
zzz
2020-04-06 13:02:27 +00:00
parent f9d7cfa7e1
commit 2482df7121

View File

@ -482,15 +482,15 @@ public final class ECIESAEADEngine {
private CloveSet decryptExistingSession(byte[] tag, byte[] data, SessionKeyAndNonce key, private CloveSet decryptExistingSession(byte[] tag, byte[] data, SessionKeyAndNonce key,
PrivateKey targetPrivateKey, RatchetSKM keyManager) PrivateKey targetPrivateKey, RatchetSKM keyManager)
throws DataFormatException { throws DataFormatException {
// TODO decrypt in place?
int nonce = key.getNonce(); int nonce = key.getNonce();
byte decrypted[] = decryptAEADBlock(tag, data, TAGLEN, data.length - TAGLEN, key, nonce); // this decrypts in-place
if (decrypted == null) { boolean ok = decryptAEADBlock(tag, data, TAGLEN, data.length - TAGLEN, key, nonce);
if (!ok) {
if (_log.shouldWarn()) if (_log.shouldWarn())
_log.warn("Decrypt of ES failed"); _log.warn("Decrypt of ES failed");
return null; return null;
} }
if (decrypted.length == 0) { if (data.length == TAGLEN + MACLEN) {
if (_log.shouldWarn()) if (_log.shouldWarn())
_log.warn("Zero length payload in ES"); _log.warn("Zero length payload in ES");
return null; return null;
@ -498,7 +498,7 @@ public final class ECIESAEADEngine {
PublicKey remote = key.getRemoteKey(); PublicKey remote = key.getRemoteKey();
PLCallback pc = new PLCallback(keyManager, remote); PLCallback pc = new PLCallback(keyManager, remote);
try { 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()) if (_log.shouldDebug())
_log.debug("Processed " + blocks + " blocks in IB ES"); _log.debug("Processed " + blocks + " blocks in IB ES");
} catch (DataFormatException e) { } catch (DataFormatException e) {
@ -526,39 +526,27 @@ public final class ECIESAEADEngine {
return rv; 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 * @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 { long n) throws DataFormatException {
// TODO decrypt in place?
byte decrypted[] = new byte[encryptedLen - MACLEN];
ChaChaPolyCipherState chacha = new ChaChaPolyCipherState(); ChaChaPolyCipherState chacha = new ChaChaPolyCipherState();
chacha.initializeKey(key.getData(), 0); chacha.initializeKey(key.getData(), 0);
chacha.setNonce(n); chacha.setNonce(n);
try { 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) { } catch (GeneralSecurityException e) {
if (_log.shouldWarn()) if (_log.shouldWarn())
_log.warn("Unable to decrypt AEAD block", e); _log.warn("Unable to decrypt AEAD block", e);
return null; return false;
} }
//// return true;
return decrypted;
} }
//// end decrypt, start encrypt //// //// end decrypt, start encrypt ////