what-the-bank/sources/org/jmrtd/protocol/DESedeSecureMessagingWrappe...

270 lines
11 KiB
Java
Raw Normal View History

2024-07-27 18:17:47 +07:00
package org.jmrtd.protocol;
import com.google.common.primitives.UnsignedBytes;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.Cipher;
import javax.crypto.Mac;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import net.sf.scuba.smartcards.CommandAPDU;
import net.sf.scuba.smartcards.ResponseAPDU;
import o.C15109ghW;
import org.jmrtd.Util;
/* loaded from: classes6.dex */
public class DESedeSecureMessagingWrapper extends SecureMessagingWrapper implements Serializable {
private static final Logger LOGGER = Logger.getLogger("org.jmrtd");
public static final IvParameterSpec ZERO_IV_PARAM_SPEC = new IvParameterSpec(new byte[]{0, 0, 0, 0, 0, 0, 0, 0});
private static final long serialVersionUID = -2859033943345961793L;
private transient Cipher cipher;
private SecretKey ksEnc;
private SecretKey ksMac;
private transient Mac mac;
private boolean shouldCheckMAC;
private long ssc;
public DESedeSecureMessagingWrapper(SecretKey secretKey, SecretKey secretKey2) throws GeneralSecurityException {
this(secretKey, secretKey2, true);
}
public DESedeSecureMessagingWrapper(SecretKey secretKey, SecretKey secretKey2, boolean z) throws GeneralSecurityException {
this(secretKey, secretKey2, z, 0L);
}
public DESedeSecureMessagingWrapper(SecretKey secretKey, SecretKey secretKey2, long j) throws NoSuchAlgorithmException, NoSuchPaddingException {
this(secretKey, secretKey2, "DESede/CBC/NoPadding", "ISO9797Alg3Mac", true, j);
}
public DESedeSecureMessagingWrapper(SecretKey secretKey, SecretKey secretKey2, boolean z, long j) throws NoSuchAlgorithmException, NoSuchPaddingException {
this(secretKey, secretKey2, "DESede/CBC/NoPadding", "ISO9797Alg3Mac", z, j);
}
private DESedeSecureMessagingWrapper(SecretKey secretKey, SecretKey secretKey2, String str, String str2, boolean z, long j) throws NoSuchAlgorithmException, NoSuchPaddingException {
this.ksEnc = secretKey;
this.ksMac = secretKey2;
this.shouldCheckMAC = z;
this.ssc = j;
this.cipher = Cipher.getInstance(str);
this.mac = Mac.getInstance(str2);
}
@Override // net.sf.scuba.smartcards.APDUWrapper
public CommandAPDU wrap(CommandAPDU commandAPDU) {
long j = this.ssc + 1;
this.ssc = j;
try {
return wrapCommandAPDU(commandAPDU, j);
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Exception", (Throwable) e);
throw new IllegalStateException(e.getMessage());
} catch (GeneralSecurityException e2) {
LOGGER.log(Level.SEVERE, "Exception", (Throwable) e2);
throw new IllegalStateException(e2.getMessage());
}
}
@Override // net.sf.scuba.smartcards.APDUWrapper
public ResponseAPDU unwrap(ResponseAPDU responseAPDU) {
this.ssc++;
try {
byte[] data = responseAPDU.getData();
if (data == null || data.length <= 0) {
StringBuilder sb = new StringBuilder("Card indicates SM error, SW = ");
sb.append(Integer.toHexString(responseAPDU.getSW() & 65535));
throw new IllegalStateException(sb.toString());
}
return unwrapResponseAPDU(responseAPDU, this.ssc);
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Exception", (Throwable) e);
throw new IllegalStateException(e.getMessage());
} catch (GeneralSecurityException e2) {
LOGGER.log(Level.SEVERE, "Exception", (Throwable) e2);
throw new IllegalStateException(e2.getMessage());
}
}
public String toString() {
StringBuilder sb = new StringBuilder("DESedeSecureMessagingWrapper [ ");
sb.append(this.ksEnc.toString());
sb.append(", ");
sb.append(this.ksMac.toString());
sb.append(", ");
sb.append(this.ssc);
sb.append("]");
return sb.toString();
}
private CommandAPDU wrapCommandAPDU(CommandAPDU commandAPDU, long j) throws GeneralSecurityException, IOException {
int nc = commandAPDU.getNc();
int ne = commandAPDU.getNe();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] bArr = {(byte) (commandAPDU.getCLA() | 12), (byte) commandAPDU.getINS(), (byte) commandAPDU.getP1(), (byte) commandAPDU.getP2()};
byte[] pad = Util.pad(bArr, 8);
int i = ((byte) commandAPDU.getINS()) == -79 ? 1 : 0;
byte[] bArr2 = new byte[0];
byte[] bArr3 = new byte[0];
if (ne > 0) {
byteArrayOutputStream.reset();
byteArrayOutputStream.write(-105);
byteArrayOutputStream.write(1);
byteArrayOutputStream.write((byte) ne);
bArr3 = byteArrayOutputStream.toByteArray();
}
this.cipher.init(1, this.ksEnc, ZERO_IV_PARAM_SPEC);
if (nc > 0) {
byte[] doFinal = this.cipher.doFinal(Util.pad(commandAPDU.getData(), 8));
byteArrayOutputStream.reset();
byteArrayOutputStream.write(i != 0 ? -123 : -121);
byteArrayOutputStream.write(C15109ghW.a(doFinal.length + (i ^ 1)));
if (i == 0) {
byteArrayOutputStream.write(1);
}
byteArrayOutputStream.write(doFinal, 0, doFinal.length);
bArr2 = byteArrayOutputStream.toByteArray();
}
byteArrayOutputStream.reset();
DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream);
dataOutputStream.writeLong(j);
dataOutputStream.write(pad);
dataOutputStream.write(bArr2);
dataOutputStream.write(bArr3);
dataOutputStream.flush();
byte[] pad2 = Util.pad(byteArrayOutputStream.toByteArray(), 8);
this.mac.init(this.ksMac);
byte[] doFinal2 = this.mac.doFinal(pad2);
int length = doFinal2.length;
int i2 = length == 8 ? length : 8;
byteArrayOutputStream.reset();
byteArrayOutputStream.write(-114);
byteArrayOutputStream.write(i2);
byteArrayOutputStream.write(doFinal2, 0, i2);
byte[] byteArray = byteArrayOutputStream.toByteArray();
byteArrayOutputStream.reset();
byteArrayOutputStream.write(bArr2);
byteArrayOutputStream.write(bArr3);
byteArrayOutputStream.write(byteArray);
return new CommandAPDU(bArr[0], bArr[1], bArr[2], bArr[3], byteArrayOutputStream.toByteArray(), 256);
}
private ResponseAPDU unwrapResponseAPDU(ResponseAPDU responseAPDU, long j) throws GeneralSecurityException, IOException {
byte[] bytes = responseAPDU.getBytes();
if (bytes == null || bytes.length < 2) {
throw new IllegalArgumentException("Invalid response APDU");
}
this.cipher.init(2, this.ksEnc, ZERO_IV_PARAM_SPEC);
DataInputStream dataInputStream = new DataInputStream(new ByteArrayInputStream(bytes));
byte[] bArr = new byte[0];
byte[] bArr2 = null;
boolean z = false;
short s = 0;
while (!z) {
byte readByte = dataInputStream.readByte();
if (readByte == -123) {
bArr = readDO87(dataInputStream, true);
} else if (readByte == -121) {
bArr = readDO87(dataInputStream, false);
} else if (readByte == -114) {
bArr2 = readDO8E(dataInputStream);
z = true;
} else if (readByte == -103) {
s = readDO99(dataInputStream);
}
}
if (this.shouldCheckMAC && !checkMac(bytes, bArr2, j)) {
throw new IllegalStateException("Invalid MAC");
}
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byteArrayOutputStream.write(bArr, 0, bArr.length);
byteArrayOutputStream.write((65280 & s) >> 8);
byteArrayOutputStream.write(s & 255);
return new ResponseAPDU(byteArrayOutputStream.toByteArray());
}
private byte[] readDO87(DataInputStream dataInputStream, boolean z) throws IOException, GeneralSecurityException {
int readUnsignedByte = dataInputStream.readUnsignedByte();
if ((readUnsignedByte & 128) == 128) {
int i = 0;
for (int i2 = 0; i2 < (readUnsignedByte & 127); i2++) {
i = (i << 8) | dataInputStream.readUnsignedByte();
}
readUnsignedByte = i;
}
if (!z) {
int readUnsignedByte2 = dataInputStream.readUnsignedByte();
if (readUnsignedByte2 != 1) {
StringBuilder sb = new StringBuilder("DO'87 expected 0x01 marker, found ");
sb.append(Integer.toHexString(readUnsignedByte2 & 255));
throw new IllegalStateException(sb.toString());
}
readUnsignedByte--;
}
byte[] bArr = new byte[readUnsignedByte];
dataInputStream.readFully(bArr);
return Util.unpad(this.cipher.doFinal(bArr));
}
private short readDO99(DataInputStream dataInputStream) throws IOException {
if (dataInputStream.readUnsignedByte() != 2) {
throw new IllegalStateException("DO'99 wrong length");
}
return (short) ((dataInputStream.readByte() & UnsignedBytes.MAX_VALUE) | ((dataInputStream.readByte() & UnsignedBytes.MAX_VALUE) << 8));
}
private byte[] readDO8E(DataInputStream dataInputStream) throws IOException, GeneralSecurityException {
if (dataInputStream.readUnsignedByte() != 8) {
throw new IllegalStateException("DO'8E wrong length");
}
byte[] bArr = new byte[8];
dataInputStream.readFully(bArr);
return bArr;
}
private boolean checkMac(byte[] bArr, byte[] bArr2, long j) throws GeneralSecurityException {
try {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream);
dataOutputStream.writeLong(j);
byte[] pad = Util.pad(bArr, 0, bArr.length - 12, 8);
dataOutputStream.write(pad, 0, pad.length);
dataOutputStream.flush();
dataOutputStream.close();
this.mac.init(this.ksMac);
byte[] doFinal = this.mac.doFinal(byteArrayOutputStream.toByteArray());
if (doFinal.length > 8 && bArr2.length == 8) {
byte[] bArr3 = new byte[8];
System.arraycopy(doFinal, 0, bArr3, 0, 8);
doFinal = bArr3;
}
return Arrays.equals(bArr2, doFinal);
} catch (IOException unused) {
return false;
}
}
@Override // org.jmrtd.protocol.SecureMessagingWrapper
public long getSendSequenceCounter() {
return this.ssc;
}
@Override // org.jmrtd.protocol.SecureMessagingWrapper
public SecretKey getMACKey() {
return this.ksMac;
}
@Override // org.jmrtd.protocol.SecureMessagingWrapper
public SecretKey getEncryptionKey() {
return this.ksEnc;
}
}