org.bouncycastle.crypto.modes.AESCTRPacketCipher Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bcprov-lts8on Show documentation
Show all versions of bcprov-lts8on Show documentation
The Long Term Stable (LTS) Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. This jar contains the JCA/JCE provider and low-level API for the BC LTS version 2.73.7 for Java 8 and later.
package org.bouncycastle.crypto.modes;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.ExceptionMessages;
import org.bouncycastle.crypto.NativeServices;
import org.bouncycastle.crypto.OutputLengthException;
import org.bouncycastle.crypto.PacketCipherException;
import org.bouncycastle.crypto.engines.AESNativeCTRPacketCipher;
import org.bouncycastle.crypto.engines.AESPacketCipher;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.Bytes;
public class AESCTRPacketCipher
implements AESCTRModePacketCipher
{
public static AESCTRModePacketCipher newInstance()
{
if (CryptoServicesRegistrar.hasEnabledService(NativeServices.AES_CTR_PC))
{
return new AESNativeCTRPacketCipher();
}
return new AESCTRPacketCipher();
}
private AESCTRPacketCipher()
{
}
@Override
public int getOutputSize(boolean encryption, CipherParameters parameters, int len)
{
if (len < 0)
{
throw new IllegalArgumentException(ExceptionMessages.LEN_NEGATIVE);
}
checkParameters(parameters);
return len;
}
@Override
public int processPacket(boolean encryption, CipherParameters parameters, byte[] input, int inOff, final int len,
byte[] output, int outOff)
throws PacketCipherException
{
PacketCipherChecks.checkBoundsInputAndOutput(input, inOff, len, output, outOff);
if (len == 0)
{
return 0;
}
byte[] ivOwned;
byte[] counter = new byte[AESPacketCipher.BLOCK_SIZE];
byte[] counterOut = new byte[AESPacketCipher.BLOCK_SIZE];
int[][] workingKey;
byte[] s = AESPacketCipher.createS(true);
if (parameters instanceof ParametersWithIV)
{
ParametersWithIV ivParam = (ParametersWithIV) parameters;
ivOwned = Arrays.clone(ivParam.getIV());
if (ivOwned.length > AESPacketCipher.BLOCK_SIZE)
{
throw new IllegalArgumentException(ExceptionMessages.CTR16_IV_TOO_LONG);
}
if (ivOwned.length < 8)
{
throw new IllegalArgumentException(ExceptionMessages.CTR16_IV_TOO_SHORT);
}
System.arraycopy(ivOwned, 0, counter, 0, ivOwned.length);
KeyParameter keyParameter = (KeyParameter) ivParam.getParameters();
if (keyParameter == null)
{
throw PacketCipherException.from(new IllegalStateException(ExceptionMessages.CTR_CIPHER_UNITIALIZED));
}
int keyLen = keyParameter.getKey().length;
PacketCipherChecks.checkKeyLength(keyLen);
workingKey = AESPacketCipher.generateWorkingKey(true, keyParameter.getKey());
}
else
{
throw new IllegalArgumentException(ExceptionMessages.CTR_INVALID_PARAMETER);
}
int ctrSize = AESPacketCipher.BLOCK_SIZE - ivOwned.length;
if (ctrSize > 0 && ctrSize < 4)
{
//
// We may have a problem because they could pass in more info than
// we have counter space for. With bigger counters they cannot pass in
// an array big enough to overflow the counter.
// If set with a 16byte iv then the assumption is the caller
// knows what they are doing.
//
int ctrBits = ctrSize * 8;
int maxBlocks = 1 << ctrBits;
int maxLen = maxBlocks * AESPacketCipher.BLOCK_SIZE;
if (len > maxLen)
{
throw new IllegalStateException("Counter in CTR/SIC mode out of range.");
}
}
int remaining = len;
while (remaining > AESPacketCipher.BLOCK_SIZE)
{
AESPacketCipher.processBlock(true, workingKey, s, counter, 0, counterOut, 0);
Bytes.xor(AESPacketCipher.BLOCK_SIZE, input, inOff, counterOut, 0, output, outOff);
incrementCounter(counter, ivOwned);
inOff += AESPacketCipher.BLOCK_SIZE;
outOff += AESPacketCipher.BLOCK_SIZE;
remaining -= AESPacketCipher.BLOCK_SIZE;
}
AESPacketCipher.processBlock(true, workingKey, s, counter, 0, counterOut, 0);
Bytes.xor(remaining, input, inOff, counterOut, 0, output, outOff);
Arrays.clear(counterOut);
Arrays.clear(counter);
Arrays.clear(ivOwned);
Arrays.clear(workingKey);
Arrays.clear(s);
return len;
}
private static void incrementCounter(byte[] counter, byte[] iv)
{
int i = counter.length;
while (--i >= 0)
{
if (++counter[i] != 0)
{
break;
}
}
}
@Override
public String toString()
{
return "CTR-PS[Java](AES[Java])";
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy