264 lines
9.7 KiB
Java
264 lines
9.7 KiB
Java
|
package org.bouncycastle.crypto.tls;
|
||
|
|
||
|
import com.google.common.primitives.UnsignedBytes;
|
||
|
import java.io.IOException;
|
||
|
import java.security.SecureRandom;
|
||
|
import org.bouncycastle.crypto.BlockCipher;
|
||
|
import org.bouncycastle.crypto.Digest;
|
||
|
import org.bouncycastle.crypto.params.KeyParameter;
|
||
|
import org.bouncycastle.crypto.params.ParametersWithIV;
|
||
|
import org.bouncycastle.util.Arrays;
|
||
|
|
||
|
/* loaded from: classes6.dex */
|
||
|
public class TlsBlockCipher implements TlsCipher {
|
||
|
protected TlsContext context;
|
||
|
protected BlockCipher decryptCipher;
|
||
|
protected BlockCipher encryptCipher;
|
||
|
protected boolean encryptThenMAC;
|
||
|
protected byte[] randomData = new byte[256];
|
||
|
protected TlsMac readMac;
|
||
|
protected boolean useExplicitIV;
|
||
|
protected TlsMac writeMac;
|
||
|
|
||
|
protected int lowestBitSet(int i) {
|
||
|
if (i == 0) {
|
||
|
return 32;
|
||
|
}
|
||
|
int i2 = 0;
|
||
|
while ((i & 1) == 0) {
|
||
|
i2++;
|
||
|
i >>= 1;
|
||
|
}
|
||
|
return i2;
|
||
|
}
|
||
|
|
||
|
public TlsMac getWriteMac() {
|
||
|
return this.writeMac;
|
||
|
}
|
||
|
|
||
|
public TlsMac getReadMac() {
|
||
|
return this.readMac;
|
||
|
}
|
||
|
|
||
|
@Override // org.bouncycastle.crypto.tls.TlsCipher
|
||
|
public int getPlaintextLimit(int i) {
|
||
|
int i2;
|
||
|
int blockSize = this.encryptCipher.getBlockSize();
|
||
|
int size = this.writeMac.getSize();
|
||
|
if (this.useExplicitIV) {
|
||
|
i -= blockSize;
|
||
|
}
|
||
|
if (this.encryptThenMAC) {
|
||
|
int i3 = i - size;
|
||
|
i2 = i3 - (i3 % blockSize);
|
||
|
} else {
|
||
|
i2 = (i - (i % blockSize)) - size;
|
||
|
}
|
||
|
return i2 - 1;
|
||
|
}
|
||
|
|
||
|
@Override // org.bouncycastle.crypto.tls.TlsCipher
|
||
|
public byte[] encodePlaintext(long j, short s, byte[] bArr, int i, int i2) {
|
||
|
byte[] bArr2;
|
||
|
int i3;
|
||
|
int i4;
|
||
|
int blockSize = this.encryptCipher.getBlockSize();
|
||
|
int size = this.writeMac.getSize();
|
||
|
ProtocolVersion serverVersion = this.context.getServerVersion();
|
||
|
int i5 = (blockSize - 1) - ((!this.encryptThenMAC ? i2 + size : i2) % blockSize);
|
||
|
if (!serverVersion.isDTLS() && !serverVersion.isSSL()) {
|
||
|
i5 += chooseExtraPadBlocks(this.context.getSecureRandom(), (255 - i5) / blockSize) * blockSize;
|
||
|
}
|
||
|
int i6 = i5;
|
||
|
int i7 = size + i2 + i6 + 1;
|
||
|
boolean z = this.useExplicitIV;
|
||
|
if (z) {
|
||
|
i7 += blockSize;
|
||
|
}
|
||
|
byte[] bArr3 = new byte[i7];
|
||
|
if (z) {
|
||
|
byte[] bArr4 = new byte[blockSize];
|
||
|
this.context.getNonceRandomGenerator().nextBytes(bArr4);
|
||
|
this.encryptCipher.init(true, new ParametersWithIV(null, bArr4));
|
||
|
System.arraycopy(bArr4, 0, bArr3, 0, blockSize);
|
||
|
bArr2 = bArr;
|
||
|
i3 = i;
|
||
|
i4 = blockSize;
|
||
|
} else {
|
||
|
bArr2 = bArr;
|
||
|
i3 = i;
|
||
|
i4 = 0;
|
||
|
}
|
||
|
System.arraycopy(bArr2, i3, bArr3, i4, i2);
|
||
|
int i8 = i4 + i2;
|
||
|
if (!this.encryptThenMAC) {
|
||
|
byte[] calculateMac = this.writeMac.calculateMac(j, s, bArr, i, i2);
|
||
|
System.arraycopy(calculateMac, 0, bArr3, i8, calculateMac.length);
|
||
|
i8 += calculateMac.length;
|
||
|
}
|
||
|
int i9 = i8;
|
||
|
int i10 = 0;
|
||
|
while (i10 <= i6) {
|
||
|
bArr3[i9] = (byte) i6;
|
||
|
i10++;
|
||
|
i9++;
|
||
|
}
|
||
|
while (i4 < i9) {
|
||
|
this.encryptCipher.processBlock(bArr3, i4, bArr3, i4);
|
||
|
i4 += blockSize;
|
||
|
}
|
||
|
if (!this.encryptThenMAC) {
|
||
|
return bArr3;
|
||
|
}
|
||
|
byte[] calculateMac2 = this.writeMac.calculateMac(j, s, bArr3, 0, i9);
|
||
|
System.arraycopy(calculateMac2, 0, bArr3, i9, calculateMac2.length);
|
||
|
int length = calculateMac2.length;
|
||
|
return bArr3;
|
||
|
}
|
||
|
|
||
|
@Override // org.bouncycastle.crypto.tls.TlsCipher
|
||
|
public byte[] decodeCiphertext(long j, short s, byte[] bArr, int i, int i2) throws IOException {
|
||
|
int i3;
|
||
|
byte[] bArr2;
|
||
|
int i4 = i;
|
||
|
int blockSize = this.decryptCipher.getBlockSize();
|
||
|
int size = this.readMac.getSize();
|
||
|
int max = this.encryptThenMAC ? blockSize + size : Math.max(blockSize, size + 1);
|
||
|
if (this.useExplicitIV) {
|
||
|
max += blockSize;
|
||
|
}
|
||
|
if (i2 < max) {
|
||
|
throw new TlsFatalAlert((short) 50);
|
||
|
}
|
||
|
boolean z = this.encryptThenMAC;
|
||
|
int i5 = z ? i2 - size : i2;
|
||
|
if (i5 % blockSize != 0) {
|
||
|
throw new TlsFatalAlert((short) 21);
|
||
|
}
|
||
|
if (z) {
|
||
|
int i6 = i4 + i2;
|
||
|
if (!Arrays.constantTimeAreEqual(this.readMac.calculateMac(j, s, bArr, i, i2 - size), Arrays.copyOfRange(bArr, i6 - size, i6))) {
|
||
|
throw new TlsFatalAlert((short) 20);
|
||
|
}
|
||
|
}
|
||
|
if (this.useExplicitIV) {
|
||
|
this.decryptCipher.init(false, new ParametersWithIV(null, bArr, i4, blockSize));
|
||
|
i4 += blockSize;
|
||
|
i5 -= blockSize;
|
||
|
}
|
||
|
int i7 = i4;
|
||
|
int i8 = i5;
|
||
|
for (int i9 = 0; i9 < i8; i9 += blockSize) {
|
||
|
int i10 = i7 + i9;
|
||
|
this.decryptCipher.processBlock(bArr, i10, bArr, i10);
|
||
|
}
|
||
|
int checkPaddingConstantTime = checkPaddingConstantTime(bArr, i7, i8, blockSize, this.encryptThenMAC ? 0 : size);
|
||
|
boolean z2 = checkPaddingConstantTime == 0;
|
||
|
int i11 = i8 - checkPaddingConstantTime;
|
||
|
if (this.encryptThenMAC) {
|
||
|
i3 = i7;
|
||
|
bArr2 = bArr;
|
||
|
} else {
|
||
|
i11 -= size;
|
||
|
int i12 = i7 + i11;
|
||
|
i3 = i7;
|
||
|
bArr2 = bArr;
|
||
|
z2 |= !Arrays.constantTimeAreEqual(this.readMac.calculateMacConstantTime(j, s, bArr, i7, i11, i8 - size, this.randomData), Arrays.copyOfRange(bArr, i12, i12 + size));
|
||
|
}
|
||
|
if (z2) {
|
||
|
throw new TlsFatalAlert((short) 20);
|
||
|
}
|
||
|
return Arrays.copyOfRange(bArr2, i3, i3 + i11);
|
||
|
}
|
||
|
|
||
|
protected int chooseExtraPadBlocks(SecureRandom secureRandom, int i) {
|
||
|
return Math.min(lowestBitSet(secureRandom.nextInt()), i);
|
||
|
}
|
||
|
|
||
|
protected int checkPaddingConstantTime(byte[] bArr, int i, int i2, int i3, int i4) {
|
||
|
byte b;
|
||
|
int i5;
|
||
|
int i6 = i + i2;
|
||
|
byte b2 = bArr[i6 - 1];
|
||
|
int i7 = (b2 & UnsignedBytes.MAX_VALUE) + 1;
|
||
|
if ((!TlsUtils.isSSL(this.context) || i7 <= i3) && i4 + i7 <= i2) {
|
||
|
int i8 = i6 - i7;
|
||
|
b = 0;
|
||
|
while (true) {
|
||
|
int i9 = i8 + 1;
|
||
|
b = (byte) ((bArr[i8] ^ b2) | b);
|
||
|
if (i9 >= i6) {
|
||
|
break;
|
||
|
}
|
||
|
i8 = i9;
|
||
|
}
|
||
|
i5 = i7;
|
||
|
if (b != 0) {
|
||
|
i7 = 0;
|
||
|
}
|
||
|
} else {
|
||
|
i5 = 0;
|
||
|
b = 0;
|
||
|
i7 = 0;
|
||
|
}
|
||
|
byte[] bArr2 = this.randomData;
|
||
|
while (i5 < 256) {
|
||
|
b = (byte) ((bArr2[i5] ^ b2) | b);
|
||
|
i5++;
|
||
|
}
|
||
|
bArr2[0] = (byte) (bArr2[0] ^ b);
|
||
|
return i7;
|
||
|
}
|
||
|
|
||
|
public TlsBlockCipher(TlsContext tlsContext, BlockCipher blockCipher, BlockCipher blockCipher2, Digest digest, Digest digest2, int i) throws IOException {
|
||
|
byte[] copyOfRange;
|
||
|
byte[] copyOfRange2;
|
||
|
ParametersWithIV parametersWithIV;
|
||
|
ParametersWithIV parametersWithIV2;
|
||
|
this.context = tlsContext;
|
||
|
tlsContext.getNonceRandomGenerator().nextBytes(this.randomData);
|
||
|
this.useExplicitIV = TlsUtils.isTLSv11(tlsContext);
|
||
|
this.encryptThenMAC = tlsContext.getSecurityParameters().encryptThenMAC;
|
||
|
int digestSize = (i << 1) + digest.getDigestSize() + digest2.getDigestSize();
|
||
|
int blockSize = this.useExplicitIV ? digestSize : digestSize + blockCipher.getBlockSize() + blockCipher2.getBlockSize();
|
||
|
byte[] calculateKeyBlock = TlsUtils.calculateKeyBlock(tlsContext, blockSize);
|
||
|
TlsMac tlsMac = new TlsMac(tlsContext, digest, calculateKeyBlock, 0, digest.getDigestSize());
|
||
|
int digestSize2 = digest.getDigestSize();
|
||
|
TlsMac tlsMac2 = new TlsMac(tlsContext, digest2, calculateKeyBlock, digestSize2, digest2.getDigestSize());
|
||
|
int digestSize3 = digestSize2 + digest2.getDigestSize();
|
||
|
KeyParameter keyParameter = new KeyParameter(calculateKeyBlock, digestSize3, i);
|
||
|
int i2 = digestSize3 + i;
|
||
|
KeyParameter keyParameter2 = new KeyParameter(calculateKeyBlock, i2, i);
|
||
|
int i3 = i2 + i;
|
||
|
if (this.useExplicitIV) {
|
||
|
copyOfRange = new byte[blockCipher.getBlockSize()];
|
||
|
copyOfRange2 = new byte[blockCipher2.getBlockSize()];
|
||
|
} else {
|
||
|
copyOfRange = Arrays.copyOfRange(calculateKeyBlock, i3, blockCipher.getBlockSize() + i3);
|
||
|
int blockSize2 = i3 + blockCipher.getBlockSize();
|
||
|
copyOfRange2 = Arrays.copyOfRange(calculateKeyBlock, blockSize2, blockCipher2.getBlockSize() + blockSize2);
|
||
|
i3 = blockSize2 + blockCipher2.getBlockSize();
|
||
|
}
|
||
|
if (i3 != blockSize) {
|
||
|
throw new TlsFatalAlert((short) 80);
|
||
|
}
|
||
|
if (tlsContext.isServer()) {
|
||
|
this.writeMac = tlsMac2;
|
||
|
this.readMac = tlsMac;
|
||
|
this.encryptCipher = blockCipher2;
|
||
|
this.decryptCipher = blockCipher;
|
||
|
parametersWithIV = new ParametersWithIV(keyParameter2, copyOfRange2);
|
||
|
parametersWithIV2 = new ParametersWithIV(keyParameter, copyOfRange);
|
||
|
} else {
|
||
|
this.writeMac = tlsMac;
|
||
|
this.readMac = tlsMac2;
|
||
|
this.encryptCipher = blockCipher;
|
||
|
this.decryptCipher = blockCipher2;
|
||
|
parametersWithIV = new ParametersWithIV(keyParameter, copyOfRange);
|
||
|
parametersWithIV2 = new ParametersWithIV(keyParameter2, copyOfRange2);
|
||
|
}
|
||
|
this.encryptCipher.init(true, parametersWithIV);
|
||
|
this.decryptCipher.init(false, parametersWithIV2);
|
||
|
}
|
||
|
}
|