200 lines
11 KiB
Java
200 lines
11 KiB
Java
|
package org.bouncycastle.crypto.engines;
|
||
|
|
||
|
import com.google.common.base.Ascii;
|
||
|
import com.google.common.primitives.SignedBytes;
|
||
|
import com.google.common.primitives.UnsignedBytes;
|
||
|
import net.sf.scuba.smartcards.ISO7816;
|
||
|
import net.sf.scuba.smartcards.ISOFileInfo;
|
||
|
import org.bouncycastle.crypto.BlockCipher;
|
||
|
import org.bouncycastle.crypto.CipherParameters;
|
||
|
import org.bouncycastle.crypto.DataLengthException;
|
||
|
import org.bouncycastle.crypto.OutputLengthException;
|
||
|
import org.bouncycastle.crypto.params.KeyParameter;
|
||
|
import org.bouncycastle.crypto.params.RC2Parameters;
|
||
|
import org.bouncycastle.crypto.signers.PSSSigner;
|
||
|
import org.jmrtd.lds.CVCAFile;
|
||
|
|
||
|
/* loaded from: classes6.dex */
|
||
|
public class RC2Engine implements BlockCipher {
|
||
|
private static final int BLOCK_SIZE = 8;
|
||
|
private static byte[] piTable = {-39, 120, -7, -60, Ascii.EM, -35, -75, -19, 40, -23, -3, 121, 74, ISOFileInfo.A0, ISO7816.INS_LOAD_KEY_FILE, -99, -58, 126, 55, ISOFileInfo.FILE_IDENTIFIER, 43, 118, 83, ISOFileInfo.CHANNEL_SECURITY, ISOFileInfo.FCP_BYTE, 76, ISOFileInfo.FMD_BYTE, -120, ISO7816.INS_REHABILITATE_CHV, ISOFileInfo.SECURITY_ATTR_EXP, -5, -94, Ascii.ETB, -102, 89, -11, ISOFileInfo.FCI_EXT, ISO7816.INS_READ_RECORD2, 79, 19, 97, 69, 109, ISOFileInfo.ENV_TEMP_EF, 9, ISOFileInfo.DATA_BYTES2, 125, ISO7816.INS_INCREASE, -67, -113, SignedBytes.MAX_POWER_OF_TWO, -21, -122, -73, 123, 11, -16, -107, 33, ISO7816.INS_MSE, 92, 107, 78, -126, 84, ISO7816.INS_UPDATE_BINARY, 101, -109, -50, 96, -78, 28, 115, 86, ISO7816.INS_GET_RESPONSE, Ascii.DC4, -89, ISOFileInfo.SECURITY_ATTR_COMPACT, -15, ISO7816.INS_UPDATE_RECORD, Ascii.DC2, 117, ISO7816.INS_GET_DATA, Ascii.US, 59, -66, ISO7816.INS_DELETE_FILE, -47, CVCAFile.CAR_TAG, 61, -44, ISO7816.INS_DECREASE, -93, 60, ISO7816.INS_READ_RECORD_STAMPED, 38, ISOFileInfo.FCI_BYTE, -65, 14, ISO7816.INS_PUT_DATA, 70, 105, 7, 87, 39, -14, 29, -101, PSSSigner.TRAILER_IMPLICIT, -108, 67, 3, -8, 17, -57, -10, -112, -17, 62, -25, 6, -61, -43, 47, -56, 102, 30, -41, 8, -24, -22, -34, Byte.MIN_VALUE, 82, -18, -9, -124, -86, 114, -84, 53, 77, 106, ISO7816.INS_PSO, -106, Ascii.SUB, ISO7816.INS_WRITE_RECORD, 113, 90, Ascii.NAK, 73, 116, 75, -97, ISO7816.INS_WRITE_BINARY, 94, 4, Ascii.CAN, -92, -20, ISO7816.INS_ENVELOPE, ISO7816.INS_CREATE_FILE, 65, 110, 15, 81, -53, -52, ISO7816.INS_CHANGE_CHV, -111, -81, 80, ISOFileInfo.A1, -12, ISO7816.INS_MANAGE_CHANNEL, 57, -103, 124, 58, ISOFileInfo.PROP_INFO, 35, -72, ISO7816.INS_READ_BINARY_STAMPED, 122, -4, 2, 54, 91, 37, 85, -105, 49, 45, 93, -6, -104, -29, ISOFileInfo.LCS_BYTE, -110, -82, 5, -33, 41, 16, 103, 108, -70, -55, -45, 0, -26, -49, -31, -98, -88, ISO7816.INS_UNBLOCK_CHV, 99, Ascii.SYN, 1, 63, 88, ISO7816.INS_APPEND_RECORD, -119, -87, 13, 56, ISO7816.INS_DECREASE_STAMPED, Ascii.ESC, ISOFileInfo.AB, 51, -1, ISO7816.INS_READ_BINARY, -69, 72, 12, 95, -71, ISO7816.INS_READ_BINARY2, -51, 46, -59, -13, -37, 71, -27, ISOFileInfo.A5, -100, 119, 10, -90, 32, 104, -2, Ascii.DEL, -63, -83};
|
||
|
private boolean encrypting;
|
||
|
private int[] workingKey;
|
||
|
|
||
|
private int rotateWordLeft(int i, int i2) {
|
||
|
int i3 = i & 65535;
|
||
|
return (i3 << i2) | (i3 >> (16 - i2));
|
||
|
}
|
||
|
|
||
|
@Override // org.bouncycastle.crypto.BlockCipher
|
||
|
public int getBlockSize() {
|
||
|
return 8;
|
||
|
}
|
||
|
|
||
|
@Override // org.bouncycastle.crypto.BlockCipher
|
||
|
public void reset() {
|
||
|
}
|
||
|
|
||
|
@Override // org.bouncycastle.crypto.BlockCipher
|
||
|
public final int processBlock(byte[] bArr, int i, byte[] bArr2, int i2) {
|
||
|
if (this.workingKey == null) {
|
||
|
throw new IllegalStateException("RC2 engine not initialised");
|
||
|
}
|
||
|
if (i + 8 > bArr.length) {
|
||
|
throw new DataLengthException("input buffer too short");
|
||
|
}
|
||
|
if (i2 + 8 > bArr2.length) {
|
||
|
throw new OutputLengthException("output buffer too short");
|
||
|
}
|
||
|
if (this.encrypting) {
|
||
|
encryptBlock(bArr, i, bArr2, i2);
|
||
|
return 8;
|
||
|
}
|
||
|
decryptBlock(bArr, i, bArr2, i2);
|
||
|
return 8;
|
||
|
}
|
||
|
|
||
|
@Override // org.bouncycastle.crypto.BlockCipher
|
||
|
public void init(boolean z, CipherParameters cipherParameters) {
|
||
|
this.encrypting = z;
|
||
|
if (cipherParameters instanceof RC2Parameters) {
|
||
|
RC2Parameters rC2Parameters = (RC2Parameters) cipherParameters;
|
||
|
this.workingKey = generateWorkingKey(rC2Parameters.getKey(), rC2Parameters.getEffectiveKeyBits());
|
||
|
} else if (cipherParameters instanceof KeyParameter) {
|
||
|
byte[] key = ((KeyParameter) cipherParameters).getKey();
|
||
|
this.workingKey = generateWorkingKey(key, key.length << 3);
|
||
|
} else {
|
||
|
StringBuilder sb = new StringBuilder("invalid parameter passed to RC2 init - ");
|
||
|
sb.append(cipherParameters.getClass().getName());
|
||
|
throw new IllegalArgumentException(sb.toString());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override // org.bouncycastle.crypto.BlockCipher
|
||
|
public String getAlgorithmName() {
|
||
|
return "RC2";
|
||
|
}
|
||
|
|
||
|
private int[] generateWorkingKey(byte[] bArr, int i) {
|
||
|
int[] iArr = new int[128];
|
||
|
for (int i2 = 0; i2 != bArr.length; i2++) {
|
||
|
iArr[i2] = bArr[i2] & 255;
|
||
|
}
|
||
|
int length = bArr.length;
|
||
|
if (length < 128) {
|
||
|
int i3 = iArr[length - 1];
|
||
|
int i4 = 0;
|
||
|
while (true) {
|
||
|
i3 = piTable[(i3 + iArr[i4]) & 255] & UnsignedBytes.MAX_VALUE;
|
||
|
int i5 = length + 1;
|
||
|
iArr[length] = i3;
|
||
|
if (i5 >= 128) {
|
||
|
break;
|
||
|
}
|
||
|
i4++;
|
||
|
length = i5;
|
||
|
}
|
||
|
}
|
||
|
int i6 = (i + 7) >> 3;
|
||
|
int i7 = 128 - i6;
|
||
|
int i8 = piTable[(255 >> ((-i) & 7)) & iArr[i7]] & UnsignedBytes.MAX_VALUE;
|
||
|
iArr[i7] = i8;
|
||
|
for (int i9 = 127 - i6; i9 >= 0; i9--) {
|
||
|
i8 = piTable[i8 ^ iArr[i9 + i6]] & UnsignedBytes.MAX_VALUE;
|
||
|
iArr[i9] = i8;
|
||
|
}
|
||
|
int[] iArr2 = new int[64];
|
||
|
for (int i10 = 0; i10 != 64; i10++) {
|
||
|
int i11 = i10 << 1;
|
||
|
iArr2[i10] = iArr[i11] + (iArr[i11 + 1] << 8);
|
||
|
}
|
||
|
return iArr2;
|
||
|
}
|
||
|
|
||
|
private void encryptBlock(byte[] bArr, int i, byte[] bArr2, int i2) {
|
||
|
int i3 = ((bArr[i + 7] & UnsignedBytes.MAX_VALUE) << 8) + (bArr[i + 6] & UnsignedBytes.MAX_VALUE);
|
||
|
int i4 = ((bArr[i + 5] & UnsignedBytes.MAX_VALUE) << 8) + (bArr[i + 4] & UnsignedBytes.MAX_VALUE);
|
||
|
int i5 = ((bArr[i + 3] & UnsignedBytes.MAX_VALUE) << 8) + (bArr[i + 2] & UnsignedBytes.MAX_VALUE);
|
||
|
int i6 = ((bArr[i + 1] & UnsignedBytes.MAX_VALUE) << 8) + (bArr[i] & UnsignedBytes.MAX_VALUE);
|
||
|
for (int i7 = 0; i7 <= 16; i7 += 4) {
|
||
|
i6 = rotateWordLeft(i6 + ((~i3) & i5) + (i4 & i3) + this.workingKey[i7], 1);
|
||
|
i5 = rotateWordLeft(i5 + ((~i6) & i4) + (i3 & i6) + this.workingKey[i7 + 1], 2);
|
||
|
i4 = rotateWordLeft(i4 + ((~i5) & i3) + (i6 & i5) + this.workingKey[i7 + 2], 3);
|
||
|
i3 = rotateWordLeft(i3 + ((~i4) & i6) + (i5 & i4) + this.workingKey[i7 + 3], 5);
|
||
|
}
|
||
|
int[] iArr = this.workingKey;
|
||
|
int i8 = i6 + iArr[i3 & 63];
|
||
|
int i9 = i5 + iArr[i8 & 63];
|
||
|
int i10 = i4 + iArr[i9 & 63];
|
||
|
int i11 = i3 + iArr[i10 & 63];
|
||
|
for (int i12 = 20; i12 <= 40; i12 += 4) {
|
||
|
i8 = rotateWordLeft(i8 + ((~i11) & i9) + (i10 & i11) + this.workingKey[i12], 1);
|
||
|
i9 = rotateWordLeft(i9 + ((~i8) & i10) + (i11 & i8) + this.workingKey[i12 + 1], 2);
|
||
|
i10 = rotateWordLeft(i10 + ((~i9) & i11) + (i8 & i9) + this.workingKey[i12 + 2], 3);
|
||
|
i11 = rotateWordLeft(i11 + ((~i10) & i8) + (i9 & i10) + this.workingKey[i12 + 3], 5);
|
||
|
}
|
||
|
int[] iArr2 = this.workingKey;
|
||
|
int i13 = i8 + iArr2[i11 & 63];
|
||
|
int i14 = i9 + iArr2[i13 & 63];
|
||
|
int i15 = i10 + iArr2[i14 & 63];
|
||
|
int i16 = i11 + iArr2[i15 & 63];
|
||
|
for (int i17 = 44; i17 < 64; i17 += 4) {
|
||
|
i13 = rotateWordLeft(i13 + ((~i16) & i14) + (i15 & i16) + this.workingKey[i17], 1);
|
||
|
i14 = rotateWordLeft(i14 + ((~i13) & i15) + (i16 & i13) + this.workingKey[i17 + 1], 2);
|
||
|
i15 = rotateWordLeft(i15 + ((~i14) & i16) + (i13 & i14) + this.workingKey[i17 + 2], 3);
|
||
|
i16 = rotateWordLeft(i16 + ((~i15) & i13) + (i14 & i15) + this.workingKey[i17 + 3], 5);
|
||
|
}
|
||
|
bArr2[i2] = (byte) i13;
|
||
|
bArr2[i2 + 1] = (byte) (i13 >> 8);
|
||
|
bArr2[i2 + 2] = (byte) i14;
|
||
|
bArr2[i2 + 3] = (byte) (i14 >> 8);
|
||
|
bArr2[i2 + 4] = (byte) i15;
|
||
|
bArr2[i2 + 5] = (byte) (i15 >> 8);
|
||
|
bArr2[i2 + 6] = (byte) i16;
|
||
|
bArr2[i2 + 7] = (byte) (i16 >> 8);
|
||
|
}
|
||
|
|
||
|
private void decryptBlock(byte[] bArr, int i, byte[] bArr2, int i2) {
|
||
|
int i3 = ((bArr[i + 7] & UnsignedBytes.MAX_VALUE) << 8) + (bArr[i + 6] & UnsignedBytes.MAX_VALUE);
|
||
|
int i4 = ((bArr[i + 5] & UnsignedBytes.MAX_VALUE) << 8) + (bArr[i + 4] & UnsignedBytes.MAX_VALUE);
|
||
|
int i5 = ((bArr[i + 3] & UnsignedBytes.MAX_VALUE) << 8) + (bArr[i + 2] & UnsignedBytes.MAX_VALUE);
|
||
|
int i6 = ((bArr[i + 1] & UnsignedBytes.MAX_VALUE) << 8) + (bArr[i] & UnsignedBytes.MAX_VALUE);
|
||
|
for (int i7 = 60; i7 >= 44; i7 -= 4) {
|
||
|
i3 = rotateWordLeft(i3, 11) - ((((~i4) & i6) + (i5 & i4)) + this.workingKey[i7 + 3]);
|
||
|
i4 = rotateWordLeft(i4, 13) - ((((~i5) & i3) + (i6 & i5)) + this.workingKey[i7 + 2]);
|
||
|
i5 = rotateWordLeft(i5, 14) - ((((~i6) & i4) + (i3 & i6)) + this.workingKey[i7 + 1]);
|
||
|
i6 = rotateWordLeft(i6, 15) - ((((~i3) & i5) + (i4 & i3)) + this.workingKey[i7]);
|
||
|
}
|
||
|
int[] iArr = this.workingKey;
|
||
|
int i8 = i3 - iArr[i4 & 63];
|
||
|
int i9 = i4 - iArr[i5 & 63];
|
||
|
int i10 = i5 - iArr[i6 & 63];
|
||
|
int i11 = i6 - iArr[i8 & 63];
|
||
|
for (int i12 = 40; i12 >= 20; i12 -= 4) {
|
||
|
i8 = rotateWordLeft(i8, 11) - ((((~i9) & i11) + (i10 & i9)) + this.workingKey[i12 + 3]);
|
||
|
i9 = rotateWordLeft(i9, 13) - ((((~i10) & i8) + (i11 & i10)) + this.workingKey[i12 + 2]);
|
||
|
i10 = rotateWordLeft(i10, 14) - ((((~i11) & i9) + (i8 & i11)) + this.workingKey[i12 + 1]);
|
||
|
i11 = rotateWordLeft(i11, 15) - ((((~i8) & i10) + (i9 & i8)) + this.workingKey[i12]);
|
||
|
}
|
||
|
int[] iArr2 = this.workingKey;
|
||
|
int i13 = i8 - iArr2[i9 & 63];
|
||
|
int i14 = i9 - iArr2[i10 & 63];
|
||
|
int i15 = i10 - iArr2[i11 & 63];
|
||
|
int i16 = i11 - iArr2[i13 & 63];
|
||
|
for (int i17 = 16; i17 >= 0; i17 -= 4) {
|
||
|
i13 = rotateWordLeft(i13, 11) - ((((~i14) & i16) + (i15 & i14)) + this.workingKey[i17 + 3]);
|
||
|
i14 = rotateWordLeft(i14, 13) - ((((~i15) & i13) + (i16 & i15)) + this.workingKey[i17 + 2]);
|
||
|
i15 = rotateWordLeft(i15, 14) - ((((~i16) & i14) + (i13 & i16)) + this.workingKey[i17 + 1]);
|
||
|
i16 = rotateWordLeft(i16, 15) - ((((~i13) & i15) + (i14 & i13)) + this.workingKey[i17]);
|
||
|
}
|
||
|
bArr2[i2] = (byte) i16;
|
||
|
bArr2[i2 + 1] = (byte) (i16 >> 8);
|
||
|
bArr2[i2 + 2] = (byte) i15;
|
||
|
bArr2[i2 + 3] = (byte) (i15 >> 8);
|
||
|
bArr2[i2 + 4] = (byte) i14;
|
||
|
bArr2[i2 + 5] = (byte) (i14 >> 8);
|
||
|
bArr2[i2 + 6] = (byte) i13;
|
||
|
bArr2[i2 + 7] = (byte) (i13 >> 8);
|
||
|
}
|
||
|
}
|