mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-16 13:25:34 +00:00
6914943: Implement final TLS renegotiation fix
RFC 5746 implementation Reviewed-by: wetmore, weijun
This commit is contained in:
parent
356e978bce
commit
53a219bfee
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2007, 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
|
||||
@ -74,7 +74,7 @@ final class Alerts {
|
||||
static final byte alert_insufficient_security = 71;
|
||||
static final byte alert_internal_error = 80;
|
||||
static final byte alert_user_canceled = 90;
|
||||
static final byte alert_no_negotiation = 100;
|
||||
static final byte alert_no_renegotiation = 100;
|
||||
|
||||
// from RFC 3546 (TLS Extensions)
|
||||
static final byte alert_unsupported_extension = 110;
|
||||
@ -132,8 +132,8 @@ final class Alerts {
|
||||
return "internal_error";
|
||||
case alert_user_canceled:
|
||||
return "user_canceled";
|
||||
case alert_no_negotiation:
|
||||
return "no_negotiation";
|
||||
case alert_no_renegotiation:
|
||||
return "no_renegotiation";
|
||||
case alert_unsupported_extension:
|
||||
return "unsupported_extension";
|
||||
case alert_certificate_unobtainable:
|
||||
@ -203,7 +203,7 @@ final class Alerts {
|
||||
case alert_protocol_version:
|
||||
case alert_internal_error:
|
||||
case alert_user_canceled:
|
||||
case alert_no_negotiation:
|
||||
case alert_no_renegotiation:
|
||||
default:
|
||||
e = new SSLException(reason);
|
||||
break;
|
||||
|
||||
@ -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
|
||||
@ -126,6 +126,8 @@ final class CipherSuite implements Comparable {
|
||||
macAlg = M_SHA;
|
||||
} else if (name.endsWith("_NULL")) {
|
||||
macAlg = M_NULL;
|
||||
} else if (name.endsWith("_SCSV")) {
|
||||
macAlg = M_NULL;
|
||||
} else {
|
||||
throw new IllegalArgumentException
|
||||
("Unknown MAC algorithm for ciphersuite " + name);
|
||||
@ -160,6 +162,10 @@ final class CipherSuite implements Comparable {
|
||||
return allowed && keyExchange.isAvailable() && cipher.isAvailable();
|
||||
}
|
||||
|
||||
boolean isNegotiable() {
|
||||
return this != C_SCSV && isAvailable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares CipherSuites based on their priority. Has the effect of
|
||||
* sorting CipherSuites when put in a sorted collection, which is
|
||||
@ -268,7 +274,10 @@ final class CipherSuite implements Comparable {
|
||||
|
||||
// Kerberos cipher suites
|
||||
K_KRB5 ("KRB5", true),
|
||||
K_KRB5_EXPORT("KRB5_EXPORT", true);
|
||||
K_KRB5_EXPORT("KRB5_EXPORT", true),
|
||||
|
||||
// renegotiation protection request signaling cipher suite
|
||||
K_SCSV ("SCSV", true);
|
||||
|
||||
// name of the key exchange algorithm, e.g. DHE_DSS
|
||||
final String name;
|
||||
@ -352,7 +361,8 @@ final class CipherSuite implements Comparable {
|
||||
this.exportable = true;
|
||||
}
|
||||
|
||||
BulkCipher(String transformation, int keySize, int ivSize, boolean allowed) {
|
||||
BulkCipher(String transformation, int keySize,
|
||||
int ivSize, boolean allowed) {
|
||||
this.transformation = transformation;
|
||||
this.algorithm = transformation.split("/")[0];
|
||||
this.description = this.algorithm + "/" + (keySize << 3);
|
||||
@ -370,7 +380,8 @@ final class CipherSuite implements Comparable {
|
||||
*
|
||||
* @exception NoSuchAlgorithmException if anything goes wrong
|
||||
*/
|
||||
CipherBox newCipher(ProtocolVersion version, SecretKey key, IvParameterSpec iv,
|
||||
CipherBox newCipher(ProtocolVersion version,
|
||||
SecretKey key, IvParameterSpec iv,
|
||||
boolean encrypt) throws NoSuchAlgorithmException {
|
||||
return CipherBox.newCipherBox(version, this, key, iv, encrypt);
|
||||
}
|
||||
@ -407,8 +418,9 @@ final class CipherSuite implements Comparable {
|
||||
if (b == null) {
|
||||
try {
|
||||
SecretKey key = new SecretKeySpec
|
||||
(new byte[cipher.expandedKeySize], cipher.algorithm);
|
||||
IvParameterSpec iv = new IvParameterSpec(new byte[cipher.ivSize]);
|
||||
(new byte[cipher.expandedKeySize], cipher.algorithm);
|
||||
IvParameterSpec iv =
|
||||
new IvParameterSpec(new byte[cipher.ivSize]);
|
||||
cipher.newCipher(ProtocolVersion.DEFAULT, key, iv, true);
|
||||
b = Boolean.TRUE;
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
@ -460,18 +472,28 @@ final class CipherSuite implements Comparable {
|
||||
}
|
||||
|
||||
// export strength ciphers
|
||||
final static BulkCipher B_NULL = new BulkCipher("NULL", 0, 0, 0, true);
|
||||
final static BulkCipher B_RC4_40 = new BulkCipher(CIPHER_RC4, 5, 16, 0, true);
|
||||
final static BulkCipher B_RC2_40 = new BulkCipher("RC2", 5, 16, 8, false);
|
||||
final static BulkCipher B_DES_40 = new BulkCipher(CIPHER_DES, 5, 8, 8, true);
|
||||
final static BulkCipher B_NULL =
|
||||
new BulkCipher("NULL", 0, 0, 0, true);
|
||||
final static BulkCipher B_RC4_40 =
|
||||
new BulkCipher(CIPHER_RC4, 5, 16, 0, true);
|
||||
final static BulkCipher B_RC2_40 =
|
||||
new BulkCipher("RC2", 5, 16, 8, false);
|
||||
final static BulkCipher B_DES_40 =
|
||||
new BulkCipher(CIPHER_DES, 5, 8, 8, true);
|
||||
|
||||
// domestic strength ciphers
|
||||
final static BulkCipher B_RC4_128 = new BulkCipher(CIPHER_RC4, 16, 0, true);
|
||||
final static BulkCipher B_DES = new BulkCipher(CIPHER_DES, 8, 8, true);
|
||||
final static BulkCipher B_3DES = new BulkCipher(CIPHER_3DES, 24, 8, true);
|
||||
final static BulkCipher B_IDEA = new BulkCipher("IDEA", 16, 8, false);
|
||||
final static BulkCipher B_AES_128 = new BulkCipher(CIPHER_AES, 16, 16, true);
|
||||
final static BulkCipher B_AES_256 = new BulkCipher(CIPHER_AES, 32, 16, true);
|
||||
final static BulkCipher B_RC4_128 =
|
||||
new BulkCipher(CIPHER_RC4, 16, 0, true);
|
||||
final static BulkCipher B_DES =
|
||||
new BulkCipher(CIPHER_DES, 8, 8, true);
|
||||
final static BulkCipher B_3DES =
|
||||
new BulkCipher(CIPHER_3DES, 24, 8, true);
|
||||
final static BulkCipher B_IDEA =
|
||||
new BulkCipher("IDEA", 16, 8, false);
|
||||
final static BulkCipher B_AES_128 =
|
||||
new BulkCipher(CIPHER_AES, 16, 16, true);
|
||||
final static BulkCipher B_AES_256 =
|
||||
new BulkCipher(CIPHER_AES, 32, 16, true);
|
||||
|
||||
// MACs
|
||||
final static MacAlg M_NULL = new MacAlg("NULL", 0);
|
||||
@ -487,93 +509,159 @@ final class CipherSuite implements Comparable {
|
||||
// N: ciphersuites only allowed if we are not in FIPS mode
|
||||
final boolean N = (SunJSSE.isFIPS() == false);
|
||||
|
||||
add("SSL_NULL_WITH_NULL_NULL", 0x0000, 1, K_NULL, B_NULL, F);
|
||||
add("SSL_NULL_WITH_NULL_NULL",
|
||||
0x0000, 1, K_NULL, B_NULL, F);
|
||||
|
||||
// Definition of the CipherSuites that are enabled by default.
|
||||
// They are listed in preference order, most preferred first.
|
||||
int p = DEFAULT_SUITES_PRIORITY * 2;
|
||||
|
||||
add("SSL_RSA_WITH_RC4_128_MD5", 0x0004, --p, K_RSA, B_RC4_128, N);
|
||||
add("SSL_RSA_WITH_RC4_128_SHA", 0x0005, --p, K_RSA, B_RC4_128, N);
|
||||
add("TLS_RSA_WITH_AES_128_CBC_SHA", 0x002f, --p, K_RSA, B_AES_128, T);
|
||||
add("TLS_RSA_WITH_AES_256_CBC_SHA", 0x0035, --p, K_RSA, B_AES_256, T);
|
||||
add("SSL_RSA_WITH_RC4_128_MD5",
|
||||
0x0004, --p, K_RSA, B_RC4_128, N);
|
||||
add("SSL_RSA_WITH_RC4_128_SHA",
|
||||
0x0005, --p, K_RSA, B_RC4_128, N);
|
||||
add("TLS_RSA_WITH_AES_128_CBC_SHA",
|
||||
0x002f, --p, K_RSA, B_AES_128, T);
|
||||
add("TLS_RSA_WITH_AES_256_CBC_SHA",
|
||||
0x0035, --p, K_RSA, B_AES_256, T);
|
||||
|
||||
add("TLS_ECDH_ECDSA_WITH_RC4_128_SHA", 0xC002, --p, K_ECDH_ECDSA, B_RC4_128, N);
|
||||
add("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA", 0xC004, --p, K_ECDH_ECDSA, B_AES_128, T);
|
||||
add("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA", 0xC005, --p, K_ECDH_ECDSA, B_AES_256, T);
|
||||
add("TLS_ECDH_RSA_WITH_RC4_128_SHA", 0xC00C, --p, K_ECDH_RSA, B_RC4_128, N);
|
||||
add("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA", 0xC00E, --p, K_ECDH_RSA, B_AES_128, T);
|
||||
add("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA", 0xC00F, --p, K_ECDH_RSA, B_AES_256, T);
|
||||
add("TLS_ECDH_ECDSA_WITH_RC4_128_SHA",
|
||||
0xC002, --p, K_ECDH_ECDSA, B_RC4_128, N);
|
||||
add("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA",
|
||||
0xC004, --p, K_ECDH_ECDSA, B_AES_128, T);
|
||||
add("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA",
|
||||
0xC005, --p, K_ECDH_ECDSA, B_AES_256, T);
|
||||
add("TLS_ECDH_RSA_WITH_RC4_128_SHA",
|
||||
0xC00C, --p, K_ECDH_RSA, B_RC4_128, N);
|
||||
add("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",
|
||||
0xC00E, --p, K_ECDH_RSA, B_AES_128, T);
|
||||
add("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA",
|
||||
0xC00F, --p, K_ECDH_RSA, B_AES_256, T);
|
||||
|
||||
add("TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", 0xC007, --p, K_ECDHE_ECDSA,B_RC4_128, N);
|
||||
add("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", 0xC009, --p, K_ECDHE_ECDSA,B_AES_128, T);
|
||||
add("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", 0xC00A, --p, K_ECDHE_ECDSA,B_AES_256, T);
|
||||
add("TLS_ECDHE_RSA_WITH_RC4_128_SHA", 0xC011, --p, K_ECDHE_RSA, B_RC4_128, N);
|
||||
add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", 0xC013, --p, K_ECDHE_RSA, B_AES_128, T);
|
||||
add("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", 0xC014, --p, K_ECDHE_RSA, B_AES_256, T);
|
||||
add("TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
|
||||
0xC007, --p, K_ECDHE_ECDSA,B_RC4_128, N);
|
||||
add("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
|
||||
0xC009, --p, K_ECDHE_ECDSA,B_AES_128, T);
|
||||
add("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
|
||||
0xC00A, --p, K_ECDHE_ECDSA,B_AES_256, T);
|
||||
add("TLS_ECDHE_RSA_WITH_RC4_128_SHA",
|
||||
0xC011, --p, K_ECDHE_RSA, B_RC4_128, N);
|
||||
add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
|
||||
0xC013, --p, K_ECDHE_RSA, B_AES_128, T);
|
||||
add("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
|
||||
0xC014, --p, K_ECDHE_RSA, B_AES_256, T);
|
||||
|
||||
add("TLS_DHE_RSA_WITH_AES_128_CBC_SHA", 0x0033, --p, K_DHE_RSA, B_AES_128, T);
|
||||
add("TLS_DHE_RSA_WITH_AES_256_CBC_SHA", 0x0039, --p, K_DHE_RSA, B_AES_256, T);
|
||||
add("TLS_DHE_DSS_WITH_AES_128_CBC_SHA", 0x0032, --p, K_DHE_DSS, B_AES_128, T);
|
||||
add("TLS_DHE_DSS_WITH_AES_256_CBC_SHA", 0x0038, --p, K_DHE_DSS, B_AES_256, T);
|
||||
add("TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
|
||||
0x0033, --p, K_DHE_RSA, B_AES_128, T);
|
||||
add("TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
|
||||
0x0039, --p, K_DHE_RSA, B_AES_256, T);
|
||||
add("TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
|
||||
0x0032, --p, K_DHE_DSS, B_AES_128, T);
|
||||
add("TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
|
||||
0x0038, --p, K_DHE_DSS, B_AES_256, T);
|
||||
|
||||
add("SSL_RSA_WITH_3DES_EDE_CBC_SHA", 0x000a, --p, K_RSA, B_3DES, T);
|
||||
add("TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA", 0xC003, --p, K_ECDH_ECDSA, B_3DES, T);
|
||||
add("TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA", 0xC00D, --p, K_ECDH_RSA, B_3DES, T);
|
||||
add("TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", 0xC008, --p, K_ECDHE_ECDSA,B_3DES, T);
|
||||
add("TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", 0xC012, --p, K_ECDHE_RSA, B_3DES, T);
|
||||
add("SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA", 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_3DES_EDE_CBC_SHA",
|
||||
0x000a, --p, K_RSA, B_3DES, T);
|
||||
add("TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA",
|
||||
0xC003, --p, K_ECDH_ECDSA, B_3DES, T);
|
||||
add("TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||
0xC00D, --p, K_ECDH_RSA, B_3DES, T);
|
||||
add("TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
|
||||
0xC008, --p, K_ECDHE_ECDSA,B_3DES, T);
|
||||
add("TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||
0xC012, --p, K_ECDHE_RSA, B_3DES, T);
|
||||
add("SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||
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", 0x0015, --p, K_DHE_RSA, B_DES, N);
|
||||
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);
|
||||
add("SSL_RSA_EXPORT_WITH_DES40_CBC_SHA", 0x0008, --p, K_RSA_EXPORT, B_DES_40, N);
|
||||
add("SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", 0x0014, --p, K_DHE_RSA, B_DES_40, N);
|
||||
add("SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", 0x0011, --p, K_DHE_DSS, B_DES_40, N);
|
||||
add("SSL_RSA_WITH_DES_CBC_SHA",
|
||||
0x0009, --p, K_RSA, B_DES, N);
|
||||
add("SSL_DHE_RSA_WITH_DES_CBC_SHA",
|
||||
0x0015, --p, K_DHE_RSA, B_DES, N);
|
||||
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);
|
||||
add("SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
|
||||
0x0008, --p, K_RSA_EXPORT, B_DES_40, N);
|
||||
add("SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
|
||||
0x0014, --p, K_DHE_RSA, B_DES_40, N);
|
||||
add("SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
|
||||
0x0011, --p, K_DHE_DSS, B_DES_40, N);
|
||||
|
||||
// Renegotiation protection request Signalling Cipher Suite Value (SCSV)
|
||||
add("TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
|
||||
0x00ff, --p, K_SCSV, B_NULL, T);
|
||||
|
||||
// Definition of the CipherSuites that are supported but not enabled
|
||||
// by default.
|
||||
// They are listed in preference order, preferred first.
|
||||
p = DEFAULT_SUITES_PRIORITY;
|
||||
|
||||
// Anonymous key exchange and the NULL ciphers
|
||||
add("SSL_RSA_WITH_NULL_MD5", 0x0001, --p, K_RSA, B_NULL, N);
|
||||
add("SSL_RSA_WITH_NULL_SHA", 0x0002, --p, K_RSA, B_NULL, N);
|
||||
add("TLS_ECDH_ECDSA_WITH_NULL_SHA", 0xC001, --p, K_ECDH_ECDSA, B_NULL, N);
|
||||
add("TLS_ECDH_RSA_WITH_NULL_SHA", 0xC00B, --p, K_ECDH_RSA, B_NULL, N);
|
||||
add("TLS_ECDHE_ECDSA_WITH_NULL_SHA", 0xC006, --p, K_ECDHE_ECDSA,B_NULL, N);
|
||||
add("TLS_ECDHE_RSA_WITH_NULL_SHA", 0xC010, --p, K_ECDHE_RSA, B_NULL, N);
|
||||
// Anonymous key exchange and the NULL ciphers
|
||||
add("SSL_RSA_WITH_NULL_MD5",
|
||||
0x0001, --p, K_RSA, B_NULL, N);
|
||||
add("SSL_RSA_WITH_NULL_SHA",
|
||||
0x0002, --p, K_RSA, B_NULL, N);
|
||||
add("TLS_ECDH_ECDSA_WITH_NULL_SHA",
|
||||
0xC001, --p, K_ECDH_ECDSA, B_NULL, N);
|
||||
add("TLS_ECDH_RSA_WITH_NULL_SHA",
|
||||
0xC00B, --p, K_ECDH_RSA, B_NULL, N);
|
||||
add("TLS_ECDHE_ECDSA_WITH_NULL_SHA",
|
||||
0xC006, --p, K_ECDHE_ECDSA,B_NULL, N);
|
||||
add("TLS_ECDHE_RSA_WITH_NULL_SHA",
|
||||
0xC010, --p, K_ECDHE_RSA, B_NULL, N);
|
||||
|
||||
add("SSL_DH_anon_WITH_RC4_128_MD5", 0x0018, --p, K_DH_ANON, B_RC4_128, N);
|
||||
add("TLS_DH_anon_WITH_AES_128_CBC_SHA", 0x0034, --p, K_DH_ANON, B_AES_128, N);
|
||||
add("TLS_DH_anon_WITH_AES_256_CBC_SHA", 0x003a, --p, K_DH_ANON, B_AES_256, N);
|
||||
add("SSL_DH_anon_WITH_3DES_EDE_CBC_SHA", 0x001b, --p, K_DH_ANON, B_3DES, N);
|
||||
add("SSL_DH_anon_WITH_DES_CBC_SHA", 0x001a, --p, K_DH_ANON, B_DES, N);
|
||||
add("SSL_DH_anon_WITH_RC4_128_MD5",
|
||||
0x0018, --p, K_DH_ANON, B_RC4_128, N);
|
||||
add("TLS_DH_anon_WITH_AES_128_CBC_SHA",
|
||||
0x0034, --p, K_DH_ANON, B_AES_128, N);
|
||||
add("TLS_DH_anon_WITH_AES_256_CBC_SHA",
|
||||
0x003a, --p, K_DH_ANON, B_AES_256, N);
|
||||
add("SSL_DH_anon_WITH_3DES_EDE_CBC_SHA",
|
||||
0x001b, --p, K_DH_ANON, B_3DES, N);
|
||||
add("SSL_DH_anon_WITH_DES_CBC_SHA",
|
||||
0x001a, --p, K_DH_ANON, B_DES, N);
|
||||
|
||||
add("TLS_ECDH_anon_WITH_RC4_128_SHA", 0xC016, --p, K_ECDH_ANON, B_RC4_128, N);
|
||||
add("TLS_ECDH_anon_WITH_AES_128_CBC_SHA", 0xC018, --p, K_ECDH_ANON, B_AES_128, T);
|
||||
add("TLS_ECDH_anon_WITH_AES_256_CBC_SHA", 0xC019, --p, K_ECDH_ANON, B_AES_256, T);
|
||||
add("TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA", 0xC017, --p, K_ECDH_ANON, B_3DES, T);
|
||||
add("TLS_ECDH_anon_WITH_RC4_128_SHA",
|
||||
0xC016, --p, K_ECDH_ANON, B_RC4_128, N);
|
||||
add("TLS_ECDH_anon_WITH_AES_128_CBC_SHA",
|
||||
0xC018, --p, K_ECDH_ANON, B_AES_128, T);
|
||||
add("TLS_ECDH_anon_WITH_AES_256_CBC_SHA",
|
||||
0xC019, --p, K_ECDH_ANON, B_AES_256, T);
|
||||
add("TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA",
|
||||
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);
|
||||
add("SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA", 0x0019, --p, K_DH_ANON, B_DES_40, N);
|
||||
add("SSL_DH_anon_EXPORT_WITH_RC4_40_MD5",
|
||||
0x0017, --p, K_DH_ANON, B_RC4_40, N);
|
||||
add("SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
|
||||
0x0019, --p, K_DH_ANON, B_DES_40, N);
|
||||
|
||||
add("TLS_ECDH_anon_WITH_NULL_SHA", 0xC015, --p, K_ECDH_ANON, B_NULL, N);
|
||||
|
||||
// Supported Kerberos ciphersuites from RFC2712
|
||||
add("TLS_KRB5_WITH_RC4_128_SHA", 0x0020, --p, K_KRB5, B_RC4_128, N);
|
||||
add("TLS_KRB5_WITH_RC4_128_MD5", 0x0024, --p, K_KRB5, B_RC4_128, N);
|
||||
add("TLS_KRB5_WITH_3DES_EDE_CBC_SHA", 0x001f, --p, K_KRB5, B_3DES, N);
|
||||
add("TLS_KRB5_WITH_3DES_EDE_CBC_MD5", 0x0023, --p, K_KRB5, B_3DES, N);
|
||||
add("TLS_KRB5_WITH_DES_CBC_SHA", 0x001e, --p, K_KRB5, B_DES, N);
|
||||
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);
|
||||
add("TLS_KRB5_EXPORT_WITH_RC4_40_MD5", 0x002b, --p, K_KRB5_EXPORT, B_RC4_40, N);
|
||||
add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA", 0x0026, --p, K_KRB5_EXPORT, B_DES_40, N);
|
||||
add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5", 0x0029, --p, K_KRB5_EXPORT, B_DES_40, N);
|
||||
add("TLS_ECDH_anon_WITH_NULL_SHA",
|
||||
0xC015, --p, K_ECDH_ANON, B_NULL, N);
|
||||
|
||||
// Supported Kerberos ciphersuites from RFC2712
|
||||
add("TLS_KRB5_WITH_RC4_128_SHA",
|
||||
0x0020, --p, K_KRB5, B_RC4_128, N);
|
||||
add("TLS_KRB5_WITH_RC4_128_MD5",
|
||||
0x0024, --p, K_KRB5, B_RC4_128, N);
|
||||
add("TLS_KRB5_WITH_3DES_EDE_CBC_SHA",
|
||||
0x001f, --p, K_KRB5, B_3DES, N);
|
||||
add("TLS_KRB5_WITH_3DES_EDE_CBC_MD5",
|
||||
0x0023, --p, K_KRB5, B_3DES, N);
|
||||
add("TLS_KRB5_WITH_DES_CBC_SHA",
|
||||
0x001e, --p, K_KRB5, B_DES, N);
|
||||
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);
|
||||
add("TLS_KRB5_EXPORT_WITH_RC4_40_MD5",
|
||||
0x002b, --p, K_KRB5_EXPORT, B_RC4_40, N);
|
||||
add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA",
|
||||
0x0026, --p, K_KRB5_EXPORT, B_DES_40, N);
|
||||
add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5",
|
||||
0x0029, --p, K_KRB5_EXPORT, B_DES_40, N);
|
||||
|
||||
// Register the names of a few additional CipherSuites.
|
||||
// Makes them show up as names instead of numbers in
|
||||
@ -618,4 +706,6 @@ add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5", 0x0029, --p, K_KRB5_EXPORT, B_DES_4
|
||||
// ciphersuite SSL_NULL_WITH_NULL_NULL
|
||||
final static CipherSuite C_NULL = CipherSuite.valueOf(0, 0);
|
||||
|
||||
// ciphersuite TLS_EMPTY_RENEGOTIATION_INFO_SCSV
|
||||
final static CipherSuite C_SCSV = CipherSuite.valueOf(0x00, 0xff);
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2007, 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
|
||||
@ -51,8 +51,9 @@ final class CipherSuiteList {
|
||||
// null if not yet checked.
|
||||
private volatile Boolean containsEC;
|
||||
|
||||
// for use by buildAvailableCache() only
|
||||
private CipherSuiteList(Collection<CipherSuite> cipherSuites) {
|
||||
// for use by buildAvailableCache() and
|
||||
// Handshaker.getKickstartMessage() only
|
||||
CipherSuiteList(Collection<CipherSuite> cipherSuites) {
|
||||
this.cipherSuites = cipherSuites;
|
||||
}
|
||||
|
||||
@ -221,15 +222,18 @@ final class CipherSuiteList {
|
||||
// SortedSet automatically arranges ciphersuites in default
|
||||
// preference order
|
||||
Set<CipherSuite> cipherSuites = new TreeSet<CipherSuite>();
|
||||
Collection<CipherSuite> allowedCipherSuites = CipherSuite.allowedCipherSuites();
|
||||
Collection<CipherSuite> allowedCipherSuites =
|
||||
CipherSuite.allowedCipherSuites();
|
||||
for (CipherSuite c : allowedCipherSuites) {
|
||||
if ((c.allowed == false) || (c.priority < minPriority)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c.isAvailable()) {
|
||||
cipherSuites.add(c);
|
||||
}
|
||||
}
|
||||
|
||||
return new CipherSuiteList(cipherSuites);
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2009, 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
|
||||
@ -94,16 +94,24 @@ final class ClientHandshaker extends Handshaker {
|
||||
*/
|
||||
ClientHandshaker(SSLSocketImpl socket, SSLContextImpl context,
|
||||
ProtocolList enabledProtocols,
|
||||
ProtocolVersion activeProtocolVersion) {
|
||||
super(socket, context, enabledProtocols, true, true);
|
||||
this.activeProtocolVersion = activeProtocolVersion;
|
||||
ProtocolVersion activeProtocolVersion,
|
||||
boolean isInitialHandshake, boolean secureRenegotiation,
|
||||
byte[] clientVerifyData, byte[] serverVerifyData) {
|
||||
|
||||
super(socket, context, enabledProtocols, true, true,
|
||||
activeProtocolVersion, isInitialHandshake, secureRenegotiation,
|
||||
clientVerifyData, serverVerifyData);
|
||||
}
|
||||
|
||||
ClientHandshaker(SSLEngineImpl engine, SSLContextImpl context,
|
||||
ProtocolList enabledProtocols,
|
||||
ProtocolVersion activeProtocolVersion) {
|
||||
super(engine, context, enabledProtocols, true, true);
|
||||
this.activeProtocolVersion = activeProtocolVersion;
|
||||
ProtocolVersion activeProtocolVersion,
|
||||
boolean isInitialHandshake, boolean secureRenegotiation,
|
||||
byte[] clientVerifyData, byte[] serverVerifyData) {
|
||||
|
||||
super(engine, context, enabledProtocols, true, true,
|
||||
activeProtocolVersion, isInitialHandshake, secureRenegotiation,
|
||||
clientVerifyData, serverVerifyData);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -279,10 +287,11 @@ final class ClientHandshaker extends Handshaker {
|
||||
// sent the "client hello" but the server's not seen it.
|
||||
//
|
||||
if (state < HandshakeMessage.ht_client_hello) {
|
||||
if (!renegotiable) { // renegotiation is not allowed.
|
||||
if (!secureRenegotiation && !allowUnsafeRenegotiation) {
|
||||
// renegotiation is not allowed.
|
||||
if (activeProtocolVersion.v >= ProtocolVersion.TLS10.v) {
|
||||
// response with a no_negotiation warning,
|
||||
warningSE(Alerts.alert_no_negotiation);
|
||||
// response with a no_renegotiation warning,
|
||||
warningSE(Alerts.alert_no_renegotiation);
|
||||
|
||||
// invalidate the handshake so that the caller can
|
||||
// dispose this object.
|
||||
@ -293,26 +302,24 @@ final class ClientHandshaker extends Handshaker {
|
||||
// and the next handshake message will become incomplete.
|
||||
//
|
||||
// However, according to SSL/TLS specifications, no more
|
||||
// handshake message could immediately follow ClientHello
|
||||
// or HelloRequest. But in case of any improper messages,
|
||||
// we'd better check to ensure there is no remaining bytes
|
||||
// in the handshake input stream.
|
||||
if (input.available() > 0) {
|
||||
fatalSE(Alerts.alert_unexpected_message,
|
||||
"HelloRequest followed by an unexpected " +
|
||||
"handshake message");
|
||||
}
|
||||
|
||||
// handshake message should immediately follow ClientHello
|
||||
// or HelloRequest. So just let it be.
|
||||
} else {
|
||||
// For SSLv3, send the handshake_failure fatal error.
|
||||
// Note that SSLv3 does not define a no_negotiation alert
|
||||
// like TLSv1. However we cannot ignore the message
|
||||
// Note that SSLv3 does not define a no_renegotiation
|
||||
// alert like TLSv1. However we cannot ignore the message
|
||||
// simply, otherwise the other side was waiting for a
|
||||
// response that would never come.
|
||||
fatalSE(Alerts.alert_handshake_failure,
|
||||
"renegotiation is not allowed");
|
||||
"Renegotiation is not allowed");
|
||||
}
|
||||
} else {
|
||||
if (!secureRenegotiation) {
|
||||
if (debug != null && Debug.isOn("handshake")) {
|
||||
System.out.println(
|
||||
"Warning: continue with insecure renegotiation");
|
||||
}
|
||||
}
|
||||
kickstart();
|
||||
}
|
||||
}
|
||||
@ -347,6 +354,68 @@ final class ClientHandshaker extends Handshaker {
|
||||
// Handshake streams
|
||||
setVersion(mesgVersion);
|
||||
|
||||
// check the "renegotiation_info" extension
|
||||
RenegotiationInfoExtension serverHelloRI = (RenegotiationInfoExtension)
|
||||
mesg.extensions.get(ExtensionType.EXT_RENEGOTIATION_INFO);
|
||||
if (serverHelloRI != null) {
|
||||
if (isInitialHandshake) {
|
||||
// verify the length of the "renegotiated_connection" field
|
||||
if (!serverHelloRI.isEmpty()) {
|
||||
// abort the handshake with a fatal handshake_failure alert
|
||||
fatalSE(Alerts.alert_handshake_failure,
|
||||
"The renegotiation_info field is not empty");
|
||||
}
|
||||
|
||||
secureRenegotiation = true;
|
||||
} else {
|
||||
// For a legacy renegotiation, the client MUST verify that
|
||||
// it does not contain the "renegotiation_info" extension.
|
||||
if (!secureRenegotiation) {
|
||||
fatalSE(Alerts.alert_handshake_failure,
|
||||
"Unexpected renegotiation indication extension");
|
||||
}
|
||||
|
||||
// verify the client_verify_data and server_verify_data values
|
||||
byte[] verifyData =
|
||||
new byte[clientVerifyData.length + serverVerifyData.length];
|
||||
System.arraycopy(clientVerifyData, 0, verifyData,
|
||||
0, clientVerifyData.length);
|
||||
System.arraycopy(serverVerifyData, 0, verifyData,
|
||||
clientVerifyData.length, serverVerifyData.length);
|
||||
if (!Arrays.equals(verifyData,
|
||||
serverHelloRI.getRenegotiatedConnection())) {
|
||||
fatalSE(Alerts.alert_handshake_failure,
|
||||
"Incorrect verify data in ServerHello " +
|
||||
"renegotiation_info message");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// no renegotiation indication extension
|
||||
if (isInitialHandshake) {
|
||||
if (!allowLegacyHelloMessages) {
|
||||
// abort the handshake with a fatal handshake_failure alert
|
||||
fatalSE(Alerts.alert_handshake_failure,
|
||||
"Failed to negotiate the use of secure renegotiation");
|
||||
}
|
||||
|
||||
secureRenegotiation = false;
|
||||
if (debug != null && Debug.isOn("handshake")) {
|
||||
System.out.println("Warning: No renegotiation " +
|
||||
"indication extension in ServerHello");
|
||||
}
|
||||
} else {
|
||||
// For a secure renegotiation, the client must abort the
|
||||
// handshake if no "renegotiation_info" extension is present.
|
||||
if (secureRenegotiation) {
|
||||
fatalSE(Alerts.alert_handshake_failure,
|
||||
"No renegotiation indication extension");
|
||||
}
|
||||
|
||||
// we have already allowed unsafe renegotation before request
|
||||
// the renegotiation.
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Save server nonce, we always use it to compute connection
|
||||
// keys and it's also used to create the master secret if we're
|
||||
@ -354,10 +423,11 @@ final class ClientHandshaker extends Handshaker {
|
||||
//
|
||||
svr_random = mesg.svr_random;
|
||||
|
||||
if (isEnabled(mesg.cipherSuite) == false) {
|
||||
if (isNegotiable(mesg.cipherSuite) == false) {
|
||||
fatalSE(Alerts.alert_illegal_parameter,
|
||||
"Server selected disabled ciphersuite " + cipherSuite);
|
||||
"Server selected improper ciphersuite " + cipherSuite);
|
||||
}
|
||||
|
||||
setCipherSuite(mesg.cipherSuite);
|
||||
|
||||
if (mesg.compression_method != 0) {
|
||||
@ -452,7 +522,8 @@ final class ClientHandshaker extends Handshaker {
|
||||
for (HelloExtension ext : mesg.extensions.list()) {
|
||||
ExtensionType type = ext.type;
|
||||
if ((type != ExtensionType.EXT_ELLIPTIC_CURVES)
|
||||
&& (type != ExtensionType.EXT_EC_POINT_FORMATS)) {
|
||||
&& (type != ExtensionType.EXT_EC_POINT_FORMATS)
|
||||
&& (type != ExtensionType.EXT_RENEGOTIATION_INFO)) {
|
||||
fatalSE(Alerts.alert_unsupported_extension,
|
||||
"Server sent an unsupported extension: " + type);
|
||||
}
|
||||
@ -868,6 +939,13 @@ final class ClientHandshaker extends Handshaker {
|
||||
// NOTREACHED
|
||||
}
|
||||
|
||||
/*
|
||||
* save server verify data for secure renegotiation
|
||||
*/
|
||||
if (secureRenegotiation) {
|
||||
serverVerifyData = mesg.getVerifyData();
|
||||
}
|
||||
|
||||
/*
|
||||
* OK, it verified. If we're doing the fast handshake, add that
|
||||
* "Finished" message to the hash of handshake messages, then send
|
||||
@ -920,6 +998,13 @@ final class ClientHandshaker extends Handshaker {
|
||||
*/
|
||||
sendChangeCipherSpec(mesg, finishedTag);
|
||||
|
||||
/*
|
||||
* save client verify data for secure renegotiation
|
||||
*/
|
||||
if (secureRenegotiation) {
|
||||
clientVerifyData = mesg.getVerifyData();
|
||||
}
|
||||
|
||||
/*
|
||||
* Update state machine so server MUST send 'finished' next.
|
||||
* (In "long" handshake case; in short case, we're responding
|
||||
@ -933,11 +1018,14 @@ final class ClientHandshaker extends Handshaker {
|
||||
* Returns a ClientHello message to kickstart renegotiations
|
||||
*/
|
||||
HandshakeMessage getKickstartMessage() throws SSLException {
|
||||
ClientHello mesg = new ClientHello(sslContext.getSecureRandom(),
|
||||
protocolVersion);
|
||||
maxProtocolVersion = protocolVersion;
|
||||
// session ID of the ClientHello message
|
||||
SessionId sessionId = SSLSessionImpl.nullSession.getSessionId();
|
||||
|
||||
clnt_random = mesg.clnt_random;
|
||||
// a list of cipher suites sent by the client
|
||||
CipherSuiteList cipherSuites = enabledCipherSuites;
|
||||
|
||||
// set the max protocol version this client is supporting.
|
||||
maxProtocolVersion = protocolVersion;
|
||||
|
||||
//
|
||||
// Try to resume an existing session. This might be mandatory,
|
||||
@ -962,9 +1050,9 @@ final class ClientHandshaker extends Handshaker {
|
||||
if (session != null) {
|
||||
CipherSuite sessionSuite = session.getSuite();
|
||||
ProtocolVersion sessionVersion = session.getProtocolVersion();
|
||||
if (isEnabled(sessionSuite) == false) {
|
||||
if (isNegotiable(sessionSuite) == false) {
|
||||
if (debug != null && Debug.isOn("session")) {
|
||||
System.out.println("%% can't resume, cipher disabled");
|
||||
System.out.println("%% can't resume, unavailable cipher");
|
||||
}
|
||||
session = null;
|
||||
}
|
||||
@ -984,9 +1072,8 @@ final class ClientHandshaker extends Handshaker {
|
||||
+ " from port " + getLocalPortSE());
|
||||
}
|
||||
}
|
||||
mesg.sessionId = session.getSessionId();
|
||||
|
||||
mesg.protocolVersion = sessionVersion;
|
||||
sessionId = session.getSessionId();
|
||||
maxProtocolVersion = sessionVersion;
|
||||
|
||||
// Update SSL version number in underlying SSL socket and
|
||||
@ -995,33 +1082,78 @@ final class ClientHandshaker extends Handshaker {
|
||||
setVersion(sessionVersion);
|
||||
}
|
||||
|
||||
//
|
||||
// don't say much beyond the obvious if we _must_ resume.
|
||||
//
|
||||
/*
|
||||
* Force use of the previous session ciphersuite, and
|
||||
* add the SCSV if enabled.
|
||||
*/
|
||||
if (!enableNewSession) {
|
||||
if (session == null) {
|
||||
throw new SSLException(
|
||||
"Can't reuse existing SSL client session");
|
||||
}
|
||||
mesg.setCipherSuites(new CipherSuiteList(sessionSuite));
|
||||
return mesg;
|
||||
}
|
||||
}
|
||||
if (session == null) {
|
||||
if (enableNewSession) {
|
||||
mesg.sessionId = SSLSessionImpl.nullSession.getSessionId();
|
||||
} else {
|
||||
throw new SSLException("No existing session to resume.");
|
||||
|
||||
Collection<CipherSuite> cipherList =
|
||||
new ArrayList<CipherSuite>(2);
|
||||
cipherList.add(sessionSuite);
|
||||
if (!secureRenegotiation &&
|
||||
cipherSuites.contains(CipherSuite.C_SCSV)) {
|
||||
cipherList.add(CipherSuite.C_SCSV);
|
||||
} // otherwise, renegotiation_info extension will be used
|
||||
|
||||
cipherSuites = new CipherSuiteList(cipherList);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// All we have left to do is fill out the cipher suites.
|
||||
// (If this changes, change the 'return' above!)
|
||||
//
|
||||
mesg.setCipherSuites(enabledCipherSuites);
|
||||
if (session == null && !enableNewSession) {
|
||||
throw new SSLException("No existing session to resume");
|
||||
}
|
||||
|
||||
return mesg;
|
||||
// exclude SCSV for secure renegotiation
|
||||
if (secureRenegotiation && cipherSuites.contains(CipherSuite.C_SCSV)) {
|
||||
Collection<CipherSuite> cipherList =
|
||||
new ArrayList<CipherSuite>(cipherSuites.size() - 1);
|
||||
for (CipherSuite suite : cipherSuites.collection()) {
|
||||
if (suite != CipherSuite.C_SCSV) {
|
||||
cipherList.add(suite);
|
||||
}
|
||||
}
|
||||
|
||||
cipherSuites = new CipherSuiteList(cipherList);
|
||||
}
|
||||
|
||||
// make sure there is a negotiable cipher suite.
|
||||
boolean negotiable = false;
|
||||
for (CipherSuite suite : cipherSuites.collection()) {
|
||||
if (isNegotiable(suite)) {
|
||||
negotiable = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!negotiable) {
|
||||
throw new SSLException("No negotiable cipher suite");
|
||||
}
|
||||
|
||||
// create the ClientHello message
|
||||
ClientHello clientHelloMessage = new ClientHello(
|
||||
sslContext.getSecureRandom(), maxProtocolVersion,
|
||||
sessionId, cipherSuites);
|
||||
|
||||
// reset the client random cookie
|
||||
clnt_random = clientHelloMessage.clnt_random;
|
||||
|
||||
/*
|
||||
* need to set the renegotiation_info extension for:
|
||||
* 1: secure renegotiation
|
||||
* 2: initial handshake and no SCSV in the ClientHello
|
||||
* 3: insecure renegotiation and no SCSV in the ClientHello
|
||||
*/
|
||||
if (secureRenegotiation ||
|
||||
!cipherSuites.contains(CipherSuite.C_SCSV)) {
|
||||
clientHelloMessage.addRenegotiationInfoExtension(clientVerifyData);
|
||||
}
|
||||
|
||||
return clientHelloMessage;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2009, 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
|
||||
@ -172,9 +172,7 @@ public abstract class HandshakeMessage {
|
||||
* Server can ask the client to initiate a new handshake, e.g. to change
|
||||
* session parameters after a connection has been (re)established.
|
||||
*/
|
||||
static final
|
||||
class HelloRequest extends HandshakeMessage
|
||||
{
|
||||
static final class HelloRequest extends HandshakeMessage {
|
||||
int messageType() { return ht_hello_request; }
|
||||
|
||||
HelloRequest() { }
|
||||
@ -210,10 +208,7 @@ class HelloRequest extends HandshakeMessage
|
||||
* Until we know how to parse it, we will just read what we know
|
||||
* about, and let our caller handle the jumps over unknown data.
|
||||
*/
|
||||
static final
|
||||
class ClientHello extends HandshakeMessage
|
||||
{
|
||||
int messageType() { return ht_client_hello; }
|
||||
static final class ClientHello extends HandshakeMessage {
|
||||
|
||||
ProtocolVersion protocolVersion;
|
||||
RandomCookie clnt_random;
|
||||
@ -225,37 +220,20 @@ class ClientHello extends HandshakeMessage
|
||||
|
||||
private final static byte[] NULL_COMPRESSION = new byte[] {0};
|
||||
|
||||
ClientHello(SecureRandom generator, ProtocolVersion protocolVersion) {
|
||||
ClientHello(SecureRandom generator, ProtocolVersion protocolVersion,
|
||||
SessionId sessionId, CipherSuiteList cipherSuites) {
|
||||
|
||||
this.protocolVersion = protocolVersion;
|
||||
clnt_random = new RandomCookie(generator);
|
||||
compression_methods = NULL_COMPRESSION;
|
||||
// sessionId, cipher_suites TBS later
|
||||
}
|
||||
|
||||
CipherSuiteList getCipherSuites() {
|
||||
return cipherSuites;
|
||||
}
|
||||
|
||||
// Set the ciphersuites.
|
||||
// This method may only be called once.
|
||||
void setCipherSuites(CipherSuiteList cipherSuites) {
|
||||
this.sessionId = sessionId;
|
||||
this.cipherSuites = cipherSuites;
|
||||
|
||||
if (cipherSuites.containsEC()) {
|
||||
extensions.add(SupportedEllipticCurvesExtension.DEFAULT);
|
||||
extensions.add(SupportedEllipticPointFormatsExtension.DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
int messageLength() {
|
||||
/*
|
||||
* Add fixed size parts of each field...
|
||||
* version + random + session + cipher + compress
|
||||
*/
|
||||
return (2 + 32 + 1 + 2 + 1
|
||||
+ sessionId.length() /* ... + variable parts */
|
||||
+ (cipherSuites.size() * 2)
|
||||
+ compression_methods.length)
|
||||
+ extensions.length();
|
||||
clnt_random = new RandomCookie(generator);
|
||||
compression_methods = NULL_COMPRESSION;
|
||||
}
|
||||
|
||||
ClientHello(HandshakeInStream s, int messageLength) throws IOException {
|
||||
@ -269,6 +247,34 @@ class ClientHello extends HandshakeMessage
|
||||
}
|
||||
}
|
||||
|
||||
CipherSuiteList getCipherSuites() {
|
||||
return cipherSuites;
|
||||
}
|
||||
|
||||
// add renegotiation_info extension
|
||||
void addRenegotiationInfoExtension(byte[] clientVerifyData) {
|
||||
HelloExtension renegotiationInfo = new RenegotiationInfoExtension(
|
||||
clientVerifyData, new byte[0]);
|
||||
extensions.add(renegotiationInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
int messageType() { return ht_client_hello; }
|
||||
|
||||
@Override
|
||||
int messageLength() {
|
||||
/*
|
||||
* Add fixed size parts of each field...
|
||||
* version + random + session + cipher + compress
|
||||
*/
|
||||
return (2 + 32 + 1 + 2 + 1
|
||||
+ sessionId.length() /* ... + variable parts */
|
||||
+ (cipherSuites.size() * 2)
|
||||
+ compression_methods.length)
|
||||
+ extensions.length();
|
||||
}
|
||||
|
||||
@Override
|
||||
void send(HandshakeOutStream s) throws IOException {
|
||||
s.putInt8(protocolVersion.major);
|
||||
s.putInt8(protocolVersion.minor);
|
||||
@ -279,6 +285,7 @@ class ClientHello extends HandshakeMessage
|
||||
extensions.send(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
void print(PrintStream s) throws IOException {
|
||||
s.println("*** ClientHello, " + protocolVersion);
|
||||
|
||||
@ -315,7 +322,6 @@ class ServerHello extends HandshakeMessage
|
||||
CipherSuite cipherSuite;
|
||||
byte compression_method;
|
||||
HelloExtensions extensions = new HelloExtensions();
|
||||
int extensionLength;
|
||||
|
||||
ServerHello() {
|
||||
// empty
|
||||
@ -1425,8 +1431,6 @@ static final class CertificateVerify extends HandshakeMessage {
|
||||
*/
|
||||
static final class Finished extends HandshakeMessage {
|
||||
|
||||
int messageType() { return ht_finished; }
|
||||
|
||||
// constant for a Finished message sent by the client
|
||||
final static int CLIENT = 1;
|
||||
|
||||
@ -1468,7 +1472,7 @@ static final class Finished extends HandshakeMessage {
|
||||
* both client and server are fully in sync, and that the handshake
|
||||
* computations have been successful.
|
||||
*/
|
||||
boolean verify(ProtocolVersion protocolVersion,
|
||||
boolean verify(ProtocolVersion protocolVersion,
|
||||
HandshakeHash handshakeHash, int sender, SecretKey master) {
|
||||
byte[] myFinished = getFinished(protocolVersion, handshakeHash,
|
||||
sender, master);
|
||||
@ -1542,14 +1546,25 @@ static final class Finished extends HandshakeMessage {
|
||||
CertificateVerify.updateDigest(md, pad1, pad2, masterSecret);
|
||||
}
|
||||
|
||||
// get the verify_data of the finished message
|
||||
byte[] getVerifyData() {
|
||||
return verifyData;
|
||||
}
|
||||
|
||||
@Override
|
||||
int messageType() { return ht_finished; }
|
||||
|
||||
@Override
|
||||
int messageLength() {
|
||||
return verifyData.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
void send(HandshakeOutStream out) throws IOException {
|
||||
out.write(verifyData);
|
||||
}
|
||||
|
||||
@Override
|
||||
void print(PrintStream s) throws IOException {
|
||||
s.println("*** Finished");
|
||||
if (debug != null && Debug.isOn("verbose")) {
|
||||
@ -1557,7 +1572,6 @@ static final class Finished extends HandshakeMessage {
|
||||
s.println("***");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2009, 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
|
||||
@ -66,6 +66,14 @@ abstract class Handshaker {
|
||||
// the currently active protocol version during a renegotiation
|
||||
ProtocolVersion activeProtocolVersion;
|
||||
|
||||
// security parameters for secure renegotiation.
|
||||
boolean secureRenegotiation;
|
||||
byte[] clientVerifyData;
|
||||
byte[] serverVerifyData;
|
||||
|
||||
// is it an initial negotiation or a renegotiation?
|
||||
boolean isInitialHandshake;
|
||||
|
||||
// list of enabled protocols
|
||||
ProtocolList enabledProtocols;
|
||||
|
||||
@ -128,31 +136,66 @@ abstract class Handshaker {
|
||||
static final Debug debug = Debug.getInstance("ssl");
|
||||
|
||||
// By default, disable the unsafe legacy session renegotiation
|
||||
static final boolean renegotiable = Debug.getBooleanProperty(
|
||||
static final boolean allowUnsafeRenegotiation = Debug.getBooleanProperty(
|
||||
"sun.security.ssl.allowUnsafeRenegotiation", false);
|
||||
|
||||
// For maximum interoperability and backward compatibility, RFC 5746
|
||||
// allows server (or client) to accept ClientHello (or ServerHello)
|
||||
// message without the secure renegotiation_info extension or SCSV.
|
||||
//
|
||||
// For maximum security, RFC 5746 also allows server (or client) to
|
||||
// reject such message with a fatal "handshake_failure" alert.
|
||||
//
|
||||
// By default, allow such legacy hello messages.
|
||||
static final boolean allowLegacyHelloMessages = Debug.getBooleanProperty(
|
||||
"sun.security.ssl.allowLegacyHelloMessages", true);
|
||||
|
||||
// need to dispose the object when it is invalidated
|
||||
boolean invalidated;
|
||||
|
||||
Handshaker(SSLSocketImpl c, SSLContextImpl context,
|
||||
ProtocolList enabledProtocols, boolean needCertVerify,
|
||||
boolean isClient) {
|
||||
boolean isClient, ProtocolVersion activeProtocolVersion,
|
||||
boolean isInitialHandshake, boolean secureRenegotiation,
|
||||
byte[] clientVerifyData, byte[] serverVerifyData) {
|
||||
this.conn = c;
|
||||
init(context, enabledProtocols, needCertVerify, isClient);
|
||||
init(context, enabledProtocols, needCertVerify, isClient,
|
||||
activeProtocolVersion, isInitialHandshake, secureRenegotiation,
|
||||
clientVerifyData, serverVerifyData);
|
||||
}
|
||||
|
||||
Handshaker(SSLEngineImpl engine, SSLContextImpl context,
|
||||
ProtocolList enabledProtocols, boolean needCertVerify,
|
||||
boolean isClient) {
|
||||
boolean isClient, ProtocolVersion activeProtocolVersion,
|
||||
boolean isInitialHandshake, boolean secureRenegotiation,
|
||||
byte[] clientVerifyData, byte[] serverVerifyData) {
|
||||
this.engine = engine;
|
||||
init(context, enabledProtocols, needCertVerify, isClient);
|
||||
init(context, enabledProtocols, needCertVerify, isClient,
|
||||
activeProtocolVersion, isInitialHandshake, secureRenegotiation,
|
||||
clientVerifyData, serverVerifyData);
|
||||
}
|
||||
|
||||
private void init(SSLContextImpl context, ProtocolList enabledProtocols,
|
||||
boolean needCertVerify, boolean isClient) {
|
||||
boolean needCertVerify, boolean isClient,
|
||||
ProtocolVersion activeProtocolVersion,
|
||||
boolean isInitialHandshake, boolean secureRenegotiation,
|
||||
byte[] clientVerifyData, byte[] serverVerifyData) {
|
||||
|
||||
if (debug != null && Debug.isOn("handshake")) {
|
||||
System.out.println(
|
||||
"Allow unsafe renegotiation: " + allowUnsafeRenegotiation +
|
||||
"\nAllow legacy hello messages: " + allowLegacyHelloMessages +
|
||||
"\nIs initial handshake: " + isInitialHandshake +
|
||||
"\nIs secure renegotiation: " + secureRenegotiation);
|
||||
}
|
||||
|
||||
this.sslContext = context;
|
||||
this.isClient = isClient;
|
||||
this.activeProtocolVersion = activeProtocolVersion;
|
||||
this.isInitialHandshake = isInitialHandshake;
|
||||
this.secureRenegotiation = secureRenegotiation;
|
||||
this.clientVerifyData = clientVerifyData;
|
||||
this.serverVerifyData = serverVerifyData;
|
||||
enableNewSession = true;
|
||||
invalidated = false;
|
||||
|
||||
@ -353,8 +396,8 @@ abstract class Handshaker {
|
||||
* changed due to change in JCE providers since it was enabled).
|
||||
* Does not check if the required server certificates are available.
|
||||
*/
|
||||
boolean isEnabled(CipherSuite s) {
|
||||
return enabledCipherSuites.contains(s) && s.isAvailable();
|
||||
boolean isNegotiable(CipherSuite s) {
|
||||
return enabledCipherSuites.contains(s) && s.isNegotiable();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -458,6 +501,27 @@ abstract class Handshaker {
|
||||
return session;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if renegotiation is in use for this connection.
|
||||
*/
|
||||
boolean isSecureRenegotiation() {
|
||||
return secureRenegotiation;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the verify_data from the Finished message sent by the client.
|
||||
*/
|
||||
byte[] getClientVerifyData() {
|
||||
return clientVerifyData;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the verify_data from the Finished message sent by the server.
|
||||
*/
|
||||
byte[] getServerVerifyData() {
|
||||
return serverVerifyData;
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine is fed SSL handshake records when they become available,
|
||||
* and processes messages found therein.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2006, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2006, 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
|
||||
@ -81,7 +81,10 @@ final class HelloExtensions {
|
||||
} else if (extType == ExtensionType.EXT_ELLIPTIC_CURVES) {
|
||||
extension = new SupportedEllipticCurvesExtension(s, extlen);
|
||||
} else if (extType == ExtensionType.EXT_EC_POINT_FORMATS) {
|
||||
extension = new SupportedEllipticPointFormatsExtension(s, extlen);
|
||||
extension =
|
||||
new SupportedEllipticPointFormatsExtension(s, extlen);
|
||||
} else if (extType == ExtensionType.EXT_RENEGOTIATION_INFO) {
|
||||
extension = new RenegotiationInfoExtension(s, extlen);
|
||||
} else {
|
||||
extension = new UnknownExtension(s, extlen, extType);
|
||||
}
|
||||
@ -89,7 +92,8 @@ final class HelloExtensions {
|
||||
len -= extlen + 4;
|
||||
}
|
||||
if (len != 0) {
|
||||
throw new SSLProtocolException("Error parsing extensions: extra data");
|
||||
throw new SSLProtocolException(
|
||||
"Error parsing extensions: extra data");
|
||||
}
|
||||
}
|
||||
|
||||
@ -162,7 +166,8 @@ final class ExtensionType {
|
||||
return name;
|
||||
}
|
||||
|
||||
static List<ExtensionType> knownExtensions = new ArrayList<ExtensionType>(8);
|
||||
static List<ExtensionType> knownExtensions =
|
||||
new ArrayList<ExtensionType>(9);
|
||||
|
||||
static ExtensionType get(int id) {
|
||||
for (ExtensionType ext : knownExtensions) {
|
||||
@ -180,17 +185,44 @@ final class ExtensionType {
|
||||
}
|
||||
|
||||
// extensions defined in RFC 3546
|
||||
final static ExtensionType EXT_SERVER_NAME = e( 0, "server_name");
|
||||
final static ExtensionType EXT_MAX_FRAGMENT_LENGTH = e( 1, "max_fragment_length");
|
||||
final static ExtensionType EXT_CLIENT_CERTIFICATE_URL = e( 2, "client_certificate_url");
|
||||
final static ExtensionType EXT_TRUSTED_CA_KEYS = e( 3, "trusted_ca_keys");
|
||||
final static ExtensionType EXT_TRUNCATED_HMAC = e( 4, "truncated_hmac");
|
||||
final static ExtensionType EXT_STATUS_REQUEST = e( 5, "status_request");
|
||||
final static ExtensionType EXT_SERVER_NAME =
|
||||
e(0x0000, "server_name"); // IANA registry value: 0
|
||||
final static ExtensionType EXT_MAX_FRAGMENT_LENGTH =
|
||||
e(0x0001, "max_fragment_length"); // IANA registry value: 1
|
||||
final static ExtensionType EXT_CLIENT_CERTIFICATE_URL =
|
||||
e(0x0002, "client_certificate_url"); // IANA registry value: 2
|
||||
final static ExtensionType EXT_TRUSTED_CA_KEYS =
|
||||
e(0x0003, "trusted_ca_keys"); // IANA registry value: 3
|
||||
final static ExtensionType EXT_TRUNCATED_HMAC =
|
||||
e(0x0004, "truncated_hmac"); // IANA registry value: 4
|
||||
final static ExtensionType EXT_STATUS_REQUEST =
|
||||
e(0x0005, "status_request"); // IANA registry value: 5
|
||||
|
||||
// extensions defined in RFC 4681
|
||||
final static ExtensionType EXT_USER_MAPPING =
|
||||
e(0x0006, "user_mapping"); // IANA registry value: 6
|
||||
|
||||
// extensions defined in RFC 5081
|
||||
final static ExtensionType EXT_CERT_TYPE =
|
||||
e(0x0009, "cert_type"); // IANA registry value: 9
|
||||
|
||||
// extensions defined in RFC 4492 (ECC)
|
||||
final static ExtensionType EXT_ELLIPTIC_CURVES = e(10, "elliptic_curves");
|
||||
final static ExtensionType EXT_EC_POINT_FORMATS = e(11, "ec_point_formats");
|
||||
final static ExtensionType EXT_ELLIPTIC_CURVES =
|
||||
e(0x000A, "elliptic_curves"); // IANA registry value: 10
|
||||
final static ExtensionType EXT_EC_POINT_FORMATS =
|
||||
e(0x000B, "ec_point_formats"); // IANA registry value: 11
|
||||
|
||||
// extensions defined in RFC 5054
|
||||
final static ExtensionType EXT_SRP =
|
||||
e(0x000C, "srp"); // IANA registry value: 12
|
||||
|
||||
// extensions defined in RFC 5246
|
||||
final static ExtensionType EXT_SIGNATURE_ALGORITHMS =
|
||||
e(0x000D, "signature_algorithms"); // IANA registry value: 13
|
||||
|
||||
// extensions defined in RFC 5746
|
||||
final static ExtensionType EXT_RENEGOTIATION_INFO =
|
||||
e(0xff01, "renegotiation_info"); // IANA registry value: 65281
|
||||
}
|
||||
|
||||
abstract class HelloExtension {
|
||||
@ -238,9 +270,11 @@ final class UnknownExtension extends HelloExtension {
|
||||
}
|
||||
}
|
||||
|
||||
// Support for the server_name extension is incomplete. Parsing is implemented
|
||||
// so that we get nicer debug output, but we neither send it nor do we do
|
||||
// act on it if we receive it.
|
||||
/*
|
||||
* Support for the server_name extension is incomplete. Parsing is implemented
|
||||
* so that we get nicer debug output, but we neither send it nor do we do
|
||||
* act on it if we receive it.
|
||||
*/
|
||||
final class ServerNameExtension extends HelloExtension {
|
||||
|
||||
final static int NAME_HOST_NAME = 0;
|
||||
@ -268,9 +302,9 @@ final class ServerNameExtension extends HelloExtension {
|
||||
final String hostname;
|
||||
|
||||
ServerName(HandshakeInStream s) throws IOException {
|
||||
length = s.getInt16();
|
||||
type = s.getInt8();
|
||||
data = s.getBytes16();
|
||||
length = s.getInt16(); // ServerNameList length
|
||||
type = s.getInt8(); // NameType
|
||||
data = s.getBytes16(); // HostName (length read in getBytes16)
|
||||
if (type == NAME_HOST_NAME) {
|
||||
hostname = new String(data, "UTF8");
|
||||
} else {
|
||||
@ -549,3 +583,85 @@ final class SupportedEllipticPointFormatsExtension extends HelloExtension {
|
||||
return "Extension " + type + ", formats: " + list;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* For secure renegotiation, RFC5746 defines a new TLS extension,
|
||||
* "renegotiation_info" (with extension type 0xff01), which contains a
|
||||
* cryptographic binding to the enclosing TLS connection (if any) for
|
||||
* which the renegotiation is being performed. The "extension data"
|
||||
* field of this extension contains a "RenegotiationInfo" structure:
|
||||
*
|
||||
* struct {
|
||||
* opaque renegotiated_connection<0..255>;
|
||||
* } RenegotiationInfo;
|
||||
*/
|
||||
final class RenegotiationInfoExtension extends HelloExtension {
|
||||
private final byte[] renegotiated_connection;
|
||||
|
||||
RenegotiationInfoExtension(byte[] clientVerifyData,
|
||||
byte[] serverVerifyData) {
|
||||
super(ExtensionType.EXT_RENEGOTIATION_INFO);
|
||||
|
||||
if (clientVerifyData.length != 0) {
|
||||
renegotiated_connection =
|
||||
new byte[clientVerifyData.length + serverVerifyData.length];
|
||||
System.arraycopy(clientVerifyData, 0, renegotiated_connection,
|
||||
0, clientVerifyData.length);
|
||||
|
||||
if (serverVerifyData.length != 0) {
|
||||
System.arraycopy(serverVerifyData, 0, renegotiated_connection,
|
||||
clientVerifyData.length, serverVerifyData.length);
|
||||
}
|
||||
} else {
|
||||
// ignore both the client and server verify data.
|
||||
renegotiated_connection = new byte[0];
|
||||
}
|
||||
}
|
||||
|
||||
RenegotiationInfoExtension(HandshakeInStream s, int len)
|
||||
throws IOException {
|
||||
super(ExtensionType.EXT_RENEGOTIATION_INFO);
|
||||
|
||||
// check the extension length
|
||||
if (len < 1) {
|
||||
throw new SSLProtocolException("Invalid " + type + " extension");
|
||||
}
|
||||
|
||||
int renegoInfoDataLen = s.getInt8();
|
||||
if (renegoInfoDataLen + 1 != len) { // + 1 = the byte we just read
|
||||
throw new SSLProtocolException("Invalid " + type + " extension");
|
||||
}
|
||||
|
||||
renegotiated_connection = new byte[renegoInfoDataLen];
|
||||
if (renegoInfoDataLen != 0) {
|
||||
s.read(renegotiated_connection, 0, renegoInfoDataLen);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Length of the encoded extension, including the type and length fields
|
||||
int length() {
|
||||
return 5 + renegotiated_connection.length;
|
||||
}
|
||||
|
||||
void send(HandshakeOutStream s) throws IOException {
|
||||
s.putInt16(type.id);
|
||||
s.putInt16(renegotiated_connection.length + 1);
|
||||
s.putBytes8(renegotiated_connection);
|
||||
}
|
||||
|
||||
boolean isEmpty() {
|
||||
return renegotiated_connection.length == 0;
|
||||
}
|
||||
|
||||
byte[] getRenegotiatedConnection() {
|
||||
return renegotiated_connection;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "Extension " + type + ", renegotiated_connection: " +
|
||||
(renegotiated_connection.length == 0 ? "<empty>" :
|
||||
Debug.toString(renegotiated_connection));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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
|
||||
@ -343,6 +343,9 @@ class OutputRecord extends ByteArrayOutputStream implements Record {
|
||||
* example, Netscape Commerce 1.0 servers. The V3 message is in the
|
||||
* header and the bytes passed as parameter. This routine translates
|
||||
* the V3 message into an equivalent V2 one.
|
||||
*
|
||||
* Note that the translation will strip off all hello extensions as
|
||||
* SSL V2.0 does not support hello extension.
|
||||
*/
|
||||
private void V3toV2ClientHello(byte v3Msg []) throws SSLException {
|
||||
int v3SessionIdLenOffset = 2 + 32; // version + nonce
|
||||
@ -361,12 +364,21 @@ class OutputRecord extends ByteArrayOutputStream implements Record {
|
||||
int v3CipherSpecOffset = v3CipherSpecLenOffset + 2; // skip length
|
||||
int v2CipherSpecLen = 0;
|
||||
count = 11;
|
||||
boolean containsRenegoInfoSCSV = false;
|
||||
for (int i = 0; i < cipherSpecs; i++) {
|
||||
byte byte1, byte2;
|
||||
|
||||
byte1 = v3Msg[v3CipherSpecOffset++];
|
||||
byte2 = v3Msg[v3CipherSpecOffset++];
|
||||
v2CipherSpecLen += V3toV2CipherSuite(byte1, byte2);
|
||||
if (!containsRenegoInfoSCSV &&
|
||||
byte1 == (byte)0x00 && byte2 == (byte)0xFF) {
|
||||
containsRenegoInfoSCSV = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!containsRenegoInfoSCSV) {
|
||||
v2CipherSpecLen += V3toV2CipherSuite((byte)0x00, (byte)0xFF);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@ -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
|
||||
@ -275,6 +275,12 @@ final public class SSLEngineImpl extends SSLEngine {
|
||||
private CipherBox readCipher, writeCipher;
|
||||
// NOTE: compression state would be saved here
|
||||
|
||||
/*
|
||||
* security parameters for secure renegotiation.
|
||||
*/
|
||||
private boolean secureRenegotiation;
|
||||
private byte[] clientVerifyData;
|
||||
private byte[] serverVerifyData;
|
||||
|
||||
/*
|
||||
* READ ME * READ ME * READ ME * READ ME * READ ME * READ ME *
|
||||
@ -356,6 +362,11 @@ final public class SSLEngineImpl extends SSLEngine {
|
||||
writeCipher = CipherBox.NULL;
|
||||
writeMAC = MAC.NULL;
|
||||
|
||||
// default security parameters for secure renegotiation
|
||||
secureRenegotiation = false;
|
||||
clientVerifyData = new byte[0];
|
||||
serverVerifyData = new byte[0];
|
||||
|
||||
enabledCipherSuites = CipherSuiteList.getDefault();
|
||||
enabledProtocols = ProtocolList.getDefault();
|
||||
|
||||
@ -434,11 +445,14 @@ final public class SSLEngineImpl extends SSLEngine {
|
||||
}
|
||||
if (roleIsServer) {
|
||||
handshaker = new ServerHandshaker(this, sslContext,
|
||||
enabledProtocols, doClientAuth,
|
||||
connectionState == cs_RENEGOTIATE, protocolVersion);
|
||||
enabledProtocols, doClientAuth,
|
||||
protocolVersion, connectionState == cs_HANDSHAKE,
|
||||
secureRenegotiation, clientVerifyData, serverVerifyData);
|
||||
} else {
|
||||
handshaker = new ClientHandshaker(this, sslContext,
|
||||
enabledProtocols, protocolVersion);
|
||||
enabledProtocols,
|
||||
protocolVersion, connectionState == cs_HANDSHAKE,
|
||||
secureRenegotiation, clientVerifyData, serverVerifyData);
|
||||
}
|
||||
handshaker.enabledCipherSuites = enabledCipherSuites;
|
||||
handshaker.setEnableSessionCreation(enableSessionCreation);
|
||||
@ -640,8 +654,16 @@ final public class SSLEngineImpl extends SSLEngine {
|
||||
break;
|
||||
|
||||
case cs_DATA:
|
||||
if (!Handshaker.renegotiable) {
|
||||
throw new SSLHandshakeException("renegotiation is not allowed");
|
||||
if (!secureRenegotiation && !Handshaker.allowUnsafeRenegotiation) {
|
||||
throw new SSLHandshakeException(
|
||||
"Insecure renegotiation is not allowed");
|
||||
}
|
||||
|
||||
if (!secureRenegotiation) {
|
||||
if (debug != null && Debug.isOn("handshake")) {
|
||||
System.out.println(
|
||||
"Warning: Using insecure renegotiation");
|
||||
}
|
||||
}
|
||||
|
||||
// initialize the handshaker, move to cs_RENEGOTIATE
|
||||
@ -978,6 +1000,12 @@ final public class SSLEngineImpl extends SSLEngine {
|
||||
connectionState = cs_DATA;
|
||||
}
|
||||
} else if (handshaker.isDone()) {
|
||||
// reset the parameters for secure renegotiation.
|
||||
secureRenegotiation =
|
||||
handshaker.isSecureRenegotiation();
|
||||
clientVerifyData = handshaker.getClientVerifyData();
|
||||
serverVerifyData = handshaker.getServerVerifyData();
|
||||
|
||||
sess = handshaker.getSession();
|
||||
if (!writer.hasOutboundData()) {
|
||||
hsStatus = HandshakeStatus.FINISHED;
|
||||
|
||||
@ -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
|
||||
@ -307,8 +307,9 @@ class SSLServerSocketImpl extends SSLServerSocket
|
||||
try {
|
||||
ServerHandshaker handshaker = tmp.getServerHandshaker();
|
||||
|
||||
for (Iterator t = enabledCipherSuites.iterator(); t.hasNext(); ) {
|
||||
CipherSuite suite = (CipherSuite)t.next();
|
||||
for (Iterator<CipherSuite> t = enabledCipherSuites.iterator();
|
||||
t.hasNext();) {
|
||||
CipherSuite suite = t.next();
|
||||
if (handshaker.trySetCipherSuite(suite)) {
|
||||
checkedEnabled = true;
|
||||
return;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2009, 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
|
||||
@ -275,9 +275,9 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||
* This is necessary so that processing of close_notify alerts
|
||||
* from the peer are handled properly.
|
||||
*/
|
||||
private Object handshakeLock;
|
||||
ReentrantLock writeLock;
|
||||
private Object readLock;
|
||||
final private Object handshakeLock = new Object();
|
||||
final ReentrantLock writeLock = new ReentrantLock();
|
||||
final private Object readLock = new Object();
|
||||
|
||||
private InputRecord inrec;
|
||||
|
||||
@ -288,6 +288,13 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||
private CipherBox readCipher, writeCipher;
|
||||
// NOTE: compression state would be saved here
|
||||
|
||||
/*
|
||||
* security parameters for secure renegotiation.
|
||||
*/
|
||||
private boolean secureRenegotiation;
|
||||
private byte[] clientVerifyData;
|
||||
private byte[] serverVerifyData;
|
||||
|
||||
/*
|
||||
* The authentication context holds all information used to establish
|
||||
* who this end of the connection is (certificate chains, private keys,
|
||||
@ -528,11 +535,13 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||
writeCipher = CipherBox.NULL;
|
||||
writeMAC = MAC.NULL;
|
||||
|
||||
// initial security parameters for secure renegotiation
|
||||
secureRenegotiation = false;
|
||||
clientVerifyData = new byte[0];
|
||||
serverVerifyData = new byte[0];
|
||||
|
||||
enabledCipherSuites = CipherSuiteList.getDefault();
|
||||
enabledProtocols = ProtocolList.getDefault();
|
||||
handshakeLock = new Object();
|
||||
writeLock = new ReentrantLock();
|
||||
readLock = new Object();
|
||||
inrec = null;
|
||||
|
||||
// save the acc
|
||||
@ -914,6 +923,12 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||
connectionState = cs_DATA;
|
||||
}
|
||||
} else if (handshaker.isDone()) {
|
||||
// reset the parameters for secure renegotiation.
|
||||
secureRenegotiation =
|
||||
handshaker.isSecureRenegotiation();
|
||||
clientVerifyData = handshaker.getClientVerifyData();
|
||||
serverVerifyData = handshaker.getServerVerifyData();
|
||||
|
||||
sess = handshaker.getSession();
|
||||
handshaker = null;
|
||||
connectionState = cs_DATA;
|
||||
@ -1091,11 +1106,14 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||
}
|
||||
if (roleIsServer) {
|
||||
handshaker = new ServerHandshaker(this, sslContext,
|
||||
enabledProtocols, doClientAuth,
|
||||
connectionState == cs_RENEGOTIATE, protocolVersion);
|
||||
enabledProtocols, doClientAuth,
|
||||
protocolVersion, connectionState == cs_HANDSHAKE,
|
||||
secureRenegotiation, clientVerifyData, serverVerifyData);
|
||||
} else {
|
||||
handshaker = new ClientHandshaker(this, sslContext,
|
||||
enabledProtocols, protocolVersion);
|
||||
enabledProtocols,
|
||||
protocolVersion, connectionState == cs_HANDSHAKE,
|
||||
secureRenegotiation, clientVerifyData, serverVerifyData);
|
||||
}
|
||||
handshaker.enabledCipherSuites = enabledCipherSuites;
|
||||
handshaker.setEnableSessionCreation(enableSessionCreation);
|
||||
@ -1200,8 +1218,16 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||
break;
|
||||
|
||||
case cs_DATA:
|
||||
if (!Handshaker.renegotiable) {
|
||||
throw new SSLHandshakeException("renegotiation is not allowed");
|
||||
if (!secureRenegotiation && !Handshaker.allowUnsafeRenegotiation) {
|
||||
throw new SSLHandshakeException(
|
||||
"Insecure renegotiation is not allowed");
|
||||
}
|
||||
|
||||
if (!secureRenegotiation) {
|
||||
if (debug != null && Debug.isOn("handshake")) {
|
||||
System.out.println(
|
||||
"Warning: Using insecure renegotiation");
|
||||
}
|
||||
}
|
||||
|
||||
// initialize the handshaker, move to cs_RENEGOTIATE
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2009, 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
|
||||
@ -69,9 +69,6 @@ final class ServerHandshaker extends Handshaker {
|
||||
// flag to check for clientCertificateVerify message
|
||||
private boolean needClientVerify = false;
|
||||
|
||||
// indicate a renegotiation handshaking
|
||||
private boolean isRenegotiation = false;
|
||||
|
||||
/*
|
||||
* For exportable ciphersuites using non-exportable key sizes, we use
|
||||
* ephemeral RSA keys. We could also do anonymous RSA in the same way
|
||||
@ -100,13 +97,15 @@ final class ServerHandshaker extends Handshaker {
|
||||
*/
|
||||
ServerHandshaker(SSLSocketImpl socket, SSLContextImpl context,
|
||||
ProtocolList enabledProtocols, byte clientAuth,
|
||||
boolean isRenegotiation, ProtocolVersion activeProtocolVersion) {
|
||||
ProtocolVersion activeProtocolVersion, boolean isInitialHandshake,
|
||||
boolean secureRenegotiation,
|
||||
byte[] clientVerifyData, byte[] serverVerifyData) {
|
||||
|
||||
super(socket, context, enabledProtocols,
|
||||
(clientAuth != SSLEngineImpl.clauth_none), false);
|
||||
(clientAuth != SSLEngineImpl.clauth_none), false,
|
||||
activeProtocolVersion, isInitialHandshake, secureRenegotiation,
|
||||
clientVerifyData, serverVerifyData);
|
||||
doClientAuth = clientAuth;
|
||||
this.isRenegotiation = isRenegotiation;
|
||||
this.activeProtocolVersion = activeProtocolVersion;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -114,13 +113,15 @@ final class ServerHandshaker extends Handshaker {
|
||||
*/
|
||||
ServerHandshaker(SSLEngineImpl engine, SSLContextImpl context,
|
||||
ProtocolList enabledProtocols, byte clientAuth,
|
||||
boolean isRenegotiation, ProtocolVersion activeProtocolVersion) {
|
||||
ProtocolVersion activeProtocolVersion,
|
||||
boolean isInitialHandshake, boolean secureRenegotiation,
|
||||
byte[] clientVerifyData, byte[] serverVerifyData) {
|
||||
|
||||
super(engine, context, enabledProtocols,
|
||||
(clientAuth != SSLEngineImpl.clauth_none), false);
|
||||
(clientAuth != SSLEngineImpl.clauth_none), false,
|
||||
activeProtocolVersion, isInitialHandshake, secureRenegotiation,
|
||||
clientVerifyData, serverVerifyData);
|
||||
doClientAuth = clientAuth;
|
||||
this.isRenegotiation = isRenegotiation;
|
||||
this.activeProtocolVersion = activeProtocolVersion;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -269,41 +270,122 @@ final class ServerHandshaker extends Handshaker {
|
||||
mesg.print(System.out);
|
||||
}
|
||||
|
||||
// if it is a renegotiation request and renegotiation is not allowed
|
||||
if (isRenegotiation && !renegotiable) {
|
||||
if (activeProtocolVersion.v >= ProtocolVersion.TLS10.v) {
|
||||
// response with a no_negotiation warning,
|
||||
warningSE(Alerts.alert_no_negotiation);
|
||||
// Does the message include security renegotiation indication?
|
||||
boolean renegotiationIndicated = false;
|
||||
|
||||
// invalidate the handshake so that the caller can
|
||||
// dispose this object.
|
||||
invalidated = true;
|
||||
|
||||
// If there is still unread block in the handshake
|
||||
// input stream, it would be truncated with the disposal
|
||||
// and the next handshake message will become incomplete.
|
||||
//
|
||||
// However, according to SSL/TLS specifications, no more
|
||||
// handshake message could immediately follow ClientHello
|
||||
// or HelloRequest. But in case of any improper messages,
|
||||
// we'd better check to ensure there is no remaining bytes
|
||||
// in the handshake input stream.
|
||||
if (input.available() > 0) {
|
||||
fatalSE(Alerts.alert_unexpected_message,
|
||||
"ClientHello followed by an unexpected " +
|
||||
"handshake message");
|
||||
// check the TLS_EMPTY_RENEGOTIATION_INFO_SCSV
|
||||
CipherSuiteList cipherSuites = mesg.getCipherSuites();
|
||||
if (cipherSuites.contains(CipherSuite.C_SCSV)) {
|
||||
renegotiationIndicated = true;
|
||||
if (isInitialHandshake) {
|
||||
secureRenegotiation = true;
|
||||
} else {
|
||||
// abort the handshake with a fatal handshake_failure alert
|
||||
if (secureRenegotiation) {
|
||||
fatalSE(Alerts.alert_handshake_failure,
|
||||
"The SCSV is present in a secure renegotiation");
|
||||
} else {
|
||||
fatalSE(Alerts.alert_handshake_failure,
|
||||
"The SCSV is present in a insecure renegotiation");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check the "renegotiation_info" extension
|
||||
RenegotiationInfoExtension clientHelloRI = (RenegotiationInfoExtension)
|
||||
mesg.extensions.get(ExtensionType.EXT_RENEGOTIATION_INFO);
|
||||
if (clientHelloRI != null) {
|
||||
renegotiationIndicated = true;
|
||||
if (isInitialHandshake) {
|
||||
// verify the length of the "renegotiated_connection" field
|
||||
if (!clientHelloRI.isEmpty()) {
|
||||
// abort the handshake with a fatal handshake_failure alert
|
||||
fatalSE(Alerts.alert_handshake_failure,
|
||||
"The renegotiation_info field is not empty");
|
||||
}
|
||||
|
||||
return;
|
||||
secureRenegotiation = true;
|
||||
} else {
|
||||
// For SSLv3, send the handshake_failure fatal error.
|
||||
// Note that SSLv3 does not define a no_negotiation alert
|
||||
// like TLSv1. However we cannot ignore the message
|
||||
// simply, otherwise the other side was waiting for a
|
||||
// response that would never come.
|
||||
fatalSE(Alerts.alert_handshake_failure,
|
||||
"renegotiation is not allowed");
|
||||
if (!secureRenegotiation) {
|
||||
// unexpected RI extension for insecure renegotiation,
|
||||
// abort the handshake with a fatal handshake_failure alert
|
||||
fatalSE(Alerts.alert_handshake_failure,
|
||||
"The renegotiation_info is present in a insecure " +
|
||||
"renegotiation");
|
||||
}
|
||||
|
||||
// verify the client_verify_data value
|
||||
if (!Arrays.equals(clientVerifyData,
|
||||
clientHelloRI.getRenegotiatedConnection())) {
|
||||
fatalSE(Alerts.alert_handshake_failure,
|
||||
"Incorrect verify data in ClientHello " +
|
||||
"renegotiation_info message");
|
||||
}
|
||||
}
|
||||
} else if (!isInitialHandshake && secureRenegotiation) {
|
||||
// if the connection's "secure_renegotiation" flag is set to TRUE
|
||||
// and the "renegotiation_info" extension is not present, abort
|
||||
// the handshake.
|
||||
fatalSE(Alerts.alert_handshake_failure,
|
||||
"Inconsistent secure renegotiation indication");
|
||||
}
|
||||
|
||||
// if there is no security renegotiation indication or the previous
|
||||
// handshake is insecure.
|
||||
if (!renegotiationIndicated || !secureRenegotiation) {
|
||||
if (isInitialHandshake) {
|
||||
if (!allowLegacyHelloMessages) {
|
||||
// abort the handshake with a fatal handshake_failure alert
|
||||
fatalSE(Alerts.alert_handshake_failure,
|
||||
"Failed to negotiate the use of secure renegotiation");
|
||||
}
|
||||
|
||||
// continue with legacy ClientHello
|
||||
if (debug != null && Debug.isOn("handshake")) {
|
||||
System.out.println("Warning: No renegotiation " +
|
||||
"indication in ClientHello, allow legacy ClientHello");
|
||||
}
|
||||
} else if (!allowUnsafeRenegotiation) {
|
||||
// abort the handshake
|
||||
if (activeProtocolVersion.v >= ProtocolVersion.TLS10.v) {
|
||||
// response with a no_renegotiation warning,
|
||||
warningSE(Alerts.alert_no_renegotiation);
|
||||
|
||||
// invalidate the handshake so that the caller can
|
||||
// dispose this object.
|
||||
invalidated = true;
|
||||
|
||||
// If there is still unread block in the handshake
|
||||
// input stream, it would be truncated with the disposal
|
||||
// and the next handshake message will become incomplete.
|
||||
//
|
||||
// However, according to SSL/TLS specifications, no more
|
||||
// handshake message could immediately follow ClientHello
|
||||
// or HelloRequest. But in case of any improper messages,
|
||||
// we'd better check to ensure there is no remaining bytes
|
||||
// in the handshake input stream.
|
||||
if (input.available() > 0) {
|
||||
fatalSE(Alerts.alert_unexpected_message,
|
||||
"ClientHello followed by an unexpected " +
|
||||
"handshake message");
|
||||
}
|
||||
|
||||
return;
|
||||
} else {
|
||||
// For SSLv3, send the handshake_failure fatal error.
|
||||
// Note that SSLv3 does not define a no_renegotiation
|
||||
// alert like TLSv1. However we cannot ignore the message
|
||||
// simply, otherwise the other side was waiting for a
|
||||
// response that would never come.
|
||||
fatalSE(Alerts.alert_handshake_failure,
|
||||
"Renegotiation is not allowed");
|
||||
}
|
||||
} else { // !isInitialHandshake && allowUnsafeRenegotiation
|
||||
// continue with unsafe renegotiation.
|
||||
if (debug != null && Debug.isOn("handshake")) {
|
||||
System.out.println(
|
||||
"Warning: continue with insecure renegotiation");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -454,7 +536,7 @@ final class ServerHandshaker extends Handshaker {
|
||||
// verify that the ciphersuite from the cached session
|
||||
// is in the list of client requested ciphersuites and
|
||||
// we have it enabled
|
||||
if ((isEnabled(suite) == false) ||
|
||||
if ((isNegotiable(suite) == false) ||
|
||||
(mesg.getCipherSuites().contains(suite) == false)) {
|
||||
resumingSession = false;
|
||||
} else {
|
||||
@ -484,8 +566,8 @@ final class ServerHandshaker extends Handshaker {
|
||||
if (!enableNewSession) {
|
||||
throw new SSLException("Client did not resume a session");
|
||||
}
|
||||
supportedCurves = (SupportedEllipticCurvesExtension)mesg.extensions.get
|
||||
(ExtensionType.EXT_ELLIPTIC_CURVES);
|
||||
supportedCurves = (SupportedEllipticCurvesExtension)
|
||||
mesg.extensions.get(ExtensionType.EXT_ELLIPTIC_CURVES);
|
||||
chooseCipherSuite(mesg);
|
||||
session = new SSLSessionImpl(protocolVersion, cipherSuite,
|
||||
sslContext.getSecureRandom(),
|
||||
@ -498,6 +580,21 @@ final class ServerHandshaker extends Handshaker {
|
||||
m1.sessionId = session.getSessionId();
|
||||
m1.compression_method = session.getCompression();
|
||||
|
||||
if (secureRenegotiation) {
|
||||
// For ServerHellos that are initial handshakes, then the
|
||||
// "renegotiated_connection" field in "renegotiation_info"
|
||||
// extension is of zero length.
|
||||
//
|
||||
// For ServerHellos that are renegotiating, this field contains
|
||||
// the concatenation of client_verify_data and server_verify_data.
|
||||
//
|
||||
// Note that for initial handshakes, both the clientVerifyData
|
||||
// variable and serverVerifyData variable are of zero length.
|
||||
HelloExtension serverHelloRI = new RenegotiationInfoExtension(
|
||||
clientVerifyData, serverVerifyData);
|
||||
m1.extensions.add(serverHelloRI);
|
||||
}
|
||||
|
||||
if (debug != null && Debug.isOn("handshake")) {
|
||||
m1.print(System.out);
|
||||
System.out.println("Cipher suite: " + session.getSuite());
|
||||
@ -686,11 +783,13 @@ final class ServerHandshaker extends Handshaker {
|
||||
*/
|
||||
private void chooseCipherSuite(ClientHello mesg) throws IOException {
|
||||
for (CipherSuite suite : mesg.getCipherSuites().collection()) {
|
||||
if (isEnabled(suite) == false) {
|
||||
if (isNegotiable(suite) == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (doClientAuth == SSLEngineImpl.clauth_required) {
|
||||
if ((suite.keyExchange == K_DH_ANON) || (suite.keyExchange == K_ECDH_ANON)) {
|
||||
if ((suite.keyExchange == K_DH_ANON) ||
|
||||
(suite.keyExchange == K_ECDH_ANON)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -728,7 +827,7 @@ final class ServerHandshaker extends Handshaker {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (suite.isAvailable() == false) {
|
||||
if (suite.isNegotiable() == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1135,6 +1234,13 @@ final class ServerHandshaker extends Handshaker {
|
||||
// NOTREACHED
|
||||
}
|
||||
|
||||
/*
|
||||
* save client verify data for secure renegotiation
|
||||
*/
|
||||
if (secureRenegotiation) {
|
||||
clientVerifyData = mesg.getVerifyData();
|
||||
}
|
||||
|
||||
/*
|
||||
* OK, it verified. If we're doing the full handshake, add that
|
||||
* "Finished" message to the hash of handshake messages, then send
|
||||
@ -1184,6 +1290,13 @@ final class ServerHandshaker extends Handshaker {
|
||||
*/
|
||||
sendChangeCipherSpec(mesg, finishedTag);
|
||||
|
||||
/*
|
||||
* save server verify data for secure renegotiation
|
||||
*/
|
||||
if (secureRenegotiation) {
|
||||
serverVerifyData = mesg.getVerifyData();
|
||||
}
|
||||
|
||||
/*
|
||||
* Update state machine so client MUST send 'finished' next
|
||||
* The update should only take place if it is not in the fast
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2005, 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
|
||||
@ -114,10 +114,11 @@ public class CipherTest {
|
||||
}
|
||||
|
||||
boolean isEnabled() {
|
||||
// return cipherSuite.equals("SSL_RSA_WITH_RC4_128_MD5") &&
|
||||
// (clientAuth != null);
|
||||
// return cipherSuite.indexOf("_RSA_") != -1;
|
||||
// return cipherSuite.indexOf("DH_anon") != -1;
|
||||
// ignore SCSV
|
||||
if (cipherSuite.equals("TLS_EMPTY_RENEGOTIATION_INFO_SCSV")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2006, 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
|
||||
@ -114,12 +114,11 @@ public class CipherTest {
|
||||
}
|
||||
|
||||
boolean isEnabled() {
|
||||
// if (true) return cipherSuite.contains("_ECDH_");
|
||||
// return cipherSuite.equals("SSL_RSA_WITH_RC4_128_MD5") &&
|
||||
// (clientAuth != null);
|
||||
// return cipherSuite.indexOf("_RSA_") != -1;
|
||||
// return cipherSuite.indexOf("DH_anon") != -1;
|
||||
// return cipherSuite.contains("ECDSA") == false;
|
||||
// ignore SCSV
|
||||
if (cipherSuite.equals("TLS_EMPTY_RENEGOTIATION_INFO_SCSV")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 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
|
||||
@ -25,8 +25,6 @@
|
||||
* @test
|
||||
* @bug 4403428
|
||||
* @summary Invalidating JSSE session on server causes SSLProtocolException
|
||||
* @ignore incompatible with disabled unsafe renegotiation (6898739), please
|
||||
* reenable when safe renegotiation is implemented.
|
||||
* @author Brad Wetmore
|
||||
*/
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 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
|
||||
@ -26,8 +26,6 @@
|
||||
* @bug 4280338
|
||||
* @summary "Unsupported SSL message version" SSLProtocolException
|
||||
* w/SSL_RSA_WITH_NULL_MD5
|
||||
* @ignore incompatible with disabled unsafe renegotiation (6898739), please
|
||||
* reenable when safe renegotiation is implemented.
|
||||
*
|
||||
* @author Ram Marti
|
||||
* @author Brad Wetmore
|
||||
|
||||
@ -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
|
||||
@ -25,8 +25,6 @@
|
||||
* @test
|
||||
* @bug 4948079
|
||||
* @summary SSLEngineResult needs updating [none yet]
|
||||
* @ignore incompatible with disabled unsafe renegotiation (6898739), please
|
||||
* reenable when safe renegotiation is implemented.
|
||||
*
|
||||
* This is a simple hack to test a bunch of conditions and check
|
||||
* their return codes.
|
||||
|
||||
@ -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
|
||||
@ -26,8 +26,6 @@
|
||||
* @bug 4495742
|
||||
* @summary Add non-blocking SSL/TLS functionality, usable with any
|
||||
* I/O abstraction
|
||||
* @ignore incompatible with disabled unsafe renegotiation (6898739), please
|
||||
* reenable when safe renegotiation is implemented.
|
||||
*
|
||||
* This is a bit hacky, meant to test various conditions. The main
|
||||
* thing I wanted to do with this was to do buffer reads/writes
|
||||
|
||||
@ -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
|
||||
@ -25,8 +25,6 @@
|
||||
* @test
|
||||
* @bug 4495742
|
||||
* @summary Demonstrate SSLEngine switch from no client auth to client auth.
|
||||
* @ignore incompatible with disabled unsafe renegotiation (6898739), please
|
||||
* reenable when safe renegotiation is implemented.
|
||||
*
|
||||
* @author Brad R. Wetmore
|
||||
*/
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2005, 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
|
||||
@ -119,6 +119,15 @@ public class TestAllSuites {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't run the SCSV suite
|
||||
*/
|
||||
if (suite.equals("TLS_EMPTY_RENEGOTIATION_INFO_SCSV")) {
|
||||
System.out.println("Ignoring SCSV suite");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!suite.contains("DH_anon")) {
|
||||
ssle2.setNeedClientAuth(true);
|
||||
}
|
||||
|
||||
@ -64,6 +64,8 @@ public class CheckCipherSuites {
|
||||
"SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
|
||||
"SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
|
||||
"SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
|
||||
"TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
|
||||
|
||||
};
|
||||
|
||||
private final static String[] ENABLED_UNLIMITED = {
|
||||
@ -101,6 +103,8 @@ public class CheckCipherSuites {
|
||||
"SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
|
||||
"SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
|
||||
"SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
|
||||
"TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
|
||||
|
||||
};
|
||||
|
||||
// supported ciphersuites using default JCE policy jurisdiction files
|
||||
@ -133,6 +137,7 @@ public class CheckCipherSuites {
|
||||
"SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
|
||||
"SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
|
||||
"SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
|
||||
"TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
|
||||
|
||||
"SSL_RSA_WITH_NULL_MD5",
|
||||
"SSL_RSA_WITH_NULL_SHA",
|
||||
@ -160,6 +165,7 @@ public class CheckCipherSuites {
|
||||
"TLS_KRB5_EXPORT_WITH_RC4_40_MD5",
|
||||
"TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA",
|
||||
"TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5",
|
||||
|
||||
};
|
||||
|
||||
// supported ciphersuites using unlimited JCE policy jurisdiction files
|
||||
@ -199,6 +205,7 @@ public class CheckCipherSuites {
|
||||
"SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
|
||||
"SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
|
||||
"SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
|
||||
"TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
|
||||
|
||||
"SSL_RSA_WITH_NULL_MD5",
|
||||
"SSL_RSA_WITH_NULL_SHA",
|
||||
@ -228,6 +235,7 @@ public class CheckCipherSuites {
|
||||
"TLS_KRB5_EXPORT_WITH_RC4_40_MD5",
|
||||
"TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA",
|
||||
"TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5",
|
||||
|
||||
};
|
||||
|
||||
private static void showSuites(String[] suites) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2005, 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
|
||||
@ -115,10 +115,11 @@ public class CipherTest {
|
||||
}
|
||||
|
||||
boolean isEnabled() {
|
||||
// return cipherSuite.equals("SSL_RSA_WITH_RC4_128_MD5") &&
|
||||
// (clientAuth != null);
|
||||
// return cipherSuite.indexOf("_RSA_") != -1;
|
||||
// return cipherSuite.indexOf("DH_anon") != -1;
|
||||
// ignore SCSV
|
||||
if (cipherSuite.equals("TLS_EMPTY_RENEGOTIATION_INFO_SCSV")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user