use of javax.net.ssl.SSLProtocolException in project robovm by robovm.
the class OpenSSLSocketImpl method startHandshake.
/**
* Starts a TLS/SSL handshake on this connection using some native methods
* from the OpenSSL library. It can negotiate new encryption keys, change
* cipher suites, or initiate a new session. The certificate chain is
* verified if the correspondent property in java.Security is set. All
* listeners are notified at the end of the TLS/SSL handshake.
*/
@Override
public synchronized void startHandshake() throws IOException {
synchronized (handshakeLock) {
checkOpen();
if (!handshakeStarted) {
handshakeStarted = true;
} else {
return;
}
}
// note that this modifies the global seed, not something specific to the connection
final int seedLengthInBytes = NativeCrypto.RAND_SEED_LENGTH_IN_BYTES;
final SecureRandom secureRandom = sslParameters.getSecureRandomMember();
if (secureRandom == null) {
NativeCrypto.RAND_load_file("/dev/urandom", seedLengthInBytes);
} else {
NativeCrypto.RAND_seed(secureRandom.generateSeed(seedLengthInBytes));
}
final boolean client = sslParameters.getUseClientMode();
final long sslCtxNativePointer = (client) ? sslParameters.getClientSessionContext().sslCtxNativePointer : sslParameters.getServerSessionContext().sslCtxNativePointer;
this.sslNativePointer = 0;
boolean exception = true;
try {
sslNativePointer = NativeCrypto.SSL_new(sslCtxNativePointer);
guard.open("close");
if (npnProtocols != null) {
NativeCrypto.SSL_CTX_enable_npn(sslCtxNativePointer);
}
if (client && alpnProtocols != null) {
NativeCrypto.SSL_CTX_set_alpn_protos(sslCtxNativePointer, alpnProtocols);
}
// clients will receive a call back to request certificates.
if (!client) {
Set<String> keyTypes = new HashSet<String>();
for (String enabledCipherSuite : enabledCipherSuites) {
if (enabledCipherSuite.equals(NativeCrypto.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)) {
continue;
}
String keyType = CipherSuite.getByName(enabledCipherSuite).getServerKeyType();
if (keyType != null) {
keyTypes.add(keyType);
}
}
for (String keyType : keyTypes) {
try {
setCertificate(sslParameters.getKeyManager().chooseServerAlias(keyType, null, this));
} catch (CertificateEncodingException e) {
throw new IOException(e);
}
}
}
NativeCrypto.setEnabledProtocols(sslNativePointer, enabledProtocols);
NativeCrypto.setEnabledCipherSuites(sslNativePointer, enabledCipherSuites);
if (useSessionTickets) {
NativeCrypto.SSL_clear_options(sslNativePointer, NativeCrypto.SSL_OP_NO_TICKET);
}
if (hostname != null) {
NativeCrypto.SSL_set_tlsext_host_name(sslNativePointer, hostname);
}
boolean enableSessionCreation = sslParameters.getEnableSessionCreation();
if (!enableSessionCreation) {
NativeCrypto.SSL_set_session_creation_enabled(sslNativePointer, enableSessionCreation);
}
AbstractSessionContext sessionContext;
OpenSSLSessionImpl sessionToReuse;
if (client) {
// look for client session to reuse
ClientSessionContext clientSessionContext = sslParameters.getClientSessionContext();
sessionContext = clientSessionContext;
sessionToReuse = getCachedClientSession(clientSessionContext);
if (sessionToReuse != null) {
NativeCrypto.SSL_set_session(sslNativePointer, sessionToReuse.sslSessionNativePointer);
}
} else {
sessionContext = sslParameters.getServerSessionContext();
sessionToReuse = null;
}
// setup peer certificate verification
if (client) {
// TODO support for anonymous cipher would require us to
// conditionally use SSL_VERIFY_NONE
} else {
// needing client auth takes priority...
boolean certRequested;
if (sslParameters.getNeedClientAuth()) {
NativeCrypto.SSL_set_verify(sslNativePointer, NativeCrypto.SSL_VERIFY_PEER | NativeCrypto.SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
certRequested = true;
// ... over just wanting it...
} else if (sslParameters.getWantClientAuth()) {
NativeCrypto.SSL_set_verify(sslNativePointer, NativeCrypto.SSL_VERIFY_PEER);
certRequested = true;
// ... and it defaults properly so don't call SSL_set_verify in the common case.
} else {
certRequested = false;
}
if (certRequested) {
X509TrustManager trustManager = sslParameters.getTrustManager();
X509Certificate[] issuers = trustManager.getAcceptedIssuers();
if (issuers != null && issuers.length != 0) {
byte[][] issuersBytes;
try {
issuersBytes = encodeIssuerX509Principals(issuers);
} catch (CertificateEncodingException e) {
throw new IOException("Problem encoding principals", e);
}
NativeCrypto.SSL_set_client_CA_list(sslNativePointer, issuersBytes);
}
}
}
// Temporarily use a different timeout for the handshake process
int savedReadTimeoutMilliseconds = getSoTimeout();
int savedWriteTimeoutMilliseconds = getSoWriteTimeout();
if (handshakeTimeoutMilliseconds >= 0) {
setSoTimeout(handshakeTimeoutMilliseconds);
setSoWriteTimeout(handshakeTimeoutMilliseconds);
}
// TLS Channel ID
if (channelIdEnabled) {
if (client) {
// Client-side TLS Channel ID
if (channelIdPrivateKey == null) {
throw new SSLHandshakeException("Invalid TLS channel ID key specified");
}
NativeCrypto.SSL_set1_tls_channel_id(sslNativePointer, channelIdPrivateKey.getPkeyContext());
} else {
// Server-side TLS Channel ID
NativeCrypto.SSL_enable_tls_channel_id(sslNativePointer);
}
}
long sslSessionNativePointer;
try {
sslSessionNativePointer = NativeCrypto.SSL_do_handshake(sslNativePointer, socket.getFileDescriptor$(), this, getSoTimeout(), client, npnProtocols, client ? null : alpnProtocols);
} catch (CertificateException e) {
SSLHandshakeException wrapper = new SSLHandshakeException(e.getMessage());
wrapper.initCause(e);
throw wrapper;
}
byte[] sessionId = NativeCrypto.SSL_SESSION_session_id(sslSessionNativePointer);
if (sessionToReuse != null && Arrays.equals(sessionToReuse.getId(), sessionId)) {
this.sslSession = sessionToReuse;
sslSession.lastAccessedTime = System.currentTimeMillis();
NativeCrypto.SSL_SESSION_free(sslSessionNativePointer);
} else {
if (!enableSessionCreation) {
// Should have been prevented by NativeCrypto.SSL_set_session_creation_enabled
throw new IllegalStateException("SSL Session may not be created");
}
X509Certificate[] localCertificates = createCertChain(NativeCrypto.SSL_get_certificate(sslNativePointer));
X509Certificate[] peerCertificates = createCertChain(NativeCrypto.SSL_get_peer_cert_chain(sslNativePointer));
this.sslSession = new OpenSSLSessionImpl(sslSessionNativePointer, localCertificates, peerCertificates, getPeerHostName(), getPeerPort(), sessionContext);
// if not, putSession later in handshakeCompleted() callback
if (handshakeCompleted) {
sessionContext.putSession(sslSession);
}
}
// Restore the original timeout now that the handshake is complete
if (handshakeTimeoutMilliseconds >= 0) {
setSoTimeout(savedReadTimeoutMilliseconds);
setSoWriteTimeout(savedWriteTimeoutMilliseconds);
}
// if not, notifyHandshakeCompletedListeners later in handshakeCompleted() callback
if (handshakeCompleted) {
notifyHandshakeCompletedListeners();
}
exception = false;
} catch (SSLProtocolException e) {
throw new SSLHandshakeException(e);
} finally {
// on exceptional exit, treat the socket as closed
if (exception) {
close();
}
}
}
use of javax.net.ssl.SSLProtocolException in project robovm by robovm.
the class SSLProtocolExceptionTest method test_Constructor02.
/**
* Test for <code>SSLProtocolException(String)</code> constructor Assertion:
* constructs SSLProtocolException with detail message msg. Parameter
* <code>msg</code> is null.
*/
public void test_Constructor02() {
String msg = null;
SSLProtocolException sslE = new SSLProtocolException(msg);
assertNull("getMessage() must return null.", sslE.getMessage());
assertNull("getCause() must return null", sslE.getCause());
}
use of javax.net.ssl.SSLProtocolException in project robovm by robovm.
the class SSLProtocolExceptionTest method test_Constructor01.
/**
* Test for <code>SSLProtocolException(String)</code> constructor Assertion:
* constructs SSLProtocolException with detail message msg. Parameter
* <code>msg</code> is not null.
*/
public void test_Constructor01() {
SSLProtocolException sslE;
for (int i = 0; i < msgs.length; i++) {
sslE = new SSLProtocolException(msgs[i]);
assertEquals("getMessage() must return: ".concat(msgs[i]), sslE.getMessage(), msgs[i]);
assertNull("getCause() must return null", sslE.getCause());
}
}
use of javax.net.ssl.SSLProtocolException in project XobotOS by xamarin.
the class SSLRecordProtocol method unwrap.
/**
* Retrieves the fragment field of TLSCiphertext, and than
* depending on the established Connection State
* decrypts and decompresses it. The following structure is expected
* on the input at the moment of the call:
*
* struct {
* ContentType type;
* ProtocolVersion version;
* uint16 length;
* select (CipherSpec.cipher_type) {
* case stream: GenericStreamCipher;
* case block: GenericBlockCipher;
* } fragment;
* } TLSCiphertext;
*
* (as specified by RFC 2246, TLS v1 Protocol specification)
*
* In addition this method can recognize SSLv2 hello message which
* are often used to establish the SSL/TLS session.
*
* @throws IOException if some io errors have been occurred
* @throws EndOfSourceException if underlying input stream
* has ran out of data.
* @throws EndOfBufferException if there was not enough data
* to build complete ssl packet.
* @return the type of unwrapped message.
*/
protected int unwrap() throws IOException {
if (logger != null) {
logger.println("SSLRecordProtocol.unwrap: BEGIN [");
}
int type = in.readUint8();
if ((type < ContentType.CHANGE_CIPHER_SPEC) || (type > ContentType.APPLICATION_DATA)) {
if (logger != null) {
logger.println("Non v3.1 message type:" + type);
}
if (type >= 0x80) {
// it is probably SSL v2 client_hello message
// (see SSL v2 spec at:
// http://wp.netscape.com/eng/security/SSL_2.html)
int length = (type & 0x7f) << 8 | in.read();
byte[] fragment = in.read(length);
handshakeProtocol.unwrapSSLv2(fragment);
if (logger != null) {
logger.println("SSLRecordProtocol:unwrap ] END, SSLv2 type");
}
return ContentType.HANDSHAKE;
}
throw new AlertException(AlertProtocol.UNEXPECTED_MESSAGE, new SSLProtocolException("Unexpected message type has been received: " + type));
}
if (logger != null) {
logger.println("Got the message of type: " + type);
}
if (version != null) {
if ((in.read() != version[0]) || (in.read() != version[1])) {
throw new AlertException(AlertProtocol.UNEXPECTED_MESSAGE, new SSLProtocolException("Unexpected message type has been received: " + type));
}
} else {
// just skip the version number
in.skip(2);
}
int length = in.readUint16();
if (logger != null) {
logger.println("TLSCiphertext.fragment[" + length + "]: ...");
}
if (length > MAX_CIPHERED_DATA_LENGTH) {
throw new AlertException(AlertProtocol.RECORD_OVERFLOW, new SSLProtocolException("Received message is too big."));
}
byte[] fragment = in.read(length);
if (logger != null) {
logger.print(fragment);
}
if (activeReadState != null) {
fragment = activeReadState.decrypt((byte) type, fragment);
if (logger != null) {
logger.println("TLSPlaintext.fragment:");
logger.print(fragment);
}
}
if (fragment.length > MAX_DATA_LENGTH) {
throw new AlertException(AlertProtocol.DECOMPRESSION_FAILURE, new SSLProtocolException("Decompressed plain data is too big."));
}
switch(type) {
case ContentType.CHANGE_CIPHER_SPEC:
// notify handshake protocol:
handshakeProtocol.receiveChangeCipherSpec();
setSession(handshakeProtocol.getSession());
// change cipher spec message has been received, so:
if (logger != null) {
logger.println("activeReadState = pendingConnectionState");
}
activeReadState = pendingConnectionState;
break;
case ContentType.ALERT:
alert(fragment[0], fragment[1]);
break;
case ContentType.HANDSHAKE:
handshakeProtocol.unwrap(fragment);
break;
case ContentType.APPLICATION_DATA:
if (logger != null) {
logger.println("TLSCiphertext.unwrap: APP DATA[" + length + "]:");
logger.println(new String(fragment));
}
appData.append(fragment);
break;
default:
throw new AlertException(AlertProtocol.UNEXPECTED_MESSAGE, new SSLProtocolException("Unexpected message type has been received: " + type));
}
if (logger != null) {
logger.println("SSLRecordProtocol:unwrap ] END, type: " + type);
}
return type;
}
use of javax.net.ssl.SSLProtocolException in project XobotOS by xamarin.
the class ConnectionStateSSLv3 method decrypt.
/**
* Retrieves the fragment of the Plaintext structure of
* the specified type from the provided data.
* @throws AlertException if alert was occured.
*/
@Override
protected byte[] decrypt(byte type, byte[] fragment, int offset, int len) {
// plain data of the Generic[Stream|Block]Cipher structure
byte[] data = decCipher.update(fragment, offset, len);
// the 'content' part of the structure
byte[] content;
if (block_size != 0) {
// check padding
int padding_length = data[data.length - 1];
for (int i = 0; i < padding_length; i++) {
if (data[data.length - 2 - i] != padding_length) {
throw new AlertException(AlertProtocol.DECRYPTION_FAILED, new SSLProtocolException("Received message has bad padding"));
}
}
content = new byte[data.length - hash_size - padding_length - 1];
} else {
content = new byte[data.length - hash_size];
}
byte[] mac_value;
mac_material_part[0] = type;
mac_material_part[1] = (byte) ((0x00FF00 & content.length) >> 8);
mac_material_part[2] = (byte) (0x0000FF & content.length);
messageDigest.update(mac_read_secret);
messageDigest.update(pad_1);
messageDigest.update(read_seq_num);
messageDigest.update(mac_material_part);
messageDigest.update(data, 0, content.length);
mac_value = messageDigest.digest();
messageDigest.update(mac_read_secret);
messageDigest.update(pad_2);
messageDigest.update(mac_value);
mac_value = messageDigest.digest();
if (logger != null) {
logger.println("Decrypted:");
logger.print(data);
//logger.println("MAC Material:");
//logger.print(read_seq_num);
//logger.print(mac_material_header);
//logger.print(data, 0, content.length);
logger.println("Expected mac value:");
logger.print(mac_value);
}
// checking the mac value
for (int i = 0; i < hash_size; i++) {
if (mac_value[i] != data[i + content.length]) {
throw new AlertException(AlertProtocol.BAD_RECORD_MAC, new SSLProtocolException("Bad record MAC"));
}
}
System.arraycopy(data, 0, content, 0, content.length);
incSequenceNumber(read_seq_num);
return content;
}
Aggregations