what-the-bank/sources/org/bouncycastle/crypto/prng/drbg/CTRSP800DRBG.java

296 lines
11 KiB
Java
Raw Permalink Normal View History

2024-07-27 18:17:47 +07:00
package org.bouncycastle.crypto.prng.drbg;
import com.google.common.primitives.UnsignedBytes;
import net.sf.scuba.smartcards.ISO7816;
import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.prng.EntropySource;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.encoders.Hex;
/* loaded from: classes6.dex */
public class CTRSP800DRBG implements SP80090DRBG {
private static final int AES_MAX_BITS_REQUEST = 262144;
private static final long AES_RESEED_MAX = 140737488355328L;
private static final byte[] K_BITS = Hex.decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F");
private static final int TDEA_MAX_BITS_REQUEST = 4096;
private static final long TDEA_RESEED_MAX = 2147483648L;
private byte[] _Key;
private byte[] _V;
private BlockCipher _engine;
private EntropySource _entropySource;
private boolean _isTDEA;
private int _keySizeInBits;
private long _reseedCounter = 0;
private int _securityStrength;
private int _seedLength;
@Override // org.bouncycastle.crypto.prng.drbg.SP80090DRBG
public void reseed(byte[] bArr) {
CTR_DRBG_Reseed_algorithm(bArr);
}
@Override // org.bouncycastle.crypto.prng.drbg.SP80090DRBG
public int getBlockSize() {
return this._V.length << 3;
}
@Override // org.bouncycastle.crypto.prng.drbg.SP80090DRBG
public int generate(byte[] bArr, byte[] bArr2, boolean z) {
byte[] bArr3;
boolean z2 = this._isTDEA;
long j = this._reseedCounter;
if (z2) {
if (j > TDEA_RESEED_MAX) {
return -1;
}
if (Utils.isTooLarge(bArr, 512)) {
throw new IllegalArgumentException("Number of bits per request limited to 4096");
}
} else {
if (j > AES_RESEED_MAX) {
return -1;
}
if (Utils.isTooLarge(bArr, 32768)) {
throw new IllegalArgumentException("Number of bits per request limited to 262144");
}
}
if (z) {
CTR_DRBG_Reseed_algorithm(bArr2);
bArr2 = null;
}
if (bArr2 != null) {
bArr3 = Block_Cipher_df(bArr2, this._seedLength);
CTR_DRBG_Update(bArr3, this._Key, this._V);
} else {
bArr3 = new byte[this._seedLength];
}
int length = this._V.length;
byte[] bArr4 = new byte[length];
this._engine.init(true, new KeyParameter(expandKey(this._Key)));
for (int i = 0; i <= bArr.length / length; i++) {
int i2 = i * length;
int length2 = bArr.length - i2 > length ? length : bArr.length - (this._V.length * i);
if (length2 != 0) {
addOneTo(this._V);
this._engine.processBlock(this._V, 0, bArr4, 0);
System.arraycopy(bArr4, 0, bArr, i2, length2);
}
}
CTR_DRBG_Update(bArr3, this._Key, this._V);
this._reseedCounter++;
return bArr.length << 3;
}
byte[] expandKey(byte[] bArr) {
if (!this._isTDEA) {
return bArr;
}
byte[] bArr2 = new byte[24];
padKey(bArr, 0, bArr2, 0);
padKey(bArr, 7, bArr2, 8);
padKey(bArr, 14, bArr2, 16);
return bArr2;
}
private void padKey(byte[] bArr, int i, byte[] bArr2, int i2) {
bArr2[i2] = (byte) (bArr[i] & 254);
int i3 = i + 1;
bArr2[i2 + 1] = (byte) ((bArr[i] << 7) | ((bArr[i3] & 252) >>> 1));
byte b = bArr[i3];
int i4 = i + 2;
bArr2[i2 + 2] = (byte) ((b << 6) | ((bArr[i4] & 248) >>> 2));
byte b2 = bArr[i4];
int i5 = i + 3;
bArr2[i2 + 3] = (byte) ((b2 << 5) | ((bArr[i5] & 240) >>> 3));
byte b3 = bArr[i5];
int i6 = i + 4;
bArr2[i2 + 4] = (byte) ((b3 << 4) | ((bArr[i6] & ISO7816.INS_CREATE_FILE) >>> 4));
byte b4 = bArr[i6];
int i7 = i + 5;
bArr2[i2 + 5] = (byte) ((b4 << 3) | ((bArr[i7] & ISO7816.INS_GET_RESPONSE) >>> 5));
int i8 = i + 6;
bArr2[i2 + 6] = (byte) ((bArr[i7] << 2) | ((bArr[i8] & 128) >>> 6));
int i9 = i2 + 7;
bArr2[i9] = (byte) (bArr[i8] << 1);
while (i2 <= i9) {
byte b5 = bArr2[i2];
bArr2[i2] = (byte) ((b5 & 254) | ((((b5 >> 7) ^ ((((((b5 >> 1) ^ (b5 >> 2)) ^ (b5 >> 3)) ^ (b5 >> 4)) ^ (b5 >> 5)) ^ (b5 >> 6))) ^ 1) & 1));
i2++;
}
}
private boolean isTDEA(BlockCipher blockCipher) {
return blockCipher.getAlgorithmName().equals("DESede") || blockCipher.getAlgorithmName().equals("TDEA");
}
private int getMaxSecurityStrength(BlockCipher blockCipher, int i) {
if (isTDEA(blockCipher) && i == 168) {
return 112;
}
if (blockCipher.getAlgorithmName().equals("AES")) {
return i;
}
return -1;
}
private byte[] getEntropy() {
byte[] entropy = this._entropySource.getEntropy();
if (entropy.length >= (this._securityStrength + 7) / 8) {
return entropy;
}
throw new IllegalStateException("Insufficient entropy provided by entropy source");
}
private void copyIntToByteArray(byte[] bArr, int i, int i2) {
bArr[i2] = (byte) (i >> 24);
bArr[i2 + 1] = (byte) (i >> 16);
bArr[i2 + 2] = (byte) (i >> 8);
bArr[i2 + 3] = (byte) i;
}
private void addOneTo(byte[] bArr) {
int i = 1;
for (int i2 = 1; i2 <= bArr.length; i2++) {
int i3 = (bArr[bArr.length - i2] & UnsignedBytes.MAX_VALUE) + i;
i = i3 > 255 ? 1 : 0;
bArr[bArr.length - i2] = (byte) i3;
}
}
private void XOR(byte[] bArr, byte[] bArr2, byte[] bArr3, int i) {
for (int i2 = 0; i2 < bArr.length; i2++) {
bArr[i2] = (byte) (bArr2[i2] ^ bArr3[i2 + i]);
}
}
private void CTR_DRBG_Update(byte[] bArr, byte[] bArr2, byte[] bArr3) {
int length = bArr.length;
byte[] bArr4 = new byte[length];
byte[] bArr5 = new byte[this._engine.getBlockSize()];
int blockSize = this._engine.getBlockSize();
this._engine.init(true, new KeyParameter(expandKey(bArr2)));
int i = 0;
while (true) {
int i2 = i * blockSize;
if (i2 >= bArr.length) {
XOR(bArr4, bArr, bArr4, 0);
System.arraycopy(bArr4, 0, bArr2, 0, bArr2.length);
System.arraycopy(bArr4, bArr2.length, bArr3, 0, bArr3.length);
return;
} else {
addOneTo(bArr3);
this._engine.processBlock(bArr3, 0, bArr5, 0);
int i3 = length - i2;
if (i3 > blockSize) {
i3 = blockSize;
}
System.arraycopy(bArr5, 0, bArr4, i2, i3);
i++;
}
}
}
private void CTR_DRBG_Reseed_algorithm(byte[] bArr) {
CTR_DRBG_Update(Block_Cipher_df(Arrays.concatenate(getEntropy(), bArr), this._seedLength), this._Key, this._V);
this._reseedCounter = 1L;
}
private void CTR_DRBG_Instantiate_algorithm(byte[] bArr, byte[] bArr2, byte[] bArr3) {
byte[] Block_Cipher_df = Block_Cipher_df(Arrays.concatenate(bArr, bArr2, bArr3), this._seedLength);
int blockSize = this._engine.getBlockSize();
byte[] bArr4 = new byte[(this._keySizeInBits + 7) / 8];
this._Key = bArr4;
byte[] bArr5 = new byte[blockSize];
this._V = bArr5;
CTR_DRBG_Update(Block_Cipher_df, bArr4, bArr5);
this._reseedCounter = 1L;
}
private byte[] Block_Cipher_df(byte[] bArr, int i) {
int blockSize = this._engine.getBlockSize();
int length = bArr.length;
byte[] bArr2 = new byte[((((length + 9) + blockSize) - 1) / blockSize) * blockSize];
copyIntToByteArray(bArr2, length, 0);
copyIntToByteArray(bArr2, i / 8, 4);
System.arraycopy(bArr, 0, bArr2, 8, length);
bArr2[length + 8] = Byte.MIN_VALUE;
int i2 = this._keySizeInBits / 8;
int i3 = i2 + blockSize;
byte[] bArr3 = new byte[i3];
byte[] bArr4 = new byte[blockSize];
byte[] bArr5 = new byte[blockSize];
byte[] bArr6 = new byte[i2];
System.arraycopy(K_BITS, 0, bArr6, 0, i2);
int i4 = 0;
while (true) {
int i5 = i4 * blockSize;
if ((i5 << 3) >= this._keySizeInBits + (blockSize << 3)) {
break;
}
copyIntToByteArray(bArr5, i4, 0);
BCC(bArr4, bArr6, bArr5, bArr2);
int i6 = i3 - i5;
if (i6 > blockSize) {
i6 = blockSize;
}
System.arraycopy(bArr4, 0, bArr3, i5, i6);
i4++;
}
byte[] bArr7 = new byte[blockSize];
System.arraycopy(bArr3, 0, bArr6, 0, i2);
System.arraycopy(bArr3, i2, bArr7, 0, blockSize);
int i7 = i / 2;
byte[] bArr8 = new byte[i7];
this._engine.init(true, new KeyParameter(expandKey(bArr6)));
int i8 = 0;
while (true) {
int i9 = i8 * blockSize;
if (i9 >= i7) {
return bArr8;
}
this._engine.processBlock(bArr7, 0, bArr7, 0);
int i10 = i7 - i9;
if (i10 > blockSize) {
i10 = blockSize;
}
System.arraycopy(bArr7, 0, bArr8, i9, i10);
i8++;
}
}
private void BCC(byte[] bArr, byte[] bArr2, byte[] bArr3, byte[] bArr4) {
int blockSize = this._engine.getBlockSize();
byte[] bArr5 = new byte[blockSize];
int length = bArr4.length / blockSize;
byte[] bArr6 = new byte[blockSize];
this._engine.init(true, new KeyParameter(expandKey(bArr2)));
this._engine.processBlock(bArr3, 0, bArr5, 0);
for (int i = 0; i < length; i++) {
XOR(bArr6, bArr5, bArr4, i * blockSize);
this._engine.processBlock(bArr6, 0, bArr5, 0);
}
System.arraycopy(bArr5, 0, bArr, 0, bArr.length);
}
public CTRSP800DRBG(BlockCipher blockCipher, int i, int i2, EntropySource entropySource, byte[] bArr, byte[] bArr2) {
this._isTDEA = false;
this._entropySource = entropySource;
this._engine = blockCipher;
this._keySizeInBits = i;
this._securityStrength = i2;
this._seedLength = (blockCipher.getBlockSize() << 3) + i;
this._isTDEA = isTDEA(blockCipher);
if (i2 > 256) {
throw new IllegalArgumentException("Requested security strength is not supported by the derivation function");
}
if (getMaxSecurityStrength(blockCipher, i) < i2) {
throw new IllegalArgumentException("Requested security strength is not supported by block cipher and key size");
}
if (entropySource.entropySize() < i2) {
throw new IllegalArgumentException("Not enough entropy for security strength required");
}
CTR_DRBG_Instantiate_algorithm(getEntropy(), bArr2, bArr);
}
}