package org.bouncycastle.crypto.modes; import com.google.common.primitives.UnsignedBytes; 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.modes.gcm.GCMExponentiator; import org.bouncycastle.crypto.modes.gcm.GCMMultiplier; import org.bouncycastle.crypto.modes.gcm.GCMUtil; import org.bouncycastle.crypto.modes.gcm.Tables1kGCMExponentiator; import org.bouncycastle.crypto.modes.gcm.Tables8kGCMMultiplier; import org.bouncycastle.crypto.params.AEADParameters; import org.bouncycastle.crypto.params.KeyParameter; import org.bouncycastle.crypto.params.ParametersWithIV; import org.bouncycastle.util.Arrays; import org.bouncycastle.util.Pack; /* loaded from: classes6.dex */ public class GCMBlockCipher implements AEADBlockCipher { private static final int BLOCK_SIZE = 16; private byte[] H; private byte[] J0; private byte[] S; private byte[] S_at; private byte[] S_atPre; private byte[] atBlock; private int atBlockPos; private long atLength; private long atLengthPre; private int blocksRemaining; private byte[] bufBlock; private int bufOff; private BlockCipher cipher; private byte[] counter; private GCMExponentiator exp; private boolean forEncryption; private byte[] initialAssociatedText; private byte[] macBlock; private int macSize; private GCMMultiplier multiplier; private byte[] nonce; private long totalLength; @Override // org.bouncycastle.crypto.modes.AEADBlockCipher public void reset() { reset(true); } @Override // org.bouncycastle.crypto.modes.AEADBlockCipher public int processBytes(byte[] bArr, int i, int i2, byte[] bArr2, int i3) throws DataLengthException { if (bArr.length < i + i2) { throw new DataLengthException("Input buffer too short"); } int i4 = 0; for (int i5 = 0; i5 < i2; i5++) { byte[] bArr3 = this.bufBlock; int i6 = this.bufOff; bArr3[i6] = bArr[i + i5]; int i7 = i6 + 1; this.bufOff = i7; if (i7 == bArr3.length) { outputBlock(bArr2, i3 + i4); i4 += 16; } } return i4; } @Override // org.bouncycastle.crypto.modes.AEADBlockCipher public int processByte(byte b, byte[] bArr, int i) throws DataLengthException { byte[] bArr2 = this.bufBlock; int i2 = this.bufOff; bArr2[i2] = b; int i3 = i2 + 1; this.bufOff = i3; if (i3 != bArr2.length) { return 0; } outputBlock(bArr, i); return 16; } @Override // org.bouncycastle.crypto.modes.AEADBlockCipher public void processAADBytes(byte[] bArr, int i, int i2) { for (int i3 = 0; i3 < i2; i3++) { byte[] bArr2 = this.atBlock; int i4 = this.atBlockPos; bArr2[i4] = bArr[i + i3]; int i5 = i4 + 1; this.atBlockPos = i5; if (i5 == 16) { gHASHBlock(this.S_at, bArr2); this.atBlockPos = 0; this.atLength += 16; } } } @Override // org.bouncycastle.crypto.modes.AEADBlockCipher public void processAADByte(byte b) { byte[] bArr = this.atBlock; int i = this.atBlockPos; bArr[i] = b; int i2 = i + 1; this.atBlockPos = i2; if (i2 == 16) { gHASHBlock(this.S_at, bArr); this.atBlockPos = 0; this.atLength += 16; } } @Override // org.bouncycastle.crypto.modes.AEADBlockCipher public void init(boolean z, CipherParameters cipherParameters) throws IllegalArgumentException { KeyParameter keyParameter; this.forEncryption = z; this.macBlock = null; if (cipherParameters instanceof AEADParameters) { AEADParameters aEADParameters = (AEADParameters) cipherParameters; this.nonce = aEADParameters.getNonce(); this.initialAssociatedText = aEADParameters.getAssociatedText(); int macSize = aEADParameters.getMacSize(); if (macSize < 32 || macSize > 128 || macSize % 8 != 0) { throw new IllegalArgumentException("Invalid value for MAC size: ".concat(String.valueOf(macSize))); } this.macSize = macSize / 8; keyParameter = aEADParameters.getKey(); } else { if (!(cipherParameters instanceof ParametersWithIV)) { throw new IllegalArgumentException("invalid parameters passed to GCM"); } ParametersWithIV parametersWithIV = (ParametersWithIV) cipherParameters; this.nonce = parametersWithIV.getIV(); this.initialAssociatedText = null; this.macSize = 16; keyParameter = (KeyParameter) parametersWithIV.getParameters(); } this.bufBlock = new byte[z ? 16 : this.macSize + 16]; byte[] bArr = this.nonce; if (bArr == null || bArr.length <= 0) { throw new IllegalArgumentException("IV must be at least 1 byte"); } if (keyParameter != null) { this.cipher.init(true, keyParameter); byte[] bArr2 = new byte[16]; this.H = bArr2; this.cipher.processBlock(bArr2, 0, bArr2, 0); this.multiplier.init(this.H); this.exp = null; } else if (this.H == null) { throw new IllegalArgumentException("Key must be specified in initial init"); } byte[] bArr3 = new byte[16]; this.J0 = bArr3; byte[] bArr4 = this.nonce; if (bArr4.length == 12) { System.arraycopy(bArr4, 0, bArr3, 0, bArr4.length); this.J0[15] = 1; } else { gHASH(bArr3, bArr4, bArr4.length); byte[] bArr5 = new byte[16]; Pack.longToBigEndian(this.nonce.length << 3, bArr5, 8); gHASHBlock(this.J0, bArr5); } this.S = new byte[16]; this.S_at = new byte[16]; this.S_atPre = new byte[16]; this.atBlock = new byte[16]; this.atBlockPos = 0; this.atLength = 0L; this.atLengthPre = 0L; this.counter = Arrays.clone(this.J0); this.blocksRemaining = -2; this.bufOff = 0; this.totalLength = 0L; byte[] bArr6 = this.initialAssociatedText; if (bArr6 != null) { processAADBytes(bArr6, 0, bArr6.length); } } @Override // org.bouncycastle.crypto.modes.AEADBlockCipher public int getUpdateOutputSize(int i) { int i2 = i + this.bufOff; if (!this.forEncryption) { int i3 = this.macSize; if (i2 < i3) { return 0; } i2 -= i3; } return i2 - (i2 % 16); } @Override // org.bouncycastle.crypto.modes.AEADBlockCipher public BlockCipher getUnderlyingCipher() { return this.cipher; } @Override // org.bouncycastle.crypto.modes.AEADBlockCipher public int getOutputSize(int i) { int i2 = i + this.bufOff; if (this.forEncryption) { return i2 + this.macSize; } int i3 = this.macSize; if (i2 < i3) { return 0; } return i2 - i3; } @Override // org.bouncycastle.crypto.modes.AEADBlockCipher public byte[] getMac() { return Arrays.clone(this.macBlock); } @Override // org.bouncycastle.crypto.modes.AEADBlockCipher public String getAlgorithmName() { StringBuilder sb = new StringBuilder(); sb.append(this.cipher.getAlgorithmName()); sb.append("/GCM"); return sb.toString(); } @Override // org.bouncycastle.crypto.modes.AEADBlockCipher public int doFinal(byte[] bArr, int i) throws IllegalStateException, InvalidCipherTextException { if (this.totalLength == 0) { initCipher(); } int i2 = this.bufOff; if (!this.forEncryption) { int i3 = this.macSize; if (i2 < i3) { throw new InvalidCipherTextException("data too short"); } i2 -= i3; if (bArr.length < i + i2) { throw new OutputLengthException("Output buffer too short"); } } else if (bArr.length < i + i2 + this.macSize) { throw new OutputLengthException("Output buffer too short"); } if (i2 > 0) { gCTRPartial(this.bufBlock, 0, i2, bArr, i); } long j = this.atLength; int i4 = this.atBlockPos; long j2 = j + i4; this.atLength = j2; if (j2 > this.atLengthPre) { if (i4 > 0) { gHASHPartial(this.S_at, this.atBlock, 0, i4); } if (this.atLengthPre > 0) { GCMUtil.xor(this.S_at, this.S_atPre); } long j3 = this.totalLength; byte[] bArr2 = new byte[16]; if (this.exp == null) { Tables1kGCMExponentiator tables1kGCMExponentiator = new Tables1kGCMExponentiator(); this.exp = tables1kGCMExponentiator; tables1kGCMExponentiator.init(this.H); } this.exp.exponentiateX(((j3 << 3) + 127) >>> 7, bArr2); GCMUtil.multiply(this.S_at, bArr2); GCMUtil.xor(this.S, this.S_at); } byte[] bArr3 = new byte[16]; Pack.longToBigEndian(this.atLength << 3, bArr3, 0); Pack.longToBigEndian(this.totalLength << 3, bArr3, 8); gHASHBlock(this.S, bArr3); byte[] bArr4 = new byte[16]; this.cipher.processBlock(this.J0, 0, bArr4, 0); GCMUtil.xor(bArr4, this.S); int i5 = this.macSize; byte[] bArr5 = new byte[i5]; this.macBlock = bArr5; System.arraycopy(bArr4, 0, bArr5, 0, i5); if (this.forEncryption) { System.arraycopy(this.macBlock, 0, bArr, i + this.bufOff, this.macSize); i2 += this.macSize; } else { int i6 = this.macSize; byte[] bArr6 = new byte[i6]; System.arraycopy(this.bufBlock, i2, bArr6, 0, i6); if (!Arrays.constantTimeAreEqual(this.macBlock, bArr6)) { throw new InvalidCipherTextException("mac check in GCM failed"); } } reset(false); return i2; } private void reset(boolean z) { this.cipher.reset(); this.S = new byte[16]; this.S_at = new byte[16]; this.S_atPre = new byte[16]; this.atBlock = new byte[16]; this.atBlockPos = 0; this.atLength = 0L; this.atLengthPre = 0L; this.counter = Arrays.clone(this.J0); this.blocksRemaining = -2; this.bufOff = 0; this.totalLength = 0L; byte[] bArr = this.bufBlock; if (bArr != null) { Arrays.fill(bArr, (byte) 0); } if (z) { this.macBlock = null; } byte[] bArr2 = this.initialAssociatedText; if (bArr2 != null) { processAADBytes(bArr2, 0, bArr2.length); } } private void outputBlock(byte[] bArr, int i) { if (bArr.length < i + 16) { throw new OutputLengthException("Output buffer too short"); } if (this.totalLength == 0) { initCipher(); } gCTRBlock(this.bufBlock, bArr, i); if (this.forEncryption) { this.bufOff = 0; return; } byte[] bArr2 = this.bufBlock; System.arraycopy(bArr2, 16, bArr2, 0, this.macSize); this.bufOff = this.macSize; } private void initCipher() { if (this.atLength > 0) { System.arraycopy(this.S_at, 0, this.S_atPre, 0, 16); this.atLengthPre = this.atLength; } int i = this.atBlockPos; if (i > 0) { gHASHPartial(this.S_atPre, this.atBlock, 0, i); this.atLengthPre += this.atBlockPos; } if (this.atLengthPre > 0) { System.arraycopy(this.S_atPre, 0, this.S, 0, 16); } } private byte[] getNextCounterBlock() { int i = this.blocksRemaining; if (i == 0) { throw new IllegalStateException("Attempt to process too many blocks"); } this.blocksRemaining = i - 1; byte[] bArr = this.counter; int i2 = (bArr[15] & UnsignedBytes.MAX_VALUE) + 1; bArr[15] = (byte) i2; int i3 = (i2 >>> 8) + (bArr[14] & UnsignedBytes.MAX_VALUE); bArr[14] = (byte) i3; int i4 = (i3 >>> 8) + (bArr[13] & UnsignedBytes.MAX_VALUE); bArr[13] = (byte) i4; bArr[12] = (byte) ((i4 >>> 8) + (bArr[12] & UnsignedBytes.MAX_VALUE)); byte[] bArr2 = new byte[16]; this.cipher.processBlock(bArr, 0, bArr2, 0); return bArr2; } private void gHASHPartial(byte[] bArr, byte[] bArr2, int i, int i2) { GCMUtil.xor(bArr, bArr2, i, i2); this.multiplier.multiplyH(bArr); } private void gHASHBlock(byte[] bArr, byte[] bArr2) { GCMUtil.xor(bArr, bArr2); this.multiplier.multiplyH(bArr); } private void gHASH(byte[] bArr, byte[] bArr2, int i) { for (int i2 = 0; i2 < i; i2 += 16) { gHASHPartial(bArr, bArr2, i2, Math.min(i - i2, 16)); } } private void gCTRPartial(byte[] bArr, int i, int i2, byte[] bArr2, int i3) { byte[] nextCounterBlock = getNextCounterBlock(); GCMUtil.xor(nextCounterBlock, bArr, i, i2); System.arraycopy(nextCounterBlock, 0, bArr2, i3, i2); byte[] bArr3 = this.S; if (this.forEncryption) { bArr = nextCounterBlock; } gHASHPartial(bArr3, bArr, 0, i2); this.totalLength += i2; } private void gCTRBlock(byte[] bArr, byte[] bArr2, int i) { byte[] nextCounterBlock = getNextCounterBlock(); GCMUtil.xor(nextCounterBlock, bArr); System.arraycopy(nextCounterBlock, 0, bArr2, i, 16); byte[] bArr3 = this.S; if (this.forEncryption) { bArr = nextCounterBlock; } gHASHBlock(bArr3, bArr); this.totalLength += 16; } public GCMBlockCipher(BlockCipher blockCipher, GCMMultiplier gCMMultiplier) { if (blockCipher.getBlockSize() != 16) { throw new IllegalArgumentException("cipher required with a block size of 16."); } gCMMultiplier = gCMMultiplier == null ? new Tables8kGCMMultiplier() : gCMMultiplier; this.cipher = blockCipher; this.multiplier = gCMMultiplier; } public GCMBlockCipher(BlockCipher blockCipher) { this(blockCipher, null); } }