282 lines
12 KiB
Java
282 lines
12 KiB
Java
|
package org.bouncycastle.crypto.engines;
|
||
|
|
||
|
import java.io.ByteArrayInputStream;
|
||
|
import java.io.IOException;
|
||
|
import org.bouncycastle.crypto.BasicAgreement;
|
||
|
import org.bouncycastle.crypto.BufferedBlockCipher;
|
||
|
import org.bouncycastle.crypto.CipherParameters;
|
||
|
import org.bouncycastle.crypto.DerivationFunction;
|
||
|
import org.bouncycastle.crypto.EphemeralKeyPair;
|
||
|
import org.bouncycastle.crypto.InvalidCipherTextException;
|
||
|
import org.bouncycastle.crypto.KeyParser;
|
||
|
import org.bouncycastle.crypto.Mac;
|
||
|
import org.bouncycastle.crypto.generators.EphemeralKeyPairGenerator;
|
||
|
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
|
||
|
import org.bouncycastle.crypto.params.IESParameters;
|
||
|
import org.bouncycastle.crypto.params.IESWithCipherParameters;
|
||
|
import org.bouncycastle.crypto.params.KDFParameters;
|
||
|
import org.bouncycastle.crypto.params.KeyParameter;
|
||
|
import org.bouncycastle.crypto.params.ParametersWithIV;
|
||
|
import org.bouncycastle.util.Arrays;
|
||
|
import org.bouncycastle.util.BigIntegers;
|
||
|
import org.bouncycastle.util.Pack;
|
||
|
|
||
|
/* loaded from: classes6.dex */
|
||
|
public class IESEngine {
|
||
|
private byte[] IV;
|
||
|
byte[] V;
|
||
|
BasicAgreement agree;
|
||
|
BufferedBlockCipher cipher;
|
||
|
boolean forEncryption;
|
||
|
DerivationFunction kdf;
|
||
|
private EphemeralKeyPairGenerator keyPairGenerator;
|
||
|
private KeyParser keyParser;
|
||
|
Mac mac;
|
||
|
byte[] macBuf;
|
||
|
IESParameters param;
|
||
|
CipherParameters privParam;
|
||
|
CipherParameters pubParam;
|
||
|
|
||
|
public byte[] processBlock(byte[] bArr, int i, int i2) throws InvalidCipherTextException {
|
||
|
if (this.forEncryption) {
|
||
|
EphemeralKeyPairGenerator ephemeralKeyPairGenerator = this.keyPairGenerator;
|
||
|
if (ephemeralKeyPairGenerator != null) {
|
||
|
EphemeralKeyPair generate = ephemeralKeyPairGenerator.generate();
|
||
|
this.privParam = generate.getKeyPair().getPrivate();
|
||
|
this.V = generate.getEncodedPublicKey();
|
||
|
}
|
||
|
} else if (this.keyParser != null) {
|
||
|
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bArr, i, i2);
|
||
|
try {
|
||
|
this.pubParam = this.keyParser.readKey(byteArrayInputStream);
|
||
|
this.V = Arrays.copyOfRange(bArr, i, (i2 - byteArrayInputStream.available()) + i);
|
||
|
} catch (IOException e) {
|
||
|
StringBuilder sb = new StringBuilder("unable to recover ephemeral public key: ");
|
||
|
sb.append(e.getMessage());
|
||
|
throw new InvalidCipherTextException(sb.toString(), e);
|
||
|
}
|
||
|
}
|
||
|
this.agree.init(this.privParam);
|
||
|
byte[] asUnsignedByteArray = BigIntegers.asUnsignedByteArray(this.agree.getFieldSize(), this.agree.calculateAgreement(this.pubParam));
|
||
|
byte[] bArr2 = this.V;
|
||
|
if (bArr2.length != 0) {
|
||
|
byte[] concatenate = Arrays.concatenate(bArr2, asUnsignedByteArray);
|
||
|
Arrays.fill(asUnsignedByteArray, (byte) 0);
|
||
|
asUnsignedByteArray = concatenate;
|
||
|
}
|
||
|
try {
|
||
|
this.kdf.init(new KDFParameters(asUnsignedByteArray, this.param.getDerivationV()));
|
||
|
return this.forEncryption ? encryptBlock(bArr, i, i2) : decryptBlock(bArr, i, i2);
|
||
|
} finally {
|
||
|
Arrays.fill(asUnsignedByteArray, (byte) 0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void init(boolean z, CipherParameters cipherParameters, CipherParameters cipherParameters2, CipherParameters cipherParameters3) {
|
||
|
this.forEncryption = z;
|
||
|
this.privParam = cipherParameters;
|
||
|
this.pubParam = cipherParameters2;
|
||
|
this.V = new byte[0];
|
||
|
extractParams(cipherParameters3);
|
||
|
}
|
||
|
|
||
|
public void init(AsymmetricKeyParameter asymmetricKeyParameter, CipherParameters cipherParameters, EphemeralKeyPairGenerator ephemeralKeyPairGenerator) {
|
||
|
this.forEncryption = true;
|
||
|
this.pubParam = asymmetricKeyParameter;
|
||
|
this.keyPairGenerator = ephemeralKeyPairGenerator;
|
||
|
extractParams(cipherParameters);
|
||
|
}
|
||
|
|
||
|
public void init(AsymmetricKeyParameter asymmetricKeyParameter, CipherParameters cipherParameters, KeyParser keyParser) {
|
||
|
this.forEncryption = false;
|
||
|
this.privParam = asymmetricKeyParameter;
|
||
|
this.keyParser = keyParser;
|
||
|
extractParams(cipherParameters);
|
||
|
}
|
||
|
|
||
|
public Mac getMac() {
|
||
|
return this.mac;
|
||
|
}
|
||
|
|
||
|
protected byte[] getLengthTag(byte[] bArr) {
|
||
|
byte[] bArr2 = new byte[8];
|
||
|
if (bArr != null) {
|
||
|
Pack.longToBigEndian(bArr.length << 3, bArr2, 0);
|
||
|
}
|
||
|
return bArr2;
|
||
|
}
|
||
|
|
||
|
public BufferedBlockCipher getCipher() {
|
||
|
return this.cipher;
|
||
|
}
|
||
|
|
||
|
private void extractParams(CipherParameters cipherParameters) {
|
||
|
if (cipherParameters instanceof ParametersWithIV) {
|
||
|
ParametersWithIV parametersWithIV = (ParametersWithIV) cipherParameters;
|
||
|
this.IV = parametersWithIV.getIV();
|
||
|
cipherParameters = parametersWithIV.getParameters();
|
||
|
} else {
|
||
|
this.IV = null;
|
||
|
}
|
||
|
this.param = (IESParameters) cipherParameters;
|
||
|
}
|
||
|
|
||
|
private byte[] encryptBlock(byte[] bArr, int i, int i2) throws InvalidCipherTextException {
|
||
|
BufferedBlockCipher bufferedBlockCipher;
|
||
|
CipherParameters keyParameter;
|
||
|
byte[] bArr2;
|
||
|
byte[] bArr3;
|
||
|
if (this.cipher == null) {
|
||
|
byte[] bArr4 = new byte[i2];
|
||
|
int macKeySize = this.param.getMacKeySize() / 8;
|
||
|
bArr3 = new byte[macKeySize];
|
||
|
int i3 = i2 + macKeySize;
|
||
|
byte[] bArr5 = new byte[i3];
|
||
|
this.kdf.generateBytes(bArr5, 0, i3);
|
||
|
if (this.V.length != 0) {
|
||
|
System.arraycopy(bArr5, 0, bArr3, 0, macKeySize);
|
||
|
System.arraycopy(bArr5, macKeySize, bArr4, 0, i2);
|
||
|
} else {
|
||
|
System.arraycopy(bArr5, 0, bArr4, 0, i2);
|
||
|
System.arraycopy(bArr5, i2, bArr3, 0, macKeySize);
|
||
|
}
|
||
|
bArr2 = new byte[i2];
|
||
|
for (int i4 = 0; i4 != i2; i4++) {
|
||
|
bArr2[i4] = (byte) (bArr[i + i4] ^ bArr4[i4]);
|
||
|
}
|
||
|
} else {
|
||
|
int cipherKeySize = ((IESWithCipherParameters) this.param).getCipherKeySize() / 8;
|
||
|
byte[] bArr6 = new byte[cipherKeySize];
|
||
|
int macKeySize2 = this.param.getMacKeySize() / 8;
|
||
|
byte[] bArr7 = new byte[macKeySize2];
|
||
|
int i5 = cipherKeySize + macKeySize2;
|
||
|
byte[] bArr8 = new byte[i5];
|
||
|
this.kdf.generateBytes(bArr8, 0, i5);
|
||
|
System.arraycopy(bArr8, 0, bArr6, 0, cipherKeySize);
|
||
|
System.arraycopy(bArr8, cipherKeySize, bArr7, 0, macKeySize2);
|
||
|
if (this.IV != null) {
|
||
|
bufferedBlockCipher = this.cipher;
|
||
|
keyParameter = new ParametersWithIV(new KeyParameter(bArr6), this.IV);
|
||
|
} else {
|
||
|
bufferedBlockCipher = this.cipher;
|
||
|
keyParameter = new KeyParameter(bArr6);
|
||
|
}
|
||
|
bufferedBlockCipher.init(true, keyParameter);
|
||
|
bArr2 = new byte[this.cipher.getOutputSize(i2)];
|
||
|
int processBytes = this.cipher.processBytes(bArr, i, i2, bArr2, 0);
|
||
|
i2 = processBytes + this.cipher.doFinal(bArr2, processBytes);
|
||
|
bArr3 = bArr7;
|
||
|
}
|
||
|
byte[] encodingV = this.param.getEncodingV();
|
||
|
byte[] lengthTag = this.V.length != 0 ? getLengthTag(encodingV) : null;
|
||
|
int macSize = this.mac.getMacSize();
|
||
|
byte[] bArr9 = new byte[macSize];
|
||
|
this.mac.init(new KeyParameter(bArr3));
|
||
|
this.mac.update(bArr2, 0, bArr2.length);
|
||
|
if (encodingV != null) {
|
||
|
this.mac.update(encodingV, 0, encodingV.length);
|
||
|
}
|
||
|
if (this.V.length != 0) {
|
||
|
this.mac.update(lengthTag, 0, lengthTag.length);
|
||
|
}
|
||
|
this.mac.doFinal(bArr9, 0);
|
||
|
byte[] bArr10 = this.V;
|
||
|
byte[] bArr11 = new byte[bArr10.length + i2 + macSize];
|
||
|
System.arraycopy(bArr10, 0, bArr11, 0, bArr10.length);
|
||
|
System.arraycopy(bArr2, 0, bArr11, this.V.length, i2);
|
||
|
System.arraycopy(bArr9, 0, bArr11, this.V.length + i2, macSize);
|
||
|
return bArr11;
|
||
|
}
|
||
|
|
||
|
private byte[] decryptBlock(byte[] bArr, int i, int i2) throws InvalidCipherTextException {
|
||
|
byte[] bArr2;
|
||
|
BufferedBlockCipher bufferedBlockCipher;
|
||
|
CipherParameters keyParameter;
|
||
|
byte[] bArr3;
|
||
|
int doFinal;
|
||
|
if (i2 < this.V.length + this.mac.getMacSize()) {
|
||
|
throw new InvalidCipherTextException("Length of input must be greater than the MAC and V combined");
|
||
|
}
|
||
|
if (this.cipher == null) {
|
||
|
doFinal = (i2 - this.V.length) - this.mac.getMacSize();
|
||
|
byte[] bArr4 = new byte[doFinal];
|
||
|
int macKeySize = this.param.getMacKeySize() / 8;
|
||
|
bArr2 = new byte[macKeySize];
|
||
|
int i3 = doFinal + macKeySize;
|
||
|
byte[] bArr5 = new byte[i3];
|
||
|
this.kdf.generateBytes(bArr5, 0, i3);
|
||
|
if (this.V.length != 0) {
|
||
|
System.arraycopy(bArr5, 0, bArr2, 0, macKeySize);
|
||
|
System.arraycopy(bArr5, macKeySize, bArr4, 0, doFinal);
|
||
|
} else {
|
||
|
System.arraycopy(bArr5, 0, bArr4, 0, doFinal);
|
||
|
System.arraycopy(bArr5, doFinal, bArr2, 0, macKeySize);
|
||
|
}
|
||
|
bArr3 = new byte[doFinal];
|
||
|
for (int i4 = 0; i4 != doFinal; i4++) {
|
||
|
bArr3[i4] = (byte) (bArr[(this.V.length + i) + i4] ^ bArr4[i4]);
|
||
|
}
|
||
|
} else {
|
||
|
int cipherKeySize = ((IESWithCipherParameters) this.param).getCipherKeySize() / 8;
|
||
|
byte[] bArr6 = new byte[cipherKeySize];
|
||
|
int macKeySize2 = this.param.getMacKeySize() / 8;
|
||
|
bArr2 = new byte[macKeySize2];
|
||
|
int i5 = cipherKeySize + macKeySize2;
|
||
|
byte[] bArr7 = new byte[i5];
|
||
|
this.kdf.generateBytes(bArr7, 0, i5);
|
||
|
System.arraycopy(bArr7, 0, bArr6, 0, cipherKeySize);
|
||
|
System.arraycopy(bArr7, cipherKeySize, bArr2, 0, macKeySize2);
|
||
|
if (this.IV != null) {
|
||
|
bufferedBlockCipher = this.cipher;
|
||
|
keyParameter = new ParametersWithIV(new KeyParameter(bArr6), this.IV);
|
||
|
} else {
|
||
|
bufferedBlockCipher = this.cipher;
|
||
|
keyParameter = new KeyParameter(bArr6);
|
||
|
}
|
||
|
bufferedBlockCipher.init(false, keyParameter);
|
||
|
bArr3 = new byte[this.cipher.getOutputSize((i2 - this.V.length) - this.mac.getMacSize())];
|
||
|
BufferedBlockCipher bufferedBlockCipher2 = this.cipher;
|
||
|
byte[] bArr8 = this.V;
|
||
|
int processBytes = bufferedBlockCipher2.processBytes(bArr, i + bArr8.length, (i2 - bArr8.length) - this.mac.getMacSize(), bArr3, 0);
|
||
|
doFinal = processBytes + this.cipher.doFinal(bArr3, processBytes);
|
||
|
}
|
||
|
byte[] encodingV = this.param.getEncodingV();
|
||
|
byte[] lengthTag = this.V.length != 0 ? getLengthTag(encodingV) : null;
|
||
|
int i6 = i + i2;
|
||
|
byte[] copyOfRange = Arrays.copyOfRange(bArr, i6 - this.mac.getMacSize(), i6);
|
||
|
int length = copyOfRange.length;
|
||
|
byte[] bArr9 = new byte[length];
|
||
|
this.mac.init(new KeyParameter(bArr2));
|
||
|
Mac mac = this.mac;
|
||
|
byte[] bArr10 = this.V;
|
||
|
mac.update(bArr, i + bArr10.length, (i2 - bArr10.length) - length);
|
||
|
if (encodingV != null) {
|
||
|
this.mac.update(encodingV, 0, encodingV.length);
|
||
|
}
|
||
|
if (this.V.length != 0) {
|
||
|
this.mac.update(lengthTag, 0, lengthTag.length);
|
||
|
}
|
||
|
this.mac.doFinal(bArr9, 0);
|
||
|
if (Arrays.constantTimeAreEqual(copyOfRange, bArr9)) {
|
||
|
return Arrays.copyOfRange(bArr3, 0, doFinal);
|
||
|
}
|
||
|
throw new InvalidCipherTextException("Invalid MAC.");
|
||
|
}
|
||
|
|
||
|
public IESEngine(BasicAgreement basicAgreement, DerivationFunction derivationFunction, Mac mac, BufferedBlockCipher bufferedBlockCipher) {
|
||
|
this.agree = basicAgreement;
|
||
|
this.kdf = derivationFunction;
|
||
|
this.mac = mac;
|
||
|
this.macBuf = new byte[mac.getMacSize()];
|
||
|
this.cipher = bufferedBlockCipher;
|
||
|
}
|
||
|
|
||
|
public IESEngine(BasicAgreement basicAgreement, DerivationFunction derivationFunction, Mac mac) {
|
||
|
this.agree = basicAgreement;
|
||
|
this.kdf = derivationFunction;
|
||
|
this.mac = mac;
|
||
|
this.macBuf = new byte[mac.getMacSize()];
|
||
|
this.cipher = null;
|
||
|
}
|
||
|
}
|