278 lines
9.9 KiB
Java
278 lines
9.9 KiB
Java
|
package org.bouncycastle.crypto.io;
|
||
|
|
||
|
import com.google.common.primitives.UnsignedBytes;
|
||
|
import java.io.FilterInputStream;
|
||
|
import java.io.IOException;
|
||
|
import java.io.InputStream;
|
||
|
import org.bouncycastle.crypto.BufferedBlockCipher;
|
||
|
import org.bouncycastle.crypto.InvalidCipherTextException;
|
||
|
import org.bouncycastle.crypto.SkippingCipher;
|
||
|
import org.bouncycastle.crypto.StreamCipher;
|
||
|
import org.bouncycastle.crypto.modes.AEADBlockCipher;
|
||
|
import org.bouncycastle.util.Arrays;
|
||
|
|
||
|
/* loaded from: classes6.dex */
|
||
|
public class CipherInputStream extends FilterInputStream {
|
||
|
private static final int INPUT_BUF_SIZE = 2048;
|
||
|
private AEADBlockCipher aeadBlockCipher;
|
||
|
private byte[] buf;
|
||
|
private int bufOff;
|
||
|
private BufferedBlockCipher bufferedBlockCipher;
|
||
|
private boolean finalized;
|
||
|
private byte[] inBuf;
|
||
|
private byte[] markBuf;
|
||
|
private int markBufOff;
|
||
|
private long markPosition;
|
||
|
private int maxBuf;
|
||
|
private SkippingCipher skippingCipher;
|
||
|
private StreamCipher streamCipher;
|
||
|
|
||
|
@Override // java.io.FilterInputStream, java.io.InputStream
|
||
|
public long skip(long j) throws IOException {
|
||
|
if (j <= 0) {
|
||
|
return 0L;
|
||
|
}
|
||
|
if (this.skippingCipher == null) {
|
||
|
int min = (int) Math.min(j, available());
|
||
|
this.bufOff += min;
|
||
|
return min;
|
||
|
}
|
||
|
long available = available();
|
||
|
if (j <= available) {
|
||
|
this.bufOff = (int) (this.bufOff + j);
|
||
|
return j;
|
||
|
}
|
||
|
this.bufOff = this.maxBuf;
|
||
|
long skip = ((FilterInputStream) this).in.skip(j - available);
|
||
|
if (skip == this.skippingCipher.skip(skip)) {
|
||
|
return skip + available;
|
||
|
}
|
||
|
StringBuilder sb = new StringBuilder("Unable to skip cipher ");
|
||
|
sb.append(skip);
|
||
|
sb.append(" bytes.");
|
||
|
throw new IOException(sb.toString());
|
||
|
}
|
||
|
|
||
|
@Override // java.io.FilterInputStream, java.io.InputStream
|
||
|
public void reset() throws IOException {
|
||
|
if (this.skippingCipher == null) {
|
||
|
throw new IOException("cipher must implement SkippingCipher to be used with reset()");
|
||
|
}
|
||
|
((FilterInputStream) this).in.reset();
|
||
|
this.skippingCipher.seekTo(this.markPosition);
|
||
|
byte[] bArr = this.markBuf;
|
||
|
if (bArr != null) {
|
||
|
this.buf = bArr;
|
||
|
}
|
||
|
this.bufOff = this.markBufOff;
|
||
|
}
|
||
|
|
||
|
@Override // java.io.FilterInputStream, java.io.InputStream
|
||
|
public int read(byte[] bArr, int i, int i2) throws IOException {
|
||
|
if (this.bufOff >= this.maxBuf && nextChunk() < 0) {
|
||
|
return -1;
|
||
|
}
|
||
|
int min = Math.min(i2, available());
|
||
|
System.arraycopy(this.buf, this.bufOff, bArr, i, min);
|
||
|
this.bufOff += min;
|
||
|
return min;
|
||
|
}
|
||
|
|
||
|
@Override // java.io.FilterInputStream, java.io.InputStream
|
||
|
public int read(byte[] bArr) throws IOException {
|
||
|
return read(bArr, 0, bArr.length);
|
||
|
}
|
||
|
|
||
|
@Override // java.io.FilterInputStream, java.io.InputStream
|
||
|
public int read() throws IOException {
|
||
|
if (this.bufOff >= this.maxBuf && nextChunk() < 0) {
|
||
|
return -1;
|
||
|
}
|
||
|
byte[] bArr = this.buf;
|
||
|
int i = this.bufOff;
|
||
|
this.bufOff = i + 1;
|
||
|
return bArr[i] & UnsignedBytes.MAX_VALUE;
|
||
|
}
|
||
|
|
||
|
@Override // java.io.FilterInputStream, java.io.InputStream
|
||
|
public boolean markSupported() {
|
||
|
if (this.skippingCipher != null) {
|
||
|
return ((FilterInputStream) this).in.markSupported();
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
@Override // java.io.FilterInputStream, java.io.InputStream
|
||
|
public void mark(int i) {
|
||
|
((FilterInputStream) this).in.mark(i);
|
||
|
SkippingCipher skippingCipher = this.skippingCipher;
|
||
|
if (skippingCipher != null) {
|
||
|
this.markPosition = skippingCipher.getPosition();
|
||
|
}
|
||
|
byte[] bArr = this.buf;
|
||
|
if (bArr != null) {
|
||
|
byte[] bArr2 = new byte[bArr.length];
|
||
|
this.markBuf = bArr2;
|
||
|
System.arraycopy(bArr, 0, bArr2, 0, bArr.length);
|
||
|
}
|
||
|
this.markBufOff = this.bufOff;
|
||
|
}
|
||
|
|
||
|
@Override // java.io.FilterInputStream, java.io.InputStream, java.io.Closeable, java.lang.AutoCloseable
|
||
|
public void close() throws IOException {
|
||
|
try {
|
||
|
((FilterInputStream) this).in.close();
|
||
|
this.bufOff = 0;
|
||
|
this.maxBuf = 0;
|
||
|
this.markBufOff = 0;
|
||
|
this.markPosition = 0L;
|
||
|
byte[] bArr = this.markBuf;
|
||
|
if (bArr != null) {
|
||
|
Arrays.fill(bArr, (byte) 0);
|
||
|
this.markBuf = null;
|
||
|
}
|
||
|
byte[] bArr2 = this.buf;
|
||
|
if (bArr2 != null) {
|
||
|
Arrays.fill(bArr2, (byte) 0);
|
||
|
this.buf = null;
|
||
|
}
|
||
|
Arrays.fill(this.inBuf, (byte) 0);
|
||
|
} finally {
|
||
|
if (!this.finalized) {
|
||
|
finaliseCipher();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override // java.io.FilterInputStream, java.io.InputStream
|
||
|
public int available() throws IOException {
|
||
|
return this.maxBuf - this.bufOff;
|
||
|
}
|
||
|
|
||
|
private int nextChunk() throws IOException {
|
||
|
if (this.finalized) {
|
||
|
return -1;
|
||
|
}
|
||
|
this.bufOff = 0;
|
||
|
this.maxBuf = 0;
|
||
|
while (true) {
|
||
|
int i = this.maxBuf;
|
||
|
if (i != 0) {
|
||
|
return i;
|
||
|
}
|
||
|
int read = ((FilterInputStream) this).in.read(this.inBuf);
|
||
|
if (read == -1) {
|
||
|
finaliseCipher();
|
||
|
int i2 = this.maxBuf;
|
||
|
if (i2 == 0) {
|
||
|
return -1;
|
||
|
}
|
||
|
return i2;
|
||
|
}
|
||
|
try {
|
||
|
ensureCapacity(read, false);
|
||
|
BufferedBlockCipher bufferedBlockCipher = this.bufferedBlockCipher;
|
||
|
if (bufferedBlockCipher != null) {
|
||
|
read = bufferedBlockCipher.processBytes(this.inBuf, 0, read, this.buf, 0);
|
||
|
} else {
|
||
|
AEADBlockCipher aEADBlockCipher = this.aeadBlockCipher;
|
||
|
if (aEADBlockCipher != null) {
|
||
|
read = aEADBlockCipher.processBytes(this.inBuf, 0, read, this.buf, 0);
|
||
|
} else {
|
||
|
this.streamCipher.processBytes(this.inBuf, 0, read, this.buf, 0);
|
||
|
}
|
||
|
}
|
||
|
this.maxBuf = read;
|
||
|
} catch (Exception e) {
|
||
|
throw new CipherIOException("Error processing stream ", e);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void finaliseCipher() throws IOException {
|
||
|
int doFinal;
|
||
|
try {
|
||
|
this.finalized = true;
|
||
|
ensureCapacity(0, true);
|
||
|
BufferedBlockCipher bufferedBlockCipher = this.bufferedBlockCipher;
|
||
|
if (bufferedBlockCipher != null) {
|
||
|
doFinal = bufferedBlockCipher.doFinal(this.buf, 0);
|
||
|
} else {
|
||
|
AEADBlockCipher aEADBlockCipher = this.aeadBlockCipher;
|
||
|
if (aEADBlockCipher == null) {
|
||
|
this.maxBuf = 0;
|
||
|
return;
|
||
|
}
|
||
|
doFinal = aEADBlockCipher.doFinal(this.buf, 0);
|
||
|
}
|
||
|
this.maxBuf = doFinal;
|
||
|
} catch (InvalidCipherTextException e) {
|
||
|
throw new InvalidCipherTextIOException("Error finalising cipher", e);
|
||
|
} catch (Exception e2) {
|
||
|
throw new IOException("Error finalising cipher ".concat(String.valueOf(e2)));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void ensureCapacity(int i, boolean z) {
|
||
|
if (z) {
|
||
|
BufferedBlockCipher bufferedBlockCipher = this.bufferedBlockCipher;
|
||
|
if (bufferedBlockCipher != null) {
|
||
|
i = bufferedBlockCipher.getOutputSize(i);
|
||
|
} else {
|
||
|
AEADBlockCipher aEADBlockCipher = this.aeadBlockCipher;
|
||
|
if (aEADBlockCipher != null) {
|
||
|
i = aEADBlockCipher.getOutputSize(i);
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
BufferedBlockCipher bufferedBlockCipher2 = this.bufferedBlockCipher;
|
||
|
if (bufferedBlockCipher2 != null) {
|
||
|
i = bufferedBlockCipher2.getUpdateOutputSize(i);
|
||
|
} else {
|
||
|
AEADBlockCipher aEADBlockCipher2 = this.aeadBlockCipher;
|
||
|
if (aEADBlockCipher2 != null) {
|
||
|
i = aEADBlockCipher2.getUpdateOutputSize(i);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
byte[] bArr = this.buf;
|
||
|
if (bArr == null || bArr.length < i) {
|
||
|
this.buf = new byte[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public CipherInputStream(InputStream inputStream, AEADBlockCipher aEADBlockCipher, int i) {
|
||
|
super(inputStream);
|
||
|
this.aeadBlockCipher = aEADBlockCipher;
|
||
|
this.inBuf = new byte[i];
|
||
|
this.skippingCipher = aEADBlockCipher instanceof SkippingCipher ? (SkippingCipher) aEADBlockCipher : null;
|
||
|
}
|
||
|
|
||
|
public CipherInputStream(InputStream inputStream, AEADBlockCipher aEADBlockCipher) {
|
||
|
this(inputStream, aEADBlockCipher, 2048);
|
||
|
}
|
||
|
|
||
|
public CipherInputStream(InputStream inputStream, StreamCipher streamCipher, int i) {
|
||
|
super(inputStream);
|
||
|
this.streamCipher = streamCipher;
|
||
|
this.inBuf = new byte[i];
|
||
|
this.skippingCipher = streamCipher instanceof SkippingCipher ? (SkippingCipher) streamCipher : null;
|
||
|
}
|
||
|
|
||
|
public CipherInputStream(InputStream inputStream, StreamCipher streamCipher) {
|
||
|
this(inputStream, streamCipher, 2048);
|
||
|
}
|
||
|
|
||
|
/* JADX WARN: Multi-variable type inference failed */
|
||
|
public CipherInputStream(InputStream inputStream, BufferedBlockCipher bufferedBlockCipher, int i) {
|
||
|
super(inputStream);
|
||
|
this.bufferedBlockCipher = bufferedBlockCipher;
|
||
|
this.inBuf = new byte[i];
|
||
|
this.skippingCipher = bufferedBlockCipher instanceof SkippingCipher ? (SkippingCipher) bufferedBlockCipher : null;
|
||
|
}
|
||
|
|
||
|
public CipherInputStream(InputStream inputStream, BufferedBlockCipher bufferedBlockCipher) {
|
||
|
this(inputStream, bufferedBlockCipher, 2048);
|
||
|
}
|
||
|
}
|