1024 lines
40 KiB
Java
1024 lines
40 KiB
Java
package org.bouncycastle.crypto.tls;
|
|
|
|
import java.io.ByteArrayInputStream;
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.EOFException;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.OutputStream;
|
|
import java.security.SecureRandom;
|
|
import java.util.Enumeration;
|
|
import java.util.Hashtable;
|
|
import java.util.Vector;
|
|
import org.bouncycastle.crypto.Digest;
|
|
import org.bouncycastle.crypto.prng.RandomGenerator;
|
|
import org.bouncycastle.crypto.tls.SessionParameters;
|
|
import org.bouncycastle.util.Arrays;
|
|
import org.bouncycastle.util.Integers;
|
|
|
|
/* loaded from: classes6.dex */
|
|
public abstract class TlsProtocol {
|
|
protected static final short ADS_MODE_0_N = 1;
|
|
protected static final short ADS_MODE_0_N_FIRSTONLY = 2;
|
|
protected static final short ADS_MODE_1_Nsub1 = 0;
|
|
protected static final short CS_CERTIFICATE_REQUEST = 7;
|
|
protected static final short CS_CERTIFICATE_STATUS = 5;
|
|
protected static final short CS_CERTIFICATE_VERIFY = 12;
|
|
protected static final short CS_CLIENT_CERTIFICATE = 10;
|
|
protected static final short CS_CLIENT_FINISHED = 13;
|
|
protected static final short CS_CLIENT_HELLO = 1;
|
|
protected static final short CS_CLIENT_KEY_EXCHANGE = 11;
|
|
protected static final short CS_CLIENT_SUPPLEMENTAL_DATA = 9;
|
|
protected static final short CS_END = 16;
|
|
protected static final short CS_SERVER_CERTIFICATE = 4;
|
|
protected static final short CS_SERVER_FINISHED = 15;
|
|
protected static final short CS_SERVER_HELLO = 2;
|
|
protected static final short CS_SERVER_HELLO_DONE = 8;
|
|
protected static final short CS_SERVER_KEY_EXCHANGE = 6;
|
|
protected static final short CS_SERVER_SESSION_TICKET = 14;
|
|
protected static final short CS_SERVER_SUPPLEMENTAL_DATA = 3;
|
|
protected static final short CS_START = 0;
|
|
protected static final Integer EXT_RenegotiationInfo = Integers.valueOf(65281);
|
|
protected static final Integer EXT_SessionTicket = Integers.valueOf(35);
|
|
private static final String TLS_ERROR_MESSAGE = "Internal TLS error, this could be an attack";
|
|
private ByteQueue alertQueue;
|
|
protected boolean allowCertificateStatus;
|
|
private volatile boolean appDataReady;
|
|
private volatile boolean appDataSplitEnabled;
|
|
private volatile int appDataSplitMode;
|
|
private ByteQueue applicationDataQueue;
|
|
protected boolean blocking;
|
|
protected Hashtable clientExtensions;
|
|
private volatile boolean closed;
|
|
protected short connection_state;
|
|
protected boolean expectSessionTicket;
|
|
private byte[] expected_verify_data;
|
|
private volatile boolean failedWithError;
|
|
private ByteQueue handshakeQueue;
|
|
protected ByteQueueInputStream inputBuffers;
|
|
protected int[] offeredCipherSuites;
|
|
protected short[] offeredCompressionMethods;
|
|
protected ByteQueueOutputStream outputBuffer;
|
|
protected Certificate peerCertificate;
|
|
protected boolean receivedChangeCipherSpec;
|
|
RecordStream recordStream;
|
|
protected boolean resumedSession;
|
|
protected SecureRandom secureRandom;
|
|
protected boolean secure_renegotiation;
|
|
protected SecurityParameters securityParameters;
|
|
protected Hashtable serverExtensions;
|
|
protected SessionParameters sessionParameters;
|
|
private TlsInputStream tlsInputStream;
|
|
private TlsOutputStream tlsOutputStream;
|
|
protected TlsSession tlsSession;
|
|
|
|
private void processApplicationData() {
|
|
}
|
|
|
|
protected abstract TlsContext getContext();
|
|
|
|
abstract AbstractTlsContext getContextAdmin();
|
|
|
|
protected abstract TlsPeer getPeer();
|
|
|
|
protected void handleChangeCipherSpecMessage() throws IOException {
|
|
}
|
|
|
|
protected abstract void handleHandshakeMessage(short s, byte[] bArr) throws IOException;
|
|
|
|
/* JADX INFO: Access modifiers changed from: protected */
|
|
public void handleWarningMessage(short s) throws IOException {
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: protected */
|
|
public void writeHandshakeMessage(byte[] bArr, int i, int i2) throws IOException {
|
|
while (i2 > 0) {
|
|
int min = Math.min(i2, this.recordStream.getPlaintextLimit());
|
|
safeWriteRecord((short) 22, bArr, i, min);
|
|
i += min;
|
|
i2 -= min;
|
|
}
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: protected */
|
|
public void writeData(byte[] bArr, int i, int i2) throws IOException {
|
|
if (this.closed) {
|
|
if (!this.failedWithError) {
|
|
throw new IOException("Sorry, connection has been closed, you cannot write more data");
|
|
}
|
|
throw new IOException(TLS_ERROR_MESSAGE);
|
|
}
|
|
while (i2 > 0) {
|
|
if (this.appDataSplitEnabled) {
|
|
int i3 = this.appDataSplitMode;
|
|
if (i3 != 1) {
|
|
if (i3 != 2) {
|
|
safeWriteRecord((short) 23, bArr, i, 1);
|
|
i++;
|
|
i2--;
|
|
} else {
|
|
this.appDataSplitEnabled = false;
|
|
}
|
|
}
|
|
safeWriteRecord((short) 23, TlsUtils.EMPTY_BYTES, 0, 0);
|
|
}
|
|
if (i2 > 0) {
|
|
int min = Math.min(i2, this.recordStream.getPlaintextLimit());
|
|
safeWriteRecord((short) 23, bArr, i, min);
|
|
i += min;
|
|
i2 -= min;
|
|
}
|
|
}
|
|
}
|
|
|
|
protected void setAppDataSplitMode(int i) {
|
|
if (i < 0 || i > 2) {
|
|
throw new IllegalArgumentException("Illegal appDataSplitMode mode: ".concat(String.valueOf(i)));
|
|
}
|
|
this.appDataSplitMode = i;
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: protected */
|
|
public void sendSupplementalDataMessage(Vector vector) throws IOException {
|
|
HandshakeMessage handshakeMessage = new HandshakeMessage(this, (short) 23);
|
|
writeSupplementalData(handshakeMessage, vector);
|
|
handshakeMessage.writeToRecordStream();
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: protected */
|
|
public void sendFinishedMessage() throws IOException {
|
|
byte[] createVerifyData = createVerifyData(getContext().isServer());
|
|
HandshakeMessage handshakeMessage = new HandshakeMessage(this, (short) 20, createVerifyData.length);
|
|
handshakeMessage.write(createVerifyData);
|
|
handshakeMessage.writeToRecordStream();
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: protected */
|
|
public void sendChangeCipherSpecMessage() throws IOException {
|
|
safeWriteRecord((short) 20, new byte[]{1}, 0, 1);
|
|
this.recordStream.sentWriteCipherSpec();
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: protected */
|
|
public void sendCertificateMessage(Certificate certificate) throws IOException {
|
|
if (certificate == null) {
|
|
certificate = Certificate.EMPTY_CHAIN;
|
|
}
|
|
if (certificate.isEmpty() && !getContext().isServer()) {
|
|
ProtocolVersion serverVersion = getContext().getServerVersion();
|
|
if (serverVersion.isSSL()) {
|
|
StringBuilder sb = new StringBuilder();
|
|
sb.append(serverVersion.toString());
|
|
sb.append(" client didn't provide credentials");
|
|
raiseWarning((short) 41, sb.toString());
|
|
return;
|
|
}
|
|
}
|
|
HandshakeMessage handshakeMessage = new HandshakeMessage(this, (short) 11);
|
|
certificate.encode(handshakeMessage);
|
|
handshakeMessage.writeToRecordStream();
|
|
}
|
|
|
|
protected void safeWriteRecord(short s, byte[] bArr, int i, int i2) throws IOException {
|
|
try {
|
|
this.recordStream.writeRecord(s, bArr, i, i2);
|
|
} catch (RuntimeException e) {
|
|
if (!this.closed) {
|
|
failWithError((short) 2, (short) 80, "Failed to write record", e);
|
|
}
|
|
throw e;
|
|
} catch (TlsFatalAlert e2) {
|
|
if (!this.closed) {
|
|
failWithError((short) 2, e2.getAlertDescription(), "Failed to write record", e2);
|
|
}
|
|
throw e2;
|
|
} catch (IOException e3) {
|
|
if (!this.closed) {
|
|
failWithError((short) 2, (short) 80, "Failed to write record", e3);
|
|
}
|
|
throw e3;
|
|
}
|
|
}
|
|
|
|
protected void safeReadRecord() throws IOException {
|
|
try {
|
|
if (this.recordStream.readRecord()) {
|
|
} else {
|
|
throw new EOFException();
|
|
}
|
|
} catch (IOException e) {
|
|
if (!this.closed) {
|
|
failWithError((short) 2, (short) 80, "Failed to read record", e);
|
|
}
|
|
throw e;
|
|
} catch (RuntimeException e2) {
|
|
if (!this.closed) {
|
|
failWithError((short) 2, (short) 80, "Failed to read record", e2);
|
|
}
|
|
throw e2;
|
|
} catch (TlsFatalAlert e3) {
|
|
if (!this.closed) {
|
|
failWithError((short) 2, e3.getAlertDescription(), "Failed to read record", e3);
|
|
}
|
|
throw e3;
|
|
}
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: protected */
|
|
public void refuseRenegotiation() throws IOException {
|
|
if (TlsUtils.isSSL(getContext())) {
|
|
throw new TlsFatalAlert((short) 40);
|
|
}
|
|
raiseWarning((short) 100, "Renegotiation not supported");
|
|
}
|
|
|
|
public int readOutput(byte[] bArr, int i, int i2) {
|
|
if (this.blocking) {
|
|
throw new IllegalStateException("Cannot use readOutput() in blocking mode! Use getOutputStream() instead.");
|
|
}
|
|
int min = Math.min(getAvailableOutputBytes(), i2);
|
|
this.outputBuffer.getBuffer().removeData(bArr, i, min, 0);
|
|
return min;
|
|
}
|
|
|
|
public int readInput(byte[] bArr, int i, int i2) {
|
|
if (this.blocking) {
|
|
throw new IllegalStateException("Cannot use readInput() in blocking mode! Use getInputStream() instead.");
|
|
}
|
|
try {
|
|
return readApplicationData(bArr, i, Math.min(i2, applicationDataAvailable()));
|
|
} catch (IOException e) {
|
|
throw new RuntimeException(e.toString());
|
|
}
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: protected */
|
|
public int readApplicationData(byte[] bArr, int i, int i2) throws IOException {
|
|
if (i2 <= 0) {
|
|
return 0;
|
|
}
|
|
while (this.applicationDataQueue.available() == 0) {
|
|
if (this.closed) {
|
|
if (this.failedWithError) {
|
|
throw new IOException(TLS_ERROR_MESSAGE);
|
|
}
|
|
return -1;
|
|
}
|
|
safeReadRecord();
|
|
}
|
|
int min = Math.min(i2, this.applicationDataQueue.available());
|
|
this.applicationDataQueue.removeData(bArr, i, min, 0);
|
|
return min;
|
|
}
|
|
|
|
protected void raiseWarning(short s, String str) throws IOException {
|
|
raiseAlert((short) 1, s, str, null);
|
|
}
|
|
|
|
protected void raiseAlert(short s, short s2, String str, Throwable th) throws IOException {
|
|
getPeer().notifyAlertRaised(s, s2, str, th);
|
|
safeWriteRecord((short) 21, new byte[]{(byte) s, (byte) s2}, 0, 2);
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: protected */
|
|
public void processRecord(short s, byte[] bArr, int i, int i2) throws IOException {
|
|
switch (s) {
|
|
case 20:
|
|
processChangeCipherSpec(bArr, i, i2);
|
|
return;
|
|
case 21:
|
|
this.alertQueue.addData(bArr, i, i2);
|
|
processAlert();
|
|
return;
|
|
case 22:
|
|
this.handshakeQueue.addData(bArr, i, i2);
|
|
processHandshake();
|
|
return;
|
|
case 23:
|
|
if (!this.appDataReady) {
|
|
throw new TlsFatalAlert((short) 10);
|
|
}
|
|
this.applicationDataQueue.addData(bArr, i, i2);
|
|
processApplicationData();
|
|
return;
|
|
case 24:
|
|
if (!this.appDataReady) {
|
|
throw new TlsFatalAlert((short) 10);
|
|
}
|
|
return;
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: protected */
|
|
public short processMaxFragmentLengthExtension(Hashtable hashtable, Hashtable hashtable2, short s) throws IOException {
|
|
short maxFragmentLengthExtension = TlsExtensionsUtils.getMaxFragmentLengthExtension(hashtable2);
|
|
if (maxFragmentLengthExtension < 0 || (MaxFragmentLength.isValid(maxFragmentLengthExtension) && (this.resumedSession || maxFragmentLengthExtension == TlsExtensionsUtils.getMaxFragmentLengthExtension(hashtable)))) {
|
|
return maxFragmentLengthExtension;
|
|
}
|
|
throw new TlsFatalAlert(s);
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: protected */
|
|
public void processFinishedMessage(ByteArrayInputStream byteArrayInputStream) throws IOException {
|
|
byte[] bArr = this.expected_verify_data;
|
|
if (bArr == null) {
|
|
throw new TlsFatalAlert((short) 80);
|
|
}
|
|
byte[] readFully = TlsUtils.readFully(bArr.length, byteArrayInputStream);
|
|
assertEmpty(byteArrayInputStream);
|
|
if (!Arrays.constantTimeAreEqual(this.expected_verify_data, readFully)) {
|
|
throw new TlsFatalAlert((short) 51);
|
|
}
|
|
}
|
|
|
|
public void offerOutput(byte[] bArr, int i, int i2) throws IOException {
|
|
if (this.blocking) {
|
|
throw new IllegalStateException("Cannot use offerOutput() in blocking mode! Use getOutputStream() instead.");
|
|
}
|
|
if (!this.appDataReady) {
|
|
throw new IOException("Application data cannot be sent until the handshake is complete!");
|
|
}
|
|
writeData(bArr, i, i2);
|
|
}
|
|
|
|
public void offerInput(byte[] bArr) throws IOException {
|
|
if (this.blocking) {
|
|
throw new IllegalStateException("Cannot use offerInput() in blocking mode! Use getInputStream() instead.");
|
|
}
|
|
if (this.closed) {
|
|
throw new IOException("Connection is closed, cannot accept any more input");
|
|
}
|
|
this.inputBuffers.addBytes(bArr);
|
|
while (this.inputBuffers.available() >= 5) {
|
|
byte[] bArr2 = new byte[5];
|
|
this.inputBuffers.peek(bArr2);
|
|
if (this.inputBuffers.available() < TlsUtils.readUint16(bArr2, 3) + 5) {
|
|
return;
|
|
} else {
|
|
safeReadRecord();
|
|
}
|
|
}
|
|
}
|
|
|
|
public boolean isClosed() {
|
|
return this.closed;
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: protected */
|
|
public void invalidateSession() {
|
|
SessionParameters sessionParameters = this.sessionParameters;
|
|
if (sessionParameters != null) {
|
|
sessionParameters.clear();
|
|
this.sessionParameters = null;
|
|
}
|
|
TlsSession tlsSession = this.tlsSession;
|
|
if (tlsSession != null) {
|
|
tlsSession.invalidate();
|
|
this.tlsSession = null;
|
|
}
|
|
}
|
|
|
|
protected void handleClose(boolean z) throws IOException {
|
|
if (this.closed) {
|
|
return;
|
|
}
|
|
if (z && !this.appDataReady) {
|
|
raiseWarning((short) 90, "User canceled handshake");
|
|
}
|
|
failWithError((short) 1, (short) 0, "Connection closed", null);
|
|
}
|
|
|
|
public OutputStream getOutputStream() {
|
|
if (this.blocking) {
|
|
return this.tlsOutputStream;
|
|
}
|
|
throw new IllegalStateException("Cannot use OutputStream in non-blocking mode! Use offerOutput() instead.");
|
|
}
|
|
|
|
public InputStream getInputStream() {
|
|
if (this.blocking) {
|
|
return this.tlsInputStream;
|
|
}
|
|
throw new IllegalStateException("Cannot use InputStream in non-blocking mode! Use offerInput() instead.");
|
|
}
|
|
|
|
public int getAvailableOutputBytes() {
|
|
if (this.blocking) {
|
|
throw new IllegalStateException("Cannot use getAvailableOutputBytes() in blocking mode! Use getOutputStream() instead.");
|
|
}
|
|
return this.outputBuffer.getBuffer().available();
|
|
}
|
|
|
|
public int getAvailableInputBytes() {
|
|
if (this.blocking) {
|
|
throw new IllegalStateException("Cannot use getAvailableInputBytes() in blocking mode! Use getInputStream().available() instead.");
|
|
}
|
|
return applicationDataAvailable();
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: protected */
|
|
public void flush() throws IOException {
|
|
this.recordStream.flush();
|
|
}
|
|
|
|
protected void failWithError(short s, short s2, String str, Throwable th) throws IOException {
|
|
if (!this.closed) {
|
|
this.closed = true;
|
|
if (s == 2) {
|
|
invalidateSession();
|
|
this.failedWithError = true;
|
|
}
|
|
raiseAlert(s, s2, str, th);
|
|
this.recordStream.safeClose();
|
|
if (s != 2) {
|
|
return;
|
|
}
|
|
}
|
|
throw new IOException(TLS_ERROR_MESSAGE);
|
|
}
|
|
|
|
protected byte[] createVerifyData(boolean z) {
|
|
TlsContext context = getContext();
|
|
return TlsUtils.calculateVerifyData(context, z ? ExporterLabel.server_finished : ExporterLabel.client_finished, getCurrentPRFHash(context, this.recordStream.getHandshakeHash(), z ? TlsUtils.SSL_SERVER : TlsUtils.SSL_CLIENT));
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: protected */
|
|
public void completeHandshake() throws IOException {
|
|
try {
|
|
this.recordStream.finaliseHandshake();
|
|
this.appDataSplitEnabled = !TlsUtils.isTLSv11(getContext());
|
|
if (!this.appDataReady) {
|
|
this.appDataReady = true;
|
|
if (this.blocking) {
|
|
this.tlsInputStream = new TlsInputStream(this);
|
|
this.tlsOutputStream = new TlsOutputStream(this);
|
|
}
|
|
}
|
|
if (this.tlsSession != null) {
|
|
if (this.sessionParameters == null) {
|
|
this.sessionParameters = new SessionParameters.Builder().setCipherSuite(this.securityParameters.getCipherSuite()).setCompressionAlgorithm(this.securityParameters.getCompressionAlgorithm()).setMasterSecret(this.securityParameters.getMasterSecret()).setPeerCertificate(this.peerCertificate).setPSKIdentity(this.securityParameters.getPSKIdentity()).setSRPIdentity(this.securityParameters.getSRPIdentity()).setServerExtensions(this.serverExtensions).build();
|
|
this.tlsSession = new TlsSessionImpl(this.tlsSession.getSessionID(), this.sessionParameters);
|
|
}
|
|
getContextAdmin().setResumableSession(this.tlsSession);
|
|
}
|
|
getPeer().notifyHandshakeComplete();
|
|
} finally {
|
|
cleanupHandshake();
|
|
}
|
|
}
|
|
|
|
public void close() throws IOException {
|
|
handleClose(true);
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: protected */
|
|
public void cleanupHandshake() {
|
|
byte[] bArr = this.expected_verify_data;
|
|
if (bArr != null) {
|
|
Arrays.fill(bArr, (byte) 0);
|
|
this.expected_verify_data = null;
|
|
}
|
|
this.securityParameters.clear();
|
|
this.peerCertificate = null;
|
|
this.offeredCipherSuites = null;
|
|
this.offeredCompressionMethods = null;
|
|
this.clientExtensions = null;
|
|
this.serverExtensions = null;
|
|
this.resumedSession = false;
|
|
this.receivedChangeCipherSpec = false;
|
|
this.secure_renegotiation = false;
|
|
this.allowCertificateStatus = false;
|
|
this.expectSessionTicket = false;
|
|
}
|
|
|
|
protected void checkReceivedChangeCipherSpec(boolean z) throws IOException {
|
|
if (z != this.receivedChangeCipherSpec) {
|
|
throw new TlsFatalAlert((short) 10);
|
|
}
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: protected */
|
|
public void blockForHandshake() throws IOException {
|
|
if (this.blocking) {
|
|
while (this.connection_state != 16) {
|
|
safeReadRecord();
|
|
}
|
|
}
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: protected */
|
|
public void applyMaxFragmentLengthExtension() throws IOException {
|
|
if (this.securityParameters.maxFragmentLength >= 0) {
|
|
if (!MaxFragmentLength.isValid(this.securityParameters.maxFragmentLength)) {
|
|
throw new TlsFatalAlert((short) 80);
|
|
}
|
|
this.recordStream.setPlaintextLimit(1 << (this.securityParameters.maxFragmentLength + CS_SERVER_HELLO_DONE));
|
|
}
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: protected */
|
|
public int applicationDataAvailable() {
|
|
return this.applicationDataQueue.available();
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: protected */
|
|
public static void writeSupplementalData(OutputStream outputStream, Vector vector) throws IOException {
|
|
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
|
for (int i = 0; i < vector.size(); i++) {
|
|
SupplementalDataEntry supplementalDataEntry = (SupplementalDataEntry) vector.elementAt(i);
|
|
int dataType = supplementalDataEntry.getDataType();
|
|
TlsUtils.checkUint16(dataType);
|
|
TlsUtils.writeUint16(dataType, byteArrayOutputStream);
|
|
TlsUtils.writeOpaque16(supplementalDataEntry.getData(), byteArrayOutputStream);
|
|
}
|
|
TlsUtils.writeOpaque24(byteArrayOutputStream.toByteArray(), outputStream);
|
|
}
|
|
|
|
protected static void writeSelectedExtensions(OutputStream outputStream, Hashtable hashtable, boolean z) throws IOException {
|
|
Enumeration keys = hashtable.keys();
|
|
while (keys.hasMoreElements()) {
|
|
Integer num = (Integer) keys.nextElement();
|
|
int intValue = num.intValue();
|
|
byte[] bArr = (byte[]) hashtable.get(num);
|
|
if (z == (bArr.length == 0)) {
|
|
TlsUtils.checkUint16(intValue);
|
|
TlsUtils.writeUint16(intValue, outputStream);
|
|
TlsUtils.writeOpaque16(bArr, outputStream);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: protected */
|
|
public static void writeExtensions(OutputStream outputStream, Hashtable hashtable) throws IOException {
|
|
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
|
writeSelectedExtensions(byteArrayOutputStream, hashtable, true);
|
|
writeSelectedExtensions(byteArrayOutputStream, hashtable, false);
|
|
TlsUtils.writeOpaque16(byteArrayOutputStream.toByteArray(), outputStream);
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: protected */
|
|
public static Vector readSupplementalDataMessage(ByteArrayInputStream byteArrayInputStream) throws IOException {
|
|
byte[] readOpaque24 = TlsUtils.readOpaque24(byteArrayInputStream);
|
|
assertEmpty(byteArrayInputStream);
|
|
ByteArrayInputStream byteArrayInputStream2 = new ByteArrayInputStream(readOpaque24);
|
|
Vector vector = new Vector();
|
|
while (byteArrayInputStream2.available() > 0) {
|
|
vector.addElement(new SupplementalDataEntry(TlsUtils.readUint16(byteArrayInputStream2), TlsUtils.readOpaque16(byteArrayInputStream2)));
|
|
}
|
|
return vector;
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: protected */
|
|
public static Hashtable readExtensions(ByteArrayInputStream byteArrayInputStream) throws IOException {
|
|
if (byteArrayInputStream.available() <= 0) {
|
|
return null;
|
|
}
|
|
byte[] readOpaque16 = TlsUtils.readOpaque16(byteArrayInputStream);
|
|
assertEmpty(byteArrayInputStream);
|
|
ByteArrayInputStream byteArrayInputStream2 = new ByteArrayInputStream(readOpaque16);
|
|
Hashtable hashtable = new Hashtable();
|
|
while (byteArrayInputStream2.available() > 0) {
|
|
if (hashtable.put(Integers.valueOf(TlsUtils.readUint16(byteArrayInputStream2)), TlsUtils.readOpaque16(byteArrayInputStream2)) != null) {
|
|
throw new TlsFatalAlert((short) 47);
|
|
}
|
|
}
|
|
return hashtable;
|
|
}
|
|
|
|
private void processHandshake() throws IOException {
|
|
while (this.handshakeQueue.available() >= 4) {
|
|
byte[] bArr = new byte[4];
|
|
this.handshakeQueue.read(bArr, 0, 4, 0);
|
|
short readUint8 = TlsUtils.readUint8(bArr, 0);
|
|
int readUint24 = TlsUtils.readUint24(bArr, 1);
|
|
if (this.handshakeQueue.available() < readUint24 + 4) {
|
|
return;
|
|
}
|
|
byte[] removeData = this.handshakeQueue.removeData(readUint24, 4);
|
|
checkReceivedChangeCipherSpec(this.connection_state == 16 || readUint8 == 20);
|
|
if (readUint8 != 0) {
|
|
if (readUint8 == 20) {
|
|
TlsContext context = getContext();
|
|
if (this.expected_verify_data == null && context.getSecurityParameters().getMasterSecret() != null) {
|
|
this.expected_verify_data = createVerifyData(true ^ context.isServer());
|
|
}
|
|
}
|
|
this.recordStream.updateHandshakeData(bArr, 0, 4);
|
|
this.recordStream.updateHandshakeData(removeData, 0, readUint24);
|
|
}
|
|
handleHandshakeMessage(readUint8, removeData);
|
|
}
|
|
}
|
|
|
|
private void processChangeCipherSpec(byte[] bArr, int i, int i2) throws IOException {
|
|
for (int i3 = 0; i3 < i2; i3++) {
|
|
if (TlsUtils.readUint8(bArr, i + i3) != 1) {
|
|
throw new TlsFatalAlert((short) 50);
|
|
}
|
|
if (this.receivedChangeCipherSpec || this.alertQueue.available() > 0 || this.handshakeQueue.available() > 0) {
|
|
throw new TlsFatalAlert((short) 10);
|
|
}
|
|
this.recordStream.receivedReadCipherSpec();
|
|
this.receivedChangeCipherSpec = true;
|
|
handleChangeCipherSpecMessage();
|
|
}
|
|
}
|
|
|
|
private void processAlert() throws IOException {
|
|
while (this.alertQueue.available() >= 2) {
|
|
byte[] removeData = this.alertQueue.removeData(2, 0);
|
|
short s = removeData[0];
|
|
short s2 = removeData[1];
|
|
getPeer().notifyAlertReceived(s, s2);
|
|
if (s == 2) {
|
|
invalidateSession();
|
|
this.failedWithError = true;
|
|
this.closed = true;
|
|
this.recordStream.safeClose();
|
|
throw new IOException(TLS_ERROR_MESSAGE);
|
|
}
|
|
if (s2 == 0) {
|
|
handleClose(false);
|
|
}
|
|
handleWarningMessage(s2);
|
|
}
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: protected */
|
|
/* JADX WARN: Can't fix incorrect switch cases order, some code will duplicate */
|
|
/* JADX WARN: Failed to find 'out' block for switch in B:10:0x001b. Please report as an issue. */
|
|
/* JADX WARN: Failed to find 'out' block for switch in B:11:0x001e. Please report as an issue. */
|
|
/* JADX WARN: Failed to find 'out' block for switch in B:12:0x0021. Please report as an issue. */
|
|
/* JADX WARN: Failed to find 'out' block for switch in B:5:0x000e. Please report as an issue. */
|
|
/* JADX WARN: Failed to find 'out' block for switch in B:6:0x0011. Please report as an issue. */
|
|
/* JADX WARN: Failed to find 'out' block for switch in B:8:0x0015. Please report as an issue. */
|
|
/* JADX WARN: Failed to find 'out' block for switch in B:9:0x0018. Please report as an issue. */
|
|
/* JADX WARN: Removed duplicated region for block: B:23:0x0031 */
|
|
/* JADX WARN: Removed duplicated region for block: B:28:0x003c A[RETURN] */
|
|
/* JADX WARN: Removed duplicated region for block: B:29:0x003d */
|
|
/*
|
|
Code decompiled incorrectly, please refer to instructions dump.
|
|
To view partially-correct add '--show-bad-code' argument
|
|
*/
|
|
public static int getPRFAlgorithm(org.bouncycastle.crypto.tls.TlsContext r4, int r5) throws java.io.IOException {
|
|
/*
|
|
boolean r4 = org.bouncycastle.crypto.tls.TlsUtils.isTLSv12(r4)
|
|
r0 = 1
|
|
r1 = 47
|
|
switch(r5) {
|
|
case 59: goto L3a;
|
|
case 60: goto L3a;
|
|
case 61: goto L3a;
|
|
case 62: goto L3a;
|
|
case 63: goto L3a;
|
|
case 64: goto L3a;
|
|
default: goto La;
|
|
}
|
|
La:
|
|
switch(r5) {
|
|
case 103: goto L3a;
|
|
case 104: goto L3a;
|
|
case 105: goto L3a;
|
|
case 106: goto L3a;
|
|
case 107: goto L3a;
|
|
default: goto Ld;
|
|
}
|
|
Ld:
|
|
r2 = 2
|
|
switch(r5) {
|
|
case 156: goto L3a;
|
|
case 157: goto L31;
|
|
case 158: goto L3a;
|
|
case 159: goto L31;
|
|
case 160: goto L3a;
|
|
case 161: goto L31;
|
|
case 162: goto L3a;
|
|
case 163: goto L31;
|
|
case 164: goto L3a;
|
|
case 165: goto L31;
|
|
default: goto L11;
|
|
}
|
|
L11:
|
|
switch(r5) {
|
|
case 168: goto L3a;
|
|
case 169: goto L31;
|
|
case 170: goto L3a;
|
|
case 171: goto L31;
|
|
case 172: goto L3a;
|
|
case 173: goto L31;
|
|
default: goto L14;
|
|
}
|
|
L14:
|
|
r3 = 0
|
|
switch(r5) {
|
|
case 175: goto L43;
|
|
case 177: goto L43;
|
|
case 179: goto L43;
|
|
case 181: goto L43;
|
|
case 183: goto L43;
|
|
case 49208: goto L43;
|
|
case 49211: goto L43;
|
|
case 49301: goto L43;
|
|
case 49303: goto L43;
|
|
case 49305: goto L43;
|
|
default: goto L18;
|
|
}
|
|
L18:
|
|
switch(r5) {
|
|
case 49266: goto L3a;
|
|
case 49267: goto L31;
|
|
case 49268: goto L3a;
|
|
case 49269: goto L31;
|
|
case 49270: goto L3a;
|
|
case 49271: goto L31;
|
|
case 49272: goto L3a;
|
|
case 49273: goto L31;
|
|
case 49274: goto L3a;
|
|
case 49275: goto L31;
|
|
case 49276: goto L3a;
|
|
case 49277: goto L31;
|
|
case 49278: goto L3a;
|
|
case 49279: goto L31;
|
|
case 49280: goto L3a;
|
|
case 49281: goto L31;
|
|
case 49282: goto L3a;
|
|
case 49283: goto L31;
|
|
case 49284: goto L3a;
|
|
case 49285: goto L31;
|
|
case 49286: goto L3a;
|
|
case 49287: goto L31;
|
|
case 49288: goto L3a;
|
|
case 49289: goto L31;
|
|
case 49290: goto L3a;
|
|
case 49291: goto L31;
|
|
case 49292: goto L3a;
|
|
case 49293: goto L31;
|
|
case 49294: goto L3a;
|
|
case 49295: goto L31;
|
|
case 49296: goto L3a;
|
|
case 49297: goto L31;
|
|
case 49298: goto L3a;
|
|
case 49299: goto L31;
|
|
default: goto L1b;
|
|
}
|
|
L1b:
|
|
switch(r5) {
|
|
case 65296: goto L3a;
|
|
case 65297: goto L3a;
|
|
case 65298: goto L3a;
|
|
case 65299: goto L3a;
|
|
case 65300: goto L3a;
|
|
case 65301: goto L3a;
|
|
default: goto L1e;
|
|
}
|
|
L1e:
|
|
switch(r5) {
|
|
case 185: goto L43;
|
|
case 186: goto L3a;
|
|
case 187: goto L3a;
|
|
case 188: goto L3a;
|
|
case 189: goto L3a;
|
|
case 190: goto L3a;
|
|
case 191: goto L3a;
|
|
case 192: goto L3a;
|
|
case 193: goto L3a;
|
|
case 194: goto L3a;
|
|
case 195: goto L3a;
|
|
case 196: goto L3a;
|
|
case 197: goto L3a;
|
|
default: goto L21;
|
|
}
|
|
L21:
|
|
switch(r5) {
|
|
case 49187: goto L3a;
|
|
case 49188: goto L31;
|
|
case 49189: goto L3a;
|
|
case 49190: goto L31;
|
|
case 49191: goto L3a;
|
|
case 49192: goto L31;
|
|
case 49193: goto L3a;
|
|
case 49194: goto L31;
|
|
case 49195: goto L3a;
|
|
case 49196: goto L31;
|
|
case 49197: goto L3a;
|
|
case 49198: goto L31;
|
|
case 49199: goto L3a;
|
|
case 49200: goto L31;
|
|
case 49201: goto L3a;
|
|
case 49202: goto L31;
|
|
default: goto L24;
|
|
}
|
|
L24:
|
|
switch(r5) {
|
|
case 49307: goto L43;
|
|
case 49308: goto L3a;
|
|
case 49309: goto L3a;
|
|
case 49310: goto L3a;
|
|
case 49311: goto L3a;
|
|
case 49312: goto L3a;
|
|
case 49313: goto L3a;
|
|
case 49314: goto L3a;
|
|
case 49315: goto L3a;
|
|
case 49316: goto L3a;
|
|
case 49317: goto L3a;
|
|
case 49318: goto L3a;
|
|
case 49319: goto L3a;
|
|
case 49320: goto L3a;
|
|
case 49321: goto L3a;
|
|
case 49322: goto L3a;
|
|
case 49323: goto L3a;
|
|
case 49324: goto L3a;
|
|
case 49325: goto L3a;
|
|
case 49326: goto L3a;
|
|
case 49327: goto L3a;
|
|
default: goto L27;
|
|
}
|
|
L27:
|
|
switch(r5) {
|
|
case 52392: goto L3a;
|
|
case 52393: goto L3a;
|
|
case 52394: goto L3a;
|
|
case 52395: goto L3a;
|
|
case 52396: goto L3a;
|
|
case 52397: goto L3a;
|
|
case 52398: goto L3a;
|
|
default: goto L2a;
|
|
}
|
|
L2a:
|
|
switch(r5) {
|
|
case 65280: goto L3a;
|
|
case 65281: goto L3a;
|
|
case 65282: goto L3a;
|
|
case 65283: goto L3a;
|
|
case 65284: goto L3a;
|
|
case 65285: goto L3a;
|
|
default: goto L2d;
|
|
}
|
|
L2d:
|
|
if (r4 == 0) goto L30
|
|
return r0
|
|
L30:
|
|
return r3
|
|
L31:
|
|
if (r4 == 0) goto L34
|
|
return r2
|
|
L34:
|
|
org.bouncycastle.crypto.tls.TlsFatalAlert r4 = new org.bouncycastle.crypto.tls.TlsFatalAlert
|
|
r4.<init>(r1)
|
|
throw r4
|
|
L3a:
|
|
if (r4 == 0) goto L3d
|
|
return r0
|
|
L3d:
|
|
org.bouncycastle.crypto.tls.TlsFatalAlert r4 = new org.bouncycastle.crypto.tls.TlsFatalAlert
|
|
r4.<init>(r1)
|
|
throw r4
|
|
L43:
|
|
if (r4 == 0) goto L46
|
|
return r2
|
|
L46:
|
|
return r3
|
|
*/
|
|
throw new UnsupportedOperationException("Method not decompiled: org.bouncycastle.crypto.tls.TlsProtocol.getPRFAlgorithm(org.bouncycastle.crypto.tls.TlsContext, int):int");
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: protected */
|
|
public static byte[] getCurrentPRFHash(TlsContext tlsContext, TlsHandshakeHash tlsHandshakeHash, byte[] bArr) {
|
|
Digest forkPRFHash = tlsHandshakeHash.forkPRFHash();
|
|
if (bArr != null && TlsUtils.isSSL(tlsContext)) {
|
|
forkPRFHash.update(bArr, 0, bArr.length);
|
|
}
|
|
byte[] bArr2 = new byte[forkPRFHash.getDigestSize()];
|
|
forkPRFHash.doFinal(bArr2, 0);
|
|
return bArr2;
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: protected */
|
|
public static void establishMasterSecret(TlsContext tlsContext, TlsKeyExchange tlsKeyExchange) throws IOException {
|
|
byte[] generatePremasterSecret = tlsKeyExchange.generatePremasterSecret();
|
|
try {
|
|
tlsContext.getSecurityParameters().masterSecret = TlsUtils.calculateMasterSecret(tlsContext, generatePremasterSecret);
|
|
} finally {
|
|
if (generatePremasterSecret != null) {
|
|
Arrays.fill(generatePremasterSecret, (byte) 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: protected */
|
|
public static byte[] createRenegotiationInfo(byte[] bArr) throws IOException {
|
|
return TlsUtils.encodeOpaque8(bArr);
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: protected */
|
|
public static byte[] createRandomBlock(boolean z, RandomGenerator randomGenerator) {
|
|
byte[] bArr = new byte[32];
|
|
randomGenerator.nextBytes(bArr);
|
|
if (z) {
|
|
TlsUtils.writeGMTUnixTime(bArr, 0);
|
|
}
|
|
return bArr;
|
|
}
|
|
|
|
/* loaded from: classes6.dex */
|
|
class HandshakeMessage extends ByteArrayOutputStream {
|
|
final TlsProtocol this$0;
|
|
|
|
/* JADX INFO: Access modifiers changed from: package-private */
|
|
public void writeToRecordStream() throws IOException {
|
|
int i = ((ByteArrayOutputStream) this).count - 4;
|
|
TlsUtils.checkUint24(i);
|
|
TlsUtils.writeUint24(i, ((ByteArrayOutputStream) this).buf, 1);
|
|
this.this$0.writeHandshakeMessage(((ByteArrayOutputStream) this).buf, 0, ((ByteArrayOutputStream) this).count);
|
|
((ByteArrayOutputStream) this).buf = null;
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: package-private */
|
|
/* JADX WARN: 'super' call moved to the top of the method (can break code semantics) */
|
|
public HandshakeMessage(TlsProtocol tlsProtocol, short s, int i) throws IOException {
|
|
super(i + 4);
|
|
this.this$0 = tlsProtocol;
|
|
TlsUtils.writeUint8(s, (OutputStream) this);
|
|
((ByteArrayOutputStream) this).count += 3;
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: package-private */
|
|
public HandshakeMessage(TlsProtocol tlsProtocol, short s) throws IOException {
|
|
this(tlsProtocol, s, 60);
|
|
}
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: protected */
|
|
public static void assertEmpty(ByteArrayInputStream byteArrayInputStream) throws IOException {
|
|
if (byteArrayInputStream.available() > 0) {
|
|
throw new TlsFatalAlert((short) 50);
|
|
}
|
|
}
|
|
|
|
public TlsProtocol(SecureRandom secureRandom) {
|
|
this.applicationDataQueue = new ByteQueue();
|
|
this.alertQueue = new ByteQueue(2);
|
|
this.handshakeQueue = new ByteQueue();
|
|
this.tlsInputStream = null;
|
|
this.tlsOutputStream = null;
|
|
this.closed = false;
|
|
this.failedWithError = false;
|
|
this.appDataReady = false;
|
|
this.appDataSplitEnabled = true;
|
|
this.appDataSplitMode = 0;
|
|
this.expected_verify_data = null;
|
|
this.tlsSession = null;
|
|
this.sessionParameters = null;
|
|
this.securityParameters = null;
|
|
this.peerCertificate = null;
|
|
this.offeredCipherSuites = null;
|
|
this.offeredCompressionMethods = null;
|
|
this.clientExtensions = null;
|
|
this.serverExtensions = null;
|
|
this.connection_state = (short) 0;
|
|
this.resumedSession = false;
|
|
this.receivedChangeCipherSpec = false;
|
|
this.secure_renegotiation = false;
|
|
this.allowCertificateStatus = false;
|
|
this.expectSessionTicket = false;
|
|
this.blocking = false;
|
|
this.inputBuffers = new ByteQueueInputStream();
|
|
this.outputBuffer = new ByteQueueOutputStream();
|
|
this.recordStream = new RecordStream(this, this.inputBuffers, this.outputBuffer);
|
|
this.secureRandom = secureRandom;
|
|
}
|
|
|
|
public TlsProtocol(InputStream inputStream, OutputStream outputStream, SecureRandom secureRandom) {
|
|
this.applicationDataQueue = new ByteQueue();
|
|
this.alertQueue = new ByteQueue(2);
|
|
this.handshakeQueue = new ByteQueue();
|
|
this.tlsInputStream = null;
|
|
this.tlsOutputStream = null;
|
|
this.closed = false;
|
|
this.failedWithError = false;
|
|
this.appDataReady = false;
|
|
this.appDataSplitEnabled = true;
|
|
this.appDataSplitMode = 0;
|
|
this.expected_verify_data = null;
|
|
this.tlsSession = null;
|
|
this.sessionParameters = null;
|
|
this.securityParameters = null;
|
|
this.peerCertificate = null;
|
|
this.offeredCipherSuites = null;
|
|
this.offeredCompressionMethods = null;
|
|
this.clientExtensions = null;
|
|
this.serverExtensions = null;
|
|
this.connection_state = (short) 0;
|
|
this.resumedSession = false;
|
|
this.receivedChangeCipherSpec = false;
|
|
this.secure_renegotiation = false;
|
|
this.allowCertificateStatus = false;
|
|
this.expectSessionTicket = false;
|
|
this.blocking = true;
|
|
this.recordStream = new RecordStream(this, inputStream, outputStream);
|
|
this.secureRandom = secureRandom;
|
|
}
|
|
}
|