mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-21 19:44:41 +02:00
4873188: Support TLS 1.1
Reviewed-by: wetmore, weijun
This commit is contained in:
parent
4dce0bd6ec
commit
aab01a90d7
30 changed files with 3393 additions and 377 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -30,6 +30,7 @@ import java.net.*;
|
||||||
import javax.net.SocketFactory;
|
import javax.net.SocketFactory;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.*;
|
import java.security.*;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
import sun.security.action.GetPropertyAction;
|
import sun.security.action.GetPropertyAction;
|
||||||
|
|
||||||
|
@ -50,7 +51,8 @@ public abstract class SSLSocketFactory extends SocketFactory
|
||||||
|
|
||||||
static {
|
static {
|
||||||
String s = java.security.AccessController.doPrivileged(
|
String s = java.security.AccessController.doPrivileged(
|
||||||
new GetPropertyAction("javax.net.debug", "")).toLowerCase();
|
new GetPropertyAction("javax.net.debug", "")).toLowerCase(
|
||||||
|
Locale.ENGLISH);
|
||||||
DEBUG = s.contains("all") || s.contains("ssl");
|
DEBUG = s.contains("all") || s.contains("ssl");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -90,8 +90,10 @@ public class TlsKeyMaterialParameterSpec implements AlgorithmParameterSpec {
|
||||||
throw new NullPointerException();
|
throw new NullPointerException();
|
||||||
}
|
}
|
||||||
this.masterSecret = masterSecret;
|
this.masterSecret = masterSecret;
|
||||||
this.majorVersion = TlsMasterSecretParameterSpec.checkVersion(majorVersion);
|
this.majorVersion =
|
||||||
this.minorVersion = TlsMasterSecretParameterSpec.checkVersion(minorVersion);
|
TlsMasterSecretParameterSpec.checkVersion(majorVersion);
|
||||||
|
this.minorVersion =
|
||||||
|
TlsMasterSecretParameterSpec.checkVersion(minorVersion);
|
||||||
this.clientRandom = clientRandom.clone();
|
this.clientRandom = clientRandom.clone();
|
||||||
this.serverRandom = serverRandom.clone();
|
this.serverRandom = serverRandom.clone();
|
||||||
this.cipherAlgorithm = cipherAlgorithm;
|
this.cipherAlgorithm = cipherAlgorithm;
|
||||||
|
@ -172,20 +174,36 @@ public class TlsKeyMaterialParameterSpec implements AlgorithmParameterSpec {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the length in bytes of the expanded encryption key to be generated.
|
* Returns the length in bytes of the expanded encryption key to be
|
||||||
|
* generated. Returns zero if the expanded encryption key is not
|
||||||
|
* supposed to be generated.
|
||||||
*
|
*
|
||||||
* @return the length in bytes of the expanded encryption key to be generated.
|
* @return the length in bytes of the expanded encryption key to be
|
||||||
|
* generated.
|
||||||
*/
|
*/
|
||||||
public int getExpandedCipherKeyLength() {
|
public int getExpandedCipherKeyLength() {
|
||||||
|
// TLS v1.1 disables the exportable weak cipher suites.
|
||||||
|
if (majorVersion >= 0x03 && minorVersion >= 0x02) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return expandedCipherKeyLength;
|
return expandedCipherKeyLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the length in bytes of the initialization vector to be generated.
|
* Returns the length in bytes of the initialization vector to be
|
||||||
|
* generated. Returns zero if the initialization vector is not
|
||||||
|
* supposed to be generated.
|
||||||
*
|
*
|
||||||
* @return the length in bytes of the initialization vector to be generated.
|
* @return the length in bytes of the initialization vector to be
|
||||||
|
* generated.
|
||||||
*/
|
*/
|
||||||
public int getIvLength() {
|
public int getIvLength() {
|
||||||
|
// TLS v1.1 or later uses an explicit IV to protect against
|
||||||
|
// the CBC attacks.
|
||||||
|
if (majorVersion >= 0x03 && minorVersion >= 0x02) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return ivLength;
|
return ivLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -67,7 +67,8 @@ public class TlsMasterSecretParameterSpec implements AlgorithmParameterSpec {
|
||||||
* negative or larger than 255
|
* negative or larger than 255
|
||||||
*/
|
*/
|
||||||
public TlsMasterSecretParameterSpec(SecretKey premasterSecret,
|
public TlsMasterSecretParameterSpec(SecretKey premasterSecret,
|
||||||
int majorVersion, int minorVersion, byte[] clientRandom, byte[] serverRandom) {
|
int majorVersion, int minorVersion,
|
||||||
|
byte[] clientRandom, byte[] serverRandom) {
|
||||||
if (premasterSecret == null) {
|
if (premasterSecret == null) {
|
||||||
throw new NullPointerException("premasterSecret must not be null");
|
throw new NullPointerException("premasterSecret must not be null");
|
||||||
}
|
}
|
||||||
|
@ -80,7 +81,8 @@ public class TlsMasterSecretParameterSpec implements AlgorithmParameterSpec {
|
||||||
|
|
||||||
static int checkVersion(int version) {
|
static int checkVersion(int version) {
|
||||||
if ((version < 0) || (version > 255)) {
|
if ((version < 0) || (version > 255)) {
|
||||||
throw new IllegalArgumentException("Version must be between 0 and 255");
|
throw new IllegalArgumentException(
|
||||||
|
"Version must be between 0 and 255");
|
||||||
}
|
}
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -28,6 +28,7 @@ package sun.security.ssl;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
|
||||||
import java.security.*;
|
import java.security.*;
|
||||||
import javax.crypto.*;
|
import javax.crypto.*;
|
||||||
|
@ -50,6 +51,37 @@ import sun.misc.HexDumpEncoder;
|
||||||
* Individual instances are obtained by calling the static method
|
* Individual instances are obtained by calling the static method
|
||||||
* newCipherBox(), which should only be invoked by BulkCipher.newCipher().
|
* newCipherBox(), which should only be invoked by BulkCipher.newCipher().
|
||||||
*
|
*
|
||||||
|
* In RFC 2246, with bock ciphers in CBC mode, the Initialization
|
||||||
|
* Vector (IV) for the first record is generated with the other keys
|
||||||
|
* and secrets when the security parameters are set. The IV for
|
||||||
|
* subsequent records is the last ciphertext block from the previous
|
||||||
|
* record.
|
||||||
|
*
|
||||||
|
* In RFC 4346, the implicit Initialization Vector (IV) is replaced
|
||||||
|
* with an explicit IV to protect against CBC attacks. RFC 4346
|
||||||
|
* recommends two algorithms used to generated the per-record IV.
|
||||||
|
* The implementation uses the algorithm (2)(b), as described at
|
||||||
|
* section 6.2.3.2 of RFC 4346.
|
||||||
|
*
|
||||||
|
* The usage of IV in CBC block cipher can be illustrated in
|
||||||
|
* the following diagrams.
|
||||||
|
*
|
||||||
|
* (random)
|
||||||
|
* R P1 IV C1
|
||||||
|
* | | | |
|
||||||
|
* SIV---+ |-----+ |-... |----- |------
|
||||||
|
* | | | | | | | |
|
||||||
|
* +----+ | +----+ | +----+ | +----+ |
|
||||||
|
* | Ek | | + Ek + | | Dk | | | Dk | |
|
||||||
|
* +----+ | +----+ | +----+ | +----+ |
|
||||||
|
* | | | | | | | |
|
||||||
|
* |----| |----| SIV--+ |----| |-...
|
||||||
|
* | | | |
|
||||||
|
* IV C1 R P1
|
||||||
|
* (discard)
|
||||||
|
*
|
||||||
|
* CBC Encryption CBC Decryption
|
||||||
|
*
|
||||||
* NOTE that any ciphering involved in key exchange (e.g. with RSA) is
|
* NOTE that any ciphering involved in key exchange (e.g. with RSA) is
|
||||||
* handled separately.
|
* handled separately.
|
||||||
*
|
*
|
||||||
|
@ -75,6 +107,21 @@ final class CipherBox {
|
||||||
*/
|
*/
|
||||||
private int blockSize;
|
private int blockSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* secure random
|
||||||
|
*/
|
||||||
|
private SecureRandom random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fixed masks of various block size, as the initial decryption IVs
|
||||||
|
* for TLS 1.1 or later.
|
||||||
|
*
|
||||||
|
* For performance, we do not use random IVs. As the initial decryption
|
||||||
|
* IVs will be discarded by TLS decryption processes, so the fixed masks
|
||||||
|
* do not hurt cryptographic strength.
|
||||||
|
*/
|
||||||
|
private static Hashtable<Integer, IvParameterSpec> masks;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NULL cipherbox. Identity operation, no encryption.
|
* NULL cipherbox. Identity operation, no encryption.
|
||||||
*/
|
*/
|
||||||
|
@ -90,14 +137,37 @@ final class CipherBox {
|
||||||
* implementation could be found.
|
* implementation could be found.
|
||||||
*/
|
*/
|
||||||
private CipherBox(ProtocolVersion protocolVersion, BulkCipher bulkCipher,
|
private CipherBox(ProtocolVersion protocolVersion, BulkCipher bulkCipher,
|
||||||
SecretKey key, IvParameterSpec iv, boolean encrypt)
|
SecretKey key, IvParameterSpec iv, SecureRandom random,
|
||||||
throws NoSuchAlgorithmException {
|
boolean encrypt) throws NoSuchAlgorithmException {
|
||||||
try {
|
try {
|
||||||
this.protocolVersion = protocolVersion;
|
this.protocolVersion = protocolVersion;
|
||||||
this.cipher = JsseJce.getCipher(bulkCipher.transformation);
|
this.cipher = JsseJce.getCipher(bulkCipher.transformation);
|
||||||
int mode = encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE;
|
int mode = encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE;
|
||||||
cipher.init(mode, key, iv);
|
|
||||||
// do not call getBlockSize until after init()
|
if (random == null) {
|
||||||
|
random = JsseJce.getSecureRandom();
|
||||||
|
}
|
||||||
|
this.random = random;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RFC 4346 recommends two algorithms used to generated the
|
||||||
|
* per-record IV. The implementation uses the algorithm (2)(b),
|
||||||
|
* as described at section 6.2.3.2 of RFC 4346.
|
||||||
|
*
|
||||||
|
* As we don't care about the initial IV value for TLS 1.1 or
|
||||||
|
* later, so if the "iv" parameter is null, we use the default
|
||||||
|
* value generated by Cipher.init() for encryption, and a fixed
|
||||||
|
* mask for decryption.
|
||||||
|
*/
|
||||||
|
if (iv == null && bulkCipher.ivSize != 0 &&
|
||||||
|
mode == Cipher.DECRYPT_MODE &&
|
||||||
|
protocolVersion.v >= ProtocolVersion.TLS11.v) {
|
||||||
|
iv = getFixedMask(bulkCipher.ivSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
cipher.init(mode, key, iv, random);
|
||||||
|
|
||||||
|
// Do not call getBlockSize until after init()
|
||||||
// otherwise we would disrupt JCE delayed provider selection
|
// otherwise we would disrupt JCE delayed provider selection
|
||||||
blockSize = cipher.getBlockSize();
|
blockSize = cipher.getBlockSize();
|
||||||
// some providers implement getBlockSize() incorrectly
|
// some providers implement getBlockSize() incorrectly
|
||||||
|
@ -119,18 +189,36 @@ final class CipherBox {
|
||||||
* Factory method to obtain a new CipherBox object.
|
* Factory method to obtain a new CipherBox object.
|
||||||
*/
|
*/
|
||||||
static CipherBox newCipherBox(ProtocolVersion version, BulkCipher cipher,
|
static CipherBox newCipherBox(ProtocolVersion version, BulkCipher cipher,
|
||||||
SecretKey key, IvParameterSpec iv, boolean encrypt)
|
SecretKey key, IvParameterSpec iv, SecureRandom random,
|
||||||
throws NoSuchAlgorithmException {
|
boolean encrypt) throws NoSuchAlgorithmException {
|
||||||
if (cipher.allowed == false) {
|
if (cipher.allowed == false) {
|
||||||
throw new NoSuchAlgorithmException("Unsupported cipher " + cipher);
|
throw new NoSuchAlgorithmException("Unsupported cipher " + cipher);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cipher == B_NULL) {
|
if (cipher == B_NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
} else {
|
} else {
|
||||||
return new CipherBox(version, cipher, key, iv, encrypt);
|
return new CipherBox(version, cipher, key, iv, random, encrypt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get a fixed mask, as the initial decryption IVs for TLS 1.1 or later.
|
||||||
|
*/
|
||||||
|
private static IvParameterSpec getFixedMask(int ivSize) {
|
||||||
|
if (masks == null) {
|
||||||
|
masks = new Hashtable<Integer, IvParameterSpec>(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
IvParameterSpec iv = masks.get(ivSize);
|
||||||
|
if (iv == null) {
|
||||||
|
iv = new IvParameterSpec(new byte[ivSize]);
|
||||||
|
masks.put(ivSize, iv);
|
||||||
|
}
|
||||||
|
|
||||||
|
return iv;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Encrypts a block of data, returning the size of the
|
* Encrypts a block of data, returning the size of the
|
||||||
* resulting block.
|
* resulting block.
|
||||||
|
@ -139,8 +227,26 @@ final class CipherBox {
|
||||||
if (cipher == null) {
|
if (cipher == null) {
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (blockSize != 0) {
|
if (blockSize != 0) {
|
||||||
|
// TLSv1.1 needs a IV block
|
||||||
|
if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
|
||||||
|
// generate a random number
|
||||||
|
byte[] prefix = new byte[blockSize];
|
||||||
|
random.nextBytes(prefix);
|
||||||
|
|
||||||
|
// move forward the plaintext
|
||||||
|
System.arraycopy(buf, offset,
|
||||||
|
buf, offset + prefix.length, len);
|
||||||
|
|
||||||
|
// prefix the plaintext
|
||||||
|
System.arraycopy(prefix, 0,
|
||||||
|
buf, offset, prefix.length);
|
||||||
|
|
||||||
|
len += prefix.length;
|
||||||
|
}
|
||||||
|
|
||||||
len = addPadding(buf, offset, len, blockSize);
|
len = addPadding(buf, offset, len, blockSize);
|
||||||
}
|
}
|
||||||
if (debug != null && Debug.isOn("plaintext")) {
|
if (debug != null && Debug.isOn("plaintext")) {
|
||||||
|
@ -189,6 +295,34 @@ final class CipherBox {
|
||||||
int pos = bb.position();
|
int pos = bb.position();
|
||||||
|
|
||||||
if (blockSize != 0) {
|
if (blockSize != 0) {
|
||||||
|
// TLSv1.1 needs a IV block
|
||||||
|
if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
|
||||||
|
// generate a random number
|
||||||
|
byte[] prefix = new byte[blockSize];
|
||||||
|
random.nextBytes(prefix);
|
||||||
|
|
||||||
|
// move forward the plaintext
|
||||||
|
byte[] buf = null;
|
||||||
|
int limit = bb.limit();
|
||||||
|
if (bb.hasArray()) {
|
||||||
|
buf = bb.array();
|
||||||
|
System.arraycopy(buf, pos,
|
||||||
|
buf, pos + prefix.length, limit - pos);
|
||||||
|
bb.limit(limit + prefix.length);
|
||||||
|
} else {
|
||||||
|
buf = new byte[limit - pos];
|
||||||
|
bb.get(buf, 0, limit - pos);
|
||||||
|
bb.position(pos + prefix.length);
|
||||||
|
bb.limit(limit + prefix.length);
|
||||||
|
bb.put(buf);
|
||||||
|
}
|
||||||
|
bb.position(pos);
|
||||||
|
|
||||||
|
// prefix the plaintext
|
||||||
|
bb.put(prefix);
|
||||||
|
bb.position(pos);
|
||||||
|
}
|
||||||
|
|
||||||
// addPadding adjusts pos/limit
|
// addPadding adjusts pos/limit
|
||||||
len = addPadding(bb, blockSize);
|
len = addPadding(bb, blockSize);
|
||||||
bb.position(pos);
|
bb.position(pos);
|
||||||
|
@ -236,11 +370,25 @@ final class CipherBox {
|
||||||
/*
|
/*
|
||||||
* Decrypts a block of data, returning the size of the
|
* Decrypts a block of data, returning the size of the
|
||||||
* resulting block if padding was required.
|
* resulting block if padding was required.
|
||||||
|
*
|
||||||
|
* For SSLv3 and TLSv1.0, with block ciphers in CBC mode the
|
||||||
|
* Initialization Vector (IV) for the first record is generated by
|
||||||
|
* the handshake protocol, the IV for subsequent records is the
|
||||||
|
* last ciphertext block from the previous record.
|
||||||
|
*
|
||||||
|
* From TLSv1.1, the implicit IV is replaced with an explicit IV to
|
||||||
|
* protect against CBC attacks.
|
||||||
|
*
|
||||||
|
* Differentiating between bad_record_mac and decryption_failed alerts
|
||||||
|
* may permit certain attacks against CBC mode. It is preferable to
|
||||||
|
* uniformly use the bad_record_mac alert to hide the specific type of
|
||||||
|
* the error.
|
||||||
*/
|
*/
|
||||||
int decrypt(byte[] buf, int offset, int len) throws BadPaddingException {
|
int decrypt(byte[] buf, int offset, int len) throws BadPaddingException {
|
||||||
if (cipher == null) {
|
if (cipher == null) {
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
int newLen = cipher.update(buf, offset, len, buf, offset);
|
int newLen = cipher.update(buf, offset, len, buf, offset);
|
||||||
if (newLen != len) {
|
if (newLen != len) {
|
||||||
|
@ -263,6 +411,18 @@ final class CipherBox {
|
||||||
if (blockSize != 0) {
|
if (blockSize != 0) {
|
||||||
newLen = removePadding(buf, offset, newLen,
|
newLen = removePadding(buf, offset, newLen,
|
||||||
blockSize, protocolVersion);
|
blockSize, protocolVersion);
|
||||||
|
|
||||||
|
if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
|
||||||
|
if (newLen < blockSize) {
|
||||||
|
throw new BadPaddingException("invalid explicit IV");
|
||||||
|
}
|
||||||
|
|
||||||
|
// discards the first cipher block, the IV component.
|
||||||
|
System.arraycopy(buf, offset + blockSize,
|
||||||
|
buf, offset, newLen - blockSize);
|
||||||
|
|
||||||
|
newLen -= blockSize;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return newLen;
|
return newLen;
|
||||||
} catch (ShortBufferException e) {
|
} catch (ShortBufferException e) {
|
||||||
|
@ -277,6 +437,8 @@ final class CipherBox {
|
||||||
* point to the end of the decrypted/depadded data. The initial
|
* point to the end of the decrypted/depadded data. The initial
|
||||||
* limit and new limit may be different, given we may
|
* limit and new limit may be different, given we may
|
||||||
* have stripped off some padding bytes.
|
* have stripped off some padding bytes.
|
||||||
|
*
|
||||||
|
* @see decrypt(byte[], int, int)
|
||||||
*/
|
*/
|
||||||
int decrypt(ByteBuffer bb) throws BadPaddingException {
|
int decrypt(ByteBuffer bb) throws BadPaddingException {
|
||||||
|
|
||||||
|
@ -292,7 +454,6 @@ final class CipherBox {
|
||||||
* Decrypt "in-place".
|
* Decrypt "in-place".
|
||||||
*/
|
*/
|
||||||
int pos = bb.position();
|
int pos = bb.position();
|
||||||
|
|
||||||
ByteBuffer dup = bb.duplicate();
|
ByteBuffer dup = bb.duplicate();
|
||||||
int newLen = cipher.update(dup, bb);
|
int newLen = cipher.update(dup, bb);
|
||||||
if (newLen != len) {
|
if (newLen != len) {
|
||||||
|
@ -320,6 +481,33 @@ final class CipherBox {
|
||||||
if (blockSize != 0) {
|
if (blockSize != 0) {
|
||||||
bb.position(pos);
|
bb.position(pos);
|
||||||
newLen = removePadding(bb, blockSize, protocolVersion);
|
newLen = removePadding(bb, blockSize, protocolVersion);
|
||||||
|
|
||||||
|
if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
|
||||||
|
if (newLen < blockSize) {
|
||||||
|
throw new BadPaddingException("invalid explicit IV");
|
||||||
|
}
|
||||||
|
|
||||||
|
// discards the first cipher block, the IV component.
|
||||||
|
byte[] buf = null;
|
||||||
|
int limit = bb.limit();
|
||||||
|
if (bb.hasArray()) {
|
||||||
|
buf = bb.array();
|
||||||
|
System.arraycopy(buf, pos + blockSize,
|
||||||
|
buf, pos, limit - pos - blockSize);
|
||||||
|
bb.limit(limit - blockSize);
|
||||||
|
} else {
|
||||||
|
buf = new byte[limit - pos - blockSize];
|
||||||
|
bb.position(pos + blockSize);
|
||||||
|
bb.get(buf);
|
||||||
|
bb.position(pos);
|
||||||
|
bb.put(buf);
|
||||||
|
bb.limit(limit - blockSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset the position to the end of the decrypted data
|
||||||
|
limit = bb.limit();
|
||||||
|
bb.position(limit);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return newLen;
|
return newLen;
|
||||||
} catch (ShortBufferException e) {
|
} catch (ShortBufferException e) {
|
||||||
|
|
|
@ -30,6 +30,7 @@ import java.util.*;
|
||||||
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
|
||||||
import javax.crypto.SecretKey;
|
import javax.crypto.SecretKey;
|
||||||
import javax.crypto.spec.IvParameterSpec;
|
import javax.crypto.spec.IvParameterSpec;
|
||||||
|
@ -112,8 +113,12 @@ final class CipherSuite implements Comparable {
|
||||||
// true iff implemented and enabled at compile time
|
// true iff implemented and enabled at compile time
|
||||||
final boolean allowed;
|
final boolean allowed;
|
||||||
|
|
||||||
|
// obsoleted since protocol version
|
||||||
|
final int obsoleted;
|
||||||
|
|
||||||
private CipherSuite(String name, int id, int priority,
|
private CipherSuite(String name, int id, int priority,
|
||||||
KeyExchange keyExchange, BulkCipher cipher, boolean allowed) {
|
KeyExchange keyExchange, BulkCipher cipher,
|
||||||
|
boolean allowed, int obsoleted) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.priority = priority;
|
this.priority = priority;
|
||||||
|
@ -136,6 +141,7 @@ final class CipherSuite implements Comparable {
|
||||||
allowed &= keyExchange.allowed;
|
allowed &= keyExchange.allowed;
|
||||||
allowed &= cipher.allowed;
|
allowed &= cipher.allowed;
|
||||||
this.allowed = allowed;
|
this.allowed = allowed;
|
||||||
|
this.obsoleted = obsoleted;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CipherSuite(String name, int id) {
|
private CipherSuite(String name, int id) {
|
||||||
|
@ -148,6 +154,7 @@ final class CipherSuite implements Comparable {
|
||||||
this.cipher = null;
|
this.cipher = null;
|
||||||
this.macAlg = null;
|
this.macAlg = null;
|
||||||
this.exportable = false;
|
this.exportable = false;
|
||||||
|
this.obsoleted = ProtocolVersion.LIMIT_MAX_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -197,10 +204,12 @@ final class CipherSuite implements Comparable {
|
||||||
if (s == null) {
|
if (s == null) {
|
||||||
throw new IllegalArgumentException("Name must not be null");
|
throw new IllegalArgumentException("Name must not be null");
|
||||||
}
|
}
|
||||||
|
|
||||||
CipherSuite c = nameMap.get(s);
|
CipherSuite c = nameMap.get(s);
|
||||||
if ((c == null) || (c.allowed == false)) {
|
if ((c == null) || (c.allowed == false)) {
|
||||||
throw new IllegalArgumentException("Unsupported ciphersuite " + s);
|
throw new IllegalArgumentException("Unsupported ciphersuite " + s);
|
||||||
}
|
}
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,9 +237,11 @@ final class CipherSuite implements Comparable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void add(String name, int id, int priority,
|
private static void add(String name, int id, int priority,
|
||||||
KeyExchange keyExchange, BulkCipher cipher, boolean allowed) {
|
KeyExchange keyExchange, BulkCipher cipher,
|
||||||
|
boolean allowed, int obsoleted) {
|
||||||
|
|
||||||
CipherSuite c = new CipherSuite(name, id, priority, keyExchange,
|
CipherSuite c = new CipherSuite(name, id, priority, keyExchange,
|
||||||
cipher, allowed);
|
cipher, allowed, obsoleted);
|
||||||
if (idMap.put(id, c) != null) {
|
if (idMap.put(id, c) != null) {
|
||||||
throw new RuntimeException("Duplicate ciphersuite definition: "
|
throw new RuntimeException("Duplicate ciphersuite definition: "
|
||||||
+ id + ", " + name);
|
+ id + ", " + name);
|
||||||
|
@ -243,6 +254,12 @@ final class CipherSuite implements Comparable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void add(String name, int id, int priority,
|
||||||
|
KeyExchange keyExchange, BulkCipher cipher, boolean allowed) {
|
||||||
|
add(name, id, priority, keyExchange,
|
||||||
|
cipher, allowed, ProtocolVersion.LIMIT_MAX_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
private static void add(String name, int id) {
|
private static void add(String name, int id) {
|
||||||
CipherSuite c = new CipherSuite(name, id);
|
CipherSuite c = new CipherSuite(name, id);
|
||||||
if (idMap.put(id, c) != null) {
|
if (idMap.put(id, c) != null) {
|
||||||
|
@ -380,10 +397,11 @@ final class CipherSuite implements Comparable {
|
||||||
*
|
*
|
||||||
* @exception NoSuchAlgorithmException if anything goes wrong
|
* @exception NoSuchAlgorithmException if anything goes wrong
|
||||||
*/
|
*/
|
||||||
CipherBox newCipher(ProtocolVersion version,
|
CipherBox newCipher(ProtocolVersion version, SecretKey key,
|
||||||
SecretKey key, IvParameterSpec iv,
|
IvParameterSpec iv, SecureRandom random,
|
||||||
boolean encrypt) throws NoSuchAlgorithmException {
|
boolean encrypt) throws NoSuchAlgorithmException {
|
||||||
return CipherBox.newCipherBox(version, this, key, iv, encrypt);
|
return CipherBox.newCipherBox(version, this,
|
||||||
|
key, iv, random, encrypt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -402,6 +420,7 @@ final class CipherSuite implements Comparable {
|
||||||
if (this == B_AES_256) {
|
if (this == B_AES_256) {
|
||||||
return isAvailable(this);
|
return isAvailable(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// always available
|
// always available
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -421,7 +440,8 @@ final class CipherSuite implements Comparable {
|
||||||
(new byte[cipher.expandedKeySize], cipher.algorithm);
|
(new byte[cipher.expandedKeySize], cipher.algorithm);
|
||||||
IvParameterSpec iv =
|
IvParameterSpec iv =
|
||||||
new IvParameterSpec(new byte[cipher.ivSize]);
|
new IvParameterSpec(new byte[cipher.ivSize]);
|
||||||
cipher.newCipher(ProtocolVersion.DEFAULT, key, iv, true);
|
cipher.newCipher(ProtocolVersion.DEFAULT,
|
||||||
|
key, iv, null, true);
|
||||||
b = Boolean.TRUE;
|
b = Boolean.TRUE;
|
||||||
} catch (NoSuchAlgorithmException e) {
|
} catch (NoSuchAlgorithmException e) {
|
||||||
b = Boolean.FALSE;
|
b = Boolean.FALSE;
|
||||||
|
@ -509,6 +529,239 @@ final class CipherSuite implements Comparable {
|
||||||
// N: ciphersuites only allowed if we are not in FIPS mode
|
// N: ciphersuites only allowed if we are not in FIPS mode
|
||||||
final boolean N = (SunJSSE.isFIPS() == false);
|
final boolean N = (SunJSSE.isFIPS() == false);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TLS Cipher Suite Registry, as of August 2010.
|
||||||
|
*
|
||||||
|
* http://www.iana.org/assignments/tls-parameters/tls-parameters.xml
|
||||||
|
*
|
||||||
|
* Range Registration Procedures Notes
|
||||||
|
* 000-191 Standards Action Refers to value of first byte
|
||||||
|
* 192-254 Specification Required Refers to value of first byte
|
||||||
|
* 255 Reserved for Private Use Refers to value of first byte
|
||||||
|
*
|
||||||
|
* Value Description Reference
|
||||||
|
* 0x00,0x00 TLS_NULL_WITH_NULL_NULL [RFC5246]
|
||||||
|
* 0x00,0x01 TLS_RSA_WITH_NULL_MD5 [RFC5246]
|
||||||
|
* 0x00,0x02 TLS_RSA_WITH_NULL_SHA [RFC5246]
|
||||||
|
* 0x00,0x03 TLS_RSA_EXPORT_WITH_RC4_40_MD5 [RFC4346]
|
||||||
|
* 0x00,0x04 TLS_RSA_WITH_RC4_128_MD5 [RFC5246]
|
||||||
|
* 0x00,0x05 TLS_RSA_WITH_RC4_128_SHA [RFC5246]
|
||||||
|
* 0x00,0x06 TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 [RFC4346]
|
||||||
|
* 0x00,0x07 TLS_RSA_WITH_IDEA_CBC_SHA [RFC5469]
|
||||||
|
* 0x00,0x08 TLS_RSA_EXPORT_WITH_DES40_CBC_SHA [RFC4346]
|
||||||
|
* 0x00,0x09 TLS_RSA_WITH_DES_CBC_SHA [RFC5469]
|
||||||
|
* 0x00,0x0A TLS_RSA_WITH_3DES_EDE_CBC_SHA [RFC5246]
|
||||||
|
* 0x00,0x0B TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA [RFC4346]
|
||||||
|
* 0x00,0x0C TLS_DH_DSS_WITH_DES_CBC_SHA [RFC5469]
|
||||||
|
* 0x00,0x0D TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA [RFC5246]
|
||||||
|
* 0x00,0x0E TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA [RFC4346]
|
||||||
|
* 0x00,0x0F TLS_DH_RSA_WITH_DES_CBC_SHA [RFC5469]
|
||||||
|
* 0x00,0x10 TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA [RFC5246]
|
||||||
|
* 0x00,0x11 TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA [RFC4346]
|
||||||
|
* 0x00,0x12 TLS_DHE_DSS_WITH_DES_CBC_SHA [RFC5469]
|
||||||
|
* 0x00,0x13 TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA [RFC5246]
|
||||||
|
* 0x00,0x14 TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA [RFC4346]
|
||||||
|
* 0x00,0x15 TLS_DHE_RSA_WITH_DES_CBC_SHA [RFC5469]
|
||||||
|
* 0x00,0x16 TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA [RFC5246]
|
||||||
|
* 0x00,0x17 TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 [RFC4346]
|
||||||
|
* 0x00,0x18 TLS_DH_anon_WITH_RC4_128_MD5 [RFC5246]
|
||||||
|
* 0x00,0x19 TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA [RFC4346]
|
||||||
|
* 0x00,0x1A TLS_DH_anon_WITH_DES_CBC_SHA [RFC5469]
|
||||||
|
* 0x00,0x1B TLS_DH_anon_WITH_3DES_EDE_CBC_SHA [RFC5246]
|
||||||
|
* 0x00,0x1C-1D Reserved to avoid conflicts with SSLv3 [RFC5246]
|
||||||
|
* 0x00,0x1E TLS_KRB5_WITH_DES_CBC_SHA [RFC2712]
|
||||||
|
* 0x00,0x1F TLS_KRB5_WITH_3DES_EDE_CBC_SHA [RFC2712]
|
||||||
|
* 0x00,0x20 TLS_KRB5_WITH_RC4_128_SHA [RFC2712]
|
||||||
|
* 0x00,0x21 TLS_KRB5_WITH_IDEA_CBC_SHA [RFC2712]
|
||||||
|
* 0x00,0x22 TLS_KRB5_WITH_DES_CBC_MD5 [RFC2712]
|
||||||
|
* 0x00,0x23 TLS_KRB5_WITH_3DES_EDE_CBC_MD5 [RFC2712]
|
||||||
|
* 0x00,0x24 TLS_KRB5_WITH_RC4_128_MD5 [RFC2712]
|
||||||
|
* 0x00,0x25 TLS_KRB5_WITH_IDEA_CBC_MD5 [RFC2712]
|
||||||
|
* 0x00,0x26 TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA [RFC2712]
|
||||||
|
* 0x00,0x27 TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA [RFC2712]
|
||||||
|
* 0x00,0x28 TLS_KRB5_EXPORT_WITH_RC4_40_SHA [RFC2712]
|
||||||
|
* 0x00,0x29 TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5 [RFC2712]
|
||||||
|
* 0x00,0x2A TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5 [RFC2712]
|
||||||
|
* 0x00,0x2B TLS_KRB5_EXPORT_WITH_RC4_40_MD5 [RFC2712]
|
||||||
|
* 0x00,0x2C TLS_PSK_WITH_NULL_SHA [RFC4785]
|
||||||
|
* 0x00,0x2D TLS_DHE_PSK_WITH_NULL_SHA [RFC4785]
|
||||||
|
* 0x00,0x2E TLS_RSA_PSK_WITH_NULL_SHA [RFC4785]
|
||||||
|
* 0x00,0x2F TLS_RSA_WITH_AES_128_CBC_SHA [RFC5246]
|
||||||
|
* 0x00,0x30 TLS_DH_DSS_WITH_AES_128_CBC_SHA [RFC5246]
|
||||||
|
* 0x00,0x31 TLS_DH_RSA_WITH_AES_128_CBC_SHA [RFC5246]
|
||||||
|
* 0x00,0x32 TLS_DHE_DSS_WITH_AES_128_CBC_SHA [RFC5246]
|
||||||
|
* 0x00,0x33 TLS_DHE_RSA_WITH_AES_128_CBC_SHA [RFC5246]
|
||||||
|
* 0x00,0x34 TLS_DH_anon_WITH_AES_128_CBC_SHA [RFC5246]
|
||||||
|
* 0x00,0x35 TLS_RSA_WITH_AES_256_CBC_SHA [RFC5246]
|
||||||
|
* 0x00,0x36 TLS_DH_DSS_WITH_AES_256_CBC_SHA [RFC5246]
|
||||||
|
* 0x00,0x37 TLS_DH_RSA_WITH_AES_256_CBC_SHA [RFC5246]
|
||||||
|
* 0x00,0x38 TLS_DHE_DSS_WITH_AES_256_CBC_SHA [RFC5246]
|
||||||
|
* 0x00,0x39 TLS_DHE_RSA_WITH_AES_256_CBC_SHA [RFC5246]
|
||||||
|
* 0x00,0x3A TLS_DH_anon_WITH_AES_256_CBC_SHA [RFC5246]
|
||||||
|
* 0x00,0x3B TLS_RSA_WITH_NULL_SHA256 [RFC5246]
|
||||||
|
* 0x00,0x3C TLS_RSA_WITH_AES_128_CBC_SHA256 [RFC5246]
|
||||||
|
* 0x00,0x3D TLS_RSA_WITH_AES_256_CBC_SHA256 [RFC5246]
|
||||||
|
* 0x00,0x3E TLS_DH_DSS_WITH_AES_128_CBC_SHA256 [RFC5246]
|
||||||
|
* 0x00,0x3F TLS_DH_RSA_WITH_AES_128_CBC_SHA256 [RFC5246]
|
||||||
|
* 0x00,0x40 TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 [RFC5246]
|
||||||
|
* 0x00,0x41 TLS_RSA_WITH_CAMELLIA_128_CBC_SHA [RFC5932]
|
||||||
|
* 0x00,0x42 TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA [RFC5932]
|
||||||
|
* 0x00,0x43 TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA [RFC5932]
|
||||||
|
* 0x00,0x44 TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA [RFC5932]
|
||||||
|
* 0x00,0x45 TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA [RFC5932]
|
||||||
|
* 0x00,0x46 TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA [RFC5932]
|
||||||
|
* 0x00,0x47-4F Reserved to avoid conflicts with
|
||||||
|
* deployed implementations [Pasi_Eronen]
|
||||||
|
* 0x00,0x50-58 Reserved to avoid conflicts [Pasi Eronen]
|
||||||
|
* 0x00,0x59-5C Reserved to avoid conflicts with
|
||||||
|
* deployed implementations [Pasi_Eronen]
|
||||||
|
* 0x00,0x5D-5F Unassigned
|
||||||
|
* 0x00,0x60-66 Reserved to avoid conflicts with widely
|
||||||
|
* deployed implementations [Pasi_Eronen]
|
||||||
|
* 0x00,0x67 TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 [RFC5246]
|
||||||
|
* 0x00,0x68 TLS_DH_DSS_WITH_AES_256_CBC_SHA256 [RFC5246]
|
||||||
|
* 0x00,0x69 TLS_DH_RSA_WITH_AES_256_CBC_SHA256 [RFC5246]
|
||||||
|
* 0x00,0x6A TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 [RFC5246]
|
||||||
|
* 0x00,0x6B TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 [RFC5246]
|
||||||
|
* 0x00,0x6C TLS_DH_anon_WITH_AES_128_CBC_SHA256 [RFC5246]
|
||||||
|
* 0x00,0x6D TLS_DH_anon_WITH_AES_256_CBC_SHA256 [RFC5246]
|
||||||
|
* 0x00,0x6E-83 Unassigned
|
||||||
|
* 0x00,0x84 TLS_RSA_WITH_CAMELLIA_256_CBC_SHA [RFC5932]
|
||||||
|
* 0x00,0x85 TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA [RFC5932]
|
||||||
|
* 0x00,0x86 TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA [RFC5932]
|
||||||
|
* 0x00,0x87 TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA [RFC5932]
|
||||||
|
* 0x00,0x88 TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA [RFC5932]
|
||||||
|
* 0x00,0x89 TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA [RFC5932]
|
||||||
|
* 0x00,0x8A TLS_PSK_WITH_RC4_128_SHA [RFC4279]
|
||||||
|
* 0x00,0x8B TLS_PSK_WITH_3DES_EDE_CBC_SHA [RFC4279]
|
||||||
|
* 0x00,0x8C TLS_PSK_WITH_AES_128_CBC_SHA [RFC4279]
|
||||||
|
* 0x00,0x8D TLS_PSK_WITH_AES_256_CBC_SHA [RFC4279]
|
||||||
|
* 0x00,0x8E TLS_DHE_PSK_WITH_RC4_128_SHA [RFC4279]
|
||||||
|
* 0x00,0x8F TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA [RFC4279]
|
||||||
|
* 0x00,0x90 TLS_DHE_PSK_WITH_AES_128_CBC_SHA [RFC4279]
|
||||||
|
* 0x00,0x91 TLS_DHE_PSK_WITH_AES_256_CBC_SHA [RFC4279]
|
||||||
|
* 0x00,0x92 TLS_RSA_PSK_WITH_RC4_128_SHA [RFC4279]
|
||||||
|
* 0x00,0x93 TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA [RFC4279]
|
||||||
|
* 0x00,0x94 TLS_RSA_PSK_WITH_AES_128_CBC_SHA [RFC4279]
|
||||||
|
* 0x00,0x95 TLS_RSA_PSK_WITH_AES_256_CBC_SHA [RFC4279]
|
||||||
|
* 0x00,0x96 TLS_RSA_WITH_SEED_CBC_SHA [RFC4162]
|
||||||
|
* 0x00,0x97 TLS_DH_DSS_WITH_SEED_CBC_SHA [RFC4162]
|
||||||
|
* 0x00,0x98 TLS_DH_RSA_WITH_SEED_CBC_SHA [RFC4162]
|
||||||
|
* 0x00,0x99 TLS_DHE_DSS_WITH_SEED_CBC_SHA [RFC4162]
|
||||||
|
* 0x00,0x9A TLS_DHE_RSA_WITH_SEED_CBC_SHA [RFC4162]
|
||||||
|
* 0x00,0x9B TLS_DH_anon_WITH_SEED_CBC_SHA [RFC4162]
|
||||||
|
* 0x00,0x9C TLS_RSA_WITH_AES_128_GCM_SHA256 [RFC5288]
|
||||||
|
* 0x00,0x9D TLS_RSA_WITH_AES_256_GCM_SHA384 [RFC5288]
|
||||||
|
* 0x00,0x9E TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 [RFC5288]
|
||||||
|
* 0x00,0x9F TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 [RFC5288]
|
||||||
|
* 0x00,0xA0 TLS_DH_RSA_WITH_AES_128_GCM_SHA256 [RFC5288]
|
||||||
|
* 0x00,0xA1 TLS_DH_RSA_WITH_AES_256_GCM_SHA384 [RFC5288]
|
||||||
|
* 0x00,0xA2 TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 [RFC5288]
|
||||||
|
* 0x00,0xA3 TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 [RFC5288]
|
||||||
|
* 0x00,0xA4 TLS_DH_DSS_WITH_AES_128_GCM_SHA256 [RFC5288]
|
||||||
|
* 0x00,0xA5 TLS_DH_DSS_WITH_AES_256_GCM_SHA384 [RFC5288]
|
||||||
|
* 0x00,0xA6 TLS_DH_anon_WITH_AES_128_GCM_SHA256 [RFC5288]
|
||||||
|
* 0x00,0xA7 TLS_DH_anon_WITH_AES_256_GCM_SHA384 [RFC5288]
|
||||||
|
* 0x00,0xA8 TLS_PSK_WITH_AES_128_GCM_SHA256 [RFC5487]
|
||||||
|
* 0x00,0xA9 TLS_PSK_WITH_AES_256_GCM_SHA384 [RFC5487]
|
||||||
|
* 0x00,0xAA TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 [RFC5487]
|
||||||
|
* 0x00,0xAB TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 [RFC5487]
|
||||||
|
* 0x00,0xAC TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 [RFC5487]
|
||||||
|
* 0x00,0xAD TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 [RFC5487]
|
||||||
|
* 0x00,0xAE TLS_PSK_WITH_AES_128_CBC_SHA256 [RFC5487]
|
||||||
|
* 0x00,0xAF TLS_PSK_WITH_AES_256_CBC_SHA384 [RFC5487]
|
||||||
|
* 0x00,0xB0 TLS_PSK_WITH_NULL_SHA256 [RFC5487]
|
||||||
|
* 0x00,0xB1 TLS_PSK_WITH_NULL_SHA384 [RFC5487]
|
||||||
|
* 0x00,0xB2 TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 [RFC5487]
|
||||||
|
* 0x00,0xB3 TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 [RFC5487]
|
||||||
|
* 0x00,0xB4 TLS_DHE_PSK_WITH_NULL_SHA256 [RFC5487]
|
||||||
|
* 0x00,0xB5 TLS_DHE_PSK_WITH_NULL_SHA384 [RFC5487]
|
||||||
|
* 0x00,0xB6 TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 [RFC5487]
|
||||||
|
* 0x00,0xB7 TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 [RFC5487]
|
||||||
|
* 0x00,0xB8 TLS_RSA_PSK_WITH_NULL_SHA256 [RFC5487]
|
||||||
|
* 0x00,0xB9 TLS_RSA_PSK_WITH_NULL_SHA384 [RFC5487]
|
||||||
|
* 0x00,0xBA TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 [RFC5932]
|
||||||
|
* 0x00,0xBB TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256 [RFC5932]
|
||||||
|
* 0x00,0xBC TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256 [RFC5932]
|
||||||
|
* 0x00,0xBD TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 [RFC5932]
|
||||||
|
* 0x00,0xBE TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 [RFC5932]
|
||||||
|
* 0x00,0xBF TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256 [RFC5932]
|
||||||
|
* 0x00,0xC0 TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 [RFC5932]
|
||||||
|
* 0x00,0xC1 TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256 [RFC5932]
|
||||||
|
* 0x00,0xC2 TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256 [RFC5932]
|
||||||
|
* 0x00,0xC3 TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 [RFC5932]
|
||||||
|
* 0x00,0xC4 TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 [RFC5932]
|
||||||
|
* 0x00,0xC5 TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256 [RFC5932]
|
||||||
|
* 0x00,0xC6-FE Unassigned
|
||||||
|
* 0x00,0xFF TLS_EMPTY_RENEGOTIATION_INFO_SCSV [RFC5746]
|
||||||
|
* 0x01-BF,* Unassigned
|
||||||
|
* 0xC0,0x01 TLS_ECDH_ECDSA_WITH_NULL_SHA [RFC4492]
|
||||||
|
* 0xC0,0x02 TLS_ECDH_ECDSA_WITH_RC4_128_SHA [RFC4492]
|
||||||
|
* 0xC0,0x03 TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA [RFC4492]
|
||||||
|
* 0xC0,0x04 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA [RFC4492]
|
||||||
|
* 0xC0,0x05 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA [RFC4492]
|
||||||
|
* 0xC0,0x06 TLS_ECDHE_ECDSA_WITH_NULL_SHA [RFC4492]
|
||||||
|
* 0xC0,0x07 TLS_ECDHE_ECDSA_WITH_RC4_128_SHA [RFC4492]
|
||||||
|
* 0xC0,0x08 TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA [RFC4492]
|
||||||
|
* 0xC0,0x09 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA [RFC4492]
|
||||||
|
* 0xC0,0x0A TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA [RFC4492]
|
||||||
|
* 0xC0,0x0B TLS_ECDH_RSA_WITH_NULL_SHA [RFC4492]
|
||||||
|
* 0xC0,0x0C TLS_ECDH_RSA_WITH_RC4_128_SHA [RFC4492]
|
||||||
|
* 0xC0,0x0D TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA [RFC4492]
|
||||||
|
* 0xC0,0x0E TLS_ECDH_RSA_WITH_AES_128_CBC_SHA [RFC4492]
|
||||||
|
* 0xC0,0x0F TLS_ECDH_RSA_WITH_AES_256_CBC_SHA [RFC4492]
|
||||||
|
* 0xC0,0x10 TLS_ECDHE_RSA_WITH_NULL_SHA [RFC4492]
|
||||||
|
* 0xC0,0x11 TLS_ECDHE_RSA_WITH_RC4_128_SHA [RFC4492]
|
||||||
|
* 0xC0,0x12 TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA [RFC4492]
|
||||||
|
* 0xC0,0x13 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA [RFC4492]
|
||||||
|
* 0xC0,0x14 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA [RFC4492]
|
||||||
|
* 0xC0,0x15 TLS_ECDH_anon_WITH_NULL_SHA [RFC4492]
|
||||||
|
* 0xC0,0x16 TLS_ECDH_anon_WITH_RC4_128_SHA [RFC4492]
|
||||||
|
* 0xC0,0x17 TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA [RFC4492]
|
||||||
|
* 0xC0,0x18 TLS_ECDH_anon_WITH_AES_128_CBC_SHA [RFC4492]
|
||||||
|
* 0xC0,0x19 TLS_ECDH_anon_WITH_AES_256_CBC_SHA [RFC4492]
|
||||||
|
* 0xC0,0x1A TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA [RFC5054]
|
||||||
|
* 0xC0,0x1B TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA [RFC5054]
|
||||||
|
* 0xC0,0x1C TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA [RFC5054]
|
||||||
|
* 0xC0,0x1D TLS_SRP_SHA_WITH_AES_128_CBC_SHA [RFC5054]
|
||||||
|
* 0xC0,0x1E TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA [RFC5054]
|
||||||
|
* 0xC0,0x1F TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA [RFC5054]
|
||||||
|
* 0xC0,0x20 TLS_SRP_SHA_WITH_AES_256_CBC_SHA [RFC5054]
|
||||||
|
* 0xC0,0x21 TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA [RFC5054]
|
||||||
|
* 0xC0,0x22 TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA [RFC5054]
|
||||||
|
* 0xC0,0x23 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 [RFC5289]
|
||||||
|
* 0xC0,0x24 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 [RFC5289]
|
||||||
|
* 0xC0,0x25 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 [RFC5289]
|
||||||
|
* 0xC0,0x26 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 [RFC5289]
|
||||||
|
* 0xC0,0x27 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 [RFC5289]
|
||||||
|
* 0xC0,0x28 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 [RFC5289]
|
||||||
|
* 0xC0,0x29 TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 [RFC5289]
|
||||||
|
* 0xC0,0x2A TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 [RFC5289]
|
||||||
|
* 0xC0,0x2B TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 [RFC5289]
|
||||||
|
* 0xC0,0x2C TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 [RFC5289]
|
||||||
|
* 0xC0,0x2D TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 [RFC5289]
|
||||||
|
* 0xC0,0x2E TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 [RFC5289]
|
||||||
|
* 0xC0,0x2F TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 [RFC5289]
|
||||||
|
* 0xC0,0x30 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 [RFC5289]
|
||||||
|
* 0xC0,0x31 TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 [RFC5289]
|
||||||
|
* 0xC0,0x32 TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 [RFC5289]
|
||||||
|
* 0xC0,0x33 TLS_ECDHE_PSK_WITH_RC4_128_SHA [RFC5489]
|
||||||
|
* 0xC0,0x34 TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA [RFC5489]
|
||||||
|
* 0xC0,0x35 TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA [RFC5489]
|
||||||
|
* 0xC0,0x36 TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA [RFC5489]
|
||||||
|
* 0xC0,0x37 TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 [RFC5489]
|
||||||
|
* 0xC0,0x38 TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 [RFC5489]
|
||||||
|
* 0xC0,0x39 TLS_ECDHE_PSK_WITH_NULL_SHA [RFC5489]
|
||||||
|
* 0xC0,0x3A TLS_ECDHE_PSK_WITH_NULL_SHA256 [RFC5489]
|
||||||
|
* 0xC0,0x3B TLS_ECDHE_PSK_WITH_NULL_SHA384 [RFC5489]
|
||||||
|
* 0xC0,0x3C-FF Unassigned
|
||||||
|
* 0xC1-FD,* Unassigned
|
||||||
|
* 0xFE,0x00-FD Unassigned
|
||||||
|
* 0xFE,0xFE-FF Reserved to avoid conflicts with widely
|
||||||
|
* deployed implementations [Pasi_Eronen]
|
||||||
|
* 0xFF,0x00-FF Reserved for Private Use [RFC5246]
|
||||||
|
*/
|
||||||
|
|
||||||
add("SSL_NULL_WITH_NULL_NULL",
|
add("SSL_NULL_WITH_NULL_NULL",
|
||||||
0x0000, 1, K_NULL, B_NULL, F);
|
0x0000, 1, K_NULL, B_NULL, F);
|
||||||
|
|
||||||
|
@ -574,7 +827,6 @@ final class CipherSuite implements Comparable {
|
||||||
0x0016, --p, K_DHE_RSA, B_3DES, T);
|
0x0016, --p, K_DHE_RSA, B_3DES, T);
|
||||||
add("SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
|
add("SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
|
||||||
0x0013, --p, K_DHE_DSS, B_3DES, N);
|
0x0013, --p, K_DHE_DSS, B_3DES, N);
|
||||||
|
|
||||||
add("SSL_RSA_WITH_DES_CBC_SHA",
|
add("SSL_RSA_WITH_DES_CBC_SHA",
|
||||||
0x0009, --p, K_RSA, B_DES, N);
|
0x0009, --p, K_RSA, B_DES, N);
|
||||||
add("SSL_DHE_RSA_WITH_DES_CBC_SHA",
|
add("SSL_DHE_RSA_WITH_DES_CBC_SHA",
|
||||||
|
@ -582,13 +834,17 @@ final class CipherSuite implements Comparable {
|
||||||
add("SSL_DHE_DSS_WITH_DES_CBC_SHA",
|
add("SSL_DHE_DSS_WITH_DES_CBC_SHA",
|
||||||
0x0012, --p, K_DHE_DSS, B_DES, N);
|
0x0012, --p, K_DHE_DSS, B_DES, N);
|
||||||
add("SSL_RSA_EXPORT_WITH_RC4_40_MD5",
|
add("SSL_RSA_EXPORT_WITH_RC4_40_MD5",
|
||||||
0x0003, --p, K_RSA_EXPORT, B_RC4_40, N);
|
0x0003, --p, K_RSA_EXPORT, B_RC4_40, N,
|
||||||
|
ProtocolVersion.TLS11.v);
|
||||||
add("SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
|
add("SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
|
||||||
0x0008, --p, K_RSA_EXPORT, B_DES_40, N);
|
0x0008, --p, K_RSA_EXPORT, B_DES_40, N,
|
||||||
|
ProtocolVersion.TLS11.v);
|
||||||
add("SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
|
add("SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
|
||||||
0x0014, --p, K_DHE_RSA, B_DES_40, N);
|
0x0014, --p, K_DHE_RSA, B_DES_40, N,
|
||||||
|
ProtocolVersion.TLS11.v);
|
||||||
add("SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
|
add("SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
|
||||||
0x0011, --p, K_DHE_DSS, B_DES_40, N);
|
0x0011, --p, K_DHE_DSS, B_DES_40, N,
|
||||||
|
ProtocolVersion.TLS11.v);
|
||||||
|
|
||||||
// Renegotiation protection request Signalling Cipher Suite Value (SCSV)
|
// Renegotiation protection request Signalling Cipher Suite Value (SCSV)
|
||||||
add("TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
|
add("TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
|
||||||
|
@ -634,9 +890,11 @@ final class CipherSuite implements Comparable {
|
||||||
0xC017, --p, K_ECDH_ANON, B_3DES, T);
|
0xC017, --p, K_ECDH_ANON, B_3DES, T);
|
||||||
|
|
||||||
add("SSL_DH_anon_EXPORT_WITH_RC4_40_MD5",
|
add("SSL_DH_anon_EXPORT_WITH_RC4_40_MD5",
|
||||||
0x0017, --p, K_DH_ANON, B_RC4_40, N);
|
0x0017, --p, K_DH_ANON, B_RC4_40, N,
|
||||||
|
ProtocolVersion.TLS11.v);
|
||||||
add("SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
|
add("SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
|
||||||
0x0019, --p, K_DH_ANON, B_DES_40, N);
|
0x0019, --p, K_DH_ANON, B_DES_40, N,
|
||||||
|
ProtocolVersion.TLS11.v);
|
||||||
|
|
||||||
add("TLS_ECDH_anon_WITH_NULL_SHA",
|
add("TLS_ECDH_anon_WITH_NULL_SHA",
|
||||||
0xC015, --p, K_ECDH_ANON, B_NULL, N);
|
0xC015, --p, K_ECDH_ANON, B_NULL, N);
|
||||||
|
@ -655,13 +913,28 @@ final class CipherSuite implements Comparable {
|
||||||
add("TLS_KRB5_WITH_DES_CBC_MD5",
|
add("TLS_KRB5_WITH_DES_CBC_MD5",
|
||||||
0x0022, --p, K_KRB5, B_DES, N);
|
0x0022, --p, K_KRB5, B_DES, N);
|
||||||
add("TLS_KRB5_EXPORT_WITH_RC4_40_SHA",
|
add("TLS_KRB5_EXPORT_WITH_RC4_40_SHA",
|
||||||
0x0028, --p, K_KRB5_EXPORT, B_RC4_40, N);
|
0x0028, --p, K_KRB5_EXPORT, B_RC4_40, N,
|
||||||
|
ProtocolVersion.TLS11.v);
|
||||||
add("TLS_KRB5_EXPORT_WITH_RC4_40_MD5",
|
add("TLS_KRB5_EXPORT_WITH_RC4_40_MD5",
|
||||||
0x002b, --p, K_KRB5_EXPORT, B_RC4_40, N);
|
0x002b, --p, K_KRB5_EXPORT, B_RC4_40, N,
|
||||||
|
ProtocolVersion.TLS11.v);
|
||||||
add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA",
|
add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA",
|
||||||
0x0026, --p, K_KRB5_EXPORT, B_DES_40, N);
|
0x0026, --p, K_KRB5_EXPORT, B_DES_40, N,
|
||||||
|
ProtocolVersion.TLS11.v);
|
||||||
add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5",
|
add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5",
|
||||||
0x0029, --p, K_KRB5_EXPORT, B_DES_40, N);
|
0x0029, --p, K_KRB5_EXPORT, B_DES_40, N,
|
||||||
|
ProtocolVersion.TLS11.v);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Other values from the TLS Cipher Suite Registry, as of August 2010.
|
||||||
|
*
|
||||||
|
* http://www.iana.org/assignments/tls-parameters/tls-parameters.xml
|
||||||
|
*
|
||||||
|
* Range Registration Procedures Notes
|
||||||
|
* 000-191 Standards Action Refers to value of first byte
|
||||||
|
* 192-254 Specification Required Refers to value of first byte
|
||||||
|
* 255 Reserved for Private Use Refers to value of first byte
|
||||||
|
*/
|
||||||
|
|
||||||
// Register the names of a few additional CipherSuites.
|
// Register the names of a few additional CipherSuites.
|
||||||
// Makes them show up as names instead of numbers in
|
// Makes them show up as names instead of numbers in
|
||||||
|
@ -701,6 +974,151 @@ final class CipherSuite implements Comparable {
|
||||||
add("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA", 0x0027);
|
add("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA", 0x0027);
|
||||||
add("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5", 0x002a);
|
add("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5", 0x002a);
|
||||||
|
|
||||||
|
// Unsupported cipher suites from RFC 4162
|
||||||
|
add("TLS_RSA_WITH_SEED_CBC_SHA", 0x0096);
|
||||||
|
add("TLS_DH_DSS_WITH_SEED_CBC_SHA", 0x0097);
|
||||||
|
add("TLS_DH_RSA_WITH_SEED_CBC_SHA", 0x0098);
|
||||||
|
add("TLS_DHE_DSS_WITH_SEED_CBC_SHA", 0x0099);
|
||||||
|
add("TLS_DHE_RSA_WITH_SEED_CBC_SHA", 0x009a);
|
||||||
|
add("TLS_DH_anon_WITH_SEED_CBC_SHA", 0x009b);
|
||||||
|
|
||||||
|
// Unsupported cipher suites from RFC 4279
|
||||||
|
add("TLS_PSK_WITH_RC4_128_SHA", 0x008a);
|
||||||
|
add("TLS_PSK_WITH_3DES_EDE_CBC_SHA", 0x008b);
|
||||||
|
add("TLS_PSK_WITH_AES_128_CBC_SHA", 0x008c);
|
||||||
|
add("TLS_PSK_WITH_AES_256_CBC_SHA", 0x008d);
|
||||||
|
add("TLS_DHE_PSK_WITH_RC4_128_SHA", 0x008e);
|
||||||
|
add("TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA", 0x008f);
|
||||||
|
add("TLS_DHE_PSK_WITH_AES_128_CBC_SHA", 0x0090);
|
||||||
|
add("TLS_DHE_PSK_WITH_AES_256_CBC_SHA", 0x0091);
|
||||||
|
add("TLS_RSA_PSK_WITH_RC4_128_SHA", 0x0092);
|
||||||
|
add("TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA", 0x0093);
|
||||||
|
add("TLS_RSA_PSK_WITH_AES_128_CBC_SHA", 0x0094);
|
||||||
|
add("TLS_RSA_PSK_WITH_AES_256_CBC_SHA", 0x0095);
|
||||||
|
|
||||||
|
// Unsupported cipher suites from RFC 4785
|
||||||
|
add("TLS_PSK_WITH_NULL_SHA", 0x002c);
|
||||||
|
add("TLS_DHE_PSK_WITH_NULL_SHA", 0x002d);
|
||||||
|
add("TLS_RSA_PSK_WITH_NULL_SHA", 0x002e);
|
||||||
|
|
||||||
|
// Unsupported cipher suites from RFC 5246
|
||||||
|
add("TLS_DH_DSS_WITH_AES_128_CBC_SHA", 0x0030);
|
||||||
|
add("TLS_DH_RSA_WITH_AES_128_CBC_SHA", 0x0031);
|
||||||
|
add("TLS_DH_DSS_WITH_AES_256_CBC_SHA", 0x0036);
|
||||||
|
add("TLS_DH_RSA_WITH_AES_256_CBC_SHA", 0x0037);
|
||||||
|
add("TLS_RSA_WITH_NULL_SHA256", 0x003b);
|
||||||
|
add("TLS_RSA_WITH_AES_128_CBC_SHA256", 0x003c);
|
||||||
|
add("TLS_RSA_WITH_AES_256_CBC_SHA256", 0x003d);
|
||||||
|
add("TLS_DH_DSS_WITH_AES_128_CBC_SHA256", 0x003e);
|
||||||
|
add("TLS_DH_RSA_WITH_AES_128_CBC_SHA256", 0x003f);
|
||||||
|
add("TLS_DHE_DSS_WITH_AES_128_CBC_SHA256", 0x0040);
|
||||||
|
add("TLS_DHE_RSA_WITH_AES_128_CBC_SHA256", 0x0067);
|
||||||
|
add("TLS_DH_DSS_WITH_AES_256_CBC_SHA256", 0x0068);
|
||||||
|
add("TLS_DH_RSA_WITH_AES_256_CBC_SHA256", 0x0069);
|
||||||
|
add("TLS_DHE_DSS_WITH_AES_256_CBC_SHA256", 0x006a);
|
||||||
|
add("TLS_DHE_RSA_WITH_AES_256_CBC_SHA256", 0x006b);
|
||||||
|
add("TLS_DH_anon_WITH_AES_128_CBC_SHA256", 0x006c);
|
||||||
|
add("TLS_DH_anon_WITH_AES_256_CBC_SHA256", 0x006d);
|
||||||
|
|
||||||
|
// Unsupported cipher suites from RFC 5288
|
||||||
|
add("TLS_RSA_WITH_AES_128_GCM_SHA256", 0x009c);
|
||||||
|
add("TLS_RSA_WITH_AES_256_GCM_SHA384", 0x009d);
|
||||||
|
add("TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", 0x009e);
|
||||||
|
add("TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", 0x009f);
|
||||||
|
add("TLS_DH_RSA_WITH_AES_128_GCM_SHA256", 0x00a0);
|
||||||
|
add("TLS_DH_RSA_WITH_AES_256_GCM_SHA384", 0x00a1);
|
||||||
|
add("TLS_DHE_DSS_WITH_AES_128_GCM_SHA256", 0x00a2);
|
||||||
|
add("TLS_DHE_DSS_WITH_AES_256_GCM_SHA384", 0x00a3);
|
||||||
|
add("TLS_DH_DSS_WITH_AES_128_GCM_SHA256", 0x00a4);
|
||||||
|
add("TLS_DH_DSS_WITH_AES_256_GCM_SHA384", 0x00a5);
|
||||||
|
add("TLS_DH_anon_WITH_AES_128_GCM_SHA256", 0x00a6);
|
||||||
|
add("TLS_DH_anon_WITH_AES_256_GCM_SHA384", 0x00a7);
|
||||||
|
|
||||||
|
// Unsupported cipher suites from RFC 5487
|
||||||
|
add("TLS_PSK_WITH_AES_128_GCM_SHA256", 0x00a8);
|
||||||
|
add("TLS_PSK_WITH_AES_256_GCM_SHA384", 0x00a9);
|
||||||
|
add("TLS_DHE_PSK_WITH_AES_128_GCM_SHA256", 0x00aa);
|
||||||
|
add("TLS_DHE_PSK_WITH_AES_256_GCM_SHA384", 0x00ab);
|
||||||
|
add("TLS_RSA_PSK_WITH_AES_128_GCM_SHA256", 0x00ac);
|
||||||
|
add("TLS_RSA_PSK_WITH_AES_256_GCM_SHA384", 0x00ad);
|
||||||
|
add("TLS_PSK_WITH_AES_128_CBC_SHA256", 0x00ae);
|
||||||
|
add("TLS_PSK_WITH_AES_256_CBC_SHA384", 0x00af);
|
||||||
|
add("TLS_PSK_WITH_NULL_SHA256", 0x00b0);
|
||||||
|
add("TLS_PSK_WITH_NULL_SHA384", 0x00b1);
|
||||||
|
add("TLS_DHE_PSK_WITH_AES_128_CBC_SHA256", 0x00b2);
|
||||||
|
add("TLS_DHE_PSK_WITH_AES_256_CBC_SHA384", 0x00b3);
|
||||||
|
add("TLS_DHE_PSK_WITH_NULL_SHA256", 0x00b4);
|
||||||
|
add("TLS_DHE_PSK_WITH_NULL_SHA384", 0x00b5);
|
||||||
|
add("TLS_RSA_PSK_WITH_AES_128_CBC_SHA256", 0x00b6);
|
||||||
|
add("TLS_RSA_PSK_WITH_AES_256_CBC_SHA384", 0x00b7);
|
||||||
|
add("TLS_RSA_PSK_WITH_NULL_SHA256", 0x00b8);
|
||||||
|
add("TLS_RSA_PSK_WITH_NULL_SHA384", 0x00b9);
|
||||||
|
|
||||||
|
// Unsupported cipher suites from RFC 5932
|
||||||
|
add("TLS_RSA_WITH_CAMELLIA_128_CBC_SHA", 0x0041);
|
||||||
|
add("TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA", 0x0042);
|
||||||
|
add("TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA", 0x0043);
|
||||||
|
add("TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA", 0x0044);
|
||||||
|
add("TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA", 0x0045);
|
||||||
|
add("TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA", 0x0046);
|
||||||
|
add("TLS_RSA_WITH_CAMELLIA_256_CBC_SHA", 0x0084);
|
||||||
|
add("TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA", 0x0085);
|
||||||
|
add("TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA", 0x0086);
|
||||||
|
add("TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA", 0x0087);
|
||||||
|
add("TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA", 0x0088);
|
||||||
|
add("TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA", 0x0089);
|
||||||
|
add("TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256", 0x00ba);
|
||||||
|
add("TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256", 0x00bb);
|
||||||
|
add("TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256", 0x00bc);
|
||||||
|
add("TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256", 0x00bd);
|
||||||
|
add("TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256", 0x00be);
|
||||||
|
add("TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256", 0x00bf);
|
||||||
|
add("TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256", 0x00c0);
|
||||||
|
add("TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256", 0x00c1);
|
||||||
|
add("TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256", 0x00c2);
|
||||||
|
add("TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256", 0x00c3);
|
||||||
|
add("TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256", 0x00c4);
|
||||||
|
add("TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256", 0x00c5);
|
||||||
|
|
||||||
|
// Unsupported cipher suites from RFC 5054
|
||||||
|
add("TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA", 0xc01a);
|
||||||
|
add("TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA", 0xc01b);
|
||||||
|
add("TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA", 0xc01c);
|
||||||
|
add("TLS_SRP_SHA_WITH_AES_128_CBC_SHA", 0xc01d);
|
||||||
|
add("TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA", 0xc01e);
|
||||||
|
add("TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA", 0xc01f);
|
||||||
|
add("TLS_SRP_SHA_WITH_AES_256_CBC_SHA", 0xc020);
|
||||||
|
add("TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA", 0xc021);
|
||||||
|
add("TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA", 0xc022);
|
||||||
|
|
||||||
|
// Unsupported cipher suites from RFC 5289
|
||||||
|
add("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", 0xc023);
|
||||||
|
add("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", 0xc024);
|
||||||
|
add("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256", 0xc025);
|
||||||
|
add("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384", 0xc026);
|
||||||
|
add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", 0xc027);
|
||||||
|
add("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", 0xc028);
|
||||||
|
add("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256", 0xc029);
|
||||||
|
add("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384", 0xc02a);
|
||||||
|
add("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 0xc02b);
|
||||||
|
add("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 0xc02c);
|
||||||
|
add("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", 0xc02d);
|
||||||
|
add("TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384", 0xc02e);
|
||||||
|
add("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 0xc02f);
|
||||||
|
add("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 0xc030);
|
||||||
|
add("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", 0xc031);
|
||||||
|
add("TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384", 0xc032);
|
||||||
|
|
||||||
|
// Unsupported cipher suites from RFC 5489
|
||||||
|
add("TLS_ECDHE_PSK_WITH_RC4_128_SHA", 0xc033);
|
||||||
|
add("TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA", 0xc034);
|
||||||
|
add("TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA", 0xc035);
|
||||||
|
add("TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA", 0xc036);
|
||||||
|
add("TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256", 0xc037);
|
||||||
|
add("TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384", 0xc038);
|
||||||
|
add("TLS_ECDHE_PSK_WITH_NULL_SHA", 0xc039);
|
||||||
|
add("TLS_ECDHE_PSK_WITH_NULL_SHA256", 0xc03a);
|
||||||
|
add("TLS_ECDHE_PSK_WITH_NULL_SHA384", 0xc03b);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ciphersuite SSL_NULL_WITH_NULL_NULL
|
// ciphersuite SSL_NULL_WITH_NULL_NULL
|
||||||
|
|
|
@ -345,9 +345,10 @@ final class ClientHandshaker extends Handshaker {
|
||||||
|
|
||||||
// check if the server selected protocol version is OK for us
|
// check if the server selected protocol version is OK for us
|
||||||
ProtocolVersion mesgVersion = mesg.protocolVersion;
|
ProtocolVersion mesgVersion = mesg.protocolVersion;
|
||||||
if (enabledProtocols.contains(mesgVersion) == false) {
|
if (!isNegotiable(mesgVersion)) {
|
||||||
throw new SSLHandshakeException
|
throw new SSLHandshakeException(
|
||||||
("Server chose unsupported or disabled protocol: " + mesgVersion);
|
"Server chose unsupported or disabled protocol: " +
|
||||||
|
mesgVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set protocolVersion and propagate to SSLSocket and the
|
// Set protocolVersion and propagate to SSLSocket and the
|
||||||
|
@ -1022,7 +1023,7 @@ final class ClientHandshaker extends Handshaker {
|
||||||
SessionId sessionId = SSLSessionImpl.nullSession.getSessionId();
|
SessionId sessionId = SSLSessionImpl.nullSession.getSessionId();
|
||||||
|
|
||||||
// a list of cipher suites sent by the client
|
// a list of cipher suites sent by the client
|
||||||
CipherSuiteList cipherSuites = enabledCipherSuites;
|
CipherSuiteList cipherSuites = getActiveCipherSuites();
|
||||||
|
|
||||||
// set the max protocol version this client is supporting.
|
// set the max protocol version this client is supporting.
|
||||||
maxProtocolVersion = protocolVersion;
|
maxProtocolVersion = protocolVersion;
|
||||||
|
@ -1057,8 +1058,7 @@ final class ClientHandshaker extends Handshaker {
|
||||||
session = null;
|
session = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((session != null) &&
|
if ((session != null) && !isNegotiable(sessionVersion)) {
|
||||||
(enabledProtocols.contains(sessionVersion) == false)) {
|
|
||||||
if (debug != null && Debug.isOn("session")) {
|
if (debug != null && Debug.isOn("session")) {
|
||||||
System.out.println("%% can't resume, protocol disabled");
|
System.out.println("%% can't resume, protocol disabled");
|
||||||
}
|
}
|
||||||
|
@ -1088,7 +1088,7 @@ final class ClientHandshaker extends Handshaker {
|
||||||
*/
|
*/
|
||||||
if (!enableNewSession) {
|
if (!enableNewSession) {
|
||||||
if (session == null) {
|
if (session == null) {
|
||||||
throw new SSLException(
|
throw new SSLHandshakeException(
|
||||||
"Can't reuse existing SSL client session");
|
"Can't reuse existing SSL client session");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1105,7 +1105,7 @@ final class ClientHandshaker extends Handshaker {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (session == null && !enableNewSession) {
|
if (session == null && !enableNewSession) {
|
||||||
throw new SSLException("No existing session to resume");
|
throw new SSLHandshakeException("No existing session to resume");
|
||||||
}
|
}
|
||||||
|
|
||||||
// exclude SCSV for secure renegotiation
|
// exclude SCSV for secure renegotiation
|
||||||
|
@ -1131,7 +1131,7 @@ final class ClientHandshaker extends Handshaker {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!negotiable) {
|
if (!negotiable) {
|
||||||
throw new SSLException("No negotiable cipher suite");
|
throw new SSLHandshakeException("No negotiable cipher suite");
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the ClientHello message
|
// create the ClientHello message
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2009, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -27,6 +27,7 @@ package sun.security.ssl;
|
||||||
|
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.security.AccessController;
|
import java.security.AccessController;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
import sun.security.action.GetPropertyAction;
|
import sun.security.action.GetPropertyAction;
|
||||||
|
|
||||||
|
@ -44,7 +45,7 @@ public class Debug {
|
||||||
static {
|
static {
|
||||||
args = java.security.AccessController.doPrivileged(
|
args = java.security.AccessController.doPrivileged(
|
||||||
new GetPropertyAction("javax.net.debug", ""));
|
new GetPropertyAction("javax.net.debug", ""));
|
||||||
args = args.toLowerCase();
|
args = args.toLowerCase(Locale.ENGLISH);
|
||||||
if (args.equals("help")) {
|
if (args.equals("help")) {
|
||||||
Help();
|
Help();
|
||||||
}
|
}
|
||||||
|
@ -114,7 +115,7 @@ public class Debug {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
int n = 0;
|
int n = 0;
|
||||||
option = option.toLowerCase();
|
option = option.toLowerCase(Locale.ENGLISH);
|
||||||
|
|
||||||
if (args.indexOf("all") != -1) {
|
if (args.indexOf("all") != -1) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1167,10 +1167,15 @@ class CertificateRequest extends HandshakeMessage
|
||||||
s.println();
|
s.println();
|
||||||
|
|
||||||
s.println("Cert Authorities:");
|
s.println("Cert Authorities:");
|
||||||
for (int i = 0; i < authorities.length; i++)
|
if (authorities.length == 0) {
|
||||||
|
s.println("<Empty>");
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < authorities.length; i++) {
|
||||||
authorities[i].print(s);
|
authorities[i].print(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -71,11 +71,31 @@ abstract class Handshaker {
|
||||||
byte[] clientVerifyData;
|
byte[] clientVerifyData;
|
||||||
byte[] serverVerifyData;
|
byte[] serverVerifyData;
|
||||||
|
|
||||||
// is it an initial negotiation or a renegotiation?
|
// Is it an initial negotiation or a renegotiation?
|
||||||
boolean isInitialHandshake;
|
boolean isInitialHandshake;
|
||||||
|
|
||||||
// list of enabled protocols
|
// List of enabled protocols
|
||||||
ProtocolList enabledProtocols;
|
private ProtocolList enabledProtocols;
|
||||||
|
|
||||||
|
// List of enabled CipherSuites
|
||||||
|
private CipherSuiteList enabledCipherSuites;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List of active protocols
|
||||||
|
*
|
||||||
|
* Active protocols is a subset of enabled protocols, and will
|
||||||
|
* contain only those protocols that have vaild cipher suites
|
||||||
|
* enabled.
|
||||||
|
*/
|
||||||
|
private ProtocolList activeProtocols;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List of active cipher suites
|
||||||
|
*
|
||||||
|
* Active cipher suites is a subset of enabled cipher suites, and will
|
||||||
|
* contain only those cipher suites available for the active protocols.
|
||||||
|
*/
|
||||||
|
private CipherSuiteList activeCipherSuites;
|
||||||
|
|
||||||
private boolean isClient;
|
private boolean isClient;
|
||||||
|
|
||||||
|
@ -94,9 +114,6 @@ abstract class Handshaker {
|
||||||
// in reset state after use.
|
// in reset state after use.
|
||||||
private MessageDigest md5Tmp, shaTmp;
|
private MessageDigest md5Tmp, shaTmp;
|
||||||
|
|
||||||
// list of enabled CipherSuites
|
|
||||||
CipherSuiteList enabledCipherSuites;
|
|
||||||
|
|
||||||
// current CipherSuite. Never null, initially SSL_NULL_WITH_NULL_NULL
|
// current CipherSuite. Never null, initially SSL_NULL_WITH_NULL_NULL
|
||||||
CipherSuite cipherSuite;
|
CipherSuite cipherSuite;
|
||||||
|
|
||||||
|
@ -233,7 +250,7 @@ abstract class Handshaker {
|
||||||
// client's cert verify, those constants are in a convenient
|
// client's cert verify, those constants are in a convenient
|
||||||
// order to drastically simplify state machine checking.
|
// order to drastically simplify state machine checking.
|
||||||
//
|
//
|
||||||
state = -1;
|
state = -2; // initialized but not activated
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -345,26 +362,69 @@ abstract class Handshaker {
|
||||||
void setVersion(ProtocolVersion protocolVersion) {
|
void setVersion(ProtocolVersion protocolVersion) {
|
||||||
this.protocolVersion = protocolVersion;
|
this.protocolVersion = protocolVersion;
|
||||||
setVersionSE(protocolVersion);
|
setVersionSE(protocolVersion);
|
||||||
|
|
||||||
output.r.setVersion(protocolVersion);
|
output.r.setVersion(protocolVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the enabled protocols. Called from the constructor or
|
* Set the enabled protocols. Called from the constructor or
|
||||||
* SSLSocketImpl.setEnabledProtocols() (if the handshake is not yet
|
* SSLSocketImpl/SSLEngineImpl.setEnabledProtocols() (if the
|
||||||
* in progress).
|
* handshake is not yet in progress).
|
||||||
*/
|
*/
|
||||||
void setEnabledProtocols(ProtocolList enabledProtocols) {
|
void setEnabledProtocols(ProtocolList enabledProtocols) {
|
||||||
|
activeCipherSuites = null;
|
||||||
|
activeProtocols = null;
|
||||||
|
|
||||||
this.enabledProtocols = enabledProtocols;
|
this.enabledProtocols = enabledProtocols;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the enabled cipher suites. Called from
|
||||||
|
* SSLSocketImpl/SSLEngineImpl.setEnabledCipherSuites() (if the
|
||||||
|
* handshake is not yet in progress).
|
||||||
|
*/
|
||||||
|
void setEnabledCipherSuites(CipherSuiteList enabledCipherSuites) {
|
||||||
|
activeCipherSuites = null;
|
||||||
|
activeProtocols = null;
|
||||||
|
this.enabledCipherSuites = enabledCipherSuites;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prior to handshaking, activate the handshake and initialize the version,
|
||||||
|
* input stream and output stream.
|
||||||
|
*/
|
||||||
|
void activate(ProtocolVersion helloVersion) throws IOException {
|
||||||
|
if (activeProtocols == null) {
|
||||||
|
activeProtocols = getActiveProtocols();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activeProtocols.collection().isEmpty() ||
|
||||||
|
activeProtocols.max.v == ProtocolVersion.NONE.v) {
|
||||||
|
throw new SSLHandshakeException("No appropriate protocol");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activeCipherSuites == null) {
|
||||||
|
activeCipherSuites = getActiveCipherSuites();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activeCipherSuites.collection().isEmpty()) {
|
||||||
|
throw new SSLHandshakeException("No appropriate cipher suite");
|
||||||
|
}
|
||||||
|
|
||||||
// temporary protocol version until the actual protocol version
|
// temporary protocol version until the actual protocol version
|
||||||
// is negotiated in the Hello exchange. This affects the record
|
// is negotiated in the Hello exchange. This affects the record
|
||||||
// version we sent with the ClientHello. Using max() as the record
|
// version we sent with the ClientHello.
|
||||||
// version is not really correct but some implementations fail to
|
if (!isInitialHandshake) {
|
||||||
// correctly negotiate TLS otherwise.
|
protocolVersion = activeProtocolVersion;
|
||||||
protocolVersion = enabledProtocols.max;
|
} else {
|
||||||
|
protocolVersion = activeProtocols.max;
|
||||||
|
}
|
||||||
|
|
||||||
ProtocolVersion helloVersion = enabledProtocols.helloVersion;
|
if (helloVersion == null || helloVersion.v == ProtocolVersion.NONE.v) {
|
||||||
|
helloVersion = activeProtocols.helloVersion;
|
||||||
|
}
|
||||||
|
|
||||||
input = new HandshakeInStream(handshakeHash);
|
input = new HandshakeInStream(handshakeHash);
|
||||||
|
|
||||||
|
@ -372,12 +432,16 @@ abstract class Handshaker {
|
||||||
output = new HandshakeOutStream(protocolVersion, helloVersion,
|
output = new HandshakeOutStream(protocolVersion, helloVersion,
|
||||||
handshakeHash, conn);
|
handshakeHash, conn);
|
||||||
conn.getAppInputStream().r.setHelloVersion(helloVersion);
|
conn.getAppInputStream().r.setHelloVersion(helloVersion);
|
||||||
|
conn.getAppOutputStream().r.setHelloVersion(helloVersion);
|
||||||
} else {
|
} else {
|
||||||
output = new HandshakeOutStream(protocolVersion, helloVersion,
|
output = new HandshakeOutStream(protocolVersion, helloVersion,
|
||||||
handshakeHash, engine);
|
handshakeHash, engine);
|
||||||
|
engine.inputRecord.setHelloVersion(helloVersion);
|
||||||
engine.outputRecord.setHelloVersion(helloVersion);
|
engine.outputRecord.setHelloVersion(helloVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// move state to activated
|
||||||
|
state = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -392,20 +456,127 @@ abstract class Handshaker {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the given ciphersuite is enabled and available.
|
* Check if the given ciphersuite is enabled and available.
|
||||||
* (Enabled ciphersuites are always available unless the status has
|
|
||||||
* changed due to change in JCE providers since it was enabled).
|
|
||||||
* Does not check if the required server certificates are available.
|
* Does not check if the required server certificates are available.
|
||||||
*/
|
*/
|
||||||
boolean isNegotiable(CipherSuite s) {
|
boolean isNegotiable(CipherSuite s) {
|
||||||
return enabledCipherSuites.contains(s) && s.isNegotiable();
|
if (activeCipherSuites == null) {
|
||||||
|
activeCipherSuites = getActiveCipherSuites();
|
||||||
|
}
|
||||||
|
|
||||||
|
return activeCipherSuites.contains(s) && s.isNegotiable();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* As long as handshaking has not started, we can
|
* Check if the given protocol version is enabled and available.
|
||||||
|
*/
|
||||||
|
boolean isNegotiable(ProtocolVersion protocolVersion) {
|
||||||
|
if (activeProtocols == null) {
|
||||||
|
activeProtocols = getActiveProtocols();
|
||||||
|
}
|
||||||
|
|
||||||
|
return activeProtocols.contains(protocolVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select a protocol version from the list. Called from
|
||||||
|
* ServerHandshaker to negotiate protocol version.
|
||||||
|
*
|
||||||
|
* Return the lower of the protocol version suggested in the
|
||||||
|
* clien hello and the highest supported by the server.
|
||||||
|
*/
|
||||||
|
ProtocolVersion selectProtocolVersion(ProtocolVersion protocolVersion) {
|
||||||
|
if (activeProtocols == null) {
|
||||||
|
activeProtocols = getActiveProtocols();
|
||||||
|
}
|
||||||
|
|
||||||
|
return activeProtocols.selectProtocolVersion(protocolVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the active cipher suites.
|
||||||
|
*
|
||||||
|
* In TLS 1.1, many weak or vulnerable cipher suites were obsoleted,
|
||||||
|
* such as TLS_RSA_EXPORT_WITH_RC4_40_MD5. The implementation MUST NOT
|
||||||
|
* negotiate these cipher suites in TLS 1.1 or later mode.
|
||||||
|
*
|
||||||
|
* Therefore, when the active protocols only include TLS 1.1 or later,
|
||||||
|
* the client cannot request to negotiate those obsoleted cipher
|
||||||
|
* suites, that's, the obsoleted suites should not be included in the
|
||||||
|
* client hello. So we need to create a subset of the enabled cipher
|
||||||
|
* suites, the active cipher suites, which does not contain obsoleted
|
||||||
|
* cipher suites of the minimum active protocol.
|
||||||
|
*
|
||||||
|
* Return empty list instead of null if no active cipher suites.
|
||||||
|
*/
|
||||||
|
CipherSuiteList getActiveCipherSuites() {
|
||||||
|
if (activeCipherSuites == null) {
|
||||||
|
if (activeProtocols == null) {
|
||||||
|
activeProtocols = getActiveProtocols();
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList<CipherSuite> suites = new ArrayList<CipherSuite>();
|
||||||
|
if (!(activeProtocols.collection().isEmpty()) &&
|
||||||
|
activeProtocols.min.v != ProtocolVersion.NONE.v) {
|
||||||
|
for (CipherSuite suite : enabledCipherSuites.collection()) {
|
||||||
|
if (suite.obsoleted > activeProtocols.min.v) {
|
||||||
|
suites.add(suite);
|
||||||
|
} else if (debug != null && Debug.isOn("handshake")) {
|
||||||
|
System.out.println(
|
||||||
|
"Ignoring obsoleted cipher suite: " + suite);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
activeCipherSuites = new CipherSuiteList(suites);
|
||||||
|
}
|
||||||
|
|
||||||
|
return activeCipherSuites;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the active protocol versions.
|
||||||
|
*
|
||||||
|
* In TLS 1.1, many weak or vulnerable cipher suites were obsoleted,
|
||||||
|
* such as TLS_RSA_EXPORT_WITH_RC4_40_MD5. The implementation MUST NOT
|
||||||
|
* negotiate these cipher suites in TLS 1.1 or later mode.
|
||||||
|
*
|
||||||
|
* For example, if "TLS_RSA_EXPORT_WITH_RC4_40_MD5" is the
|
||||||
|
* only enabled cipher suite, the client cannot request TLS 1.1 or
|
||||||
|
* later, even though TLS 1.1 or later is enabled. We need to create a
|
||||||
|
* subset of the enabled protocols, called the active protocols, which
|
||||||
|
* contains protocols appropriate to the list of enabled Ciphersuites.
|
||||||
|
*
|
||||||
|
* Return empty list instead of null if no active protocol versions.
|
||||||
|
*/
|
||||||
|
ProtocolList getActiveProtocols() {
|
||||||
|
if (activeProtocols == null) {
|
||||||
|
ArrayList<ProtocolVersion> protocols =
|
||||||
|
new ArrayList<ProtocolVersion>(3);
|
||||||
|
for (ProtocolVersion protocol : enabledProtocols.collection()) {
|
||||||
|
boolean found = false;
|
||||||
|
for (CipherSuite suite : enabledCipherSuites.collection()) {
|
||||||
|
if (suite.isAvailable() && suite.obsoleted > protocol.v) {
|
||||||
|
protocols.add(protocol);
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found && (debug != null) && Debug.isOn("handshake")) {
|
||||||
|
System.out.println(
|
||||||
|
"No available cipher suite for " + protocol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
activeProtocols = new ProtocolList(protocols);
|
||||||
|
}
|
||||||
|
|
||||||
|
return activeProtocols;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* As long as handshaking has not activated, we can
|
||||||
* change whether session creations are allowed.
|
* change whether session creations are allowed.
|
||||||
*
|
*
|
||||||
* Callers should do their own checking if handshaking
|
* Callers should do their own checking if handshaking
|
||||||
* has started.
|
* has activated.
|
||||||
*/
|
*/
|
||||||
void setEnableSessionCreation(boolean newSessions) {
|
void setEnableSessionCreation(boolean newSessions) {
|
||||||
enableNewSession = newSessions;
|
enableNewSession = newSessions;
|
||||||
|
@ -419,12 +590,12 @@ abstract class Handshaker {
|
||||||
CipherBox box;
|
CipherBox box;
|
||||||
if (isClient) {
|
if (isClient) {
|
||||||
box = cipher.newCipher(protocolVersion, svrWriteKey, svrWriteIV,
|
box = cipher.newCipher(protocolVersion, svrWriteKey, svrWriteIV,
|
||||||
false);
|
sslContext.getSecureRandom(), false);
|
||||||
svrWriteKey = null;
|
svrWriteKey = null;
|
||||||
svrWriteIV = null;
|
svrWriteIV = null;
|
||||||
} else {
|
} else {
|
||||||
box = cipher.newCipher(protocolVersion, clntWriteKey, clntWriteIV,
|
box = cipher.newCipher(protocolVersion, clntWriteKey, clntWriteIV,
|
||||||
false);
|
sslContext.getSecureRandom(), false);
|
||||||
clntWriteKey = null;
|
clntWriteKey = null;
|
||||||
clntWriteIV = null;
|
clntWriteIV = null;
|
||||||
}
|
}
|
||||||
|
@ -439,12 +610,12 @@ abstract class Handshaker {
|
||||||
CipherBox box;
|
CipherBox box;
|
||||||
if (isClient) {
|
if (isClient) {
|
||||||
box = cipher.newCipher(protocolVersion, clntWriteKey, clntWriteIV,
|
box = cipher.newCipher(protocolVersion, clntWriteKey, clntWriteIV,
|
||||||
true);
|
sslContext.getSecureRandom(), true);
|
||||||
clntWriteKey = null;
|
clntWriteKey = null;
|
||||||
clntWriteIV = null;
|
clntWriteIV = null;
|
||||||
} else {
|
} else {
|
||||||
box = cipher.newCipher(protocolVersion, svrWriteKey, svrWriteIV,
|
box = cipher.newCipher(protocolVersion, svrWriteKey, svrWriteIV,
|
||||||
true);
|
sslContext.getSecureRandom(), true);
|
||||||
svrWriteKey = null;
|
svrWriteKey = null;
|
||||||
svrWriteIV = null;
|
svrWriteIV = null;
|
||||||
}
|
}
|
||||||
|
@ -613,14 +784,21 @@ abstract class Handshaker {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true iff the handshaker has been activated.
|
||||||
|
*
|
||||||
|
* In activated state, the handshaker may not send any messages out.
|
||||||
|
*/
|
||||||
|
boolean activated() {
|
||||||
|
return state >= -1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true iff the handshaker has sent any messages.
|
* Returns true iff the handshaker has sent any messages.
|
||||||
* Server kickstarting is not as neat as it should be; we
|
|
||||||
* need to create a new handshaker, this method lets us
|
|
||||||
* know if we should.
|
|
||||||
*/
|
*/
|
||||||
boolean started() {
|
boolean started() {
|
||||||
return state >= 0;
|
return state >= 0; // 0: HandshakeMessage.ht_hello_request
|
||||||
|
// 1: HandshakeMessage.ht_hello_request
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -633,6 +811,7 @@ abstract class Handshaker {
|
||||||
if (state >= 0) {
|
if (state >= 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
HandshakeMessage m = getKickstartMessage();
|
HandshakeMessage m = getKickstartMessage();
|
||||||
|
|
||||||
if (debug != null && Debug.isOn("handshake")) {
|
if (debug != null && Debug.isOn("handshake")) {
|
||||||
|
@ -746,6 +925,7 @@ abstract class Handshaker {
|
||||||
*/
|
*/
|
||||||
private SecretKey calculateMasterSecret(SecretKey preMasterSecret,
|
private SecretKey calculateMasterSecret(SecretKey preMasterSecret,
|
||||||
ProtocolVersion requestedVersion) {
|
ProtocolVersion requestedVersion) {
|
||||||
|
|
||||||
TlsMasterSecretParameterSpec spec = new TlsMasterSecretParameterSpec
|
TlsMasterSecretParameterSpec spec = new TlsMasterSecretParameterSpec
|
||||||
(preMasterSecret, protocolVersion.major, protocolVersion.minor,
|
(preMasterSecret, protocolVersion.major, protocolVersion.minor,
|
||||||
clnt_random.random_bytes, svr_random.random_bytes);
|
clnt_random.random_bytes, svr_random.random_bytes);
|
||||||
|
@ -773,22 +953,37 @@ abstract class Handshaker {
|
||||||
if (!preMasterSecret.getAlgorithm().equals("TlsRsaPremasterSecret")) {
|
if (!preMasterSecret.getAlgorithm().equals("TlsRsaPremasterSecret")) {
|
||||||
throw new ProviderException(e);
|
throw new ProviderException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debug != null && Debug.isOn("handshake")) {
|
if (debug != null && Debug.isOn("handshake")) {
|
||||||
System.out.println("RSA master secret generation error:");
|
System.out.println("RSA master secret generation error:");
|
||||||
e.printStackTrace(System.out);
|
e.printStackTrace(System.out);
|
||||||
System.out.println("Generating new random premaster secret");
|
System.out.println("Generating new random premaster secret");
|
||||||
}
|
}
|
||||||
preMasterSecret = RSAClientKeyExchange.generateDummySecret(protocolVersion);
|
|
||||||
|
if (requestedVersion != null) {
|
||||||
|
preMasterSecret =
|
||||||
|
RSAClientKeyExchange.generateDummySecret(requestedVersion);
|
||||||
|
} else {
|
||||||
|
preMasterSecret =
|
||||||
|
RSAClientKeyExchange.generateDummySecret(protocolVersion);
|
||||||
|
}
|
||||||
|
|
||||||
// recursive call with new premaster secret
|
// recursive call with new premaster secret
|
||||||
return calculateMasterSecret(preMasterSecret, null);
|
return calculateMasterSecret(preMasterSecret, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if no version check requested (client side handshake),
|
// if no version check requested (client side handshake), or version
|
||||||
// or version information is not available (not an RSA premaster secret),
|
// information is not available (not an RSA premaster secret),
|
||||||
// return master secret immediately.
|
// return master secret immediately.
|
||||||
if ((requestedVersion == null) || !(masterSecret instanceof TlsMasterSecret)) {
|
if ((requestedVersion == null) ||
|
||||||
|
!(masterSecret instanceof TlsMasterSecret)) {
|
||||||
return masterSecret;
|
return masterSecret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// we have checked the ClientKeyExchange message when reading TLS
|
||||||
|
// record, the following check is necessary to ensure that
|
||||||
|
// JCE provider does not ignore the checking, or the previous
|
||||||
|
// checking process bypassed the premaster secret version checking.
|
||||||
TlsMasterSecret tlsKey = (TlsMasterSecret)masterSecret;
|
TlsMasterSecret tlsKey = (TlsMasterSecret)masterSecret;
|
||||||
int major = tlsKey.getMajorVersion();
|
int major = tlsKey.getMajorVersion();
|
||||||
int minor = tlsKey.getMinorVersion();
|
int minor = tlsKey.getMinorVersion();
|
||||||
|
@ -800,13 +995,21 @@ abstract class Handshaker {
|
||||||
// the specification says that it must be the maximum version supported
|
// the specification says that it must be the maximum version supported
|
||||||
// by the client from its ClientHello message. However, many
|
// by the client from its ClientHello message. However, many
|
||||||
// implementations send the negotiated version, so accept both
|
// implementations send the negotiated version, so accept both
|
||||||
// NOTE that we may be comparing two unsupported version numbers in
|
// for SSL v3.0 and TLS v1.0.
|
||||||
// the second case, which is why we cannot use object reference
|
// NOTE that we may be comparing two unsupported version numbers, which
|
||||||
// equality in this special case
|
// is why we cannot use object reference equality in this special case.
|
||||||
ProtocolVersion premasterVersion = ProtocolVersion.valueOf(major, minor);
|
ProtocolVersion premasterVersion =
|
||||||
boolean versionMismatch = (premasterVersion != protocolVersion) &&
|
ProtocolVersion.valueOf(major, minor);
|
||||||
(premasterVersion.v != requestedVersion.v);
|
boolean versionMismatch = (premasterVersion.v != requestedVersion.v);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* we never checked the client_version in server side
|
||||||
|
* for TLS v1.0 and SSL v3.0. For compatibility, we
|
||||||
|
* maintain this behavior.
|
||||||
|
*/
|
||||||
|
if (versionMismatch && requestedVersion.v <= ProtocolVersion.TLS10.v) {
|
||||||
|
versionMismatch = (premasterVersion.v != protocolVersion.v);
|
||||||
|
}
|
||||||
|
|
||||||
if (versionMismatch == false) {
|
if (versionMismatch == false) {
|
||||||
// check passed, return key
|
// check passed, return key
|
||||||
|
@ -823,7 +1026,9 @@ abstract class Handshaker {
|
||||||
+ premasterVersion);
|
+ premasterVersion);
|
||||||
System.out.println("Generating new random premaster secret");
|
System.out.println("Generating new random premaster secret");
|
||||||
}
|
}
|
||||||
preMasterSecret = RSAClientKeyExchange.generateDummySecret(protocolVersion);
|
preMasterSecret =
|
||||||
|
RSAClientKeyExchange.generateDummySecret(requestedVersion);
|
||||||
|
|
||||||
// recursive call with new premaster secret
|
// recursive call with new premaster secret
|
||||||
return calculateMasterSecret(preMasterSecret, null);
|
return calculateMasterSecret(preMasterSecret, null);
|
||||||
}
|
}
|
||||||
|
@ -849,8 +1054,6 @@ abstract class Handshaker {
|
||||||
int hashSize = cipherSuite.macAlg.size;
|
int hashSize = cipherSuite.macAlg.size;
|
||||||
boolean is_exportable = cipherSuite.exportable;
|
boolean is_exportable = cipherSuite.exportable;
|
||||||
BulkCipher cipher = cipherSuite.cipher;
|
BulkCipher cipher = cipherSuite.cipher;
|
||||||
int keySize = cipher.keySize;
|
|
||||||
int ivSize = cipher.ivSize;
|
|
||||||
int expandedKeySize = is_exportable ? cipher.expandedKeySize : 0;
|
int expandedKeySize = is_exportable ? cipher.expandedKeySize : 0;
|
||||||
|
|
||||||
TlsKeyMaterialParameterSpec spec = new TlsKeyMaterialParameterSpec
|
TlsKeyMaterialParameterSpec spec = new TlsKeyMaterialParameterSpec
|
||||||
|
@ -867,6 +1070,8 @@ abstract class Handshaker {
|
||||||
clntWriteKey = keySpec.getClientCipherKey();
|
clntWriteKey = keySpec.getClientCipherKey();
|
||||||
svrWriteKey = keySpec.getServerCipherKey();
|
svrWriteKey = keySpec.getServerCipherKey();
|
||||||
|
|
||||||
|
// Return null if IVs are not supposed to be generated.
|
||||||
|
// e.g. TLS 1.1+.
|
||||||
clntWriteIV = keySpec.getClientIv();
|
clntWriteIV = keySpec.getClientIv();
|
||||||
svrWriteIV = keySpec.getServerIv();
|
svrWriteIV = keySpec.getServerIv();
|
||||||
|
|
||||||
|
@ -913,9 +1118,14 @@ abstract class Handshaker {
|
||||||
printHex(dump, clntWriteIV.getIV());
|
printHex(dump, clntWriteIV.getIV());
|
||||||
System.out.println("Server write IV:");
|
System.out.println("Server write IV:");
|
||||||
printHex(dump, svrWriteIV.getIV());
|
printHex(dump, svrWriteIV.getIV());
|
||||||
|
} else {
|
||||||
|
if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
|
||||||
|
System.out.println(
|
||||||
|
"... no IV derived for this protocol");
|
||||||
} else {
|
} else {
|
||||||
System.out.println("... no IV used for this cipher");
|
System.out.println("... no IV used for this cipher");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
System.out.flush();
|
System.out.flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -69,6 +69,7 @@ public class KerberosClientKeyExchange extends HandshakeMessage {
|
||||||
}
|
}
|
||||||
|
|
||||||
public KerberosClientKeyExchange() {
|
public KerberosClientKeyExchange() {
|
||||||
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
public KerberosClientKeyExchange(String serverName, boolean isLoopback,
|
public KerberosClientKeyExchange(String serverName, boolean isLoopback,
|
||||||
|
@ -93,14 +94,17 @@ public class KerberosClientKeyExchange extends HandshakeMessage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
int messageType() {
|
int messageType() {
|
||||||
return ht_client_key_exchange;
|
return ht_client_key_exchange;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int messageLength() {
|
public int messageLength() {
|
||||||
return impl.messageLength();
|
return impl.messageLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void send(HandshakeOutStream s) throws IOException {
|
public void send(HandshakeOutStream s) throws IOException {
|
||||||
impl.send(s);
|
impl.send(s);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -155,6 +155,42 @@ final class MAC {
|
||||||
return compute(type, bb, null, 0, bb.remaining());
|
return compute(type, bb, null, 0, bb.remaining());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether the sequence number is close to wrap
|
||||||
|
*
|
||||||
|
* Sequence numbers are of type uint64 and may not exceed 2^64-1.
|
||||||
|
* Sequence numbers do not wrap. When the sequence number is near
|
||||||
|
* to wrap, we need to close the connection immediately.
|
||||||
|
*/
|
||||||
|
final boolean seqNumOverflow() {
|
||||||
|
/*
|
||||||
|
* Conservatively, we don't allow more records to be generated
|
||||||
|
* when there are only 2^8 sequence numbers left.
|
||||||
|
*/
|
||||||
|
return (block != null && mac != null &&
|
||||||
|
block[0] == 0xFF && block[1] == 0xFF &&
|
||||||
|
block[2] == 0xFF && block[3] == 0xFF &&
|
||||||
|
block[4] == 0xFF && block[5] == 0xFF &&
|
||||||
|
block[6] == 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check whether to renew the sequence number
|
||||||
|
*
|
||||||
|
* Sequence numbers are of type uint64 and may not exceed 2^64-1.
|
||||||
|
* Sequence numbers do not wrap. If a TLS
|
||||||
|
* implementation would need to wrap a sequence number, it must
|
||||||
|
* renegotiate instead.
|
||||||
|
*/
|
||||||
|
final boolean seqNumIsHuge() {
|
||||||
|
/*
|
||||||
|
* Conservatively, we should ask for renegotiation when there are
|
||||||
|
* only 2^48 sequence numbers left.
|
||||||
|
*/
|
||||||
|
return (block != null && mac != null &&
|
||||||
|
block[0] == 0xFF && block[1] == 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
// increment the sequence number in the block array
|
// increment the sequence number in the block array
|
||||||
// it is a 64-bit number stored in big-endian format
|
// it is a 64-bit number stored in big-endian format
|
||||||
private void incrementSequenceNumber() {
|
private void incrementSequenceNumber() {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -38,8 +38,12 @@ import java.util.*;
|
||||||
final class ProtocolList {
|
final class ProtocolList {
|
||||||
|
|
||||||
private static final ProtocolList SUPPORTED;
|
private static final ProtocolList SUPPORTED;
|
||||||
|
private static final ProtocolList CLIENT_DEFAULT;
|
||||||
|
private static final ProtocolList SERVER_DEFAULT;
|
||||||
|
|
||||||
|
// the sorted protocol version list
|
||||||
|
private final ArrayList<ProtocolVersion> protocols;
|
||||||
|
|
||||||
private final Collection<ProtocolVersion> protocols;
|
|
||||||
private String[] protocolNames;
|
private String[] protocolNames;
|
||||||
|
|
||||||
// the minimum and maximum ProtocolVersions in this list
|
// the minimum and maximum ProtocolVersions in this list
|
||||||
|
@ -49,30 +53,45 @@ final class ProtocolList {
|
||||||
final ProtocolVersion helloVersion;
|
final ProtocolVersion helloVersion;
|
||||||
|
|
||||||
ProtocolList(String[] names) {
|
ProtocolList(String[] names) {
|
||||||
|
this(convert(names));
|
||||||
|
}
|
||||||
|
|
||||||
|
ProtocolList(ArrayList<ProtocolVersion> versions) {
|
||||||
|
this.protocols = versions;
|
||||||
|
|
||||||
|
if ((protocols.size() == 1) &&
|
||||||
|
protocols.contains(ProtocolVersion.SSL20Hello)) {
|
||||||
|
throw new IllegalArgumentException("SSLv2Hello cannot be " +
|
||||||
|
"enabled unless at least one other supported version " +
|
||||||
|
"is also enabled.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (protocols.size() != 0) {
|
||||||
|
Collections.sort(protocols);
|
||||||
|
min = protocols.get(0);
|
||||||
|
max = protocols.get(protocols.size() - 1);
|
||||||
|
helloVersion = protocols.get(0);
|
||||||
|
} else {
|
||||||
|
min = ProtocolVersion.NONE;
|
||||||
|
max = ProtocolVersion.NONE;
|
||||||
|
helloVersion = ProtocolVersion.NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ArrayList<ProtocolVersion> convert(String[] names) {
|
||||||
if (names == null) {
|
if (names == null) {
|
||||||
throw new IllegalArgumentException("Protocols may not be null");
|
throw new IllegalArgumentException("Protocols may not be null");
|
||||||
}
|
}
|
||||||
protocols = new ArrayList<ProtocolVersion>(3);
|
|
||||||
|
ArrayList<ProtocolVersion> versions = new ArrayList<ProtocolVersion>(3);
|
||||||
for (int i = 0; i < names.length; i++ ) {
|
for (int i = 0; i < names.length; i++ ) {
|
||||||
ProtocolVersion version = ProtocolVersion.valueOf(names[i]);
|
ProtocolVersion version = ProtocolVersion.valueOf(names[i]);
|
||||||
if (protocols.contains(version) == false) {
|
if (versions.contains(version) == false) {
|
||||||
protocols.add(version);
|
versions.add(version);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((protocols.size() == 1)
|
|
||||||
&& protocols.contains(ProtocolVersion.SSL20Hello)) {
|
return versions;
|
||||||
throw new IllegalArgumentException("SSLv2Hello" +
|
|
||||||
"cannot be enabled unless TLSv1 or SSLv3 is also enabled");
|
|
||||||
}
|
|
||||||
min = contains(ProtocolVersion.SSL30) ? ProtocolVersion.SSL30
|
|
||||||
: ProtocolVersion.TLS10;
|
|
||||||
max = contains(ProtocolVersion.TLS10) ? ProtocolVersion.TLS10
|
|
||||||
: ProtocolVersion.SSL30;
|
|
||||||
if (protocols.contains(ProtocolVersion.SSL20Hello)) {
|
|
||||||
helloVersion = ProtocolVersion.SSL20Hello;
|
|
||||||
} else {
|
|
||||||
helloVersion = min;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -87,6 +106,37 @@ final class ProtocolList {
|
||||||
return protocols.contains(protocolVersion);
|
return protocols.contains(protocolVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a reference to the internal Collection of CipherSuites.
|
||||||
|
* The Collection MUST NOT be modified.
|
||||||
|
*/
|
||||||
|
Collection<ProtocolVersion> collection() {
|
||||||
|
return protocols;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select a protocol version from the list.
|
||||||
|
*
|
||||||
|
* Return the lower of the protocol version of that suggested by
|
||||||
|
* the <code>protocolVersion</code> and the highest version of this
|
||||||
|
* protocol list, or null if no protocol version is available.
|
||||||
|
*
|
||||||
|
* The method is used by TLS server to negotiated the protocol
|
||||||
|
* version between client suggested protocol version in the
|
||||||
|
* client hello and protocol versions supported by the server.
|
||||||
|
*/
|
||||||
|
ProtocolVersion selectProtocolVersion(ProtocolVersion protocolVersion) {
|
||||||
|
ProtocolVersion selectedVersion = null;
|
||||||
|
for (ProtocolVersion pv : protocols) {
|
||||||
|
if (pv.v > protocolVersion.v) {
|
||||||
|
break; // Safe to break here as this.protocols is sorted
|
||||||
|
}
|
||||||
|
selectedVersion = pv;
|
||||||
|
}
|
||||||
|
|
||||||
|
return selectedVersion;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an array with the names of the ProtocolVersions in this list.
|
* Return an array with the names of the ProtocolVersions in this list.
|
||||||
*/
|
*/
|
||||||
|
@ -106,11 +156,18 @@ final class ProtocolList {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the list of default enabled protocols. Currently, this
|
* Return the list of default enabled protocols.
|
||||||
* is identical to the supported protocols.
|
|
||||||
*/
|
*/
|
||||||
static ProtocolList getDefault() {
|
static ProtocolList getDefault(boolean isServer) {
|
||||||
return SUPPORTED;
|
return isServer ? SERVER_DEFAULT : CLIENT_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether a protocol list is the original default enabled
|
||||||
|
* protocols. See: SSLSocket/SSLEngine.setEnabledProtocols()
|
||||||
|
*/
|
||||||
|
static boolean isDefaultProtocolList(ProtocolList protocols) {
|
||||||
|
return protocols == CLIENT_DEFAULT || protocols == SERVER_DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -123,6 +180,12 @@ final class ProtocolList {
|
||||||
static {
|
static {
|
||||||
if (SunJSSE.isFIPS()) {
|
if (SunJSSE.isFIPS()) {
|
||||||
SUPPORTED = new ProtocolList(new String[] {
|
SUPPORTED = new ProtocolList(new String[] {
|
||||||
|
ProtocolVersion.TLS10.name,
|
||||||
|
ProtocolVersion.TLS11.name
|
||||||
|
});
|
||||||
|
|
||||||
|
SERVER_DEFAULT = SUPPORTED;
|
||||||
|
CLIENT_DEFAULT = new ProtocolList(new String[] {
|
||||||
ProtocolVersion.TLS10.name
|
ProtocolVersion.TLS10.name
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -130,6 +193,13 @@ final class ProtocolList {
|
||||||
ProtocolVersion.SSL20Hello.name,
|
ProtocolVersion.SSL20Hello.name,
|
||||||
ProtocolVersion.SSL30.name,
|
ProtocolVersion.SSL30.name,
|
||||||
ProtocolVersion.TLS10.name,
|
ProtocolVersion.TLS10.name,
|
||||||
|
ProtocolVersion.TLS11.name
|
||||||
|
});
|
||||||
|
|
||||||
|
SERVER_DEFAULT = SUPPORTED;
|
||||||
|
CLIENT_DEFAULT = new ProtocolList(new String[] {
|
||||||
|
ProtocolVersion.SSL30.name,
|
||||||
|
ProtocolVersion.TLS10.name
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -45,9 +45,12 @@ package sun.security.ssl;
|
||||||
* @author Andreas Sterbenz
|
* @author Andreas Sterbenz
|
||||||
* @since 1.4.1
|
* @since 1.4.1
|
||||||
*/
|
*/
|
||||||
public final class ProtocolVersion {
|
public final class ProtocolVersion implements Comparable<ProtocolVersion> {
|
||||||
|
|
||||||
// dummy protocol version value for invalid SSLSession
|
// The limit of maximum protocol version
|
||||||
|
final static int LIMIT_MAX_VALUE = 0xFFFF;
|
||||||
|
|
||||||
|
// Dummy protocol version value for invalid SSLSession
|
||||||
final static ProtocolVersion NONE = new ProtocolVersion(-1, "NONE");
|
final static ProtocolVersion NONE = new ProtocolVersion(-1, "NONE");
|
||||||
|
|
||||||
// If enabled, send/ accept SSLv2 hello messages
|
// If enabled, send/ accept SSLv2 hello messages
|
||||||
|
@ -61,22 +64,24 @@ public final class ProtocolVersion {
|
||||||
final static ProtocolVersion TLS10 = new ProtocolVersion(0x0301, "TLSv1");
|
final static ProtocolVersion TLS10 = new ProtocolVersion(0x0301, "TLSv1");
|
||||||
|
|
||||||
// TLS 1.1
|
// TLS 1.1
|
||||||
// not supported yet, but added for better readability of the debug trace
|
|
||||||
final static ProtocolVersion TLS11 = new ProtocolVersion(0x0302, "TLSv1.1");
|
final static ProtocolVersion TLS11 = new ProtocolVersion(0x0302, "TLSv1.1");
|
||||||
|
|
||||||
|
// TLS 1.2
|
||||||
|
final static ProtocolVersion TLS12 = new ProtocolVersion(0x0303, "TLSv1.2");
|
||||||
|
|
||||||
private static final boolean FIPS = SunJSSE.isFIPS();
|
private static final boolean FIPS = SunJSSE.isFIPS();
|
||||||
|
|
||||||
// minimum version we implement (SSL 3.0)
|
// minimum version we implement (SSL 3.0)
|
||||||
final static ProtocolVersion MIN = FIPS ? TLS10 : SSL30;
|
final static ProtocolVersion MIN = FIPS ? TLS10 : SSL30;
|
||||||
|
|
||||||
// maximum version we implement (TLS 1.0)
|
// maximum version we implement (TLS 1.1)
|
||||||
final static ProtocolVersion MAX = TLS10;
|
final static ProtocolVersion MAX = TLS11;
|
||||||
|
|
||||||
// ProtocolVersion to use by default (TLS 1.0)
|
// ProtocolVersion to use by default (TLS 1.0)
|
||||||
final static ProtocolVersion DEFAULT = TLS10;
|
final static ProtocolVersion DEFAULT = TLS10;
|
||||||
|
|
||||||
// Default version for hello messages (SSLv2Hello)
|
// Default version for hello messages (SSLv2Hello)
|
||||||
final static ProtocolVersion DEFAULT_HELLO = FIPS ? TLS10 : SSL20Hello;
|
final static ProtocolVersion DEFAULT_HELLO = FIPS ? TLS10 : SSL30;
|
||||||
|
|
||||||
// version in 16 bit MSB format as it appears in records and
|
// version in 16 bit MSB format as it appears in records and
|
||||||
// messages, i.e. 0x0301 for TLS 1.0
|
// messages, i.e. 0x0301 for TLS 1.0
|
||||||
|
@ -104,6 +109,8 @@ public final class ProtocolVersion {
|
||||||
return TLS10;
|
return TLS10;
|
||||||
} else if (v == TLS11.v) {
|
} else if (v == TLS11.v) {
|
||||||
return TLS11;
|
return TLS11;
|
||||||
|
} else if (v == TLS12.v) {
|
||||||
|
return TLS12;
|
||||||
} else if (v == SSL20Hello.v) {
|
} else if (v == SSL20Hello.v) {
|
||||||
return SSL20Hello;
|
return SSL20Hello;
|
||||||
} else {
|
} else {
|
||||||
|
@ -134,18 +141,20 @@ public final class ProtocolVersion {
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
throw new IllegalArgumentException("Protocol cannot be null");
|
throw new IllegalArgumentException("Protocol cannot be null");
|
||||||
}
|
}
|
||||||
if (FIPS) {
|
|
||||||
if (name.equals(TLS10.name)) {
|
if (FIPS && (name.equals(SSL30.name) || name.equals(SSL20Hello.name))) {
|
||||||
return TLS10;
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException
|
throw new IllegalArgumentException
|
||||||
("Only TLS 1.0 allowed in FIPS mode");
|
("Only TLS 1.0 or later allowed in FIPS mode");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name.equals(SSL30.name)) {
|
if (name.equals(SSL30.name)) {
|
||||||
return SSL30;
|
return SSL30;
|
||||||
} else if (name.equals(TLS10.name)) {
|
} else if (name.equals(TLS10.name)) {
|
||||||
return TLS10;
|
return TLS10;
|
||||||
|
} else if (name.equals(TLS11.name)) {
|
||||||
|
return TLS11;
|
||||||
|
} else if (name.equals(TLS12.name)) {
|
||||||
|
return TLS12;
|
||||||
} else if (name.equals(SSL20Hello.name)) {
|
} else if (name.equals(SSL20Hello.name)) {
|
||||||
return SSL20Hello;
|
return SSL20Hello;
|
||||||
} else {
|
} else {
|
||||||
|
@ -157,4 +166,10 @@ public final class ProtocolVersion {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares this object with the specified object for order.
|
||||||
|
*/
|
||||||
|
public int compareTo(ProtocolVersion protocolVersion) {
|
||||||
|
return this.v - protocolVersion.v;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -55,20 +55,17 @@ final class RSAClientKeyExchange extends HandshakeMessage {
|
||||||
* requested in its client hello version). However, we (and other
|
* requested in its client hello version). However, we (and other
|
||||||
* implementations) used to send the active negotiated version. The
|
* implementations) used to send the active negotiated version. The
|
||||||
* system property below allows to toggle the behavior.
|
* system property below allows to toggle the behavior.
|
||||||
*
|
|
||||||
* Default is "false" (old behavior) for compatibility reasons. This
|
|
||||||
* will be changed in the future.
|
|
||||||
*/
|
*/
|
||||||
private final static String PROP_NAME =
|
private final static String PROP_NAME =
|
||||||
"com.sun.net.ssl.rsaPreMasterSecretFix";
|
"com.sun.net.ssl.rsaPreMasterSecretFix";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Default is "false" (old behavior) for compatibility reasons in
|
||||||
|
* SSLv3/TLSv1. Later protocols (TLSv1.1+) do not use this property.
|
||||||
|
*/
|
||||||
private final static boolean rsaPreMasterSecretFix =
|
private final static boolean rsaPreMasterSecretFix =
|
||||||
Debug.getBooleanProperty(PROP_NAME, false);
|
Debug.getBooleanProperty(PROP_NAME, false);
|
||||||
|
|
||||||
int messageType() {
|
|
||||||
return ht_client_key_exchange;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following field values were encrypted with the server's public
|
* The following field values were encrypted with the server's public
|
||||||
* key (or temp key from server key exchange msg) and are presented
|
* key (or temp key from server key exchange msg) and are presented
|
||||||
|
@ -78,14 +75,14 @@ final class RSAClientKeyExchange extends HandshakeMessage {
|
||||||
SecretKey preMaster;
|
SecretKey preMaster;
|
||||||
private byte[] encrypted; // same size as public modulus
|
private byte[] encrypted; // same size as public modulus
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Client randomly creates a pre-master secret and encrypts it
|
* Client randomly creates a pre-master secret and encrypts it
|
||||||
* using the server's RSA public key; only the server can decrypt
|
* using the server's RSA public key; only the server can decrypt
|
||||||
* it, using its RSA private key. Result is the same size as the
|
* it, using its RSA private key. Result is the same size as the
|
||||||
* server's public key, and uses PKCS #1 block format 02.
|
* server's public key, and uses PKCS #1 block format 02.
|
||||||
*/
|
*/
|
||||||
RSAClientKeyExchange(ProtocolVersion protocolVersion, ProtocolVersion maxVersion,
|
RSAClientKeyExchange(ProtocolVersion protocolVersion,
|
||||||
|
ProtocolVersion maxVersion,
|
||||||
SecureRandom generator, PublicKey publicKey) throws IOException {
|
SecureRandom generator, PublicKey publicKey) throws IOException {
|
||||||
if (publicKey.getAlgorithm().equals("RSA") == false) {
|
if (publicKey.getAlgorithm().equals("RSA") == false) {
|
||||||
throw new SSLKeyException("Public key not of type RSA");
|
throw new SSLKeyException("Public key not of type RSA");
|
||||||
|
@ -94,7 +91,7 @@ final class RSAClientKeyExchange extends HandshakeMessage {
|
||||||
|
|
||||||
int major, minor;
|
int major, minor;
|
||||||
|
|
||||||
if (rsaPreMasterSecretFix) {
|
if (rsaPreMasterSecretFix || maxVersion.v >= ProtocolVersion.TLS11.v) {
|
||||||
major = maxVersion.major;
|
major = maxVersion.major;
|
||||||
minor = maxVersion.minor;
|
minor = maxVersion.minor;
|
||||||
} else {
|
} else {
|
||||||
|
@ -103,7 +100,8 @@ final class RSAClientKeyExchange extends HandshakeMessage {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
KeyGenerator kg = JsseJce.getKeyGenerator("SunTlsRsaPremasterSecret");
|
KeyGenerator kg =
|
||||||
|
JsseJce.getKeyGenerator("SunTlsRsaPremasterSecret");
|
||||||
kg.init(new TlsRsaPremasterSecretParameterSpec(major, minor));
|
kg.init(new TlsRsaPremasterSecretParameterSpec(major, minor));
|
||||||
preMaster = kg.generateKey();
|
preMaster = kg.generateKey();
|
||||||
|
|
||||||
|
@ -120,14 +118,15 @@ final class RSAClientKeyExchange extends HandshakeMessage {
|
||||||
* Server gets the PKCS #1 (block format 02) data, decrypts
|
* Server gets the PKCS #1 (block format 02) data, decrypts
|
||||||
* it with its private key.
|
* it with its private key.
|
||||||
*/
|
*/
|
||||||
RSAClientKeyExchange(ProtocolVersion currentVersion, HandshakeInStream input,
|
RSAClientKeyExchange(ProtocolVersion currentVersion,
|
||||||
|
ProtocolVersion maxVersion,
|
||||||
|
SecureRandom generator, HandshakeInStream input,
|
||||||
int messageSize, PrivateKey privateKey) throws IOException {
|
int messageSize, PrivateKey privateKey) throws IOException {
|
||||||
|
|
||||||
if (privateKey.getAlgorithm().equals("RSA") == false) {
|
if (privateKey.getAlgorithm().equals("RSA") == false) {
|
||||||
throw new SSLKeyException("Private key not of type RSA");
|
throw new SSLKeyException("Private key not of type RSA");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.protocolVersion = currentVersion;
|
|
||||||
if (currentVersion.v >= ProtocolVersion.TLS10.v) {
|
if (currentVersion.v >= ProtocolVersion.TLS10.v) {
|
||||||
encrypted = input.getBytes16();
|
encrypted = input.getBytes16();
|
||||||
} else {
|
} else {
|
||||||
|
@ -143,24 +142,101 @@ final class RSAClientKeyExchange extends HandshakeMessage {
|
||||||
cipher.init(Cipher.UNWRAP_MODE, privateKey);
|
cipher.init(Cipher.UNWRAP_MODE, privateKey);
|
||||||
preMaster = (SecretKey)cipher.unwrap(encrypted,
|
preMaster = (SecretKey)cipher.unwrap(encrypted,
|
||||||
"TlsRsaPremasterSecret", Cipher.SECRET_KEY);
|
"TlsRsaPremasterSecret", Cipher.SECRET_KEY);
|
||||||
|
|
||||||
|
// polish the premaster secret
|
||||||
|
preMaster = polishPreMasterSecretKey(currentVersion, maxVersion,
|
||||||
|
generator, preMaster, null);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
/*
|
// polish the premaster secret
|
||||||
* Bogus decrypted ClientKeyExchange? If so, conjure a
|
preMaster =
|
||||||
* a random preMaster secret that will fail later during
|
polishPreMasterSecretKey(currentVersion, maxVersion,
|
||||||
* Finished message processing. This is a countermeasure against
|
generator, null, e);
|
||||||
* the "interactive RSA PKCS#1 encryption envelop attack" reported
|
}
|
||||||
* in June 1998. Preserving the executation path will
|
}
|
||||||
* mitigate timing attacks and force consistent error handling
|
|
||||||
* that will prevent an attacking client from differentiating
|
/**
|
||||||
* different kinds of decrypted ClientKeyExchange bogosities.
|
* To avoid vulnerabilities described by section 7.4.7.1, RFC 5246,
|
||||||
|
* treating incorrectly formatted message blocks and/or mismatched
|
||||||
|
* version numbers in a manner indistinguishable from correctly
|
||||||
|
* formatted RSA blocks.
|
||||||
|
*
|
||||||
|
* RFC 5246 describes the approach as :
|
||||||
|
*
|
||||||
|
* 1. Generate a string R of 46 random bytes
|
||||||
|
*
|
||||||
|
* 2. Decrypt the message to recover the plaintext M
|
||||||
|
*
|
||||||
|
* 3. If the PKCS#1 padding is not correct, or the length of message
|
||||||
|
* M is not exactly 48 bytes:
|
||||||
|
* pre_master_secret = ClientHello.client_version || R
|
||||||
|
* else If ClientHello.client_version <= TLS 1.0, and version
|
||||||
|
* number check is explicitly disabled:
|
||||||
|
* pre_master_secret = M
|
||||||
|
* else:
|
||||||
|
* pre_master_secret = ClientHello.client_version || M[2..47]
|
||||||
*/
|
*/
|
||||||
|
private SecretKey polishPreMasterSecretKey(ProtocolVersion currentVersion,
|
||||||
|
ProtocolVersion clientHelloVersion, SecureRandom generator,
|
||||||
|
SecretKey secretKey, Exception failoverException) {
|
||||||
|
|
||||||
|
this.protocolVersion = clientHelloVersion;
|
||||||
|
|
||||||
|
if (failoverException == null && secretKey != null) {
|
||||||
|
// check the length
|
||||||
|
byte[] encoded = secretKey.getEncoded();
|
||||||
|
if (encoded == null) { // unable to get the encoded key
|
||||||
if (debug != null && Debug.isOn("handshake")) {
|
if (debug != null && Debug.isOn("handshake")) {
|
||||||
|
System.out.println(
|
||||||
|
"unable to get the plaintext of the premaster secret");
|
||||||
|
}
|
||||||
|
|
||||||
|
// We are not always able to get the encoded key of the
|
||||||
|
// premaster secret. Pass the cheking to master secret
|
||||||
|
// calculation.
|
||||||
|
return secretKey;
|
||||||
|
} else if (encoded.length == 48) {
|
||||||
|
// check the version
|
||||||
|
if (clientHelloVersion.major == encoded[0] &&
|
||||||
|
clientHelloVersion.minor == encoded[1]) {
|
||||||
|
return secretKey;
|
||||||
|
} else if (clientHelloVersion.v <= ProtocolVersion.TLS10.v) {
|
||||||
|
/*
|
||||||
|
* we never checked the client_version in server side
|
||||||
|
* for TLS v1.0 and SSL v3.0. For compatibility, we
|
||||||
|
* maintain this behavior.
|
||||||
|
*/
|
||||||
|
if (currentVersion.major == encoded[0] &&
|
||||||
|
currentVersion.minor == encoded[1]) {
|
||||||
|
this.protocolVersion = currentVersion;
|
||||||
|
return secretKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug != null && Debug.isOn("handshake")) {
|
||||||
|
System.out.println("Mismatching Protocol Versions, " +
|
||||||
|
"ClientHello.client_version is " + clientHelloVersion +
|
||||||
|
", while PreMasterSecret.client_version is " +
|
||||||
|
ProtocolVersion.valueOf(encoded[0], encoded[1]));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (debug != null && Debug.isOn("handshake")) {
|
||||||
|
System.out.println(
|
||||||
|
"incorrect length of premaster secret: " +
|
||||||
|
encoded.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug != null && Debug.isOn("handshake")) {
|
||||||
|
if (failoverException != null) {
|
||||||
System.out.println("Error decrypting premaster secret:");
|
System.out.println("Error decrypting premaster secret:");
|
||||||
e.printStackTrace(System.out);
|
failoverException.printStackTrace(System.out);
|
||||||
|
}
|
||||||
|
|
||||||
System.out.println("Generating random secret");
|
System.out.println("Generating random secret");
|
||||||
}
|
}
|
||||||
preMaster = generateDummySecret(currentVersion);
|
|
||||||
}
|
return generateDummySecret(clientHelloVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate a premaster secret with the specified version number
|
// generate a premaster secret with the specified version number
|
||||||
|
@ -176,6 +252,12 @@ final class RSAClientKeyExchange extends HandshakeMessage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
int messageType() {
|
||||||
|
return ht_client_key_exchange;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
int messageLength() {
|
int messageLength() {
|
||||||
if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
|
if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
|
||||||
return encrypted.length + 2;
|
return encrypted.length + 2;
|
||||||
|
@ -184,6 +266,7 @@ final class RSAClientKeyExchange extends HandshakeMessage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
void send(HandshakeOutStream s) throws IOException {
|
void send(HandshakeOutStream s) throws IOException {
|
||||||
if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
|
if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
|
||||||
s.putBytes16(encrypted);
|
s.putBytes16(encrypted);
|
||||||
|
@ -192,7 +275,9 @@ final class RSAClientKeyExchange extends HandshakeMessage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
void print(PrintStream s) throws IOException {
|
void print(PrintStream s) throws IOException {
|
||||||
s.println("*** ClientKeyExchange, RSA PreMasterSecret, " + protocolVersion);
|
s.println("*** ClientKeyExchange, RSA PreMasterSecret, " +
|
||||||
|
protocolVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -52,6 +52,7 @@ interface Record {
|
||||||
static final int trailerSize = 20; // SHA1 hash size
|
static final int trailerSize = 20; // SHA1 hash size
|
||||||
static final int maxDataSize = 16384; // 2^14 bytes of data
|
static final int maxDataSize = 16384; // 2^14 bytes of data
|
||||||
static final int maxPadding = 256; // block cipher padding
|
static final int maxPadding = 256; // block cipher padding
|
||||||
|
static final int maxIVLength = 256; // block length
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SSL has a maximum record size. It's header, (compressed) data,
|
* SSL has a maximum record size. It's header, (compressed) data,
|
||||||
|
@ -61,6 +62,7 @@ interface Record {
|
||||||
*/
|
*/
|
||||||
static final int maxRecordSize =
|
static final int maxRecordSize =
|
||||||
headerSize // header
|
headerSize // header
|
||||||
|
+ maxIVLength // iv
|
||||||
+ maxDataSize // data
|
+ maxDataSize // data
|
||||||
+ maxPadding // padding
|
+ maxPadding // padding
|
||||||
+ trailerSize; // MAC
|
+ trailerSize; // MAC
|
||||||
|
@ -85,6 +87,10 @@ interface Record {
|
||||||
* Allocate a smaller array.
|
* Allocate a smaller array.
|
||||||
*/
|
*/
|
||||||
static final int maxAlertRecordSize =
|
static final int maxAlertRecordSize =
|
||||||
headerSize + 2 + maxPadding + trailerSize;
|
headerSize // header
|
||||||
|
+ maxIVLength // iv
|
||||||
|
+ 2 // alert
|
||||||
|
+ maxPadding // padding
|
||||||
|
+ trailerSize; // MAC
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -240,12 +240,14 @@ final public class SSLEngineImpl extends SSLEngine {
|
||||||
* session is changed.
|
* session is changed.
|
||||||
*/
|
*/
|
||||||
private byte doClientAuth;
|
private byte doClientAuth;
|
||||||
private CipherSuiteList enabledCipherSuites;
|
|
||||||
private boolean enableSessionCreation = true;
|
private boolean enableSessionCreation = true;
|
||||||
EngineInputRecord inputRecord;
|
EngineInputRecord inputRecord;
|
||||||
EngineOutputRecord outputRecord;
|
EngineOutputRecord outputRecord;
|
||||||
private AccessControlContext acc;
|
private AccessControlContext acc;
|
||||||
|
|
||||||
|
// The cipher suites enabled for use on this connection.
|
||||||
|
private CipherSuiteList enabledCipherSuites;
|
||||||
|
|
||||||
// hostname identification algorithm, the hostname identification is
|
// hostname identification algorithm, the hostname identification is
|
||||||
// disabled by default.
|
// disabled by default.
|
||||||
private String identificationAlg = null;
|
private String identificationAlg = null;
|
||||||
|
@ -255,11 +257,11 @@ final public class SSLEngineImpl extends SSLEngine {
|
||||||
private boolean roleIsServer;
|
private boolean roleIsServer;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The protocols we support are SSL Version 3.0) and
|
* The protocol versions enabled for use on this connection.
|
||||||
* TLS (version 3.1).
|
*
|
||||||
* In addition we support a pseudo protocol called
|
* Note: we support a pseudo protocol called SSLv2Hello which when
|
||||||
* SSLv2Hello which when set will result in an SSL v2 Hello
|
* set will result in an SSL v2 Hello being sent with SSL (version 3.0)
|
||||||
* being sent with SSLv3 or TLSv1 version info.
|
* or TLS (version 3.1, 3.2, etc.) version info.
|
||||||
*/
|
*/
|
||||||
private ProtocolList enabledProtocols;
|
private ProtocolList enabledProtocols;
|
||||||
|
|
||||||
|
@ -368,7 +370,7 @@ final public class SSLEngineImpl extends SSLEngine {
|
||||||
serverVerifyData = new byte[0];
|
serverVerifyData = new byte[0];
|
||||||
|
|
||||||
enabledCipherSuites = CipherSuiteList.getDefault();
|
enabledCipherSuites = CipherSuiteList.getDefault();
|
||||||
enabledProtocols = ProtocolList.getDefault();
|
enabledProtocols = ProtocolList.getDefault(roleIsServer);
|
||||||
|
|
||||||
wrapLock = new Object();
|
wrapLock = new Object();
|
||||||
unwrapLock = new Object();
|
unwrapLock = new Object();
|
||||||
|
@ -405,8 +407,8 @@ final public class SSLEngineImpl extends SSLEngine {
|
||||||
* . if the engine is already closed, throw an Exception (internal error)
|
* . if the engine is already closed, throw an Exception (internal error)
|
||||||
*
|
*
|
||||||
* . otherwise (cs_START or cs_DATA), create the appropriate handshaker
|
* . otherwise (cs_START or cs_DATA), create the appropriate handshaker
|
||||||
* object, initialize it, and advance the connection state (to
|
* object and advance the connection state (to cs_HANDSHAKE or
|
||||||
* cs_HANDSHAKE or cs_RENEGOTIATE, respectively).
|
* cs_RENEGOTIATE, respectively).
|
||||||
*
|
*
|
||||||
* This method is called right after a new engine is created, when
|
* This method is called right after a new engine is created, when
|
||||||
* starting renegotiation, or when changing client/server mode of the
|
* starting renegotiation, or when changing client/server mode of the
|
||||||
|
@ -454,12 +456,8 @@ final public class SSLEngineImpl extends SSLEngine {
|
||||||
protocolVersion, connectionState == cs_HANDSHAKE,
|
protocolVersion, connectionState == cs_HANDSHAKE,
|
||||||
secureRenegotiation, clientVerifyData, serverVerifyData);
|
secureRenegotiation, clientVerifyData, serverVerifyData);
|
||||||
}
|
}
|
||||||
handshaker.enabledCipherSuites = enabledCipherSuites;
|
handshaker.setEnabledCipherSuites(enabledCipherSuites);
|
||||||
handshaker.setEnableSessionCreation(enableSessionCreation);
|
handshaker.setEnableSessionCreation(enableSessionCreation);
|
||||||
if (connectionState == cs_RENEGOTIATE) {
|
|
||||||
// don't use SSLv2Hello when renegotiating
|
|
||||||
handshaker.output.r.setHelloVersion(protocolVersion);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -686,7 +684,15 @@ final public class SSLEngineImpl extends SSLEngine {
|
||||||
// to its HandshakeOutStream, which calls back into
|
// to its HandshakeOutStream, which calls back into
|
||||||
// SSLSocketImpl.writeRecord() to send it.
|
// SSLSocketImpl.writeRecord() to send it.
|
||||||
//
|
//
|
||||||
if (!handshaker.started()) {
|
if (!handshaker.activated()) {
|
||||||
|
// prior to handshaking, activate the handshake
|
||||||
|
if (connectionState == cs_RENEGOTIATE) {
|
||||||
|
// don't use SSLv2Hello when renegotiating
|
||||||
|
handshaker.activate(protocolVersion);
|
||||||
|
} else {
|
||||||
|
handshaker.activate(null);
|
||||||
|
}
|
||||||
|
|
||||||
if (handshaker instanceof ClientHandshaker) {
|
if (handshaker instanceof ClientHandshaker) {
|
||||||
// send client hello
|
// send client hello
|
||||||
handshaker.kickstart();
|
handshaker.kickstart();
|
||||||
|
@ -696,6 +702,7 @@ final public class SSLEngineImpl extends SSLEngine {
|
||||||
} else {
|
} else {
|
||||||
// we want to renegotiate, send hello request
|
// we want to renegotiate, send hello request
|
||||||
handshaker.kickstart();
|
handshaker.kickstart();
|
||||||
|
|
||||||
// hello request is not included in the handshake
|
// hello request is not included in the handshake
|
||||||
// hashes, reset them
|
// hashes, reset them
|
||||||
handshaker.handshakeHash.reset();
|
handshaker.handshakeHash.reset();
|
||||||
|
@ -982,6 +989,15 @@ final public class SSLEngineImpl extends SSLEngine {
|
||||||
* in it.
|
* in it.
|
||||||
*/
|
*/
|
||||||
initHandshaker();
|
initHandshaker();
|
||||||
|
if (!handshaker.activated()) {
|
||||||
|
// prior to handshaking, activate the handshake
|
||||||
|
if (connectionState == cs_RENEGOTIATE) {
|
||||||
|
// don't use SSLv2Hello when renegotiating
|
||||||
|
handshaker.activate(protocolVersion);
|
||||||
|
} else {
|
||||||
|
handshaker.activate(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* process the handshake record ... may contain just
|
* process the handshake record ... may contain just
|
||||||
|
@ -1081,6 +1097,26 @@ final public class SSLEngineImpl extends SSLEngine {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
} // switch
|
} // switch
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We only need to check the sequence number state for
|
||||||
|
* non-handshaking record.
|
||||||
|
*
|
||||||
|
* Note that in order to maintain the handshake status
|
||||||
|
* properly, we check the sequence number after the last
|
||||||
|
* record reading process. As we request renegotiation
|
||||||
|
* or close the connection for wrapped sequence number
|
||||||
|
* when there is enough sequence number space left to
|
||||||
|
* handle a few more records, so the sequence number
|
||||||
|
* of the last record cannot be wrapped.
|
||||||
|
*/
|
||||||
|
if (connectionState < cs_ERROR && !isInboundDone() &&
|
||||||
|
(hsStatus == HandshakeStatus.NOT_HANDSHAKING)) {
|
||||||
|
if (checkSequenceNumber(readMAC,
|
||||||
|
inputRecord.contentType())) {
|
||||||
|
hsStatus = getHSStatus(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
} // synchronized (this)
|
} // synchronized (this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1229,7 +1265,29 @@ final public class SSLEngineImpl extends SSLEngine {
|
||||||
EngineArgs ea) throws IOException {
|
EngineArgs ea) throws IOException {
|
||||||
|
|
||||||
// eventually compress as well.
|
// eventually compress as well.
|
||||||
return writer.writeRecord(eor, ea, writeMAC, writeCipher);
|
HandshakeStatus hsStatus =
|
||||||
|
writer.writeRecord(eor, ea, writeMAC, writeCipher);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We only need to check the sequence number state for
|
||||||
|
* non-handshaking record.
|
||||||
|
*
|
||||||
|
* Note that in order to maintain the handshake status
|
||||||
|
* properly, we check the sequence number after the last
|
||||||
|
* record writing process. As we request renegotiation
|
||||||
|
* or close the connection for wrapped sequence number
|
||||||
|
* when there is enough sequence number space left to
|
||||||
|
* handle a few more records, so the sequence number
|
||||||
|
* of the last record cannot be wrapped.
|
||||||
|
*/
|
||||||
|
if (connectionState < cs_ERROR && !isOutboundDone() &&
|
||||||
|
(hsStatus == HandshakeStatus.NOT_HANDSHAKING)) {
|
||||||
|
if (checkSequenceNumber(writeMAC, eor.contentType())) {
|
||||||
|
hsStatus = getHSStatus(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return hsStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1238,12 +1296,88 @@ final public class SSLEngineImpl extends SSLEngine {
|
||||||
void writeRecord(EngineOutputRecord eor) throws IOException {
|
void writeRecord(EngineOutputRecord eor) throws IOException {
|
||||||
// eventually compress as well.
|
// eventually compress as well.
|
||||||
writer.writeRecord(eor, writeMAC, writeCipher);
|
writer.writeRecord(eor, writeMAC, writeCipher);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check the sequence number state
|
||||||
|
*
|
||||||
|
* Note that in order to maintain the connection I/O
|
||||||
|
* properly, we check the sequence number after the last
|
||||||
|
* record writing process. As we request renegotiation
|
||||||
|
* or close the connection for wrapped sequence number
|
||||||
|
* when there is enough sequence number space left to
|
||||||
|
* handle a few more records, so the sequence number
|
||||||
|
* of the last record cannot be wrapped.
|
||||||
|
*/
|
||||||
|
if ((connectionState < cs_ERROR) && !isOutboundDone()) {
|
||||||
|
checkSequenceNumber(writeMAC, eor.contentType());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Close code
|
// Close code
|
||||||
//
|
//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the sequence number state
|
||||||
|
*
|
||||||
|
* RFC 4346 states that, "Sequence numbers are of type uint64 and
|
||||||
|
* may not exceed 2^64-1. Sequence numbers do not wrap. If a TLS
|
||||||
|
* implementation would need to wrap a sequence number, it must
|
||||||
|
* renegotiate instead."
|
||||||
|
*
|
||||||
|
* Return true if the handshake status may be changed.
|
||||||
|
*/
|
||||||
|
private boolean checkSequenceNumber(MAC mac, byte type)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Don't bother to check the sequence number for error or
|
||||||
|
* closed connections, or NULL MAC
|
||||||
|
*/
|
||||||
|
if (connectionState >= cs_ERROR || mac == MAC.NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Conservatively, close the connection immediately when the
|
||||||
|
* sequence number is close to overflow
|
||||||
|
*/
|
||||||
|
if (mac.seqNumOverflow()) {
|
||||||
|
/*
|
||||||
|
* TLS protocols do not define a error alert for sequence
|
||||||
|
* number overflow. We use handshake_failure error alert
|
||||||
|
* for handshaking and bad_record_mac for other records.
|
||||||
|
*/
|
||||||
|
if (debug != null && Debug.isOn("ssl")) {
|
||||||
|
System.out.println(threadName() +
|
||||||
|
", sequence number extremely close to overflow " +
|
||||||
|
"(2^64-1 packets). Closing connection.");
|
||||||
|
}
|
||||||
|
|
||||||
|
fatal(Alerts.alert_handshake_failure, "sequence number overflow");
|
||||||
|
|
||||||
|
return true; // make the compiler happy
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ask for renegotiation when need to renew sequence number.
|
||||||
|
*
|
||||||
|
* Don't bother to kickstart the renegotiation when the local is
|
||||||
|
* asking for it.
|
||||||
|
*/
|
||||||
|
if ((type != Record.ct_handshake) && mac.seqNumIsHuge()) {
|
||||||
|
if (debug != null && Debug.isOn("ssl")) {
|
||||||
|
System.out.println(threadName() + ", request renegotiation " +
|
||||||
|
"to avoid sequence number overflow");
|
||||||
|
}
|
||||||
|
|
||||||
|
beginHandshake();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signals that no more outbound application data will be sent
|
* Signals that no more outbound application data will be sent
|
||||||
* on this <code>SSLEngine</code>.
|
* on this <code>SSLEngine</code>.
|
||||||
|
@ -1594,10 +1728,18 @@ final public class SSLEngineImpl extends SSLEngine {
|
||||||
* Emit alerts. Caller must have synchronized with "this".
|
* Emit alerts. Caller must have synchronized with "this".
|
||||||
*/
|
*/
|
||||||
private void sendAlert(byte level, byte description) {
|
private void sendAlert(byte level, byte description) {
|
||||||
|
// the connectionState cannot be cs_START
|
||||||
if (connectionState >= cs_CLOSED) {
|
if (connectionState >= cs_CLOSED) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For initial handshaking, don't send alert message to peer if
|
||||||
|
// handshaker has not started.
|
||||||
|
if (connectionState == cs_HANDSHAKE &&
|
||||||
|
(handshaker == null || !handshaker.started())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
EngineOutputRecord r = new EngineOutputRecord(Record.ct_alert, this);
|
EngineOutputRecord r = new EngineOutputRecord(Record.ct_alert, this);
|
||||||
r.setVersion(protocolVersion);
|
r.setVersion(protocolVersion);
|
||||||
|
|
||||||
|
@ -1647,7 +1789,7 @@ final public class SSLEngineImpl extends SSLEngine {
|
||||||
synchronized public void setEnableSessionCreation(boolean flag) {
|
synchronized public void setEnableSessionCreation(boolean flag) {
|
||||||
enableSessionCreation = flag;
|
enableSessionCreation = flag;
|
||||||
|
|
||||||
if ((handshaker != null) && !handshaker.started()) {
|
if ((handshaker != null) && !handshaker.activated()) {
|
||||||
handshaker.setEnableSessionCreation(enableSessionCreation);
|
handshaker.setEnableSessionCreation(enableSessionCreation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1675,7 +1817,7 @@ final public class SSLEngineImpl extends SSLEngine {
|
||||||
|
|
||||||
if ((handshaker != null) &&
|
if ((handshaker != null) &&
|
||||||
(handshaker instanceof ServerHandshaker) &&
|
(handshaker instanceof ServerHandshaker) &&
|
||||||
!handshaker.started()) {
|
!handshaker.activated()) {
|
||||||
((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
|
((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1698,7 +1840,7 @@ final public class SSLEngineImpl extends SSLEngine {
|
||||||
|
|
||||||
if ((handshaker != null) &&
|
if ((handshaker != null) &&
|
||||||
(handshaker instanceof ServerHandshaker) &&
|
(handshaker instanceof ServerHandshaker) &&
|
||||||
!handshaker.started()) {
|
!handshaker.activated()) {
|
||||||
((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
|
((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1717,6 +1859,16 @@ final public class SSLEngineImpl extends SSLEngine {
|
||||||
switch (connectionState) {
|
switch (connectionState) {
|
||||||
|
|
||||||
case cs_START:
|
case cs_START:
|
||||||
|
/*
|
||||||
|
* If we need to change the engine mode and the enabled
|
||||||
|
* protocols haven't specifically been set by the user,
|
||||||
|
* change them to the corresponding default ones.
|
||||||
|
*/
|
||||||
|
if (roleIsServer != (!flag) &&
|
||||||
|
ProtocolList.isDefaultProtocolList(enabledProtocols)) {
|
||||||
|
enabledProtocols = ProtocolList.getDefault(!flag);
|
||||||
|
}
|
||||||
|
|
||||||
roleIsServer = !flag;
|
roleIsServer = !flag;
|
||||||
serverModeSet = true;
|
serverModeSet = true;
|
||||||
break;
|
break;
|
||||||
|
@ -1730,7 +1882,17 @@ final public class SSLEngineImpl extends SSLEngine {
|
||||||
* have the streams.
|
* have the streams.
|
||||||
*/
|
*/
|
||||||
assert(handshaker != null);
|
assert(handshaker != null);
|
||||||
if (!handshaker.started()) {
|
if (!handshaker.activated()) {
|
||||||
|
/*
|
||||||
|
* If we need to change the engine mode and the enabled
|
||||||
|
* protocols haven't specifically been set by the user,
|
||||||
|
* change them to the corresponding default ones.
|
||||||
|
*/
|
||||||
|
if (roleIsServer != (!flag) &&
|
||||||
|
ProtocolList.isDefaultProtocolList(enabledProtocols)) {
|
||||||
|
enabledProtocols = ProtocolList.getDefault(!flag);
|
||||||
|
}
|
||||||
|
|
||||||
roleIsServer = !flag;
|
roleIsServer = !flag;
|
||||||
connectionState = cs_START;
|
connectionState = cs_START;
|
||||||
initHandshaker();
|
initHandshaker();
|
||||||
|
@ -1786,8 +1948,8 @@ final public class SSLEngineImpl extends SSLEngine {
|
||||||
*/
|
*/
|
||||||
synchronized public void setEnabledCipherSuites(String[] suites) {
|
synchronized public void setEnabledCipherSuites(String[] suites) {
|
||||||
enabledCipherSuites = new CipherSuiteList(suites);
|
enabledCipherSuites = new CipherSuiteList(suites);
|
||||||
if ((handshaker != null) && !handshaker.started()) {
|
if ((handshaker != null) && !handshaker.activated()) {
|
||||||
handshaker.enabledCipherSuites = enabledCipherSuites;
|
handshaker.setEnabledCipherSuites(enabledCipherSuites);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1826,7 +1988,7 @@ final public class SSLEngineImpl extends SSLEngine {
|
||||||
*/
|
*/
|
||||||
synchronized public void setEnabledProtocols(String[] protocols) {
|
synchronized public void setEnabledProtocols(String[] protocols) {
|
||||||
enabledProtocols = new ProtocolList(protocols);
|
enabledProtocols = new ProtocolList(protocols);
|
||||||
if ((handshaker != null) && !handshaker.started()) {
|
if ((handshaker != null) && !handshaker.activated()) {
|
||||||
handshaker.setEnabledProtocols(enabledProtocols);
|
handshaker.setEnabledProtocols(enabledProtocols);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,7 +145,7 @@ class SSLServerSocketImpl extends SSLServerSocket
|
||||||
}
|
}
|
||||||
sslContext = context;
|
sslContext = context;
|
||||||
enabledCipherSuites = CipherSuiteList.getDefault();
|
enabledCipherSuites = CipherSuiteList.getDefault();
|
||||||
enabledProtocols = ProtocolList.getDefault();
|
enabledProtocols = ProtocolList.getDefault(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -238,6 +238,16 @@ class SSLServerSocketImpl extends SSLServerSocket
|
||||||
* rejoining the already-negotiated SSL connection.
|
* rejoining the already-negotiated SSL connection.
|
||||||
*/
|
*/
|
||||||
public void setUseClientMode(boolean flag) {
|
public void setUseClientMode(boolean flag) {
|
||||||
|
/*
|
||||||
|
* If we need to change the socket mode and the enabled
|
||||||
|
* protocols haven't specifically been set by the user,
|
||||||
|
* change them to the corresponding default ones.
|
||||||
|
*/
|
||||||
|
if (useServerMode != (!flag) &&
|
||||||
|
ProtocolList.isDefaultProtocolList(enabledProtocols)) {
|
||||||
|
enabledProtocols = ProtocolList.getDefault(!flag);
|
||||||
|
}
|
||||||
|
|
||||||
useServerMode = !flag;
|
useServerMode = !flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,15 +272,12 @@ class SSLServerSocketImpl extends SSLServerSocket
|
||||||
return enableSessionCreation;
|
return enableSessionCreation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Accept a new SSL connection. This server identifies itself with
|
* Accept a new SSL connection. This server identifies itself with
|
||||||
* information provided in the authentication context which was
|
* information provided in the authentication context which was
|
||||||
* presented during construction.
|
* presented during construction.
|
||||||
*/
|
*/
|
||||||
public Socket accept() throws IOException {
|
public Socket accept() throws IOException {
|
||||||
checkEnabledSuites();
|
|
||||||
|
|
||||||
SSLSocketImpl s = new SSLSocketImpl(sslContext, useServerMode,
|
SSLSocketImpl s = new SSLSocketImpl(sslContext, useServerMode,
|
||||||
enabledCipherSuites, doClientAuth, enableSessionCreation,
|
enabledCipherSuites, doClientAuth, enableSessionCreation,
|
||||||
enabledProtocols);
|
enabledProtocols);
|
||||||
|
@ -280,56 +287,6 @@ class SSLServerSocketImpl extends SSLServerSocket
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is a sometimes helpful diagnostic check that is performed
|
|
||||||
* once for each ServerSocket to verify that the initial set of
|
|
||||||
* enabled suites are capable of supporting a successful handshake.
|
|
||||||
*/
|
|
||||||
private void checkEnabledSuites() throws IOException {
|
|
||||||
//
|
|
||||||
// We want to report an error if no cipher suites were actually
|
|
||||||
// enabled, since this is an error users are known to make. Then
|
|
||||||
// they get vastly confused by having clients report an error!
|
|
||||||
//
|
|
||||||
synchronized (this) {
|
|
||||||
if (checkedEnabled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (useServerMode == false) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SSLSocketImpl tmp = new SSLSocketImpl(sslContext, useServerMode,
|
|
||||||
enabledCipherSuites, doClientAuth,
|
|
||||||
enableSessionCreation, enabledProtocols);
|
|
||||||
|
|
||||||
try {
|
|
||||||
ServerHandshaker handshaker = tmp.getServerHandshaker();
|
|
||||||
|
|
||||||
for (Iterator<CipherSuite> t = enabledCipherSuites.iterator();
|
|
||||||
t.hasNext();) {
|
|
||||||
CipherSuite suite = t.next();
|
|
||||||
if (handshaker.trySetCipherSuite(suite)) {
|
|
||||||
checkedEnabled = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
tmp.closeSocket();
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// diagnostic text here is currently appropriate
|
|
||||||
// since it's only certificate unavailability that can
|
|
||||||
// cause such problems ... but that might change someday.
|
|
||||||
//
|
|
||||||
throw new SSLException("No available certificate or key corresponds"
|
|
||||||
+ " to the SSL cipher suites which are enabled.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides a brief description of this SSL socket.
|
* Provides a brief description of this SSL socket.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -194,12 +194,14 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||||
*/
|
*/
|
||||||
private byte doClientAuth;
|
private byte doClientAuth;
|
||||||
private boolean roleIsServer;
|
private boolean roleIsServer;
|
||||||
private CipherSuiteList enabledCipherSuites;
|
|
||||||
private boolean enableSessionCreation = true;
|
private boolean enableSessionCreation = true;
|
||||||
private String host;
|
private String host;
|
||||||
private boolean autoClose = true;
|
private boolean autoClose = true;
|
||||||
private AccessControlContext acc;
|
private AccessControlContext acc;
|
||||||
|
|
||||||
|
// The cipher suites enabled for use on this connection.
|
||||||
|
private CipherSuiteList enabledCipherSuites;
|
||||||
|
|
||||||
// hostname identification algorithm, the hostname identification is
|
// hostname identification algorithm, the hostname identification is
|
||||||
// disabled by default.
|
// disabled by default.
|
||||||
private String identificationAlg = null;
|
private String identificationAlg = null;
|
||||||
|
@ -341,11 +343,11 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||||
private AppOutputStream output;
|
private AppOutputStream output;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The protocols we support are SSL Version 3.0) and
|
* The protocol versions enabled for use on this connection.
|
||||||
* TLS (version 3.1).
|
*
|
||||||
* In addition we support a pseudo protocol called
|
* Note: we support a pseudo protocol called SSLv2Hello which when
|
||||||
* SSLv2Hello which when set will result in an SSL v2 Hello
|
* set will result in an SSL v2 Hello being sent with SSL (version 3.0)
|
||||||
* being sent with SSLv3 or TLSv1 version info.
|
* or TLS (version 3.1, 3.2, etc.) version info.
|
||||||
*/
|
*/
|
||||||
private ProtocolList enabledProtocols;
|
private ProtocolList enabledProtocols;
|
||||||
|
|
||||||
|
@ -541,7 +543,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||||
serverVerifyData = new byte[0];
|
serverVerifyData = new byte[0];
|
||||||
|
|
||||||
enabledCipherSuites = CipherSuiteList.getDefault();
|
enabledCipherSuites = CipherSuiteList.getDefault();
|
||||||
enabledProtocols = ProtocolList.getDefault();
|
enabledProtocols = ProtocolList.getDefault(roleIsServer);
|
||||||
inrec = null;
|
inrec = null;
|
||||||
|
|
||||||
// save the acc
|
// save the acc
|
||||||
|
@ -764,6 +766,21 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||||
r.addMAC(writeMAC);
|
r.addMAC(writeMAC);
|
||||||
r.encrypt(writeCipher);
|
r.encrypt(writeCipher);
|
||||||
r.write(sockOutput);
|
r.write(sockOutput);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check the sequence number state
|
||||||
|
*
|
||||||
|
* Note that in order to maintain the connection I/O
|
||||||
|
* properly, we check the sequence number after the last
|
||||||
|
* record writing process. As we request renegotiation
|
||||||
|
* or close the connection for wrapped sequence number
|
||||||
|
* when there is enough sequence number space left to
|
||||||
|
* handle a few more records, so the sequence number
|
||||||
|
* of the last record cannot be wrapped.
|
||||||
|
*/
|
||||||
|
if (connectionState < cs_ERROR) {
|
||||||
|
checkSequenceNumber(writeMAC, r.contentType());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -883,6 +900,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// if (!r.decompress(c))
|
// if (!r.decompress(c))
|
||||||
// fatal(Alerts.alert_decompression_failure,
|
// fatal(Alerts.alert_decompression_failure,
|
||||||
// "decompression failure");
|
// "decompression failure");
|
||||||
|
@ -905,6 +923,15 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||||
* in it.
|
* in it.
|
||||||
*/
|
*/
|
||||||
initHandshaker();
|
initHandshaker();
|
||||||
|
if (!handshaker.activated()) {
|
||||||
|
// prior to handshaking, activate the handshake
|
||||||
|
if (connectionState == cs_RENEGOTIATE) {
|
||||||
|
// don't use SSLv2Hello when renegotiating
|
||||||
|
handshaker.activate(protocolVersion);
|
||||||
|
} else {
|
||||||
|
handshaker.activate(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* process the handshake record ... may contain just
|
* process the handshake record ... may contain just
|
||||||
|
@ -949,9 +976,8 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||||
|
|
||||||
if (needAppData || connectionState != cs_DATA) {
|
if (needAppData || connectionState != cs_DATA) {
|
||||||
continue;
|
continue;
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case Record.ct_application_data:
|
case Record.ct_application_data:
|
||||||
// Pass this right back up to the application.
|
// Pass this right back up to the application.
|
||||||
|
@ -971,7 +997,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
r.setAppDataValid(true);
|
r.setAppDataValid(true);
|
||||||
return;
|
break;
|
||||||
|
|
||||||
case Record.ct_alert:
|
case Record.ct_alert:
|
||||||
recvAlert(r);
|
recvAlert(r);
|
||||||
|
@ -1010,6 +1036,23 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
} // switch
|
} // switch
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check the sequence number state
|
||||||
|
*
|
||||||
|
* Note that in order to maintain the connection I/O
|
||||||
|
* properly, we check the sequence number after the last
|
||||||
|
* record reading process. As we request renegotiation
|
||||||
|
* or close the connection for wrapped sequence number
|
||||||
|
* when there is enough sequence number space left to
|
||||||
|
* handle a few more records, so the sequence number
|
||||||
|
* of the last record cannot be wrapped.
|
||||||
|
*/
|
||||||
|
if (connectionState < cs_ERROR) {
|
||||||
|
checkSequenceNumber(readMAC, r.contentType());
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
} // synchronized (this)
|
} // synchronized (this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1021,6 +1064,61 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||||
} // synchronized (readLock)
|
} // synchronized (readLock)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the sequence number state
|
||||||
|
*
|
||||||
|
* RFC 4346 states that, "Sequence numbers are of type uint64 and
|
||||||
|
* may not exceed 2^64-1. Sequence numbers do not wrap. If a TLS
|
||||||
|
* implementation would need to wrap a sequence number, it must
|
||||||
|
* renegotiate instead."
|
||||||
|
*/
|
||||||
|
private void checkSequenceNumber(MAC mac, byte type)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Don't bother to check the sequence number for error or
|
||||||
|
* closed connections, or NULL MAC.
|
||||||
|
*/
|
||||||
|
if (connectionState >= cs_ERROR || mac == MAC.NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Conservatively, close the connection immediately when the
|
||||||
|
* sequence number is close to overflow
|
||||||
|
*/
|
||||||
|
if (mac.seqNumOverflow()) {
|
||||||
|
/*
|
||||||
|
* TLS protocols do not define a error alert for sequence
|
||||||
|
* number overflow. We use handshake_failure error alert
|
||||||
|
* for handshaking and bad_record_mac for other records.
|
||||||
|
*/
|
||||||
|
if (debug != null && Debug.isOn("ssl")) {
|
||||||
|
System.out.println(threadName() +
|
||||||
|
", sequence number extremely close to overflow " +
|
||||||
|
"(2^64-1 packets). Closing connection.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fatal(Alerts.alert_handshake_failure, "sequence number overflow");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ask for renegotiation when need to renew sequence number.
|
||||||
|
*
|
||||||
|
* Don't bother to kickstart the renegotiation when the local is
|
||||||
|
* asking for it.
|
||||||
|
*/
|
||||||
|
if ((type != Record.ct_handshake) && mac.seqNumIsHuge()) {
|
||||||
|
if (debug != null && Debug.isOn("ssl")) {
|
||||||
|
System.out.println(threadName() + ", request renegotiation " +
|
||||||
|
"to avoid sequence number overflow");
|
||||||
|
}
|
||||||
|
|
||||||
|
startHandshake();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// HANDSHAKE RELATED CODE
|
// HANDSHAKE RELATED CODE
|
||||||
//
|
//
|
||||||
|
@ -1033,28 +1131,10 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize and get the server handshaker. Used by SSLServerSocketImpl
|
* Return the AppOutputStream. For use by Handshaker only.
|
||||||
* for the ciphersuite availability test *only*.
|
|
||||||
*/
|
*/
|
||||||
ServerHandshaker getServerHandshaker() throws SSLException {
|
AppOutputStream getAppOutputStream() {
|
||||||
initHandshaker();
|
return output;
|
||||||
|
|
||||||
// The connection state would have been set to cs_HANDSHAKE during the
|
|
||||||
// handshaking initializing, however the caller may not have the
|
|
||||||
// the low level connection's established, which is not consistent with
|
|
||||||
// the HANDSHAKE state. As if it is unconnected, we need to reset the
|
|
||||||
// connection state to cs_START.
|
|
||||||
if (!isConnected()) {
|
|
||||||
connectionState = cs_START;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure that we get a ServerHandshaker.
|
|
||||||
// This should never happen.
|
|
||||||
if (!(handshaker instanceof ServerHandshaker)) {
|
|
||||||
throw new SSLProtocolException("unexpected handshaker instance");
|
|
||||||
}
|
|
||||||
|
|
||||||
return (ServerHandshaker)handshaker;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1066,8 +1146,8 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||||
* . if the socket is already closed, throw an Exception (internal error)
|
* . if the socket is already closed, throw an Exception (internal error)
|
||||||
*
|
*
|
||||||
* . otherwise (cs_START or cs_DATA), create the appropriate handshaker
|
* . otherwise (cs_START or cs_DATA), create the appropriate handshaker
|
||||||
* object, initialize it, and advance the connection state (to
|
* object, and advance the connection state (to cs_HANDSHAKE or
|
||||||
* cs_HANDSHAKE or cs_RENEGOTIATE, respectively).
|
* cs_RENEGOTIATE, respectively).
|
||||||
*
|
*
|
||||||
* This method is called right after a new socket is created, when
|
* This method is called right after a new socket is created, when
|
||||||
* starting renegotiation, or when changing client/ server mode of the
|
* starting renegotiation, or when changing client/ server mode of the
|
||||||
|
@ -1115,12 +1195,8 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||||
protocolVersion, connectionState == cs_HANDSHAKE,
|
protocolVersion, connectionState == cs_HANDSHAKE,
|
||||||
secureRenegotiation, clientVerifyData, serverVerifyData);
|
secureRenegotiation, clientVerifyData, serverVerifyData);
|
||||||
}
|
}
|
||||||
handshaker.enabledCipherSuites = enabledCipherSuites;
|
handshaker.setEnabledCipherSuites(enabledCipherSuites);
|
||||||
handshaker.setEnableSessionCreation(enableSessionCreation);
|
handshaker.setEnableSessionCreation(enableSessionCreation);
|
||||||
if (connectionState == cs_RENEGOTIATE) {
|
|
||||||
// don't use SSLv2Hello when renegotiating
|
|
||||||
handshaker.output.r.setHelloVersion(protocolVersion);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1135,6 +1211,8 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||||
// one thread performs the handshake
|
// one thread performs the handshake
|
||||||
synchronized (handshakeLock) {
|
synchronized (handshakeLock) {
|
||||||
if (getConnectionState() == cs_HANDSHAKE) {
|
if (getConnectionState() == cs_HANDSHAKE) {
|
||||||
|
kickstartHandshake();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* All initial handshaking goes through this
|
* All initial handshaking goes through this
|
||||||
* InputRecord until we have a valid SSL connection.
|
* InputRecord until we have a valid SSL connection.
|
||||||
|
@ -1157,7 +1235,6 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||||
inrec.enableFormatChecks();
|
inrec.enableFormatChecks();
|
||||||
}
|
}
|
||||||
|
|
||||||
kickstartHandshake();
|
|
||||||
readRecord(inrec, false);
|
readRecord(inrec, false);
|
||||||
inrec = null;
|
inrec = null;
|
||||||
}
|
}
|
||||||
|
@ -1211,6 +1288,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||||
* on servers when renegotiating).
|
* on servers when renegotiating).
|
||||||
*/
|
*/
|
||||||
private synchronized void kickstartHandshake() throws IOException {
|
private synchronized void kickstartHandshake() throws IOException {
|
||||||
|
|
||||||
switch (connectionState) {
|
switch (connectionState) {
|
||||||
|
|
||||||
case cs_HANDSHAKE:
|
case cs_HANDSHAKE:
|
||||||
|
@ -1257,7 +1335,15 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||||
// to its HandshakeOutStream, which calls back into
|
// to its HandshakeOutStream, which calls back into
|
||||||
// SSLSocketImpl.writeRecord() to send it.
|
// SSLSocketImpl.writeRecord() to send it.
|
||||||
//
|
//
|
||||||
if (!handshaker.started()) {
|
if (!handshaker.activated()) {
|
||||||
|
// prior to handshaking, activate the handshake
|
||||||
|
if (connectionState == cs_RENEGOTIATE) {
|
||||||
|
// don't use SSLv2Hello when renegotiating
|
||||||
|
handshaker.activate(protocolVersion);
|
||||||
|
} else {
|
||||||
|
handshaker.activate(null);
|
||||||
|
}
|
||||||
|
|
||||||
if (handshaker instanceof ClientHandshaker) {
|
if (handshaker instanceof ClientHandshaker) {
|
||||||
// send client hello
|
// send client hello
|
||||||
handshaker.kickstart();
|
handshaker.kickstart();
|
||||||
|
@ -1752,10 +1838,18 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||||
* Emit alerts. Caller must have synchronized with "this".
|
* Emit alerts. Caller must have synchronized with "this".
|
||||||
*/
|
*/
|
||||||
private void sendAlert(byte level, byte description) {
|
private void sendAlert(byte level, byte description) {
|
||||||
|
// the connectionState cannot be cs_START
|
||||||
if (connectionState >= cs_SENT_CLOSE) {
|
if (connectionState >= cs_SENT_CLOSE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For initial handshaking, don't send alert message to peer if
|
||||||
|
// handshaker has not started.
|
||||||
|
if (connectionState == cs_HANDSHAKE &&
|
||||||
|
(handshaker == null || !handshaker.started())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
OutputRecord r = new OutputRecord(Record.ct_alert);
|
OutputRecord r = new OutputRecord(Record.ct_alert);
|
||||||
r.setVersion(protocolVersion);
|
r.setVersion(protocolVersion);
|
||||||
|
|
||||||
|
@ -1962,7 +2056,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||||
synchronized public void setEnableSessionCreation(boolean flag) {
|
synchronized public void setEnableSessionCreation(boolean flag) {
|
||||||
enableSessionCreation = flag;
|
enableSessionCreation = flag;
|
||||||
|
|
||||||
if ((handshaker != null) && !handshaker.started()) {
|
if ((handshaker != null) && !handshaker.activated()) {
|
||||||
handshaker.setEnableSessionCreation(enableSessionCreation);
|
handshaker.setEnableSessionCreation(enableSessionCreation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1990,7 +2084,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||||
|
|
||||||
if ((handshaker != null) &&
|
if ((handshaker != null) &&
|
||||||
(handshaker instanceof ServerHandshaker) &&
|
(handshaker instanceof ServerHandshaker) &&
|
||||||
!handshaker.started()) {
|
!handshaker.activated()) {
|
||||||
((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
|
((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2013,7 +2107,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||||
|
|
||||||
if ((handshaker != null) &&
|
if ((handshaker != null) &&
|
||||||
(handshaker instanceof ServerHandshaker) &&
|
(handshaker instanceof ServerHandshaker) &&
|
||||||
!handshaker.started()) {
|
!handshaker.activated()) {
|
||||||
((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
|
((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2032,6 +2126,15 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||||
switch (connectionState) {
|
switch (connectionState) {
|
||||||
|
|
||||||
case cs_START:
|
case cs_START:
|
||||||
|
/*
|
||||||
|
* If we need to change the socket mode and the enabled
|
||||||
|
* protocols haven't specifically been set by the user,
|
||||||
|
* change them to the corresponding default ones.
|
||||||
|
*/
|
||||||
|
if (roleIsServer != (!flag) &&
|
||||||
|
ProtocolList.isDefaultProtocolList(enabledProtocols)) {
|
||||||
|
enabledProtocols = ProtocolList.getDefault(!flag);
|
||||||
|
}
|
||||||
roleIsServer = !flag;
|
roleIsServer = !flag;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -2044,7 +2147,16 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||||
* have the streams.
|
* have the streams.
|
||||||
*/
|
*/
|
||||||
assert(handshaker != null);
|
assert(handshaker != null);
|
||||||
if (!handshaker.started()) {
|
if (!handshaker.activated()) {
|
||||||
|
/*
|
||||||
|
* If we need to change the socket mode and the enabled
|
||||||
|
* protocols haven't specifically been set by the user,
|
||||||
|
* change them to the corresponding default ones.
|
||||||
|
*/
|
||||||
|
if (roleIsServer != (!flag) &&
|
||||||
|
ProtocolList.isDefaultProtocolList(enabledProtocols)) {
|
||||||
|
enabledProtocols = ProtocolList.getDefault(!flag);
|
||||||
|
}
|
||||||
roleIsServer = !flag;
|
roleIsServer = !flag;
|
||||||
connectionState = cs_START;
|
connectionState = cs_START;
|
||||||
initHandshaker();
|
initHandshaker();
|
||||||
|
@ -2095,8 +2207,8 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||||
*/
|
*/
|
||||||
synchronized public void setEnabledCipherSuites(String[] suites) {
|
synchronized public void setEnabledCipherSuites(String[] suites) {
|
||||||
enabledCipherSuites = new CipherSuiteList(suites);
|
enabledCipherSuites = new CipherSuiteList(suites);
|
||||||
if ((handshaker != null) && !handshaker.started()) {
|
if ((handshaker != null) && !handshaker.activated()) {
|
||||||
handshaker.enabledCipherSuites = enabledCipherSuites;
|
handshaker.setEnabledCipherSuites(enabledCipherSuites);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2135,7 +2247,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||||
*/
|
*/
|
||||||
synchronized public void setEnabledProtocols(String[] protocols) {
|
synchronized public void setEnabledProtocols(String[] protocols) {
|
||||||
enabledProtocols = new ProtocolList(protocols);
|
enabledProtocols = new ProtocolList(protocols);
|
||||||
if ((handshaker != null) && !handshaker.started()) {
|
if ((handshaker != null) && !handshaker.activated()) {
|
||||||
handshaker.setEnabledProtocols(enabledProtocols);
|
handshaker.setEnabledProtocols(enabledProtocols);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -185,8 +185,10 @@ final class ServerHandshaker extends Handshaker {
|
||||||
* temporary one used for non-export or signing-only
|
* temporary one used for non-export or signing-only
|
||||||
* certificates/keys.
|
* certificates/keys.
|
||||||
*/
|
*/
|
||||||
RSAClientKeyExchange pms = new RSAClientKeyExchange
|
RSAClientKeyExchange pms = new RSAClientKeyExchange(
|
||||||
(protocolVersion, input, message_len, privateKey);
|
protocolVersion, clientRequestedVersion,
|
||||||
|
sslContext.getSecureRandom(), input,
|
||||||
|
message_len, privateKey);
|
||||||
preMasterSecret = this.clientKeyExchange(pms);
|
preMasterSecret = this.clientKeyExchange(pms);
|
||||||
break;
|
break;
|
||||||
case K_KRB5:
|
case K_KRB5:
|
||||||
|
@ -408,21 +410,15 @@ final class ServerHandshaker extends Handshaker {
|
||||||
|
|
||||||
clientRequestedVersion = mesg.protocolVersion;
|
clientRequestedVersion = mesg.protocolVersion;
|
||||||
|
|
||||||
// check if clientVersion is recent enough for us
|
// select a proper protocol version.
|
||||||
if (clientRequestedVersion.v < enabledProtocols.min.v) {
|
ProtocolVersion selectedVersion =
|
||||||
|
selectProtocolVersion(clientRequestedVersion);
|
||||||
|
if (selectedVersion == null ||
|
||||||
|
selectedVersion.v == ProtocolVersion.SSL20Hello.v) {
|
||||||
fatalSE(Alerts.alert_handshake_failure,
|
fatalSE(Alerts.alert_handshake_failure,
|
||||||
"Client requested protocol " + clientRequestedVersion +
|
"Client requested protocol " + clientRequestedVersion +
|
||||||
" not enabled or not supported");
|
" not enabled or not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
// now we know we have an acceptable version
|
|
||||||
// use the lower of our max and the client requested version
|
|
||||||
ProtocolVersion selectedVersion;
|
|
||||||
if (clientRequestedVersion.v <= enabledProtocols.max.v) {
|
|
||||||
selectedVersion = clientRequestedVersion;
|
|
||||||
} else {
|
|
||||||
selectedVersion = enabledProtocols.max;
|
|
||||||
}
|
|
||||||
setVersion(selectedVersion);
|
setVersion(selectedVersion);
|
||||||
|
|
||||||
m1.protocolVersion = protocolVersion;
|
m1.protocolVersion = protocolVersion;
|
||||||
|
@ -813,8 +809,7 @@ final class ServerHandshaker extends Handshaker {
|
||||||
* method should only be called if you really want to use the
|
* method should only be called if you really want to use the
|
||||||
* CipherSuite.
|
* CipherSuite.
|
||||||
*
|
*
|
||||||
* This method is called from chooseCipherSuite() in this class
|
* This method is called from chooseCipherSuite() in this class.
|
||||||
* and SSLServerSocketImpl.checkEnabledSuites() (as a sanity check).
|
|
||||||
*/
|
*/
|
||||||
boolean trySetCipherSuite(CipherSuite suite) {
|
boolean trySetCipherSuite(CipherSuite suite) {
|
||||||
/*
|
/*
|
||||||
|
@ -831,6 +826,11 @@ final class ServerHandshaker extends Handshaker {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TLSv1.1 must not negotiate the exportable weak cipher suites.
|
||||||
|
if (protocolVersion.v >= suite.obsoleted) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
KeyExchange keyExchange = suite.keyExchange;
|
KeyExchange keyExchange = suite.keyExchange;
|
||||||
|
|
||||||
// null out any existing references
|
// null out any existing references
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -38,7 +38,7 @@ import java.security.*;
|
||||||
*
|
*
|
||||||
* SunJSSE now supports an experimental FIPS compliant mode when used with an
|
* SunJSSE now supports an experimental FIPS compliant mode when used with an
|
||||||
* appropriate FIPS certified crypto provider. In FIPS mode, we:
|
* appropriate FIPS certified crypto provider. In FIPS mode, we:
|
||||||
* . allow only TLS 1.0
|
* . allow only TLS 1.0 or later
|
||||||
* . allow only FIPS approved ciphersuites
|
* . allow only FIPS approved ciphersuites
|
||||||
* . perform all crypto in the FIPS crypto provider
|
* . perform all crypto in the FIPS crypto provider
|
||||||
*
|
*
|
||||||
|
@ -211,6 +211,8 @@ public abstract class SunJSSE extends java.security.Provider {
|
||||||
"sun.security.ssl.SSLContextImpl");
|
"sun.security.ssl.SSLContextImpl");
|
||||||
put("SSLContext.TLSv1",
|
put("SSLContext.TLSv1",
|
||||||
"sun.security.ssl.SSLContextImpl");
|
"sun.security.ssl.SSLContextImpl");
|
||||||
|
put("SSLContext.TLSv1.1",
|
||||||
|
"sun.security.ssl.SSLContextImpl");
|
||||||
put("SSLContext.Default",
|
put("SSLContext.Default",
|
||||||
"sun.security.ssl.DefaultSSLContextImpl");
|
"sun.security.ssl.DefaultSSLContextImpl");
|
||||||
|
|
||||||
|
|
|
@ -244,7 +244,7 @@ public final class KerberosClientKeyExchangeImpl
|
||||||
clientVersion, rand, input, sessionKey);
|
clientVersion, rand, input, sessionKey);
|
||||||
} else {
|
} else {
|
||||||
// Generate bogus premaster secret
|
// Generate bogus premaster secret
|
||||||
preMaster = new KerberosPreMasterSecret(protocolVersion, rand);
|
preMaster = new KerberosPreMasterSecret(clientVersion, rand);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -176,13 +176,21 @@ final class KerberosPreMasterSecret {
|
||||||
// check if the premaster secret version is ok
|
// check if the premaster secret version is ok
|
||||||
// the specification says that it must be the maximum version supported
|
// the specification says that it must be the maximum version supported
|
||||||
// by the client from its ClientHello message. However, many
|
// by the client from its ClientHello message. However, many
|
||||||
// implementations send the negotiated version, so accept both
|
// old implementations send the negotiated version, so accept both
|
||||||
|
// for SSL v3.0 and TLS v1.0.
|
||||||
// NOTE that we may be comparing two unsupported version numbers in
|
// NOTE that we may be comparing two unsupported version numbers in
|
||||||
// the second case, which is why we cannot use object references
|
// the second case, which is why we cannot use object references
|
||||||
// equality in this special case
|
// equality in this special case
|
||||||
boolean versionMismatch = (protocolVersion != currentVersion) &&
|
boolean versionMismatch = (protocolVersion.v != clientVersion.v);
|
||||||
(protocolVersion.v != clientVersion.v);
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* we never checked the client_version in server side
|
||||||
|
* for TLS v1.0 and SSL v3.0. For compatibility, we
|
||||||
|
* maintain this behavior.
|
||||||
|
*/
|
||||||
|
if (versionMismatch && (clientVersion.v <= 0x0301)) {
|
||||||
|
versionMismatch = (protocolVersion.v != currentVersion.v);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Bogus decrypted ClientKeyExchange? If so, conjure a
|
* Bogus decrypted ClientKeyExchange? If so, conjure a
|
||||||
|
@ -203,8 +211,14 @@ final class KerberosPreMasterSecret {
|
||||||
Debug.println(System.out, "Invalid secret", preMaster);
|
Debug.println(System.out, "Invalid secret", preMaster);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
preMaster = generatePreMaster(generator, currentVersion);
|
|
||||||
protocolVersion = currentVersion;
|
/*
|
||||||
|
* Randomize the preMaster secret with the
|
||||||
|
* ClientHello.client_version, as will produce invalid master
|
||||||
|
* secret to prevent the attacks.
|
||||||
|
*/
|
||||||
|
preMaster = generatePreMaster(generator, clientVersion);
|
||||||
|
protocolVersion = clientVersion;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -119,6 +119,13 @@ public class CipherTest {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ignore exportable cipher suite for TLSv1.1
|
||||||
|
if (protocol.equals("TLSv1.1")) {
|
||||||
|
if(cipherSuite.indexOf("_EXPORT_") != -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,18 +156,14 @@ public class CipherTest {
|
||||||
cipherSuites.length * protocols.length * clientAuths.length);
|
cipherSuites.length * protocols.length * clientAuths.length);
|
||||||
for (int i = 0; i < cipherSuites.length; i++) {
|
for (int i = 0; i < cipherSuites.length; i++) {
|
||||||
String cipherSuite = cipherSuites[i];
|
String cipherSuite = cipherSuites[i];
|
||||||
if (peerFactory.isSupported(cipherSuite) == false) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// skip kerberos cipher suites
|
|
||||||
if (cipherSuite.startsWith("TLS_KRB5")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (int j = 0; j < protocols.length; j++) {
|
for (int j = 0; j < protocols.length; j++) {
|
||||||
String protocol = protocols[j];
|
String protocol = protocols[j];
|
||||||
if (protocol.equals("SSLv2Hello")) {
|
|
||||||
|
if (!peerFactory.isSupported(cipherSuite, protocol)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int k = 0; k < clientAuths.length; k++) {
|
for (int k = 0; k < clientAuths.length; k++) {
|
||||||
String clientAuth = clientAuths[k];
|
String clientAuth = clientAuths[k];
|
||||||
if ((clientAuth != null) &&
|
if ((clientAuth != null) &&
|
||||||
|
@ -293,11 +296,12 @@ public class CipherTest {
|
||||||
return ks;
|
return ks;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(PeerFactory peerFactory, KeyStore keyStore, String[] args)
|
public static void main(PeerFactory peerFactory, KeyStore keyStore,
|
||||||
throws Exception {
|
String[] args) throws Exception {
|
||||||
|
|
||||||
long time = System.currentTimeMillis();
|
long time = System.currentTimeMillis();
|
||||||
String relPath;
|
String relPath;
|
||||||
if ((args.length > 0) && args[0].equals("sh")) {
|
if ((args != null) && (args.length > 0) && args[0].equals("sh")) {
|
||||||
relPath = pathToStoresSH;
|
relPath = pathToStoresSH;
|
||||||
} else {
|
} else {
|
||||||
relPath = pathToStores;
|
relPath = pathToStores;
|
||||||
|
@ -345,7 +349,30 @@ public class CipherTest {
|
||||||
|
|
||||||
abstract Server newServer(CipherTest cipherTest) throws Exception;
|
abstract Server newServer(CipherTest cipherTest) throws Exception;
|
||||||
|
|
||||||
boolean isSupported(String cipherSuite) {
|
boolean isSupported(String cipherSuite, String protocol) {
|
||||||
|
// skip kerberos cipher suites
|
||||||
|
if (cipherSuite.startsWith("TLS_KRB5")) {
|
||||||
|
System.out.println("Skipping unsupported test for " +
|
||||||
|
cipherSuite + " of " + protocol);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip SSLv2Hello protocol
|
||||||
|
if (protocol.equals("SSLv2Hello")) {
|
||||||
|
System.out.println("Skipping unsupported test for " +
|
||||||
|
cipherSuite + " of " + protocol);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore exportable cipher suite for TLSv1.1
|
||||||
|
if (protocol.equals("TLSv1.1")) {
|
||||||
|
if (cipherSuite.indexOf("_EXPORT_WITH") != -1) {
|
||||||
|
System.out.println("Skipping obsoleted test for " +
|
||||||
|
cipherSuite + " of " + protocol);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,6 +119,13 @@ public class CipherTest {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ignore exportable cipher suite for TLSv1.1
|
||||||
|
if (protocol.equals("TLSv1.1")) {
|
||||||
|
if(cipherSuite.indexOf("_EXPORT_") != -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,18 +155,14 @@ public class CipherTest {
|
||||||
cipherSuites.length * protocols.length * clientAuths.length);
|
cipherSuites.length * protocols.length * clientAuths.length);
|
||||||
for (int i = 0; i < cipherSuites.length; i++) {
|
for (int i = 0; i < cipherSuites.length; i++) {
|
||||||
String cipherSuite = cipherSuites[i];
|
String cipherSuite = cipherSuites[i];
|
||||||
if (peerFactory.isSupported(cipherSuite) == false) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// skip kerberos cipher suites
|
|
||||||
if (cipherSuite.startsWith("TLS_KRB5")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (int j = 0; j < protocols.length; j++) {
|
for (int j = 0; j < protocols.length; j++) {
|
||||||
String protocol = protocols[j];
|
String protocol = protocols[j];
|
||||||
if (protocol.equals("SSLv2Hello")) {
|
|
||||||
|
if (!peerFactory.isSupported(cipherSuite, protocol)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int k = 0; k < clientAuths.length; k++) {
|
for (int k = 0; k < clientAuths.length; k++) {
|
||||||
String clientAuth = clientAuths[k];
|
String clientAuth = clientAuths[k];
|
||||||
if ((clientAuth != null) &&
|
if ((clientAuth != null) &&
|
||||||
|
@ -275,7 +278,6 @@ public class CipherTest {
|
||||||
|
|
||||||
// for some reason, ${test.src} has a different value when the
|
// for some reason, ${test.src} has a different value when the
|
||||||
// test is called from the script and when it is called directly...
|
// test is called from the script and when it is called directly...
|
||||||
// static String pathToStores = "../../etc";
|
|
||||||
static String pathToStores = ".";
|
static String pathToStores = ".";
|
||||||
static String pathToStoresSH = ".";
|
static String pathToStoresSH = ".";
|
||||||
static String keyStoreFile = "keystore";
|
static String keyStoreFile = "keystore";
|
||||||
|
@ -336,7 +338,30 @@ public class CipherTest {
|
||||||
|
|
||||||
abstract Server newServer(CipherTest cipherTest) throws Exception;
|
abstract Server newServer(CipherTest cipherTest) throws Exception;
|
||||||
|
|
||||||
boolean isSupported(String cipherSuite) {
|
boolean isSupported(String cipherSuite, String protocol) {
|
||||||
|
// skip kerberos cipher suites
|
||||||
|
if (cipherSuite.startsWith("TLS_KRB5")) {
|
||||||
|
System.out.println("Skipping unsupported test for " +
|
||||||
|
cipherSuite + " of " + protocol);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip SSLv2Hello protocol
|
||||||
|
if (protocol.equals("SSLv2Hello")) {
|
||||||
|
System.out.println("Skipping unsupported test for " +
|
||||||
|
cipherSuite + " of " + protocol);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore exportable cipher suite for TLSv1.1
|
||||||
|
if (protocol.equals("TLSv1.1")) {
|
||||||
|
if (cipherSuite.indexOf("_EXPORT_WITH") != -1) {
|
||||||
|
System.out.println("Skipping obsoleted test for " +
|
||||||
|
cipherSuite + " of " + protocol);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,371 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 4873188
|
||||||
|
* @summary Support TLS 1.1
|
||||||
|
* @run main/othervm -Djavax.net.debug=all EmptyCertificateAuthorities
|
||||||
|
*
|
||||||
|
* @author Xuelei Fan
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.*;
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.cert.*;
|
||||||
|
import javax.net.ssl.*;
|
||||||
|
|
||||||
|
public class EmptyCertificateAuthorities {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* =============================================================
|
||||||
|
* Set the various variables needed for the tests, then
|
||||||
|
* specify what tests to run on each side.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Should we run the client or server in a separate thread?
|
||||||
|
* Both sides can throw exceptions, but do you have a preference
|
||||||
|
* as to which side should be the main thread.
|
||||||
|
*/
|
||||||
|
static boolean separateServerThread = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Where do we find the keystores?
|
||||||
|
*/
|
||||||
|
static String pathToStores = "/../../../../etc";
|
||||||
|
static String keyStoreFile = "keystore";
|
||||||
|
static String trustStoreFile = "truststore";
|
||||||
|
static String passwd = "passphrase";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Is the server ready to serve?
|
||||||
|
*/
|
||||||
|
volatile static boolean serverReady = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Turn on SSL debugging?
|
||||||
|
*/
|
||||||
|
static boolean debug = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the client or server is doing some kind of object creation
|
||||||
|
* that the other side depends on, and that thread prematurely
|
||||||
|
* exits, you may experience a hang. The test harness will
|
||||||
|
* terminate all hung threads after its timeout has expired,
|
||||||
|
* currently 3 minutes by default, but you might try to be
|
||||||
|
* smart about it....
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define the server side of the test.
|
||||||
|
*
|
||||||
|
* If the server prematurely exits, serverReady will be set to true
|
||||||
|
* to avoid infinite hangs.
|
||||||
|
*/
|
||||||
|
void doServerSide() throws Exception {
|
||||||
|
SSLServerSocketFactory sslssf = getSSLServerSF();
|
||||||
|
SSLServerSocket sslServerSocket =
|
||||||
|
(SSLServerSocket) sslssf.createServerSocket(serverPort);
|
||||||
|
|
||||||
|
// require client authentication.
|
||||||
|
sslServerSocket.setNeedClientAuth(true);
|
||||||
|
|
||||||
|
serverPort = sslServerSocket.getLocalPort();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Signal Client, we're ready for his connect.
|
||||||
|
*/
|
||||||
|
serverReady = true;
|
||||||
|
|
||||||
|
SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
|
||||||
|
InputStream sslIS = sslSocket.getInputStream();
|
||||||
|
OutputStream sslOS = sslSocket.getOutputStream();
|
||||||
|
|
||||||
|
sslIS.read();
|
||||||
|
sslOS.write('A');
|
||||||
|
sslOS.flush();
|
||||||
|
|
||||||
|
sslSocket.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define the client side of the test.
|
||||||
|
*
|
||||||
|
* If the server prematurely exits, serverReady will be set to true
|
||||||
|
* to avoid infinite hangs.
|
||||||
|
*/
|
||||||
|
void doClientSide() throws Exception {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wait for server to get started.
|
||||||
|
*/
|
||||||
|
while (!serverReady) {
|
||||||
|
Thread.sleep(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
SSLSocketFactory sslsf =
|
||||||
|
(SSLSocketFactory) SSLSocketFactory.getDefault();
|
||||||
|
SSLSocket sslSocket = (SSLSocket)
|
||||||
|
sslsf.createSocket("localhost", serverPort);
|
||||||
|
|
||||||
|
// enable TLSv1.1 only
|
||||||
|
sslSocket.setEnabledProtocols(new String[] {"TLSv1.1"});
|
||||||
|
|
||||||
|
InputStream sslIS = sslSocket.getInputStream();
|
||||||
|
OutputStream sslOS = sslSocket.getOutputStream();
|
||||||
|
|
||||||
|
sslOS.write('B');
|
||||||
|
sslOS.flush();
|
||||||
|
sslIS.read();
|
||||||
|
|
||||||
|
sslSocket.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private SSLServerSocketFactory getSSLServerSF() throws Exception {
|
||||||
|
|
||||||
|
char [] password =
|
||||||
|
System.getProperty("javax.net.ssl.keyStorePassword").toCharArray();
|
||||||
|
String keyFilename = System.getProperty("javax.net.ssl.keyStore");
|
||||||
|
|
||||||
|
KeyStore ks = KeyStore.getInstance("JKS");
|
||||||
|
ks.load(new FileInputStream(keyFilename), password);
|
||||||
|
|
||||||
|
KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509");
|
||||||
|
kmf.init(ks, password);
|
||||||
|
|
||||||
|
KeyManager[] kms = kmf.getKeyManagers();
|
||||||
|
TrustManager[] tms = new MyX509TM[] {new MyX509TM()};
|
||||||
|
|
||||||
|
SSLContext ctx = SSLContext.getInstance("TLS");
|
||||||
|
ctx.init(kms, tms, null);
|
||||||
|
|
||||||
|
return ctx.getServerSocketFactory();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static class MyX509TM implements X509TrustManager {
|
||||||
|
X509TrustManager tm;
|
||||||
|
|
||||||
|
public void checkClientTrusted(X509Certificate[] chain,
|
||||||
|
String authType) throws CertificateException {
|
||||||
|
if (tm == null) {
|
||||||
|
initialize();
|
||||||
|
}
|
||||||
|
tm.checkClientTrusted(chain, authType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkServerTrusted(X509Certificate[] chain,
|
||||||
|
String authType) throws CertificateException {
|
||||||
|
if (tm == null) {
|
||||||
|
initialize();
|
||||||
|
}
|
||||||
|
tm.checkServerTrusted(chain, authType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public X509Certificate[] getAcceptedIssuers() {
|
||||||
|
// always return empty array
|
||||||
|
return new X509Certificate[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initialize() throws CertificateException {
|
||||||
|
String passwd =
|
||||||
|
System.getProperty("javax.net.ssl.trustStorePassword");
|
||||||
|
char [] password = passwd.toCharArray();
|
||||||
|
String trustFilename =
|
||||||
|
System.getProperty("javax.net.ssl.trustStore");
|
||||||
|
|
||||||
|
try {
|
||||||
|
KeyStore ks = KeyStore.getInstance("JKS");
|
||||||
|
ks.load(new FileInputStream(trustFilename), password);
|
||||||
|
|
||||||
|
TrustManagerFactory tmf =
|
||||||
|
TrustManagerFactory.getInstance("PKIX");
|
||||||
|
tmf.init(ks);
|
||||||
|
tm = (X509TrustManager)tmf.getTrustManagers()[0];
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new CertificateException("Unable to initialize TM");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* =============================================================
|
||||||
|
* The remainder is just support stuff
|
||||||
|
*/
|
||||||
|
|
||||||
|
// use any free port by default
|
||||||
|
volatile int serverPort = 0;
|
||||||
|
|
||||||
|
volatile Exception serverException = null;
|
||||||
|
volatile Exception clientException = null;
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
String keyFilename =
|
||||||
|
System.getProperty("test.src", ".") + "/" + pathToStores +
|
||||||
|
"/" + keyStoreFile;
|
||||||
|
String trustFilename =
|
||||||
|
System.getProperty("test.src", ".") + "/" + pathToStores +
|
||||||
|
"/" + trustStoreFile;
|
||||||
|
|
||||||
|
System.setProperty("javax.net.ssl.keyStore", keyFilename);
|
||||||
|
System.setProperty("javax.net.ssl.keyStorePassword", passwd);
|
||||||
|
System.setProperty("javax.net.ssl.trustStore", trustFilename);
|
||||||
|
System.setProperty("javax.net.ssl.trustStorePassword", passwd);
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
System.setProperty("javax.net.debug", "all");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Start the tests.
|
||||||
|
*/
|
||||||
|
new EmptyCertificateAuthorities();
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread clientThread = null;
|
||||||
|
Thread serverThread = null;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Primary constructor, used to drive remainder of the test.
|
||||||
|
*
|
||||||
|
* Fork off the other side, then do your work.
|
||||||
|
*/
|
||||||
|
EmptyCertificateAuthorities() throws Exception {
|
||||||
|
try {
|
||||||
|
if (separateServerThread) {
|
||||||
|
startServer(true);
|
||||||
|
startClient(false);
|
||||||
|
} else {
|
||||||
|
startClient(true);
|
||||||
|
startServer(false);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
// swallow for now. Show later
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wait for other side to close down.
|
||||||
|
*/
|
||||||
|
if (separateServerThread) {
|
||||||
|
serverThread.join();
|
||||||
|
} else {
|
||||||
|
clientThread.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When we get here, the test is pretty much over.
|
||||||
|
* Which side threw the error?
|
||||||
|
*/
|
||||||
|
Exception local;
|
||||||
|
Exception remote;
|
||||||
|
String whichRemote;
|
||||||
|
|
||||||
|
if (separateServerThread) {
|
||||||
|
remote = serverException;
|
||||||
|
local = clientException;
|
||||||
|
whichRemote = "server";
|
||||||
|
} else {
|
||||||
|
remote = clientException;
|
||||||
|
local = serverException;
|
||||||
|
whichRemote = "client";
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If both failed, return the curthread's exception, but also
|
||||||
|
* print the remote side Exception
|
||||||
|
*/
|
||||||
|
if ((local != null) && (remote != null)) {
|
||||||
|
System.out.println(whichRemote + " also threw:");
|
||||||
|
remote.printStackTrace();
|
||||||
|
System.out.println();
|
||||||
|
throw local;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remote != null) {
|
||||||
|
throw remote;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (local != null) {
|
||||||
|
throw local;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void startServer(boolean newThread) throws Exception {
|
||||||
|
if (newThread) {
|
||||||
|
serverThread = new Thread() {
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
doServerSide();
|
||||||
|
} catch (Exception e) {
|
||||||
|
/*
|
||||||
|
* Our server thread just died.
|
||||||
|
*
|
||||||
|
* Release the client, if not active already...
|
||||||
|
*/
|
||||||
|
System.err.println("Server died...");
|
||||||
|
serverReady = true;
|
||||||
|
serverException = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
serverThread.start();
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
doServerSide();
|
||||||
|
} catch (Exception e) {
|
||||||
|
serverException = e;
|
||||||
|
} finally {
|
||||||
|
serverReady = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void startClient(boolean newThread) throws Exception {
|
||||||
|
if (newThread) {
|
||||||
|
clientThread = new Thread() {
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
doClientSide();
|
||||||
|
} catch (Exception e) {
|
||||||
|
/*
|
||||||
|
* Our client thread just died.
|
||||||
|
*/
|
||||||
|
System.err.println("Client died...");
|
||||||
|
clientException = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
clientThread.start();
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
doClientSide();
|
||||||
|
} catch (Exception e) {
|
||||||
|
clientException = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,327 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 4873188
|
||||||
|
* @summary Support TLS 1.1
|
||||||
|
* @run main/othervm -Djavax.net.debug=all ExportableBlockCipher
|
||||||
|
*
|
||||||
|
* @author Xuelei Fan
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.*;
|
||||||
|
import javax.net.ssl.*;
|
||||||
|
|
||||||
|
public class ExportableBlockCipher {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* =============================================================
|
||||||
|
* Set the various variables needed for the tests, then
|
||||||
|
* specify what tests to run on each side.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Should we run the client or server in a separate thread?
|
||||||
|
* Both sides can throw exceptions, but do you have a preference
|
||||||
|
* as to which side should be the main thread.
|
||||||
|
*/
|
||||||
|
static boolean separateServerThread = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Where do we find the keystores?
|
||||||
|
*/
|
||||||
|
static String pathToStores = "/../../../../etc";
|
||||||
|
static String keyStoreFile = "keystore";
|
||||||
|
static String trustStoreFile = "truststore";
|
||||||
|
static String passwd = "passphrase";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Is the server ready to serve?
|
||||||
|
*/
|
||||||
|
volatile static boolean serverReady = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Turn on SSL debugging?
|
||||||
|
*/
|
||||||
|
static boolean debug = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the client or server is doing some kind of object creation
|
||||||
|
* that the other side depends on, and that thread prematurely
|
||||||
|
* exits, you may experience a hang. The test harness will
|
||||||
|
* terminate all hung threads after its timeout has expired,
|
||||||
|
* currently 3 minutes by default, but you might try to be
|
||||||
|
* smart about it....
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define the server side of the test.
|
||||||
|
*
|
||||||
|
* If the server prematurely exits, serverReady will be set to true
|
||||||
|
* to avoid infinite hangs.
|
||||||
|
*/
|
||||||
|
void doServerSide() throws Exception {
|
||||||
|
SSLServerSocketFactory sslssf =
|
||||||
|
(SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
|
||||||
|
SSLServerSocket sslServerSocket =
|
||||||
|
(SSLServerSocket) sslssf.createServerSocket(serverPort);
|
||||||
|
|
||||||
|
serverPort = sslServerSocket.getLocalPort();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Signal Client, we're ready for his connect.
|
||||||
|
*/
|
||||||
|
serverReady = true;
|
||||||
|
|
||||||
|
SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
|
||||||
|
InputStream sslIS = sslSocket.getInputStream();
|
||||||
|
OutputStream sslOS = sslSocket.getOutputStream();
|
||||||
|
|
||||||
|
boolean interrupted = false;
|
||||||
|
try {
|
||||||
|
sslIS.read();
|
||||||
|
sslOS.write('A');
|
||||||
|
sslOS.flush();
|
||||||
|
} catch (SSLException ssle) {
|
||||||
|
// get the expected exception
|
||||||
|
interrupted = true;
|
||||||
|
} finally {
|
||||||
|
sslSocket.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!interrupted) {
|
||||||
|
throw new SSLHandshakeException(
|
||||||
|
"A weak cipher suite is negotiated, " +
|
||||||
|
"TLSv1.1 must not negotiate the exportable cipher suites.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define the client side of the test.
|
||||||
|
*
|
||||||
|
* If the server prematurely exits, serverReady will be set to true
|
||||||
|
* to avoid infinite hangs.
|
||||||
|
*/
|
||||||
|
void doClientSide() throws Exception {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wait for server to get started.
|
||||||
|
*/
|
||||||
|
while (!serverReady) {
|
||||||
|
Thread.sleep(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
SSLSocketFactory sslsf =
|
||||||
|
(SSLSocketFactory) SSLSocketFactory.getDefault();
|
||||||
|
SSLSocket sslSocket = (SSLSocket)
|
||||||
|
sslsf.createSocket("localhost", serverPort);
|
||||||
|
|
||||||
|
// enable TLSv1.1 only
|
||||||
|
sslSocket.setEnabledProtocols(new String[] {"TLSv1.1"});
|
||||||
|
|
||||||
|
// enable a exportable block cipher
|
||||||
|
sslSocket.setEnabledCipherSuites(
|
||||||
|
new String[] {"SSL_RSA_EXPORT_WITH_DES40_CBC_SHA"});
|
||||||
|
|
||||||
|
InputStream sslIS = sslSocket.getInputStream();
|
||||||
|
OutputStream sslOS = sslSocket.getOutputStream();
|
||||||
|
|
||||||
|
boolean interrupted = false;
|
||||||
|
try {
|
||||||
|
sslOS.write('B');
|
||||||
|
sslOS.flush();
|
||||||
|
sslIS.read();
|
||||||
|
} catch (SSLException ssle) {
|
||||||
|
// get the expected exception
|
||||||
|
interrupted = true;
|
||||||
|
} finally {
|
||||||
|
sslSocket.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!interrupted) {
|
||||||
|
throw new SSLHandshakeException(
|
||||||
|
"A weak cipher suite is negotiated, " +
|
||||||
|
"TLSv1.1 must not negotiate the exportable cipher suites.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* =============================================================
|
||||||
|
* The remainder is just support stuff
|
||||||
|
*/
|
||||||
|
|
||||||
|
// use any free port by default
|
||||||
|
volatile int serverPort = 0;
|
||||||
|
|
||||||
|
volatile Exception serverException = null;
|
||||||
|
volatile Exception clientException = null;
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
String keyFilename =
|
||||||
|
System.getProperty("test.src", ".") + "/" + pathToStores +
|
||||||
|
"/" + keyStoreFile;
|
||||||
|
String trustFilename =
|
||||||
|
System.getProperty("test.src", ".") + "/" + pathToStores +
|
||||||
|
"/" + trustStoreFile;
|
||||||
|
|
||||||
|
System.setProperty("javax.net.ssl.keyStore", keyFilename);
|
||||||
|
System.setProperty("javax.net.ssl.keyStorePassword", passwd);
|
||||||
|
System.setProperty("javax.net.ssl.trustStore", trustFilename);
|
||||||
|
System.setProperty("javax.net.ssl.trustStorePassword", passwd);
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
System.setProperty("javax.net.debug", "all");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Start the tests.
|
||||||
|
*/
|
||||||
|
new ExportableBlockCipher();
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread clientThread = null;
|
||||||
|
Thread serverThread = null;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Primary constructor, used to drive remainder of the test.
|
||||||
|
*
|
||||||
|
* Fork off the other side, then do your work.
|
||||||
|
*/
|
||||||
|
ExportableBlockCipher() throws Exception {
|
||||||
|
try {
|
||||||
|
if (separateServerThread) {
|
||||||
|
startServer(true);
|
||||||
|
startClient(false);
|
||||||
|
} else {
|
||||||
|
startClient(true);
|
||||||
|
startServer(false);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
// swallow for now. Show later
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wait for other side to close down.
|
||||||
|
*/
|
||||||
|
if (separateServerThread) {
|
||||||
|
serverThread.join();
|
||||||
|
} else {
|
||||||
|
clientThread.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When we get here, the test is pretty much over.
|
||||||
|
* Which side threw the error?
|
||||||
|
*/
|
||||||
|
Exception local;
|
||||||
|
Exception remote;
|
||||||
|
String whichRemote;
|
||||||
|
|
||||||
|
if (separateServerThread) {
|
||||||
|
remote = serverException;
|
||||||
|
local = clientException;
|
||||||
|
whichRemote = "server";
|
||||||
|
} else {
|
||||||
|
remote = clientException;
|
||||||
|
local = serverException;
|
||||||
|
whichRemote = "client";
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If both failed, return the curthread's exception, but also
|
||||||
|
* print the remote side Exception
|
||||||
|
*/
|
||||||
|
if ((local != null) && (remote != null)) {
|
||||||
|
System.out.println(whichRemote + " also threw:");
|
||||||
|
remote.printStackTrace();
|
||||||
|
System.out.println();
|
||||||
|
throw local;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remote != null) {
|
||||||
|
throw remote;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (local != null) {
|
||||||
|
throw local;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void startServer(boolean newThread) throws Exception {
|
||||||
|
if (newThread) {
|
||||||
|
serverThread = new Thread() {
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
doServerSide();
|
||||||
|
} catch (Exception e) {
|
||||||
|
/*
|
||||||
|
* Our server thread just died.
|
||||||
|
*
|
||||||
|
* Release the client, if not active already...
|
||||||
|
*/
|
||||||
|
System.err.println("Server died...");
|
||||||
|
serverReady = true;
|
||||||
|
serverException = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
serverThread.start();
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
doServerSide();
|
||||||
|
} catch (Exception e) {
|
||||||
|
serverException = e;
|
||||||
|
} finally {
|
||||||
|
serverReady = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void startClient(boolean newThread) throws Exception {
|
||||||
|
if (newThread) {
|
||||||
|
clientThread = new Thread() {
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
doClientSide();
|
||||||
|
} catch (Exception e) {
|
||||||
|
/*
|
||||||
|
* Our client thread just died.
|
||||||
|
*/
|
||||||
|
System.err.println("Client died...");
|
||||||
|
clientException = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
clientThread.start();
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
doClientSide();
|
||||||
|
} catch (Exception e) {
|
||||||
|
clientException = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,327 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 4873188
|
||||||
|
* @summary Support TLS 1.1
|
||||||
|
* @run main/othervm -Djavax.net.debug=all ExportableStreamCipher
|
||||||
|
*
|
||||||
|
* @author Xuelei Fan
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.*;
|
||||||
|
import javax.net.ssl.*;
|
||||||
|
|
||||||
|
public class ExportableStreamCipher {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* =============================================================
|
||||||
|
* Set the various variables needed for the tests, then
|
||||||
|
* specify what tests to run on each side.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Should we run the client or server in a separate thread?
|
||||||
|
* Both sides can throw exceptions, but do you have a preference
|
||||||
|
* as to which side should be the main thread.
|
||||||
|
*/
|
||||||
|
static boolean separateServerThread = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Where do we find the keystores?
|
||||||
|
*/
|
||||||
|
static String pathToStores = "/../../../../etc";
|
||||||
|
static String keyStoreFile = "keystore";
|
||||||
|
static String trustStoreFile = "truststore";
|
||||||
|
static String passwd = "passphrase";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Is the server ready to serve?
|
||||||
|
*/
|
||||||
|
volatile static boolean serverReady = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Turn on SSL debugging?
|
||||||
|
*/
|
||||||
|
static boolean debug = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the client or server is doing some kind of object creation
|
||||||
|
* that the other side depends on, and that thread prematurely
|
||||||
|
* exits, you may experience a hang. The test harness will
|
||||||
|
* terminate all hung threads after its timeout has expired,
|
||||||
|
* currently 3 minutes by default, but you might try to be
|
||||||
|
* smart about it....
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define the server side of the test.
|
||||||
|
*
|
||||||
|
* If the server prematurely exits, serverReady will be set to true
|
||||||
|
* to avoid infinite hangs.
|
||||||
|
*/
|
||||||
|
void doServerSide() throws Exception {
|
||||||
|
SSLServerSocketFactory sslssf =
|
||||||
|
(SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
|
||||||
|
SSLServerSocket sslServerSocket =
|
||||||
|
(SSLServerSocket) sslssf.createServerSocket(serverPort);
|
||||||
|
|
||||||
|
serverPort = sslServerSocket.getLocalPort();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Signal Client, we're ready for his connect.
|
||||||
|
*/
|
||||||
|
serverReady = true;
|
||||||
|
|
||||||
|
SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
|
||||||
|
InputStream sslIS = sslSocket.getInputStream();
|
||||||
|
OutputStream sslOS = sslSocket.getOutputStream();
|
||||||
|
|
||||||
|
boolean interrupted = false;
|
||||||
|
try {
|
||||||
|
sslIS.read();
|
||||||
|
sslOS.write('A');
|
||||||
|
sslOS.flush();
|
||||||
|
} catch (SSLException ssle) {
|
||||||
|
// get the expected exception
|
||||||
|
interrupted = true;
|
||||||
|
} finally {
|
||||||
|
sslSocket.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!interrupted) {
|
||||||
|
throw new SSLHandshakeException(
|
||||||
|
"A weak cipher suite is negotiated, " +
|
||||||
|
"TLSv1.1 must not negotiate the exportable cipher suites.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define the client side of the test.
|
||||||
|
*
|
||||||
|
* If the server prematurely exits, serverReady will be set to true
|
||||||
|
* to avoid infinite hangs.
|
||||||
|
*/
|
||||||
|
void doClientSide() throws Exception {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wait for server to get started.
|
||||||
|
*/
|
||||||
|
while (!serverReady) {
|
||||||
|
Thread.sleep(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
SSLSocketFactory sslsf =
|
||||||
|
(SSLSocketFactory) SSLSocketFactory.getDefault();
|
||||||
|
SSLSocket sslSocket = (SSLSocket)
|
||||||
|
sslsf.createSocket("localhost", serverPort);
|
||||||
|
|
||||||
|
// enable TLSv1.1 only
|
||||||
|
sslSocket.setEnabledProtocols(new String[] {"TLSv1.1"});
|
||||||
|
|
||||||
|
// enable a exportable stream cipher
|
||||||
|
sslSocket.setEnabledCipherSuites(
|
||||||
|
new String[] {"SSL_RSA_EXPORT_WITH_RC4_40_MD5"});
|
||||||
|
|
||||||
|
InputStream sslIS = sslSocket.getInputStream();
|
||||||
|
OutputStream sslOS = sslSocket.getOutputStream();
|
||||||
|
|
||||||
|
boolean interrupted = false;
|
||||||
|
try {
|
||||||
|
sslOS.write('B');
|
||||||
|
sslOS.flush();
|
||||||
|
sslIS.read();
|
||||||
|
} catch (SSLException ssle) {
|
||||||
|
// get the expected exception
|
||||||
|
interrupted = true;
|
||||||
|
} finally {
|
||||||
|
sslSocket.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!interrupted) {
|
||||||
|
throw new SSLHandshakeException(
|
||||||
|
"A weak cipher suite is negotiated, " +
|
||||||
|
"TLSv1.1 must not negotiate the exportable cipher suites.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* =============================================================
|
||||||
|
* The remainder is just support stuff
|
||||||
|
*/
|
||||||
|
|
||||||
|
// use any free port by default
|
||||||
|
volatile int serverPort = 0;
|
||||||
|
|
||||||
|
volatile Exception serverException = null;
|
||||||
|
volatile Exception clientException = null;
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
String keyFilename =
|
||||||
|
System.getProperty("test.src", ".") + "/" + pathToStores +
|
||||||
|
"/" + keyStoreFile;
|
||||||
|
String trustFilename =
|
||||||
|
System.getProperty("test.src", ".") + "/" + pathToStores +
|
||||||
|
"/" + trustStoreFile;
|
||||||
|
|
||||||
|
System.setProperty("javax.net.ssl.keyStore", keyFilename);
|
||||||
|
System.setProperty("javax.net.ssl.keyStorePassword", passwd);
|
||||||
|
System.setProperty("javax.net.ssl.trustStore", trustFilename);
|
||||||
|
System.setProperty("javax.net.ssl.trustStorePassword", passwd);
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
System.setProperty("javax.net.debug", "all");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Start the tests.
|
||||||
|
*/
|
||||||
|
new ExportableStreamCipher();
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread clientThread = null;
|
||||||
|
Thread serverThread = null;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Primary constructor, used to drive remainder of the test.
|
||||||
|
*
|
||||||
|
* Fork off the other side, then do your work.
|
||||||
|
*/
|
||||||
|
ExportableStreamCipher() throws Exception {
|
||||||
|
try {
|
||||||
|
if (separateServerThread) {
|
||||||
|
startServer(true);
|
||||||
|
startClient(false);
|
||||||
|
} else {
|
||||||
|
startClient(true);
|
||||||
|
startServer(false);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
// swallow for now. Show later
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wait for other side to close down.
|
||||||
|
*/
|
||||||
|
if (separateServerThread) {
|
||||||
|
serverThread.join();
|
||||||
|
} else {
|
||||||
|
clientThread.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When we get here, the test is pretty much over.
|
||||||
|
* Which side threw the error?
|
||||||
|
*/
|
||||||
|
Exception local;
|
||||||
|
Exception remote;
|
||||||
|
String whichRemote;
|
||||||
|
|
||||||
|
if (separateServerThread) {
|
||||||
|
remote = serverException;
|
||||||
|
local = clientException;
|
||||||
|
whichRemote = "server";
|
||||||
|
} else {
|
||||||
|
remote = clientException;
|
||||||
|
local = serverException;
|
||||||
|
whichRemote = "client";
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If both failed, return the curthread's exception, but also
|
||||||
|
* print the remote side Exception
|
||||||
|
*/
|
||||||
|
if ((local != null) && (remote != null)) {
|
||||||
|
System.out.println(whichRemote + " also threw:");
|
||||||
|
remote.printStackTrace();
|
||||||
|
System.out.println();
|
||||||
|
throw local;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remote != null) {
|
||||||
|
throw remote;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (local != null) {
|
||||||
|
throw local;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void startServer(boolean newThread) throws Exception {
|
||||||
|
if (newThread) {
|
||||||
|
serverThread = new Thread() {
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
doServerSide();
|
||||||
|
} catch (Exception e) {
|
||||||
|
/*
|
||||||
|
* Our server thread just died.
|
||||||
|
*
|
||||||
|
* Release the client, if not active already...
|
||||||
|
*/
|
||||||
|
System.err.println("Server died...");
|
||||||
|
serverReady = true;
|
||||||
|
serverException = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
serverThread.start();
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
doServerSide();
|
||||||
|
} catch (Exception e) {
|
||||||
|
serverException = e;
|
||||||
|
} finally {
|
||||||
|
serverReady = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void startClient(boolean newThread) throws Exception {
|
||||||
|
if (newThread) {
|
||||||
|
clientThread = new Thread() {
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
doClientSide();
|
||||||
|
} catch (Exception e) {
|
||||||
|
/*
|
||||||
|
* Our client thread just died.
|
||||||
|
*/
|
||||||
|
System.err.println("Client died...");
|
||||||
|
clientException = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
clientThread.start();
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
doClientSide();
|
||||||
|
} catch (Exception e) {
|
||||||
|
clientException = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,303 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 4873188
|
||||||
|
* @summary Support TLS 1.1
|
||||||
|
* @run main/othervm -Djavax.net.debug=all GenericBlockCipher
|
||||||
|
*
|
||||||
|
* @author Xuelei Fan
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.*;
|
||||||
|
import javax.net.ssl.*;
|
||||||
|
|
||||||
|
public class GenericBlockCipher {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* =============================================================
|
||||||
|
* Set the various variables needed for the tests, then
|
||||||
|
* specify what tests to run on each side.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Should we run the client or server in a separate thread?
|
||||||
|
* Both sides can throw exceptions, but do you have a preference
|
||||||
|
* as to which side should be the main thread.
|
||||||
|
*/
|
||||||
|
static boolean separateServerThread = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Where do we find the keystores?
|
||||||
|
*/
|
||||||
|
static String pathToStores = "/../../../../etc";
|
||||||
|
static String keyStoreFile = "keystore";
|
||||||
|
static String trustStoreFile = "truststore";
|
||||||
|
static String passwd = "passphrase";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Is the server ready to serve?
|
||||||
|
*/
|
||||||
|
volatile static boolean serverReady = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Turn on SSL debugging?
|
||||||
|
*/
|
||||||
|
static boolean debug = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the client or server is doing some kind of object creation
|
||||||
|
* that the other side depends on, and that thread prematurely
|
||||||
|
* exits, you may experience a hang. The test harness will
|
||||||
|
* terminate all hung threads after its timeout has expired,
|
||||||
|
* currently 3 minutes by default, but you might try to be
|
||||||
|
* smart about it....
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define the server side of the test.
|
||||||
|
*
|
||||||
|
* If the server prematurely exits, serverReady will be set to true
|
||||||
|
* to avoid infinite hangs.
|
||||||
|
*/
|
||||||
|
void doServerSide() throws Exception {
|
||||||
|
SSLServerSocketFactory sslssf =
|
||||||
|
(SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
|
||||||
|
SSLServerSocket sslServerSocket =
|
||||||
|
(SSLServerSocket) sslssf.createServerSocket(serverPort);
|
||||||
|
|
||||||
|
serverPort = sslServerSocket.getLocalPort();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Signal Client, we're ready for his connect.
|
||||||
|
*/
|
||||||
|
serverReady = true;
|
||||||
|
|
||||||
|
SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
|
||||||
|
InputStream sslIS = sslSocket.getInputStream();
|
||||||
|
OutputStream sslOS = sslSocket.getOutputStream();
|
||||||
|
|
||||||
|
sslIS.read();
|
||||||
|
sslOS.write('A');
|
||||||
|
sslOS.flush();
|
||||||
|
|
||||||
|
sslSocket.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define the client side of the test.
|
||||||
|
*
|
||||||
|
* If the server prematurely exits, serverReady will be set to true
|
||||||
|
* to avoid infinite hangs.
|
||||||
|
*/
|
||||||
|
void doClientSide() throws Exception {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wait for server to get started.
|
||||||
|
*/
|
||||||
|
while (!serverReady) {
|
||||||
|
Thread.sleep(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
SSLSocketFactory sslsf =
|
||||||
|
(SSLSocketFactory) SSLSocketFactory.getDefault();
|
||||||
|
SSLSocket sslSocket = (SSLSocket)
|
||||||
|
sslsf.createSocket("localhost", serverPort);
|
||||||
|
|
||||||
|
// enable TLSv1.1 only
|
||||||
|
sslSocket.setEnabledProtocols(new String[] {"TLSv1.1"});
|
||||||
|
|
||||||
|
// enable a block cipher
|
||||||
|
sslSocket.setEnabledCipherSuites(
|
||||||
|
new String[] {"TLS_RSA_WITH_AES_128_CBC_SHA"});
|
||||||
|
|
||||||
|
InputStream sslIS = sslSocket.getInputStream();
|
||||||
|
OutputStream sslOS = sslSocket.getOutputStream();
|
||||||
|
|
||||||
|
sslOS.write('B');
|
||||||
|
sslOS.flush();
|
||||||
|
sslIS.read();
|
||||||
|
|
||||||
|
sslSocket.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* =============================================================
|
||||||
|
* The remainder is just support stuff
|
||||||
|
*/
|
||||||
|
|
||||||
|
// use any free port by default
|
||||||
|
volatile int serverPort = 0;
|
||||||
|
|
||||||
|
volatile Exception serverException = null;
|
||||||
|
volatile Exception clientException = null;
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
String keyFilename =
|
||||||
|
System.getProperty("test.src", ".") + "/" + pathToStores +
|
||||||
|
"/" + keyStoreFile;
|
||||||
|
String trustFilename =
|
||||||
|
System.getProperty("test.src", ".") + "/" + pathToStores +
|
||||||
|
"/" + trustStoreFile;
|
||||||
|
|
||||||
|
System.setProperty("javax.net.ssl.keyStore", keyFilename);
|
||||||
|
System.setProperty("javax.net.ssl.keyStorePassword", passwd);
|
||||||
|
System.setProperty("javax.net.ssl.trustStore", trustFilename);
|
||||||
|
System.setProperty("javax.net.ssl.trustStorePassword", passwd);
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
System.setProperty("javax.net.debug", "all");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Start the tests.
|
||||||
|
*/
|
||||||
|
new GenericBlockCipher();
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread clientThread = null;
|
||||||
|
Thread serverThread = null;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Primary constructor, used to drive remainder of the test.
|
||||||
|
*
|
||||||
|
* Fork off the other side, then do your work.
|
||||||
|
*/
|
||||||
|
GenericBlockCipher() throws Exception {
|
||||||
|
try {
|
||||||
|
if (separateServerThread) {
|
||||||
|
startServer(true);
|
||||||
|
startClient(false);
|
||||||
|
} else {
|
||||||
|
startClient(true);
|
||||||
|
startServer(false);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
// swallow for now. Show later
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wait for other side to close down.
|
||||||
|
*/
|
||||||
|
if (separateServerThread) {
|
||||||
|
serverThread.join();
|
||||||
|
} else {
|
||||||
|
clientThread.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When we get here, the test is pretty much over.
|
||||||
|
* Which side threw the error?
|
||||||
|
*/
|
||||||
|
Exception local;
|
||||||
|
Exception remote;
|
||||||
|
String whichRemote;
|
||||||
|
|
||||||
|
if (separateServerThread) {
|
||||||
|
remote = serverException;
|
||||||
|
local = clientException;
|
||||||
|
whichRemote = "server";
|
||||||
|
} else {
|
||||||
|
remote = clientException;
|
||||||
|
local = serverException;
|
||||||
|
whichRemote = "client";
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If both failed, return the curthread's exception, but also
|
||||||
|
* print the remote side Exception
|
||||||
|
*/
|
||||||
|
if ((local != null) && (remote != null)) {
|
||||||
|
System.out.println(whichRemote + " also threw:");
|
||||||
|
remote.printStackTrace();
|
||||||
|
System.out.println();
|
||||||
|
throw local;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remote != null) {
|
||||||
|
throw remote;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (local != null) {
|
||||||
|
throw local;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void startServer(boolean newThread) throws Exception {
|
||||||
|
if (newThread) {
|
||||||
|
serverThread = new Thread() {
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
doServerSide();
|
||||||
|
} catch (Exception e) {
|
||||||
|
/*
|
||||||
|
* Our server thread just died.
|
||||||
|
*
|
||||||
|
* Release the client, if not active already...
|
||||||
|
*/
|
||||||
|
System.err.println("Server died...");
|
||||||
|
serverReady = true;
|
||||||
|
serverException = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
serverThread.start();
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
doServerSide();
|
||||||
|
} catch (Exception e) {
|
||||||
|
serverException = e;
|
||||||
|
} finally {
|
||||||
|
serverReady = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void startClient(boolean newThread) throws Exception {
|
||||||
|
if (newThread) {
|
||||||
|
clientThread = new Thread() {
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
doClientSide();
|
||||||
|
} catch (Exception e) {
|
||||||
|
/*
|
||||||
|
* Our client thread just died.
|
||||||
|
*/
|
||||||
|
System.err.println("Client died...");
|
||||||
|
clientException = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
clientThread.start();
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
doClientSide();
|
||||||
|
} catch (Exception e) {
|
||||||
|
clientException = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,303 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 4873188
|
||||||
|
* @summary Support TLS 1.1
|
||||||
|
* @run main/othervm -Djavax.net.debug=all GenericStreamCipher
|
||||||
|
*
|
||||||
|
* @author Xuelei Fan
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.*;
|
||||||
|
import javax.net.ssl.*;
|
||||||
|
|
||||||
|
public class GenericStreamCipher {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* =============================================================
|
||||||
|
* Set the various variables needed for the tests, then
|
||||||
|
* specify what tests to run on each side.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Should we run the client or server in a separate thread?
|
||||||
|
* Both sides can throw exceptions, but do you have a preference
|
||||||
|
* as to which side should be the main thread.
|
||||||
|
*/
|
||||||
|
static boolean separateServerThread = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Where do we find the keystores?
|
||||||
|
*/
|
||||||
|
static String pathToStores = "/../../../../etc";
|
||||||
|
static String keyStoreFile = "keystore";
|
||||||
|
static String trustStoreFile = "truststore";
|
||||||
|
static String passwd = "passphrase";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Is the server ready to serve?
|
||||||
|
*/
|
||||||
|
volatile static boolean serverReady = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Turn on SSL debugging?
|
||||||
|
*/
|
||||||
|
static boolean debug = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the client or server is doing some kind of object creation
|
||||||
|
* that the other side depends on, and that thread prematurely
|
||||||
|
* exits, you may experience a hang. The test harness will
|
||||||
|
* terminate all hung threads after its timeout has expired,
|
||||||
|
* currently 3 minutes by default, but you might try to be
|
||||||
|
* smart about it....
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define the server side of the test.
|
||||||
|
*
|
||||||
|
* If the server prematurely exits, serverReady will be set to true
|
||||||
|
* to avoid infinite hangs.
|
||||||
|
*/
|
||||||
|
void doServerSide() throws Exception {
|
||||||
|
SSLServerSocketFactory sslssf =
|
||||||
|
(SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
|
||||||
|
SSLServerSocket sslServerSocket =
|
||||||
|
(SSLServerSocket) sslssf.createServerSocket(serverPort);
|
||||||
|
|
||||||
|
serverPort = sslServerSocket.getLocalPort();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Signal Client, we're ready for his connect.
|
||||||
|
*/
|
||||||
|
serverReady = true;
|
||||||
|
|
||||||
|
SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
|
||||||
|
InputStream sslIS = sslSocket.getInputStream();
|
||||||
|
OutputStream sslOS = sslSocket.getOutputStream();
|
||||||
|
|
||||||
|
sslIS.read();
|
||||||
|
sslOS.write('A');
|
||||||
|
sslOS.flush();
|
||||||
|
|
||||||
|
sslSocket.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define the client side of the test.
|
||||||
|
*
|
||||||
|
* If the server prematurely exits, serverReady will be set to true
|
||||||
|
* to avoid infinite hangs.
|
||||||
|
*/
|
||||||
|
void doClientSide() throws Exception {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wait for server to get started.
|
||||||
|
*/
|
||||||
|
while (!serverReady) {
|
||||||
|
Thread.sleep(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
SSLSocketFactory sslsf =
|
||||||
|
(SSLSocketFactory) SSLSocketFactory.getDefault();
|
||||||
|
SSLSocket sslSocket = (SSLSocket)
|
||||||
|
sslsf.createSocket("localhost", serverPort);
|
||||||
|
|
||||||
|
// enable TLSv1.1 only
|
||||||
|
sslSocket.setEnabledProtocols(new String[] {"TLSv1.1"});
|
||||||
|
|
||||||
|
// enable a stream cipher
|
||||||
|
sslSocket.setEnabledCipherSuites(
|
||||||
|
new String[] {"SSL_RSA_WITH_RC4_128_MD5"});
|
||||||
|
|
||||||
|
InputStream sslIS = sslSocket.getInputStream();
|
||||||
|
OutputStream sslOS = sslSocket.getOutputStream();
|
||||||
|
|
||||||
|
sslOS.write('B');
|
||||||
|
sslOS.flush();
|
||||||
|
sslIS.read();
|
||||||
|
|
||||||
|
sslSocket.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* =============================================================
|
||||||
|
* The remainder is just support stuff
|
||||||
|
*/
|
||||||
|
|
||||||
|
// use any free port by default
|
||||||
|
volatile int serverPort = 0;
|
||||||
|
|
||||||
|
volatile Exception serverException = null;
|
||||||
|
volatile Exception clientException = null;
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
String keyFilename =
|
||||||
|
System.getProperty("test.src", ".") + "/" + pathToStores +
|
||||||
|
"/" + keyStoreFile;
|
||||||
|
String trustFilename =
|
||||||
|
System.getProperty("test.src", ".") + "/" + pathToStores +
|
||||||
|
"/" + trustStoreFile;
|
||||||
|
|
||||||
|
System.setProperty("javax.net.ssl.keyStore", keyFilename);
|
||||||
|
System.setProperty("javax.net.ssl.keyStorePassword", passwd);
|
||||||
|
System.setProperty("javax.net.ssl.trustStore", trustFilename);
|
||||||
|
System.setProperty("javax.net.ssl.trustStorePassword", passwd);
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
System.setProperty("javax.net.debug", "all");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Start the tests.
|
||||||
|
*/
|
||||||
|
new GenericStreamCipher();
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread clientThread = null;
|
||||||
|
Thread serverThread = null;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Primary constructor, used to drive remainder of the test.
|
||||||
|
*
|
||||||
|
* Fork off the other side, then do your work.
|
||||||
|
*/
|
||||||
|
GenericStreamCipher() throws Exception {
|
||||||
|
try {
|
||||||
|
if (separateServerThread) {
|
||||||
|
startServer(true);
|
||||||
|
startClient(false);
|
||||||
|
} else {
|
||||||
|
startClient(true);
|
||||||
|
startServer(false);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
// swallow for now. Show later
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wait for other side to close down.
|
||||||
|
*/
|
||||||
|
if (separateServerThread) {
|
||||||
|
serverThread.join();
|
||||||
|
} else {
|
||||||
|
clientThread.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When we get here, the test is pretty much over.
|
||||||
|
* Which side threw the error?
|
||||||
|
*/
|
||||||
|
Exception local;
|
||||||
|
Exception remote;
|
||||||
|
String whichRemote;
|
||||||
|
|
||||||
|
if (separateServerThread) {
|
||||||
|
remote = serverException;
|
||||||
|
local = clientException;
|
||||||
|
whichRemote = "server";
|
||||||
|
} else {
|
||||||
|
remote = clientException;
|
||||||
|
local = serverException;
|
||||||
|
whichRemote = "client";
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If both failed, return the curthread's exception, but also
|
||||||
|
* print the remote side Exception
|
||||||
|
*/
|
||||||
|
if ((local != null) && (remote != null)) {
|
||||||
|
System.out.println(whichRemote + " also threw:");
|
||||||
|
remote.printStackTrace();
|
||||||
|
System.out.println();
|
||||||
|
throw local;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remote != null) {
|
||||||
|
throw remote;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (local != null) {
|
||||||
|
throw local;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void startServer(boolean newThread) throws Exception {
|
||||||
|
if (newThread) {
|
||||||
|
serverThread = new Thread() {
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
doServerSide();
|
||||||
|
} catch (Exception e) {
|
||||||
|
/*
|
||||||
|
* Our server thread just died.
|
||||||
|
*
|
||||||
|
* Release the client, if not active already...
|
||||||
|
*/
|
||||||
|
System.err.println("Server died...");
|
||||||
|
serverReady = true;
|
||||||
|
serverException = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
serverThread.start();
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
doServerSide();
|
||||||
|
} catch (Exception e) {
|
||||||
|
serverException = e;
|
||||||
|
} finally {
|
||||||
|
serverReady = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void startClient(boolean newThread) throws Exception {
|
||||||
|
if (newThread) {
|
||||||
|
clientThread = new Thread() {
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
doClientSide();
|
||||||
|
} catch (Exception e) {
|
||||||
|
/*
|
||||||
|
* Our client thread just died.
|
||||||
|
*/
|
||||||
|
System.err.println("Client died...");
|
||||||
|
clientException = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
clientThread.start();
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
doClientSide();
|
||||||
|
} catch (Exception e) {
|
||||||
|
clientException = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -120,6 +120,13 @@ public class CipherTest {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ignore exportable cipher suite for TLSv1.1
|
||||||
|
if (protocol.equals("TLSv1.1")) {
|
||||||
|
if(cipherSuite.indexOf("_EXPORT_") != -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,18 +156,14 @@ public class CipherTest {
|
||||||
cipherSuites.length * protocols.length * clientAuths.length);
|
cipherSuites.length * protocols.length * clientAuths.length);
|
||||||
for (int i = 0; i < cipherSuites.length; i++) {
|
for (int i = 0; i < cipherSuites.length; i++) {
|
||||||
String cipherSuite = cipherSuites[i];
|
String cipherSuite = cipherSuites[i];
|
||||||
if (peerFactory.isSupported(cipherSuite) == false) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// skip kerberos cipher suites
|
|
||||||
if (cipherSuite.startsWith("TLS_KRB5")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (int j = 0; j < protocols.length; j++) {
|
for (int j = 0; j < protocols.length; j++) {
|
||||||
String protocol = protocols[j];
|
String protocol = protocols[j];
|
||||||
if (protocol.equals("SSLv2Hello")) {
|
|
||||||
|
if (!peerFactory.isSupported(cipherSuite, protocol)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int k = 0; k < clientAuths.length; k++) {
|
for (int k = 0; k < clientAuths.length; k++) {
|
||||||
String clientAuth = clientAuths[k];
|
String clientAuth = clientAuths[k];
|
||||||
if ((clientAuth != null) &&
|
if ((clientAuth != null) &&
|
||||||
|
@ -297,7 +300,7 @@ public class CipherTest {
|
||||||
throws Exception {
|
throws Exception {
|
||||||
long time = System.currentTimeMillis();
|
long time = System.currentTimeMillis();
|
||||||
String relPath;
|
String relPath;
|
||||||
if ((args.length > 0) && args[0].equals("sh")) {
|
if ((args != null) && (args.length > 0) && args[0].equals("sh")) {
|
||||||
relPath = pathToStoresSH;
|
relPath = pathToStoresSH;
|
||||||
} else {
|
} else {
|
||||||
relPath = pathToStores;
|
relPath = pathToStores;
|
||||||
|
@ -336,7 +339,30 @@ public class CipherTest {
|
||||||
|
|
||||||
abstract Server newServer(CipherTest cipherTest) throws Exception;
|
abstract Server newServer(CipherTest cipherTest) throws Exception;
|
||||||
|
|
||||||
boolean isSupported(String cipherSuite) {
|
boolean isSupported(String cipherSuite, String protocol) {
|
||||||
|
// skip kerberos cipher suites
|
||||||
|
if (cipherSuite.startsWith("TLS_KRB5")) {
|
||||||
|
System.out.println("Skipping unsupported test for " +
|
||||||
|
cipherSuite + " of " + protocol);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip SSLv2Hello protocol
|
||||||
|
if (protocol.equals("SSLv2Hello")) {
|
||||||
|
System.out.println("Skipping unsupported test for " +
|
||||||
|
cipherSuite + " of " + protocol);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore exportable cipher suite for TLSv1.1
|
||||||
|
if (protocol.equals("TLSv1.1")) {
|
||||||
|
if (cipherSuite.indexOf("_EXPORT_WITH") != -1) {
|
||||||
|
System.out.println("Skipping obsoleted test for " +
|
||||||
|
cipherSuite + " of " + protocol);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue