what-the-bank/sources/org/bouncycastle/crypto/modes/CCMBlockCipher.java

332 lines
12 KiB
Java
Raw Permalink Normal View History

2024-07-27 18:17:47 +07:00
package org.bouncycastle.crypto.modes;
import com.google.common.primitives.SignedBytes;
import java.io.ByteArrayOutputStream;
import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.OutputLengthException;
import org.bouncycastle.crypto.macs.CBCBlockCipherMac;
import org.bouncycastle.crypto.params.AEADParameters;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.bouncycastle.util.Arrays;
/* loaded from: classes6.dex */
public class CCMBlockCipher implements AEADBlockCipher {
private int blockSize;
private BlockCipher cipher;
private boolean forEncryption;
private byte[] initialAssociatedText;
private CipherParameters keyParam;
private byte[] macBlock;
private int macSize;
private byte[] nonce;
private ExposedByteArrayOutputStream associatedText = new ExposedByteArrayOutputStream(this);
private ExposedByteArrayOutputStream data = new ExposedByteArrayOutputStream(this);
@Override // org.bouncycastle.crypto.modes.AEADBlockCipher
public int getUpdateOutputSize(int i) {
return 0;
}
@Override // org.bouncycastle.crypto.modes.AEADBlockCipher
public void reset() {
this.cipher.reset();
this.associatedText.reset();
this.data.reset();
}
public byte[] processPacket(byte[] bArr, int i, int i2) throws IllegalStateException, InvalidCipherTextException {
int i3;
if (this.forEncryption) {
i3 = this.macSize + i2;
} else {
int i4 = this.macSize;
if (i2 < i4) {
throw new InvalidCipherTextException("data too short");
}
i3 = i2 - i4;
}
byte[] bArr2 = new byte[i3];
processPacket(bArr, i, i2, bArr2, 0);
return bArr2;
}
public int processPacket(byte[] bArr, int i, int i2, byte[] bArr2, int i3) throws IllegalStateException, InvalidCipherTextException, DataLengthException {
int i4;
if (this.keyParam == null) {
throw new IllegalStateException("CCM cipher unitialized.");
}
byte[] bArr3 = this.nonce;
int length = bArr3.length;
int i5 = 15 - length;
if (i5 < 4 && i2 >= (1 << (i5 << 3))) {
throw new IllegalStateException("CCM packet too large for choice of q.");
}
byte[] bArr4 = new byte[this.blockSize];
bArr4[0] = (byte) ((14 - length) & 7);
System.arraycopy(bArr3, 0, bArr4, 1, bArr3.length);
SICBlockCipher sICBlockCipher = new SICBlockCipher(this.cipher);
sICBlockCipher.init(this.forEncryption, new ParametersWithIV(this.keyParam, bArr4));
if (!this.forEncryption) {
int i6 = this.macSize;
if (i2 < i6) {
throw new InvalidCipherTextException("data too short");
}
int i7 = i2 - i6;
if (bArr2.length < i7 + i3) {
throw new OutputLengthException("Output buffer too short.");
}
int i8 = i + i7;
System.arraycopy(bArr, i8, this.macBlock, 0, i6);
byte[] bArr5 = this.macBlock;
sICBlockCipher.processBlock(bArr5, 0, bArr5, 0);
int i9 = this.macSize;
while (true) {
byte[] bArr6 = this.macBlock;
if (i9 == bArr6.length) {
break;
}
bArr6[i9] = 0;
i9++;
}
int i10 = i;
int i11 = i3;
while (true) {
i4 = this.blockSize;
if (i10 >= i8 - i4) {
break;
}
sICBlockCipher.processBlock(bArr, i10, bArr2, i11);
int i12 = this.blockSize;
i11 += i12;
i10 += i12;
}
byte[] bArr7 = new byte[i4];
int i13 = i7 - (i10 - i);
System.arraycopy(bArr, i10, bArr7, 0, i13);
sICBlockCipher.processBlock(bArr7, 0, bArr7, 0);
System.arraycopy(bArr7, 0, bArr2, i11, i13);
byte[] bArr8 = new byte[this.blockSize];
calculateMac(bArr2, i3, i7, bArr8);
if (Arrays.constantTimeAreEqual(this.macBlock, bArr8)) {
return i7;
}
throw new InvalidCipherTextException("mac check in CCM failed");
}
int i14 = this.macSize + i2;
if (bArr2.length < i14 + i3) {
throw new OutputLengthException("Output buffer too short.");
}
calculateMac(bArr, i, i2, this.macBlock);
byte[] bArr9 = new byte[this.blockSize];
sICBlockCipher.processBlock(this.macBlock, 0, bArr9, 0);
int i15 = i;
int i16 = i3;
while (true) {
int i17 = i + i2;
int i18 = this.blockSize;
if (i15 >= i17 - i18) {
byte[] bArr10 = new byte[i18];
int i19 = i17 - i15;
System.arraycopy(bArr, i15, bArr10, 0, i19);
sICBlockCipher.processBlock(bArr10, 0, bArr10, 0);
System.arraycopy(bArr10, 0, bArr2, i16, i19);
System.arraycopy(bArr9, 0, bArr2, i3 + i2, this.macSize);
return i14;
}
sICBlockCipher.processBlock(bArr, i15, bArr2, i16);
int i20 = this.blockSize;
i16 += i20;
i15 += i20;
}
}
@Override // org.bouncycastle.crypto.modes.AEADBlockCipher
public int processBytes(byte[] bArr, int i, int i2, byte[] bArr2, int i3) throws DataLengthException, IllegalStateException {
if (bArr.length < i + i2) {
throw new DataLengthException("Input buffer too short");
}
this.data.write(bArr, i, i2);
return 0;
}
@Override // org.bouncycastle.crypto.modes.AEADBlockCipher
public int processByte(byte b, byte[] bArr, int i) throws DataLengthException, IllegalStateException {
this.data.write(b);
return 0;
}
@Override // org.bouncycastle.crypto.modes.AEADBlockCipher
public void processAADBytes(byte[] bArr, int i, int i2) {
this.associatedText.write(bArr, i, i2);
}
@Override // org.bouncycastle.crypto.modes.AEADBlockCipher
public void processAADByte(byte b) {
this.associatedText.write(b);
}
@Override // org.bouncycastle.crypto.modes.AEADBlockCipher
public void init(boolean z, CipherParameters cipherParameters) throws IllegalArgumentException {
CipherParameters parameters;
this.forEncryption = z;
if (cipherParameters instanceof AEADParameters) {
AEADParameters aEADParameters = (AEADParameters) cipherParameters;
this.nonce = aEADParameters.getNonce();
this.initialAssociatedText = aEADParameters.getAssociatedText();
this.macSize = aEADParameters.getMacSize() / 8;
parameters = aEADParameters.getKey();
} else {
if (!(cipherParameters instanceof ParametersWithIV)) {
StringBuilder sb = new StringBuilder("invalid parameters passed to CCM: ");
sb.append(cipherParameters.getClass().getName());
throw new IllegalArgumentException(sb.toString());
}
ParametersWithIV parametersWithIV = (ParametersWithIV) cipherParameters;
this.nonce = parametersWithIV.getIV();
this.initialAssociatedText = null;
this.macSize = this.macBlock.length / 2;
parameters = parametersWithIV.getParameters();
}
if (parameters != null) {
this.keyParam = parameters;
}
byte[] bArr = this.nonce;
if (bArr == null || bArr.length < 7 || bArr.length > 13) {
throw new IllegalArgumentException("nonce must have length from 7 to 13 octets");
}
reset();
}
@Override // org.bouncycastle.crypto.modes.AEADBlockCipher
public BlockCipher getUnderlyingCipher() {
return this.cipher;
}
@Override // org.bouncycastle.crypto.modes.AEADBlockCipher
public int getOutputSize(int i) {
int size = i + this.data.size();
if (this.forEncryption) {
return size + this.macSize;
}
int i2 = this.macSize;
if (size < i2) {
return 0;
}
return size - i2;
}
@Override // org.bouncycastle.crypto.modes.AEADBlockCipher
public byte[] getMac() {
int i = this.macSize;
byte[] bArr = new byte[i];
System.arraycopy(this.macBlock, 0, bArr, 0, i);
return bArr;
}
@Override // org.bouncycastle.crypto.modes.AEADBlockCipher
public String getAlgorithmName() {
StringBuilder sb = new StringBuilder();
sb.append(this.cipher.getAlgorithmName());
sb.append("/CCM");
return sb.toString();
}
@Override // org.bouncycastle.crypto.modes.AEADBlockCipher
public int doFinal(byte[] bArr, int i) throws IllegalStateException, InvalidCipherTextException {
int processPacket = processPacket(this.data.getBuffer(), 0, this.data.size(), bArr, i);
reset();
return processPacket;
}
private boolean hasAssociatedText() {
return getAssociatedTextLength() > 0;
}
/* JADX INFO: Access modifiers changed from: package-private */
/* loaded from: classes6.dex */
public class ExposedByteArrayOutputStream extends ByteArrayOutputStream {
final CCMBlockCipher this$0;
public byte[] getBuffer() {
return ((ByteArrayOutputStream) this).buf;
}
public ExposedByteArrayOutputStream(CCMBlockCipher cCMBlockCipher) {
this.this$0 = cCMBlockCipher;
}
}
private int getAssociatedTextLength() {
int size = this.associatedText.size();
byte[] bArr = this.initialAssociatedText;
return size + (bArr == null ? 0 : bArr.length);
}
private int calculateMac(byte[] bArr, int i, int i2, byte[] bArr2) {
CBCBlockCipherMac cBCBlockCipherMac = new CBCBlockCipherMac(this.cipher, this.macSize << 3);
cBCBlockCipherMac.init(this.keyParam);
byte[] bArr3 = new byte[16];
if (hasAssociatedText()) {
bArr3[0] = (byte) (bArr3[0] | SignedBytes.MAX_POWER_OF_TWO);
}
int i3 = 2;
byte macSize = (byte) (bArr3[0] | ((((cBCBlockCipherMac.getMacSize() - 2) / 2) & 7) << 3));
bArr3[0] = macSize;
byte[] bArr4 = this.nonce;
bArr3[0] = (byte) (macSize | ((14 - bArr4.length) & 7));
System.arraycopy(bArr4, 0, bArr3, 1, bArr4.length);
int i4 = i2;
int i5 = 1;
while (i4 > 0) {
bArr3[16 - i5] = (byte) i4;
i4 >>>= 8;
i5++;
}
cBCBlockCipherMac.update(bArr3, 0, 16);
if (hasAssociatedText()) {
int associatedTextLength = getAssociatedTextLength();
if (associatedTextLength < 65280) {
cBCBlockCipherMac.update((byte) (associatedTextLength >> 8));
cBCBlockCipherMac.update((byte) associatedTextLength);
} else {
cBCBlockCipherMac.update((byte) -1);
cBCBlockCipherMac.update((byte) -2);
cBCBlockCipherMac.update((byte) (associatedTextLength >> 24));
cBCBlockCipherMac.update((byte) (associatedTextLength >> 16));
cBCBlockCipherMac.update((byte) (associatedTextLength >> 8));
cBCBlockCipherMac.update((byte) associatedTextLength);
i3 = 6;
}
byte[] bArr5 = this.initialAssociatedText;
if (bArr5 != null) {
cBCBlockCipherMac.update(bArr5, 0, bArr5.length);
}
if (this.associatedText.size() > 0) {
cBCBlockCipherMac.update(this.associatedText.getBuffer(), 0, this.associatedText.size());
}
int i6 = (i3 + associatedTextLength) % 16;
if (i6 != 0) {
while (i6 != 16) {
cBCBlockCipherMac.update((byte) 0);
i6++;
}
}
}
cBCBlockCipherMac.update(bArr, i, i2);
return cBCBlockCipherMac.doFinal(bArr2, 0);
}
public CCMBlockCipher(BlockCipher blockCipher) {
this.cipher = blockCipher;
int blockSize = blockCipher.getBlockSize();
this.blockSize = blockSize;
this.macBlock = new byte[blockSize];
if (blockSize != 16) {
throw new IllegalArgumentException("cipher required with a block size of 16.");
}
}
}