提交 ce33a12d 编写于 作者: M mullan

Merge

/* /*
* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -165,16 +165,18 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi { ...@@ -165,16 +165,18 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
// partition keyblock into individual secrets // partition keyblock into individual secrets
int ofs = 0; int ofs = 0;
byte[] tmp = new byte[macLength]; if (macLength != 0) {
byte[] tmp = new byte[macLength];
// mac keys // mac keys
System.arraycopy(keyBlock, ofs, tmp, 0, macLength); System.arraycopy(keyBlock, ofs, tmp, 0, macLength);
ofs += macLength; ofs += macLength;
clientMacKey = new SecretKeySpec(tmp, "Mac"); clientMacKey = new SecretKeySpec(tmp, "Mac");
System.arraycopy(keyBlock, ofs, tmp, 0, macLength); System.arraycopy(keyBlock, ofs, tmp, 0, macLength);
ofs += macLength; ofs += macLength;
serverMacKey = new SecretKeySpec(tmp, "Mac"); serverMacKey = new SecretKeySpec(tmp, "Mac");
}
if (keyLength == 0) { // SSL_RSA_WITH_NULL_* ciphersuites if (keyLength == 0) { // SSL_RSA_WITH_NULL_* ciphersuites
return new TlsKeyMaterialSpec(clientMacKey, serverMacKey); return new TlsKeyMaterialSpec(clientMacKey, serverMacKey);
...@@ -198,7 +200,7 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi { ...@@ -198,7 +200,7 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
// IV keys if needed. // IV keys if needed.
if (ivLength != 0) { if (ivLength != 0) {
tmp = new byte[ivLength]; byte[] tmp = new byte[ivLength];
System.arraycopy(keyBlock, ofs, tmp, 0, ivLength); System.arraycopy(keyBlock, ofs, tmp, 0, ivLength);
ofs += ivLength; ofs += ivLength;
...@@ -220,8 +222,8 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi { ...@@ -220,8 +222,8 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
// TLS 1.0 // TLS 1.0
byte[] seed = concat(clientRandom, serverRandom); byte[] seed = concat(clientRandom, serverRandom);
tmp = doTLS10PRF(clientKeyBytes, LABEL_CLIENT_WRITE_KEY, seed, byte[] tmp = doTLS10PRF(clientKeyBytes,
expandedKeyLength, md5, sha); LABEL_CLIENT_WRITE_KEY, seed, expandedKeyLength, md5, sha);
clientCipherKey = new SecretKeySpec(tmp, alg); clientCipherKey = new SecretKeySpec(tmp, alg);
tmp = doTLS10PRF(serverKeyBytes, LABEL_SERVER_WRITE_KEY, seed, tmp = doTLS10PRF(serverKeyBytes, LABEL_SERVER_WRITE_KEY, seed,
...@@ -239,7 +241,7 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi { ...@@ -239,7 +241,7 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
} }
} else { } else {
// SSLv3 // SSLv3
tmp = new byte[expandedKeyLength]; byte[] tmp = new byte[expandedKeyLength];
md5.update(clientKeyBytes); md5.update(clientKeyBytes);
md5.update(clientRandom); md5.update(clientRandom);
......
/* /*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -212,12 +212,6 @@ public class TlsKeyMaterialParameterSpec implements AlgorithmParameterSpec { ...@@ -212,12 +212,6 @@ public class TlsKeyMaterialParameterSpec implements AlgorithmParameterSpec {
* generated. * generated.
*/ */
public int getIvLength() { public int getIvLength() {
// TLS v1.1 or later uses an explicit IV to protect against
// the CBC attacks.
if (majorVersion >= 0x03 && minorVersion >= 0x02) {
return 0;
}
return ivLength; return ivLength;
} }
......
/* /*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -58,9 +58,8 @@ public class TlsKeyMaterialSpec implements KeySpec, SecretKey { ...@@ -58,9 +58,8 @@ public class TlsKeyMaterialSpec implements KeySpec, SecretKey {
* <code>new TlsKeymaterialSpec(clientMacKey, serverMacKey, * <code>new TlsKeymaterialSpec(clientMacKey, serverMacKey,
* null, null, null, null)</code>. * null, null, null, null)</code>.
* *
* @param clientMacKey the client MAC key * @param clientMacKey the client MAC key (or null)
* @param serverMacKey the server MAC key * @param serverMacKey the server MAC key (or null)
* @throws NullPointerException if clientMacKey or serverMacKey is null
*/ */
public TlsKeyMaterialSpec(SecretKey clientMacKey, SecretKey serverMacKey) { public TlsKeyMaterialSpec(SecretKey clientMacKey, SecretKey serverMacKey) {
this(clientMacKey, serverMacKey, null, null, null, null); this(clientMacKey, serverMacKey, null, null, null, null);
...@@ -73,11 +72,10 @@ public class TlsKeyMaterialSpec implements KeySpec, SecretKey { ...@@ -73,11 +72,10 @@ public class TlsKeyMaterialSpec implements KeySpec, SecretKey {
* <code>new TlsKeymaterialSpec(clientMacKey, serverMacKey, * <code>new TlsKeymaterialSpec(clientMacKey, serverMacKey,
* clientCipherKey, serverCipherKey, null, null)</code>. * clientCipherKey, serverCipherKey, null, null)</code>.
* *
* @param clientMacKey the client MAC key * @param clientMacKey the client MAC key (or null)
* @param serverMacKey the server MAC key * @param serverMacKey the server MAC key (or null)
* @param clientCipherKey the client cipher key (or null) * @param clientCipherKey the client cipher key (or null)
* @param serverCipherKey the server cipher key (or null) * @param serverCipherKey the server cipher key (or null)
* @throws NullPointerException if clientMacKey or serverMacKey is null
*/ */
public TlsKeyMaterialSpec(SecretKey clientMacKey, SecretKey serverMacKey, public TlsKeyMaterialSpec(SecretKey clientMacKey, SecretKey serverMacKey,
SecretKey clientCipherKey, SecretKey serverCipherKey) { SecretKey clientCipherKey, SecretKey serverCipherKey) {
...@@ -90,21 +88,17 @@ public class TlsKeyMaterialSpec implements KeySpec, SecretKey { ...@@ -90,21 +88,17 @@ public class TlsKeyMaterialSpec implements KeySpec, SecretKey {
* keys, client and server cipher keys, and client and server * keys, client and server cipher keys, and client and server
* initialization vectors. * initialization vectors.
* *
* @param clientMacKey the client MAC key * @param clientMacKey the client MAC key (or null)
* @param serverMacKey the server MAC key * @param serverMacKey the server MAC key (or null)
* @param clientCipherKey the client cipher key (or null) * @param clientCipherKey the client cipher key (or null)
* @param clientIv the client initialization vector (or null) * @param clientIv the client initialization vector (or null)
* @param serverCipherKey the server cipher key (or null) * @param serverCipherKey the server cipher key (or null)
* @param serverIv the server initialization vector (or null) * @param serverIv the server initialization vector (or null)
*
* @throws NullPointerException if clientMacKey or serverMacKey is null
*/ */
public TlsKeyMaterialSpec(SecretKey clientMacKey, SecretKey serverMacKey, public TlsKeyMaterialSpec(SecretKey clientMacKey, SecretKey serverMacKey,
SecretKey clientCipherKey, IvParameterSpec clientIv, SecretKey clientCipherKey, IvParameterSpec clientIv,
SecretKey serverCipherKey, IvParameterSpec serverIv) { SecretKey serverCipherKey, IvParameterSpec serverIv) {
if ((clientMacKey == null) || (serverMacKey == null)) {
throw new NullPointerException("MAC keys must not be null");
}
this.clientMacKey = clientMacKey; this.clientMacKey = clientMacKey;
this.serverMacKey = serverMacKey; this.serverMacKey = serverMacKey;
this.clientCipherKey = clientCipherKey; this.clientCipherKey = clientCipherKey;
...@@ -143,7 +137,7 @@ public class TlsKeyMaterialSpec implements KeySpec, SecretKey { ...@@ -143,7 +137,7 @@ public class TlsKeyMaterialSpec implements KeySpec, SecretKey {
/** /**
* Returns the client MAC key. * Returns the client MAC key.
* *
* @return the client MAC key. * @return the client MAC key (or null).
*/ */
public SecretKey getClientMacKey() { public SecretKey getClientMacKey() {
return clientMacKey; return clientMacKey;
...@@ -152,7 +146,7 @@ public class TlsKeyMaterialSpec implements KeySpec, SecretKey { ...@@ -152,7 +146,7 @@ public class TlsKeyMaterialSpec implements KeySpec, SecretKey {
/** /**
* Return the server MAC key. * Return the server MAC key.
* *
* @return the server MAC key. * @return the server MAC key (or null).
*/ */
public SecretKey getServerMacKey() { public SecretKey getServerMacKey() {
return serverMacKey; return serverMacKey;
......
/* /*
* Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -168,10 +168,22 @@ public final class P11TlsKeyMaterialGenerator extends KeyGeneratorSpi { ...@@ -168,10 +168,22 @@ public final class P11TlsKeyMaterialGenerator extends KeyGeneratorSpi {
// Note that the MAC keys do not inherit all attributes from the // Note that the MAC keys do not inherit all attributes from the
// template, but they do inherit the sensitive/extractable/token // template, but they do inherit the sensitive/extractable/token
// flags, which is all P11Key cares about. // flags, which is all P11Key cares about.
SecretKey clientMacKey = P11Key.secretKey SecretKey clientMacKey, serverMacKey;
// The MAC size may be zero for GCM mode.
//
// PKCS11 does not support GCM mode as the author made the comment,
// so the macBits is unlikely to be zero. It's only a place holder.
if (macBits != 0) {
clientMacKey = P11Key.secretKey
(session, out.hClientMacSecret, "MAC", macBits, attributes); (session, out.hClientMacSecret, "MAC", macBits, attributes);
SecretKey serverMacKey = P11Key.secretKey serverMacKey = P11Key.secretKey
(session, out.hServerMacSecret, "MAC", macBits, attributes); (session, out.hServerMacSecret, "MAC", macBits, attributes);
} else {
clientMacKey = null;
serverMacKey = null;
}
SecretKey clientCipherKey, serverCipherKey; SecretKey clientCipherKey, serverCipherKey;
if (keyBits != 0) { if (keyBits != 0) {
clientCipherKey = P11Key.secretKey(session, out.hClientKey, clientCipherKey = P11Key.secretKey(session, out.hClientKey,
......
...@@ -89,7 +89,7 @@ public final class OCSP { ...@@ -89,7 +89,7 @@ public final class OCSP {
new GetIntegerAction("com.sun.security.ocsp.timeout", new GetIntegerAction("com.sun.security.ocsp.timeout",
DEFAULT_CONNECT_TIMEOUT)); DEFAULT_CONNECT_TIMEOUT));
if (tmp < 0) { if (tmp < 0) {
tmp = DEFAULT_CONNECT_TIMEOUT; return DEFAULT_CONNECT_TIMEOUT;
} }
// Convert to milliseconds, as the system property will be // Convert to milliseconds, as the system property will be
// specified in seconds // specified in seconds
......
/*
* Copyright (c) 2012, 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.
*/
package sun.security.ssl;
import java.util.Arrays;
/**
* This class represents an SSL/TLS message authentication token,
* which encapsulates a sequence number and ensures that attempts to
* delete or reorder messages can be detected.
*
* Each SSL/TLS connection state contains a sequence number, which
* is maintained separately for read and write states. The sequence
* number MUST be set to zero whenever a connection state is made the
* active state. Sequence numbers are of type uint64 and may not
* exceed 2^64-1. Sequence numbers do not wrap. If a SSL/TLS
* implementation would need to wrap a sequence number, it must
* renegotiate instead. A sequence number is incremented after each
* record: specifically, the first record transmitted under a
* particular connection state MUST use sequence number 0.
*/
class Authenticator {
// byte array containing the additional authentication information for
// each record
private final byte[] block;
// the block size of SSL v3.0:
// sequence number + record type + + record length
private static final int BLOCK_SIZE_SSL = 8 + 1 + 2;
// the block size of TLS v1.0 and later:
// sequence number + record type + protocol version + record length
private static final int BLOCK_SIZE_TLS = 8 + 1 + 2 + 2;
/**
* Default construct, no message authentication token is initialized.
*
* Note that this construct can only be called for null MAC
*/
Authenticator() {
block = new byte[0];
}
/**
* Constructs the message authentication token for the specified
* SSL/TLS protocol.
*/
Authenticator(ProtocolVersion protocolVersion) {
if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
block = new byte[BLOCK_SIZE_TLS];
block[9] = protocolVersion.major;
block[10] = protocolVersion.minor;
} else {
block = new byte[BLOCK_SIZE_SSL];
}
}
/**
* Checks 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.
*
* @return true if the sequence number is close to wrap
*/
final boolean seqNumOverflow() {
/*
* Conservatively, we don't allow more records to be generated
* when there are only 2^8 sequence numbers left.
*/
return (block.length != 0 &&
block[0] == (byte)0xFF && block[1] == (byte)0xFF &&
block[2] == (byte)0xFF && block[3] == (byte)0xFF &&
block[4] == (byte)0xFF && block[5] == (byte)0xFF &&
block[6] == (byte)0xFF);
}
/**
* Checks whether the sequence number close to renew.
*
* 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 sequence number is huge enough to renew
*/
final boolean seqNumIsHuge() {
/*
* Conservatively, we should ask for renegotiation when there are
* only 2^48 sequence numbers left.
*/
return (block.length != 0 &&
block[0] == (byte)0xFF && block[1] == (byte)0xFF);
}
/**
* Gets the current sequence number.
*
* @return the byte array of the current sequence number
*/
final byte[] sequenceNumber() {
return Arrays.copyOf(block, 8);
}
/**
* Acquires the current message authentication information with the
* specified record type and fragment length, and then increases the
* sequence number.
*
* @param type the record type
* @param length the fragment of the record
* @return the byte array of the current message authentication information
*/
final byte[] acquireAuthenticationBytes(byte type, int length) {
byte[] copy = block.clone();
if (block.length != 0) {
copy[8] = type;
copy[copy.length - 2] = (byte)(length >> 8);
copy[copy.length - 1] = (byte)(length);
/*
* Increase the sequence number in the block array
* it is a 64-bit number stored in big-endian format
*/
int k = 7;
while ((k >= 0) && (++block[k] == 0)) {
k--;
}
}
return copy;
}
}
...@@ -33,12 +33,14 @@ import java.security.InvalidKeyException; ...@@ -33,12 +33,14 @@ import java.security.InvalidKeyException;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.security.KeyManagementException; import java.security.KeyManagementException;
import javax.crypto.Cipher;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.SecretKeySpec;
import static sun.security.ssl.CipherSuite.KeyExchange.*; import static sun.security.ssl.CipherSuite.KeyExchange.*;
import static sun.security.ssl.CipherSuite.PRF.*; import static sun.security.ssl.CipherSuite.PRF.*;
import static sun.security.ssl.CipherSuite.CipherType.*;
import static sun.security.ssl.JsseJce.*; import static sun.security.ssl.JsseJce.*;
/** /**
...@@ -135,7 +137,9 @@ final class CipherSuite implements Comparable<CipherSuite> { ...@@ -135,7 +137,9 @@ final class CipherSuite implements Comparable<CipherSuite> {
this.keyExchange = keyExchange; this.keyExchange = keyExchange;
this.cipher = cipher; this.cipher = cipher;
this.exportable = cipher.exportable; this.exportable = cipher.exportable;
if (name.endsWith("_MD5")) { if (cipher.cipherType == CipherType.AEAD_CIPHER) {
macAlg = M_NULL;
} else if (name.endsWith("_MD5")) {
macAlg = M_MD5; macAlg = M_MD5;
} else if (name.endsWith("_SHA")) { } else if (name.endsWith("_SHA")) {
macAlg = M_SHA; macAlg = M_SHA;
...@@ -385,6 +389,12 @@ final class CipherSuite implements Comparable<CipherSuite> { ...@@ -385,6 +389,12 @@ final class CipherSuite implements Comparable<CipherSuite> {
} }
} }
static enum CipherType {
STREAM_CIPHER, // null or stream cipher
BLOCK_CIPHER, // block cipher in CBC mode
AEAD_CIPHER // AEAD cipher
}
/** /**
* An SSL/TLS bulk cipher algorithm. One instance per combination of * An SSL/TLS bulk cipher algorithm. One instance per combination of
* cipher and key length. * cipher and key length.
...@@ -417,14 +427,26 @@ final class CipherSuite implements Comparable<CipherSuite> { ...@@ -417,14 +427,26 @@ final class CipherSuite implements Comparable<CipherSuite> {
// for non-exportable ciphers, this is the same as keySize // for non-exportable ciphers, this is the same as keySize
final int expandedKeySize; final int expandedKeySize;
// size of the IV (also block size) // size of the IV
final int ivSize; final int ivSize;
// size of fixed IV
//
// record_iv_length = ivSize - fixedIvSize
final int fixedIvSize;
// exportable under 512/40 bit rules // exportable under 512/40 bit rules
final boolean exportable; final boolean exportable;
// Is the cipher algorithm of Cipher Block Chaining (CBC) mode? // Is the cipher algorithm of Cipher Block Chaining (CBC) mode?
final boolean isCBCMode; final CipherType cipherType;
// size of the authentication tag, only applicable to cipher suites in
// Galois Counter Mode (GCM)
//
// As far as we know, all supported GCM cipher suites use 128-bits
// authentication tags.
final int tagSize = 16;
// The secure random used to detect the cipher availability. // The secure random used to detect the cipher availability.
private final static SecureRandom secureRandom; private final static SecureRandom secureRandom;
...@@ -437,32 +459,34 @@ final class CipherSuite implements Comparable<CipherSuite> { ...@@ -437,32 +459,34 @@ final class CipherSuite implements Comparable<CipherSuite> {
} }
} }
BulkCipher(String transformation, int keySize, BulkCipher(String transformation, CipherType cipherType, int keySize,
int expandedKeySize, int ivSize, boolean allowed) { int expandedKeySize, int ivSize,
int fixedIvSize, boolean allowed) {
this.transformation = transformation; this.transformation = transformation;
String[] splits = transformation.split("/"); String[] splits = transformation.split("/");
this.algorithm = splits[0]; this.algorithm = splits[0];
this.isCBCMode = this.cipherType = cipherType;
splits.length <= 1 ? false : "CBC".equalsIgnoreCase(splits[1]);
this.description = this.algorithm + "/" + (keySize << 3); this.description = this.algorithm + "/" + (keySize << 3);
this.keySize = keySize; this.keySize = keySize;
this.ivSize = ivSize; this.ivSize = ivSize;
this.fixedIvSize = fixedIvSize;
this.allowed = allowed; this.allowed = allowed;
this.expandedKeySize = expandedKeySize; this.expandedKeySize = expandedKeySize;
this.exportable = true; this.exportable = true;
} }
BulkCipher(String transformation, int keySize, BulkCipher(String transformation, CipherType cipherType, int keySize,
int ivSize, boolean allowed) { int ivSize, int fixedIvSize, boolean allowed) {
this.transformation = transformation; this.transformation = transformation;
String[] splits = transformation.split("/"); String[] splits = transformation.split("/");
this.algorithm = splits[0]; this.algorithm = splits[0];
this.isCBCMode = this.cipherType = cipherType;
splits.length <= 1 ? false : "CBC".equalsIgnoreCase(splits[1]);
this.description = this.algorithm + "/" + (keySize << 3); this.description = this.algorithm + "/" + (keySize << 3);
this.keySize = keySize; this.keySize = keySize;
this.ivSize = ivSize; this.ivSize = ivSize;
this.fixedIvSize = fixedIvSize;
this.allowed = allowed; this.allowed = allowed;
this.expandedKeySize = keySize; this.expandedKeySize = keySize;
...@@ -486,16 +510,20 @@ final class CipherSuite implements Comparable<CipherSuite> { ...@@ -486,16 +510,20 @@ final class CipherSuite implements Comparable<CipherSuite> {
* Test if this bulk cipher is available. For use by CipherSuite. * Test if this bulk cipher is available. For use by CipherSuite.
* *
* Currently all supported ciphers except AES are always available * Currently all supported ciphers except AES are always available
* via the JSSE internal implementations. We also assume AES/128 * via the JSSE internal implementations. We also assume AES/128 of
* is always available since it is shipped with the SunJCE provider. * CBC mode is always available since it is shipped with the SunJCE
* However, AES/256 is unavailable when the default JCE policy * provider. However, AES/256 is unavailable when the default JCE
* jurisdiction files are installed because of key length restrictions. * policy jurisdiction files are installed because of key length
* restrictions, and AEAD is unavailable when the underlying providers
* do not support AEAD/GCM mode.
*/ */
boolean isAvailable() { boolean isAvailable() {
if (allowed == false) { if (allowed == false) {
return false; return false;
} }
if (this == B_AES_256) {
if ((this == B_AES_256) ||
(this.cipherType == CipherType.AEAD_CIPHER)) {
return isAvailable(this); return isAvailable(this);
} }
...@@ -513,19 +541,50 @@ final class CipherSuite implements Comparable<CipherSuite> { ...@@ -513,19 +541,50 @@ final class CipherSuite implements Comparable<CipherSuite> {
private static synchronized boolean isAvailable(BulkCipher cipher) { private static synchronized boolean isAvailable(BulkCipher cipher) {
Boolean b = availableCache.get(cipher); Boolean b = availableCache.get(cipher);
if (b == null) { if (b == null) {
try { int keySizeInBits = cipher.keySize * 8;
SecretKey key = new SecretKeySpec if (keySizeInBits > 128) { // need the JCE unlimited
(new byte[cipher.expandedKeySize], cipher.algorithm); // strength jurisdiction policy
IvParameterSpec iv = try {
new IvParameterSpec(new byte[cipher.ivSize]); if (Cipher.getMaxAllowedKeyLength(
cipher.newCipher(ProtocolVersion.DEFAULT, cipher.transformation) < keySizeInBits) {
b = Boolean.FALSE;
}
} catch (Exception e) {
b = Boolean.FALSE;
}
}
if (b == null) {
b = Boolean.FALSE; // may be reset to TRUE if
// the cipher is available
CipherBox temporary = null;
try {
SecretKey key = new SecretKeySpec(
new byte[cipher.expandedKeySize],
cipher.algorithm);
IvParameterSpec iv;
if (cipher.cipherType == CipherType.AEAD_CIPHER) {
iv = new IvParameterSpec(
new byte[cipher.fixedIvSize]);
} else {
iv = new IvParameterSpec(new byte[cipher.ivSize]);
}
temporary = cipher.newCipher(
ProtocolVersion.DEFAULT,
key, iv, secureRandom, true); key, iv, secureRandom, true);
b = Boolean.TRUE; b = temporary.isAvailable();
} catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
b = Boolean.FALSE; // not available
} finally {
if (temporary != null) {
temporary.dispose();
}
}
} }
availableCache.put(cipher, b); availableCache.put(cipher, b);
} }
return b.booleanValue(); return b.booleanValue();
} }
...@@ -573,27 +632,31 @@ final class CipherSuite implements Comparable<CipherSuite> { ...@@ -573,27 +632,31 @@ final class CipherSuite implements Comparable<CipherSuite> {
// export strength ciphers // export strength ciphers
final static BulkCipher B_NULL = final static BulkCipher B_NULL =
new BulkCipher("NULL", 0, 0, 0, true); new BulkCipher("NULL", STREAM_CIPHER, 0, 0, 0, 0, true);
final static BulkCipher B_RC4_40 = final static BulkCipher B_RC4_40 =
new BulkCipher(CIPHER_RC4, 5, 16, 0, true); new BulkCipher(CIPHER_RC4, STREAM_CIPHER, 5, 16, 0, 0, true);
final static BulkCipher B_RC2_40 = final static BulkCipher B_RC2_40 =
new BulkCipher("RC2", 5, 16, 8, false); new BulkCipher("RC2", BLOCK_CIPHER, 5, 16, 8, 0, false);
final static BulkCipher B_DES_40 = final static BulkCipher B_DES_40 =
new BulkCipher(CIPHER_DES, 5, 8, 8, true); new BulkCipher(CIPHER_DES, BLOCK_CIPHER, 5, 8, 8, 0, true);
// domestic strength ciphers // domestic strength ciphers
final static BulkCipher B_RC4_128 = final static BulkCipher B_RC4_128 =
new BulkCipher(CIPHER_RC4, 16, 0, true); new BulkCipher(CIPHER_RC4, STREAM_CIPHER, 16, 0, 0, true);
final static BulkCipher B_DES = final static BulkCipher B_DES =
new BulkCipher(CIPHER_DES, 8, 8, true); new BulkCipher(CIPHER_DES, BLOCK_CIPHER, 8, 8, 0, true);
final static BulkCipher B_3DES = final static BulkCipher B_3DES =
new BulkCipher(CIPHER_3DES, 24, 8, true); new BulkCipher(CIPHER_3DES, BLOCK_CIPHER, 24, 8, 0, true);
final static BulkCipher B_IDEA = final static BulkCipher B_IDEA =
new BulkCipher("IDEA", 16, 8, false); new BulkCipher("IDEA", BLOCK_CIPHER, 16, 8, 0, false);
final static BulkCipher B_AES_128 = final static BulkCipher B_AES_128 =
new BulkCipher(CIPHER_AES, 16, 16, true); new BulkCipher(CIPHER_AES, BLOCK_CIPHER, 16, 16, 0, true);
final static BulkCipher B_AES_256 = final static BulkCipher B_AES_256 =
new BulkCipher(CIPHER_AES, 32, 16, true); new BulkCipher(CIPHER_AES, BLOCK_CIPHER, 32, 16, 0, true);
final static BulkCipher B_AES_128_GCM =
new BulkCipher(CIPHER_AES_GCM, AEAD_CIPHER, 16, 12, 4, true);
final static BulkCipher B_AES_256_GCM =
new BulkCipher(CIPHER_AES_GCM, AEAD_CIPHER, 32, 12, 4, true);
// MACs // MACs
final static MacAlg M_NULL = new MacAlg("NULL", 0); final static MacAlg M_NULL = new MacAlg("NULL", 0);
...@@ -893,11 +956,12 @@ final class CipherSuite implements Comparable<CipherSuite> { ...@@ -893,11 +956,12 @@ final class CipherSuite implements Comparable<CipherSuite> {
* Definition of the CipherSuites that are enabled by default. * Definition of the CipherSuites that are enabled by default.
* They are listed in preference order, most preferred first, using * They are listed in preference order, most preferred first, using
* the following criteria: * the following criteria:
* 1. Prefer the stronger buld cipher, in the order of AES_256, * 1. Prefer Suite B compliant cipher suites, see RFC6460.
* AES_128, RC-4, 3DES-EDE. * 2. Prefer the stronger bulk cipher, in the order of AES_256(GCM),
* 2. Prefer the stronger MAC algorithm, in the order of SHA384, * AES_128(GCM), AES_256, AES_128, RC-4, 3DES-EDE.
* 3. Prefer the stronger MAC algorithm, in the order of SHA384,
* SHA256, SHA, MD5. * SHA256, SHA, MD5.
* 3. Prefer the better performance of key exchange and digital * 4. Prefer the better performance of key exchange and digital
* signature algorithm, in the order of ECDHE-ECDSA, ECDHE-RSA, * signature algorithm, in the order of ECDHE-ECDSA, ECDHE-RSA,
* RSA, ECDH-ECDSA, ECDH-RSA, DHE-RSA, DHE-DSS. * RSA, ECDH-ECDSA, ECDH-RSA, DHE-RSA, DHE-DSS.
*/ */
...@@ -910,6 +974,16 @@ final class CipherSuite implements Comparable<CipherSuite> { ...@@ -910,6 +974,16 @@ final class CipherSuite implements Comparable<CipherSuite> {
// ID Key Exchange Cipher A obs suprt PRF // ID Key Exchange Cipher A obs suprt PRF
// ====== ============ ========= = === ===== ======== // ====== ============ ========= = === ===== ========
// Placeholder for cipher suites in GCM mode.
//
// For better compatibility and interoperability, we decrease the
// priority of cipher suites in GCM mode for a while as GCM
// technologies mature in the industry. Eventually we'll move
// the GCM suites here.
// AES_256(CBC)
add("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", add("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
0xc024, --p, K_ECDHE_ECDSA, B_AES_256, T, max, tls12, P_SHA384); 0xc024, --p, K_ECDHE_ECDSA, B_AES_256, T, max, tls12, P_SHA384);
add("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", add("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
...@@ -940,6 +1014,7 @@ final class CipherSuite implements Comparable<CipherSuite> { ...@@ -940,6 +1014,7 @@ final class CipherSuite implements Comparable<CipherSuite> {
add("TLS_DHE_DSS_WITH_AES_256_CBC_SHA", add("TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
0x0038, --p, K_DHE_DSS, B_AES_256, T); 0x0038, --p, K_DHE_DSS, B_AES_256, T);
// AES_128(CBC)
add("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", add("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
0xc023, --p, K_ECDHE_ECDSA, B_AES_128, T, max, tls12, P_SHA256); 0xc023, --p, K_ECDHE_ECDSA, B_AES_128, T, max, tls12, P_SHA256);
add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
...@@ -970,6 +1045,7 @@ final class CipherSuite implements Comparable<CipherSuite> { ...@@ -970,6 +1045,7 @@ final class CipherSuite implements Comparable<CipherSuite> {
add("TLS_DHE_DSS_WITH_AES_128_CBC_SHA", add("TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
0x0032, --p, K_DHE_DSS, B_AES_128, T); 0x0032, --p, K_DHE_DSS, B_AES_128, T);
// RC-4
add("TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", add("TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
0xC007, --p, K_ECDHE_ECDSA, B_RC4_128, N); 0xC007, --p, K_ECDHE_ECDSA, B_RC4_128, N);
add("TLS_ECDHE_RSA_WITH_RC4_128_SHA", add("TLS_ECDHE_RSA_WITH_RC4_128_SHA",
...@@ -981,6 +1057,51 @@ final class CipherSuite implements Comparable<CipherSuite> { ...@@ -981,6 +1057,51 @@ final class CipherSuite implements Comparable<CipherSuite> {
add("TLS_ECDH_RSA_WITH_RC4_128_SHA", add("TLS_ECDH_RSA_WITH_RC4_128_SHA",
0xC00C, --p, K_ECDH_RSA, B_RC4_128, N); 0xC00C, --p, K_ECDH_RSA, B_RC4_128, N);
// Cipher suites in GCM mode, see RFC 5288/5289.
//
// We may increase the priority of cipher suites in GCM mode when
// GCM technologies become mature in the industry.
// Suite B compliant cipher suites, see RFC 6460.
//
// Note that, at present this provider is not Suite B compliant. The
// preference order of the GCM cipher suites does not follow the spec
// of RFC 6460.
add("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
0xc02c, --p, K_ECDHE_ECDSA, B_AES_256_GCM, T, max, tls12, P_SHA384);
add("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
0xc02b, --p, K_ECDHE_ECDSA, B_AES_128_GCM, T, max, tls12, P_SHA256);
// AES_256(GCM)
add("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
0xc030, --p, K_ECDHE_RSA, B_AES_256_GCM, T, max, tls12, P_SHA384);
add("TLS_RSA_WITH_AES_256_GCM_SHA384",
0x009d, --p, K_RSA, B_AES_256_GCM, T, max, tls12, P_SHA384);
add("TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384",
0xc02e, --p, K_ECDH_ECDSA, B_AES_256_GCM, T, max, tls12, P_SHA384);
add("TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384",
0xc032, --p, K_ECDH_RSA, B_AES_256_GCM, T, max, tls12, P_SHA384);
add("TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
0x009f, --p, K_DHE_RSA, B_AES_256_GCM, T, max, tls12, P_SHA384);
add("TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",
0x00a3, --p, K_DHE_DSS, B_AES_256_GCM, T, max, tls12, P_SHA384);
// AES_128(GCM)
add("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
0xc02f, --p, K_ECDHE_RSA, B_AES_128_GCM, T, max, tls12, P_SHA256);
add("TLS_RSA_WITH_AES_128_GCM_SHA256",
0x009c, --p, K_RSA, B_AES_128_GCM, T, max, tls12, P_SHA256);
add("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",
0xc02d, --p, K_ECDH_ECDSA, B_AES_128_GCM, T, max, tls12, P_SHA256);
add("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",
0xc031, --p, K_ECDH_RSA, B_AES_128_GCM, T, max, tls12, P_SHA256);
add("TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
0x009e, --p, K_DHE_RSA, B_AES_128_GCM, T, max, tls12, P_SHA256);
add("TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",
0x00a2, --p, K_DHE_DSS, B_AES_128_GCM, T, max, tls12, P_SHA256);
// End of cipher suites in GCM mode.
// 3DES_EDE
add("TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", add("TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
0xC008, --p, K_ECDHE_ECDSA, B_3DES, T); 0xC008, --p, K_ECDHE_ECDSA, B_3DES, T);
add("TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", add("TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
...@@ -1024,17 +1145,22 @@ final class CipherSuite implements Comparable<CipherSuite> { ...@@ -1024,17 +1145,22 @@ final class CipherSuite implements Comparable<CipherSuite> {
*/ */
p = DEFAULT_SUITES_PRIORITY; p = DEFAULT_SUITES_PRIORITY;
add("TLS_DH_anon_WITH_AES_256_GCM_SHA384",
0x00a7, --p, K_DH_ANON, B_AES_256_GCM, N, max, tls12, P_SHA384);
add("TLS_DH_anon_WITH_AES_128_GCM_SHA256",
0x00a6, --p, K_DH_ANON, B_AES_128_GCM, N, max, tls12, P_SHA256);
add("TLS_DH_anon_WITH_AES_256_CBC_SHA256", add("TLS_DH_anon_WITH_AES_256_CBC_SHA256",
0x006d, --p, K_DH_ANON, B_AES_256, N, max, tls12, P_SHA256); 0x006d, --p, K_DH_ANON, B_AES_256, N, max, tls12, P_SHA256);
add("TLS_ECDH_anon_WITH_AES_256_CBC_SHA", add("TLS_ECDH_anon_WITH_AES_256_CBC_SHA",
0xC019, --p, K_ECDH_ANON, B_AES_256, T); 0xC019, --p, K_ECDH_ANON, B_AES_256, N);
add("TLS_DH_anon_WITH_AES_256_CBC_SHA", add("TLS_DH_anon_WITH_AES_256_CBC_SHA",
0x003a, --p, K_DH_ANON, B_AES_256, N); 0x003a, --p, K_DH_ANON, B_AES_256, N);
add("TLS_DH_anon_WITH_AES_128_CBC_SHA256", add("TLS_DH_anon_WITH_AES_128_CBC_SHA256",
0x006c, --p, K_DH_ANON, B_AES_128, N, max, tls12, P_SHA256); 0x006c, --p, K_DH_ANON, B_AES_128, N, max, tls12, P_SHA256);
add("TLS_ECDH_anon_WITH_AES_128_CBC_SHA", add("TLS_ECDH_anon_WITH_AES_128_CBC_SHA",
0xC018, --p, K_ECDH_ANON, B_AES_128, T); 0xC018, --p, K_ECDH_ANON, B_AES_128, N);
add("TLS_DH_anon_WITH_AES_128_CBC_SHA", add("TLS_DH_anon_WITH_AES_128_CBC_SHA",
0x0034, --p, K_DH_ANON, B_AES_128, N); 0x0034, --p, K_DH_ANON, B_AES_128, N);
...@@ -1044,7 +1170,7 @@ final class CipherSuite implements Comparable<CipherSuite> { ...@@ -1044,7 +1170,7 @@ final class CipherSuite implements Comparable<CipherSuite> {
0x0018, --p, K_DH_ANON, B_RC4_128, N); 0x0018, --p, K_DH_ANON, B_RC4_128, N);
add("TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA", add("TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA",
0xC017, --p, K_ECDH_ANON, B_3DES, T); 0xC017, --p, K_ECDH_ANON, B_3DES, N);
add("SSL_DH_anon_WITH_3DES_EDE_CBC_SHA", add("SSL_DH_anon_WITH_3DES_EDE_CBC_SHA",
0x001b, --p, K_DH_ANON, B_3DES, N); 0x001b, --p, K_DH_ANON, B_3DES, N);
...@@ -1199,18 +1325,10 @@ final class CipherSuite implements Comparable<CipherSuite> { ...@@ -1199,18 +1325,10 @@ final class CipherSuite implements Comparable<CipherSuite> {
add("TLS_DH_RSA_WITH_AES_256_CBC_SHA256", 0x0069); add("TLS_DH_RSA_WITH_AES_256_CBC_SHA256", 0x0069);
// Unsupported cipher suites from RFC 5288 // 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_128_GCM_SHA256", 0x00a0);
add("TLS_DH_RSA_WITH_AES_256_GCM_SHA384", 0x00a1); 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_128_GCM_SHA256", 0x00a4);
add("TLS_DH_DSS_WITH_AES_256_GCM_SHA384", 0x00a5); 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 // Unsupported cipher suites from RFC 5487
add("TLS_PSK_WITH_AES_128_GCM_SHA256", 0x00a8); add("TLS_PSK_WITH_AES_128_GCM_SHA256", 0x00a8);
...@@ -1269,16 +1387,6 @@ final class CipherSuite implements Comparable<CipherSuite> { ...@@ -1269,16 +1387,6 @@ final class CipherSuite implements Comparable<CipherSuite> {
add("TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA", 0xc021); add("TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA", 0xc021);
add("TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA", 0xc022); add("TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA", 0xc022);
// Unsupported cipher suites from RFC 5289
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 // Unsupported cipher suites from RFC 5489
add("TLS_ECDHE_PSK_WITH_RC4_128_SHA", 0xc033); add("TLS_ECDHE_PSK_WITH_RC4_128_SHA", 0xc033);
add("TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA", 0xc034); add("TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA", 0xc034);
......
/* /*
* Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -178,90 +178,94 @@ final class EngineInputRecord extends InputRecord { ...@@ -178,90 +178,94 @@ final class EngineInputRecord extends InputRecord {
} }
/* /*
* Verifies and removes the MAC value. Returns true if * Pass the data down if it's internally cached, otherwise
* the MAC checks out OK. * do it here.
* *
* On entry: * If internal data, data is decrypted internally.
* position = beginning of app/MAC data
* limit = end of MAC data.
* *
* On return: * If external data(app), return a new ByteBuffer with data to
* position = beginning of app data * process.
* limit = end of app data
*/ */
boolean checkMAC(MAC signer, ByteBuffer bb) { ByteBuffer decrypt(Authenticator authenticator,
CipherBox box, ByteBuffer bb) throws BadPaddingException {
if (internalData) { if (internalData) {
return checkMAC(signer); decrypt(authenticator, box); // MAC is checked during decryption
return tmpBB;
} }
int len = signer.MAClen(); BadPaddingException bpe = null;
if (len == 0) { // no mac if (!box.isNullCipher()) {
return true; try {
// apply explicit nonce for AEAD/CBC cipher suites if needed
int nonceSize =
box.applyExplicitNonce(authenticator, contentType(), bb);
// decrypt the content
if (box.isAEADMode()) {
// DON'T encrypt the nonce_explicit for AEAD mode
bb.position(bb.position() + nonceSize);
} // The explicit IV for CBC mode can be decrypted.
box.decrypt(bb);
bb.position(nonceSize); // We don't actually remove the nonce.
} catch (BadPaddingException e) {
// RFC 2246 states that decryption_failed should be used
// for this purpose. However, that allows certain attacks,
// so we just send bad record MAC. We also need to make
// sure to always check the MAC to avoid a timing attack
// for the same issue. See paper by Vaudenay et al and the
// update in RFC 4346/5246.
//
// Failover to message authentication code checking.
bpe = new BadPaddingException("invalid padding");
}
} }
/* // Requires message authentication code for null, stream and block
* Grab the original limit // cipher suites.
*/ if (authenticator instanceof MAC) {
int lim = bb.limit(); MAC signer = (MAC)authenticator;
int macLen = signer.MAClen();
/* if (macLen != 0) {
* Delineate the area to apply a MAC on. if (bb.remaining() < macLen) {
*/ // negative data length, something is wrong
int macData = lim - len; throw new BadPaddingException("bad record");
bb.limit(macData); }
byte[] mac = signer.compute(contentType(), bb); int position = bb.position();
int limit = bb.limit();
int macOffset = limit - macLen;
if (len != mac.length) { bb.limit(macOffset);
throw new RuntimeException("Internal MAC error"); byte[] hash = signer.compute(contentType(), bb);
} if (hash == null || macLen != hash.length) {
// something is wrong with MAC implementation
throw new RuntimeException("Internal MAC error");
}
/* bb.position(macOffset);
* Delineate the MAC values, position was already set bb.limit(limit);
* by doing the compute above.
*
* We could zero the MAC area, but not much useful information
* there anyway.
*/
bb.position(macData);
bb.limit(lim);
try { try {
for (int i = 0; i < len; i++) { for (byte b : hash) { // No BB.equals(byte []); !
if (bb.get() != mac[i]) { // No BB.equals(byte []); ! if (bb.get() != b) {
return false; throw new BadPaddingException("bad record MAC");
}
}
} finally {
// reset to the data
bb.position(position);
bb.limit(macOffset);
} }
} }
return true;
} finally {
/*
* Position to the data.
*/
bb.rewind();
bb.limit(macData);
} }
}
/*
* Pass the data down if it's internally cached, otherwise
* do it here.
*
* If internal data, data is decrypted internally.
*
* If external data(app), return a new ByteBuffer with data to
* process.
*/
ByteBuffer decrypt(CipherBox box, ByteBuffer bb)
throws BadPaddingException {
if (internalData) { // Is it a failover?
decrypt(box); if (bpe != null) {
return tmpBB; throw bpe;
} }
box.decrypt(bb);
bb.rewind();
return bb.slice(); return bb.slice();
} }
...@@ -338,8 +342,8 @@ final class EngineInputRecord extends InputRecord { ...@@ -338,8 +342,8 @@ final class EngineInputRecord extends InputRecord {
if (debug != null && Debug.isOn("packet")) { if (debug != null && Debug.isOn("packet")) {
try { try {
HexDumpEncoder hd = new HexDumpEncoder(); HexDumpEncoder hd = new HexDumpEncoder();
srcBB.limit(srcPos + len);
ByteBuffer bb = srcBB.duplicate(); // Use copy of BB ByteBuffer bb = srcBB.duplicate(); // Use copy of BB
bb.limit(srcPos + len);
System.out.println("[Raw read (bb)]: length = " + len); System.out.println("[Raw read (bb)]: length = " + len);
hd.encodeBuffer(bb, System.out); hd.encodeBuffer(bb, System.out);
......
...@@ -29,7 +29,6 @@ package sun.security.ssl; ...@@ -29,7 +29,6 @@ package sun.security.ssl;
import java.io.*; import java.io.*;
import java.nio.*; import java.nio.*;
/** /**
* A OutputRecord class extension which uses external ByteBuffers * A OutputRecord class extension which uses external ByteBuffers
* or the internal ByteArrayOutputStream for data manipulations. * or the internal ByteArrayOutputStream for data manipulations.
...@@ -101,51 +100,6 @@ final class EngineOutputRecord extends OutputRecord { ...@@ -101,51 +100,6 @@ final class EngineOutputRecord extends OutputRecord {
return finishedMsg; return finishedMsg;
} }
/**
* Calculate the MAC value, storing the result either in
* the internal buffer, or at the end of the destination
* ByteBuffer.
* <P>
* We assume that the higher levels have assured us enough
* room, otherwise we'll indirectly throw a
* BufferOverFlowException runtime exception.
*
* position should equal limit, and points to the next
* free spot.
*/
private void addMAC(MAC signer, ByteBuffer bb)
throws IOException {
if (signer.MAClen() != 0) {
byte[] hash = signer.compute(contentType(), bb);
/*
* position was advanced to limit in compute above.
*
* Mark next area as writable (above layers should have
* established that we have plenty of room), then write
* out the hash.
*/
bb.limit(bb.limit() + hash.length);
bb.put(hash);
}
}
/*
* Encrypt a ByteBuffer.
*
* We assume that the higher levels have assured us enough
* room for the encryption (plus padding), otherwise we'll
* indirectly throw a BufferOverFlowException runtime exception.
*
* position and limit will be the same, and points to the
* next free spot.
*/
void encrypt(CipherBox box, ByteBuffer bb) {
box.encrypt(bb);
}
/* /*
* Override the actual write below. We do things this way to be * Override the actual write below. We do things this way to be
* consistent with InputRecord. InputRecord may try to write out * consistent with InputRecord. InputRecord may try to write out
...@@ -160,7 +114,8 @@ final class EngineOutputRecord extends OutputRecord { ...@@ -160,7 +114,8 @@ final class EngineOutputRecord extends OutputRecord {
* Copy data out of buffer, it's ready to go. * Copy data out of buffer, it's ready to go.
*/ */
ByteBuffer netBB = (ByteBuffer) ByteBuffer netBB = (ByteBuffer)
ByteBuffer.allocate(len).put(buf, 0, len).flip(); ByteBuffer.allocate(len).put(buf, off, len).flip();
writer.putOutboundData(netBB); writer.putOutboundData(netBB);
} }
...@@ -168,17 +123,19 @@ final class EngineOutputRecord extends OutputRecord { ...@@ -168,17 +123,19 @@ final class EngineOutputRecord extends OutputRecord {
* Main method for writing non-application data. * Main method for writing non-application data.
* We MAC/encrypt, then send down for processing. * We MAC/encrypt, then send down for processing.
*/ */
void write(MAC writeMAC, CipherBox writeCipher) throws IOException { void write(Authenticator authenticator, CipherBox writeCipher)
throws IOException {
/* /*
* Sanity check. * Sanity check.
*/ */
switch (contentType()) { switch (contentType()) {
case ct_change_cipher_spec: case ct_change_cipher_spec:
case ct_alert: case ct_alert:
case ct_handshake: case ct_handshake:
break; break;
default: default:
throw new RuntimeException("unexpected byte buffers"); throw new RuntimeException("unexpected byte buffers");
} }
/* /*
...@@ -193,10 +150,10 @@ final class EngineOutputRecord extends OutputRecord { ...@@ -193,10 +150,10 @@ final class EngineOutputRecord extends OutputRecord {
*/ */
if (!isEmpty()) { if (!isEmpty()) {
// compress(); // eventually // compress(); // eventually
addMAC(writeMAC); encrypt(authenticator, writeCipher);
encrypt(writeCipher);
write((OutputStream)null, false, // send down for processing // send down for processing
(ByteArrayOutputStream)null); write((OutputStream)null, false, (ByteArrayOutputStream)null);
} }
return; return;
} }
...@@ -204,8 +161,8 @@ final class EngineOutputRecord extends OutputRecord { ...@@ -204,8 +161,8 @@ final class EngineOutputRecord extends OutputRecord {
/** /**
* Main wrap/write driver. * Main wrap/write driver.
*/ */
void write(EngineArgs ea, MAC writeMAC, CipherBox writeCipher) void write(EngineArgs ea, Authenticator authenticator,
throws IOException { CipherBox writeCipher) throws IOException {
/* /*
* sanity check to make sure someone didn't inadvertantly * sanity check to make sure someone didn't inadvertantly
* send us an impossible combination we don't know how * send us an impossible combination we don't know how
...@@ -217,7 +174,7 @@ final class EngineOutputRecord extends OutputRecord { ...@@ -217,7 +174,7 @@ final class EngineOutputRecord extends OutputRecord {
* Have we set the MAC's yet? If not, we're not ready * Have we set the MAC's yet? If not, we're not ready
* to process application data yet. * to process application data yet.
*/ */
if (writeMAC == MAC.NULL) { if (authenticator == MAC.NULL) {
return; return;
} }
...@@ -255,7 +212,7 @@ final class EngineOutputRecord extends OutputRecord { ...@@ -255,7 +212,7 @@ final class EngineOutputRecord extends OutputRecord {
*/ */
int length; int length;
if (engine.needToSplitPayload(writeCipher, protocolVersion)) { if (engine.needToSplitPayload(writeCipher, protocolVersion)) {
write(ea, writeMAC, writeCipher, 0x01); write(ea, authenticator, writeCipher, 0x01);
ea.resetLim(); // reset application data buffer limit ea.resetLim(); // reset application data buffer limit
length = Math.min(ea.getAppRemaining(), length = Math.min(ea.getAppRemaining(),
maxDataSizeMinusOneByteRecord); maxDataSizeMinusOneByteRecord);
...@@ -265,14 +222,14 @@ final class EngineOutputRecord extends OutputRecord { ...@@ -265,14 +222,14 @@ final class EngineOutputRecord extends OutputRecord {
// Don't bother to really write empty records. // Don't bother to really write empty records.
if (length > 0) { if (length > 0) {
write(ea, writeMAC, writeCipher, length); write(ea, authenticator, writeCipher, length);
} }
return; return;
} }
void write(EngineArgs ea, MAC writeMAC, CipherBox writeCipher, void write(EngineArgs ea, Authenticator authenticator,
int length) throws IOException { CipherBox writeCipher, int length) throws IOException {
/* /*
* Copy out existing buffer values. * Copy out existing buffer values.
*/ */
...@@ -286,39 +243,76 @@ final class EngineOutputRecord extends OutputRecord { ...@@ -286,39 +243,76 @@ final class EngineOutputRecord extends OutputRecord {
* Don't need to worry about SSLv2 rewrites, if we're here, * Don't need to worry about SSLv2 rewrites, if we're here,
* that's long since done. * that's long since done.
*/ */
int dstData = dstPos + headerSize; int dstData = dstPos + headerSize + writeCipher.getExplicitNonceSize();
dstBB.position(dstData); dstBB.position(dstData);
ea.gather(length);
/* /*
* "flip" but skip over header again, add MAC & encrypt * transfer application data into the network data buffer
* addMAC will expand the limit to reflect the new
* data.
*/ */
ea.gather(length);
dstBB.limit(dstBB.position()); dstBB.limit(dstBB.position());
dstBB.position(dstData); dstBB.position(dstData);
addMAC(writeMAC, dstBB);
/* /*
* Encrypt may pad, so again the limit may have changed. * "flip" but skip over header again, add MAC & encrypt
*/ */
dstBB.limit(dstBB.position()); if (authenticator instanceof MAC) {
dstBB.position(dstData); MAC signer = (MAC)authenticator;
encrypt(writeCipher, dstBB); if (signer.MAClen() != 0) {
byte[] hash = signer.compute(contentType(), dstBB);
/*
* position was advanced to limit in compute above.
*
* Mark next area as writable (above layers should have
* established that we have plenty of room), then write
* out the hash.
*/
dstBB.limit(dstBB.limit() + hash.length);
dstBB.put(hash);
// reset the position and limit
dstBB.limit(dstBB.position());
dstBB.position(dstData);
}
}
if (!writeCipher.isNullCipher()) {
/*
* Requires explicit IV/nonce for CBC/AEAD cipher suites for TLS 1.1
* or later.
*/
if (protocolVersion.v >= ProtocolVersion.TLS11.v &&
(writeCipher.isCBCMode() || writeCipher.isAEADMode())) {
byte[] nonce = writeCipher.createExplicitNonce(
authenticator, contentType(), dstBB.remaining());
dstBB.position(dstPos + headerSize);
dstBB.put(nonce);
if (!writeCipher.isAEADMode()) {
// The explicit IV in TLS 1.1 and later can be encrypted.
dstBB.position(dstPos + headerSize);
} // Otherwise, DON'T encrypt the nonce_explicit for AEAD mode
}
if (debug != null /*
&& (Debug.isOn("record") || Debug.isOn("handshake"))) { * Encrypt may pad, so again the limit may have changed.
if ((debug != null && Debug.isOn("record")) */
|| contentType() == ct_change_cipher_spec) writeCipher.encrypt(dstBB, dstLim);
if ((debug != null) && (Debug.isOn("record") ||
(Debug.isOn("handshake") &&
(contentType() == ct_change_cipher_spec)))) {
System.out.println(Thread.currentThread().getName() System.out.println(Thread.currentThread().getName()
// v3.0/v3.1 ... // v3.0/v3.1 ...
+ ", WRITE: " + protocolVersion + ", WRITE: " + protocolVersion
+ " " + InputRecord.contentName(contentType()) + " " + InputRecord.contentName(contentType())
+ ", length = " + length); + ", length = " + length);
}
} else {
dstBB.position(dstBB.limit());
} }
int packetLength = dstBB.limit() - dstData; int packetLength = dstBB.limit() - dstPos - headerSize;
/* /*
* Finish out the record header. * Finish out the record header.
...@@ -333,7 +327,5 @@ final class EngineOutputRecord extends OutputRecord { ...@@ -333,7 +327,5 @@ final class EngineOutputRecord extends OutputRecord {
* Position was already set by encrypt() above. * Position was already set by encrypt() above.
*/ */
dstBB.limit(dstLim); dstBB.limit(dstLim);
return;
} }
} }
/* /*
* Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -99,7 +99,8 @@ final class EngineWriter { ...@@ -99,7 +99,8 @@ final class EngineWriter {
* other writeRecord. * other writeRecord.
*/ */
synchronized void writeRecord(EngineOutputRecord outputRecord, synchronized void writeRecord(EngineOutputRecord outputRecord,
MAC writeMAC, CipherBox writeCipher) throws IOException { Authenticator authenticator,
CipherBox writeCipher) throws IOException {
/* /*
* Only output if we're still open. * Only output if we're still open.
...@@ -108,7 +109,7 @@ final class EngineWriter { ...@@ -108,7 +109,7 @@ final class EngineWriter {
throw new IOException("writer side was already closed."); throw new IOException("writer side was already closed.");
} }
outputRecord.write(writeMAC, writeCipher); outputRecord.write(authenticator, writeCipher);
/* /*
* Did our handshakers notify that we just sent the * Did our handshakers notify that we just sent the
...@@ -151,7 +152,8 @@ final class EngineWriter { ...@@ -151,7 +152,8 @@ final class EngineWriter {
* Return any determined status. * Return any determined status.
*/ */
synchronized HandshakeStatus writeRecord( synchronized HandshakeStatus writeRecord(
EngineOutputRecord outputRecord, EngineArgs ea, MAC writeMAC, EngineOutputRecord outputRecord, EngineArgs ea,
Authenticator authenticator,
CipherBox writeCipher) throws IOException { CipherBox writeCipher) throws IOException {
/* /*
...@@ -181,7 +183,7 @@ final class EngineWriter { ...@@ -181,7 +183,7 @@ final class EngineWriter {
throw new IOException("The write side was already closed"); throw new IOException("The write side was already closed");
} }
outputRecord.write(ea, writeMAC, writeCipher); outputRecord.write(ea, authenticator, writeCipher);
if (debug != null && Debug.isOn("packet")) { if (debug != null && Debug.isOn("packet")) {
dumpPacket(ea, false); dumpPacket(ea, false);
......
...@@ -49,6 +49,7 @@ import sun.security.ssl.HandshakeMessage.*; ...@@ -49,6 +49,7 @@ import sun.security.ssl.HandshakeMessage.*;
import sun.security.ssl.CipherSuite.*; import sun.security.ssl.CipherSuite.*;
import static sun.security.ssl.CipherSuite.PRF.*; import static sun.security.ssl.CipherSuite.PRF.*;
import static sun.security.ssl.CipherSuite.CipherType.*;
/** /**
* Handshaker ... processes handshake records from an SSL V3.0 * Handshaker ... processes handshake records from an SSL V3.0
...@@ -714,33 +715,47 @@ abstract class Handshaker { ...@@ -714,33 +715,47 @@ abstract class Handshaker {
/** /**
* Create a new read MAC and return it to caller. * Create a new read MAC and return it to caller.
*/ */
MAC newReadMAC() throws NoSuchAlgorithmException, InvalidKeyException { Authenticator newReadAuthenticator()
MacAlg macAlg = cipherSuite.macAlg; throws NoSuchAlgorithmException, InvalidKeyException {
MAC mac;
if (isClient) { Authenticator authenticator = null;
mac = macAlg.newMac(protocolVersion, svrMacSecret); if (cipherSuite.cipher.cipherType == AEAD_CIPHER) {
svrMacSecret = null; authenticator = new Authenticator(protocolVersion);
} else { } else {
mac = macAlg.newMac(protocolVersion, clntMacSecret); MacAlg macAlg = cipherSuite.macAlg;
clntMacSecret = null; if (isClient) {
authenticator = macAlg.newMac(protocolVersion, svrMacSecret);
svrMacSecret = null;
} else {
authenticator = macAlg.newMac(protocolVersion, clntMacSecret);
clntMacSecret = null;
}
} }
return mac;
return authenticator;
} }
/** /**
* Create a new write MAC and return it to caller. * Create a new write MAC and return it to caller.
*/ */
MAC newWriteMAC() throws NoSuchAlgorithmException, InvalidKeyException { Authenticator newWriteAuthenticator()
MacAlg macAlg = cipherSuite.macAlg; throws NoSuchAlgorithmException, InvalidKeyException {
MAC mac;
if (isClient) { Authenticator authenticator = null;
mac = macAlg.newMac(protocolVersion, clntMacSecret); if (cipherSuite.cipher.cipherType == AEAD_CIPHER) {
clntMacSecret = null; authenticator = new Authenticator(protocolVersion);
} else { } else {
mac = macAlg.newMac(protocolVersion, svrMacSecret); MacAlg macAlg = cipherSuite.macAlg;
svrMacSecret = null; if (isClient) {
authenticator = macAlg.newMac(protocolVersion, clntMacSecret);
clntMacSecret = null;
} else {
authenticator = macAlg.newMac(protocolVersion, svrMacSecret);
svrMacSecret = null;
}
} }
return mac;
return authenticator;
} }
/* /*
...@@ -1189,11 +1204,23 @@ abstract class Handshaker { ...@@ -1189,11 +1204,23 @@ abstract class Handshaker {
int prfHashLength = prf.getPRFHashLength(); int prfHashLength = prf.getPRFHashLength();
int prfBlockSize = prf.getPRFBlockSize(); int prfBlockSize = prf.getPRFBlockSize();
// TLS v1.1 or later uses an explicit IV in CBC cipher suites to
// protect against the CBC attacks. AEAD/GCM cipher suites in TLS
// v1.2 or later use a fixed IV as the implicit part of the partially
// implicit nonce technique described in RFC 5116.
int ivSize = cipher.ivSize;
if (cipher.cipherType == AEAD_CIPHER) {
ivSize = cipher.fixedIvSize;
} else if (protocolVersion.v >= ProtocolVersion.TLS11.v &&
cipher.cipherType == BLOCK_CIPHER) {
ivSize = 0;
}
TlsKeyMaterialParameterSpec spec = new TlsKeyMaterialParameterSpec( TlsKeyMaterialParameterSpec spec = new TlsKeyMaterialParameterSpec(
masterKey, protocolVersion.major, protocolVersion.minor, masterKey, protocolVersion.major, protocolVersion.minor,
clnt_random.random_bytes, svr_random.random_bytes, clnt_random.random_bytes, svr_random.random_bytes,
cipher.algorithm, cipher.keySize, expandedKeySize, cipher.algorithm, cipher.keySize, expandedKeySize,
cipher.ivSize, hashSize, ivSize, hashSize,
prfHashAlg, prfHashLength, prfBlockSize); prfHashAlg, prfHashLength, prfBlockSize);
try { try {
...@@ -1201,14 +1228,15 @@ abstract class Handshaker { ...@@ -1201,14 +1228,15 @@ abstract class Handshaker {
kg.init(spec); kg.init(spec);
TlsKeyMaterialSpec keySpec = (TlsKeyMaterialSpec)kg.generateKey(); TlsKeyMaterialSpec keySpec = (TlsKeyMaterialSpec)kg.generateKey();
// Return null if cipher keys are not supposed to be generated.
clntWriteKey = keySpec.getClientCipherKey(); clntWriteKey = keySpec.getClientCipherKey();
svrWriteKey = keySpec.getServerCipherKey(); svrWriteKey = keySpec.getServerCipherKey();
// Return null if IVs are not supposed to be generated. // Return null if IVs are not supposed to be generated.
// e.g. TLS 1.1+.
clntWriteIV = keySpec.getClientIv(); clntWriteIV = keySpec.getClientIv();
svrWriteIV = keySpec.getServerIv(); svrWriteIV = keySpec.getServerIv();
// Return null if MAC keys are not supposed to be generated.
clntMacSecret = keySpec.getClientMacKey(); clntMacSecret = keySpec.getClientMacKey();
svrMacSecret = keySpec.getServerMacKey(); svrMacSecret = keySpec.getServerMacKey();
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {
...@@ -1233,10 +1261,14 @@ abstract class Handshaker { ...@@ -1233,10 +1261,14 @@ abstract class Handshaker {
printHex(dump, masterKey.getEncoded()); printHex(dump, masterKey.getEncoded());
// Outputs: // Outputs:
System.out.println("Client MAC write Secret:"); if (clntMacSecret != null) {
printHex(dump, clntMacSecret.getEncoded()); System.out.println("Client MAC write Secret:");
System.out.println("Server MAC write Secret:"); printHex(dump, clntMacSecret.getEncoded());
printHex(dump, svrMacSecret.getEncoded()); System.out.println("Server MAC write Secret:");
printHex(dump, svrMacSecret.getEncoded());
} else {
System.out.println("... no MAC keys used for this cipher");
}
if (clntWriteKey != null) { if (clntWriteKey != null) {
System.out.println("Client write key:"); System.out.println("Client write key:");
......
/* /*
* Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -77,6 +77,17 @@ class InputRecord extends ByteArrayInputStream implements Record { ...@@ -77,6 +77,17 @@ class InputRecord extends ByteArrayInputStream implements Record {
/* /*
* Construct the record to hold the maximum sized input record. * Construct the record to hold the maximum sized input record.
* Data will be filled in separately. * Data will be filled in separately.
*
* The structure of the byte buffer looks like:
*
* |--------+---------+---------------------------------|
* | header | IV | content, MAC/TAG, padding, etc. |
* | headerPlusIVSize |
*
* header: the header of an SSL records
* IV: the optional IV/nonce field, it is only required for block
* (TLS 1.1 or later) and AEAD cipher suites.
*
*/ */
InputRecord() { InputRecord() {
super(new byte[maxRecordSize]); super(new byte[maxRecordSize]);
...@@ -133,44 +144,83 @@ class InputRecord extends ByteArrayInputStream implements Record { ...@@ -133,44 +144,83 @@ class InputRecord extends ByteArrayInputStream implements Record {
return handshakeHash; return handshakeHash;
} }
/* void decrypt(Authenticator authenticator,
* Verify and remove the MAC ... used for all records. CipherBox box) throws BadPaddingException {
*/
boolean checkMAC(MAC signer) {
int len = signer.MAClen();
if (len == 0) { // no mac
return true;
}
int offset = count - len; BadPaddingException bpe = null;
if (!box.isNullCipher()) {
if (offset < headerSize) { try {
// data length would be negative, something is wrong int cipheredLength = count - headerSize;
return false;
// apply explicit nonce for AEAD/CBC cipher suites if needed
int nonceSize = box.applyExplicitNonce(authenticator,
contentType(), buf, headerSize, cipheredLength);
pos = headerSize + nonceSize;
lastHashed = pos; // don't digest the explicit nonce
// decrypt the content
int offset = headerSize;
if (box.isAEADMode()) {
// DON'T encrypt the nonce_explicit for AEAD mode
offset += nonceSize;
} // The explicit IV for CBC mode can be decrypted.
count = offset + box.decrypt(buf, offset, count - offset);
// Note that we don't remove the nonce from the buffer.
} catch (BadPaddingException e) {
// RFC 2246 states that decryption_failed should be used
// for this purpose. However, that allows certain attacks,
// so we just send bad record MAC. We also need to make
// sure to always check the MAC to avoid a timing attack
// for the same issue. See paper by Vaudenay et al and the
// update in RFC 4346/5246.
//
// Failover to message authenticatoin code checking.
bpe = new BadPaddingException("invalid padding");
}
} }
byte[] mac = signer.compute(contentType(), buf, // Requires message authentication code for null, stream and block
headerSize, offset - headerSize); // cipher suites.
if (authenticator instanceof MAC) {
MAC signer = (MAC)authenticator;
int macLen = signer.MAClen();
if (macLen != 0) {
int macOffset = count - macLen;
int contentLen = macOffset - pos;
if (contentLen < 0) {
// negative data length, something is wrong
throw new BadPaddingException("bad record");
}
if (len != mac.length) { count -= macLen; // Set the count before any MAC checking
throw new RuntimeException("Internal MAC error"); // exception occurs, so that the following
} // process can read the actual decrypted
// content (minus the MAC) in the fragment
// if necessary.
byte[] hash = signer.compute(contentType(),
buf, pos, contentLen);
if (hash == null || macLen != hash.length) {
// something is wrong with MAC implementation
throw new RuntimeException("Internal MAC error");
}
for (int i = 0; i < len; i++) { int offset = macOffset;
if (buf[offset + i] != mac[i]) { for (byte b : hash) {
return false; if (buf[offset++] != b) {
throw new BadPaddingException("bad record MAC");
}
}
} }
} }
count -= len;
return true;
}
void decrypt(CipherBox box) throws BadPaddingException { // Is it a failover?
int len = count - headerSize; if (bpe != null) {
count = headerSize + box.decrypt(buf, headerSize, len); throw bpe;
}
} }
/* /*
* Well ... hello_request messages are _never_ hashed since we can't * Well ... hello_request messages are _never_ hashed since we can't
* know when they'd appear in the sequence. * know when they'd appear in the sequence.
......
/* /*
* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -154,6 +154,11 @@ final class JsseJce { ...@@ -154,6 +154,11 @@ final class JsseJce {
* without padding. * without padding.
*/ */
final static String CIPHER_AES = "AES/CBC/NoPadding"; final static String CIPHER_AES = "AES/CBC/NoPadding";
/**
* JCE transformation string for AES in GCM mode
* without padding.
*/
final static String CIPHER_AES_GCM = "AES/GCM/NoPadding";
/** /**
* JCA identifier string for DSA, i.e. a DSA with SHA-1. * JCA identifier string for DSA, i.e. a DSA with SHA-1.
*/ */
......
/* /*
* Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -39,19 +39,15 @@ import static sun.security.ssl.CipherSuite.*; ...@@ -39,19 +39,15 @@ import static sun.security.ssl.CipherSuite.*;
/** /**
* This class computes the "Message Authentication Code" (MAC) for each * This class computes the "Message Authentication Code" (MAC) for each
* SSL message. This is essentially a shared-secret signature, used to * SSL stream and block cipher message. This is essentially a shared-secret
* provide integrity protection for SSL messages. The MAC is actually * signature, used to provide integrity protection for SSL messages. The
* one of several keyed hashes, as associated with the cipher suite and * MAC is actually one of several keyed hashes, as associated with the cipher
* protocol version. (SSL v3.0 uses one construct, TLS uses another.) * suite and protocol version. (SSL v3.0 uses one construct, TLS uses another.)
*
* <P>NOTE: MAC computation is the only place in the SSL protocol that the
* sequence number is used. It's also reset to zero with each change of
* a cipher spec, so this is the only place this state is needed.
* *
* @author David Brownell * @author David Brownell
* @author Andreas Sterbenz * @author Andreas Sterbenz
*/ */
final class MAC { final class MAC extends Authenticator {
final static MAC NULL = new MAC(); final static MAC NULL = new MAC();
...@@ -64,26 +60,9 @@ final class MAC { ...@@ -64,26 +60,9 @@ final class MAC {
// JCE Mac object // JCE Mac object
private final Mac mac; private final Mac mac;
// byte array containing the additional information we MAC in each record
// (see below)
private final byte[] block;
// sequence number + record type + + record length
private static final int BLOCK_SIZE_SSL = 8 + 1 + 2;
// sequence number + record type + protocol version + record length
private static final int BLOCK_SIZE_TLS = 8 + 1 + 2 + 2;
// offset of record type in block
private static final int BLOCK_OFFSET_TYPE = 8;
// offset of protocol version number in block (TLS only)
private static final int BLOCK_OFFSET_VERSION = 8 + 1;
private MAC() { private MAC() {
macSize = 0; macSize = 0;
mac = null; mac = null;
block = null;
} }
/** /**
...@@ -91,6 +70,8 @@ final class MAC { ...@@ -91,6 +70,8 @@ final class MAC {
*/ */
MAC(MacAlg macAlg, ProtocolVersion protocolVersion, SecretKey key) MAC(MacAlg macAlg, ProtocolVersion protocolVersion, SecretKey key)
throws NoSuchAlgorithmException, InvalidKeyException { throws NoSuchAlgorithmException, InvalidKeyException {
super(protocolVersion);
this.macSize = macAlg.size; this.macSize = macAlg.size;
String algorithm; String algorithm;
...@@ -110,14 +91,6 @@ final class MAC { ...@@ -110,14 +91,6 @@ final class MAC {
mac = JsseJce.getMac(algorithm); mac = JsseJce.getMac(algorithm);
mac.init(key); mac.init(key);
if (tls) {
block = new byte[BLOCK_SIZE_TLS];
block[BLOCK_OFFSET_VERSION] = protocolVersion.major;
block[BLOCK_OFFSET_VERSION+1] = protocolVersion.minor;
} else {
block = new byte[BLOCK_SIZE_SSL];
}
} }
/** /**
...@@ -136,7 +109,15 @@ final class MAC { ...@@ -136,7 +109,15 @@ final class MAC {
* @param len the size of the compressed record * @param len the size of the compressed record
*/ */
final byte[] compute(byte type, byte buf[], int offset, int len) { final byte[] compute(byte type, byte buf[], int offset, int len) {
return compute(type, null, buf, offset, len); if (macSize == 0) {
return nullMAC;
}
byte[] additional = acquireAuthenticationBytes(type, len);
mac.update(additional);
mac.update(buf, offset, len);
return mac.doFinal();
} }
/** /**
...@@ -151,78 +132,13 @@ final class MAC { ...@@ -151,78 +132,13 @@ final class MAC {
* demarcate the data to be MAC'd. * demarcate the data to be MAC'd.
*/ */
final byte[] compute(byte type, ByteBuffer bb) { final byte[] compute(byte type, ByteBuffer bb) {
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] == (byte)0xFF && block[1] == (byte)0xFF &&
block[2] == (byte)0xFF && block[3] == (byte)0xFF &&
block[4] == (byte)0xFF && block[5] == (byte)0xFF &&
block[6] == (byte)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] == (byte)0xFF && block[1] == (byte)0xFF);
}
// increment the sequence number in the block array
// it is a 64-bit number stored in big-endian format
private void incrementSequenceNumber() {
int k = 7;
while ((k >= 0) && (++block[k] == 0)) {
k--;
}
}
/*
* Compute based on either buffer type, either bb.position/limit
* or buf/offset/len.
*/
private byte[] compute(byte type, ByteBuffer bb, byte[] buf,
int offset, int len) {
if (macSize == 0) { if (macSize == 0) {
return nullMAC; return nullMAC;
} }
block[BLOCK_OFFSET_TYPE] = type; byte[] additional = acquireAuthenticationBytes(type, bb.remaining());
block[block.length - 2] = (byte)(len >> 8); mac.update(additional);
block[block.length - 1] = (byte)(len ); mac.update(bb);
mac.update(block);
incrementSequenceNumber();
// content
if (bb != null) {
mac.update(bb);
} else {
mac.update(buf, offset, len);
}
return mac.doFinal(); return mac.doFinal();
} }
......
...@@ -54,6 +54,7 @@ class OutputRecord extends ByteArrayOutputStream implements Record { ...@@ -54,6 +54,7 @@ class OutputRecord extends ByteArrayOutputStream implements Record {
private int lastHashed; private int lastHashed;
private boolean firstMessage; private boolean firstMessage;
final private byte contentType; final private byte contentType;
private int headerOffset;
// current protocol version, sent as record version // current protocol version, sent as record version
ProtocolVersion protocolVersion; ProtocolVersion protocolVersion;
...@@ -70,6 +71,23 @@ class OutputRecord extends ByteArrayOutputStream implements Record { ...@@ -70,6 +71,23 @@ class OutputRecord extends ByteArrayOutputStream implements Record {
* Default constructor makes a record supporting the maximum * Default constructor makes a record supporting the maximum
* SSL record size. It allocates the header bytes directly. * SSL record size. It allocates the header bytes directly.
* *
* The structure of the byte buffer looks like:
*
* |---------+--------+-------+---------------------------------|
* | unused | header | IV | content, MAC/TAG, padding, etc. |
* | headerPlusMaxIVSize |
*
* unused: unused part of the buffer of size
*
* headerPlusMaxIVSize - header size - IV size
*
* When this object is created, we don't know the protocol
* version number, IV length, etc., so reserve space in front
* to avoid extra data movement (copies).
* header: the header of an SSL record
* IV: the optional IV/nonce field, it is only required for block
* (TLS 1.1 or later) and AEAD cipher suites.
*
* @param type the content type for the record * @param type the content type for the record
*/ */
OutputRecord(byte type, int size) { OutputRecord(byte type, int size) {
...@@ -77,9 +95,10 @@ class OutputRecord extends ByteArrayOutputStream implements Record { ...@@ -77,9 +95,10 @@ class OutputRecord extends ByteArrayOutputStream implements Record {
this.protocolVersion = ProtocolVersion.DEFAULT; this.protocolVersion = ProtocolVersion.DEFAULT;
this.helloVersion = ProtocolVersion.DEFAULT_HELLO; this.helloVersion = ProtocolVersion.DEFAULT_HELLO;
firstMessage = true; firstMessage = true;
count = headerSize; count = headerPlusMaxIVSize;
contentType = type; contentType = type;
lastHashed = count; lastHashed = count;
headerOffset = headerPlusMaxIVSize - headerSize;
} }
OutputRecord(byte type) { OutputRecord(byte type) {
...@@ -119,8 +138,9 @@ class OutputRecord extends ByteArrayOutputStream implements Record { ...@@ -119,8 +138,9 @@ class OutputRecord extends ByteArrayOutputStream implements Record {
@Override @Override
public synchronized void reset() { public synchronized void reset() {
super.reset(); super.reset();
count = headerSize; count = headerPlusMaxIVSize;
lastHashed = count; lastHashed = count;
headerOffset = headerPlusMaxIVSize - headerSize;
} }
/* /*
...@@ -173,58 +193,84 @@ class OutputRecord extends ByteArrayOutputStream implements Record { ...@@ -173,58 +193,84 @@ class OutputRecord extends ByteArrayOutputStream implements Record {
* of sending empty records over the network. * of sending empty records over the network.
*/ */
boolean isEmpty() { boolean isEmpty() {
return count == headerSize; return count == headerPlusMaxIVSize;
} }
/* /*
* Return true if the record is of a given alert. * Return true if the record is of an alert of the given description.
*
* Per SSL/TLS specifications, alert messages convey the severity of the
* message (warning or fatal) and a description of the alert. An alert
* is defined with a two bytes struct, {byte level, byte description},
* following after the header bytes.
*/ */
boolean isAlert(byte description) { boolean isAlert(byte description) {
// An alert is defined with a two bytes struct, if ((count > (headerPlusMaxIVSize + 1)) && (contentType == ct_alert)) {
// {byte level, byte description}, following after the header bytes. return buf[headerPlusMaxIVSize + 1] == description;
if (count > (headerSize + 1) && contentType == ct_alert) {
return buf[headerSize + 1] == description;
} }
return false; return false;
} }
/* /*
* Compute the MAC and append it to this record. In case we * Encrypt ... length may grow due to block cipher padding, or
* are automatically flushing a handshake stream, make sure we * message authentication code or tag.
* have hashed the message first.
*/ */
void addMAC(MAC signer) throws IOException { void encrypt(Authenticator authenticator, CipherBox box)
throws IOException {
// In case we are automatically flushing a handshake stream, make
// sure we have hashed the message first.
// //
// when we support compression, hashing can't go here // when we support compression, hashing can't go here
// since it'll need to be done on the uncompressed data, // since it'll need to be done on the uncompressed data,
// and the MAC applies to the compressed data. // and the MAC applies to the compressed data.
//
if (contentType == ct_handshake) { if (contentType == ct_handshake) {
doHashes(); doHashes();
} }
if (signer.MAClen() != 0) {
byte[] hash = signer.compute(contentType, buf, // Requires message authentication code for stream and block
headerSize, count - headerSize); // cipher suites.
write(hash); if (authenticator instanceof MAC) {
MAC signer = (MAC)authenticator;
if (signer.MAClen() != 0) {
byte[] hash = signer.compute(contentType, buf,
headerPlusMaxIVSize, count - headerPlusMaxIVSize);
write(hash);
}
} }
}
/* if (!box.isNullCipher()) {
* Encrypt ... length may grow due to block cipher padding // Requires explicit IV/nonce for CBC/AEAD cipher suites for
*/ // TLS 1.1 or later.
void encrypt(CipherBox box) { if ((protocolVersion.v >= ProtocolVersion.TLS11.v) &&
int len = count - headerSize; (box.isCBCMode() || box.isAEADMode())) {
count = headerSize + box.encrypt(buf, headerSize, len); byte[] nonce = box.createExplicitNonce(authenticator,
} contentType, count - headerPlusMaxIVSize);
int offset = headerPlusMaxIVSize - nonce.length;
System.arraycopy(nonce, 0, buf, offset, nonce.length);
headerOffset = offset - headerSize;
} else {
headerOffset = headerPlusMaxIVSize - headerSize;
}
// encrypt the content
int offset = headerPlusMaxIVSize;
if (!box.isAEADMode()) {
// The explicit IV can be encrypted.
offset = headerOffset + headerSize;
} // Otherwise, DON'T encrypt the nonce_explicit for AEAD mode
count = offset + box.encrypt(buf, offset, count - offset);
}
}
/* /*
* Tell how full the buffer is ... for filling it with application or * Tell how full the buffer is ... for filling it with application or
* handshake data. * handshake data.
*/ */
final int availableDataBytes() { final int availableDataBytes() {
int dataSize = count - headerSize; int dataSize = count - headerPlusMaxIVSize;
return maxDataSize - dataSize; return maxDataSize - dataSize;
} }
...@@ -270,11 +316,11 @@ class OutputRecord extends ByteArrayOutputStream implements Record { ...@@ -270,11 +316,11 @@ class OutputRecord extends ByteArrayOutputStream implements Record {
* Don't emit content-free records. (Even change cipher spec * Don't emit content-free records. (Even change cipher spec
* messages have a byte of data!) * messages have a byte of data!)
*/ */
if (count == headerSize) { if (count == headerPlusMaxIVSize) {
return; return;
} }
int length = count - headerSize; int length = count - headerOffset - headerSize;
// "should" really never write more than about 14 Kb... // "should" really never write more than about 14 Kb...
if (length < 0) { if (length < 0) {
throw new SSLException("output record size too small: " throw new SSLException("output record size too small: "
...@@ -299,7 +345,9 @@ class OutputRecord extends ByteArrayOutputStream implements Record { ...@@ -299,7 +345,9 @@ class OutputRecord extends ByteArrayOutputStream implements Record {
*/ */
if (firstMessage && useV2Hello()) { if (firstMessage && useV2Hello()) {
byte[] v3Msg = new byte[length - 4]; byte[] v3Msg = new byte[length - 4];
System.arraycopy(buf, headerSize + 4, v3Msg, 0, v3Msg.length); System.arraycopy(buf, headerPlusMaxIVSize + 4,
v3Msg, 0, v3Msg.length);
headerOffset = 0; // reset the header offset
V3toV2ClientHello(v3Msg); V3toV2ClientHello(v3Msg);
handshakeHash.reset(); handshakeHash.reset();
lastHashed = 2; lastHashed = 2;
...@@ -314,11 +362,11 @@ class OutputRecord extends ByteArrayOutputStream implements Record { ...@@ -314,11 +362,11 @@ class OutputRecord extends ByteArrayOutputStream implements Record {
/* /*
* Fill out the header, write it and the message. * Fill out the header, write it and the message.
*/ */
buf[0] = contentType; buf[headerOffset + 0] = contentType;
buf[1] = protocolVersion.major; buf[headerOffset + 1] = protocolVersion.major;
buf[2] = protocolVersion.minor; buf[headerOffset + 2] = protocolVersion.minor;
buf[3] = (byte)(length >> 8); buf[headerOffset + 3] = (byte)(length >> 8);
buf[4] = (byte)(length); buf[headerOffset + 4] = (byte)(length);
} }
firstMessage = false; firstMessage = false;
...@@ -338,7 +386,8 @@ class OutputRecord extends ByteArrayOutputStream implements Record { ...@@ -338,7 +386,8 @@ class OutputRecord extends ByteArrayOutputStream implements Record {
* when holdRecord is true, the implementation in this class * when holdRecord is true, the implementation in this class
* will be used. * will be used.
*/ */
writeBuffer(heldRecordBuffer, buf, 0, count, debugOffset); writeBuffer(heldRecordBuffer,
buf, headerOffset, count - headerOffset, debugOffset);
} else { } else {
// It's time to send, do we have buffered data? // It's time to send, do we have buffered data?
// May or may not have a heldRecordBuffer. // May or may not have a heldRecordBuffer.
...@@ -346,15 +395,18 @@ class OutputRecord extends ByteArrayOutputStream implements Record { ...@@ -346,15 +395,18 @@ class OutputRecord extends ByteArrayOutputStream implements Record {
int heldLen = heldRecordBuffer.size(); int heldLen = heldRecordBuffer.size();
// Ensure the capacity of this buffer. // Ensure the capacity of this buffer.
ensureCapacity(count + heldLen); int newCount = count + heldLen - headerOffset;
ensureCapacity(newCount);
// Slide everything in the buffer to the right. // Slide everything in the buffer to the right.
System.arraycopy(buf, 0, buf, heldLen, count); System.arraycopy(buf, headerOffset,
buf, heldLen, count - headerOffset);
// Prepend the held record to the buffer. // Prepend the held record to the buffer.
System.arraycopy( System.arraycopy(
heldRecordBuffer.toByteArray(), 0, buf, 0, heldLen); heldRecordBuffer.toByteArray(), 0, buf, 0, heldLen);
count += heldLen; count = newCount;
headerOffset = 0;
// Clear the held buffer. // Clear the held buffer.
heldRecordBuffer.reset(); heldRecordBuffer.reset();
...@@ -362,7 +414,8 @@ class OutputRecord extends ByteArrayOutputStream implements Record { ...@@ -362,7 +414,8 @@ class OutputRecord extends ByteArrayOutputStream implements Record {
// The held buffer has been dumped, set the debug dump offset. // The held buffer has been dumped, set the debug dump offset.
debugOffset = heldLen; debugOffset = heldLen;
} }
writeBuffer(s, buf, 0, count, debugOffset); writeBuffer(s, buf, headerOffset,
count - headerOffset, debugOffset);
} }
reset(); reset();
...@@ -382,12 +435,11 @@ class OutputRecord extends ByteArrayOutputStream implements Record { ...@@ -382,12 +435,11 @@ class OutputRecord extends ByteArrayOutputStream implements Record {
if (debug != null && Debug.isOn("packet")) { if (debug != null && Debug.isOn("packet")) {
try { try {
HexDumpEncoder hd = new HexDumpEncoder(); HexDumpEncoder hd = new HexDumpEncoder();
ByteBuffer bb = ByteBuffer.wrap(
buf, off + debugOffset, len - debugOffset);
System.out.println("[Raw write]: length = " + System.out.println("[Raw write]: length = " +
bb.remaining()); (len - debugOffset));
hd.encodeBuffer(bb, System.out); hd.encodeBuffer(new ByteArrayInputStream(buf,
off + debugOffset, len - debugOffset), System.out);
} catch (IOException e) { } } catch (IOException e) { }
} }
} }
...@@ -400,8 +452,13 @@ class OutputRecord extends ByteArrayOutputStream implements Record { ...@@ -400,8 +452,13 @@ class OutputRecord extends ByteArrayOutputStream implements Record {
return firstMessage return firstMessage
&& (helloVersion == ProtocolVersion.SSL20Hello) && (helloVersion == ProtocolVersion.SSL20Hello)
&& (contentType == ct_handshake) && (contentType == ct_handshake)
&& (buf[5] == HandshakeMessage.ht_client_hello) && (buf[headerOffset + 5] == HandshakeMessage.ht_client_hello)
&& (buf[headerSize + 4+2+32] == 0); // V3 session ID is empty // 5: recode header size
&& (buf[headerPlusMaxIVSize + 4 + 2 + 32] == 0);
// V3 session ID is empty
// 4: handshake header size
// 2: client_version in ClientHello
// 32: random in ClientHello
} }
/* /*
......
...@@ -52,20 +52,29 @@ interface Record { ...@@ -52,20 +52,29 @@ interface Record {
static final int trailerSize = 20; // SHA1 hash size static final int trailerSize = 20; // SHA1 hash size
static final int maxDataSize = 16384; // 2^14 bytes of data static final int maxDataSize = 16384; // 2^14 bytes of data
static final int maxPadding = 256; // block cipher padding static final int maxPadding = 256; // block cipher padding
static final int maxIVLength = 256; // block length static final int maxIVLength = 256; // IV length
/*
* The size of the header plus the max IV length
*/
static final int headerPlusMaxIVSize =
headerSize // header
+ maxIVLength; // iv
/* /*
* SSL has a maximum record size. It's header, (compressed) data, * SSL has a maximum record size. It's header, (compressed) data,
* padding, and a trailer for the MAC. * padding, and a trailer for the message authentication information (MAC
* for block and stream ciphers, and message authentication tag for AEAD
* ciphers).
*
* Some compression algorithms have rare cases where they expand the data. * Some compression algorithms have rare cases where they expand the data.
* As we don't support compression at this time, leave that out. * As we don't support compression at this time, leave that out.
*/ */
static final int maxRecordSize = static final int maxRecordSize =
headerSize // header headerPlusMaxIVSize // header + iv
+ maxIVLength // iv + maxDataSize // data
+ maxDataSize // data + maxPadding // padding
+ maxPadding // padding + trailerSize; // MAC or AEAD tag
+ trailerSize; // MAC
static final boolean enableCBCProtection = static final boolean enableCBCProtection =
Debug.getBooleanProperty("jsse.enableCBCProtection", true); Debug.getBooleanProperty("jsse.enableCBCProtection", true);
...@@ -77,8 +86,7 @@ interface Record { ...@@ -77,8 +86,7 @@ interface Record {
static final int maxDataSizeMinusOneByteRecord = static final int maxDataSizeMinusOneByteRecord =
maxDataSize // max data size maxDataSize // max data size
- ( // max one byte record size - ( // max one byte record size
headerSize // header headerPlusMaxIVSize // header + iv
+ maxIVLength // iv
+ 1 // one byte data + 1 // one byte data
+ maxPadding // padding + maxPadding // padding
+ trailerSize // MAC + trailerSize // MAC
...@@ -104,11 +112,10 @@ interface Record { ...@@ -104,11 +112,10 @@ interface Record {
* Allocate a smaller array. * Allocate a smaller array.
*/ */
static final int maxAlertRecordSize = static final int maxAlertRecordSize =
headerSize // header headerPlusMaxIVSize // header + iv
+ maxIVLength // iv + 2 // alert
+ 2 // alert + maxPadding // padding
+ maxPadding // padding + trailerSize; // MAC
+ trailerSize; // MAC
/* /*
* The overflow values of integers of 8, 16 and 24 bits. * The overflow values of integers of 8, 16 and 24 bits.
......
...@@ -280,7 +280,7 @@ final public class SSLEngineImpl extends SSLEngine { ...@@ -280,7 +280,7 @@ final public class SSLEngineImpl extends SSLEngine {
/* /*
* Crypto state that's reinitialized when the session changes. * Crypto state that's reinitialized when the session changes.
*/ */
private MAC readMAC, writeMAC; private Authenticator readAuthenticator, writeAuthenticator;
private CipherBox readCipher, writeCipher; private CipherBox readCipher, writeCipher;
// NOTE: compression state would be saved here // NOTE: compression state would be saved here
...@@ -377,9 +377,9 @@ final public class SSLEngineImpl extends SSLEngine { ...@@ -377,9 +377,9 @@ final public class SSLEngineImpl extends SSLEngine {
* Note: compression support would go here too * Note: compression support would go here too
*/ */
readCipher = CipherBox.NULL; readCipher = CipherBox.NULL;
readMAC = MAC.NULL; readAuthenticator = MAC.NULL;
writeCipher = CipherBox.NULL; writeCipher = CipherBox.NULL;
writeMAC = MAC.NULL; writeAuthenticator = MAC.NULL;
// default security parameters for secure renegotiation // default security parameters for secure renegotiation
secureRenegotiation = false; secureRenegotiation = false;
...@@ -586,7 +586,7 @@ final public class SSLEngineImpl extends SSLEngine { ...@@ -586,7 +586,7 @@ final public class SSLEngineImpl extends SSLEngine {
try { try {
readCipher = handshaker.newReadCipher(); readCipher = handshaker.newReadCipher();
readMAC = handshaker.newReadMAC(); readAuthenticator = handshaker.newReadAuthenticator();
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {
// "can't happen" // "can't happen"
throw new SSLException("Algorithm missing: ", e); throw new SSLException("Algorithm missing: ", e);
...@@ -622,7 +622,7 @@ final public class SSLEngineImpl extends SSLEngine { ...@@ -622,7 +622,7 @@ final public class SSLEngineImpl extends SSLEngine {
try { try {
writeCipher = handshaker.newWriteCipher(); writeCipher = handshaker.newWriteCipher();
writeMAC = handshaker.newWriteMAC(); writeAuthenticator = handshaker.newWriteAuthenticator();
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {
// "can't happen" // "can't happen"
throw new SSLException("Algorithm missing: ", e); throw new SSLException("Algorithm missing: ", e);
...@@ -958,34 +958,15 @@ final public class SSLEngineImpl extends SSLEngine { ...@@ -958,34 +958,15 @@ final public class SSLEngineImpl extends SSLEngine {
* throw a fatal alert if the integrity check fails. * throw a fatal alert if the integrity check fails.
*/ */
try { try {
decryptedBB = inputRecord.decrypt(readCipher, readBB); decryptedBB = inputRecord.decrypt(
readAuthenticator, readCipher, readBB);
} catch (BadPaddingException e) { } catch (BadPaddingException e) {
// RFC 2246 states that decryption_failed should be used
// for this purpose. However, that allows certain attacks,
// so we just send bad record MAC. We also need to make
// sure to always check the MAC to avoid a timing attack
// for the same issue. See paper by Vaudenay et al.
//
// rewind the BB if necessary.
readBB.rewind();
inputRecord.checkMAC(readMAC, readBB);
// use the same alert types as for MAC failure below // use the same alert types as for MAC failure below
byte alertType = (inputRecord.contentType() == byte alertType = (inputRecord.contentType() ==
Record.ct_handshake) ? Record.ct_handshake) ?
Alerts.alert_handshake_failure : Alerts.alert_handshake_failure :
Alerts.alert_bad_record_mac; Alerts.alert_bad_record_mac;
fatal(alertType, "Invalid padding", e); fatal(alertType, e.getMessage(), e);
}
if (!inputRecord.checkMAC(readMAC, decryptedBB)) {
if (inputRecord.contentType() == Record.ct_handshake) {
fatal(Alerts.alert_handshake_failure,
"bad handshake record MAC");
} else {
fatal(Alerts.alert_bad_record_mac, "bad record MAC");
}
} }
// if (!inputRecord.decompress(c)) // if (!inputRecord.decompress(c))
...@@ -1137,7 +1118,7 @@ final public class SSLEngineImpl extends SSLEngine { ...@@ -1137,7 +1118,7 @@ final public class SSLEngineImpl extends SSLEngine {
hsStatus = getHSStatus(hsStatus); hsStatus = getHSStatus(hsStatus);
if (connectionState < cs_ERROR && !isInboundDone() && if (connectionState < cs_ERROR && !isInboundDone() &&
(hsStatus == HandshakeStatus.NOT_HANDSHAKING)) { (hsStatus == HandshakeStatus.NOT_HANDSHAKING)) {
if (checkSequenceNumber(readMAC, if (checkSequenceNumber(readAuthenticator,
inputRecord.contentType())) { inputRecord.contentType())) {
hsStatus = getHSStatus(null); hsStatus = getHSStatus(null);
} }
...@@ -1290,7 +1271,7 @@ final public class SSLEngineImpl extends SSLEngine { ...@@ -1290,7 +1271,7 @@ final public class SSLEngineImpl extends SSLEngine {
// eventually compress as well. // eventually compress as well.
HandshakeStatus hsStatus = HandshakeStatus hsStatus =
writer.writeRecord(eor, ea, writeMAC, writeCipher); writer.writeRecord(eor, ea, writeAuthenticator, writeCipher);
/* /*
* We only need to check the sequence number state for * We only need to check the sequence number state for
...@@ -1307,7 +1288,7 @@ final public class SSLEngineImpl extends SSLEngine { ...@@ -1307,7 +1288,7 @@ final public class SSLEngineImpl extends SSLEngine {
hsStatus = getHSStatus(hsStatus); hsStatus = getHSStatus(hsStatus);
if (connectionState < cs_ERROR && !isOutboundDone() && if (connectionState < cs_ERROR && !isOutboundDone() &&
(hsStatus == HandshakeStatus.NOT_HANDSHAKING)) { (hsStatus == HandshakeStatus.NOT_HANDSHAKING)) {
if (checkSequenceNumber(writeMAC, eor.contentType())) { if (checkSequenceNumber(writeAuthenticator, eor.contentType())) {
hsStatus = getHSStatus(null); hsStatus = getHSStatus(null);
} }
} }
...@@ -1346,7 +1327,7 @@ final public class SSLEngineImpl extends SSLEngine { ...@@ -1346,7 +1327,7 @@ final public class SSLEngineImpl extends SSLEngine {
*/ */
void writeRecord(EngineOutputRecord eor) throws IOException { void writeRecord(EngineOutputRecord eor) throws IOException {
// eventually compress as well. // eventually compress as well.
writer.writeRecord(eor, writeMAC, writeCipher); writer.writeRecord(eor, writeAuthenticator, writeCipher);
/* /*
* Check the sequence number state * Check the sequence number state
...@@ -1360,7 +1341,7 @@ final public class SSLEngineImpl extends SSLEngine { ...@@ -1360,7 +1341,7 @@ final public class SSLEngineImpl extends SSLEngine {
* of the last record cannot be wrapped. * of the last record cannot be wrapped.
*/ */
if ((connectionState < cs_ERROR) && !isOutboundDone()) { if ((connectionState < cs_ERROR) && !isOutboundDone()) {
checkSequenceNumber(writeMAC, eor.contentType()); checkSequenceNumber(writeAuthenticator, eor.contentType());
} }
} }
...@@ -1378,14 +1359,14 @@ final public class SSLEngineImpl extends SSLEngine { ...@@ -1378,14 +1359,14 @@ final public class SSLEngineImpl extends SSLEngine {
* *
* Return true if the handshake status may be changed. * Return true if the handshake status may be changed.
*/ */
private boolean checkSequenceNumber(MAC mac, byte type) private boolean checkSequenceNumber(Authenticator authenticator, byte type)
throws IOException { throws IOException {
/* /*
* Don't bother to check the sequence number for error or * Don't bother to check the sequence number for error or
* closed connections, or NULL MAC * closed connections, or NULL MAC
*/ */
if (connectionState >= cs_ERROR || mac == MAC.NULL) { if (connectionState >= cs_ERROR || authenticator == MAC.NULL) {
return false; return false;
} }
...@@ -1393,7 +1374,7 @@ final public class SSLEngineImpl extends SSLEngine { ...@@ -1393,7 +1374,7 @@ final public class SSLEngineImpl extends SSLEngine {
* Conservatively, close the connection immediately when the * Conservatively, close the connection immediately when the
* sequence number is close to overflow * sequence number is close to overflow
*/ */
if (mac.seqNumOverflow()) { if (authenticator.seqNumOverflow()) {
/* /*
* TLS protocols do not define a error alert for sequence * TLS protocols do not define a error alert for sequence
* number overflow. We use handshake_failure error alert * number overflow. We use handshake_failure error alert
...@@ -1416,7 +1397,7 @@ final public class SSLEngineImpl extends SSLEngine { ...@@ -1416,7 +1397,7 @@ final public class SSLEngineImpl extends SSLEngine {
* Don't bother to kickstart the renegotiation when the local is * Don't bother to kickstart the renegotiation when the local is
* asking for it. * asking for it.
*/ */
if ((type != Record.ct_handshake) && mac.seqNumIsHuge()) { if ((type != Record.ct_handshake) && authenticator.seqNumIsHuge()) {
if (debug != null && Debug.isOn("ssl")) { if (debug != null && Debug.isOn("ssl")) {
System.out.println(Thread.currentThread().getName() + System.out.println(Thread.currentThread().getName() +
", request renegotiation " + ", request renegotiation " +
......
...@@ -292,7 +292,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl { ...@@ -292,7 +292,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
/* /*
* Crypto state that's reinitialized when the session changes. * Crypto state that's reinitialized when the session changes.
*/ */
private MAC readMAC, writeMAC; private Authenticator readAuthenticator, writeAuthenticator;
private CipherBox readCipher, writeCipher; private CipherBox readCipher, writeCipher;
// NOTE: compression state would be saved here // NOTE: compression state would be saved here
...@@ -586,9 +586,9 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl { ...@@ -586,9 +586,9 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
* Note: compression support would go here too * Note: compression support would go here too
*/ */
readCipher = CipherBox.NULL; readCipher = CipherBox.NULL;
readMAC = MAC.NULL; readAuthenticator = MAC.NULL;
writeCipher = CipherBox.NULL; writeCipher = CipherBox.NULL;
writeMAC = MAC.NULL; writeAuthenticator = MAC.NULL;
// initial security parameters for secure renegotiation // initial security parameters for secure renegotiation
secureRenegotiation = false; secureRenegotiation = false;
...@@ -829,8 +829,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl { ...@@ -829,8 +829,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
boolean holdRecord) throws IOException { boolean holdRecord) throws IOException {
// r.compress(c); // r.compress(c);
r.addMAC(writeMAC); r.encrypt(writeAuthenticator, writeCipher);
r.encrypt(writeCipher);
if (holdRecord) { if (holdRecord) {
// If we were requested to delay the record due to possibility // If we were requested to delay the record due to possibility
...@@ -861,7 +860,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl { ...@@ -861,7 +860,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
* of the last record cannot be wrapped. * of the last record cannot be wrapped.
*/ */
if (connectionState < cs_ERROR) { if (connectionState < cs_ERROR) {
checkSequenceNumber(writeMAC, r.contentType()); checkSequenceNumber(writeAuthenticator, r.contentType());
} }
// turn off the flag of the first application record // turn off the flag of the first application record
...@@ -986,29 +985,14 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl { ...@@ -986,29 +985,14 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
* throw a fatal alert if the integrity check fails. * throw a fatal alert if the integrity check fails.
*/ */
try { try {
r.decrypt(readCipher); r.decrypt(readAuthenticator, readCipher);
} catch (BadPaddingException e) { } catch (BadPaddingException e) {
// RFC 2246 states that decryption_failed should be used
// for this purpose. However, that allows certain attacks,
// so we just send bad record MAC. We also need to make
// sure to always check the MAC to avoid a timing attack
// for the same issue. See paper by Vaudenay et al.
r.checkMAC(readMAC);
// use the same alert types as for MAC failure below // use the same alert types as for MAC failure below
byte alertType = (r.contentType() == Record.ct_handshake) byte alertType = (r.contentType() == Record.ct_handshake)
? Alerts.alert_handshake_failure ? Alerts.alert_handshake_failure
: Alerts.alert_bad_record_mac; : Alerts.alert_bad_record_mac;
fatal(alertType, "Invalid padding", e); fatal(alertType, e.getMessage(), e);
} }
if (!r.checkMAC(readMAC)) {
if (r.contentType() == Record.ct_handshake) {
fatal(Alerts.alert_handshake_failure,
"bad handshake record MAC");
} else {
fatal(Alerts.alert_bad_record_mac, "bad record MAC");
}
}
// if (!r.decompress(c)) // if (!r.decompress(c))
// fatal(Alerts.alert_decompression_failure, // fatal(Alerts.alert_decompression_failure,
...@@ -1159,7 +1143,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl { ...@@ -1159,7 +1143,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
* of the last record cannot be wrapped. * of the last record cannot be wrapped.
*/ */
if (connectionState < cs_ERROR) { if (connectionState < cs_ERROR) {
checkSequenceNumber(readMAC, r.contentType()); checkSequenceNumber(readAuthenticator, r.contentType());
} }
return; return;
...@@ -1182,14 +1166,14 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl { ...@@ -1182,14 +1166,14 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
* implementation would need to wrap a sequence number, it must * implementation would need to wrap a sequence number, it must
* renegotiate instead." * renegotiate instead."
*/ */
private void checkSequenceNumber(MAC mac, byte type) private void checkSequenceNumber(Authenticator authenticator, byte type)
throws IOException { throws IOException {
/* /*
* Don't bother to check the sequence number for error or * Don't bother to check the sequence number for error or
* closed connections, or NULL MAC. * closed connections, or NULL MAC.
*/ */
if (connectionState >= cs_ERROR || mac == MAC.NULL) { if (connectionState >= cs_ERROR || authenticator == MAC.NULL) {
return; return;
} }
...@@ -1197,7 +1181,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl { ...@@ -1197,7 +1181,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
* Conservatively, close the connection immediately when the * Conservatively, close the connection immediately when the
* sequence number is close to overflow * sequence number is close to overflow
*/ */
if (mac.seqNumOverflow()) { if (authenticator.seqNumOverflow()) {
/* /*
* TLS protocols do not define a error alert for sequence * TLS protocols do not define a error alert for sequence
* number overflow. We use handshake_failure error alert * number overflow. We use handshake_failure error alert
...@@ -1219,7 +1203,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl { ...@@ -1219,7 +1203,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
* Don't bother to kickstart the renegotiation when the local is * Don't bother to kickstart the renegotiation when the local is
* asking for it. * asking for it.
*/ */
if ((type != Record.ct_handshake) && mac.seqNumIsHuge()) { if ((type != Record.ct_handshake) && authenticator.seqNumIsHuge()) {
if (debug != null && Debug.isOn("ssl")) { if (debug != null && Debug.isOn("ssl")) {
System.out.println(Thread.currentThread().getName() + System.out.println(Thread.currentThread().getName() +
", request renegotiation " + ", request renegotiation " +
...@@ -2081,7 +2065,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl { ...@@ -2081,7 +2065,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
try { try {
readCipher = handshaker.newReadCipher(); readCipher = handshaker.newReadCipher();
readMAC = handshaker.newReadMAC(); readAuthenticator = handshaker.newReadAuthenticator();
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {
// "can't happen" // "can't happen"
throw new SSLException("Algorithm missing: ", e); throw new SSLException("Algorithm missing: ", e);
...@@ -2112,7 +2096,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl { ...@@ -2112,7 +2096,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
try { try {
writeCipher = handshaker.newWriteCipher(); writeCipher = handshaker.newWriteCipher();
writeMAC = handshaker.newWriteMAC(); writeAuthenticator = handshaker.newWriteAuthenticator();
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {
// "can't happen" // "can't happen"
throw new SSLException("Algorithm missing: ", e); throw new SSLException("Algorithm missing: ", e);
......
...@@ -21,6 +21,11 @@ ...@@ -21,6 +21,11 @@
* questions. * questions.
*/ */
//
// SunJSSE does not support dynamic system properties, no way to re-use
// system properties in samevm/agentvm mode.
//
/** /**
* @test * @test
* @bug 6840752 * @bug 6840752
...@@ -30,7 +35,7 @@ ...@@ -30,7 +35,7 @@
* @library ../pkcs11/sslecc * @library ../pkcs11/sslecc
* @library ../../../java/security/testlibrary * @library ../../../java/security/testlibrary
* @compile -XDignore.symbol.file TestEC.java * @compile -XDignore.symbol.file TestEC.java
* @run main TestEC * @run main/othervm TestEC
*/ */
import java.security.NoSuchProviderException; import java.security.NoSuchProviderException;
......
/* /*
* Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -147,6 +147,25 @@ public class CipherTest { ...@@ -147,6 +147,25 @@ public class CipherTest {
CS_16("TLS_DH_anon_WITH_AES_128_CBC_SHA256", 0x0303, 0xFFFF), CS_16("TLS_DH_anon_WITH_AES_128_CBC_SHA256", 0x0303, 0xFFFF),
CS_17("TLS_RSA_WITH_NULL_SHA256", 0x0303, 0xFFFF), CS_17("TLS_RSA_WITH_NULL_SHA256", 0x0303, 0xFFFF),
CS_20("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
CS_21("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
CS_22("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
CS_23("TLS_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
CS_24("TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
CS_25("TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
CS_26("TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
CS_27("TLS_DHE_DSS_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
CS_28("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
CS_29("TLS_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
CS_30("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
CS_31("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
CS_32("TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
CS_33("TLS_DHE_DSS_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
CS_34("TLS_DH_anon_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
CS_35("TLS_DH_anon_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
// cipher suites obsoleted since TLS 1.2 // cipher suites obsoleted since TLS 1.2
CS_50("SSL_RSA_WITH_DES_CBC_SHA", 0x0000, 0x0303), CS_50("SSL_RSA_WITH_DES_CBC_SHA", 0x0000, 0x0303),
CS_51("SSL_DHE_RSA_WITH_DES_CBC_SHA", 0x0000, 0x0303), CS_51("SSL_DHE_RSA_WITH_DES_CBC_SHA", 0x0000, 0x0303),
......
/* /*
* Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -147,6 +147,25 @@ public class CipherTest { ...@@ -147,6 +147,25 @@ public class CipherTest {
CS_16("TLS_DH_anon_WITH_AES_128_CBC_SHA256", 0x0303, 0xFFFF), CS_16("TLS_DH_anon_WITH_AES_128_CBC_SHA256", 0x0303, 0xFFFF),
CS_17("TLS_RSA_WITH_NULL_SHA256", 0x0303, 0xFFFF), CS_17("TLS_RSA_WITH_NULL_SHA256", 0x0303, 0xFFFF),
CS_20("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
CS_21("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
CS_22("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
CS_23("TLS_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
CS_24("TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
CS_25("TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
CS_26("TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
CS_27("TLS_DHE_DSS_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
CS_28("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
CS_29("TLS_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
CS_30("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
CS_31("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
CS_32("TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
CS_33("TLS_DHE_DSS_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
CS_34("TLS_DH_anon_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
CS_35("TLS_DH_anon_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
// cipher suites obsoleted since TLS 1.2 // cipher suites obsoleted since TLS 1.2
CS_50("SSL_RSA_WITH_DES_CBC_SHA", 0x0000, 0x0303), CS_50("SSL_RSA_WITH_DES_CBC_SHA", 0x0000, 0x0303),
CS_51("SSL_DHE_RSA_WITH_DES_CBC_SHA", 0x0000, 0x0303), CS_51("SSL_DHE_RSA_WITH_DES_CBC_SHA", 0x0000, 0x0303),
......
...@@ -21,14 +21,16 @@ ...@@ -21,14 +21,16 @@
* questions. * questions.
*/ */
//
// SunJSSE does not support dynamic system properties, no way to re-use
// system properties in samevm/agentvm mode.
//
/* /*
* @test * @test
* @bug 7031830 * @bug 7031830
* @summary bad_record_mac failure on TLSv1.2 enabled connection with SSLEngine * @summary bad_record_mac failure on TLSv1.2 enabled connection with SSLEngine
* @run main/othervm SSLEngineBadBufferArrayAccess * @run main/othervm SSLEngineBadBufferArrayAccess
*
* SunJSSE does not support dynamic system properties, no way to re-use
* system properties in samevm/agentvm mode.
*/ */
/** /**
......
/*
* Copyright (c) 2012, 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.
*/
//
// SunJSSE does not support dynamic system properties, no way to re-use
// system properties in samevm/agentvm mode.
//
/*
* @test
* @bug 7030966
* @summary Support AEAD CipherSuites
* @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* @run main/othervm ShortRSAKeyGCM PKIX TLS_RSA_WITH_AES_128_GCM_SHA256
* @run main/othervm ShortRSAKeyGCM PKIX TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
* @run main/othervm ShortRSAKeyGCM PKIX TLS_DH_anon_WITH_AES_128_GCM_SHA256
*/
/*
* Need additional key materials to run the following cases.
*
* @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
* @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
* @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
*
* Need unlimited JCE Unlimited Strength Jurisdiction Policy to run the
* following cases.
*
* @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
* @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
* @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
* @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
* @run main/othervm ShortRSAKeyGCM PKIX TLS_RSA_WITH_AES_256_GCM_SHA384
* @run main/othervm ShortRSAKeyGCM PKIX TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
* @run main/othervm ShortRSAKeyGCM PKIX TLS_DH_anon_WITH_AES_256_GCM_SHA384
*/
import java.net.*;
import java.util.*;
import java.io.*;
import javax.net.ssl.*;
import java.security.Security;
import java.security.KeyStore;
import java.security.KeyFactory;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.spec.*;
import java.security.interfaces.*;
import sun.misc.BASE64Decoder;
public class ShortRSAKeyGCM {
/*
* =============================================================
* 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 = true;
/*
* Where do we find the keystores?
*/
// Certificates and key used in the test.
static String trustedCertStr =
"-----BEGIN CERTIFICATE-----\n" +
"MIICkjCCAfugAwIBAgIBADANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" +
"MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" +
"MTEwODE5MDE1MjE5WhcNMzIwNzI5MDE1MjE5WjA7MQswCQYDVQQGEwJVUzENMAsG\n" +
"A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwgZ8wDQYJ\n" +
"KoZIhvcNAQEBBQADgY0AMIGJAoGBAM8orG08DtF98TMSscjGsidd1ZoN4jiDpi8U\n" +
"ICz+9dMm1qM1d7O2T+KH3/mxyox7Rc2ZVSCaUD0a3CkhPMnlAx8V4u0H+E9sqso6\n" +
"iDW3JpOyzMExvZiRgRG/3nvp55RMIUV4vEHOZ1QbhuqG4ebN0Vz2DkRft7+flthf\n" +
"vDld6f5JAgMBAAGjgaUwgaIwHQYDVR0OBBYEFLl81dnfp0wDrv0OJ1sxlWzH83Xh\n" +
"MGMGA1UdIwRcMFqAFLl81dnfp0wDrv0OJ1sxlWzH83XhoT+kPTA7MQswCQYDVQQG\n" +
"EwJVUzENMAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2\n" +
"Y2WCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEE\n" +
"BQADgYEALlgaH1gWtoBZ84EW8Hu6YtGLQ/L9zIFmHonUPZwn3Pr//icR9Sqhc3/l\n" +
"pVTxOINuFHLRz4BBtEylzRIOPzK3tg8XwuLb1zd0db90x3KBCiAL6E6cklGEPwLe\n" +
"XYMHDn9eDsaq861Tzn6ZwzMgw04zotPMoZN0mVd/3Qca8UJFucE=\n" +
"-----END CERTIFICATE-----";
static String targetCertStr =
"-----BEGIN CERTIFICATE-----\n" +
"MIICNDCCAZ2gAwIBAgIBDDANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" +
"MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" +
"MTExMTA3MTM1NTUyWhcNMzEwNzI1MTM1NTUyWjBPMQswCQYDVQQGEwJVUzENMAsG\n" +
"A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxEjAQBgNV\n" +
"BAMTCWxvY2FsaG9zdDBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQC3Pb49OSPfOD2G\n" +
"HSXFCFx1GJEZfqG9ZUf7xuIi/ra5dLjPGAaoY5QF2QOa8VnOriQCXDfyXHxsuRnE\n" +
"OomxL7EVAgMBAAGjeDB2MAsGA1UdDwQEAwID6DAdBgNVHQ4EFgQUXNCJK3/dtCIc\n" +
"xb+zlA/JINlvs/MwHwYDVR0jBBgwFoAUuXzV2d+nTAOu/Q4nWzGVbMfzdeEwJwYD\n" +
"VR0lBCAwHgYIKwYBBQUHAwEGCCsGAQUFBwMCBggrBgEFBQcDAzANBgkqhkiG9w0B\n" +
"AQQFAAOBgQB2qIDUxA2caMPpGtUACZAPRUtrGssCINIfItETXJZCx/cRuZ5sP4D9\n" +
"N1acoNDn0hCULe3lhXAeTC9NZ97680yJzregQMV5wATjo1FGsKY30Ma+sc/nfzQW\n" +
"+h/7RhYtoG0OTsiaDCvyhI6swkNJzSzrAccPY4+ZgU8HiDLzZTmM3Q==\n" +
"-----END CERTIFICATE-----";
// Private key in the format of PKCS#8, key size is 512 bits.
static String targetPrivateKey =
"MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAtz2+PTkj3zg9hh0l\n" +
"xQhcdRiRGX6hvWVH+8biIv62uXS4zxgGqGOUBdkDmvFZzq4kAlw38lx8bLkZxDqJ\n" +
"sS+xFQIDAQABAkByx/5Oo2hQ/w2q4L8z+NTRlJ3vdl8iIDtC/4XPnfYfnGptnpG6\n" +
"ZThQRvbMZiai0xHQPQMszvAHjZVme1eDl3EBAiEA3aKJHynPVCEJhpfCLWuMwX5J\n" +
"1LntwJO7NTOyU5m8rPECIQDTpzn5X44r2rzWBDna/Sx7HW9IWCxNgUD2Eyi2nA7W\n" +
"ZQIgJerEorw4aCAuzQPxiGu57PB6GRamAihEAtoRTBQlH0ECIQDN08FgTtnesgCU\n" +
"DFYLLcw1CiHvc7fZw4neBDHCrC8NtQIgA8TOUkGnpCZlQ0KaI8KfKWI+vxFcgFnH\n" +
"3fnqsTgaUs4=";
static char passphrase[] = "passphrase".toCharArray();
/*
* Is the server ready to serve?
*/
volatile static boolean serverReady = false;
/*
* Turn on SSL debugging?
*/
static boolean debug = false;
/*
* 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 {
SSLContext context = generateSSLContext(null, targetCertStr,
targetPrivateKey);
SSLServerSocketFactory sslssf = context.getServerSocketFactory();
SSLServerSocket sslServerSocket =
(SSLServerSocket)sslssf.createServerSocket(serverPort);
serverPort = sslServerSocket.getLocalPort();
/*
* Signal Client, we're ready for his connect.
*/
serverReady = true;
SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept();
sslSocket.setEnabledCipherSuites(sslSocket.getSupportedCipherSuites());
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);
}
SSLContext context = generateSSLContext(trustedCertStr, null, null);
SSLSocketFactory sslsf = context.getSocketFactory();
SSLSocket sslSocket =
(SSLSocket)sslsf.createSocket("localhost", serverPort);
// enable TLSv1.2 only
sslSocket.setEnabledProtocols(new String[] {"TLSv1.2"});
// enable a block cipher
sslSocket.setEnabledCipherSuites(new String[] {cipherSuite});
InputStream sslIS = sslSocket.getInputStream();
OutputStream sslOS = sslSocket.getOutputStream();
sslOS.write('B');
sslOS.flush();
sslIS.read();
sslSocket.close();
}
/*
* =============================================================
* The remainder is just support stuff
*/
private static String tmAlgorithm; // trust manager
private static String cipherSuite; // cipher suite
private static void parseArguments(String[] args) {
tmAlgorithm = args[0];
cipherSuite = args[1];
}
private static SSLContext generateSSLContext(String trustedCertStr,
String keyCertStr, String keySpecStr) throws Exception {
// generate certificate from cert string
CertificateFactory cf = CertificateFactory.getInstance("X.509");
// create a key store
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(null, null);
// import the trused cert
Certificate trusedCert = null;
ByteArrayInputStream is = null;
if (trustedCertStr != null) {
is = new ByteArrayInputStream(trustedCertStr.getBytes());
trusedCert = cf.generateCertificate(is);
is.close();
ks.setCertificateEntry("RSA Export Signer", trusedCert);
}
if (keyCertStr != null) {
// generate the private key.
PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(
new BASE64Decoder().decodeBuffer(keySpecStr));
KeyFactory kf = KeyFactory.getInstance("RSA");
RSAPrivateKey priKey =
(RSAPrivateKey)kf.generatePrivate(priKeySpec);
// generate certificate chain
is = new ByteArrayInputStream(keyCertStr.getBytes());
Certificate keyCert = cf.generateCertificate(is);
is.close();
Certificate[] chain = null;
if (trusedCert != null) {
chain = new Certificate[2];
chain[0] = keyCert;
chain[1] = trusedCert;
} else {
chain = new Certificate[1];
chain[0] = keyCert;
}
// import the key entry.
ks.setKeyEntry("Whatever", priKey, passphrase, chain);
}
// create SSL context
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmAlgorithm);
tmf.init(ks);
SSLContext ctx = SSLContext.getInstance("TLS");
if (keyCertStr != null && !keyCertStr.isEmpty()) {
KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509");
kmf.init(ks, passphrase);
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
ks = null;
} else {
ctx.init(null, tmf.getTrustManagers(), null);
}
return ctx;
}
// 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 {
// reset the security property to make sure that the algorithms
// and keys used in this test are not disabled.
Security.setProperty("jdk.certpath.disabledAlgorithms", "MD2");
if (debug) {
System.setProperty("javax.net.debug", "all");
}
/*
* Get the customized arguments.
*/
parseArguments(args);
/*
* Start the tests.
*/
new ShortRSAKeyGCM();
}
Thread clientThread = null;
Thread serverThread = null;
/*
* Primary constructor, used to drive remainder of the test.
*
* Fork off the other side, then do your work.
*/
ShortRSAKeyGCM() 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..." + e);
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..." + e);
clientException = e;
}
}
};
clientThread.start();
} else {
try {
doClientSide();
} catch (Exception e) {
clientException = e;
}
}
}
}
...@@ -21,13 +21,15 @@ ...@@ -21,13 +21,15 @@
* questions. * questions.
*/ */
//
// SunJSSE does not support dynamic system properties, no way to re-use
// system properties in samevm/agentvm mode.
//
/* /*
* @test * @test
* @bug 7174244 * @bug 7174244
* @summary NPE in Krb5ProxyImpl.getServerKeys() * @summary NPE in Krb5ProxyImpl.getServerKeys()
*
* SunJSSE does not support dynamic system properties, no way to re-use
* system properties in samevm/agentvm mode.
* @run main/othervm CipherSuitesInOrder * @run main/othervm CipherSuitesInOrder
*/ */
...@@ -72,6 +74,22 @@ public class CipherSuitesInOrder { ...@@ -72,6 +74,22 @@ public class CipherSuitesInOrder {
"SSL_RSA_WITH_RC4_128_SHA", "SSL_RSA_WITH_RC4_128_SHA",
"TLS_ECDH_ECDSA_WITH_RC4_128_SHA", "TLS_ECDH_ECDSA_WITH_RC4_128_SHA",
"TLS_ECDH_RSA_WITH_RC4_128_SHA", "TLS_ECDH_RSA_WITH_RC4_128_SHA",
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_RSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384",
"TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_RSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",
"TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
"SSL_RSA_WITH_3DES_EDE_CBC_SHA", "SSL_RSA_WITH_3DES_EDE_CBC_SHA",
...@@ -83,6 +101,9 @@ public class CipherSuitesInOrder { ...@@ -83,6 +101,9 @@ public class CipherSuitesInOrder {
"TLS_EMPTY_RENEGOTIATION_INFO_SCSV", "TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
"TLS_DH_anon_WITH_AES_256_GCM_SHA384",
"TLS_DH_anon_WITH_AES_128_GCM_SHA256",
"TLS_DH_anon_WITH_AES_256_CBC_SHA256", "TLS_DH_anon_WITH_AES_256_CBC_SHA256",
"TLS_ECDH_anon_WITH_AES_256_CBC_SHA", "TLS_ECDH_anon_WITH_AES_256_CBC_SHA",
"TLS_DH_anon_WITH_AES_256_CBC_SHA", "TLS_DH_anon_WITH_AES_256_CBC_SHA",
......
/* /*
* Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -148,6 +148,25 @@ public class CipherTest { ...@@ -148,6 +148,25 @@ public class CipherTest {
CS_16("TLS_DH_anon_WITH_AES_128_CBC_SHA256", 0x0303, 0xFFFF), CS_16("TLS_DH_anon_WITH_AES_128_CBC_SHA256", 0x0303, 0xFFFF),
CS_17("TLS_RSA_WITH_NULL_SHA256", 0x0303, 0xFFFF), CS_17("TLS_RSA_WITH_NULL_SHA256", 0x0303, 0xFFFF),
CS_20("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
CS_21("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
CS_22("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
CS_23("TLS_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
CS_24("TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
CS_25("TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
CS_26("TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
CS_27("TLS_DHE_DSS_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
CS_28("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
CS_29("TLS_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
CS_30("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
CS_31("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
CS_32("TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
CS_33("TLS_DHE_DSS_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
CS_34("TLS_DH_anon_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
CS_35("TLS_DH_anon_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
// cipher suites obsoleted since TLS 1.2 // cipher suites obsoleted since TLS 1.2
CS_50("SSL_RSA_WITH_DES_CBC_SHA", 0x0000, 0x0303), CS_50("SSL_RSA_WITH_DES_CBC_SHA", 0x0000, 0x0303),
CS_51("SSL_DHE_RSA_WITH_DES_CBC_SHA", 0x0000, 0x0303), CS_51("SSL_DHE_RSA_WITH_DES_CBC_SHA", 0x0000, 0x0303),
......
/* /*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -21,14 +21,15 @@ ...@@ -21,14 +21,15 @@
* questions. * questions.
*/ */
//
// SunJSSE does not support dynamic system properties, no way to re-use
// system properties in samevm/agentvm mode.
//
/* /*
* @test * @test
* @bug 7105780 * @bug 7105780
* @summary Add SSLSocket client/SSLEngine server to templates directory. * @summary Add SSLSocket client/SSLEngine server to templates directory.
*
* SunJSSE does not support dynamic system properties, no way to re-use
* system properties in samevm/agentvm mode.
*
* @run main/othervm SSLSocketSSLEngineTemplate * @run main/othervm SSLSocketSSLEngineTemplate
*/ */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册