--- a/jdk/src/share/classes/javax/net/ssl/SSLSocketFactory.java Fri Oct 29 12:35:07 2010 +0200
+++ b/jdk/src/share/classes/javax/net/ssl/SSLSocketFactory.java Sat Oct 30 18:39:17 2010 +0800
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -30,6 +30,7 @@
import javax.net.SocketFactory;
import java.io.IOException;
import java.security.*;
+import java.util.Locale;
import sun.security.action.GetPropertyAction;
@@ -50,7 +51,8 @@
static {
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");
}
--- a/jdk/src/share/classes/sun/security/internal/spec/TlsKeyMaterialParameterSpec.java Fri Oct 29 12:35:07 2010 +0200
+++ b/jdk/src/share/classes/sun/security/internal/spec/TlsKeyMaterialParameterSpec.java Sat Oct 30 18:39:17 2010 +0800
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -90,8 +90,10 @@
throw new NullPointerException();
}
this.masterSecret = masterSecret;
- this.majorVersion = TlsMasterSecretParameterSpec.checkVersion(majorVersion);
- this.minorVersion = TlsMasterSecretParameterSpec.checkVersion(minorVersion);
+ this.majorVersion =
+ TlsMasterSecretParameterSpec.checkVersion(majorVersion);
+ this.minorVersion =
+ TlsMasterSecretParameterSpec.checkVersion(minorVersion);
this.clientRandom = clientRandom.clone();
this.serverRandom = serverRandom.clone();
this.cipherAlgorithm = cipherAlgorithm;
@@ -172,20 +174,36 @@
}
/**
- * 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() {
+ // TLS v1.1 disables the exportable weak cipher suites.
+ if (majorVersion >= 0x03 && minorVersion >= 0x02) {
+ return 0;
+ }
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() {
+ // TLS v1.1 or later uses an explicit IV to protect against
+ // the CBC attacks.
+ if (majorVersion >= 0x03 && minorVersion >= 0x02) {
+ return 0;
+ }
+
return ivLength;
}
--- a/jdk/src/share/classes/sun/security/internal/spec/TlsMasterSecretParameterSpec.java Fri Oct 29 12:35:07 2010 +0200
+++ b/jdk/src/share/classes/sun/security/internal/spec/TlsMasterSecretParameterSpec.java Sat Oct 30 18:39:17 2010 +0800
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -67,7 +67,8 @@
* negative or larger than 255
*/
public TlsMasterSecretParameterSpec(SecretKey premasterSecret,
- int majorVersion, int minorVersion, byte[] clientRandom, byte[] serverRandom) {
+ int majorVersion, int minorVersion,
+ byte[] clientRandom, byte[] serverRandom) {
if (premasterSecret == null) {
throw new NullPointerException("premasterSecret must not be null");
}
@@ -80,7 +81,8 @@
static int checkVersion(int version) {
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;
}
--- a/jdk/src/share/classes/sun/security/ssl/CipherBox.java Fri Oct 29 12:35:07 2010 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/CipherBox.java Sat Oct 30 18:39:17 2010 +0800
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,7 @@
import java.io.ByteArrayInputStream;
import java.io.IOException;
+import java.util.Hashtable;
import java.security.*;
import javax.crypto.*;
@@ -50,6 +51,37 @@
* Individual instances are obtained by calling the static method
* 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
* handled separately.
*
@@ -76,6 +108,21 @@
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.
*/
private CipherBox() {
@@ -90,14 +137,37 @@
* implementation could be found.
*/
private CipherBox(ProtocolVersion protocolVersion, BulkCipher bulkCipher,
- SecretKey key, IvParameterSpec iv, boolean encrypt)
- throws NoSuchAlgorithmException {
+ SecretKey key, IvParameterSpec iv, SecureRandom random,
+ boolean encrypt) throws NoSuchAlgorithmException {
try {
this.protocolVersion = protocolVersion;
this.cipher = JsseJce.getCipher(bulkCipher.transformation);
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
blockSize = cipher.getBlockSize();
// some providers implement getBlockSize() incorrectly
@@ -119,19 +189,37 @@
* Factory method to obtain a new CipherBox object.
*/
static CipherBox newCipherBox(ProtocolVersion version, BulkCipher cipher,
- SecretKey key, IvParameterSpec iv, boolean encrypt)
- throws NoSuchAlgorithmException {
+ SecretKey key, IvParameterSpec iv, SecureRandom random,
+ boolean encrypt) throws NoSuchAlgorithmException {
if (cipher.allowed == false) {
throw new NoSuchAlgorithmException("Unsupported cipher " + cipher);
}
+
if (cipher == B_NULL) {
return NULL;
} 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
* resulting block.
*/
@@ -139,8 +227,26 @@
if (cipher == null) {
return len;
}
+
try {
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);
}
if (debug != null && Debug.isOn("plaintext")) {
@@ -189,6 +295,34 @@
int pos = bb.position();
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
len = addPadding(bb, blockSize);
bb.position(pos);
@@ -236,11 +370,25 @@
/*
* Decrypts a block of data, returning the size of the
* 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 {
if (cipher == null) {
return len;
}
+
try {
int newLen = cipher.update(buf, offset, len, buf, offset);
if (newLen != len) {
@@ -263,6 +411,18 @@
if (blockSize != 0) {
newLen = removePadding(buf, offset, newLen,
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;
} catch (ShortBufferException e) {
@@ -277,6 +437,8 @@
* point to the end of the decrypted/depadded data. The initial
* limit and new limit may be different, given we may
* have stripped off some padding bytes.
+ *
+ * @see decrypt(byte[], int, int)
*/
int decrypt(ByteBuffer bb) throws BadPaddingException {
@@ -292,7 +454,6 @@
* Decrypt "in-place".
*/
int pos = bb.position();
-
ByteBuffer dup = bb.duplicate();
int newLen = cipher.update(dup, bb);
if (newLen != len) {
@@ -320,6 +481,33 @@
if (blockSize != 0) {
bb.position(pos);
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;
} catch (ShortBufferException e) {
--- a/jdk/src/share/classes/sun/security/ssl/CipherSuite.java Fri Oct 29 12:35:07 2010 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/CipherSuite.java Sat Oct 30 18:39:17 2010 +0800
@@ -30,6 +30,7 @@
import java.security.NoSuchAlgorithmException;
import java.security.InvalidKeyException;
+import java.security.SecureRandom;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
@@ -112,8 +113,12 @@
// true iff implemented and enabled at compile time
final boolean allowed;
+ // obsoleted since protocol version
+ final int obsoleted;
+
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.id = id;
this.priority = priority;
@@ -136,6 +141,7 @@
allowed &= keyExchange.allowed;
allowed &= cipher.allowed;
this.allowed = allowed;
+ this.obsoleted = obsoleted;
}
private CipherSuite(String name, int id) {
@@ -148,6 +154,7 @@
this.cipher = null;
this.macAlg = null;
this.exportable = false;
+ this.obsoleted = ProtocolVersion.LIMIT_MAX_VALUE;
}
/**
@@ -197,10 +204,12 @@
if (s == null) {
throw new IllegalArgumentException("Name must not be null");
}
+
CipherSuite c = nameMap.get(s);
if ((c == null) || (c.allowed == false)) {
throw new IllegalArgumentException("Unsupported ciphersuite " + s);
}
+
return c;
}
@@ -228,9 +237,11 @@
}
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,
- cipher, allowed);
+ cipher, allowed, obsoleted);
if (idMap.put(id, c) != null) {
throw new RuntimeException("Duplicate ciphersuite definition: "
+ id + ", " + name);
@@ -243,6 +254,12 @@
}
}
+ 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) {
CipherSuite c = new CipherSuite(name, id);
if (idMap.put(id, c) != null) {
@@ -380,10 +397,11 @@
*
* @exception NoSuchAlgorithmException if anything goes wrong
*/
- CipherBox newCipher(ProtocolVersion version,
- SecretKey key, IvParameterSpec iv,
+ CipherBox newCipher(ProtocolVersion version, SecretKey key,
+ IvParameterSpec iv, SecureRandom random,
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 @@
if (this == B_AES_256) {
return isAvailable(this);
}
+
// always available
return true;
}
@@ -421,7 +440,8 @@
(new byte[cipher.expandedKeySize], cipher.algorithm);
IvParameterSpec iv =
new IvParameterSpec(new byte[cipher.ivSize]);
- cipher.newCipher(ProtocolVersion.DEFAULT, key, iv, true);
+ cipher.newCipher(ProtocolVersion.DEFAULT,
+ key, iv, null, true);
b = Boolean.TRUE;
} catch (NoSuchAlgorithmException e) {
b = Boolean.FALSE;
@@ -509,6 +529,239 @@
// N: ciphersuites only allowed if we are not in FIPS mode
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",
0x0000, 1, K_NULL, B_NULL, F);
@@ -574,7 +827,6 @@
0x0016, --p, K_DHE_RSA, B_3DES, T);
add("SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
0x0013, --p, K_DHE_DSS, B_3DES, N);
-
add("SSL_RSA_WITH_DES_CBC_SHA",
0x0009, --p, K_RSA, B_DES, N);
add("SSL_DHE_RSA_WITH_DES_CBC_SHA",
@@ -582,13 +834,17 @@
add("SSL_DHE_DSS_WITH_DES_CBC_SHA",
0x0012, --p, K_DHE_DSS, B_DES, N);
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",
- 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",
- 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",
- 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)
add("TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
@@ -634,9 +890,11 @@
0xC017, --p, K_ECDH_ANON, B_3DES, T);
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",
- 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",
0xC015, --p, K_ECDH_ANON, B_NULL, N);
@@ -655,52 +913,212 @@
add("TLS_KRB5_WITH_DES_CBC_MD5",
0x0022, --p, K_KRB5, B_DES, N);
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",
- 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",
- 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",
- 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.
// Makes them show up as names instead of numbers in
// the debug output.
// remaining unsupported ciphersuites defined in RFC2246.
- add("SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5", 0x0006);
- add("SSL_RSA_WITH_IDEA_CBC_SHA", 0x0007);
- add("SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA", 0x000b);
- add("SSL_DH_DSS_WITH_DES_CBC_SHA", 0x000c);
- add("SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA", 0x000d);
- add("SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA", 0x000e);
- add("SSL_DH_RSA_WITH_DES_CBC_SHA", 0x000f);
- add("SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA", 0x0010);
+ add("SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5", 0x0006);
+ add("SSL_RSA_WITH_IDEA_CBC_SHA", 0x0007);
+ add("SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA", 0x000b);
+ add("SSL_DH_DSS_WITH_DES_CBC_SHA", 0x000c);
+ add("SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA", 0x000d);
+ add("SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA", 0x000e);
+ add("SSL_DH_RSA_WITH_DES_CBC_SHA", 0x000f);
+ add("SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA", 0x0010);
// SSL 3.0 Fortezza ciphersuites
- add("SSL_FORTEZZA_DMS_WITH_NULL_SHA", 0x001c);
- add("SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA", 0x001d);
+ add("SSL_FORTEZZA_DMS_WITH_NULL_SHA", 0x001c);
+ add("SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA", 0x001d);
// 1024/56 bit exportable ciphersuites from expired internet draft
- add("SSL_RSA_EXPORT1024_WITH_DES_CBC_SHA", 0x0062);
- add("SSL_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA", 0x0063);
- add("SSL_RSA_EXPORT1024_WITH_RC4_56_SHA", 0x0064);
- add("SSL_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA", 0x0065);
- add("SSL_DHE_DSS_WITH_RC4_128_SHA", 0x0066);
+ add("SSL_RSA_EXPORT1024_WITH_DES_CBC_SHA", 0x0062);
+ add("SSL_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA", 0x0063);
+ add("SSL_RSA_EXPORT1024_WITH_RC4_56_SHA", 0x0064);
+ add("SSL_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA", 0x0065);
+ add("SSL_DHE_DSS_WITH_RC4_128_SHA", 0x0066);
// Netscape old and new SSL 3.0 FIPS ciphersuites
// see http://www.mozilla.org/projects/security/pki/nss/ssl/fips-ssl-ciphersuites.html
- add("NETSCAPE_RSA_FIPS_WITH_3DES_EDE_CBC_SHA", 0xffe0);
- add("NETSCAPE_RSA_FIPS_WITH_DES_CBC_SHA", 0xffe1);
- add("SSL_RSA_FIPS_WITH_DES_CBC_SHA", 0xfefe);
- add("SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA", 0xfeff);
+ add("NETSCAPE_RSA_FIPS_WITH_3DES_EDE_CBC_SHA", 0xffe0);
+ add("NETSCAPE_RSA_FIPS_WITH_DES_CBC_SHA", 0xffe1);
+ add("SSL_RSA_FIPS_WITH_DES_CBC_SHA", 0xfefe);
+ add("SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA", 0xfeff);
// Unsupported Kerberos cipher suites from RFC 2712
- add("TLS_KRB5_WITH_IDEA_CBC_SHA", 0x0021);
- add("TLS_KRB5_WITH_IDEA_CBC_MD5", 0x0025);
- add("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA", 0x0027);
- add("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5", 0x002a);
+ add("TLS_KRB5_WITH_IDEA_CBC_SHA", 0x0021);
+ add("TLS_KRB5_WITH_IDEA_CBC_MD5", 0x0025);
+ add("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA", 0x0027);
+ 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
--- a/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java Fri Oct 29 12:35:07 2010 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java Sat Oct 30 18:39:17 2010 +0800
@@ -345,9 +345,10 @@
// check if the server selected protocol version is OK for us
ProtocolVersion mesgVersion = mesg.protocolVersion;
- if (enabledProtocols.contains(mesgVersion) == false) {
- throw new SSLHandshakeException
- ("Server chose unsupported or disabled protocol: " + mesgVersion);
+ if (!isNegotiable(mesgVersion)) {
+ throw new SSLHandshakeException(
+ "Server chose unsupported or disabled protocol: " +
+ mesgVersion);
}
// Set protocolVersion and propagate to SSLSocket and the
@@ -1022,7 +1023,7 @@
SessionId sessionId = SSLSessionImpl.nullSession.getSessionId();
// a list of cipher suites sent by the client
- CipherSuiteList cipherSuites = enabledCipherSuites;
+ CipherSuiteList cipherSuites = getActiveCipherSuites();
// set the max protocol version this client is supporting.
maxProtocolVersion = protocolVersion;
@@ -1057,8 +1058,7 @@
session = null;
}
- if ((session != null) &&
- (enabledProtocols.contains(sessionVersion) == false)) {
+ if ((session != null) && !isNegotiable(sessionVersion)) {
if (debug != null && Debug.isOn("session")) {
System.out.println("%% can't resume, protocol disabled");
}
@@ -1088,7 +1088,7 @@
*/
if (!enableNewSession) {
if (session == null) {
- throw new SSLException(
+ throw new SSLHandshakeException(
"Can't reuse existing SSL client session");
}
@@ -1105,7 +1105,7 @@
}
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
@@ -1131,7 +1131,7 @@
}
if (!negotiable) {
- throw new SSLException("No negotiable cipher suite");
+ throw new SSLHandshakeException("No negotiable cipher suite");
}
// create the ClientHello message
--- a/jdk/src/share/classes/sun/security/ssl/Debug.java Fri Oct 29 12:35:07 2010 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/Debug.java Sat Oct 30 18:39:17 2010 +0800
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
import java.io.PrintStream;
import java.security.AccessController;
+import java.util.Locale;
import sun.security.action.GetPropertyAction;
@@ -44,7 +45,7 @@
static {
args = java.security.AccessController.doPrivileged(
new GetPropertyAction("javax.net.debug", ""));
- args = args.toLowerCase();
+ args = args.toLowerCase(Locale.ENGLISH);
if (args.equals("help")) {
Help();
}
@@ -114,7 +115,7 @@
return false;
} else {
int n = 0;
- option = option.toLowerCase();
+ option = option.toLowerCase(Locale.ENGLISH);
if (args.indexOf("all") != -1) {
return true;
--- a/jdk/src/share/classes/sun/security/ssl/HandshakeMessage.java Fri Oct 29 12:35:07 2010 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/HandshakeMessage.java Sat Oct 30 18:39:17 2010 +0800
@@ -1167,8 +1167,13 @@
s.println();
s.println("Cert Authorities:");
- for (int i = 0; i < authorities.length; i++)
- authorities[i].print(s);
+ if (authorities.length == 0) {
+ s.println("<Empty>");
+ } else {
+ for (int i = 0; i < authorities.length; i++) {
+ authorities[i].print(s);
+ }
+ }
}
}
}
--- a/jdk/src/share/classes/sun/security/ssl/Handshaker.java Fri Oct 29 12:35:07 2010 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/Handshaker.java Sat Oct 30 18:39:17 2010 +0800
@@ -71,11 +71,31 @@
byte[] clientVerifyData;
byte[] serverVerifyData;
- // is it an initial negotiation or a renegotiation?
+ // Is it an initial negotiation or a renegotiation?
boolean isInitialHandshake;
- // list of enabled protocols
- ProtocolList enabledProtocols;
+ // List of enabled protocols
+ 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;
@@ -94,9 +114,6 @@
// in reset state after use.
private MessageDigest md5Tmp, shaTmp;
- // list of enabled CipherSuites
- CipherSuiteList enabledCipherSuites;
-
// current CipherSuite. Never null, initially SSL_NULL_WITH_NULL_NULL
CipherSuite cipherSuite;
@@ -233,7 +250,7 @@
// client's cert verify, those constants are in a convenient
// order to drastically simplify state machine checking.
//
- state = -1;
+ state = -2; // initialized but not activated
}
/*
@@ -345,26 +362,69 @@
void setVersion(ProtocolVersion protocolVersion) {
this.protocolVersion = protocolVersion;
setVersionSE(protocolVersion);
+
output.r.setVersion(protocolVersion);
}
/**
* Set the enabled protocols. Called from the constructor or
- * SSLSocketImpl.setEnabledProtocols() (if the handshake is not yet
- * in progress).
+ * SSLSocketImpl/SSLEngineImpl.setEnabledProtocols() (if the
+ * handshake is not yet in progress).
*/
void setEnabledProtocols(ProtocolList enabledProtocols) {
+ activeCipherSuites = null;
+ activeProtocols = null;
+
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
// is negotiated in the Hello exchange. This affects the record
- // version we sent with the ClientHello. Using max() as the record
- // version is not really correct but some implementations fail to
- // correctly negotiate TLS otherwise.
- protocolVersion = enabledProtocols.max;
+ // version we sent with the ClientHello.
+ if (!isInitialHandshake) {
+ protocolVersion = activeProtocolVersion;
+ } else {
+ protocolVersion = activeProtocols.max;
+ }
- ProtocolVersion helloVersion = enabledProtocols.helloVersion;
+ if (helloVersion == null || helloVersion.v == ProtocolVersion.NONE.v) {
+ helloVersion = activeProtocols.helloVersion;
+ }
input = new HandshakeInStream(handshakeHash);
@@ -372,12 +432,16 @@
output = new HandshakeOutStream(protocolVersion, helloVersion,
handshakeHash, conn);
conn.getAppInputStream().r.setHelloVersion(helloVersion);
+ conn.getAppOutputStream().r.setHelloVersion(helloVersion);
} else {
output = new HandshakeOutStream(protocolVersion, helloVersion,
handshakeHash, engine);
+ engine.inputRecord.setHelloVersion(helloVersion);
engine.outputRecord.setHelloVersion(helloVersion);
}
+ // move state to activated
+ state = -1;
}
/**
@@ -392,20 +456,127 @@
/**
* 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.
*/
boolean isNegotiable(CipherSuite s) {
- return enabledCipherSuites.contains(s) && s.isNegotiable();
+ if (activeCipherSuites == null) {
+ activeCipherSuites = getActiveCipherSuites();
+ }
+
+ return activeCipherSuites.contains(s) && s.isNegotiable();
+ }
+
+ /**
+ * 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);
}
/**
- * As long as handshaking has not started, we can
+ * 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.
*
* Callers should do their own checking if handshaking
- * has started.
+ * has activated.
*/
void setEnableSessionCreation(boolean newSessions) {
enableNewSession = newSessions;
@@ -419,12 +590,12 @@
CipherBox box;
if (isClient) {
box = cipher.newCipher(protocolVersion, svrWriteKey, svrWriteIV,
- false);
+ sslContext.getSecureRandom(), false);
svrWriteKey = null;
svrWriteIV = null;
} else {
box = cipher.newCipher(protocolVersion, clntWriteKey, clntWriteIV,
- false);
+ sslContext.getSecureRandom(), false);
clntWriteKey = null;
clntWriteIV = null;
}
@@ -439,12 +610,12 @@
CipherBox box;
if (isClient) {
box = cipher.newCipher(protocolVersion, clntWriteKey, clntWriteIV,
- true);
+ sslContext.getSecureRandom(), true);
clntWriteKey = null;
clntWriteIV = null;
} else {
box = cipher.newCipher(protocolVersion, svrWriteKey, svrWriteIV,
- true);
+ sslContext.getSecureRandom(), true);
svrWriteKey = null;
svrWriteIV = null;
}
@@ -614,13 +785,20 @@
/**
+ * 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.
- * 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() {
- return state >= 0;
+ return state >= 0; // 0: HandshakeMessage.ht_hello_request
+ // 1: HandshakeMessage.ht_hello_request
}
@@ -633,6 +811,7 @@
if (state >= 0) {
return;
}
+
HandshakeMessage m = getKickstartMessage();
if (debug != null && Debug.isOn("handshake")) {
@@ -746,6 +925,7 @@
*/
private SecretKey calculateMasterSecret(SecretKey preMasterSecret,
ProtocolVersion requestedVersion) {
+
TlsMasterSecretParameterSpec spec = new TlsMasterSecretParameterSpec
(preMasterSecret, protocolVersion.major, protocolVersion.minor,
clnt_random.random_bytes, svr_random.random_bytes);
@@ -773,22 +953,37 @@
if (!preMasterSecret.getAlgorithm().equals("TlsRsaPremasterSecret")) {
throw new ProviderException(e);
}
+
if (debug != null && Debug.isOn("handshake")) {
System.out.println("RSA master secret generation error:");
e.printStackTrace(System.out);
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
return calculateMasterSecret(preMasterSecret, null);
}
- // if no version check requested (client side handshake),
- // or version information is not available (not an RSA premaster secret),
+ // if no version check requested (client side handshake), or version
+ // information is not available (not an RSA premaster secret),
// return master secret immediately.
- if ((requestedVersion == null) || !(masterSecret instanceof TlsMasterSecret)) {
+ if ((requestedVersion == null) ||
+ !(masterSecret instanceof TlsMasterSecret)) {
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;
int major = tlsKey.getMajorVersion();
int minor = tlsKey.getMinorVersion();
@@ -800,13 +995,21 @@
// the specification says that it must be the maximum version supported
// by the client from its ClientHello message. However, many
// implementations send the negotiated version, so accept both
- // NOTE that we may be comparing two unsupported version numbers in
- // the second case, which is why we cannot use object reference
- // equality in this special case
- ProtocolVersion premasterVersion = ProtocolVersion.valueOf(major, minor);
- boolean versionMismatch = (premasterVersion != protocolVersion) &&
- (premasterVersion.v != requestedVersion.v);
+ // for SSL v3.0 and TLS v1.0.
+ // NOTE that we may be comparing two unsupported version numbers, which
+ // is why we cannot use object reference equality in this special case.
+ ProtocolVersion premasterVersion =
+ ProtocolVersion.valueOf(major, minor);
+ 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) {
// check passed, return key
@@ -823,7 +1026,9 @@
+ premasterVersion);
System.out.println("Generating new random premaster secret");
}
- preMasterSecret = RSAClientKeyExchange.generateDummySecret(protocolVersion);
+ preMasterSecret =
+ RSAClientKeyExchange.generateDummySecret(requestedVersion);
+
// recursive call with new premaster secret
return calculateMasterSecret(preMasterSecret, null);
}
@@ -849,8 +1054,6 @@
int hashSize = cipherSuite.macAlg.size;
boolean is_exportable = cipherSuite.exportable;
BulkCipher cipher = cipherSuite.cipher;
- int keySize = cipher.keySize;
- int ivSize = cipher.ivSize;
int expandedKeySize = is_exportable ? cipher.expandedKeySize : 0;
TlsKeyMaterialParameterSpec spec = new TlsKeyMaterialParameterSpec
@@ -867,6 +1070,8 @@
clntWriteKey = keySpec.getClientCipherKey();
svrWriteKey = keySpec.getServerCipherKey();
+ // Return null if IVs are not supposed to be generated.
+ // e.g. TLS 1.1+.
clntWriteIV = keySpec.getClientIv();
svrWriteIV = keySpec.getServerIv();
@@ -914,7 +1119,12 @@
System.out.println("Server write IV:");
printHex(dump, svrWriteIV.getIV());
} else {
- System.out.println("... no IV used for this cipher");
+ if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
+ System.out.println(
+ "... no IV derived for this protocol");
+ } else {
+ System.out.println("... no IV used for this cipher");
+ }
}
System.out.flush();
}
--- a/jdk/src/share/classes/sun/security/ssl/KerberosClientKeyExchange.java Fri Oct 29 12:35:07 2010 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/KerberosClientKeyExchange.java Sat Oct 30 18:39:17 2010 +0800
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -69,6 +69,7 @@
}
public KerberosClientKeyExchange() {
+ // empty
}
public KerberosClientKeyExchange(String serverName, boolean isLoopback,
@@ -93,14 +94,17 @@
}
}
+ @Override
int messageType() {
return ht_client_key_exchange;
}
+ @Override
public int messageLength() {
return impl.messageLength();
}
+ @Override
public void send(HandshakeOutStream s) throws IOException {
impl.send(s);
}
--- a/jdk/src/share/classes/sun/security/ssl/MAC.java Fri Oct 29 12:35:07 2010 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/MAC.java Sat Oct 30 18:39:17 2010 +0800
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -155,6 +155,42 @@
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
// it is a 64-bit number stored in big-endian format
private void incrementSequenceNumber() {
--- a/jdk/src/share/classes/sun/security/ssl/ProtocolList.java Fri Oct 29 12:35:07 2010 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/ProtocolList.java Sat Oct 30 18:39:17 2010 +0800
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -38,8 +38,12 @@
final class ProtocolList {
private static final ProtocolList SUPPORTED;
+ private static final ProtocolList CLIENT_DEFAULT;
+ private static final ProtocolList SERVER_DEFAULT;
- private final Collection<ProtocolVersion> protocols;
+ // the sorted protocol version list
+ private final ArrayList<ProtocolVersion> protocols;
+
private String[] protocolNames;
// the minimum and maximum ProtocolVersions in this list
@@ -49,30 +53,45 @@
final ProtocolVersion helloVersion;
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) {
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++ ) {
ProtocolVersion version = ProtocolVersion.valueOf(names[i]);
- if (protocols.contains(version) == false) {
- protocols.add(version);
+ if (versions.contains(version) == false) {
+ versions.add(version);
}
}
- if ((protocols.size() == 1)
- && protocols.contains(ProtocolVersion.SSL20Hello)) {
- 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;
- }
+
+ return versions;
}
/**
@@ -88,6 +107,37 @@
}
/**
+ * 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.
*/
synchronized String[] toStringArray() {
@@ -106,11 +156,18 @@
}
/**
- * Return the list of default enabled protocols. Currently, this
- * is identical to the supported protocols.
+ * Return the list of default enabled protocols.
*/
- static ProtocolList getDefault() {
- return SUPPORTED;
+ static ProtocolList getDefault(boolean isServer) {
+ 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 @@
static {
if (SunJSSE.isFIPS()) {
SUPPORTED = new ProtocolList(new String[] {
+ ProtocolVersion.TLS10.name,
+ ProtocolVersion.TLS11.name
+ });
+
+ SERVER_DEFAULT = SUPPORTED;
+ CLIENT_DEFAULT = new ProtocolList(new String[] {
ProtocolVersion.TLS10.name
});
} else {
@@ -130,6 +193,13 @@
ProtocolVersion.SSL20Hello.name,
ProtocolVersion.SSL30.name,
ProtocolVersion.TLS10.name,
+ ProtocolVersion.TLS11.name
+ });
+
+ SERVER_DEFAULT = SUPPORTED;
+ CLIENT_DEFAULT = new ProtocolList(new String[] {
+ ProtocolVersion.SSL30.name,
+ ProtocolVersion.TLS10.name
});
}
}
--- a/jdk/src/share/classes/sun/security/ssl/ProtocolVersion.java Fri Oct 29 12:35:07 2010 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/ProtocolVersion.java Sat Oct 30 18:39:17 2010 +0800
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -45,9 +45,12 @@
* @author Andreas Sterbenz
* @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");
// If enabled, send/ accept SSLv2 hello messages
@@ -61,22 +64,24 @@
final static ProtocolVersion TLS10 = new ProtocolVersion(0x0301, "TLSv1");
// TLS 1.1
- // not supported yet, but added for better readability of the debug trace
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();
// minimum version we implement (SSL 3.0)
final static ProtocolVersion MIN = FIPS ? TLS10 : SSL30;
- // maximum version we implement (TLS 1.0)
- final static ProtocolVersion MAX = TLS10;
+ // maximum version we implement (TLS 1.1)
+ final static ProtocolVersion MAX = TLS11;
// ProtocolVersion to use by default (TLS 1.0)
final static ProtocolVersion DEFAULT = TLS10;
// 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
// messages, i.e. 0x0301 for TLS 1.0
@@ -104,6 +109,8 @@
return TLS10;
} else if (v == TLS11.v) {
return TLS11;
+ } else if (v == TLS12.v) {
+ return TLS12;
} else if (v == SSL20Hello.v) {
return SSL20Hello;
} else {
@@ -134,18 +141,20 @@
if (name == null) {
throw new IllegalArgumentException("Protocol cannot be null");
}
- if (FIPS) {
- if (name.equals(TLS10.name)) {
- return TLS10;
- } else {
- throw new IllegalArgumentException
- ("Only TLS 1.0 allowed in FIPS mode");
- }
+
+ if (FIPS && (name.equals(SSL30.name) || name.equals(SSL20Hello.name))) {
+ throw new IllegalArgumentException
+ ("Only TLS 1.0 or later allowed in FIPS mode");
}
+
if (name.equals(SSL30.name)) {
return SSL30;
} else if (name.equals(TLS10.name)) {
return TLS10;
+ } else if (name.equals(TLS11.name)) {
+ return TLS11;
+ } else if (name.equals(TLS12.name)) {
+ return TLS12;
} else if (name.equals(SSL20Hello.name)) {
return SSL20Hello;
} else {
@@ -157,4 +166,10 @@
return name;
}
+ /**
+ * Compares this object with the specified object for order.
+ */
+ public int compareTo(ProtocolVersion protocolVersion) {
+ return this.v - protocolVersion.v;
+ }
}
--- a/jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java Fri Oct 29 12:35:07 2010 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java Sat Oct 30 18:39:17 2010 +0800
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -55,20 +55,17 @@
* requested in its client hello version). However, we (and other
* implementations) used to send the active negotiated version. The
* 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 =
"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 =
Debug.getBooleanProperty(PROP_NAME, false);
- int messageType() {
- return ht_client_key_exchange;
- }
-
/*
* The following field values were encrypted with the server's public
* key (or temp key from server key exchange msg) and are presented
@@ -78,14 +75,14 @@
SecretKey preMaster;
private byte[] encrypted; // same size as public modulus
-
/*
* Client randomly creates a pre-master secret and encrypts it
* 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
* 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 {
if (publicKey.getAlgorithm().equals("RSA") == false) {
throw new SSLKeyException("Public key not of type RSA");
@@ -94,7 +91,7 @@
int major, minor;
- if (rsaPreMasterSecretFix) {
+ if (rsaPreMasterSecretFix || maxVersion.v >= ProtocolVersion.TLS11.v) {
major = maxVersion.major;
minor = maxVersion.minor;
} else {
@@ -103,7 +100,8 @@
}
try {
- KeyGenerator kg = JsseJce.getKeyGenerator("SunTlsRsaPremasterSecret");
+ KeyGenerator kg =
+ JsseJce.getKeyGenerator("SunTlsRsaPremasterSecret");
kg.init(new TlsRsaPremasterSecretParameterSpec(major, minor));
preMaster = kg.generateKey();
@@ -120,14 +118,15 @@
* Server gets the PKCS #1 (block format 02) data, decrypts
* 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 {
if (privateKey.getAlgorithm().equals("RSA") == false) {
throw new SSLKeyException("Private key not of type RSA");
}
- this.protocolVersion = currentVersion;
if (currentVersion.v >= ProtocolVersion.TLS10.v) {
encrypted = input.getBytes16();
} else {
@@ -143,24 +142,101 @@
cipher.init(Cipher.UNWRAP_MODE, privateKey);
preMaster = (SecretKey)cipher.unwrap(encrypted,
"TlsRsaPremasterSecret", Cipher.SECRET_KEY);
+
+ // polish the premaster secret
+ preMaster = polishPreMasterSecretKey(currentVersion, maxVersion,
+ generator, preMaster, null);
} catch (Exception e) {
- /*
- * Bogus decrypted ClientKeyExchange? If so, conjure a
- * a random preMaster secret that will fail later during
- * Finished message processing. This is a countermeasure against
- * 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.
- */
- if (debug != null && Debug.isOn("handshake")) {
+ // polish the premaster secret
+ preMaster =
+ polishPreMasterSecretKey(currentVersion, maxVersion,
+ generator, null, e);
+ }
+ }
+
+ /**
+ * 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")) {
+ 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:");
- e.printStackTrace(System.out);
- System.out.println("Generating random secret");
+ failoverException.printStackTrace(System.out);
}
- preMaster = generateDummySecret(currentVersion);
+
+ System.out.println("Generating random secret");
}
+
+ return generateDummySecret(clientHelloVersion);
}
// generate a premaster secret with the specified version number
@@ -176,6 +252,12 @@
}
}
+ @Override
+ int messageType() {
+ return ht_client_key_exchange;
+ }
+
+ @Override
int messageLength() {
if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
return encrypted.length + 2;
@@ -184,6 +266,7 @@
}
}
+ @Override
void send(HandshakeOutStream s) throws IOException {
if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
s.putBytes16(encrypted);
@@ -192,7 +275,9 @@
}
}
+ @Override
void print(PrintStream s) throws IOException {
- s.println("*** ClientKeyExchange, RSA PreMasterSecret, " + protocolVersion);
+ s.println("*** ClientKeyExchange, RSA PreMasterSecret, " +
+ protocolVersion);
}
}
--- a/jdk/src/share/classes/sun/security/ssl/Record.java Fri Oct 29 12:35:07 2010 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/Record.java Sat Oct 30 18:39:17 2010 +0800
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -47,11 +47,12 @@
static final byte ct_handshake = 22;
static final byte ct_application_data = 23;
- static final int headerSize = 5; // SSLv3 record header
- static final int maxExpansion = 1024; // for bad compression
- static final int trailerSize = 20; // SHA1 hash size
- static final int maxDataSize = 16384; // 2^14 bytes of data
- static final int maxPadding = 256; // block cipher padding
+ static final int headerSize = 5; // SSLv3 record header
+ static final int maxExpansion = 1024; // for bad compression
+ static final int trailerSize = 20; // SHA1 hash size
+ static final int maxDataSize = 16384; // 2^14 bytes of data
+ 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,
@@ -59,8 +60,9 @@
* Some compression algorithms have rare cases where they expand the data.
* As we don't support compression at this time, leave that out.
*/
- static final int maxRecordSize =
+ static final int maxRecordSize =
headerSize // header
+ + maxIVLength // iv
+ maxDataSize // data
+ maxPadding // padding
+ trailerSize; // MAC
@@ -74,7 +76,7 @@
* The maximum large record size is defined as maxRecordSize plus 2^14,
* this is the amount OpenSSL is using.
*/
- static final int maxLargeRecordSize =
+ static final int maxLargeRecordSize =
maxRecordSize // Max size with a conforming implemenation
+ maxDataSize; // extra 2^14 bytes for large data packets.
@@ -84,7 +86,11 @@
* They only contain 2 and 1 bytes of data, respectively.
* Allocate a smaller array.
*/
- static final int maxAlertRecordSize =
- headerSize + 2 + maxPadding + trailerSize;
+ static final int maxAlertRecordSize =
+ headerSize // header
+ + maxIVLength // iv
+ + 2 // alert
+ + maxPadding // padding
+ + trailerSize; // MAC
}
--- a/jdk/src/share/classes/sun/security/ssl/SSLEngineImpl.java Fri Oct 29 12:35:07 2010 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/SSLEngineImpl.java Sat Oct 30 18:39:17 2010 +0800
@@ -240,12 +240,14 @@
* session is changed.
*/
private byte doClientAuth;
- private CipherSuiteList enabledCipherSuites;
private boolean enableSessionCreation = true;
EngineInputRecord inputRecord;
EngineOutputRecord outputRecord;
private AccessControlContext acc;
+ // The cipher suites enabled for use on this connection.
+ private CipherSuiteList enabledCipherSuites;
+
// hostname identification algorithm, the hostname identification is
// disabled by default.
private String identificationAlg = null;
@@ -255,11 +257,11 @@
private boolean roleIsServer;
/*
- * The protocols we support are SSL Version 3.0) and
- * TLS (version 3.1).
- * In addition we support a pseudo protocol called
- * SSLv2Hello which when set will result in an SSL v2 Hello
- * being sent with SSLv3 or TLSv1 version info.
+ * The protocol versions enabled for use on this connection.
+ *
+ * Note: we support a pseudo protocol called SSLv2Hello which when
+ * set will result in an SSL v2 Hello being sent with SSL (version 3.0)
+ * or TLS (version 3.1, 3.2, etc.) version info.
*/
private ProtocolList enabledProtocols;
@@ -368,7 +370,7 @@
serverVerifyData = new byte[0];
enabledCipherSuites = CipherSuiteList.getDefault();
- enabledProtocols = ProtocolList.getDefault();
+ enabledProtocols = ProtocolList.getDefault(roleIsServer);
wrapLock = new Object();
unwrapLock = new Object();
@@ -405,8 +407,8 @@
* . if the engine is already closed, throw an Exception (internal error)
*
* . otherwise (cs_START or cs_DATA), create the appropriate handshaker
- * object, initialize it, and advance the connection state (to
- * cs_HANDSHAKE or cs_RENEGOTIATE, respectively).
+ * object and advance the connection state (to cs_HANDSHAKE or
+ * cs_RENEGOTIATE, respectively).
*
* This method is called right after a new engine is created, when
* starting renegotiation, or when changing client/server mode of the
@@ -454,12 +456,8 @@
protocolVersion, connectionState == cs_HANDSHAKE,
secureRenegotiation, clientVerifyData, serverVerifyData);
}
- handshaker.enabledCipherSuites = enabledCipherSuites;
+ handshaker.setEnabledCipherSuites(enabledCipherSuites);
handshaker.setEnableSessionCreation(enableSessionCreation);
- if (connectionState == cs_RENEGOTIATE) {
- // don't use SSLv2Hello when renegotiating
- handshaker.output.r.setHelloVersion(protocolVersion);
- }
}
/*
@@ -686,7 +684,15 @@
// to its HandshakeOutStream, which calls back into
// 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) {
// send client hello
handshaker.kickstart();
@@ -696,6 +702,7 @@
} else {
// we want to renegotiate, send hello request
handshaker.kickstart();
+
// hello request is not included in the handshake
// hashes, reset them
handshaker.handshakeHash.reset();
@@ -982,6 +989,15 @@
* in it.
*/
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
@@ -1081,6 +1097,26 @@
}
break;
} // 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)
}
@@ -1229,7 +1265,29 @@
EngineArgs ea) throws IOException {
// 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,6 +1296,21 @@
void writeRecord(EngineOutputRecord eor) throws IOException {
// eventually compress as well.
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());
+ }
}
//
@@ -1245,6 +1318,67 @@
//
/**
+ * 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
* on this <code>SSLEngine</code>.
*/
@@ -1594,10 +1728,18 @@
* Emit alerts. Caller must have synchronized with "this".
*/
private void sendAlert(byte level, byte description) {
+ // the connectionState cannot be cs_START
if (connectionState >= cs_CLOSED) {
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);
r.setVersion(protocolVersion);
@@ -1647,7 +1789,7 @@
synchronized public void setEnableSessionCreation(boolean flag) {
enableSessionCreation = flag;
- if ((handshaker != null) && !handshaker.started()) {
+ if ((handshaker != null) && !handshaker.activated()) {
handshaker.setEnableSessionCreation(enableSessionCreation);
}
}
@@ -1675,7 +1817,7 @@
if ((handshaker != null) &&
(handshaker instanceof ServerHandshaker) &&
- !handshaker.started()) {
+ !handshaker.activated()) {
((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
}
}
@@ -1698,7 +1840,7 @@
if ((handshaker != null) &&
(handshaker instanceof ServerHandshaker) &&
- !handshaker.started()) {
+ !handshaker.activated()) {
((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
}
}
@@ -1717,6 +1859,16 @@
switch (connectionState) {
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;
serverModeSet = true;
break;
@@ -1730,7 +1882,17 @@
* have the streams.
*/
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;
connectionState = cs_START;
initHandshaker();
@@ -1786,8 +1948,8 @@
*/
synchronized public void setEnabledCipherSuites(String[] suites) {
enabledCipherSuites = new CipherSuiteList(suites);
- if ((handshaker != null) && !handshaker.started()) {
- handshaker.enabledCipherSuites = enabledCipherSuites;
+ if ((handshaker != null) && !handshaker.activated()) {
+ handshaker.setEnabledCipherSuites(enabledCipherSuites);
}
}
@@ -1826,7 +1988,7 @@
*/
synchronized public void setEnabledProtocols(String[] protocols) {
enabledProtocols = new ProtocolList(protocols);
- if ((handshaker != null) && !handshaker.started()) {
+ if ((handshaker != null) && !handshaker.activated()) {
handshaker.setEnabledProtocols(enabledProtocols);
}
}
--- a/jdk/src/share/classes/sun/security/ssl/SSLServerSocketImpl.java Fri Oct 29 12:35:07 2010 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/SSLServerSocketImpl.java Sat Oct 30 18:39:17 2010 +0800
@@ -145,7 +145,7 @@
}
sslContext = context;
enabledCipherSuites = CipherSuiteList.getDefault();
- enabledProtocols = ProtocolList.getDefault();
+ enabledProtocols = ProtocolList.getDefault(true);
}
/**
@@ -238,6 +238,16 @@
* rejoining the already-negotiated SSL connection.
*/
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;
}
@@ -262,15 +272,12 @@
return enableSessionCreation;
}
-
/**
* Accept a new SSL connection. This server identifies itself with
* information provided in the authentication context which was
* presented during construction.
*/
public Socket accept() throws IOException {
- checkEnabledSuites();
-
SSLSocketImpl s = new SSLSocketImpl(sslContext, useServerMode,
enabledCipherSuites, doClientAuth, enableSessionCreation,
enabledProtocols);
@@ -280,56 +287,6 @@
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.
*/
--- a/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java Fri Oct 29 12:35:07 2010 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java Sat Oct 30 18:39:17 2010 +0800
@@ -194,12 +194,14 @@
*/
private byte doClientAuth;
private boolean roleIsServer;
- private CipherSuiteList enabledCipherSuites;
private boolean enableSessionCreation = true;
private String host;
private boolean autoClose = true;
private AccessControlContext acc;
+ // The cipher suites enabled for use on this connection.
+ private CipherSuiteList enabledCipherSuites;
+
// hostname identification algorithm, the hostname identification is
// disabled by default.
private String identificationAlg = null;
@@ -341,11 +343,11 @@
private AppOutputStream output;
/*
- * The protocols we support are SSL Version 3.0) and
- * TLS (version 3.1).
- * In addition we support a pseudo protocol called
- * SSLv2Hello which when set will result in an SSL v2 Hello
- * being sent with SSLv3 or TLSv1 version info.
+ * The protocol versions enabled for use on this connection.
+ *
+ * Note: we support a pseudo protocol called SSLv2Hello which when
+ * set will result in an SSL v2 Hello being sent with SSL (version 3.0)
+ * or TLS (version 3.1, 3.2, etc.) version info.
*/
private ProtocolList enabledProtocols;
@@ -541,7 +543,7 @@
serverVerifyData = new byte[0];
enabledCipherSuites = CipherSuiteList.getDefault();
- enabledProtocols = ProtocolList.getDefault();
+ enabledProtocols = ProtocolList.getDefault(roleIsServer);
inrec = null;
// save the acc
@@ -764,6 +766,21 @@
r.addMAC(writeMAC);
r.encrypt(writeCipher);
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 @@
}
}
+
// if (!r.decompress(c))
// fatal(Alerts.alert_decompression_failure,
// "decompression failure");
@@ -905,6 +923,15 @@
* in it.
*/
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
@@ -949,9 +976,8 @@
if (needAppData || connectionState != cs_DATA) {
continue;
- } else {
- return;
}
+ break;
case Record.ct_application_data:
// Pass this right back up to the application.
@@ -971,7 +997,7 @@
}
r.setAppDataValid(true);
- return;
+ break;
case Record.ct_alert:
recvAlert(r);
@@ -1010,6 +1036,23 @@
}
continue;
} // 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)
}
@@ -1021,6 +1064,61 @@
} // 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
//
@@ -1033,28 +1131,10 @@
}
/**
- * Initialize and get the server handshaker. Used by SSLServerSocketImpl
- * for the ciphersuite availability test *only*.
+ * Return the AppOutputStream. For use by Handshaker only.
*/
- ServerHandshaker getServerHandshaker() throws SSLException {
- initHandshaker();
-
- // 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;
+ AppOutputStream getAppOutputStream() {
+ return output;
}
/**
@@ -1066,8 +1146,8 @@
* . if the socket is already closed, throw an Exception (internal error)
*
* . otherwise (cs_START or cs_DATA), create the appropriate handshaker
- * object, initialize it, and advance the connection state (to
- * cs_HANDSHAKE or cs_RENEGOTIATE, respectively).
+ * object, and advance the connection state (to cs_HANDSHAKE or
+ * cs_RENEGOTIATE, respectively).
*
* This method is called right after a new socket is created, when
* starting renegotiation, or when changing client/ server mode of the
@@ -1115,12 +1195,8 @@
protocolVersion, connectionState == cs_HANDSHAKE,
secureRenegotiation, clientVerifyData, serverVerifyData);
}
- handshaker.enabledCipherSuites = enabledCipherSuites;
+ handshaker.setEnabledCipherSuites(enabledCipherSuites);
handshaker.setEnableSessionCreation(enableSessionCreation);
- if (connectionState == cs_RENEGOTIATE) {
- // don't use SSLv2Hello when renegotiating
- handshaker.output.r.setHelloVersion(protocolVersion);
- }
}
/**
@@ -1135,6 +1211,8 @@
// one thread performs the handshake
synchronized (handshakeLock) {
if (getConnectionState() == cs_HANDSHAKE) {
+ kickstartHandshake();
+
/*
* All initial handshaking goes through this
* InputRecord until we have a valid SSL connection.
@@ -1157,7 +1235,6 @@
inrec.enableFormatChecks();
}
- kickstartHandshake();
readRecord(inrec, false);
inrec = null;
}
@@ -1211,6 +1288,7 @@
* on servers when renegotiating).
*/
private synchronized void kickstartHandshake() throws IOException {
+
switch (connectionState) {
case cs_HANDSHAKE:
@@ -1257,7 +1335,15 @@
// to its HandshakeOutStream, which calls back into
// 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) {
// send client hello
handshaker.kickstart();
@@ -1752,10 +1838,18 @@
* Emit alerts. Caller must have synchronized with "this".
*/
private void sendAlert(byte level, byte description) {
+ // the connectionState cannot be cs_START
if (connectionState >= cs_SENT_CLOSE) {
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);
r.setVersion(protocolVersion);
@@ -1962,7 +2056,7 @@
synchronized public void setEnableSessionCreation(boolean flag) {
enableSessionCreation = flag;
- if ((handshaker != null) && !handshaker.started()) {
+ if ((handshaker != null) && !handshaker.activated()) {
handshaker.setEnableSessionCreation(enableSessionCreation);
}
}
@@ -1990,7 +2084,7 @@
if ((handshaker != null) &&
(handshaker instanceof ServerHandshaker) &&
- !handshaker.started()) {
+ !handshaker.activated()) {
((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
}
}
@@ -2013,7 +2107,7 @@
if ((handshaker != null) &&
(handshaker instanceof ServerHandshaker) &&
- !handshaker.started()) {
+ !handshaker.activated()) {
((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
}
}
@@ -2032,6 +2126,15 @@
switch (connectionState) {
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;
break;
@@ -2044,7 +2147,16 @@
* have the streams.
*/
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;
connectionState = cs_START;
initHandshaker();
@@ -2095,8 +2207,8 @@
*/
synchronized public void setEnabledCipherSuites(String[] suites) {
enabledCipherSuites = new CipherSuiteList(suites);
- if ((handshaker != null) && !handshaker.started()) {
- handshaker.enabledCipherSuites = enabledCipherSuites;
+ if ((handshaker != null) && !handshaker.activated()) {
+ handshaker.setEnabledCipherSuites(enabledCipherSuites);
}
}
@@ -2135,7 +2247,7 @@
*/
synchronized public void setEnabledProtocols(String[] protocols) {
enabledProtocols = new ProtocolList(protocols);
- if ((handshaker != null) && !handshaker.started()) {
+ if ((handshaker != null) && !handshaker.activated()) {
handshaker.setEnabledProtocols(enabledProtocols);
}
}
--- a/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java Fri Oct 29 12:35:07 2010 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java Sat Oct 30 18:39:17 2010 +0800
@@ -185,8 +185,10 @@
* temporary one used for non-export or signing-only
* certificates/keys.
*/
- RSAClientKeyExchange pms = new RSAClientKeyExchange
- (protocolVersion, input, message_len, privateKey);
+ RSAClientKeyExchange pms = new RSAClientKeyExchange(
+ protocolVersion, clientRequestedVersion,
+ sslContext.getSecureRandom(), input,
+ message_len, privateKey);
preMasterSecret = this.clientKeyExchange(pms);
break;
case K_KRB5:
@@ -408,20 +410,14 @@
clientRequestedVersion = mesg.protocolVersion;
- // check if clientVersion is recent enough for us
- if (clientRequestedVersion.v < enabledProtocols.min.v) {
+ // select a proper protocol version.
+ ProtocolVersion selectedVersion =
+ selectProtocolVersion(clientRequestedVersion);
+ if (selectedVersion == null ||
+ selectedVersion.v == ProtocolVersion.SSL20Hello.v) {
fatalSE(Alerts.alert_handshake_failure,
"Client requested protocol " + clientRequestedVersion +
- " 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;
+ " not enabled or not supported");
}
setVersion(selectedVersion);
@@ -813,8 +809,7 @@
* method should only be called if you really want to use the
* CipherSuite.
*
- * This method is called from chooseCipherSuite() in this class
- * and SSLServerSocketImpl.checkEnabledSuites() (as a sanity check).
+ * This method is called from chooseCipherSuite() in this class.
*/
boolean trySetCipherSuite(CipherSuite suite) {
/*
@@ -831,6 +826,11 @@
return false;
}
+ // TLSv1.1 must not negotiate the exportable weak cipher suites.
+ if (protocolVersion.v >= suite.obsoleted) {
+ return false;
+ }
+
KeyExchange keyExchange = suite.keyExchange;
// null out any existing references
--- a/jdk/src/share/classes/sun/security/ssl/SunJSSE.java Fri Oct 29 12:35:07 2010 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/SunJSSE.java Sat Oct 30 18:39:17 2010 +0800
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -38,7 +38,7 @@
*
* SunJSSE now supports an experimental FIPS compliant mode when used with an
* 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
* . perform all crypto in the FIPS crypto provider
*
@@ -211,6 +211,8 @@
"sun.security.ssl.SSLContextImpl");
put("SSLContext.TLSv1",
"sun.security.ssl.SSLContextImpl");
+ put("SSLContext.TLSv1.1",
+ "sun.security.ssl.SSLContextImpl");
put("SSLContext.Default",
"sun.security.ssl.DefaultSSLContextImpl");
--- a/jdk/src/share/classes/sun/security/ssl/krb5/KerberosClientKeyExchangeImpl.java Fri Oct 29 12:35:07 2010 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/krb5/KerberosClientKeyExchangeImpl.java Sat Oct 30 18:39:17 2010 +0800
@@ -244,7 +244,7 @@
clientVersion, rand, input, sessionKey);
} else {
// Generate bogus premaster secret
- preMaster = new KerberosPreMasterSecret(protocolVersion, rand);
+ preMaster = new KerberosPreMasterSecret(clientVersion, rand);
}
}
--- a/jdk/src/share/classes/sun/security/ssl/krb5/KerberosPreMasterSecret.java Fri Oct 29 12:35:07 2010 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/krb5/KerberosPreMasterSecret.java Sat Oct 30 18:39:17 2010 +0800
@@ -176,13 +176,21 @@
// check if the premaster secret version is ok
// the specification says that it must be the maximum version supported
// 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
// the second case, which is why we cannot use object references
// equality in this special case
- boolean versionMismatch = (protocolVersion != currentVersion) &&
- (protocolVersion.v != clientVersion.v);
+ boolean versionMismatch = (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
@@ -203,8 +211,14 @@
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;
}
}
--- a/jdk/test/sun/security/pkcs11/fips/CipherTest.java Fri Oct 29 12:35:07 2010 +0200
+++ b/jdk/test/sun/security/pkcs11/fips/CipherTest.java Sat Oct 30 18:39:17 2010 +0800
@@ -119,6 +119,13 @@
return false;
}
+ // ignore exportable cipher suite for TLSv1.1
+ if (protocol.equals("TLSv1.1")) {
+ if(cipherSuite.indexOf("_EXPORT_") != -1) {
+ return false;
+ }
+ }
+
return true;
}
@@ -149,18 +156,14 @@
cipherSuites.length * protocols.length * clientAuths.length);
for (int i = 0; i < cipherSuites.length; 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++) {
String protocol = protocols[j];
- if (protocol.equals("SSLv2Hello")) {
+
+ if (!peerFactory.isSupported(cipherSuite, protocol)) {
continue;
}
+
for (int k = 0; k < clientAuths.length; k++) {
String clientAuth = clientAuths[k];
if ((clientAuth != null) &&
@@ -293,11 +296,12 @@
return ks;
}
- public static void main(PeerFactory peerFactory, KeyStore keyStore, String[] args)
- throws Exception {
+ public static void main(PeerFactory peerFactory, KeyStore keyStore,
+ String[] args) throws Exception {
+
long time = System.currentTimeMillis();
String relPath;
- if ((args.length > 0) && args[0].equals("sh")) {
+ if ((args != null) && (args.length > 0) && args[0].equals("sh")) {
relPath = pathToStoresSH;
} else {
relPath = pathToStores;
@@ -345,7 +349,30 @@
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;
}
}
--- a/jdk/test/sun/security/pkcs11/sslecc/CipherTest.java Fri Oct 29 12:35:07 2010 +0200
+++ b/jdk/test/sun/security/pkcs11/sslecc/CipherTest.java Sat Oct 30 18:39:17 2010 +0800
@@ -119,6 +119,13 @@
return false;
}
+ // ignore exportable cipher suite for TLSv1.1
+ if (protocol.equals("TLSv1.1")) {
+ if(cipherSuite.indexOf("_EXPORT_") != -1) {
+ return false;
+ }
+ }
+
return true;
}
@@ -148,18 +155,14 @@
cipherSuites.length * protocols.length * clientAuths.length);
for (int i = 0; i < cipherSuites.length; 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++) {
String protocol = protocols[j];
- if (protocol.equals("SSLv2Hello")) {
+
+ if (!peerFactory.isSupported(cipherSuite, protocol)) {
continue;
}
+
for (int k = 0; k < clientAuths.length; k++) {
String clientAuth = clientAuths[k];
if ((clientAuth != null) &&
@@ -275,7 +278,6 @@
// for some reason, ${test.src} has a different value when the
// test is called from the script and when it is called directly...
-// static String pathToStores = "../../etc";
static String pathToStores = ".";
static String pathToStoresSH = ".";
static String keyStoreFile = "keystore";
@@ -336,7 +338,30 @@
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;
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/ssl/javax/net/ssl/TLSv11/EmptyCertificateAuthorities.java Sat Oct 30 18:39:17 2010 +0800
@@ -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;
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/ssl/javax/net/ssl/TLSv11/ExportableBlockCipher.java Sat Oct 30 18:39:17 2010 +0800
@@ -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;
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/ssl/javax/net/ssl/TLSv11/ExportableStreamCipher.java Sat Oct 30 18:39:17 2010 +0800
@@ -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;
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/ssl/javax/net/ssl/TLSv11/GenericBlockCipher.java Sat Oct 30 18:39:17 2010 +0800
@@ -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;
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/ssl/javax/net/ssl/TLSv11/GenericStreamCipher.java Sat Oct 30 18:39:17 2010 +0800
@@ -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;
+ }
+ }
+ }
+}
--- a/jdk/test/sun/security/ssl/sanity/interop/CipherTest.java Fri Oct 29 12:35:07 2010 +0200
+++ b/jdk/test/sun/security/ssl/sanity/interop/CipherTest.java Sat Oct 30 18:39:17 2010 +0800
@@ -120,6 +120,13 @@
return false;
}
+ // ignore exportable cipher suite for TLSv1.1
+ if (protocol.equals("TLSv1.1")) {
+ if(cipherSuite.indexOf("_EXPORT_") != -1) {
+ return false;
+ }
+ }
+
return true;
}
@@ -149,18 +156,14 @@
cipherSuites.length * protocols.length * clientAuths.length);
for (int i = 0; i < cipherSuites.length; 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++) {
String protocol = protocols[j];
- if (protocol.equals("SSLv2Hello")) {
+
+ if (!peerFactory.isSupported(cipherSuite, protocol)) {
continue;
}
+
for (int k = 0; k < clientAuths.length; k++) {
String clientAuth = clientAuths[k];
if ((clientAuth != null) &&
@@ -297,7 +300,7 @@
throws Exception {
long time = System.currentTimeMillis();
String relPath;
- if ((args.length > 0) && args[0].equals("sh")) {
+ if ((args != null) && (args.length > 0) && args[0].equals("sh")) {
relPath = pathToStoresSH;
} else {
relPath = pathToStores;
@@ -336,7 +339,30 @@
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;
}
}