
org.bouncycastle.crypto.engines.AEADBufferBaseEngine Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bcprov-jdk15to18 Show documentation
Show all versions of bcprov-jdk15to18 Show documentation
The Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. This jar contains JCE provider and lightweight API for the Bouncy Castle Cryptography APIs for JDK 1.5 to JDK 1.8.
The newest version!
package org.bouncycastle.crypto.engines;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.OutputLengthException;
import org.bouncycastle.util.Arrays;
abstract class AEADBufferBaseEngine
extends AEADBaseEngine
{
protected enum State
{
Uninitialized,
EncInit,
EncAad,
EncData,
EncFinal,
DecInit,
DecAad,
DecData,
DecFinal,
}
protected byte[] m_buf;
protected byte[] m_aad;
protected int m_bufPos;
protected int m_aadPos;
protected boolean aadFinished;
protected boolean initialised = false;
protected int AADBufferSize;
protected int BlockSize;
protected State m_state = State.Uninitialized;
@Override
public void processAADByte(byte input)
{
checkAAD();
if (m_aadPos == AADBufferSize)
{
processBufferAAD(m_aad, 0);
m_aadPos = 0;
}
m_aad[m_aadPos++] = input;
}
@Override
public void processAADBytes(byte[] input, int inOff, int len)
{
if ((inOff + len) > input.length)
{
throw new DataLengthException("input buffer too short");
}
// Don't enter AAD state until we actually get input
if (len <= 0)
{
return;
}
checkAAD();
if (m_aadPos > 0)
{
int available = AADBufferSize - m_aadPos;
if (len <= available)
{
System.arraycopy(input, inOff, m_aad, m_aadPos, len);
m_aadPos += len;
return;
}
System.arraycopy(input, inOff, m_aad, m_aadPos, available);
inOff += available;
len -= available;
processBufferAAD(m_aad, 0);
m_aadPos = 0;
}
while (len > AADBufferSize)
{
processBufferAAD(input, inOff);
inOff += AADBufferSize;
len -= AADBufferSize;
}
System.arraycopy(input, inOff, m_aad, m_aadPos, len);
m_aadPos += len;
}
@Override
public int processBytes(byte[] input, int inOff, int len, byte[] output, int outOff)
throws DataLengthException
{
if (inOff + len > input.length)
{
throw new DataLengthException("input buffer too short");
}
boolean forEncryption = checkData();
int resultLength = 0;
if (forEncryption)
{
if (m_bufPos > 0)
{
int available = BlockSize - m_bufPos;
if (len <= available)
{
System.arraycopy(input, inOff, m_buf, m_bufPos, len);
m_bufPos += len;
return 0;
}
System.arraycopy(input, inOff, m_buf, m_bufPos, available);
inOff += available;
len -= available;
validateAndProcessBuffer(m_buf, 0, output, outOff);
resultLength = BlockSize;
//m_bufPos = 0;
}
while (len > BlockSize)
{
validateAndProcessBuffer(input, inOff, output, outOff + resultLength);
inOff += BlockSize;
len -= BlockSize;
resultLength += BlockSize;
}
}
else
{
int available = BlockSize + MAC_SIZE - m_bufPos;
if (len <= available)
{
System.arraycopy(input, inOff, m_buf, m_bufPos, len);
m_bufPos += len;
return 0;
}
if (BlockSize >= MAC_SIZE)
{
if (m_bufPos > BlockSize)
{
validateAndProcessBuffer(m_buf, 0, output, outOff);
m_bufPos -= BlockSize;
System.arraycopy(m_buf, BlockSize, m_buf, 0, m_bufPos);
resultLength = BlockSize;
available += BlockSize;
if (len <= available)
{
System.arraycopy(input, inOff, m_buf, m_bufPos, len);
m_bufPos += len;
return resultLength;
}
}
available = BlockSize - m_bufPos;
System.arraycopy(input, inOff, m_buf, m_bufPos, available);
inOff += available;
len -= available;
validateAndProcessBuffer(m_buf, 0, output, outOff + resultLength);
resultLength += BlockSize;
//m_bufPos = 0;
}
else
{
while (m_bufPos > BlockSize && len + m_bufPos > BlockSize + MAC_SIZE)
{
validateAndProcessBuffer(m_buf, resultLength, output, outOff + resultLength);
m_bufPos -= BlockSize;
resultLength += BlockSize;
}
if (m_bufPos != 0)
{
System.arraycopy(m_buf, resultLength, m_buf, 0, m_bufPos);
if (m_bufPos + len > BlockSize + MAC_SIZE)
{
available = Math.max(BlockSize - m_bufPos, 0);
System.arraycopy(input, inOff, m_buf, m_bufPos, available);
inOff += available;
validateAndProcessBuffer(m_buf, 0, output, outOff + resultLength);
resultLength += BlockSize;
len -= available;
}
else
{
System.arraycopy(input, inOff, m_buf, m_bufPos, len);
m_bufPos += len;
return resultLength;
}
}
}
while (len > BlockSize + MAC_SIZE)
{
validateAndProcessBuffer(input, inOff, output, outOff + resultLength);
inOff += BlockSize;
len -= BlockSize;
resultLength += BlockSize;
}
}
System.arraycopy(input, inOff, m_buf, 0, len);
m_bufPos = len;
return resultLength;
}
@Override
public int doFinal(byte[] output, int outOff)
throws IllegalStateException, InvalidCipherTextException
{
boolean forEncryption = checkData();
int resultLength;
if (forEncryption)
{
resultLength = m_bufPos + MAC_SIZE;
}
else
{
if (m_bufPos < MAC_SIZE)
{
throw new InvalidCipherTextException("data too short");
}
m_bufPos -= MAC_SIZE;
resultLength = m_bufPos;
}
if (outOff > output.length - resultLength)
{
throw new OutputLengthException("output buffer too short");
}
processFinalBlock(output, outOff);
if (forEncryption)
{
System.arraycopy(mac, 0, output, outOff + resultLength - MAC_SIZE, MAC_SIZE);
}
else
{
if (!Arrays.constantTimeAreEqual(MAC_SIZE, mac, 0, m_buf, m_bufPos))
{
throw new InvalidCipherTextException(algorithmName + " mac does not match");
}
}
reset(!forEncryption);
return resultLength;
}
public int getBlockSize()
{
return BlockSize;
}
public int getUpdateOutputSize(int len)
{
// The -1 is to account for the lazy processing of a full buffer
int total = Math.max(0, len) - 1;
switch (m_state)
{
case DecInit:
case DecAad:
total = Math.max(0, total - MAC_SIZE);
break;
case DecData:
case DecFinal:
total = Math.max(0, total + m_bufPos - MAC_SIZE);
break;
case EncData:
case EncFinal:
total = Math.max(0, total + m_bufPos);
break;
default:
break;
}
return total - total % BlockSize;
}
public int getOutputSize(int len)
{
int total = Math.max(0, len);
switch (m_state)
{
case DecInit:
case DecAad:
return Math.max(0, total - MAC_SIZE);
case DecData:
case DecFinal:
return Math.max(0, total + m_bufPos - MAC_SIZE);
case EncData:
case EncFinal:
return total + m_bufPos + MAC_SIZE;
default:
return total + MAC_SIZE;
}
}
protected void checkAAD()
{
switch (m_state)
{
case DecInit:
m_state = State.DecAad;
break;
case EncInit:
m_state = State.EncAad;
break;
case DecAad:
case EncAad:
break;
case EncFinal:
throw new IllegalStateException(getAlgorithmName() + " cannot be reused for encryption");
default:
throw new IllegalStateException(getAlgorithmName() + " needs to be initialized");
}
}
protected boolean checkData()
{
switch (m_state)
{
case DecInit:
case DecAad:
finishAAD(State.DecData);
return false;
case EncInit:
case EncAad:
finishAAD(State.EncData);
return true;
case DecData:
return false;
case EncData:
return true;
case EncFinal:
throw new IllegalStateException(getAlgorithmName() + " cannot be reused for encryption");
default:
throw new IllegalStateException(getAlgorithmName() + " needs to be initialized");
}
}
private void finishAAD(State nextState)
{
// State indicates whether we ever received AAD
switch (m_state)
{
case DecAad:
case EncAad:
{
processFinalAAD();
break;
}
default:
break;
}
m_aadPos = 0;
m_state = nextState;
}
protected void bufferReset()
{
Arrays.fill(m_buf, (byte)0);
Arrays.fill(m_aad, (byte)0);
m_bufPos = 0;
m_aadPos = 0;
switch (m_state)
{
case DecInit:
case EncInit:
break;
case DecAad:
case DecData:
case DecFinal:
m_state = State.DecInit;
break;
case EncAad:
case EncData:
case EncFinal:
m_state = State.EncFinal;
return;
default:
throw new IllegalStateException(getAlgorithmName() + " needs to be initialized");
}
}
protected void validateAndProcessBuffer(byte[] input, int inOff, byte[] output, int outOff)
{
if (outOff > output.length - BlockSize)
{
throw new OutputLengthException("output buffer too short");
}
processBuffer(input, inOff, output, outOff);
}
protected abstract void processFinalBlock(byte[] output, int outOff);
protected abstract void processBufferAAD(byte[] input, int inOff);
protected abstract void processFinalAAD();
protected abstract void processBuffer(byte[] input, int inOff, byte[] output, int outOff);
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy