This commit is contained in:
Lana Steuck 2010-11-02 19:40:45 -07:00
commit fba090f3e8
186 changed files with 13538 additions and 3711 deletions

View File

@ -413,6 +413,7 @@ JAVA_JAVA_java = \
java/io/FilePermission.java \
java/io/Serializable.java \
java/io/Externalizable.java \
java/io/SerialCallbackContext.java \
java/io/Bits.java \
java/io/ObjectInput.java \
java/io/ObjectInputStream.java \

View File

@ -148,14 +148,9 @@ include $(BUILDDIR)/common/Library.gmk
#
ifeq ($(PLATFORM), windows)
STATIC_LIBRARY_DIR = $(OBJDIR)/static
STATIC_LIBRARY_NAME = $(LIBPREFIX)$(LIBRARY).lib
STATIC_LIBRARY = $(STATIC_LIBRARY_DIR)/$(STATIC_LIBRARY_NAME)
STATIC_LIBRARY = $(OBJDIR)/static/$(LIBPREFIX)$(LIBRARY).lib
$(STATIC_LIBRARY_DIR): $(OBJDIR)
@$(MKDIR) $(STATIC_LIBRARY_DIR)
$(STATIC_LIBRARY): $(STATIC_LIBRARY_DIR)
$(STATIC_LIBRARY): $(FILES_o)
@$(prep-target)
$(LIBEXE) -nologo -out:$@ $(FILES_o)

View File

@ -33,7 +33,6 @@ FILES_src = \
java/nio/channels/AsynchronousByteChannel.java \
java/nio/channels/AsynchronousChannel.java \
java/nio/channels/AsynchronousChannelGroup.java \
java/nio/channels/AsynchronousDatagramChannel.java \
java/nio/channels/AsynchronousFileChannel.java \
java/nio/channels/AsynchronousServerSocketChannel.java \
java/nio/channels/AsynchronousSocketChannel.java \
@ -207,7 +206,6 @@ FILES_src = \
sun/nio/ch/SelChImpl.java \
sun/nio/ch/ServerSocketAdaptor.java \
sun/nio/ch/ServerSocketChannelImpl.java \
sun/nio/ch/SimpleAsynchronousDatagramChannelImpl.java \
sun/nio/ch/SinkChannelImpl.java \
sun/nio/ch/SocketAdaptor.java \
sun/nio/ch/SocketChannelImpl.java \

View File

@ -48,8 +48,8 @@ jar.jmx.name = jmx.jar
jar.jmx.sealed = true
jar.jmx.spec.title = JSR 003, 160, 255 - JMX API
jar.jmx.spec.version = ${project.spec.version}
jar.jmx.spec.vendor = Sun Microsystems, Inc.
jar.jmx.impl.title = JSR 003, 160, 255 - OpenJDK 7 JMX API
jar.jmx.spec.vendor = Oracle Corporation
jar.jmx.impl.title = JSR 003, 160, 255 - OpenJDK 7 JMX API
jar.jmx.impl.vendor = Project OpenJDK
javadoc.options=-J-Xmx256m

View File

@ -355,7 +355,6 @@ JavaMain(void * _args)
JavaVM *vm = 0;
JNIEnv *env = 0;
jstring mainClassName;
jclass mainClass;
jmethodID mainID;
jobjectArray mainArgs;

View File

@ -72,7 +72,7 @@ inflate_file(int fd, zentry *entry, int *size_out)
if (entry->how == STORED) {
*(char *)((size_t)in + entry->csize) = '\0';
if (size_out) {
*size_out = entry->csize;
*size_out = (int)entry->csize;
}
return (in);
} else if (entry->how == DEFLATED) {
@ -103,7 +103,7 @@ inflate_file(int fd, zentry *entry, int *size_out)
return (NULL);
}
if (size_out) {
*size_out = entry->isize;
*size_out = (int)entry->isize;
}
return (out);
} else
@ -317,7 +317,7 @@ find_file(int fd, zentry *entry, const char *file_name)
* manifest. If so, build the entry record from the data found in
* the header located and return success.
*/
if (CENNAM(p) == JLI_StrLen(file_name) &&
if ((size_t)CENNAM(p) == JLI_StrLen(file_name) &&
memcmp((p + CENHDR), file_name, JLI_StrLen(file_name)) == 0) {
if (lseek(fd, base_offset + CENOFF(p), SEEK_SET) < (off_t)0) {
free(buffer);
@ -606,8 +606,5 @@ JLI_ManifestIterate(const char *jarfile, attribute_closure ac, void *user_data)
}
free(mp);
close(fd);
if (rc == 0)
return (0);
else
return (-2);
return (rc == 0) ? 0 : -2;
}

View File

@ -290,12 +290,12 @@ FileList_join(FileList fl, char sep)
char *path;
char *p;
for (i = 0, size = 1; i < fl->size; i++)
size += JLI_StrLen(fl->files[i]) + 1;
size += (int)JLI_StrLen(fl->files[i]) + 1;
path = JLI_MemAlloc(size);
for (i = 0, p = path; i < fl->size; i++) {
int len = JLI_StrLen(fl->files[i]);
int len = (int)JLI_StrLen(fl->files[i]);
if (i > 0) *p++ = sep;
memcpy(p, fl->files[i], len);
p += len;
@ -309,7 +309,7 @@ static FileList
FileList_split(const char *path, char sep)
{
const char *p, *q;
int len = JLI_StrLen(path);
int len = (int)JLI_StrLen(path);
int count;
FileList fl;
for (count = 1, p = path; p < path + len; p++)
@ -330,7 +330,7 @@ FileList_split(const char *path, char sep)
static int
isJarFileName(const char *filename)
{
int len = JLI_StrLen(filename);
int len = (int)JLI_StrLen(filename);
return (len >= 4) &&
(filename[len - 4] == '.') &&
(equal(filename + len - 3, "jar") ||
@ -342,8 +342,8 @@ isJarFileName(const char *filename)
static char *
wildcardConcat(const char *wildcard, const char *basename)
{
int wildlen = JLI_StrLen(wildcard);
int baselen = JLI_StrLen(basename);
int wildlen = (int)JLI_StrLen(wildcard);
int baselen = (int)JLI_StrLen(basename);
char *filename = (char *) JLI_MemAlloc(wildlen + baselen);
/* Replace the trailing '*' with basename */
memcpy(filename, wildcard, wildlen-1);
@ -369,7 +369,7 @@ wildcardFileList(const char *wildcard)
static int
isWildcard(const char *filename)
{
int len = JLI_StrLen(filename);
int len = (int)JLI_StrLen(filename);
return (len > 0) &&
(filename[len - 1] == '*') &&
(len == 1 || IS_FILE_SEPARATOR(filename[len - 2])) &&

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -253,7 +253,8 @@ final class AESCrypt extends SymmetricCipher implements AESConstants
for (j = 0; j < 8; j++) {
if (AA[i][j] != 0) {
AA[i][j] = (byte)
alog[(255 + log[AA[i][j] & 0xFF] - log[pivot & 0xFF]) % 255];
alog[(255 + log[AA[i][j] & 0xFF] - log[pivot & 0xFF])
% 255];
}
}
for (t = 0; t < 4; t++) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -92,7 +92,8 @@ public final class ARCFOURCipher extends CipherSpi {
}
// core crypt code. OFB style, so works for both encryption and decryption
private void crypt(byte[] in, int inOfs, int inLen, byte[] out, int outOfs) {
private void crypt(byte[] in, int inOfs, int inLen, byte[] out,
int outOfs) {
if (is < 0) {
// doFinal() was called, need to reset the cipher to initial state
init(lastKey);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -31,8 +31,8 @@ import javax.crypto.*;
import javax.crypto.spec.*;
/**
* This class implements the DESede algorithm (DES-EDE, tripleDES) in its various
* modes (<code>ECB</code>, <code>CFB</code>, <code>OFB</code>,
* This class implements the DESede algorithm (DES-EDE, tripleDES) in
* its various modes (<code>ECB</code>, <code>CFB</code>, <code>OFB</code>,
* <code>CBC</code>, <code>PCBC</code>) and padding schemes
* (<code>PKCS5Padding</code>, <code>NoPadding</code>,
* <code>ISO10126Padding</code>).

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -190,7 +190,8 @@ javax.crypto.interfaces.DHPrivateKey, Serializable {
ike.initCause(e);
throw ike;
} catch (IOException e) {
InvalidKeyException ike = new InvalidKeyException("Error parsing key encoding: " + e.getMessage());
InvalidKeyException ike = new InvalidKeyException(
"Error parsing key encoding: " + e.getMessage());
ike.initCause(e);
throw ike;
}
@ -300,7 +301,8 @@ javax.crypto.interfaces.DHPrivateKey, Serializable {
DerInputStream in = new DerInputStream(this.key);
this.x = in.getBigInteger();
} catch (IOException e) {
InvalidKeyException ike = new InvalidKeyException("Error parsing key encoding: " + e.getMessage());
InvalidKeyException ike = new InvalidKeyException(
"Error parsing key encoding: " + e.getMessage());
ike.initCause(e);
throw ike;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -180,7 +180,8 @@ javax.crypto.interfaces.DHPublicKey, Serializable {
throw new InvalidKeyException("Private-value length too big");
} catch (IOException e) {
throw new InvalidKeyException("Error parsing key encoding: " + e.toString());
throw new InvalidKeyException(
"Error parsing key encoding: " + e.toString());
}
}
@ -281,7 +282,8 @@ javax.crypto.interfaces.DHPublicKey, Serializable {
DerInputStream in = new DerInputStream(this.key);
this.y = in.getBigInteger();
} catch (IOException e) {
throw new InvalidKeyException("Error parsing key encoding: " + e.toString());
throw new InvalidKeyException(
"Error parsing key encoding: " + e.toString());
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -764,7 +764,8 @@ public final class JceKeyStore extends KeyStoreSpi {
cf = (CertificateFactory)cfs.get(certType);
} else {
// create new certificate factory
cf = CertificateFactory.getInstance(certType);
cf = CertificateFactory.getInstance(
certType);
// store the certificate factory so we can
// reuse it later
cfs.put(certType, cf);
@ -863,8 +864,9 @@ public final class JceKeyStore extends KeyStoreSpi {
dis.readFully(actual);
for (int i = 0; i < computed.length; i++) {
if (computed[i] != actual[i]) {
throw new IOException("Keystore was tampered with, or "
+ "password was incorrect");
throw new IOException(
"Keystore was tampered with, or "
+ "password was incorrect");
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -139,7 +139,8 @@ public final class OAEPParameters extends AlgorithmParametersSpi {
if (!val.getOID().equals((Object) OID_MGF1)) {
throw new IOException("Only MGF1 mgf is supported");
}
AlgorithmId params = AlgorithmId.parse(new DerValue(val.getEncodedParams()));
AlgorithmId params = AlgorithmId.parse(
new DerValue(val.getEncodedParams()));
String mgfDigestName = convertToStandardName(params.getName());
if (mgfDigestName.equals("SHA-1")) {
mgfSpec = MGF1ParameterSpec.SHA1;
@ -150,7 +151,8 @@ public final class OAEPParameters extends AlgorithmParametersSpi {
} else if (mgfDigestName.equals("SHA-512")) {
mgfSpec = MGF1ParameterSpec.SHA512;
} else {
throw new IOException("Unrecognized message digest algorithm");
throw new IOException(
"Unrecognized message digest algorithm");
}
} else if (data.isContextSpecific((byte) 0x02)) {
// pSource algid

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -121,8 +121,8 @@ final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey {
this.key = deriveKey(prf, passwdBytes, salt, iterCount, keyLength);
}
private static byte[] deriveKey(final Mac prf, final byte[] password, byte[] salt,
int iterCount, int keyLengthInBit) {
private static byte[] deriveKey(final Mac prf, final byte[] password,
byte[] salt, int iterCount, int keyLengthInBit) {
int keyLength = keyLengthInBit/8;
byte[] key = new byte[keyLength];
try {
@ -155,8 +155,9 @@ final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey {
if (this == obj) return true;
if (this.getClass() != obj.getClass()) return false;
SecretKey sk = (SecretKey)obj;
return prf.getAlgorithm().equalsIgnoreCase(sk.getAlgorithm()) &&
Arrays.equals(password, sk.getEncoded());
return prf.getAlgorithm().equalsIgnoreCase(
sk.getAlgorithm()) &&
Arrays.equals(password, sk.getEncoded());
}
};
prf.init(macKey);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -206,7 +206,8 @@ final class PKCS12PBECipherCore {
(algo.equalsIgnoreCase("RC2")?"RC2_40":algo), "SunJCE");
} catch (GeneralSecurityException gse) {
// should never happen
throw new RuntimeException("SunJCE provider is not configured properly");
throw new RuntimeException(
"SunJCE provider is not configured properly");
}
try {
params.init(pbeSpec);
@ -316,7 +317,8 @@ final class PKCS12PBECipherCore {
try {
paramSpec = params.getParameterSpec(PBEParameterSpec.class);
} catch (InvalidParameterSpecException ipse) {
throw new InvalidAlgorithmParameterException("requires PBE parameters");
throw new InvalidAlgorithmParameterException(
"requires PBE parameters");
}
}
implInit(opmode, key, paramSpec, random);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -423,15 +423,31 @@ public final class SunJCE extends Provider {
/*
* SSL/TLS mechanisms
*
* These are strictly internal implementations and may
* be changed at any time. These names were chosen
* because PKCS11/SunPKCS11 does not yet have TLS1.2
* mechanisms, and it will cause calls to come here.
*/
put("KeyGenerator.SunTlsPrf",
"com.sun.crypto.provider.TlsPrfGenerator");
put("KeyGenerator.SunTlsRsaPremasterSecret",
"com.sun.crypto.provider.TlsRsaPremasterSecretGenerator");
"com.sun.crypto.provider.TlsPrfGenerator$V10");
put("KeyGenerator.SunTls12Prf",
"com.sun.crypto.provider.TlsPrfGenerator$V12");
put("KeyGenerator.SunTlsMasterSecret",
"com.sun.crypto.provider.TlsMasterSecretGenerator");
"com.sun.crypto.provider.TlsMasterSecretGenerator");
put("Alg.Alias.KeyGenerator.SunTls12MasterSecret",
"SunTlsMasterSecret");
put("KeyGenerator.SunTlsKeyMaterial",
"com.sun.crypto.provider.TlsKeyMaterialGenerator");
"com.sun.crypto.provider.TlsKeyMaterialGenerator");
put("Alg.Alias.KeyGenerator.SunTls12KeyMaterial",
"SunTlsKeyMaterial");
put("KeyGenerator.SunTlsRsaPremasterSecret",
"com.sun.crypto.provider.TlsRsaPremasterSecretGenerator");
put("Alg.Alias.KeyGenerator.SunTls12RsaPremasterSecret",
"SunTlsRsaPremasterSecret");
return null;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -65,12 +65,14 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
}
this.spec = (TlsKeyMaterialParameterSpec)params;
if ("RAW".equals(spec.getMasterSecret().getFormat()) == false) {
throw new InvalidAlgorithmParameterException("Key format must be RAW");
throw new InvalidAlgorithmParameterException(
"Key format must be RAW");
}
protocolVersion = (spec.getMajorVersion() << 8) | spec.getMinorVersion();
if ((protocolVersion < 0x0300) || (protocolVersion > 0x0302)) {
throw new InvalidAlgorithmParameterException
("Only SSL 3.0, TLS 1.0, and TLS 1.1 supported");
protocolVersion = (spec.getMajorVersion() << 8)
| spec.getMinorVersion();
if ((protocolVersion < 0x0300) || (protocolVersion > 0x0303)) {
throw new InvalidAlgorithmParameterException(
"Only SSL 3.0, TLS 1.0/1.1/1.2 supported");
}
}
@ -80,8 +82,8 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
protected SecretKey engineGenerateKey() {
if (spec == null) {
throw new IllegalStateException
("TlsKeyMaterialGenerator must be initialized");
throw new IllegalStateException(
"TlsKeyMaterialGenerator must be initialized");
}
try {
return engineGenerateKey0();
@ -99,8 +101,8 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
SecretKey clientMacKey = null;
SecretKey serverMacKey = null;
SecretKey clientCipherKey = null;
IvParameterSpec clientIv = null;
SecretKey serverCipherKey = null;
IvParameterSpec clientIv = null;
IvParameterSpec serverIv = null;
int macLength = spec.getMacKeyLength();
@ -109,21 +111,33 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
int keyLength = spec.getCipherKeyLength();
int ivLength = spec.getIvLength();
int keyBlockLen = macLength + keyLength + (isExportable ? 0 : ivLength);
int keyBlockLen = macLength + keyLength
+ (isExportable ? 0 : ivLength);
keyBlockLen <<= 1;
byte[] keyBlock = new byte[keyBlockLen];
MessageDigest md5 = MessageDigest.getInstance("MD5");
MessageDigest sha = MessageDigest.getInstance("SHA1");
// These may be used again later for exportable suite calculations.
MessageDigest md5 = null;
MessageDigest sha = null;
// generate key block
if (protocolVersion >= 0x0301) {
// TLS
if (protocolVersion >= 0x0303) {
// TLS 1.2
byte[] seed = concat(serverRandom, clientRandom);
keyBlock = doPRF(masterSecret, LABEL_KEY_EXPANSION, seed,
keyBlock = doTLS12PRF(masterSecret, LABEL_KEY_EXPANSION, seed,
keyBlockLen, spec.getPRFHashAlg(),
spec.getPRFHashLength(), spec.getPRFBlockSize());
} else if (protocolVersion >= 0x0301) {
// TLS 1.0/1.1
md5 = MessageDigest.getInstance("MD5");
sha = MessageDigest.getInstance("SHA1");
byte[] seed = concat(serverRandom, clientRandom);
keyBlock = doTLS10PRF(masterSecret, LABEL_KEY_EXPANSION, seed,
keyBlockLen, md5, sha);
} else {
// SSL
md5 = MessageDigest.getInstance("MD5");
sha = MessageDigest.getInstance("SHA1");
keyBlock = new byte[keyBlockLen];
byte[] tmp = new byte[20];
@ -169,6 +183,7 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
String alg = spec.getCipherAlgorithm();
// cipher keys
byte[] clientKeyBytes = new byte[keyLength];
System.arraycopy(keyBlock, ofs, clientKeyBytes, 0, keyLength);
ofs += keyLength;
@ -182,6 +197,7 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
clientCipherKey = new SecretKeySpec(clientKeyBytes, alg);
serverCipherKey = new SecretKeySpec(serverKeyBytes, alg);
// IV keys if needed.
if (ivLength != 0) {
tmp = new byte[ivLength];
@ -194,21 +210,28 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
serverIv = new IvParameterSpec(tmp);
}
} else {
// if exportable suites, calculate the alternate
// cipher key expansion and IV generation
if (protocolVersion >= 0x0301) {
if (protocolVersion >= 0x0302) {
// TLS 1.1+
throw new RuntimeException(
"Internal Error: TLS 1.1+ should not be negotiating" +
"exportable ciphersuites");
} else if (protocolVersion == 0x0301) {
// TLS 1.0
byte[] seed = concat(clientRandom, serverRandom);
tmp = doPRF(clientKeyBytes, LABEL_CLIENT_WRITE_KEY, seed,
tmp = doTLS10PRF(clientKeyBytes, LABEL_CLIENT_WRITE_KEY, seed,
expandedKeyLength, md5, sha);
clientCipherKey = new SecretKeySpec(tmp, alg);
tmp = doPRF(serverKeyBytes, LABEL_SERVER_WRITE_KEY, seed,
tmp = doTLS10PRF(serverKeyBytes, LABEL_SERVER_WRITE_KEY, seed,
expandedKeyLength, md5, sha);
serverCipherKey = new SecretKeySpec(tmp, alg);
if (ivLength != 0) {
tmp = new byte[ivLength];
byte[] block = doPRF(null, LABEL_IV_BLOCK, seed,
byte[] block = doTLS10PRF(null, LABEL_IV_BLOCK, seed,
ivLength << 1, md5, sha);
System.arraycopy(block, 0, tmp, 0, ivLength);
clientIv = new IvParameterSpec(tmp);
@ -216,6 +239,7 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
serverIv = new IvParameterSpec(tmp);
}
} else {
// SSLv3
tmp = new byte[expandedKeyLength];
md5.update(clientKeyBytes);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -64,12 +64,14 @@ public final class TlsMasterSecretGenerator extends KeyGeneratorSpi {
}
this.spec = (TlsMasterSecretParameterSpec)params;
if ("RAW".equals(spec.getPremasterSecret().getFormat()) == false) {
throw new InvalidAlgorithmParameterException("Key format must be RAW");
throw new InvalidAlgorithmParameterException(
"Key format must be RAW");
}
protocolVersion = (spec.getMajorVersion() << 8) | spec.getMinorVersion();
if ((protocolVersion < 0x0300) || (protocolVersion > 0x0302)) {
throw new InvalidAlgorithmParameterException
("Only SSL 3.0, TLS 1.0, and TLS 1.1 supported");
protocolVersion = (spec.getMajorVersion() << 8)
| spec.getMinorVersion();
if ((protocolVersion < 0x0300) || (protocolVersion > 0x0303)) {
throw new InvalidAlgorithmParameterException(
"Only SSL 3.0, TLS 1.0/1.1/1.2 supported");
}
}
@ -79,8 +81,8 @@ public final class TlsMasterSecretGenerator extends KeyGeneratorSpi {
protected SecretKey engineGenerateKey() {
if (spec == null) {
throw new IllegalStateException
("TlsMasterSecretGenerator must be initialized");
throw new IllegalStateException(
"TlsMasterSecretGenerator must be initialized");
}
SecretKey premasterKey = spec.getPremasterSecret();
byte[] premaster = premasterKey.getEncoded();
@ -103,7 +105,11 @@ public final class TlsMasterSecretGenerator extends KeyGeneratorSpi {
if (protocolVersion >= 0x0301) {
byte[] seed = concat(clientRandom, serverRandom);
master = doPRF(premaster, LABEL_MASTER_SECRET, seed, 48);
master = ((protocolVersion >= 0x0303) ?
doTLS12PRF(premaster, LABEL_MASTER_SECRET, seed, 48,
spec.getPRFHashAlg(), spec.getPRFHashLength(),
spec.getPRFBlockSize()) :
doTLS10PRF(premaster, LABEL_MASTER_SECRET, seed, 48));
} else {
master = new byte[48];
MessageDigest md5 = MessageDigest.getInstance("MD5");
@ -124,7 +130,8 @@ public final class TlsMasterSecretGenerator extends KeyGeneratorSpi {
}
return new TlsMasterSecretKey(master, premasterMajor, premasterMinor);
return new TlsMasterSecretKey(master, premasterMajor,
premasterMinor);
} catch (NoSuchAlgorithmException e) {
throw new ProviderException(e);
} catch (DigestException e) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -37,11 +37,15 @@ import sun.security.internal.spec.TlsPrfParameterSpec;
/**
* KeyGenerator implementation for the TLS PRF function.
* <p>
* This class duplicates the HMAC functionality (RFC 2104) with
* performance optimizations (e.g. XOR'ing keys with padding doesn't
* need to be redone for each HMAC operation).
*
* @author Andreas Sterbenz
* @since 1.6
*/
public final class TlsPrfGenerator extends KeyGeneratorSpi {
abstract class TlsPrfGenerator extends KeyGeneratorSpi {
// magic constants and utility functions, also used by other files
// in this package
@ -69,8 +73,10 @@ public final class TlsPrfGenerator extends KeyGeneratorSpi {
* TLS HMAC "inner" and "outer" padding. This isn't a function
* of the digest algorithm.
*/
private static final byte[] HMAC_ipad = genPad((byte)0x36, 64);
private static final byte[] HMAC_opad = genPad((byte)0x5c, 64);
private static final byte[] HMAC_ipad64 = genPad((byte)0x36, 64);
private static final byte[] HMAC_ipad128 = genPad((byte)0x36, 128);
private static final byte[] HMAC_opad64 = genPad((byte)0x5c, 64);
private static final byte[] HMAC_opad128 = genPad((byte)0x5c, 128);
// SSL3 magic mix constants ("A", "BB", "CCC", ...)
final static byte[][] SSL3_CONST = genConst();
@ -123,8 +129,8 @@ public final class TlsPrfGenerator extends KeyGeneratorSpi {
this.spec = (TlsPrfParameterSpec)params;
SecretKey key = spec.getSecret();
if ((key != null) && ("RAW".equals(key.getFormat()) == false)) {
throw new InvalidAlgorithmParameterException
("Key encoding format must be RAW");
throw new InvalidAlgorithmParameterException(
"Key encoding format must be RAW");
}
}
@ -132,17 +138,21 @@ public final class TlsPrfGenerator extends KeyGeneratorSpi {
throw new InvalidParameterException(MSG);
}
protected SecretKey engineGenerateKey() {
SecretKey engineGenerateKey0(boolean tls12) {
if (spec == null) {
throw new IllegalStateException
("TlsPrfGenerator must be initialized");
throw new IllegalStateException(
"TlsPrfGenerator must be initialized");
}
SecretKey key = spec.getSecret();
byte[] secret = (key == null) ? null : key.getEncoded();
try {
byte[] labelBytes = spec.getLabel().getBytes("UTF8");
int n = spec.getOutputLength();
byte[] prfBytes = doPRF(secret, labelBytes, spec.getSeed(), n);
byte[] prfBytes = (tls12 ?
doTLS12PRF(secret, labelBytes, spec.getSeed(), n,
spec.getPRFHashAlg(), spec.getPRFHashLength(),
spec.getPRFBlockSize()) :
doTLS10PRF(secret, labelBytes, spec.getSeed(), n));
return new SecretKeySpec(prfBytes, "TlsPrf");
} catch (GeneralSecurityException e) {
throw new ProviderException("Could not generate PRF", e);
@ -151,16 +161,67 @@ public final class TlsPrfGenerator extends KeyGeneratorSpi {
}
}
static final byte[] doPRF(byte[] secret, byte[] labelBytes, byte[] seed,
int outputLength) throws NoSuchAlgorithmException, DigestException {
MessageDigest md5 = MessageDigest.getInstance("MD5");
MessageDigest sha = MessageDigest.getInstance("SHA1");
return doPRF(secret, labelBytes, seed, outputLength, md5, sha);
static byte[] doTLS12PRF(byte[] secret, byte[] labelBytes,
byte[] seed, int outputLength,
String prfHash, int prfHashLength, int prfBlockSize)
throws NoSuchAlgorithmException, DigestException {
if (prfHash == null) {
throw new NoSuchAlgorithmException("Unspecified PRF algorithm");
}
MessageDigest prfMD = MessageDigest.getInstance(prfHash);
return doTLS12PRF(secret, labelBytes, seed, outputLength,
prfMD, prfHashLength, prfBlockSize);
}
static final byte[] doPRF(byte[] secret, byte[] labelBytes, byte[] seed,
int outputLength, MessageDigest md5, MessageDigest sha)
static byte[] doTLS12PRF(byte[] secret, byte[] labelBytes,
byte[] seed, int outputLength,
MessageDigest mdPRF, int mdPRFLen, int mdPRFBlockSize)
throws DigestException {
if (secret == null) {
secret = B0;
}
// If we have a long secret, digest it first.
if (secret.length > mdPRFBlockSize) {
secret = mdPRF.digest(secret);
}
byte[] output = new byte[outputLength];
byte [] ipad;
byte [] opad;
switch (mdPRFBlockSize) {
case 64:
ipad = HMAC_ipad64.clone();
opad = HMAC_opad64.clone();
break;
case 128:
ipad = HMAC_ipad128.clone();
opad = HMAC_opad128.clone();
break;
default:
throw new DigestException("Unexpected block size.");
}
// P_HASH(Secret, label + seed)
expand(mdPRF, mdPRFLen, secret, 0, secret.length, labelBytes,
seed, output, ipad, opad);
return output;
}
static byte[] doTLS10PRF(byte[] secret, byte[] labelBytes,
byte[] seed, int outputLength) throws NoSuchAlgorithmException,
DigestException {
MessageDigest md5 = MessageDigest.getInstance("MD5");
MessageDigest sha = MessageDigest.getInstance("SHA1");
return doTLS10PRF(secret, labelBytes, seed, outputLength, md5, sha);
}
static byte[] doTLS10PRF(byte[] secret, byte[] labelBytes,
byte[] seed, int outputLength, MessageDigest md5,
MessageDigest sha) throws DigestException {
/*
* Split the secret into two halves S1 and S2 of same length.
* S1 is taken from the first half of the secret, S2 from the
@ -183,10 +244,12 @@ public final class TlsPrfGenerator extends KeyGeneratorSpi {
byte[] output = new byte[outputLength];
// P_MD5(S1, label + seed)
expand(md5, 16, secret, 0, seclen, labelBytes, seed, output);
expand(md5, 16, secret, 0, seclen, labelBytes, seed, output,
HMAC_ipad64.clone(), HMAC_opad64.clone());
// P_SHA-1(S2, label + seed)
expand(sha, 20, secret, off, seclen, labelBytes, seed, output);
expand(sha, 20, secret, off, seclen, labelBytes, seed, output,
HMAC_ipad64.clone(), HMAC_opad64.clone());
return output;
}
@ -201,16 +264,13 @@ public final class TlsPrfGenerator extends KeyGeneratorSpi {
* @param seed the seed
* @param output the output array
*/
private static final void expand(MessageDigest digest, int hmacSize,
private static void expand(MessageDigest digest, int hmacSize,
byte[] secret, int secOff, int secLen, byte[] label, byte[] seed,
byte[] output) throws DigestException {
byte[] output, byte[] pad1, byte[] pad2) throws DigestException {
/*
* modify the padding used, by XORing the key into our copy of that
* padding. That's to avoid doing that for each HMAC computation.
*/
byte[] pad1 = HMAC_ipad.clone();
byte[] pad2 = HMAC_opad.clone();
for (int i = 0; i < secLen; i++) {
pad1[i] ^= secret[i + secOff];
pad2[i] ^= secret[i + secOff];
@ -275,7 +335,34 @@ public final class TlsPrfGenerator extends KeyGeneratorSpi {
}
remaining -= k;
}
}
/**
* A KeyGenerator implementation that supports TLS 1.2.
* <p>
* TLS 1.2 uses a different hash algorithm than 1.0/1.1 for the PRF
* calculations. As of 2010, there is no PKCS11-level support for TLS
* 1.2 PRF calculations, and no known OS's have an internal variant
* we could use. Therefore for TLS 1.2, we are updating JSSE to request
* a different provider algorithm: "SunTls12Prf". If we reused the
* name "SunTlsPrf", the PKCS11 provider would need be updated to
* fail correctly when presented with the wrong version number
* (via Provider.Service.supportsParameters()), and add the
* appropriate supportsParamters() checks into KeyGenerators (not
* currently there).
*/
static public class V12 extends TlsPrfGenerator {
protected SecretKey engineGenerateKey() {
return engineGenerateKey0(true);
}
}
/**
* A KeyGenerator implementation that supports TLS 1.0/1.1.
*/
static public class V10 extends TlsPrfGenerator {
protected SecretKey engineGenerateKey() {
return engineGenerateKey0(false);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -69,8 +69,8 @@ public final class TlsRsaPremasterSecretGenerator extends KeyGeneratorSpi {
protected SecretKey engineGenerateKey() {
if (spec == null) {
throw new IllegalStateException
("TlsRsaPremasterSecretGenerator must be initialized");
throw new IllegalStateException(
"TlsRsaPremasterSecretGenerator must be initialized");
}
if (random == null) {
random = new SecureRandom();

View File

@ -76,9 +76,9 @@ public class ServiceName {
/**
* The vendor of the JMX specification implemented by this product.
* <BR>
* The value is <CODE>Sun Microsystems</CODE>.
* The value is <CODE>Oracle Corporation</CODE>.
*/
public static final String JMX_SPEC_VENDOR = "Sun Microsystems";
public static final String JMX_SPEC_VENDOR = "Oracle Corporation";
/**
* The name of this product implementing the JMX specification.
@ -91,7 +91,7 @@ public class ServiceName {
* The name of the vendor of this product implementing the
* JMX specification.
* <BR>
* The value is <CODE>Sun Microsystems</CODE>.
* The value is <CODE>Oracle Corporation</CODE>.
*/
public static final String JMX_IMPL_VENDOR = "Sun Microsystems";
public static final String JMX_IMPL_VENDOR = "Oracle Corporation";
}

View File

@ -27,7 +27,7 @@ package com.sun.jmx.snmp;
/**
* Used for storing default values used by SNMP Runtime services.
* <p><b>This API is a Sun Microsystems internal API and is subject
* <p><b>This API is an Oracle Corporation internal API and is subject
* to change without notice.</b></p>
*/
public class ServiceName {
@ -144,16 +144,16 @@ public class ServiceName {
/**
* The vendor of the JMX specification implemented by this product.
* <BR>
* The value is <CODE>Sun Microsystems</CODE>.
* The value is <CODE>Oracle Corporation</CODE>.
*/
public static final String JMX_SPEC_VENDOR = "Sun Microsystems";
public static final String JMX_SPEC_VENDOR = "Oracle Corporation";
/**
* The name of the vendor of this product implementing the JMX specification.
* <BR>
* The value is <CODE>Sun Microsystems</CODE>.
* The value is <CODE>Oracle Corporation</CODE>.
*/
public static final String JMX_IMPL_VENDOR = "Sun Microsystems";
public static final String JMX_IMPL_VENDOR = "Oracle Corporation";
/**
* The build number of the current product version, of the form <CODE>rXX</CODE>.

View File

@ -30,7 +30,7 @@ questions.
</head>
<body bgcolor="white">
This package contains Sun Microsystem's platform extension to
This package contains Oracle Corporation's platform extension to
the implementation of the
<a href="{@docRoot}/../../../../api/java/lang/management/package-summary.html">
java.lang.management</a> API and also defines the management

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -265,7 +265,7 @@ public class ObjectInputStream
* object currently being deserialized and descriptor for current class.
* Null when not during readObject upcall.
*/
private CallbackContext curContext;
private SerialCallbackContext curContext;
/**
* Creates an ObjectInputStream that reads from the specified InputStream.
@ -1798,7 +1798,7 @@ public class ObjectInputStream
private void readExternalData(Externalizable obj, ObjectStreamClass desc)
throws IOException
{
CallbackContext oldContext = curContext;
SerialCallbackContext oldContext = curContext;
curContext = null;
try {
boolean blocked = desc.hasBlockExternalData();
@ -1857,10 +1857,10 @@ public class ObjectInputStream
slotDesc.hasReadObjectMethod() &&
handles.lookupException(passHandle) == null)
{
CallbackContext oldContext = curContext;
SerialCallbackContext oldContext = curContext;
try {
curContext = new CallbackContext(obj, slotDesc);
curContext = new SerialCallbackContext(obj, slotDesc);
bin.setBlockDataMode(true);
slotDesc.invokeReadObject(obj, this);
@ -3505,42 +3505,4 @@ public class ObjectInputStream
}
}
/**
* Context that during upcalls to class-defined readObject methods; holds
* object currently being deserialized and descriptor for current class.
* This context keeps a boolean state to indicate that defaultReadObject
* or readFields has already been invoked with this context or the class's
* readObject method has returned; if true, the getObj method throws
* NotActiveException.
*/
private static class CallbackContext {
private final Object obj;
private final ObjectStreamClass desc;
private final AtomicBoolean used = new AtomicBoolean();
public CallbackContext(Object obj, ObjectStreamClass desc) {
this.obj = obj;
this.desc = desc;
}
public Object getObj() throws NotActiveException {
checkAndSetUsed();
return obj;
}
public ObjectStreamClass getDesc() {
return desc;
}
private void checkAndSetUsed() throws NotActiveException {
if (!used.compareAndSet(false, true)) {
throw new NotActiveException(
"not in readObject invocation or fields already read");
}
}
public void setUsed() {
used.set(true);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -35,6 +35,7 @@ import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import static java.io.ObjectStreamClass.processQueue;
import java.io.SerialCallbackContext;
/**
* An ObjectOutputStream writes primitive data types and graphs of Java objects
@ -191,10 +192,12 @@ public class ObjectOutputStream
private boolean enableReplace;
// values below valid only during upcalls to writeObject()/writeExternal()
/** object currently being serialized */
private Object curObj;
/** descriptor for current class (null if in writeExternal()) */
private ObjectStreamClass curDesc;
/**
* Context during upcalls to class-defined writeObject methods; holds
* object currently being serialized and descriptor for current class.
* Null when not during writeObject upcall.
*/
private SerialCallbackContext curContext;
/** current PutField object */
private PutFieldImpl curPut;
@ -426,9 +429,11 @@ public class ObjectOutputStream
* <code>OutputStream</code>
*/
public void defaultWriteObject() throws IOException {
if (curObj == null || curDesc == null) {
if ( curContext == null ) {
throw new NotActiveException("not in call to writeObject");
}
Object curObj = curContext.getObj();
ObjectStreamClass curDesc = curContext.getDesc();
bout.setBlockDataMode(false);
defaultWriteFields(curObj, curDesc);
bout.setBlockDataMode(true);
@ -446,9 +451,11 @@ public class ObjectOutputStream
*/
public ObjectOutputStream.PutField putFields() throws IOException {
if (curPut == null) {
if (curObj == null || curDesc == null) {
if (curContext == null) {
throw new NotActiveException("not in call to writeObject");
}
Object curObj = curContext.getObj();
ObjectStreamClass curDesc = curContext.getDesc();
curPut = new PutFieldImpl(curDesc);
}
return curPut;
@ -1420,17 +1427,15 @@ public class ObjectOutputStream
* writeExternal() method.
*/
private void writeExternalData(Externalizable obj) throws IOException {
Object oldObj = curObj;
ObjectStreamClass oldDesc = curDesc;
PutFieldImpl oldPut = curPut;
curObj = obj;
curDesc = null;
curPut = null;
if (extendedDebugInfo) {
debugInfoStack.push("writeExternal data");
}
SerialCallbackContext oldContext = curContext;
try {
curContext = null;
if (protocol == PROTOCOL_VERSION_1) {
obj.writeExternal(this);
} else {
@ -1440,13 +1445,12 @@ public class ObjectOutputStream
bout.writeByte(TC_ENDBLOCKDATA);
}
} finally {
curContext = oldContext;
if (extendedDebugInfo) {
debugInfoStack.pop();
}
}
curObj = oldObj;
curDesc = oldDesc;
curPut = oldPut;
}
@ -1461,12 +1465,9 @@ public class ObjectOutputStream
for (int i = 0; i < slots.length; i++) {
ObjectStreamClass slotDesc = slots[i].desc;
if (slotDesc.hasWriteObjectMethod()) {
Object oldObj = curObj;
ObjectStreamClass oldDesc = curDesc;
PutFieldImpl oldPut = curPut;
curObj = obj;
curDesc = slotDesc;
curPut = null;
SerialCallbackContext oldContext = curContext;
if (extendedDebugInfo) {
debugInfoStack.push(
@ -1474,18 +1475,19 @@ public class ObjectOutputStream
slotDesc.getName() + "\")");
}
try {
curContext = new SerialCallbackContext(obj, slotDesc);
bout.setBlockDataMode(true);
slotDesc.invokeWriteObject(obj, this);
bout.setBlockDataMode(false);
bout.writeByte(TC_ENDBLOCKDATA);
} finally {
curContext.setUsed();
curContext = oldContext;
if (extendedDebugInfo) {
debugInfoStack.pop();
}
}
curObj = oldObj;
curDesc = oldDesc;
curPut = oldPut;
} else {
defaultWriteFields(obj, slotDesc);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -1830,8 +1830,10 @@ public class ObjectStreamClass implements Serializable {
private final ObjectStreamField[] fields;
/** number of primitive fields */
private final int numPrimFields;
/** unsafe field keys */
private final long[] keys;
/** unsafe field keys for reading fields - may contain dupes */
private final long[] readKeys;
/** unsafe fields keys for writing fields - no dupes */
private final long[] writeKeys;
/** field data offsets */
private final int[] offsets;
/** field type codes */
@ -1849,16 +1851,22 @@ public class ObjectStreamClass implements Serializable {
FieldReflector(ObjectStreamField[] fields) {
this.fields = fields;
int nfields = fields.length;
keys = new long[nfields];
readKeys = new long[nfields];
writeKeys = new long[nfields];
offsets = new int[nfields];
typeCodes = new char[nfields];
ArrayList<Class<?>> typeList = new ArrayList<Class<?>>();
Set<Long> usedKeys = new HashSet<Long>();
for (int i = 0; i < nfields; i++) {
ObjectStreamField f = fields[i];
Field rf = f.getField();
keys[i] = (rf != null) ?
long key = (rf != null) ?
unsafe.objectFieldOffset(rf) : Unsafe.INVALID_FIELD_OFFSET;
readKeys[i] = key;
writeKeys[i] = usedKeys.add(key) ?
key : Unsafe.INVALID_FIELD_OFFSET;
offsets[i] = f.getOffset();
typeCodes[i] = f.getTypeCode();
if (!f.isPrimitive()) {
@ -1894,7 +1902,7 @@ public class ObjectStreamClass implements Serializable {
* in array should be equal to Unsafe.INVALID_FIELD_OFFSET.
*/
for (int i = 0; i < numPrimFields; i++) {
long key = keys[i];
long key = readKeys[i];
int off = offsets[i];
switch (typeCodes[i]) {
case 'Z':
@ -1945,7 +1953,7 @@ public class ObjectStreamClass implements Serializable {
throw new NullPointerException();
}
for (int i = 0; i < numPrimFields; i++) {
long key = keys[i];
long key = writeKeys[i];
if (key == Unsafe.INVALID_FIELD_OFFSET) {
continue; // discard value
}
@ -2006,7 +2014,7 @@ public class ObjectStreamClass implements Serializable {
switch (typeCodes[i]) {
case 'L':
case '[':
vals[offsets[i]] = unsafe.getObject(obj, keys[i]);
vals[offsets[i]] = unsafe.getObject(obj, readKeys[i]);
break;
default:
@ -2027,7 +2035,7 @@ public class ObjectStreamClass implements Serializable {
throw new NullPointerException();
}
for (int i = numPrimFields; i < fields.length; i++) {
long key = keys[i];
long key = writeKeys[i];
if (key == Unsafe.INVALID_FIELD_OFFSET) {
continue; // discard value
}

View File

@ -0,0 +1,58 @@
/*
* %W% %E%
*
* Copyright (c) 2006, 2010 Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package java.io;
/**
* Context during upcalls from object stream to class-defined
* readObject/writeObject methods.
* Holds object currently being deserialized and descriptor for current class.
*
* This context keeps track of the thread it was constructed on, and allows
* only a single call of defaultReadObject, readFields, defaultWriteObject
* or writeFields which must be invoked on the same thread before the class's
* readObject/writeObject method has returned.
* If not set to the current thread, the getObj method throws NotActiveException.
*/
final class SerialCallbackContext {
private final Object obj;
private final ObjectStreamClass desc;
/**
* Thread this context is in use by.
* As this only works in one thread, we do not need to worry about thread-safety.
*/
private Thread thread;
public SerialCallbackContext(Object obj, ObjectStreamClass desc) {
this.obj = obj;
this.desc = desc;
this.thread = Thread.currentThread();
}
public Object getObj() throws NotActiveException {
checkAndSetUsed();
return obj;
}
public ObjectStreamClass getDesc() {
return desc;
}
private void checkAndSetUsed() throws NotActiveException {
if (thread != Thread.currentThread()) {
throw new NotActiveException(
"not in readObject invocation or fields already read");
}
thread = null;
}
public void setUsed() {
thread = null;
}
}

View File

@ -100,7 +100,8 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* @param minimumCapacity the minimum desired capacity.
*/
public void ensureCapacity(int minimumCapacity) {
ensureCapacityInternal(minimumCapacity);
if (minimumCapacity > 0)
ensureCapacityInternal(minimumCapacity);
}
/**
@ -108,6 +109,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* never synchronized.
*/
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
if (minimumCapacity - value.length > 0)
expandCapacity(minimumCapacity);
}

View File

@ -553,6 +553,13 @@ public abstract class ClassLoader {
* If either <tt>off</tt> or <tt>len</tt> is negative, or if
* <tt>off+len</tt> is greater than <tt>b.length</tt>.
*
* @throws SecurityException
* If an attempt is made to add this class to a package that
* contains classes that were signed by a different set of
* certificates than this class, or if an attempt is made
* to define a class in a package with a fully-qualified name
* that starts with "{@code java.}".
*
* @see #loadClass(String, boolean)
* @see #resolveClass(Class)
*

View File

@ -28,9 +28,7 @@ package java.net;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.InterruptedIOException;
import java.io.FileDescriptor;
import java.io.ByteArrayOutputStream;
import sun.net.ConnectionResetException;
import sun.net.NetHooks;
@ -58,7 +56,7 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
protected int fdUseCount = 0;
/* lock when increment/decrementing fdUseCount */
protected Object fdLock = new Object();
protected final Object fdLock = new Object();
/* indicates a close is pending on the file descriptor */
protected boolean closePending = false;
@ -68,7 +66,7 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
private int CONNECTION_RESET_PENDING = 1;
private int CONNECTION_RESET = 2;
private int resetState;
private Object resetLock = new Object();
private final Object resetLock = new Object();
/**
* Load net library into runtime.
@ -100,25 +98,24 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
protected void connect(String host, int port)
throws UnknownHostException, IOException
{
IOException pending = null;
boolean connected = false;
try {
InetAddress address = InetAddress.getByName(host);
this.port = port;
this.address = address;
try {
connectToAddress(address, port, timeout);
return;
} catch (IOException e) {
pending = e;
connectToAddress(address, port, timeout);
connected = true;
} finally {
if (!connected) {
try {
close();
} catch (IOException ioe) {
/* Do nothing. If connect threw an exception then
it will be passed up the call stack */
}
}
} catch (UnknownHostException e) {
pending = e;
}
// everything failed
close();
throw pending;
}
/**
@ -151,22 +148,29 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
* SocketAddress subclass not supported by this socket
* @since 1.4
*/
protected void connect(SocketAddress address, int timeout) throws IOException {
if (address == null || !(address instanceof InetSocketAddress))
throw new IllegalArgumentException("unsupported address type");
InetSocketAddress addr = (InetSocketAddress) address;
if (addr.isUnresolved())
throw new UnknownHostException(addr.getHostName());
this.port = addr.getPort();
this.address = addr.getAddress();
protected void connect(SocketAddress address, int timeout)
throws IOException {
boolean connected = false;
try {
if (address == null || !(address instanceof InetSocketAddress))
throw new IllegalArgumentException("unsupported address type");
InetSocketAddress addr = (InetSocketAddress) address;
if (addr.isUnresolved())
throw new UnknownHostException(addr.getHostName());
this.port = addr.getPort();
this.address = addr.getAddress();
connectToAddress(this.address, port, timeout);
return;
} catch (IOException e) {
// everything failed
close();
throw e;
connected = true;
} finally {
if (!connected) {
try {
close();
} catch (IOException ioe) {
/* Do nothing. If connect threw an exception then
it will be passed up the call stack */
}
}
}
}
@ -311,7 +315,7 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
}
}
try {
FileDescriptor fd = acquireFD();
acquireFD();
try {
socketConnect(address, port, timeout);
/* socket may have been closed during poll/select */
@ -370,7 +374,7 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
* @param s the connection
*/
protected void accept(SocketImpl s) throws IOException {
FileDescriptor fd = acquireFD();
acquireFD();
try {
socketAccept(s);
} finally {
@ -562,7 +566,6 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
close();
}
/*
* "Acquires" and returns the FileDescriptor for this impl
*

View File

@ -27,6 +27,7 @@
package java.nio;
import java.io.FileDescriptor;
import sun.misc.Cleaner;
import sun.misc.Unsafe;
import sun.misc.VM;
@ -114,7 +115,7 @@ class Direct$Type$Buffer$RW$$BO$
//
Direct$Type$Buffer$RW$(int cap) { // package-private
#if[rw]
super(-1, 0, cap, cap, false);
super(-1, 0, cap, cap);
boolean pa = VM.isDirectMemoryPageAligned();
int ps = Bits.pageSize();
long size = Math.max(1L, (long)cap + (pa ? ps : 0));
@ -145,7 +146,7 @@ class Direct$Type$Buffer$RW$$BO$
// Invoked only by JNI: NewDirectByteBuffer(void*, long)
//
private Direct$Type$Buffer(long addr, int cap) {
super(-1, 0, cap, cap, false);
super(-1, 0, cap, cap);
address = addr;
cleaner = null;
}
@ -154,14 +155,17 @@ class Direct$Type$Buffer$RW$$BO$
// For memory-mapped buffers -- invoked by FileChannelImpl via reflection
//
protected Direct$Type$Buffer$RW$(int cap, long addr, Runnable unmapper) {
protected Direct$Type$Buffer$RW$(int cap, long addr,
FileDescriptor fd,
Runnable unmapper)
{
#if[rw]
super(-1, 0, cap, cap, true);
super(-1, 0, cap, cap, fd);
address = addr;
viewedBuffer = null;
cleaner = Cleaner.create(this, unmapper);
#else[rw]
super(cap, addr, unmapper);
super(cap, addr, fd, unmapper);
#end[rw]
}

View File

@ -25,6 +25,7 @@
package java.nio;
import java.io.FileDescriptor;
import sun.misc.Unsafe;
@ -71,26 +72,26 @@ public abstract class MappedByteBuffer
// for optimization purposes, it's easier to do it the other way around.
// This works because DirectByteBuffer is a package-private class.
// Volatile to make sure that the finalization thread sees the current
// value of this so that a region is not accidentally unmapped again later.
volatile boolean isAMappedBuffer; // package-private
// For mapped buffers, a FileDescriptor that may be used for mapping
// operations if valid; null if the buffer is not mapped.
private final FileDescriptor fd;
// This should only be invoked by the DirectByteBuffer constructors
//
MappedByteBuffer(int mark, int pos, int lim, int cap, // package-private
boolean mapped)
FileDescriptor fd)
{
super(mark, pos, lim, cap);
isAMappedBuffer = mapped;
this.fd = fd;
}
MappedByteBuffer(int mark, int pos, int lim, int cap) { // package-private
super(mark, pos, lim, cap);
isAMappedBuffer = false;
this.fd = null;
}
private void checkMapped() {
if (!isAMappedBuffer)
if (fd == null)
// Can only happen if a luser explicitly casts a direct byte buffer
throw new UnsupportedOperationException();
}
@ -191,13 +192,12 @@ public abstract class MappedByteBuffer
checkMapped();
if ((address != 0) && (capacity() != 0)) {
long offset = mappingOffset();
force0(mappingAddress(offset), mappingLength(offset));
force0(fd, mappingAddress(offset), mappingLength(offset));
}
return this;
}
private native boolean isLoaded0(long address, long length, int pageCount);
private native void load0(long address, long length);
private native void force0(long address, long length);
private native void force0(FileDescriptor fd, long address, long length);
}

View File

@ -1,572 +0,0 @@
/*
* Copyright (c) 2007, 2009, 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 java.nio.channels;
import java.nio.channels.spi.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.Future;
import java.io.IOException;
import java.net.SocketOption;
import java.net.SocketAddress;
import java.net.ProtocolFamily;
import java.nio.ByteBuffer;
/**
* An asynchronous channel for datagram-oriented sockets.
*
* <p> An asynchronous datagram channel is created by invoking one of the {@link
* #open open} methods defined by this class. It is not possible to create a channel
* for an arbitrary, pre-existing datagram socket. A newly-created asynchronous
* datagram channel is open but not connected. It need not be connected in order
* for the {@link #send send} and {@link #receive receive} methods to be used.
* A datagram channel may be connected, by invoking its {@link #connect connect}
* method, in order to avoid the overhead of the security checks that are otherwise
* performed as part of every send and receive operation when a security manager
* is set. The channel must be connected in order to use the {@link #read read}
* and {@link #write write} methods, since those methods do not accept or return
* socket addresses. Once connected, an asynchronous datagram channel remains
* connected until it is disconnected or closed.
*
* <p> Socket options are configured using the {@link #setOption(SocketOption,Object)
* setOption} method. An asynchronous datagram channel to an Internet Protocol
* (IP) socket supports the following options:
* <blockquote>
* <table border>
* <tr>
* <th>Option Name</th>
* <th>Description</th>
* </tr>
* <tr>
* <td> {@link java.net.StandardSocketOption#SO_SNDBUF SO_SNDBUF} </td>
* <td> The size of the socket send buffer </td>
* </tr>
* <tr>
* <td> {@link java.net.StandardSocketOption#SO_RCVBUF SO_RCVBUF} </td>
* <td> The size of the socket receive buffer </td>
* </tr>
* <tr>
* <td> {@link java.net.StandardSocketOption#SO_REUSEADDR SO_REUSEADDR} </td>
* <td> Re-use address </td>
* </tr>
* <tr>
* <td> {@link java.net.StandardSocketOption#SO_BROADCAST SO_BROADCAST} </td>
* <td> Allow transmission of broadcast datagrams </td>
* </tr>
* <tr>
* <td> {@link java.net.StandardSocketOption#IP_TOS IP_TOS} </td>
* <td> The Type of Service (ToS) octet in the Internet Protocol (IP) header </td>
* </tr>
* <tr>
* <td> {@link java.net.StandardSocketOption#IP_MULTICAST_IF IP_MULTICAST_IF} </td>
* <td> The network interface for Internet Protocol (IP) multicast datagrams </td>
* </tr>
* <tr>
* <td> {@link java.net.StandardSocketOption#IP_MULTICAST_TTL
* IP_MULTICAST_TTL} </td>
* <td> The <em>time-to-live</em> for Internet Protocol (IP) multicast
* datagrams </td>
* </tr>
* <tr>
* <td> {@link java.net.StandardSocketOption#IP_MULTICAST_LOOP
* IP_MULTICAST_LOOP} </td>
* <td> Loopback for Internet Protocol (IP) multicast datagrams </td>
* </tr>
* </table>
* </blockquote>
* Additional (implementation specific) options may also be supported.
*
* <p> Asynchronous datagram channels allow more than one read/receive and
* write/send to be oustanding at any given time.
*
* <p> <b>Usage Example:</b>
* <pre>
* final AsynchronousDatagramChannel dc = AsynchronousDatagramChannel.open()
* .bind(new InetSocketAddress(4000));
*
* // print the source address of all packets that we receive
* dc.receive(buffer, buffer, new CompletionHandler&lt;SocketAddress,ByteBuffer&gt;() {
* public void completed(SocketAddress sa, ByteBuffer buffer) {
* System.out.println(sa);
* buffer.clear();
* dc.receive(buffer, buffer, this);
* }
* public void failed(Throwable exc, ByteBuffer buffer) {
* ...
* }
* });
* </pre>
*
* @since 1.7
*/
public abstract class AsynchronousDatagramChannel
implements AsynchronousByteChannel, MulticastChannel
{
private final AsynchronousChannelProvider provider;
/**
* Initializes a new instance of this class.
*/
protected AsynchronousDatagramChannel(AsynchronousChannelProvider provider) {
this.provider = provider;
}
/**
* Returns the provider that created this channel.
*/
public final AsynchronousChannelProvider provider() {
return provider;
}
/**
* Opens an asynchronous datagram channel.
*
* <p> The new channel is created by invoking the {@link
* java.nio.channels.spi.AsynchronousChannelProvider#openAsynchronousDatagramChannel
* openAsynchronousDatagramChannel} method on the {@link
* java.nio.channels.spi.AsynchronousChannelProvider} object that created
* the given group (or the default provider where {@code group} is {@code
* null}).
*
* <p> The {@code family} parameter is used to specify the {@link ProtocolFamily}.
* If the datagram channel is to be used for Internet Protocol {@link
* MulticastChannel multicasting} then this parameter should correspond to
* the address type of the multicast groups that this channel will join.
*
* @param family
* The protocol family, or {@code null} to use the default protocol
* family
* @param group
* The group to which the newly constructed channel should be bound,
* or {@code null} for the default group
*
* @return A new asynchronous datagram channel
*
* @throws UnsupportedOperationException
* If the specified protocol family is not supported. For example,
* suppose the parameter is specified as {@link
* java.net.StandardProtocolFamily#INET6 INET6} but IPv6 is not
* enabled on the platform.
* @throws ShutdownChannelGroupException
* The specified group is shutdown
* @throws IOException
* If an I/O error occurs
*/
public static AsynchronousDatagramChannel open(ProtocolFamily family,
AsynchronousChannelGroup group)
throws IOException
{
AsynchronousChannelProvider provider = (group == null) ?
AsynchronousChannelProvider.provider() : group.provider();
return provider.openAsynchronousDatagramChannel(family, group);
}
/**
* Opens an asynchronous datagram channel.
*
* <p> This method returns an asynchronous datagram channel that is
* bound to the <em>default group</em>. This method is equivalent to evaluating
* the expression:
* <blockquote><pre>
* open((ProtocolFamily)null,&nbsp;(AsynchronousChannelGroup)null);
* </pre></blockquote>
*
* @return A new asynchronous datagram channel
*
* @throws IOException
* If an I/O error occurs
*/
public static AsynchronousDatagramChannel open()
throws IOException
{
return open(null, null);
}
// -- Socket-specific operations --
/**
* @throws AlreadyBoundException {@inheritDoc}
* @throws UnsupportedAddressTypeException {@inheritDoc}
* @throws ClosedChannelException {@inheritDoc}
* @throws IOException {@inheritDoc}
* @throws SecurityException
* If a security manager has been installed and its {@link
* SecurityManager#checkListen checkListen} method denies the
* operation
*/
@Override
public abstract AsynchronousDatagramChannel bind(SocketAddress local)
throws IOException;
/**
* @throws IllegalArgumentException {@inheritDoc}
* @throws ClosedChannelException {@inheritDoc}
* @throws IOException {@inheritDoc}
*/
@Override
public abstract <T> AsynchronousDatagramChannel setOption(SocketOption<T> name, T value)
throws IOException;
/**
* Returns the remote address to which this channel is connected.
*
* <p> Where the channel is connected to an Internet Protocol socket address
* then the return value from this method is of type {@link
* java.net.InetSocketAddress}.
*
* @return The remote address; {@code null} if the channel's socket is not
* connected
*
* @throws ClosedChannelException
* If the channel is closed
* @throws IOException
* If an I/O error occurs
*/
public abstract SocketAddress getRemoteAddress() throws IOException;
/**
* Connects this channel's socket.
*
* <p> The channel's socket is configured so that it only receives
* datagrams from, and sends datagrams to, the given remote <i>peer</i>
* address. Once connected, datagrams may not be received from or sent to
* any other address. A datagram socket remains connected until it is
* explicitly disconnected or until it is closed.
*
* <p> This method performs exactly the same security checks as the {@link
* java.net.DatagramSocket#connect connect} method of the {@link
* java.net.DatagramSocket} class. That is, if a security manager has been
* installed then this method verifies that its {@link
* java.lang.SecurityManager#checkAccept checkAccept} and {@link
* java.lang.SecurityManager#checkConnect checkConnect} methods permit
* datagrams to be received from and sent to, respectively, the given
* remote address.
*
* <p> This method may be invoked at any time. Whether it has any effect
* on outstanding read or write operations is implementation specific and
* therefore not specified.
*
* @param remote
* The remote address to which this channel is to be connected
*
* @return This datagram channel
*
* @throws ClosedChannelException
* If this channel is closed
*
* @throws SecurityException
* If a security manager has been installed
* and it does not permit access to the given remote address
*
* @throws IOException
* If some other I/O error occurs
*/
public abstract AsynchronousDatagramChannel connect(SocketAddress remote)
throws IOException;
/**
* Disconnects this channel's socket.
*
* <p> The channel's socket is configured so that it can receive datagrams
* from, and sends datagrams to, any remote address so long as the security
* manager, if installed, permits it.
*
* <p> This method may be invoked at any time. Whether it has any effect
* on outstanding read or write operations is implementation specific and
* therefore not specified.
*
* @return This datagram channel
*
* @throws IOException
* If some other I/O error occurs
*/
public abstract AsynchronousDatagramChannel disconnect() throws IOException;
/**
* Receives a datagram via this channel.
*
* <p> This method initiates the receiving of a datagram into the given
* buffer. The {@code handler} parameter is a completion handler that is
* invoked when the receive operation completes (or fails). The result
* passed to the completion handler is the datagram's source address.
*
* <p> The datagram is transferred into the given byte buffer starting at
* its current position, as if by a regular {@link AsynchronousByteChannel#read
* read} operation. If there are fewer bytes remaining in the buffer
* than are required to hold the datagram then the remainder of the datagram
* is silently discarded.
*
* <p> If a timeout is specified and the timeout elapses before the operation
* completes then the operation completes with the exception {@link
* InterruptedByTimeoutException}. When a timeout elapses then the state of
* the {@link ByteBuffer} is not defined. The buffers should be discarded or
* at least care must be taken to ensure that the buffer is not accessed
* while the channel remains open.
*
* <p> When a security manager has been installed and the channel is not
* connected, then it verifies that the source's address and port number are
* permitted by the security manager's {@link SecurityManager#checkAccept
* checkAccept} method. The permission check is performed with privileges that
* are restricted by the calling context of this method. If the permission
* check fails then the operation completes with a {@link SecurityException}.
* The overhead of this security check can be avoided by first connecting the
* socket via the {@link #connect connect} method.
*
* @param dst
* The buffer into which the datagram is to be transferred
* @param timeout
* The timeout, or {@code 0L} for no timeout
* @param unit
* The time unit of the {@code timeout} argument
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
* The handler for consuming the result
*
* @throws IllegalArgumentException
* If the timeout is negative or the buffer is read-only
* @throws ShutdownChannelGroupException
* If the channel group has terminated
*/
public abstract <A> void receive(ByteBuffer dst,
long timeout,
TimeUnit unit,
A attachment,
CompletionHandler<SocketAddress,? super A> handler);
/**
* Receives a datagram via this channel.
*
* <p> This method initiates the receiving of a datagram into the given
* buffer. The {@code handler} parameter is a completion handler that is
* invoked when the receive operation completes (or fails). The result
* passed to the completion handler is the datagram's source address.
*
* <p> This method is equivalent to invoking {@link
* #receive(ByteBuffer,long,TimeUnit,Object,CompletionHandler)} with a
* timeout of {@code 0L}.
*
* @param dst
* The buffer into which the datagram is to be transferred
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
* The handler for consuming the result
*
* @throws IllegalArgumentException
* If the buffer is read-only
* @throws ShutdownChannelGroupException
* If the channel group has terminated
*/
public final <A> void receive(ByteBuffer dst,
A attachment,
CompletionHandler<SocketAddress,? super A> handler)
{
receive(dst, 0L, TimeUnit.MILLISECONDS, attachment, handler);
}
/**
* Receives a datagram via this channel.
*
* <p> This method initiates the receiving of a datagram into the given
* buffer. The method behaves in exactly the same manner as the {@link
* #receive(ByteBuffer,Object,CompletionHandler)
* receive(ByteBuffer,Object,CompletionHandler)} method except that instead
* of specifying a completion handler, this method returns a {@code Future}
* representing the pending result. The {@code Future}'s {@link Future#get()
* get} method returns the datagram's source address.
*
* @param dst
* The buffer into which the datagram is to be transferred
*
* @return a {@code Future} object representing the pending result
*
* @throws IllegalArgumentException
* If the buffer is read-only
*/
public abstract Future<SocketAddress> receive(ByteBuffer dst);
/**
* Sends a datagram via this channel.
*
* <p> This method initiates sending of a datagram from the given buffer to
* the given address. The {@code handler} parameter is a completion handler
* that is invoked when the send completes (or fails). The result passed to
* the completion handler is the number of bytes sent.
*
* <p> Otherwise this method works in the same manner as the {@link
* AsynchronousByteChannel#write(ByteBuffer,Object,CompletionHandler)}
* method.
*
* @param src
* The buffer containing the datagram to be sent
* @param target
* The address to which the datagram is to be sent
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
* The handler for consuming the result
*
* @throws UnresolvedAddressException
* If the given remote address is not fully resolved
* @throws UnsupportedAddressTypeException
* If the type of the given remote address is not supported
* @throws IllegalArgumentException
* If the channel's socket is connected and is connected to an
* address that is not equal to {@code target}
* @throws SecurityException
* If a security manager has been installed and it does not permit
* datagrams to be sent to the given address
* @throws ShutdownChannelGroupException
* If the channel group has terminated
*/
public abstract <A> void send(ByteBuffer src,
SocketAddress target,
A attachment,
CompletionHandler<Integer,? super A> handler);
/**
* Sends a datagram via this channel.
*
* <p> This method initiates sending of a datagram from the given buffer to
* the given address. The method behaves in exactly the same manner as the
* {@link #send(ByteBuffer,SocketAddress,Object,CompletionHandler)
* send(ByteBuffer,SocketAddress,Object,CompletionHandler)} method except
* that instead of specifying a completion handler, this method returns a
* {@code Future} representing the pending result. The {@code Future}'s
* {@link Future#get() get} method returns the number of bytes sent.
*
* @param src
* The buffer containing the datagram to be sent
* @param target
* The address to which the datagram is to be sent
*
* @return a {@code Future} object representing the pending result
*
* @throws UnresolvedAddressException
* If the given remote address is not fully resolved
* @throws UnsupportedAddressTypeException
* If the type of the given remote address is not supported
* @throws IllegalArgumentException
* If the channel's socket is connected and is connected to an
* address that is not equal to {@code target}
* @throws SecurityException
* If a security manager has been installed and it does not permit
* datagrams to be sent to the given address
*/
public abstract Future<Integer> send(ByteBuffer src, SocketAddress target);
/**
* Receives a datagram via this channel.
*
* <p> This method initiates the receiving of a datagram into the given
* buffer. The {@code handler} parameter is a completion handler that is
* invoked when the receive operation completes (or fails). The result
* passed to the completion handler is number of bytes read.
*
* <p> This method may only be invoked if this channel is connected, and it
* only accepts datagrams from the peer that the channel is connected too.
* The datagram is transferred into the given byte buffer starting at
* its current position and exactly as specified in the {@link
* AsynchronousByteChannel} interface. If there are fewer bytes
* remaining in the buffer than are required to hold the datagram then the
* remainder of the datagram is silently discarded.
*
* <p> If a timeout is specified and the timeout elapses before the operation
* completes then the operation completes with the exception {@link
* InterruptedByTimeoutException}. When a timeout elapses then the state of
* the {@link ByteBuffer} is not defined. The buffers should be discarded or
* at least care must be taken to ensure that the buffer is not accessed
* while the channel remains open.
*
* @param dst
* The buffer into which the datagram is to be transferred
* @param timeout
* The timeout, or {@code 0L} for no timeout
* @param unit
* The time unit of the {@code timeout} argument
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
* The handler for consuming the result
*
* @throws IllegalArgumentException
* If the timeout is negative or buffer is read-only
* @throws NotYetConnectedException
* If this channel is not connected
* @throws ShutdownChannelGroupException
* If the channel group has terminated
*/
public abstract <A> void read(ByteBuffer dst,
long timeout,
TimeUnit unit,
A attachment,
CompletionHandler<Integer,? super A> handler);
/**
* @throws NotYetConnectedException
* If this channel is not connected
* @throws ShutdownChannelGroupException
* If the channel group has terminated
*/
@Override
public final <A> void read(ByteBuffer dst,
A attachment,
CompletionHandler<Integer,? super A> handler)
{
read(dst, 0L, TimeUnit.MILLISECONDS, attachment, handler);
}
/**
* @throws NotYetConnectedException
* If this channel is not connected
* @throws ShutdownChannelGroupException
* If the channel group has terminated
*/
@Override
public abstract Future<Integer> read(ByteBuffer dst);
/**
* @throws NotYetConnectedException
* If this channel is not connected
* @throws ShutdownChannelGroupException
* If the channel group has terminated
*/
@Override
public abstract <A> void write(ByteBuffer src,
A attachment,
CompletionHandler<Integer,? super A> handler);
/**
* @throws NotYetConnectedException
* If this channel is not connected
* @throws ShutdownChannelGroupException
* If the channel group has terminated
*/
@Override
public abstract Future<Integer> write(ByteBuffer src);
}

View File

@ -232,8 +232,6 @@
* <td>An asynchronous channel to a stream-oriented connecting socket</td></tr>
* <tr><td valign=top><tt>{@link java.nio.channels.AsynchronousServerSocketChannel}&nbsp;&nbsp;</tt></td>
* <td>An asynchronous channel to a stream-oriented listening socket</td></tr>
* <tr><td valign=top><tt>{@link java.nio.channels.AsynchronousDatagramChannel}</tt></td>
* <td>An asynchronous channel to a datagram-oriented socket</td></tr>
* <tr><td valign=top><tt>{@link java.nio.channels.CompletionHandler}</tt></td>
* <td>A handler for consuming the result of an asynchronous operation</td></tr>
* <tr><td valign=top><tt>{@link java.nio.channels.AsynchronousChannelGroup}</tt></td>

View File

@ -26,7 +26,6 @@
package java.nio.channels.spi;
import java.nio.channels.*;
import java.net.ProtocolFamily;
import java.io.IOException;
import java.util.Iterator;
import java.util.ServiceLoader;
@ -239,26 +238,4 @@ public abstract class AsynchronousChannelProvider {
*/
public abstract AsynchronousSocketChannel openAsynchronousSocketChannel
(AsynchronousChannelGroup group) throws IOException;
/**
* Opens an asynchronous datagram channel.
*
* @param family
* The protocol family, or {@code null} for the default protocol
* family
* @param group
* The group to which the channel is bound, or {@code null} to
* bind to the default group
*
* @return The new channel
*
* @throws IllegalChannelGroupException
* If the provider that created the group differs from this provider
* @throws ShutdownChannelGroupException
* The group is shutdown
* @throws IOException
* If an I/O error occurs
*/
public abstract AsynchronousDatagramChannel openAsynchronousDatagramChannel
(ProtocolFamily family, AsynchronousChannelGroup group) throws IOException;
}

View File

@ -0,0 +1,108 @@
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.security;
import java.util.Set;
/**
* This interface specifies constraints for cryptographic algorithms,
* keys (key sizes), and other algorithm parameters.
* <p>
* {@code AlgorithmConstraints} objects are immutable. An implementation
* of this interface should not provide methods that can change the state
* of an instance once it has been created.
* <p>
* Note that {@code AlgorithmConstraints} can be used to represent the
* restrictions described by the security properties
* {@code jdk.certpath.disabledAlgorithms} and
* {@code jdk.tls.disabledAlgorithms}, or could be used by a
* concrete {@code PKIXCertPathChecker} to check whether a specified
* certificate in the certification path contains the required algorithm
* constraints.
*
* @see javax.net.ssl.SSLParameters#getAlgorithmConstraints
* @see javax.net.ssl.SSLParameters#setAlgorithmConstraints(AlgorithmConstraints)
*
* @since 1.7
*/
public interface AlgorithmConstraints {
/**
* Determines whether an algorithm is granted permission for the
* specified cryptographic primitives.
*
* @param primitives a set of cryptographic primitives
* @param algorithm the algorithm name
* @param parameters the algorithm parameters, or null if no additional
* parameters
*
* @return true if the algorithm is permitted and can be used for all
* of the specified cryptographic primitives
*
* @throws IllegalArgumentException if primitives or algorithm is null
* or empty
*/
public boolean permits(Set<CryptoPrimitive> primitives,
String algorithm, AlgorithmParameters parameters);
/**
* Determines whether a key is granted permission for the specified
* cryptographic primitives.
* <p>
* This method is usually used to check key size and key usage.
*
* @param primitives a set of cryptographic primitives
* @param key the key
*
* @return true if the key can be used for all of the specified
* cryptographic primitives
*
* @throws IllegalArgumentException if primitives is null or empty,
* or the key is null
*/
public boolean permits(Set<CryptoPrimitive> primitives, Key key);
/**
* Determines whether an algorithm and the corresponding key are granted
* permission for the specified cryptographic primitives.
*
* @param primitives a set of cryptographic primitives
* @param algorithm the algorithm name
* @param key the key
* @param parameters the algorithm parameters, or null if no additional
* parameters
*
* @return true if the key and the algorithm can be used for all of the
* specified cryptographic primitives
*
* @throws IllegalArgumentException if primitives or algorithm is null
* or empty, or the key is null
*/
public boolean permits(Set<CryptoPrimitive> primitives,
String algorithm, Key key, AlgorithmParameters parameters);
}

View File

@ -0,0 +1,83 @@
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.security;
/**
* An enumeration of cryptographic primitives.
*
* @since 1.7
*/
public enum CryptoPrimitive {
/**
* Hash function
*/
MESSAGE_DIGEST,
/**
* Cryptographic random number generator
*/
SECURE_RANDOM,
/**
* Symmetric primitive: block cipher
*/
BLOCK_CIPHER,
/**
* Symmetric primitive: stream cipher
*/
STREAM_CIPHER,
/**
* Symmetric primitive: message authentication code
*/
MAC,
/**
* Symmetric primitive: key wrap
*/
KEY_WRAP,
/**
* Asymmetric primitive: public key encryption
*/
PUBLIC_KEY_ENCRYPTION,
/**
* Asymmetric primitive: signature scheme
*/
SIGNATURE,
/**
* Asymmetric primitive: key encapsulation mechanism
*/
KEY_ENCAPSULATION,
/**
* Asymmetric primitive: key agreement and key distribution
*/
KEY_AGREEMENT
}

View File

@ -176,6 +176,11 @@ public class ArrayList<E> extends AbstractList<E>
* @param minCapacity the desired minimum capacity
*/
public void ensureCapacity(int minCapacity) {
if (minCapacity > 0)
ensureCapacityInternal(minCapacity);
}
private void ensureCapacityInternal(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
@ -403,7 +408,7 @@ public class ArrayList<E> extends AbstractList<E>
* @return <tt>true</tt> (as specified by {@link Collection#add})
*/
public boolean add(E e) {
ensureCapacity(size + 1); // Increments modCount!!
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
@ -420,7 +425,7 @@ public class ArrayList<E> extends AbstractList<E>
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacity(size + 1); // Increments modCount!!
ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
@ -524,7 +529,7 @@ public class ArrayList<E> extends AbstractList<E>
public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacity(size + numNew); // Increments modCount
ensureCapacityInternal(size + numNew); // Increments modCount
System.arraycopy(a, 0, elementData, size, numNew);
size += numNew;
return numNew != 0;
@ -550,7 +555,7 @@ public class ArrayList<E> extends AbstractList<E>
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacity(size + numNew); // Increments modCount
ensureCapacityInternal(size + numNew); // Increments modCount
int numMoved = size - index;
if (numMoved > 0)

View File

@ -222,8 +222,10 @@ public class Vector<E>
* @param minCapacity the desired minimum capacity
*/
public synchronized void ensureCapacity(int minCapacity) {
modCount++;
ensureCapacityHelper(minCapacity);
if (minCapacity > 0) {
modCount++;
ensureCapacityHelper(minCapacity);
}
}
/**

View File

@ -529,8 +529,6 @@ public class LogRecord implements java.io.Serializable {
Throwable throwable = new Throwable();
int depth = access.getStackTraceDepth(throwable);
String logClassName = "java.util.logging.Logger";
String plogClassName = "sun.util.logging.PlatformLogger";
boolean lookingForLogger = true;
for (int ix = 0; ix < depth; ix++) {
// Calling getStackTraceElement directly prevents the VM
@ -538,13 +536,14 @@ public class LogRecord implements java.io.Serializable {
StackTraceElement frame =
access.getStackTraceElement(throwable, ix);
String cname = frame.getClassName();
boolean isLoggerImpl = isLoggerImplFrame(cname);
if (lookingForLogger) {
// Skip all frames until we have found the first logger frame.
if (cname.equals(logClassName) || cname.startsWith(plogClassName)) {
if (isLoggerImpl) {
lookingForLogger = false;
}
} else {
if (!cname.equals(logClassName) && !cname.startsWith(plogClassName)) {
if (!isLoggerImpl) {
// skip reflection call
if (!cname.startsWith("java.lang.reflect.") && !cname.startsWith("sun.reflect.")) {
// We've found the relevant frame.
@ -558,4 +557,11 @@ public class LogRecord implements java.io.Serializable {
// We haven't found a suitable frame, so just punt. This is
// OK as we are only committed to making a "best effort" here.
}
private boolean isLoggerImplFrame(String cname) {
// the log record could be created for a platform logger
return (cname.equals("java.util.logging.Logger") ||
cname.startsWith("java.util.logging.LoggingProxyImpl") ||
cname.startsWith("sun.util.logging."));
}
}

View File

@ -211,8 +211,8 @@ import java.util.Map;
* reverse DNS name of the organization that specifies the MBeans,
* followed by a period and a string whose interpretation is
* determined by that organization. For example, MBeans specified by
* Sun Microsystems Inc., DNS name <code>sun.com</code>, would have
* domains such as <code>com.sun.MyDomain</code>. This is essentially
* <code>example.com</code> would have
* domains such as <code>com.example.MyDomain</code>. This is essentially
* the same convention as for Java-language package names.</p>
*
* <p>The <b>serialVersionUID</b> of this class is <code>1081892073854801359L</code>.

View File

@ -35,18 +35,18 @@
. Please also read the important comment on basedir definition below.
-->
<project name="JMX API Version 1.4 - Java SE 6 implementation"
default="jar"
basedir="../../../../.."
<project name="JMX API Version 1.4 - Java SE 6 implementation"
default="jar"
basedir="../../../../.."
>
<!-- IMPORTANT: BASEDIR DEFINITION
This file is assumed to be in:
<src_bundle_dir>/j2se/src/share/classes/javax/management
Thus the basedir for this project is defined above as:
basedir="../../../../.."
<!-- IMPORTANT: BASEDIR DEFINITION
This file is assumed to be in:
<src_bundle_dir>/j2se/src/share/classes/javax/management
Thus the basedir for this project is defined above as:
basedir="../../../../.."
in order to be the parent dir of src subdir.
Result of the build will be placed in ${basedir}/build_jmx
Result of the build will be placed in ${basedir}/build_jmx
as defined by ${dir.build} property below.
-->
@ -163,14 +163,14 @@
<echo message=" BUILD_DATE = ${BUILD_DATE}" />
</target>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- Call classes subtargets and rmic stubs generation -->
<target name="classes" depends="init,classes-javac,classes-rmic"
description="Call classes subtargets and rmic stubs generation"
<target name="classes" depends="init,classes-javac,classes-rmic"
description="Call classes subtargets and rmic stubs generation"
/>
@ -183,13 +183,13 @@
<mkdir dir="${dir.build.classes}" />
<javac srcdir="${dir.src}"
destdir="${dir.build.classes}"
destdir="${dir.build.classes}"
source="${flag.javac.source}"
debug="${flag.debug}"
debuglevel="${flag.debug.level}"
optimize="${flag.optimize}"
includeAntRuntime="no"
includeJavaRuntime="no"
includeJavaRuntime="no"
>
<include name="javax/management/**"/>
<include name="com/sun/jmx/**"/>
@ -253,7 +253,7 @@
<mkdir dir="${dir.build.lib}" />
<jar jarfile="${dir.build.lib}/jmx.jar"
<jar jarfile="${dir.build.lib}/jmx.jar"
update="true"
>
@ -269,10 +269,10 @@
<attribute name="Sealed" value="true" />
<attribute name="Specification-Title" value="JMX(TM) API" />
<attribute name="Specification-Version" value="1.4" />
<attribute name="Specification-Vendor" value="Sun Microsystems, Inc." />
<attribute name="Specification-Vendor" value="Oracle Corporation" />
<attribute name="Implementation-Title" value="JMX(TM) API, Java SE 6 implementation" />
<attribute name="Implementation-Version" value="${BUILD_DATE} rebuild of Mustang JMX sources" />
<attribute name="Implementation-Vendor" value="Source bundle from Sun Microsystems, Inc. - Customer rebuilt" />
<attribute name="Implementation-Version" value="${BUILD_DATE} rebuild of Java SE JMX sources" />
<attribute name="Implementation-Vendor" value="Source bundle from Oracle Corporation - Customer rebuilt" />
</section>
</manifest>
</jar>
@ -295,16 +295,16 @@
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- Delete build directory and all its contents -->
<target name="clean-all"
<target name="clean-all"
description="Delete build directory and all its contents" >
<delete dir="${dir.build}" />
</target>
</target>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- Clean all and build everything -->
<target name="all" depends="clean-all,jar"
<target name="all" depends="clean-all,jar"
description="Clean all and build everything" />

View File

@ -92,8 +92,6 @@ import javax.management.RuntimeOperationsException;
* @since 1.5
*/
// Sun Microsystems, Sept. 2002: Revisited for JMX 1.2 (DF)
//
@SuppressWarnings("serial") // serialVersionUID is not constant
public class ModelMBeanNotificationInfo
extends MBeanNotificationInfo

View File

@ -0,0 +1,86 @@
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.net.ssl;
/**
* Extends the <code>SSLSession</code> interface to support additional
* session attributes.
*
* @since 1.7
*/
public abstract class ExtendedSSLSession implements SSLSession {
/**
* Obtains an array of supported signature algorithms that the local side
* is willing to use.
* <p>
* Note: this method is used to indicate to the peer which signature
* algorithms may be used for digital signatures in TLS 1.2. It is
* not meaningful for TLS versions prior to 1.2.
* <p>
* The signature algorithm name must be a standard Java Security
* name (such as "SHA1withRSA", "SHA256withECDSA", and so on).
* See Appendix A in the <a href=
* "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
* Java Cryptography Architecture API Specification &amp; Reference </a>
* for information about standard algorithm names.
* <p>
* Note: the local supported signature algorithms should conform to
* the algorithm constraints specified by
* {@link SSLParameters#getAlgorithmConstraints getAlgorithmConstraints()}
* method in <code>SSLParameters</code>.
*
* @return An array of supported signature algorithms, in descending
* order of preference. The return value is an empty array if
* no signature algorithm is supported.
*
* @see SSLParameters#getAlgorithmConstraints
*/
public abstract String[] getLocalSupportedSignatureAlgorithms();
/**
* Obtains an array of supported signature algorithms that the peer is
* able to use.
* <p>
* Note: this method is used to indicate to the local side which signature
* algorithms may be used for digital signatures in TLS 1.2. It is
* not meaningful for TLS versions prior to 1.2.
* <p>
* The signature algorithm name must be a standard Java Security
* name (such as "SHA1withRSA", "SHA256withECDSA", and so on).
* See Appendix A in the <a href=
* "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
* Java Cryptography Architecture API Specification &amp; Reference </a>
* for information about standard algorithm names.
*
* @return An array of supported signature algorithms, in descending
* order of preference. The return value is an empty array if
* the peer has not sent the supported signature algorithms.
*
* @see X509KeyManager
* @see X509ExtendedKeyManager
*/
public abstract String[] getPeerSupportedSignatureAlgorithms();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2005, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -188,19 +188,8 @@ class HttpsURLConnection extends HttpURLConnection
* <p>
* The default implementation will deny such connections.
*/
private static HostnameVerifier defaultHostnameVerifier;
/**
* Initialize the default <code>HostnameVerifier</code>.
*/
static {
try {
defaultHostnameVerifier =
new sun.net.www.protocol.https.DefaultHostnameVerifier();
} catch (NoClassDefFoundError e) {
defaultHostnameVerifier = new DefaultHostnameVerifier();
}
}
private static HostnameVerifier defaultHostnameVerifier =
new DefaultHostnameVerifier();
/*
* The initial default <code>HostnameVerifier</code>. Should be

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -967,6 +967,47 @@ public abstract class SSLEngine {
public abstract SSLSession getSession();
/**
* Returns the {@code SSLSession} being constructed during a SSL/TLS
* handshake.
* <p>
* TLS protocols may negotiate parameters that are needed when using
* an instance of this class, but before the {@code SSLSession} has
* been completely initialized and made available via {@code getSession}.
* For example, the list of valid signature algorithms may restrict
* the type of certificates that can used during TrustManager
* decisions, or the maximum TLS fragment packet sizes can be
* resized to better support the network environment.
* <p>
* This method provides early access to the {@code SSLSession} being
* constructed. Depending on how far the handshake has progressed,
* some data may not yet be available for use. For example, if a
* remote server will be sending a Certificate chain, but that chain
* has yet not been processed, the {@code getPeerCertificates}
* method of {@code SSLSession} will throw a
* SSLPeerUnverifiedException. Once that chain has been processed,
* {@code getPeerCertificates} will return the proper value.
*
* @see SSLSocket
* @see SSLSession
* @see ExtendedSSLSession
* @see X509ExtendedKeyManager
* @see X509ExtendedTrustManager
*
* @return null if this instance is not currently handshaking, or
* if the current handshake has not progressed far enough to
* create a basic SSLSession. Otherwise, this method returns the
* {@code SSLSession} currently being negotiated.
* @throws UnsupportedOperationException if the underlying provider
* does not implement the operation.
*
* @since 1.7
*/
public SSLSession getHandshakeSession() {
throw new UnsupportedOperationException();
}
/**
* Initiates handshaking (initial or renegotiation) on this SSLEngine.
* <P>

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,24 +25,29 @@
package javax.net.ssl;
import java.security.AlgorithmConstraints;
/**
* Encapsulates parameters for an SSL/TLS connection. The parameters
* are the list of ciphersuites to be accepted in an SSL/TLS handshake,
* the list of protocols to be allowed, and whether SSL/TLS servers should
* request or require client authentication.
*
* <p>SSLParameters can be created via the constructors in this class.
* the list of protocols to be allowed, the endpoint identification
* algorithm during SSL/TLS handshaking, the algorithm constraints and
* whether SSL/TLS servers should request or require client authentication.
* <p>
* SSLParameters can be created via the constructors in this class.
* Objects can also be obtained using the <code>getSSLParameters()</code>
* methods in
* {@link SSLSocket#getSSLParameters SSLSocket} and
* {@link SSLServerSocket#getSSLParameters SSLServerSocket} and
* {@link SSLEngine#getSSLParameters SSLEngine} or the
* {@link SSLContext#getDefaultSSLParameters getDefaultSSLParameters()} and
* {@link SSLContext#getSupportedSSLParameters getSupportedSSLParameters()}
* methods in <code>SSLContext</code>.
*
* <P>SSLParameters can be applied to a connection via the methods
* <p>
* SSLParameters can be applied to a connection via the methods
* {@link SSLSocket#setSSLParameters SSLSocket.setSSLParameters()} and
* {@link SSLEngine#setSSLParameters SSLEngine.getSSLParameters()}.
* {@link SSLServerSocket#setSSLParameters SSLServerSocket.setSSLParameters()}
* and {@link SSLEngine#setSSLParameters SSLEngine.getSSLParameters()}.
*
* @see SSLSocket
* @see SSLEngine
@ -56,11 +61,13 @@ public class SSLParameters {
private String[] protocols;
private boolean wantClientAuth;
private boolean needClientAuth;
private String identificationAlgorithm;
private AlgorithmConstraints algorithmConstraints;
/**
* Constructs SSLParameters.
*
* <p>The cipherSuites and protocols values are set to <code>null</code>,
* <p>
* The cipherSuites and protocols values are set to <code>null</code>,
* wantClientAuth and needClientAuth are set to <code>false</code>.
*/
public SSLParameters() {
@ -69,6 +76,7 @@ public class SSLParameters {
/**
* Constructs SSLParameters from the specified array of ciphersuites.
* <p>
* Calling this constructor is equivalent to calling the no-args
* constructor followed by
* <code>setCipherSuites(cipherSuites);</code>.
@ -82,6 +90,7 @@ public class SSLParameters {
/**
* Constructs SSLParameters from the specified array of ciphersuites
* and protocols.
* <p>
* Calling this constructor is equivalent to calling the no-args
* constructor followed by
* <code>setCipherSuites(cipherSuites); setProtocols(protocols);</code>.
@ -178,4 +187,71 @@ public class SSLParameters {
this.needClientAuth = needClientAuth;
}
/**
* Returns the cryptographic algorithm constraints.
*
* @return the cryptographic algorithm constraints, or null if the
* constraints have not been set
*
* @see #setAlgorithmConstraints(AlgorithmConstraints)
*
* @since 1.7
*/
public AlgorithmConstraints getAlgorithmConstraints() {
return algorithmConstraints;
}
/**
* Sets the cryptographic algorithm constraints, which will be used
* in addition to any configured by the runtime environment.
* <p>
* If the <code>constraints</code> parameter is non-null, every
* cryptographic algorithm, key and algorithm parameters used in the
* SSL/TLS handshake must be permitted by the constraints.
*
* @param constraints the algorithm constraints (or null)
*
* @since 1.7
*/
public void setAlgorithmConstraints(AlgorithmConstraints constraints) {
// the constraints object is immutable
this.algorithmConstraints = constraints;
}
/**
* Gets the endpoint identification algorithm.
*
* @return the endpoint identification algorithm, or null if none
* has been set.
*
* @see X509ExtendedTrustManager
* @see #setEndpointIdentificationAlgorithm(String)
*
* @since 1.7
*/
public String getEndpointIdentificationAlgorithm() {
return identificationAlgorithm;
}
/**
* Sets the endpoint identification algorithm.
* <p>
* If the <code>algorithm</code> parameter is non-null or non-empty, the
* endpoint identification/verification procedures must be handled during
* SSL/TLS handshaking. This is to prevent man-in-the-middle attacks.
*
* @param algorithm The standard string name of the endpoint
* identification algorithm (or null). See Appendix A in the <a href=
* "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
* Java Cryptography Architecture API Specification &amp; Reference </a>
* for information about standard algorithm names.
*
* @see X509ExtendedTrustManager
*
* @since 1.7
*/
public void setEndpointIdentificationAlgorithm(String algorithm) {
this.identificationAlgorithm = algorithm;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -56,8 +56,8 @@ import java.net.*;
* @since 1.4
* @author David Brownell
*/
public abstract class SSLServerSocket extends ServerSocket
{
public abstract class SSLServerSocket extends ServerSocket {
/**
* Used only by subclasses.
* <P>
@ -449,8 +449,79 @@ public abstract class SSLServerSocket extends ServerSocket
*
* @return true indicates that sessions may be created; this
* is the default. false indicates that an existing
* session must be resumed.
* session must be resumed
* @see #setEnableSessionCreation(boolean)
*/
public abstract boolean getEnableSessionCreation();
/**
* Returns the SSLParameters in effect for newly accepted connections.
* The ciphersuites and protocols of the returned SSLParameters
* are always non-null.
*
* @return the SSLParameters in effect for newly accepted connections
*
* @see #setSSLParameters(SSLParameters)
*
* @since 1.7
*/
public SSLParameters getSSLParameters() {
SSLParameters parameters = new SSLParameters();
parameters.setCipherSuites(getEnabledCipherSuites());
parameters.setProtocols(getEnabledProtocols());
if (getNeedClientAuth()) {
parameters.setNeedClientAuth(true);
} else if (getWantClientAuth()) {
parameters.setWantClientAuth(true);
}
return parameters;
}
/**
* Applies SSLParameters to newly accepted connections.
*
* <p>This means:
* <ul>
* <li>if <code>params.getCipherSuites()</code> is non-null,
* <code>setEnabledCipherSuites()</code> is called with that value
* <li>if <code>params.getProtocols()</code> is non-null,
* <code>setEnabledProtocols()</code> is called with that value
* <li>if <code>params.getNeedClientAuth()</code> or
* <code>params.getWantClientAuth()</code> return <code>true</code>,
* <code>setNeedClientAuth(true)</code> and
* <code>setWantClientAuth(true)</code> are called, respectively;
* otherwise <code>setWantClientAuth(false)</code> is called.
* </ul>
*
* @param params the parameters
* @throws IllegalArgumentException if the setEnabledCipherSuites() or
* the setEnabledProtocols() call fails
*
* @see #getSSLParameters()
*
* @since 1.7
*/
public void setSSLParameters(SSLParameters params) {
String[] s;
s = params.getCipherSuites();
if (s != null) {
setEnabledCipherSuites(s);
}
s = params.getProtocols();
if (s != null) {
setEnabledProtocols(s);
}
if (params.getNeedClientAuth()) {
setNeedClientAuth(true);
} else if (params.getWantClientAuth()) {
setWantClientAuth(true);
} else {
setWantClientAuth(false);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -370,6 +370,51 @@ public abstract class SSLSocket extends Socket
public abstract SSLSession getSession();
/**
* Returns the {@code SSLSession} being constructed during a SSL/TLS
* handshake.
* <p>
* TLS protocols may negotiate parameters that are needed when using
* an instance of this class, but before the {@code SSLSession} has
* been completely initialized and made available via {@code getSession}.
* For example, the list of valid signature algorithms may restrict
* the type of certificates that can used during TrustManager
* decisions, or the maximum TLS fragment packet sizes can be
* resized to better support the network environment.
* <p>
* This method provides early access to the {@code SSLSession} being
* constructed. Depending on how far the handshake has progressed,
* some data may not yet be available for use. For example, if a
* remote server will be sending a Certificate chain, but that chain
* has yet not been processed, the {@code getPeerCertificates}
* method of {@code SSLSession} will throw a
* SSLPeerUnverifiedException. Once that chain has been processed,
* {@code getPeerCertificates} will return the proper value.
* <p>
* Unlike {@link #getSession()}, this method does not initiate the
* initial handshake and does not block until handshaking is
* complete.
*
* @see SSLEngine
* @see SSLSession
* @see ExtendedSSLSession
* @see X509ExtendedKeyManager
* @see X509ExtendedTrustManager
*
* @return null if this instance is not currently handshaking, or
* if the current handshake has not progressed far enough to
* create a basic SSLSession. Otherwise, this method returns the
* {@code SSLSession} currently being negotiated.
* @throws UnsupportedOperationException if the underlying provider
* does not implement the operation.
*
* @since 1.7
*/
public SSLSession getHandshakeSession() {
throw new UnsupportedOperationException();
}
/**
* Registers an event listener to receive notifications that an
* SSL handshake has completed on this connection.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -30,6 +30,7 @@ import java.net.*;
import javax.net.SocketFactory;
import java.io.IOException;
import java.security.*;
import java.util.Locale;
import sun.security.action.GetPropertyAction;
@ -50,7 +51,8 @@ public abstract class SSLSocketFactory extends SocketFactory
static {
String s = java.security.AccessController.doPrivileged(
new GetPropertyAction("javax.net.debug", "")).toLowerCase();
new GetPropertyAction("javax.net.debug", "")).toLowerCase(
Locale.ENGLISH);
DEBUG = s.contains("all") || s.contains("ssl");
}

View File

@ -0,0 +1,234 @@
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.net.ssl;
import java.net.Socket;
import javax.net.ssl.X509TrustManager;
import java.security.cert.X509Certificate;
import java.security.cert.CertificateException;
/**
* Extensions to the <code>X509TrustManager</code> interface to support
* SSL/TLS connection sensitive trust management.
* <p>
* To prevent man-in-the-middle attacks, hostname checks can be done
* to verify that the hostname in an end-entity certificate matches the
* targeted hostname. TLS does not require such checks, but some protocols
* over TLS (such as HTTPS) do. In earlier versions of the JDK, the
* certificate chain checks were done at the SSL/TLS layer, and the hostname
* verification checks were done at the layer over TLS. This class allows
* for the checking to be done during a single call to this class.
* <p>
* RFC 2830 defines the server identification specification for the "LDAPS"
* algorithm. RFC 2818 defines both the server identification and the
* client identification specification for the "HTTPS" algorithm.
*
* @see X509TrustManager
* @see HostnameVerifier
*
* @since 1.7
*/
public abstract class X509ExtendedTrustManager implements X509TrustManager {
/**
* Given the partial or complete certificate chain provided by the
* peer, build and validate the certificate path based on the
* authentication type and ssl parameters.
* <p>
* The authentication type is determined by the actual certificate
* used. For instance, if RSAPublicKey is used, the authType
* should be "RSA". Checking is case-sensitive.
* <p>
* If the <code>socket</code> parameter is an instance of
* {@link javax.net.SSLSocket}, and the endpoint identification
* algorithm of the <code>SSLParameters</code> is non-empty, to prevent
* man-in-the-middle attacks, the address that the <code>socket</code>
* connected to should be checked against the peer's identity presented
* in the end-entity X509 certificate, as specified in the endpoint
* identification algorithm.
* <p>
* If the <code>socket</code> parameter is an instance of
* {@link javax.net.SSLSocket}, and the algorithm constraints of the
* <code>SSLParameters</code> is non-null, for every certificate in the
* certification path, fields such as subject public key, the signature
* algorithm, key usage, extended key usage, etc. need to conform to the
* algorithm constraints in place on this socket.
*
* @param chain the peer certificate chain
* @param authType the key exchange algorithm used
* @param socket the socket used for this connection. This parameter
* can be null, which indicates that implementations need not check
* the ssl parameters
* @throws IllegalArgumentException if null or zero-length array is passed
* in for the <code>chain</code> parameter or if null or zero-length
* string is passed in for the <code>authType</code> parameter
* @throws CertificateException if the certificate chain is not trusted
* by this TrustManager
*
* @see SSLParameters#getEndpointIdentificationProtocol
* @see SSLParameters#setEndpointIdentificationProtocol(String)
* @see SSLParameters#getAlgorithmConstraints
* @see SSLParameters#setAlgorithmConstraints(AlgorithmConstraints)
*/
public abstract void checkClientTrusted(X509Certificate[] chain,
String authType, Socket socket) throws CertificateException;
/**
* Given the partial or complete certificate chain provided by the
* peer, build and validate the certificate path based on the
* authentication type and ssl parameters.
* <p>
* The authentication type is the key exchange algorithm portion
* of the cipher suites represented as a String, such as "RSA",
* "DHE_DSS". Note: for some exportable cipher suites, the key
* exchange algorithm is determined at run time during the
* handshake. For instance, for TLS_RSA_EXPORT_WITH_RC4_40_MD5,
* the authType should be RSA_EXPORT when an ephemeral RSA key is
* used for the key exchange, and RSA when the key from the server
* certificate is used. Checking is case-sensitive.
* <p>
* If the <code>socket</code> parameter is an instance of
* {@link javax.net.SSLSocket}, and the endpoint identification
* algorithm of the <code>SSLParameters</code> is non-empty, to prevent
* man-in-the-middle attacks, the address that the <code>socket</code>
* connected to should be checked against the peer's identity presented
* in the end-entity X509 certificate, as specified in the endpoint
* identification algorithm.
* <p>
* If the <code>socket</code> parameter is an instance of
* {@link javax.net.SSLSocket}, and the algorithm constraints of the
* <code>SSLParameters</code> is non-null, for every certificate in the
* certification path, fields such as subject public key, the signature
* algorithm, key usage, extended key usage, etc. need to conform to the
* algorithm constraints in place on this socket.
*
* @param chain the peer certificate chain
* @param authType the key exchange algorithm used
* @param socket the socket used for this connection. This parameter
* can be null, which indicates that implementations need not check
* the ssl parameters
* @throws IllegalArgumentException if null or zero-length array is passed
* in for the <code>chain</code> parameter or if null or zero-length
* string is passed in for the <code>authType</code> parameter
* @throws CertificateException if the certificate chain is not trusted
* by this TrustManager
*
* @see SSLParameters#getEndpointIdentificationProtocol
* @see SSLParameters#setEndpointIdentificationProtocol(String)
* @see SSLParameters#getAlgorithmConstraints
* @see SSLParameters#setAlgorithmConstraints(AlgorithmConstraints)
*/
public abstract void checkServerTrusted(X509Certificate[] chain,
String authType, Socket socket) throws CertificateException;
/**
* Given the partial or complete certificate chain provided by the
* peer, build and validate the certificate path based on the
* authentication type and ssl parameters.
* <p>
* The authentication type is determined by the actual certificate
* used. For instance, if RSAPublicKey is used, the authType
* should be "RSA". Checking is case-sensitive.
* <p>
* If the <code>engine</code> parameter is available, and the endpoint
* identification algorithm of the <code>SSLParameters</code> is
* non-empty, to prevent man-in-the-middle attacks, the address that
* the <code>engine</code> connected to should be checked against
* the peer's identity presented in the end-entity X509 certificate,
* as specified in the endpoint identification algorithm.
* <p>
* If the <code>engine</code> parameter is available, and the algorithm
* constraints of the <code>SSLParameters</code> is non-null, for every
* certificate in the certification path, fields such as subject public
* key, the signature algorithm, key usage, extended key usage, etc.
* need to conform to the algorithm constraints in place on this engine.
*
* @param chain the peer certificate chain
* @param authType the key exchange algorithm used
* @param engine the engine used for this connection. This parameter
* can be null, which indicates that implementations need not check
* the ssl parameters
* @throws IllegalArgumentException if null or zero-length array is passed
* in for the <code>chain</code> parameter or if null or zero-length
* string is passed in for the <code>authType</code> parameter
* @throws CertificateException if the certificate chain is not trusted
* by this TrustManager
*
* @see SSLParameters#getEndpointIdentificationProtocol
* @see SSLParameters#setEndpointIdentificationProtocol(String)
* @see SSLParameters#getAlgorithmConstraints
* @see SSLParameters#setAlgorithmConstraints(AlgorithmConstraints)
*/
public abstract void checkClientTrusted(X509Certificate[] chain,
String authType, SSLEngine engine) throws CertificateException;
/**
* Given the partial or complete certificate chain provided by the
* peer, build and validate the certificate path based on the
* authentication type and ssl parameters.
* <p>
* The authentication type is the key exchange algorithm portion
* of the cipher suites represented as a String, such as "RSA",
* "DHE_DSS". Note: for some exportable cipher suites, the key
* exchange algorithm is determined at run time during the
* handshake. For instance, for TLS_RSA_EXPORT_WITH_RC4_40_MD5,
* the authType should be RSA_EXPORT when an ephemeral RSA key is
* used for the key exchange, and RSA when the key from the server
* certificate is used. Checking is case-sensitive.
* <p>
* If the <code>engine</code> parameter is available, and the endpoint
* identification algorithm of the <code>SSLParameters</code> is
* non-empty, to prevent man-in-the-middle attacks, the address that
* the <code>engine</code> connected to should be checked against
* the peer's identity presented in the end-entity X509 certificate,
* as specified in the endpoint identification algorithm.
* <p>
* If the <code>engine</code> parameter is available, and the algorithm
* constraints of the <code>SSLParameters</code> is non-null, for every
* certificate in the certification path, fields such as subject public
* key, the signature algorithm, key usage, extended key usage, etc.
* need to conform to the algorithm constraints in place on this engine.
*
* @param chain the peer certificate chain
* @param authType the key exchange algorithm used
* @param engine the engine used for this connection. This parameter
* can be null, which indicates that implementations need not check
* the ssl parameters
* @throws IllegalArgumentException if null or zero-length array is passed
* in for the <code>chain</code> parameter or if null or zero-length
* string is passed in for the <code>authType</code> parameter
* @throws CertificateException if the certificate chain is not trusted
* by this TrustManager
*
* @see SSLParameters#getEndpointIdentificationProtocol
* @see SSLParameters#setEndpointIdentificationProtocol(String)
* @see SSLParameters#getAlgorithmConstraints
* @see SSLParameters#setAlgorithmConstraints(AlgorithmConstraints)
*/
public abstract void checkServerTrusted(X509Certificate[] chain,
String authType, SSLEngine engine) throws CertificateException;
}

View File

@ -25,7 +25,6 @@
package sun.net;
import java.net.InetAddress;
import java.security.PrivilegedAction;
import java.security.Security;
@ -57,7 +56,7 @@ public final class InetAddressCachePolicy {
* caching. For security reasons, this caching is made forever when
* a security manager is set.
*/
private static int cachePolicy;
private static int cachePolicy = FOREVER;
/* The Java-level namelookup cache policy for negative lookups:
*
@ -67,31 +66,24 @@ public final class InetAddressCachePolicy {
* default value is 0. It can be set to some other value for
* performance reasons.
*/
private static int negativeCachePolicy;
private static int negativeCachePolicy = NEVER;
/*
* Whether or not the cache policy for successful lookups was set
* using a property (cmd line).
*/
private static boolean set = false;
private static boolean propertySet;
/*
* Whether or not the cache policy for negative lookups was set
* using a property (cmd line).
*/
private static boolean negativeSet = false;
private static boolean propertyNegativeSet;
/*
* Initialize
*/
static {
set = false;
negativeSet = false;
cachePolicy = FOREVER;
negativeCachePolicy = 0;
Integer tmp = null;
try {
@ -110,7 +102,7 @@ public final class InetAddressCachePolicy {
if (cachePolicy < 0) {
cachePolicy = FOREVER;
}
set = true;
propertySet = true;
} else {
tmp = java.security.AccessController.doPrivileged
(new sun.security.action.GetIntegerAction(cachePolicyPropFallback));
@ -119,7 +111,14 @@ public final class InetAddressCachePolicy {
if (cachePolicy < 0) {
cachePolicy = FOREVER;
}
set = true;
propertySet = true;
} else {
/* No properties defined for positive caching. If there is no
* security manager then use the default positive cache value.
*/
if (System.getSecurityManager() == null) {
cachePolicy = DEFAULT_POSITIVE;
}
}
}
@ -140,7 +139,7 @@ public final class InetAddressCachePolicy {
if (negativeCachePolicy < 0) {
negativeCachePolicy = FOREVER;
}
negativeSet = true;
propertyNegativeSet = true;
} else {
tmp = java.security.AccessController.doPrivileged
(new sun.security.action.GetIntegerAction(negativeCachePolicyPropFallback));
@ -149,17 +148,13 @@ public final class InetAddressCachePolicy {
if (negativeCachePolicy < 0) {
negativeCachePolicy = FOREVER;
}
negativeSet = true;
propertyNegativeSet = true;
}
}
}
public static synchronized int get() {
if (!set && System.getSecurityManager() == null) {
return DEFAULT_POSITIVE;
} else {
return cachePolicy;
}
return cachePolicy;
}
public static synchronized int getNegative() {
@ -174,21 +169,17 @@ public final class InetAddressCachePolicy {
* should be cached
*/
public static synchronized void setIfNotSet(int newPolicy) {
/*
* When setting the new value we may want to signal that the
* cache should be flushed, though this doesn't seem strictly
* necessary.
*/
if (!set) {
if (!propertySet) {
checkValue(newPolicy, cachePolicy);
cachePolicy = newPolicy;
}
}
/**
* Sets the cache policy for negative lookups if the user has not
* already specified a cache policy for it using a
@ -197,14 +188,12 @@ public final class InetAddressCachePolicy {
* should be cached
*/
public static synchronized void setNegativeIfNotSet(int newPolicy) {
/*
* When setting the new value we may want to signal that the
* cache should be flushed, though this doesn't seem strictly
* necessary.
*/
if (!negativeSet) {
if (!propertyNegativeSet) {
// Negative caching does not seem to have any security
// implications.
// checkValue(newPolicy, negativeCachePolicy);
@ -213,13 +202,11 @@ public final class InetAddressCachePolicy {
}
private static void checkValue(int newPolicy, int oldPolicy) {
/*
* If malicious code gets a hold of this method, prevent
* setting the cache policy to something laxer or some
* invalid negative value.
*/
if (newPolicy == FOREVER)
return;
@ -229,7 +216,6 @@ public final class InetAddressCachePolicy {
throw new
SecurityException("can't make InetAddress cache more lax");
}
}
}

View File

@ -40,6 +40,12 @@ import java.security.PrivilegedAction;
* @author Jonathan Payne
*/
public class NetworkClient {
/* Default value of read timeout, if not specified (infinity) */
public static final int DEFAULT_READ_TIMEOUT = -1;
/* Default value of connect timeout, if not specified (infinity) */
public static final int DEFAULT_CONNECT_TIMEOUT = -1;
protected Proxy proxy = Proxy.NO_PROXY;
/** Socket for communicating with server. */
protected Socket serverSocket = null;
@ -53,8 +59,8 @@ public class NetworkClient {
protected static int defaultSoTimeout;
protected static int defaultConnectTimeout;
protected int readTimeout = -1;
protected int connectTimeout = -1;
protected int readTimeout = DEFAULT_READ_TIMEOUT;
protected int connectTimeout = DEFAULT_CONNECT_TIMEOUT;
/* Name of encoding to use for output */
protected static String encoding;
@ -71,16 +77,12 @@ public class NetworkClient {
return null;
}
});
if (vals[0] == 0)
defaultSoTimeout = -1;
else
if (vals[0] != 0) {
defaultSoTimeout = vals[0];
if (vals[1] == 0)
defaultConnectTimeout = -1;
else
}
if (vals[1] != 0) {
defaultConnectTimeout = vals[1];
}
encoding = encs[0];
try {
@ -232,7 +234,23 @@ public class NetworkClient {
return connectTimeout;
}
/**
* Sets the read timeout.
*
* Note: Public URLConnection (and protocol specific implementations)
* protect against negative timeout values being set. This implemenation,
* and protocol specific implementations, use -1 to represent the default
* read timeout.
*
* This method may be invoked with the default timeout value when the
* protocol handler is trying to reset the timeout after doing a
* potentially blocking internal operation, e.g. cleaning up unread
* response data, buffering error stream response data, etc
*/
public void setReadTimeout(int timeout) {
if (timeout == DEFAULT_READ_TIMEOUT)
timeout = defaultSoTimeout;
if (serverSocket != null && timeout >= 0) {
try {
serverSocket.setSoTimeout(timeout);

View File

@ -46,6 +46,7 @@ import java.net.ProxySelector;
import java.util.StringTokenizer;
import java.util.Iterator;
import java.security.Permission;
import sun.net.NetworkClient;
import sun.net.www.MessageHeader;
import sun.net.www.MeteredStream;
import sun.net.www.URLConnection;
@ -102,11 +103,11 @@ public class FtpURLConnection extends URLConnection {
static final int BIN = 2;
static final int DIR = 3;
int type = NONE;
/* Redefine timeouts from java.net.URLConnection as we nee -1 to mean
/* Redefine timeouts from java.net.URLConnection as we need -1 to mean
* not set. This is to ensure backward compatibility.
*/
private int connectTimeout = -1;
private int readTimeout = -1;
private int connectTimeout = NetworkClient.DEFAULT_CONNECT_TIMEOUT;;
private int readTimeout = NetworkClient.DEFAULT_READ_TIMEOUT;;
/**
* For FTP URLs we need to have a special InputStream because we

View File

@ -359,11 +359,11 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
private TunnelState tunnelState = TunnelState.NONE;
/* Redefine timeouts from java.net.URLConnection as we nee -1 to mean
/* Redefine timeouts from java.net.URLConnection as we need -1 to mean
* not set. This is to ensure backward compatibility.
*/
private int connectTimeout = -1;
private int readTimeout = -1;
private int connectTimeout = NetworkClient.DEFAULT_CONNECT_TIMEOUT;
private int readTimeout = NetworkClient.DEFAULT_READ_TIMEOUT;
/* Logging support */
private static final PlatformLogger logger =
@ -1041,9 +1041,9 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
throw new ProtocolException("Server rejected operation");
}
}
if (oldTimeout > 0) {
http.setReadTimeout(oldTimeout);
}
http.setReadTimeout(oldTimeout);
responseCode = -1;
responses.reset();
// Proceed

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -109,6 +109,10 @@ final class HttpsClient extends HttpClient
// HTTPS uses a different default port number than HTTP.
private static final int httpsPortNumber = 443;
// default HostnameVerifier class canonical name
private static final String defaultHVCanonicalName =
"javax.net.ssl.HttpsURLConnection.DefaultHostnameVerifier";
/** Returns the default HTTPS port (443) */
@Override
protected int getDefaultPort() { return httpsPortNumber; }
@ -427,13 +431,93 @@ final class HttpsClient extends HttpClient
}
s.addHandshakeCompletedListener(this);
// if the HostnameVerifier is not set, try to enable endpoint
// identification during handshaking
boolean enabledIdentification = false;
if (hv instanceof DefaultHostnameVerifier &&
(s instanceof SSLSocketImpl) &&
((SSLSocketImpl)s).trySetHostnameVerification("HTTPS")) {
enabledIdentification = true;
// We have two hostname verification approaches. One is in
// SSL/TLS socket layer, where the algorithm is configured with
// SSLParameters.setEndpointIdentificationAlgorithm(), and the
// hostname verification is done by X509ExtendedTrustManager when
// the algorithm is "HTTPS". The other one is in HTTPS layer,
// where the algorithm is customized by
// HttpsURLConnection.setHostnameVerifier(), and the hostname
// verification is done by HostnameVerifier when the default
// rules for hostname verification fail.
//
// The relationship between two hostname verification approaches
// likes the following:
//
// | EIA algorithm
// +----------------------------------------------
// | null | HTTPS | LDAP/other |
// -------------------------------------------------------------
// | |1 |2 |3 |
// HNV | default | Set HTTPS EIA | use EIA | HTTPS |
// |--------------------------------------------------------
// | non - |4 |5 |6 |
// | default | HTTPS/HNV | use EIA | HTTPS/HNV |
// -------------------------------------------------------------
//
// Abbreviation:
// EIA: the endpoint identification algorithm in SSL/TLS
// socket layer
// HNV: the hostname verification object in HTTPS layer
// Notes:
// case 1. default HNV and EIA is null
// Set EIA as HTTPS, hostname check done in SSL/TLS
// layer.
// case 2. default HNV and EIA is HTTPS
// Use existing EIA, hostname check done in SSL/TLS
// layer.
// case 3. default HNV and EIA is other than HTTPS
// Use existing EIA, EIA check done in SSL/TLS
// layer, then do HTTPS check in HTTPS layer.
// case 4. non-default HNV and EIA is null
// No EIA, no EIA check done in SSL/TLS layer, then do
// HTTPS check in HTTPS layer using HNV as override.
// case 5. non-default HNV and EIA is HTTPS
// Use existing EIA, hostname check done in SSL/TLS
// layer. No HNV override possible. We will review this
// decision and may update the architecture for JDK 7.
// case 6. non-default HNV and EIA is other than HTTPS
// Use existing EIA, EIA check done in SSL/TLS layer,
// then do HTTPS check in HTTPS layer as override.
boolean needToCheckSpoofing = true;
String identification =
s.getSSLParameters().getEndpointIdentificationAlgorithm();
if (identification != null && identification.length() != 0) {
if (identification.equalsIgnoreCase("HTTPS")) {
// Do not check server identity again out of SSLSocket,
// the endpoint will be identified during TLS handshaking
// in SSLSocket.
needToCheckSpoofing = false;
} // else, we don't understand the identification algorithm,
// need to check URL spoofing here.
} else {
boolean isDefaultHostnameVerifier = false;
// We prefer to let the SSLSocket do the spoof checks, but if
// the application has specified a HostnameVerifier (HNV),
// we will always use that.
if (hv != null) {
String canonicalName = hv.getClass().getCanonicalName();
if (canonicalName != null &&
canonicalName.equalsIgnoreCase(defaultHVCanonicalName)) {
isDefaultHostnameVerifier = true;
}
} else {
// Unlikely to happen! As the behavior is the same as the
// default hostname verifier, so we prefer to let the
// SSLSocket do the spoof checks.
isDefaultHostnameVerifier = true;
}
if (isDefaultHostnameVerifier) {
// If the HNV is the default from HttpsURLConnection, we
// will do the spoof checks in SSLSocket.
SSLParameters paramaters = s.getSSLParameters();
paramaters.setEndpointIdentificationAlgorithm("HTTPS");
s.setSSLParameters(paramaters);
needToCheckSpoofing = false;
}
}
s.startHandshake();
@ -449,7 +533,7 @@ final class HttpsClient extends HttpClient
}
// check URL spoofing if it has not been checked under handshaking
if (!enabledIdentification) {
if (needToCheckSpoofing) {
checkURLSpoofing(hv);
}
} else {
@ -463,8 +547,7 @@ final class HttpsClient extends HttpClient
// Server identity checking is done according to RFC 2818: HTTP over TLS
// Section 3.1 Server Identity
private void checkURLSpoofing(HostnameVerifier hostnameVerifier)
throws IOException
{
throws IOException {
//
// Get authenticated server name, if any
//

View File

@ -711,10 +711,8 @@ class DatagramChannelImpl
cachedSenderInetAddress = isa.getAddress();
cachedSenderPort = isa.getPort();
// Socket was not bound before connecting,
if (localAddress == null) {
localAddress = Net.localAddress(fd);
}
// set or refresh local address
localAddress = Net.localAddress(fd);
}
}
}
@ -735,6 +733,9 @@ class DatagramChannelImpl
disconnect0(fd);
remoteAddress = null;
state = ST_UNCONNECTED;
// refresh local address
localAddress = Net.localAddress(fd);
}
}
}

View File

@ -699,15 +699,19 @@ public class FileChannelImpl
static volatile long totalSize;
static volatile long totalCapacity;
private long address;
private long size;
private int cap;
private volatile long address;
private final long size;
private final int cap;
private final FileDescriptor fd;
private Unmapper(long address, long size, int cap) {
private Unmapper(long address, long size, int cap,
FileDescriptor fd)
{
assert (address != 0);
this.address = address;
this.size = size;
this.cap = cap;
this.fd = fd;
synchronized (Unmapper.class) {
count++;
@ -722,6 +726,15 @@ public class FileChannelImpl
unmap0(address, size);
address = 0;
// if this mapping has a valid file descriptor then we close it
if (fd.valid()) {
try {
nd.close(fd);
} catch (IOException ignore) {
// nothing we can do
}
}
synchronized (Unmapper.class) {
count--;
totalSize -= size;
@ -784,10 +797,12 @@ public class FileChannelImpl
}
if (size == 0) {
addr = 0;
// a valid file descriptor is not required
FileDescriptor dummy = new FileDescriptor();
if ((!writable) || (imode == MAP_RO))
return Util.newMappedByteBufferR(0, 0, null);
return Util.newMappedByteBufferR(0, 0, dummy, null);
else
return Util.newMappedByteBuffer(0, 0, null);
return Util.newMappedByteBuffer(0, 0, dummy, null);
}
int pagePosition = (int)(position % allocationGranularity);
@ -813,14 +828,31 @@ public class FileChannelImpl
}
}
// On Windows, and potentially other platforms, we need an open
// file descriptor for some mapping operations.
FileDescriptor mfd;
try {
mfd = nd.duplicateForMapping(fd);
} catch (IOException ioe) {
unmap0(addr, mapSize);
throw ioe;
}
assert (IOStatus.checkAll(addr));
assert (addr % allocationGranularity == 0);
int isize = (int)size;
Unmapper um = new Unmapper(addr, size + pagePosition, isize);
if ((!writable) || (imode == MAP_RO))
return Util.newMappedByteBufferR(isize, addr + pagePosition, um);
else
return Util.newMappedByteBuffer(isize, addr + pagePosition, um);
Unmapper um = new Unmapper(addr, mapSize, isize, mfd);
if ((!writable) || (imode == MAP_RO)) {
return Util.newMappedByteBufferR(isize,
addr + pagePosition,
mfd,
um);
} else {
return Util.newMappedByteBuffer(isize,
addr + pagePosition,
mfd,
um);
}
} finally {
threads.remove(ti);
end(IOStatus.checkAll(addr));

View File

@ -45,4 +45,12 @@ abstract class FileDispatcher extends NativeDispatcher {
abstract void release(FileDescriptor fd, long pos, long size)
throws IOException;
/**
* Returns a dup of fd if a file descriptor is required for
* memory-mapping operations, otherwise returns an invalid
* FileDescriptor (meaning a newly allocated FileDescriptor)
*/
abstract FileDescriptor duplicateForMapping(FileDescriptor fd)
throws IOException;
}

View File

@ -1,667 +0,0 @@
/*
* Copyright (c) 2008, 2009, 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.nio.ch;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.net.*;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.*;
import java.security.AccessController;
import java.security.AccessControlContext;
import java.security.PrivilegedExceptionAction;
import java.security.PrivilegedActionException;
/**
* A prototype implementation of AsynchronousDatagramChannel, used to aid
* test and spec development.
*/
class SimpleAsynchronousDatagramChannelImpl
extends AsynchronousDatagramChannel implements Groupable, Cancellable
{
private final DatagramChannel dc;
private final AsynchronousChannelGroupImpl group;
private final Object attachKey;
private boolean closed;
// used to coordinate timed and blocking reads
private final Object readLock = new Object();
// channel blocking mode (requires readLock)
private boolean isBlocking = true;
// number of blocking readers (requires readLock)
private int blockingReaderCount;
// true if timed read attempted while blocking read in progress (requires readLock)
private boolean transitionToNonBlocking;
// true if a blocking read is cancelled (requires readLock)
private boolean blockingReadKilledByCancel;
// temporary Selectors used by timed reads (requires readLock)
private Selector firstReader;
private Set<Selector> otherReaders;
SimpleAsynchronousDatagramChannelImpl(ProtocolFamily family,
AsynchronousChannelGroupImpl group)
throws IOException
{
super(group.provider());
this.dc = (family == null) ?
DatagramChannel.open() : DatagramChannel.open(family);
this.group = group;
// attach this channel to the group as foreign channel
boolean registered = false;
try {
if (!(dc instanceof DatagramChannelImpl))
throw new UnsupportedOperationException();
attachKey = group
.attachForeignChannel(this, ((DatagramChannelImpl)dc).getFD());
registered = true;
} finally {
if (!registered)
dc.close();
}
}
// throws RuntimeException if blocking read has been cancelled
private void ensureBlockingReadNotKilled() {
assert Thread.holdsLock(readLock);
if (blockingReadKilledByCancel)
throw new RuntimeException("Reading not allowed due to cancellation");
}
// invoke prior to non-timed read/receive
private void beginNoTimeoutRead() {
synchronized (readLock) {
ensureBlockingReadNotKilled();
if (isBlocking)
blockingReaderCount++;
}
}
// invoke after non-timed read/receive has completed
private void endNoTimeoutRead() {
synchronized (readLock) {
if (isBlocking) {
if (--blockingReaderCount == 0 && transitionToNonBlocking) {
// notify any threads waiting to make channel non-blocking
readLock.notifyAll();
}
}
}
}
// invoke prior to timed read
// returns the timeout remaining
private long prepareForTimedRead(PendingFuture<?,?> result, long timeout)
throws IOException
{
synchronized (readLock) {
ensureBlockingReadNotKilled();
if (isBlocking) {
transitionToNonBlocking = true;
while (blockingReaderCount > 0 &&
timeout > 0L &&
!result.isCancelled())
{
long st = System.currentTimeMillis();
try {
readLock.wait(timeout);
} catch (InterruptedException e) { }
timeout -= System.currentTimeMillis() - st;
}
if (blockingReaderCount == 0) {
// re-check that blocked read wasn't cancelled
ensureBlockingReadNotKilled();
// no blocking reads so change channel to non-blocking
dc.configureBlocking(false);
isBlocking = false;
}
}
return timeout;
}
}
// returns a temporary Selector
private Selector getSelector() throws IOException {
Selector sel = Util.getTemporarySelector(dc);
synchronized (readLock) {
if (firstReader == null) {
firstReader = sel;
} else {
if (otherReaders == null)
otherReaders = new HashSet<Selector>();
otherReaders.add(sel);
}
}
return sel;
}
// releases a temporary Selector
private void releaseSelector(Selector sel) throws IOException {
synchronized (readLock) {
if (firstReader == sel) {
firstReader = null;
} else {
otherReaders.remove(sel);
}
}
Util.releaseTemporarySelector(sel);
}
// wakeup all Selectors currently in use
private void wakeupSelectors() {
synchronized (readLock) {
if (firstReader != null)
firstReader.wakeup();
if (otherReaders != null) {
for (Selector sel: otherReaders) {
sel.wakeup();
}
}
}
}
@Override
public AsynchronousChannelGroupImpl group() {
return group;
}
@Override
public boolean isOpen() {
return dc.isOpen();
}
@Override
public void onCancel(PendingFuture<?,?> task) {
synchronized (readLock) {
if (blockingReaderCount > 0) {
blockingReadKilledByCancel = true;
readLock.notifyAll();
return;
}
}
wakeupSelectors();
}
@Override
public void close() throws IOException {
synchronized (dc) {
if (closed)
return;
closed = true;
}
// detach from group and close underlying channel
group.detachForeignChannel(attachKey);
dc.close();
// wakeup any threads blocked in timed read/receives
wakeupSelectors();
}
@Override
public AsynchronousDatagramChannel connect(SocketAddress remote)
throws IOException
{
dc.connect(remote);
return this;
}
@Override
public AsynchronousDatagramChannel disconnect() throws IOException {
dc.disconnect();
return this;
}
private static class WrappedMembershipKey extends MembershipKey {
private final MulticastChannel channel;
private final MembershipKey key;
WrappedMembershipKey(MulticastChannel channel, MembershipKey key) {
this.channel = channel;
this.key = key;
}
@Override
public boolean isValid() {
return key.isValid();
}
@Override
public void drop() {
key.drop();
}
@Override
public MulticastChannel channel() {
return channel;
}
@Override
public InetAddress group() {
return key.group();
}
@Override
public NetworkInterface networkInterface() {
return key.networkInterface();
}
@Override
public InetAddress sourceAddress() {
return key.sourceAddress();
}
@Override
public MembershipKey block(InetAddress toBlock) throws IOException {
key.block(toBlock);
return this;
}
@Override
public MembershipKey unblock(InetAddress toUnblock) {
key.unblock(toUnblock);
return this;
}
@Override
public String toString() {
return key.toString();
}
}
@Override
public MembershipKey join(InetAddress group,
NetworkInterface interf)
throws IOException
{
MembershipKey key = ((MulticastChannel)dc).join(group, interf);
return new WrappedMembershipKey(this, key);
}
@Override
public MembershipKey join(InetAddress group,
NetworkInterface interf,
InetAddress source)
throws IOException
{
MembershipKey key = ((MulticastChannel)dc).join(group, interf, source);
return new WrappedMembershipKey(this, key);
}
private <A> Future<Integer> implSend(ByteBuffer src,
SocketAddress target,
A attachment,
CompletionHandler<Integer,? super A> handler)
{
int n = 0;
Throwable exc = null;
try {
n = dc.send(src, target);
} catch (IOException ioe) {
exc = ioe;
}
if (handler == null)
return CompletedFuture.withResult(n, exc);
Invoker.invoke(this, handler, attachment, n, exc);
return null;
}
@Override
public Future<Integer> send(ByteBuffer src, SocketAddress target) {
return implSend(src, target, null, null);
}
@Override
public <A> void send(ByteBuffer src,
SocketAddress target,
A attachment,
CompletionHandler<Integer,? super A> handler)
{
if (handler == null)
throw new NullPointerException("'handler' is null");
implSend(src, target, attachment, handler);
}
private <A> Future<Integer> implWrite(ByteBuffer src,
A attachment,
CompletionHandler<Integer,? super A> handler)
{
int n = 0;
Throwable exc = null;
try {
n = dc.write(src);
} catch (IOException ioe) {
exc = ioe;
}
if (handler == null)
return CompletedFuture.withResult(n, exc);
Invoker.invoke(this, handler, attachment, n, exc);
return null;
}
@Override
public Future<Integer> write(ByteBuffer src) {
return implWrite(src, null, null);
}
@Override
public <A> void write(ByteBuffer src,
A attachment,
CompletionHandler<Integer,? super A> handler)
{
if (handler == null)
throw new NullPointerException("'handler' is null");
implWrite(src, attachment, handler);
}
/**
* Receive into the given buffer with privileges enabled and restricted by
* the given AccessControlContext (can be null).
*/
private SocketAddress doRestrictedReceive(final ByteBuffer dst,
AccessControlContext acc)
throws IOException
{
if (acc == null) {
return dc.receive(dst);
} else {
try {
return AccessController.doPrivileged(
new PrivilegedExceptionAction<SocketAddress>() {
public SocketAddress run() throws IOException {
return dc.receive(dst);
}}, acc);
} catch (PrivilegedActionException pae) {
Exception cause = pae.getException();
if (cause instanceof SecurityException)
throw (SecurityException)cause;
throw (IOException)cause;
}
}
}
private <A> Future<SocketAddress> implReceive(final ByteBuffer dst,
final long timeout,
final TimeUnit unit,
A attachment,
final CompletionHandler<SocketAddress,? super A> handler)
{
if (dst.isReadOnly())
throw new IllegalArgumentException("Read-only buffer");
if (timeout < 0L)
throw new IllegalArgumentException("Negative timeout");
if (unit == null)
throw new NullPointerException();
// complete immediately if channel closed
if (!isOpen()) {
Throwable exc = new ClosedChannelException();
if (handler == null)
return CompletedFuture.withFailure(exc);
Invoker.invoke(this, handler, attachment, null, exc);
return null;
}
final AccessControlContext acc = (System.getSecurityManager() == null) ?
null : AccessController.getContext();
final PendingFuture<SocketAddress,A> result =
new PendingFuture<SocketAddress,A>(this, handler, attachment);
Runnable task = new Runnable() {
public void run() {
try {
SocketAddress remote = null;
long to;
if (timeout == 0L) {
beginNoTimeoutRead();
try {
remote = doRestrictedReceive(dst, acc);
} finally {
endNoTimeoutRead();
}
to = 0L;
} else {
to = prepareForTimedRead(result, unit.toMillis(timeout));
if (to <= 0L)
throw new InterruptedByTimeoutException();
remote = doRestrictedReceive(dst, acc);
}
if (remote == null) {
Selector sel = getSelector();
SelectionKey sk = null;
try {
sk = dc.register(sel, SelectionKey.OP_READ);
for (;;) {
if (!dc.isOpen())
throw new AsynchronousCloseException();
if (result.isCancelled())
break;
long st = System.currentTimeMillis();
int ns = sel.select(to);
if (ns > 0) {
remote = doRestrictedReceive(dst, acc);
if (remote != null)
break;
}
sel.selectedKeys().remove(sk);
if (timeout != 0L) {
to -= System.currentTimeMillis() - st;
if (to <= 0)
throw new InterruptedByTimeoutException();
}
}
} finally {
if (sk != null)
sk.cancel();
releaseSelector(sel);
}
}
result.setResult(remote);
} catch (Throwable x) {
if (x instanceof ClosedChannelException)
x = new AsynchronousCloseException();
result.setFailure(x);
}
Invoker.invokeUnchecked(result);
}
};
try {
group.executeOnPooledThread(task);
} catch (RejectedExecutionException ree) {
throw new ShutdownChannelGroupException();
}
return result;
}
@Override
public Future<SocketAddress> receive(ByteBuffer dst) {
return implReceive(dst, 0L, TimeUnit.MILLISECONDS, null, null);
}
@Override
public <A> void receive(ByteBuffer dst,
long timeout,
TimeUnit unit,
A attachment,
CompletionHandler<SocketAddress,? super A> handler)
{
if (handler == null)
throw new NullPointerException("'handler' is null");
implReceive(dst, timeout, unit, attachment, handler);
}
private <A> Future<Integer> implRead(final ByteBuffer dst,
final long timeout,
final TimeUnit unit,
A attachment,
final CompletionHandler<Integer,? super A> handler)
{
if (dst.isReadOnly())
throw new IllegalArgumentException("Read-only buffer");
if (timeout < 0L)
throw new IllegalArgumentException("Negative timeout");
if (unit == null)
throw new NullPointerException();
// complete immediately if channel closed
if (!isOpen()) {
Throwable exc = new ClosedChannelException();
if (handler == null)
return CompletedFuture.withFailure(exc);
Invoker.invoke(this, handler, attachment, null, exc);
return null;
}
// another thread may disconnect before read is initiated
if (!dc.isConnected())
throw new NotYetConnectedException();
final PendingFuture<Integer,A> result =
new PendingFuture<Integer,A>(this, handler, attachment);
Runnable task = new Runnable() {
public void run() {
try {
int n = 0;
long to;
if (timeout == 0L) {
beginNoTimeoutRead();
try {
n = dc.read(dst);
} finally {
endNoTimeoutRead();
}
to = 0L;
} else {
to = prepareForTimedRead(result, unit.toMillis(timeout));
if (to <= 0L)
throw new InterruptedByTimeoutException();
n = dc.read(dst);
}
if (n == 0) {
Selector sel = getSelector();
SelectionKey sk = null;
try {
sk = dc.register(sel, SelectionKey.OP_READ);
for (;;) {
if (!dc.isOpen())
throw new AsynchronousCloseException();
if (result.isCancelled())
break;
long st = System.currentTimeMillis();
int ns = sel.select(to);
if (ns > 0) {
if ((n = dc.read(dst)) != 0)
break;
}
sel.selectedKeys().remove(sk);
if (timeout != 0L) {
to -= System.currentTimeMillis() - st;
if (to <= 0)
throw new InterruptedByTimeoutException();
}
}
} finally {
if (sk != null)
sk.cancel();
releaseSelector(sel);
}
}
result.setResult(n);
} catch (Throwable x) {
if (x instanceof ClosedChannelException)
x = new AsynchronousCloseException();
result.setFailure(x);
}
Invoker.invokeUnchecked(result);
}
};
try {
group.executeOnPooledThread(task);
} catch (RejectedExecutionException ree) {
throw new ShutdownChannelGroupException();
}
return result;
}
@Override
public Future<Integer> read(ByteBuffer dst) {
return implRead(dst, 0L, TimeUnit.MILLISECONDS, null, null);
}
@Override
public <A> void read(ByteBuffer dst,
long timeout,
TimeUnit unit,
A attachment,
CompletionHandler<Integer,? super A> handler)
{
if (handler == null)
throw new NullPointerException("'handler' is null");
implRead(dst, timeout, unit, attachment, handler);
}
@Override
public AsynchronousDatagramChannel bind(SocketAddress local)
throws IOException
{
dc.bind(local);
return this;
}
@Override
public SocketAddress getLocalAddress() throws IOException {
return dc.getLocalAddress();
}
@Override
public <T> AsynchronousDatagramChannel setOption(SocketOption<T> name, T value)
throws IOException
{
dc.setOption(name, value);
return this;
}
@Override
public <T> T getOption(SocketOption<T> name) throws IOException {
return dc.getOption(name);
}
@Override
public Set<SocketOption<?>> supportedOptions() {
return dc.supportedOptions();
}
@Override
public SocketAddress getRemoteAddress() throws IOException {
return dc.getRemoteAddress();
}
}

View File

@ -28,6 +28,7 @@ package sun.nio.ch;
import java.lang.ref.SoftReference;
import java.lang.reflect.*;
import java.io.IOException;
import java.io.FileDescriptor;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.*;
@ -364,6 +365,7 @@ class Util {
Constructor ctor = cl.getDeclaredConstructor(
new Class[] { int.class,
long.class,
FileDescriptor.class,
Runnable.class });
ctor.setAccessible(true);
directByteBufferConstructor = ctor;
@ -381,6 +383,7 @@ class Util {
}
static MappedByteBuffer newMappedByteBuffer(int size, long addr,
FileDescriptor fd,
Runnable unmapper)
{
MappedByteBuffer dbb;
@ -390,6 +393,7 @@ class Util {
dbb = (MappedByteBuffer)directByteBufferConstructor.newInstance(
new Object[] { new Integer(size),
new Long(addr),
fd,
unmapper });
} catch (InstantiationException e) {
throw new InternalError();
@ -411,6 +415,7 @@ class Util {
Constructor ctor = cl.getDeclaredConstructor(
new Class[] { int.class,
long.class,
FileDescriptor.class,
Runnable.class });
ctor.setAccessible(true);
directByteBufferRConstructor = ctor;
@ -428,6 +433,7 @@ class Util {
}
static MappedByteBuffer newMappedByteBufferR(int size, long addr,
FileDescriptor fd,
Runnable unmapper)
{
MappedByteBuffer dbb;
@ -437,6 +443,7 @@ class Util {
dbb = (MappedByteBuffer)directByteBufferRConstructor.newInstance(
new Object[] { new Integer(size),
new Long(addr),
fd,
unmapper });
} catch (InstantiationException e) {
throw new InternalError();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -38,7 +38,8 @@ import javax.crypto.SecretKey;
*
* @since 1.6
* @author Andreas Sterbenz
* @deprecated Sun JDK internal use only --- WILL BE REMOVED in Dolphin (JDK 7)
* @deprecated Sun JDK internal use only --- WILL BE REMOVED in a future
* release.
*/
@Deprecated
public interface TlsMasterSecret extends SecretKey {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -39,7 +39,8 @@ import javax.crypto.SecretKey;
*
* @since 1.6
* @author Andreas Sterbenz
* @deprecated Sun JDK internal use only --- WILL BE REMOVED in Dolphin (JDK 7)
* @deprecated Sun JDK internal use only --- WILL BE REMOVED in a future
* release.
*/
@Deprecated
public class TlsKeyMaterialParameterSpec implements AlgorithmParameterSpec {
@ -50,6 +51,9 @@ public class TlsKeyMaterialParameterSpec implements AlgorithmParameterSpec {
private final String cipherAlgorithm;
private final int cipherKeyLength, ivLength, macKeyLength;
private final int expandedCipherKeyLength; // == 0 for domestic ciphersuites
private final String prfHashAlg;
private final int prfHashLength;
private final int prfBlockSize;
/**
* Constructs a new TlsKeyMaterialParameterSpec.
@ -71,6 +75,12 @@ public class TlsKeyMaterialParameterSpec implements AlgorithmParameterSpec {
* @param ivLength the length in bytes of the initialization vector
* to be generated, or 0 if no initialization vector is required
* @param macKeyLength the length in bytes of the MAC key to be generated
* @param prfHashAlg the name of the TLS PRF hash algorithm to use.
* Used only for TLS 1.2+. TLS1.1 and earlier use a fixed PRF.
* @param prfHashLength the output length of the TLS PRF hash algorithm.
* Used only for TLS 1.2+.
* @param prfBlockSize the input block size of the TLS PRF hash algorithm.
* Used only for TLS 1.2+.
*
* @throws NullPointerException if masterSecret, clientRandom,
* serverRandom, or cipherAlgorithm are null
@ -82,7 +92,8 @@ public class TlsKeyMaterialParameterSpec implements AlgorithmParameterSpec {
public TlsKeyMaterialParameterSpec(SecretKey masterSecret,
int majorVersion, int minorVersion, byte[] clientRandom,
byte[] serverRandom, String cipherAlgorithm, int cipherKeyLength,
int expandedCipherKeyLength, int ivLength, int macKeyLength) {
int expandedCipherKeyLength, int ivLength, int macKeyLength,
String prfHashAlg, int prfHashLength, int prfBlockSize) {
if (masterSecret.getAlgorithm().equals("TlsMasterSecret") == false) {
throw new IllegalArgumentException("Not a TLS master secret");
}
@ -90,8 +101,10 @@ public class TlsKeyMaterialParameterSpec implements AlgorithmParameterSpec {
throw new NullPointerException();
}
this.masterSecret = masterSecret;
this.majorVersion = TlsMasterSecretParameterSpec.checkVersion(majorVersion);
this.minorVersion = TlsMasterSecretParameterSpec.checkVersion(minorVersion);
this.majorVersion =
TlsMasterSecretParameterSpec.checkVersion(majorVersion);
this.minorVersion =
TlsMasterSecretParameterSpec.checkVersion(minorVersion);
this.clientRandom = clientRandom.clone();
this.serverRandom = serverRandom.clone();
this.cipherAlgorithm = cipherAlgorithm;
@ -99,6 +112,9 @@ public class TlsKeyMaterialParameterSpec implements AlgorithmParameterSpec {
this.expandedCipherKeyLength = checkSign(expandedCipherKeyLength);
this.ivLength = checkSign(ivLength);
this.macKeyLength = checkSign(macKeyLength);
this.prfHashAlg = prfHashAlg;
this.prfHashLength = prfHashLength;
this.prfBlockSize = prfBlockSize;
}
private static int checkSign(int k) {
@ -172,20 +188,36 @@ public class TlsKeyMaterialParameterSpec implements AlgorithmParameterSpec {
}
/**
* Returns the length in bytes of the expanded encryption key to be generated.
* Returns the length in bytes of the expanded encryption key to be
* generated. Returns zero if the expanded encryption key is not
* supposed to be generated.
*
* @return the length in bytes of the expanded encryption key to be generated.
* @return the length in bytes of the expanded encryption key to be
* generated.
*/
public int getExpandedCipherKeyLength() {
// TLS v1.1 disables the exportable weak cipher suites.
if (majorVersion >= 0x03 && minorVersion >= 0x02) {
return 0;
}
return expandedCipherKeyLength;
}
/**
* Returns the length in bytes of the initialization vector to be generated.
* Returns the length in bytes of the initialization vector to be
* generated. Returns zero if the initialization vector is not
* supposed to be generated.
*
* @return the length in bytes of the initialization vector to be generated.
* @return the length in bytes of the initialization vector to be
* generated.
*/
public int getIvLength() {
// TLS v1.1 or later uses an explicit IV to protect against
// the CBC attacks.
if (majorVersion >= 0x03 && minorVersion >= 0x02) {
return 0;
}
return ivLength;
}
@ -198,4 +230,30 @@ public class TlsKeyMaterialParameterSpec implements AlgorithmParameterSpec {
return macKeyLength;
}
/**
* Obtains the PRF hash algorithm to use in the PRF calculation.
*
* @return the hash algorithm.
*/
public String getPRFHashAlg() {
return prfHashAlg;
}
/**
* Obtains the length of the PRF hash algorithm.
*
* @return the hash algorithm length.
*/
public int getPRFHashLength() {
return prfHashLength;
}
/**
* Obtains the block size of the PRF hash algorithm.
*
* @return the hash algorithm block size
*/
public int getPRFBlockSize() {
return prfBlockSize;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -39,7 +39,8 @@ import javax.crypto.spec.IvParameterSpec;
*
* @since 1.6
* @author Andreas Sterbenz
* @deprecated Sun JDK internal use only --- WILL BE REMOVED in Dolphin (JDK 7)
* @deprecated Sun JDK internal use only --- WILL BE REMOVED in a future
* release.
*/
@Deprecated
public class TlsKeyMaterialSpec implements KeySpec, SecretKey {
@ -80,7 +81,8 @@ public class TlsKeyMaterialSpec implements KeySpec, SecretKey {
*/
public TlsKeyMaterialSpec(SecretKey clientMacKey, SecretKey serverMacKey,
SecretKey clientCipherKey, SecretKey serverCipherKey) {
this(clientMacKey, serverMacKey, clientCipherKey, null, serverCipherKey, null);
this(clientMacKey, serverMacKey, clientCipherKey, null,
serverCipherKey, null);
}
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -39,7 +39,8 @@ import javax.crypto.SecretKey;
*
* @since 1.6
* @author Andreas Sterbenz
* @deprecated Sun JDK internal use only --- WILL BE REMOVED in Dolphin (JDK 7)
* @deprecated Sun JDK internal use only --- WILL BE REMOVED in a future
* release.
*/
@Deprecated
public class TlsMasterSecretParameterSpec implements AlgorithmParameterSpec {
@ -47,6 +48,9 @@ public class TlsMasterSecretParameterSpec implements AlgorithmParameterSpec {
private final SecretKey premasterSecret;
private final int majorVersion, minorVersion;
private final byte[] clientRandom, serverRandom;
private final String prfHashAlg;
private final int prfHashLength;
private final int prfBlockSize;
/**
* Constructs a new TlsMasterSecretParameterSpec.
@ -60,6 +64,12 @@ public class TlsMasterSecretParameterSpec implements AlgorithmParameterSpec {
* @param minorVersion the minor number of the protocol version
* @param clientRandom the client's random value
* @param serverRandom the server's random value
* @param prfHashAlg the name of the TLS PRF hash algorithm to use.
* Used only for TLS 1.2+. TLS1.1 and earlier use a fixed PRF.
* @param prfHashLength the output length of the TLS PRF hash algorithm.
* Used only for TLS 1.2+.
* @param prfBlockSize the input block size of the TLS PRF hash algorithm.
* Used only for TLS 1.2+.
*
* @throws NullPointerException if premasterSecret, clientRandom,
* or serverRandom are null
@ -67,7 +77,9 @@ public class TlsMasterSecretParameterSpec implements AlgorithmParameterSpec {
* negative or larger than 255
*/
public TlsMasterSecretParameterSpec(SecretKey premasterSecret,
int majorVersion, int minorVersion, byte[] clientRandom, byte[] serverRandom) {
int majorVersion, int minorVersion,
byte[] clientRandom, byte[] serverRandom,
String prfHashAlg, int prfHashLength, int prfBlockSize) {
if (premasterSecret == null) {
throw new NullPointerException("premasterSecret must not be null");
}
@ -76,11 +88,15 @@ public class TlsMasterSecretParameterSpec implements AlgorithmParameterSpec {
this.minorVersion = checkVersion(minorVersion);
this.clientRandom = clientRandom.clone();
this.serverRandom = serverRandom.clone();
this.prfHashAlg = prfHashAlg;
this.prfHashLength = prfHashLength;
this.prfBlockSize = prfBlockSize;
}
static int checkVersion(int version) {
if ((version < 0) || (version > 255)) {
throw new IllegalArgumentException("Version must be between 0 and 255");
throw new IllegalArgumentException(
"Version must be between 0 and 255");
}
return version;
}
@ -130,4 +146,30 @@ public class TlsMasterSecretParameterSpec implements AlgorithmParameterSpec {
return serverRandom.clone();
}
/**
* Obtains the PRF hash algorithm to use in the PRF calculation.
*
* @return the hash algorithm.
*/
public String getPRFHashAlg() {
return prfHashAlg;
}
/**
* Obtains the length of the PRF hash algorithm.
*
* @return the hash algorithm length.
*/
public int getPRFHashLength() {
return prfHashLength;
}
/**
* Obtains the block size of the PRF hash algorithm.
*
* @return the hash algorithm block size.
*/
public int getPRFBlockSize() {
return prfBlockSize;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -38,7 +38,8 @@ import javax.crypto.SecretKey;
*
* @since 1.6
* @author Andreas Sterbenz
* @deprecated Sun JDK internal use only --- WILL BE REMOVED in Dolphin (JDK 7)
* @deprecated Sun JDK internal use only --- WILL BE REMOVED in a future
* release.
*/
@Deprecated
public class TlsPrfParameterSpec implements AlgorithmParameterSpec {
@ -47,6 +48,9 @@ public class TlsPrfParameterSpec implements AlgorithmParameterSpec {
private final String label;
private final byte[] seed;
private final int outputLength;
private final String prfHashAlg;
private final int prfHashLength;
private final int prfBlockSize;
/**
* Constructs a new TlsPrfParameterSpec.
@ -55,11 +59,19 @@ public class TlsPrfParameterSpec implements AlgorithmParameterSpec {
* @param label the label to use in the calculation
* @param seed the random seed to use in the calculation
* @param outputLength the length in bytes of the output key to be produced
* @param prfHashAlg the name of the TLS PRF hash algorithm to use.
* Used only for TLS 1.2+. TLS1.1 and earlier use a fixed PRF.
* @param prfHashLength the output length of the TLS PRF hash algorithm.
* Used only for TLS 1.2+.
* @param prfBlockSize the input block size of the TLS PRF hash algorithm.
* Used only for TLS 1.2+.
*
* @throws NullPointerException if label or seed is null
* @throws IllegalArgumentException if outputLength is negative
*/
public TlsPrfParameterSpec(SecretKey secret, String label, byte[] seed, int outputLength) {
public TlsPrfParameterSpec(SecretKey secret, String label,
byte[] seed, int outputLength,
String prfHashAlg, int prfHashLength, int prfBlockSize) {
if ((label == null) || (seed == null)) {
throw new NullPointerException("label and seed must not be null");
}
@ -70,6 +82,9 @@ public class TlsPrfParameterSpec implements AlgorithmParameterSpec {
this.label = label;
this.seed = seed.clone();
this.outputLength = outputLength;
this.prfHashAlg = prfHashAlg;
this.prfHashLength = prfHashLength;
this.prfBlockSize = prfBlockSize;
}
/**
@ -110,4 +125,33 @@ public class TlsPrfParameterSpec implements AlgorithmParameterSpec {
return outputLength;
}
/**
* Obtains the PRF hash algorithm to use in the PRF calculation.
*
* @return the hash algorithm, or null if no algorithm was specified.
*/
public String getPRFHashAlg() {
return prfHashAlg;
}
/**
* Obtains the length of PRF hash algorithm.
*
* It would have been preferred to use MessageDigest.getDigestLength(),
* but the API does not require implementations to support the method.
*
* @return the hash algorithm length.
*/
public int getPRFHashLength() {
return prfHashLength;
}
/**
* Obtains the length of PRF hash algorithm.
*
* @return the hash algorithm length.
*/
public int getPRFBlockSize() {
return prfBlockSize;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -36,10 +36,12 @@ import java.security.spec.AlgorithmParameterSpec;
*
* @since 1.6
* @author Andreas Sterbenz
* @deprecated Sun JDK internal use only --- WILL BE REMOVED in Dolphin (JDK 7)
* @deprecated Sun JDK internal use only --- WILL BE REMOVED in a future
* release.
*/
@Deprecated
public class TlsRsaPremasterSecretParameterSpec implements AlgorithmParameterSpec {
public class TlsRsaPremasterSecretParameterSpec
implements AlgorithmParameterSpec {
private final int majorVersion;
private final int minorVersion;
@ -58,10 +60,12 @@ public class TlsRsaPremasterSecretParameterSpec implements AlgorithmParameterSpe
* @throws IllegalArgumentException if minorVersion or majorVersion are
* negative or larger than 255
*/
public TlsRsaPremasterSecretParameterSpec(int majorVersion, int minorVersion) {
this.majorVersion = TlsMasterSecretParameterSpec.checkVersion(majorVersion);
this.minorVersion = TlsMasterSecretParameterSpec.checkVersion(minorVersion);
}
public TlsRsaPremasterSecretParameterSpec(int majorVersion,
int minorVersion) {
this.majorVersion =
TlsMasterSecretParameterSpec.checkVersion(majorVersion);
this.minorVersion =
TlsMasterSecretParameterSpec.checkVersion(minorVersion); }
/**
* Returns the major version.

View File

@ -34,7 +34,6 @@ package sun.security.krb5.internal.ktab;
import sun.security.krb5.*;
import sun.security.krb5.internal.*;
import sun.security.krb5.internal.crypto.*;
import java.util.Vector;
import java.util.ArrayList;
import java.util.Arrays;
import java.io.IOException;
@ -42,7 +41,10 @@ import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.File;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.Vector;
/**
* This class represents key table. The key table functions deal with storing
@ -239,23 +241,22 @@ public class KeyTab implements KeyTabConstants {
EncryptionKey key;
int size = entries.size();
ArrayList<EncryptionKey> keys = new ArrayList<EncryptionKey> (size);
if (entries != null) {
for (int i = size-1; i >= 0; i--) {
entry = entries.elementAt(i);
if (entry.service.match(service)) {
if (EType.isSupported(entry.keyType)) {
key = new EncryptionKey(entry.keyblock,
entry.keyType,
new Integer(entry.keyVersion));
keys.add(key);
if (DEBUG) {
System.out.println("Added key: " + entry.keyType +
"version: " + entry.keyVersion);
}
} else if (DEBUG) {
System.out.println("Found unsupported keytype (" +
entry.keyType + ") for " + service);
for (int i = size-1; i >= 0; i--) {
entry = entries.elementAt(i);
if (entry.service.match(service)) {
if (EType.isSupported(entry.keyType)) {
key = new EncryptionKey(entry.keyblock,
entry.keyType,
new Integer(entry.keyVersion));
keys.add(key);
if (DEBUG) {
System.out.println("Added key: " + entry.keyType +
"version: " + entry.keyVersion);
}
} else if (DEBUG) {
System.out.println("Found unsupported keytype (" +
entry.keyType + ") for " + service);
}
}
}
@ -313,16 +314,14 @@ public class KeyTab implements KeyTabConstants {
*/
public boolean findServiceEntry(PrincipalName service) {
KeyTabEntry entry;
if (entries != null) {
for (int i = 0; i < entries.size(); i++) {
entry = entries.elementAt(i);
if (entry.service.match(service)) {
if (EType.isSupported(entry.keyType)) {
return true;
} else if (DEBUG) {
System.out.println("Found unsupported keytype (" +
entry.keyType + ") for " + service);
}
for (int i = 0; i < entries.size(); i++) {
entry = entries.elementAt(i);
if (entry.service.match(service)) {
if (EType.isSupported(entry.keyType)) {
return true;
} else if (DEBUG) {
System.out.println("Found unsupported keytype (" +
entry.keyType + ") for " + service);
}
}
}
@ -337,78 +336,45 @@ public class KeyTab implements KeyTabConstants {
* Adds a new entry in the key table.
* @param service the service which will have a new entry in the key table.
* @param psswd the password which generates the key.
* @param kvno the kvno to use, -1 means automatic increasing
* @param append false if entries with old kvno would be removed.
* Note: if kvno is not -1, entries with the same kvno are always removed
*/
public void addEntry(PrincipalName service, char[] psswd)
throws KrbException {
public void addEntry(PrincipalName service, char[] psswd,
int kvno, boolean append) throws KrbException {
EncryptionKey[] encKeys = EncryptionKey.acquireSecretKeys(
psswd, service.getSalt());
for (int i = 0; encKeys != null && i < encKeys.length; i++) {
int keyType = encKeys[i].getEType();
byte[] keyValue = encKeys[i].getBytes();
int result = retrieveEntry(service, keyType);
int kvno = 1;
if (result != -1) {
KeyTabEntry oldEntry = entries.elementAt(result);
kvno = oldEntry.keyVersion;
entries.removeElementAt(result);
kvno += 1;
} else
kvno = 1;
// There should be only one maximum KVNO value for all etypes, so that
// all added keys can have the same KVNO.
KeyTabEntry newEntry = new KeyTabEntry(service,
service.getRealm(),
new KerberosTime(System.currentTimeMillis()),
kvno, keyType, keyValue);
if (entries == null)
entries = new Vector<KeyTabEntry> ();
entries.addElement(newEntry);
}
}
/**
* Only used by KDC test. This method can specify kvno and does not
* remove any old keys.
*/
public void addEntry(PrincipalName service, char[] psswd, int kvno)
throws KrbException {
EncryptionKey[] encKeys = EncryptionKey.acquireSecretKeys(
psswd, service.getSalt());
for (int i = 0; encKeys != null && i < encKeys.length; i++) {
int keyType = encKeys[i].getEType();
byte[] keyValue = encKeys[i].getBytes();
KeyTabEntry newEntry = new KeyTabEntry(service,
service.getRealm(),
new KerberosTime(System.currentTimeMillis()),
kvno, keyType, keyValue);
if (entries == null)
entries = new Vector<KeyTabEntry> ();
entries.addElement(newEntry);
}
}
/**
* Retrieves the key table entry with the specified service name.
* @param service the service which may have an entry in the key table.
* @param keyType the etype to match, returns the 1st one if -1 provided
* @return -1 if the entry is not found, else return the entry index
* in the list.
*/
private int retrieveEntry(PrincipalName service, int keyType) {
KeyTabEntry e;
if (entries != null) {
for (int i = 0; i < entries.size(); i++) {
e = entries.elementAt(i);
if (service.match(e.getService()) &&
(keyType == -1 || e.keyType == keyType)) {
return i;
int maxKvno = 0; // only useful when kvno == -1
for (int i = entries.size()-1; i >= 0; i--) {
KeyTabEntry e = entries.get(i);
if (e.service.match(service)) {
if (e.keyVersion > maxKvno) {
maxKvno = e.keyVersion;
}
if (!append || e.keyVersion == kvno) {
entries.removeElementAt(i);
}
}
}
return -1;
if (kvno == -1) {
kvno = maxKvno + 1;
}
for (int i = 0; encKeys != null && i < encKeys.length; i++) {
int keyType = encKeys[i].getEType();
byte[] keyValue = encKeys[i].getBytes();
KeyTabEntry newEntry = new KeyTabEntry(service,
service.getRealm(),
new KerberosTime(System.currentTimeMillis()),
kvno, keyType, keyValue);
entries.addElement(newEntry);
}
}
/**
@ -416,15 +382,11 @@ public class KeyTab implements KeyTabConstants {
* @return array of <code>KeyTabEntry</code>.
*/
public KeyTabEntry[] getEntries() {
if (entries != null) {
KeyTabEntry[] kentries = new KeyTabEntry[entries.size()];
for (int i = 0; i < kentries.length; i++) {
kentries[i] = entries.elementAt(i);
}
return kentries;
} else {
return null;
KeyTabEntry[] kentries = new KeyTabEntry[entries.size()];
for (int i = 0; i < kentries.length; i++) {
kentries[i] = entries.elementAt(i);
}
return kentries;
}
/**
@ -464,29 +426,55 @@ public class KeyTab implements KeyTabConstants {
}
/**
* Removes an entry from the key table.
* Removes entries from the key table.
* @param service the service <code>PrincipalName</code>.
* @param etype the etype to match, first one if -1 provided
* @return 1 if removed successfully, 0 otherwise
* @param etype the etype to match, remove all if -1
* @param kvno what kvno to remove, -1 for all, -2 for old
* @return the number of entries deleted
*/
public int deleteEntry(PrincipalName service, int etype) {
int result = retrieveEntry(service, etype);
if (result != -1) {
entries.removeElementAt(result);
return 1;
}
return 0;
}
/**
* Removes an entry from the key table.
* @param service the service <code>PrincipalName</code>.
* @return number of entries removed
*/
public int deleteEntry(PrincipalName service) {
public int deleteEntries(PrincipalName service, int etype, int kvno) {
int count = 0;
while (deleteEntry(service, -1) > 0) {
count++;
// Remember the highest KVNO for each etype. Used for kvno == -2
Map<Integer,Integer> highest = new HashMap<>();
for (int i = entries.size()-1; i >= 0; i--) {
KeyTabEntry e = entries.get(i);
if (service.match(e.getService())) {
if (etype == -1 || e.keyType == etype) {
if (kvno == -2) {
// Two rounds for kvno == -2. In the first round (here),
// only find out highest KVNO for each etype
if (highest.containsKey(e.keyType)) {
int n = highest.get(e.keyType);
if (e.keyVersion > n) {
highest.put(e.keyType, e.keyVersion);
}
} else {
highest.put(e.keyType, e.keyVersion);
}
} else if (kvno == -1 || e.keyVersion == kvno) {
entries.removeElementAt(i);
count++;
}
}
}
}
// Second round for kvno == -2, remove old entries
if (kvno == -2) {
for (int i = entries.size()-1; i >= 0; i--) {
KeyTabEntry e = entries.get(i);
if (service.match(e.getService())) {
if (etype == -1 || e.keyType == etype) {
int n = highest.get(e.keyType);
if (e.keyVersion != n) {
entries.removeElementAt(i);
count++;
}
}
}
}
}
return count;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -655,6 +655,25 @@ public final class SunPKCS11 extends AuthProvider {
d(SIG, "SHA512withRSA", P11Signature,
m(CKM_SHA512_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
/*
* TLS 1.2 uses a different hash algorithm than 1.0/1.1 for the
* PRF calculations. As of 2010, there is no PKCS11-level
* support for TLS 1.2 PRF calculations, and no known OS's have
* an internal variant we could use. Therefore for TLS 1.2, we
* are updating JSSE to request different provider algorithms
* (e.g. "SunTls12Prf"), and currently only SunJCE has these
* TLS 1.2 algorithms.
*
* If we reused the names such as "SunTlsPrf", the PKCS11
* providers would need be updated to fail correctly when
* presented with the wrong version number (via
* Provider.Service.supportsParameters()), and we would also
* need to add the appropriate supportsParamters() checks into
* KeyGenerators (not currently there).
*
* In the future, if PKCS11 support is added, we will restructure
* this.
*/
d(KG, "SunTlsRsaPremasterSecret",
"sun.security.pkcs11.P11TlsRsaPremasterSecretGenerator",
m(CKM_SSL3_PRE_MASTER_KEY_GEN, CKM_TLS_PRE_MASTER_KEY_GEN));
@ -887,7 +906,8 @@ public final class SunPKCS11 extends AuthProvider {
return (aliases == null) ? null : Arrays.asList(aliases);
}
public Object newInstance(Object param) throws NoSuchAlgorithmException {
public Object newInstance(Object param)
throws NoSuchAlgorithmException {
if (token.isValid() == false) {
throw new NoSuchAlgorithmException("Token has been removed");
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,95 +25,336 @@
package sun.security.provider.certpath;
import java.util.Set;
import java.security.AlgorithmConstraints;
import java.security.CryptoPrimitive;
import java.util.Collection;
import java.util.Locale;
import java.util.Collections;
import java.util.Set;
import java.util.EnumSet;
import java.util.HashSet;
import java.math.BigInteger;
import java.security.PublicKey;
import java.security.KeyFactory;
import java.security.AlgorithmParameters;
import java.security.NoSuchAlgorithmException;
import java.security.GeneralSecurityException;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.security.cert.X509CRL;
import java.security.cert.CertPathValidatorException;
import java.security.cert.X509Certificate;
import java.security.cert.PKIXCertPathChecker;
import java.security.cert.TrustAnchor;
import java.security.cert.CRLException;
import java.security.cert.CertificateException;
import java.security.cert.CertPathValidatorException;
import java.io.IOException;
import java.security.interfaces.*;
import java.security.spec.*;
import sun.security.util.DisabledAlgorithmConstraints;
import sun.security.x509.X509CertImpl;
import sun.security.x509.X509CRLImpl;
import sun.security.x509.AlgorithmId;
/**
* AlgorithmChecker is a <code>PKIXCertPathChecker</code> that checks that
* the signature algorithm of the specified certificate is not disabled.
* A <code>PKIXCertPathChecker</code> implementation to check whether a
* specified certificate contains the required algorithm constraints.
* <p>
* Certificate fields such as the subject public key, the signature
* algorithm, key usage, extended key usage, etc. need to conform to
* the specified algorithm constraints.
*
* @author Xuelei Fan
* @see PKIXCertPathChecker
* @see PKIXParameters
*/
final public class AlgorithmChecker extends PKIXCertPathChecker {
// the disabled algorithms
private static final String[] disabledAlgorithms = new String[] {"md2"};
private final AlgorithmConstraints constraints;
private final PublicKey trustedPubKey;
private PublicKey prevPubKey;
// singleton instance
static final AlgorithmChecker INSTANCE = new AlgorithmChecker();
private final static Set<CryptoPrimitive> SIGNATURE_PRIMITIVE_SET =
EnumSet.of(CryptoPrimitive.SIGNATURE);
private final static DisabledAlgorithmConstraints
certPathDefaultConstraints = new DisabledAlgorithmConstraints(
DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS);
/**
* Default Constructor
* Create a new <code>AlgorithmChecker</code> with the algorithm
* constraints specified in security property
* "jdk.certpath.disabledAlgorithms".
*
* @param anchor the trust anchor selected to validate the target
* certificate
*/
private AlgorithmChecker() {
// do nothing
public AlgorithmChecker(TrustAnchor anchor) {
this(anchor, certPathDefaultConstraints);
}
/**
* Return a AlgorithmChecker instance.
* Create a new <code>AlgorithmChecker</code> with the
* given {@code AlgorithmConstraints}.
* <p>
* Note that this constructor will be used to check a certification
* path where the trust anchor is unknown, or a certificate list which may
* contain the trust anchor. This constructor is used by SunJSSE.
*
* @param constraints the algorithm constraints (or null)
*/
static AlgorithmChecker getInstance() {
return INSTANCE;
public AlgorithmChecker(AlgorithmConstraints constraints) {
this.prevPubKey = null;
this.trustedPubKey = null;
this.constraints = constraints;
}
/**
* Initializes the internal state of the checker from parameters
* specified in the constructor.
* Create a new <code>AlgorithmChecker</code> with the
* given <code>TrustAnchor</code> and <code>AlgorithmConstraints</code>.
*
* @param anchor the trust anchor selected to validate the target
* certificate
* @param constraints the algorithm constraints (or null)
*
* @throws IllegalArgumentException if the <code>anchor</code> is null
*/
public AlgorithmChecker(TrustAnchor anchor,
AlgorithmConstraints constraints) {
if (anchor == null) {
throw new IllegalArgumentException(
"The trust anchor cannot be null");
}
if (anchor.getTrustedCert() != null) {
this.trustedPubKey = anchor.getTrustedCert().getPublicKey();
} else {
this.trustedPubKey = anchor.getCAPublicKey();
}
this.prevPubKey = trustedPubKey;
this.constraints = constraints;
}
@Override
public void init(boolean forward) throws CertPathValidatorException {
// do nothing
// Note that this class does not support forward mode.
if (!forward) {
if (trustedPubKey != null) {
prevPubKey = trustedPubKey;
} else {
prevPubKey = null;
}
} else {
throw new
CertPathValidatorException("forward checking not supported");
}
}
@Override
public boolean isForwardCheckingSupported() {
// Note that as this class does not support forward mode, the method
// will always returns false.
return false;
}
@Override
public Set<String> getSupportedExtensions() {
return null;
}
@Override
public void check(Certificate cert,
Collection<String> unresolvedCritExts)
throws CertPathValidatorException {
if (!(cert instanceof X509Certificate) || constraints == null) {
// ignore the check for non-x.509 certificate or null constraints
return;
}
X509CertImpl x509Cert = null;
try {
x509Cert = X509CertImpl.toImpl((X509Certificate)cert);
} catch (CertificateException ce) {
throw new CertPathValidatorException(ce);
}
PublicKey currPubKey = x509Cert.getPublicKey();
String currSigAlg = x509Cert.getSigAlgName();
AlgorithmId algorithmId = null;
try {
algorithmId = (AlgorithmId)x509Cert.get(X509CertImpl.SIG_ALG);
} catch (CertificateException ce) {
throw new CertPathValidatorException(ce);
}
AlgorithmParameters currSigAlgParams = algorithmId.getParameters();
// Check the current signature algorithm
if (!constraints.permits(
SIGNATURE_PRIMITIVE_SET,
currSigAlg, currSigAlgParams)) {
throw new CertPathValidatorException(
"Algorithm constraints check failed: " + currSigAlg);
}
// check the key usage and key size
boolean[] keyUsage = x509Cert.getKeyUsage();
if (keyUsage != null && keyUsage.length < 9) {
throw new CertPathValidatorException(
"incorrect KeyUsage extension");
}
if (keyUsage != null) {
Set<CryptoPrimitive> primitives =
EnumSet.noneOf(CryptoPrimitive.class);
if (keyUsage[0] || keyUsage[1] || keyUsage[5] || keyUsage[6]) {
// keyUsage[0]: KeyUsage.digitalSignature
// keyUsage[1]: KeyUsage.nonRepudiation
// keyUsage[5]: KeyUsage.keyCertSign
// keyUsage[6]: KeyUsage.cRLSign
primitives.add(CryptoPrimitive.SIGNATURE);
}
if (keyUsage[2]) { // KeyUsage.keyEncipherment
primitives.add(CryptoPrimitive.KEY_ENCAPSULATION);
}
if (keyUsage[3]) { // KeyUsage.dataEncipherment
primitives.add(CryptoPrimitive.PUBLIC_KEY_ENCRYPTION);
}
if (keyUsage[4]) { // KeyUsage.keyAgreement
primitives.add(CryptoPrimitive.KEY_AGREEMENT);
}
// KeyUsage.encipherOnly and KeyUsage.decipherOnly are
// undefined in the absence of the keyAgreement bit.
if (!primitives.isEmpty()) {
if (!constraints.permits(primitives, currPubKey)) {
throw new CertPathValidatorException(
"algorithm constraints check failed");
}
}
}
// Check with previous cert for signature algorithm and public key
if (prevPubKey != null) {
if (currSigAlg != null) {
if (!constraints.permits(
SIGNATURE_PRIMITIVE_SET,
currSigAlg, prevPubKey, currSigAlgParams)) {
throw new CertPathValidatorException(
"Algorithm constraints check failed: " + currSigAlg);
}
}
// Inherit key parameters from previous key
if (currPubKey instanceof DSAPublicKey &&
((DSAPublicKey)currPubKey).getParams() == null) {
// Inherit DSA parameters from previous key
if (!(prevPubKey instanceof DSAPublicKey)) {
throw new CertPathValidatorException("Input key is not " +
"of a appropriate type for inheriting parameters");
}
DSAParams params = ((DSAPublicKey)prevPubKey).getParams();
if (params == null) {
throw new CertPathValidatorException(
"Key parameters missing");
}
try {
BigInteger y = ((DSAPublicKey)currPubKey).getY();
KeyFactory kf = KeyFactory.getInstance("DSA");
DSAPublicKeySpec ks = new DSAPublicKeySpec(y,
params.getP(),
params.getQ(),
params.getG());
currPubKey = kf.generatePublic(ks);
} catch (GeneralSecurityException e) {
throw new CertPathValidatorException("Unable to generate " +
"key with inherited parameters: " + e.getMessage(), e);
}
}
}
// reset the previous public key
prevPubKey = currPubKey;
// check the extended key usage, ignore the check now
// List<String> extendedKeyUsages = x509Cert.getExtendedKeyUsage();
// DO NOT remove any unresolved critical extensions
}
/**
* Checks the signature algorithm of the specified certificate.
* Try to set the trust anchor of the checker.
* <p>
* If there is no trust anchor specified and the checker has not started,
* set the trust anchor.
*
* @param anchor the trust anchor selected to validate the target
* certificate
*/
public void check(Certificate cert, Collection<String> unresolvedCritExts)
throws CertPathValidatorException {
check(cert);
}
void trySetTrustAnchor(TrustAnchor anchor) {
// Don't bother if the check has started or trust anchor has already
// specified.
if (prevPubKey == null) {
if (anchor == null) {
throw new IllegalArgumentException(
"The trust anchor cannot be null");
}
public static void check(Certificate cert)
throws CertPathValidatorException {
X509Certificate xcert = (X509Certificate)cert;
check(xcert.getSigAlgName());
}
static void check(AlgorithmId aid) throws CertPathValidatorException {
check(aid.getName());
}
static void check(X509CRL crl) throws CertPathValidatorException {
check(crl.getSigAlgName());
}
private static void check(String algName)
throws CertPathValidatorException {
String lowerCaseAlgName = algName.toLowerCase(Locale.ENGLISH);
for (String disabled : disabledAlgorithms) {
// checking the signature algorithm name
if (lowerCaseAlgName.indexOf(disabled) != -1) {
throw new CertPathValidatorException(
"algorithm check failed: " + algName + " is disabled");
// Don't bother to change the trustedPubKey.
if (anchor.getTrustedCert() != null) {
prevPubKey = anchor.getTrustedCert().getPublicKey();
} else {
prevPubKey = anchor.getCAPublicKey();
}
}
}
/**
* Check the signature algorithm with the specified public key.
*
* @param key the public key to verify the CRL signature
* @param crl the target CRL
*/
static void check(PublicKey key, X509CRL crl)
throws CertPathValidatorException {
X509CRLImpl x509CRLImpl = null;
try {
x509CRLImpl = X509CRLImpl.toImpl(crl);
} catch (CRLException ce) {
throw new CertPathValidatorException(ce);
}
AlgorithmId algorithmId = x509CRLImpl.getSigAlgId();
check(key, algorithmId);
}
/**
* Check the signature algorithm with the specified public key.
*
* @param key the public key to verify the CRL signature
* @param crl the target CRL
*/
static void check(PublicKey key, AlgorithmId algorithmId)
throws CertPathValidatorException {
String sigAlgName = algorithmId.getName();
AlgorithmParameters sigAlgParams = algorithmId.getParameters();
if (!certPathDefaultConstraints.permits(
SIGNATURE_PRIMITIVE_SET, sigAlgName, key, sigAlgParams)) {
throw new CertPathValidatorException(
"algorithm check failed: " + sigAlgName + " is disabled");
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -289,16 +289,6 @@ class DistributionPointFetcher {
X500Name certIssuer = (X500Name) certImpl.getIssuerDN();
X500Name crlIssuer = (X500Name) crlImpl.getIssuerDN();
// check the crl signature algorithm
try {
AlgorithmChecker.check(crl);
} catch (CertPathValidatorException cpve) {
if (debug != null) {
debug.println("CRL signature algorithm check failed: " + cpve);
}
return false;
}
// if crlIssuer is set, verify that it matches the issuer of the
// CRL and the CRL contains an IDP extension with the indirectCRL
// boolean asserted. Otherwise, verify that the CRL issuer matches the
@ -637,6 +627,16 @@ class DistributionPointFetcher {
}
}
// check the crl signature algorithm
try {
AlgorithmChecker.check(prevKey, crl);
} catch (CertPathValidatorException cpve) {
if (debug != null) {
debug.println("CRL signature algorithm check failed: " + cpve);
}
return false;
}
// validate the signature on the CRL
try {
crl.verify(prevKey, provider);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -718,11 +718,6 @@ class ForwardBuilder extends Builder {
/* we don't perform any validation of the trusted cert */
if (!isTrustedCert) {
/*
* check that the signature algorithm is not disabled.
*/
AlgorithmChecker.check(cert);
/*
* Check CRITICAL private extensions for user checkers that
* support forward checking (forwardCheckers) and remove

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -327,6 +327,10 @@ class OCSPChecker extends PKIXCertPathChecker {
"(set using the OCSP security properties).");
}
// The algorithm constraints of the OCSP trusted responder certificate
// does not need to be checked in this code. The constraints will be
// checked when the responder's certificate is validated.
CertId certId = null;
OCSPResponse response = null;
try {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -32,6 +32,7 @@ import java.security.cert.CertificateException;
import java.security.cert.CertificateParsingException;
import java.security.cert.CertPathValidatorException;
import java.security.cert.CRLReason;
import java.security.cert.TrustAnchor;
import java.security.cert.X509Certificate;
import java.util.Collections;
import java.util.Date;
@ -371,6 +372,13 @@ public final class OCSPResponse {
"OCSP responses", cpe);
}
// Check algorithm constraints specified in security property
// "jdk.certpath.disabledAlgorithms".
AlgorithmChecker algChecker = new AlgorithmChecker(
new TrustAnchor(responderCert, null));
algChecker.init(false);
algChecker.check(cert, Collections.<String>emptySet());
// check the validity
try {
if (dateCheckedAgainst == null) {
@ -422,6 +430,10 @@ public final class OCSPResponse {
// Confirm that the signed response was generated using the public
// key from the trusted responder cert
if (responderCert != null) {
// Check algorithm constraints specified in security property
// "jdk.certpath.disabledAlgorithms".
AlgorithmChecker.check(responderCert.getPublicKey(), sigAlgId);
if (!verifyResponse(responseDataDer, responderCert,
sigAlgId, signature)) {
throw new CertPathValidatorException(

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -275,7 +275,7 @@ public class PKIXCertPathValidator extends CertPathValidatorSpi {
int certPathLen = certList.size();
basicChecker = new BasicChecker(anchor, testDate, sigProvider, false);
AlgorithmChecker algorithmChecker= AlgorithmChecker.getInstance();
AlgorithmChecker algorithmChecker = new AlgorithmChecker(anchor);
KeyChecker keyChecker = new KeyChecker(certPathLen,
pkixParam.getTargetCertConstraints());
ConstraintsChecker constraintsChecker =

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -347,9 +347,6 @@ class ReverseBuilder extends Builder {
return;
}
/* check that the signature algorithm is not disabled. */
AlgorithmChecker.check(cert);
/*
* check for looping - abort a loop if
* ((we encounter the same certificate twice) AND
@ -470,9 +467,16 @@ class ReverseBuilder extends Builder {
if (unresolvedCritExts == null) {
unresolvedCritExts = Collections.<String>emptySet();
}
/*
* Check that the signature algorithm is not disabled.
*/
currentState.algorithmChecker.check(cert, unresolvedCritExts);
for (PKIXCertPathChecker checker : currentState.userCheckers) {
checker.check(cert, unresolvedCritExts);
}
/*
* Look at the remaining extensions and remove any ones we have
* already checked. If there are any left, throw an exception!

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -96,6 +96,9 @@ class ReverseState implements State {
/* the checker used for revocation status */
public CrlRevocationChecker crlChecker;
/* the algorithm checker */
AlgorithmChecker algorithmChecker;
/* the trust anchor used to validate the path */
TrustAnchor trustAnchor;
@ -241,6 +244,14 @@ class ReverseState implements State {
updateState(anchor.getCAPublicKey(), caName);
}
// The user specified AlgorithmChecker may not be
// able to set the trust anchor until now.
for (PKIXCertPathChecker checker : userCheckers) {
if (checker instanceof AlgorithmChecker) {
((AlgorithmChecker)checker).trySetTrustAnchor(anchor);
}
}
init = false;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -302,6 +302,7 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
// init the crl checker
currentState.crlChecker =
new CrlRevocationChecker(null, buildParams, null, onlyEECert);
currentState.algorithmChecker = new AlgorithmChecker(anchor);
try {
depthFirstSearchReverse(null, currentState,
new ReverseBuilder(buildParams, targetSubjectDN), adjacencyList,
@ -475,29 +476,41 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
userCheckers.add(mustCheck, policyChecker);
mustCheck++;
// add the algorithm checker
userCheckers.add(mustCheck,
new AlgorithmChecker(builder.trustAnchor));
mustCheck++;
if (nextState.keyParamsNeeded()) {
PublicKey rootKey = cert.getPublicKey();
if (builder.trustAnchor.getTrustedCert() == null) {
rootKey = builder.trustAnchor.getCAPublicKey();
if (debug != null)
debug.println("SunCertPathBuilder.depthFirstSearchForward" +
" using buildParams public key: " +
rootKey.toString());
debug.println(
"SunCertPathBuilder.depthFirstSearchForward " +
"using buildParams public key: " +
rootKey.toString());
}
TrustAnchor anchor = new TrustAnchor
(cert.getSubjectX500Principal(), rootKey, null);
// add the basic checker
basicChecker = new BasicChecker(anchor,
builder.date,
buildParams.getSigProvider(),
true);
userCheckers.add(mustCheck, basicChecker);
mustCheck++;
// add the crl revocation checker
if (buildParams.isRevocationEnabled()) {
userCheckers.add(mustCheck, new CrlRevocationChecker
(anchor, buildParams, null, onlyEECert));
mustCheck++;
}
}
// Why we don't need BasicChecker and CrlRevocationChecker
// if nextState.keyParamsNeeded() is false?
for (int i=0; i<appendedCerts.size(); i++) {
X509Certificate currCert = appendedCerts.get(i);
@ -513,10 +526,18 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
for (int j=0; j<userCheckers.size(); j++) {
PKIXCertPathChecker currChecker = userCheckers.get(j);
if (j < mustCheck ||
!currChecker.isForwardCheckingSupported())
{
!currChecker.isForwardCheckingSupported()) {
if (i == 0) {
currChecker.init(false);
// The user specified
// AlgorithmChecker may not be
// able to set the trust anchor until now.
if (j >= mustCheck &&
currChecker instanceof AlgorithmChecker) {
((AlgorithmChecker)currChecker).
trySetTrustAnchor(builder.trustAnchor);
}
}
try {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -49,7 +49,7 @@ import sun.security.x509.AlgorithmId;
public abstract class RSASignature extends SignatureSpi {
// we sign an ASN.1 SEQUENCE of AlgorithmId and digest
// it has the form 30:xx:30:0c:[digestOID]:05:00:04:xx:[digest]
// it has the form 30:xx:30:xx:[digestOID]:05:00:04:xx:[digest]
// this means the encoded length is (8 + digestOID.length + digest.length)
private static final int baseLength = 8;
@ -104,7 +104,8 @@ public abstract class RSASignature extends SignatureSpi {
// initialize for signing. See JCA doc
protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
throws InvalidKeyException {
RSAPrivateKey rsaKey = (RSAPrivateKey)RSAKeyFactory.toRSAKey(privateKey);
RSAPrivateKey rsaKey =
(RSAPrivateKey)RSAKeyFactory.toRSAKey(privateKey);
this.privateKey = rsaKey;
this.publicKey = null;
initCommon(rsaKey, random);
@ -212,7 +213,8 @@ public abstract class RSASignature extends SignatureSpi {
DerOutputStream out = new DerOutputStream();
new AlgorithmId(oid).encode(out);
out.putOctetString(digest);
DerValue result = new DerValue(DerValue.tag_Sequence, out.toByteArray());
DerValue result =
new DerValue(DerValue.tag_Sequence, out.toByteArray());
return result.toByteArray();
}
@ -229,7 +231,8 @@ public abstract class RSASignature extends SignatureSpi {
}
AlgorithmId algId = AlgorithmId.parse(values[0]);
if (algId.getOID().equals(oid) == false) {
throw new IOException("ObjectIdentifier mismatch: " + algId.getOID());
throw new IOException("ObjectIdentifier mismatch: "
+ algId.getOID());
}
if (algId.getEncodedParams() != null) {
throw new IOException("Unexpected AlgorithmId parameters");

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -28,6 +28,7 @@ package sun.security.ssl;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Hashtable;
import java.security.*;
import javax.crypto.*;
@ -50,6 +51,37 @@ import sun.misc.HexDumpEncoder;
* Individual instances are obtained by calling the static method
* newCipherBox(), which should only be invoked by BulkCipher.newCipher().
*
* In RFC 2246, with bock ciphers in CBC mode, the Initialization
* Vector (IV) for the first record is generated with the other keys
* and secrets when the security parameters are set. The IV for
* subsequent records is the last ciphertext block from the previous
* record.
*
* In RFC 4346, the implicit Initialization Vector (IV) is replaced
* with an explicit IV to protect against CBC attacks. RFC 4346
* recommends two algorithms used to generated the per-record IV.
* The implementation uses the algorithm (2)(b), as described at
* section 6.2.3.2 of RFC 4346.
*
* The usage of IV in CBC block cipher can be illustrated in
* the following diagrams.
*
* (random)
* R P1 IV C1
* | | | |
* SIV---+ |-----+ |-... |----- |------
* | | | | | | | |
* +----+ | +----+ | +----+ | +----+ |
* | Ek | | + Ek + | | Dk | | | Dk | |
* +----+ | +----+ | +----+ | +----+ |
* | | | | | | | |
* |----| |----| SIV--+ |----| |-...
* | | | |
* IV C1 R P1
* (discard)
*
* CBC Encryption CBC Decryption
*
* NOTE that any ciphering involved in key exchange (e.g. with RSA) is
* handled separately.
*
@ -75,6 +107,21 @@ final class CipherBox {
*/
private int blockSize;
/**
* secure random
*/
private SecureRandom random;
/**
* Fixed masks of various block size, as the initial decryption IVs
* for TLS 1.1 or later.
*
* For performance, we do not use random IVs. As the initial decryption
* IVs will be discarded by TLS decryption processes, so the fixed masks
* do not hurt cryptographic strength.
*/
private static Hashtable<Integer, IvParameterSpec> masks;
/**
* NULL cipherbox. Identity operation, no encryption.
*/
@ -90,14 +137,37 @@ final class CipherBox {
* implementation could be found.
*/
private CipherBox(ProtocolVersion protocolVersion, BulkCipher bulkCipher,
SecretKey key, IvParameterSpec iv, boolean encrypt)
throws NoSuchAlgorithmException {
SecretKey key, IvParameterSpec iv, SecureRandom random,
boolean encrypt) throws NoSuchAlgorithmException {
try {
this.protocolVersion = protocolVersion;
this.cipher = JsseJce.getCipher(bulkCipher.transformation);
int mode = encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE;
cipher.init(mode, key, iv);
// do not call getBlockSize until after init()
if (random == null) {
random = JsseJce.getSecureRandom();
}
this.random = random;
/*
* RFC 4346 recommends two algorithms used to generated the
* per-record IV. The implementation uses the algorithm (2)(b),
* as described at section 6.2.3.2 of RFC 4346.
*
* As we don't care about the initial IV value for TLS 1.1 or
* later, so if the "iv" parameter is null, we use the default
* value generated by Cipher.init() for encryption, and a fixed
* mask for decryption.
*/
if (iv == null && bulkCipher.ivSize != 0 &&
mode == Cipher.DECRYPT_MODE &&
protocolVersion.v >= ProtocolVersion.TLS11.v) {
iv = getFixedMask(bulkCipher.ivSize);
}
cipher.init(mode, key, iv, random);
// Do not call getBlockSize until after init()
// otherwise we would disrupt JCE delayed provider selection
blockSize = cipher.getBlockSize();
// some providers implement getBlockSize() incorrectly
@ -119,18 +189,36 @@ final class CipherBox {
* Factory method to obtain a new CipherBox object.
*/
static CipherBox newCipherBox(ProtocolVersion version, BulkCipher cipher,
SecretKey key, IvParameterSpec iv, boolean encrypt)
throws NoSuchAlgorithmException {
SecretKey key, IvParameterSpec iv, SecureRandom random,
boolean encrypt) throws NoSuchAlgorithmException {
if (cipher.allowed == false) {
throw new NoSuchAlgorithmException("Unsupported cipher " + cipher);
}
if (cipher == B_NULL) {
return NULL;
} else {
return new CipherBox(version, cipher, key, iv, encrypt);
return new CipherBox(version, cipher, key, iv, random, encrypt);
}
}
/*
* Get a fixed mask, as the initial decryption IVs for TLS 1.1 or later.
*/
private static IvParameterSpec getFixedMask(int ivSize) {
if (masks == null) {
masks = new Hashtable<Integer, IvParameterSpec>(5);
}
IvParameterSpec iv = masks.get(ivSize);
if (iv == null) {
iv = new IvParameterSpec(new byte[ivSize]);
masks.put(ivSize, iv);
}
return iv;
}
/*
* Encrypts a block of data, returning the size of the
* resulting block.
@ -139,8 +227,26 @@ final class CipherBox {
if (cipher == null) {
return len;
}
try {
if (blockSize != 0) {
// TLSv1.1 needs a IV block
if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
// generate a random number
byte[] prefix = new byte[blockSize];
random.nextBytes(prefix);
// move forward the plaintext
System.arraycopy(buf, offset,
buf, offset + prefix.length, len);
// prefix the plaintext
System.arraycopy(prefix, 0,
buf, offset, prefix.length);
len += prefix.length;
}
len = addPadding(buf, offset, len, blockSize);
}
if (debug != null && Debug.isOn("plaintext")) {
@ -189,6 +295,34 @@ final class CipherBox {
int pos = bb.position();
if (blockSize != 0) {
// TLSv1.1 needs a IV block
if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
// generate a random number
byte[] prefix = new byte[blockSize];
random.nextBytes(prefix);
// move forward the plaintext
byte[] buf = null;
int limit = bb.limit();
if (bb.hasArray()) {
buf = bb.array();
System.arraycopy(buf, pos,
buf, pos + prefix.length, limit - pos);
bb.limit(limit + prefix.length);
} else {
buf = new byte[limit - pos];
bb.get(buf, 0, limit - pos);
bb.position(pos + prefix.length);
bb.limit(limit + prefix.length);
bb.put(buf);
}
bb.position(pos);
// prefix the plaintext
bb.put(prefix);
bb.position(pos);
}
// addPadding adjusts pos/limit
len = addPadding(bb, blockSize);
bb.position(pos);
@ -236,11 +370,25 @@ final class CipherBox {
/*
* Decrypts a block of data, returning the size of the
* resulting block if padding was required.
*
* For SSLv3 and TLSv1.0, with block ciphers in CBC mode the
* Initialization Vector (IV) for the first record is generated by
* the handshake protocol, the IV for subsequent records is the
* last ciphertext block from the previous record.
*
* From TLSv1.1, the implicit IV is replaced with an explicit IV to
* protect against CBC attacks.
*
* Differentiating between bad_record_mac and decryption_failed alerts
* may permit certain attacks against CBC mode. It is preferable to
* uniformly use the bad_record_mac alert to hide the specific type of
* the error.
*/
int decrypt(byte[] buf, int offset, int len) throws BadPaddingException {
if (cipher == null) {
return len;
}
try {
int newLen = cipher.update(buf, offset, len, buf, offset);
if (newLen != len) {
@ -263,6 +411,18 @@ final class CipherBox {
if (blockSize != 0) {
newLen = removePadding(buf, offset, newLen,
blockSize, protocolVersion);
if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
if (newLen < blockSize) {
throw new BadPaddingException("invalid explicit IV");
}
// discards the first cipher block, the IV component.
System.arraycopy(buf, offset + blockSize,
buf, offset, newLen - blockSize);
newLen -= blockSize;
}
}
return newLen;
} catch (ShortBufferException e) {
@ -277,6 +437,8 @@ final class CipherBox {
* point to the end of the decrypted/depadded data. The initial
* limit and new limit may be different, given we may
* have stripped off some padding bytes.
*
* @see decrypt(byte[], int, int)
*/
int decrypt(ByteBuffer bb) throws BadPaddingException {
@ -292,7 +454,6 @@ final class CipherBox {
* Decrypt "in-place".
*/
int pos = bb.position();
ByteBuffer dup = bb.duplicate();
int newLen = cipher.update(dup, bb);
if (newLen != len) {
@ -320,6 +481,33 @@ final class CipherBox {
if (blockSize != 0) {
bb.position(pos);
newLen = removePadding(bb, blockSize, protocolVersion);
if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
if (newLen < blockSize) {
throw new BadPaddingException("invalid explicit IV");
}
// discards the first cipher block, the IV component.
byte[] buf = null;
int limit = bb.limit();
if (bb.hasArray()) {
buf = bb.array();
System.arraycopy(buf, pos + blockSize,
buf, pos, limit - pos - blockSize);
bb.limit(limit - blockSize);
} else {
buf = new byte[limit - pos - blockSize];
bb.position(pos + blockSize);
bb.get(buf);
bb.position(pos);
bb.put(buf);
bb.limit(limit - blockSize);
}
// reset the position to the end of the decrypted data
limit = bb.limit();
bb.position(limit);
}
}
return newLen;
} catch (ShortBufferException e) {

View File

@ -30,6 +30,7 @@ import java.util.*;
import java.security.NoSuchAlgorithmException;
import java.security.InvalidKeyException;
import java.security.SecureRandom;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
@ -37,6 +38,7 @@ import javax.crypto.spec.SecretKeySpec;
import sun.security.ssl.CipherSuite.*;
import static sun.security.ssl.CipherSuite.KeyExchange.*;
import static sun.security.ssl.CipherSuite.PRF.*;
import static sun.security.ssl.JsseJce.*;
/**
@ -101,19 +103,32 @@ final class CipherSuite implements Comparable {
// by default
final int priority;
// key exchange, bulk cipher, and mac algorithms. See those classes below.
// key exchange, bulk cipher, mac and prf algorithms. See those
// classes below.
final KeyExchange keyExchange;
final BulkCipher cipher;
final MacAlg macAlg;
final PRF prfAlg;
// whether a CipherSuite qualifies as exportable under 512/40 bit rules.
// TLS 1.1+ (RFC 4346) must not negotiate to these suites.
final boolean exportable;
// true iff implemented and enabled at compile time
final boolean allowed;
// obsoleted since protocol version
final int obsoleted;
// supported since protocol version
final int supported;
/**
* Constructor for implemented CipherSuites.
*/
private CipherSuite(String name, int id, int priority,
KeyExchange keyExchange, BulkCipher cipher, boolean allowed) {
KeyExchange keyExchange, BulkCipher cipher,
boolean allowed, int obsoleted, int supported, PRF prfAlg) {
this.name = name;
this.id = id;
this.priority = priority;
@ -124,6 +139,10 @@ final class CipherSuite implements Comparable {
macAlg = M_MD5;
} else if (name.endsWith("_SHA")) {
macAlg = M_SHA;
} else if (name.endsWith("_SHA256")) {
macAlg = M_SHA256;
} else if (name.endsWith("_SHA384")) {
macAlg = M_SHA384;
} else if (name.endsWith("_NULL")) {
macAlg = M_NULL;
} else if (name.endsWith("_SCSV")) {
@ -136,8 +155,14 @@ final class CipherSuite implements Comparable {
allowed &= keyExchange.allowed;
allowed &= cipher.allowed;
this.allowed = allowed;
this.obsoleted = obsoleted;
this.supported = supported;
this.prfAlg = prfAlg;
}
/**
* Constructor for unimplemented CipherSuites.
*/
private CipherSuite(String name, int id) {
this.name = name;
this.id = id;
@ -148,6 +173,9 @@ final class CipherSuite implements Comparable {
this.cipher = null;
this.macAlg = null;
this.exportable = false;
this.obsoleted = ProtocolVersion.LIMIT_MAX_VALUE;
this.supported = ProtocolVersion.LIMIT_MIN_VALUE;
this.prfAlg = P_NONE;
}
/**
@ -197,10 +225,12 @@ final class CipherSuite implements Comparable {
if (s == null) {
throw new IllegalArgumentException("Name must not be null");
}
CipherSuite c = nameMap.get(s);
if ((c == null) || (c.allowed == false)) {
throw new IllegalArgumentException("Unsupported ciphersuite " + s);
}
return c;
}
@ -227,10 +257,17 @@ final class CipherSuite implements Comparable {
return nameMap.values();
}
/*
* Use this method when all of the values need to be specified.
* This is primarily used when defining a new ciphersuite for
* TLS 1.2+ that doesn't use the "default" PRF.
*/
private static void add(String name, int id, int priority,
KeyExchange keyExchange, BulkCipher cipher, boolean allowed) {
KeyExchange keyExchange, BulkCipher cipher,
boolean allowed, int obsoleted, int supported, PRF prf) {
CipherSuite c = new CipherSuite(name, id, priority, keyExchange,
cipher, allowed);
cipher, allowed, obsoleted, supported, prf);
if (idMap.put(id, c) != null) {
throw new RuntimeException("Duplicate ciphersuite definition: "
+ id + ", " + name);
@ -243,6 +280,41 @@ final class CipherSuite implements Comparable {
}
}
/*
* Use this method when there is no lower protocol limit where this
* suite can be used, and the PRF is P_SHA256. That is, the
* existing ciphersuites. From RFC 5246:
*
* All cipher suites in this document use P_SHA256.
*/
private static void add(String name, int id, int priority,
KeyExchange keyExchange, BulkCipher cipher,
boolean allowed, int obsoleted) {
// If this is an obsoleted suite, then don't let the TLS 1.2
// protocol have a valid PRF value.
PRF prf = P_SHA256;
if (obsoleted < ProtocolVersion.TLS12.v) {
prf = P_NONE;
}
add(name, id, priority, keyExchange, cipher, allowed, obsoleted,
ProtocolVersion.LIMIT_MIN_VALUE, prf);
}
/*
* Use this method when there is no upper protocol limit. That is,
* suites which have not been obsoleted.
*/
private static void add(String name, int id, int priority,
KeyExchange keyExchange, BulkCipher cipher, boolean allowed) {
add(name, id, priority, keyExchange,
cipher, allowed, ProtocolVersion.LIMIT_MAX_VALUE);
}
/*
* Use this method to define an unimplemented suite. This provides
* a number<->name mapping that can be used for debugging.
*/
private static void add(String name, int id) {
CipherSuite c = new CipherSuite(name, id);
if (idMap.put(id, c) != null) {
@ -380,10 +452,11 @@ final class CipherSuite implements Comparable {
*
* @exception NoSuchAlgorithmException if anything goes wrong
*/
CipherBox newCipher(ProtocolVersion version,
SecretKey key, IvParameterSpec iv,
CipherBox newCipher(ProtocolVersion version, SecretKey key,
IvParameterSpec iv, SecureRandom random,
boolean encrypt) throws NoSuchAlgorithmException {
return CipherBox.newCipherBox(version, this, key, iv, encrypt);
return CipherBox.newCipherBox(version, this,
key, iv, random, encrypt);
}
/**
@ -402,6 +475,7 @@ final class CipherSuite implements Comparable {
if (this == B_AES_256) {
return isAvailable(this);
}
// always available
return true;
}
@ -421,7 +495,8 @@ final class CipherSuite implements Comparable {
(new byte[cipher.expandedKeySize], cipher.algorithm);
IvParameterSpec iv =
new IvParameterSpec(new byte[cipher.ivSize]);
cipher.newCipher(ProtocolVersion.DEFAULT, key, iv, true);
cipher.newCipher(ProtocolVersion.DEFAULT,
key, iv, null, true);
b = Boolean.TRUE;
} catch (NoSuchAlgorithmException e) {
b = Boolean.FALSE;
@ -439,7 +514,7 @@ final class CipherSuite implements Comparable {
/**
* An SSL/TLS key MAC algorithm.
*
* Also contains a factory method to obtain in initialized MAC
* Also contains a factory method to obtain an initialized MAC
* for this algorithm.
*/
final static class MacAlg {
@ -499,6 +574,48 @@ final class CipherSuite implements Comparable {
final static MacAlg M_NULL = new MacAlg("NULL", 0);
final static MacAlg M_MD5 = new MacAlg("MD5", 16);
final static MacAlg M_SHA = new MacAlg("SHA", 20);
final static MacAlg M_SHA256 = new MacAlg("SHA256", 32);
final static MacAlg M_SHA384 = new MacAlg("SHA384", 48);
// PRFs (PseudoRandom Function) from TLS specifications.
//
// TLS 1.1- uses a single MD5/SHA1-based PRF algorithm for generating
// the necessary material.
//
// In TLS 1.2+, all existing/known CipherSuites use SHA256, however
// new Ciphersuites (e.g. RFC 5288) can define specific PRF hash
// algorithms.
static enum PRF {
// PRF algorithms
P_NONE( "NONE", 0, 0),
P_SHA256("SHA-256", 32, 64),
P_SHA384("SHA-384", 48, 128),
P_SHA512("SHA-512", 64, 128); // not currently used.
// PRF characteristics
private final String prfHashAlg;
private final int prfHashLength;
private final int prfBlockSize;
PRF(String prfHashAlg, int prfHashLength, int prfBlockSize) {
this.prfHashAlg = prfHashAlg;
this.prfHashLength = prfHashLength;
this.prfBlockSize = prfBlockSize;
}
String getPRFHashAlg() {
return prfHashAlg;
}
int getPRFHashLength() {
return prfHashLength;
}
int getPRFBlockSize() {
return prfBlockSize;
}
}
static {
idMap = new HashMap<Integer,CipherSuite>();
@ -509,6 +626,239 @@ final class CipherSuite implements Comparable {
// N: ciphersuites only allowed if we are not in FIPS mode
final boolean N = (SunJSSE.isFIPS() == false);
/*
* TLS Cipher Suite Registry, as of August 2010.
*
* http://www.iana.org/assignments/tls-parameters/tls-parameters.xml
*
* Range Registration Procedures Notes
* 000-191 Standards Action Refers to value of first byte
* 192-254 Specification Required Refers to value of first byte
* 255 Reserved for Private Use Refers to value of first byte
*
* Value Description Reference
* 0x00,0x00 TLS_NULL_WITH_NULL_NULL [RFC5246]
* 0x00,0x01 TLS_RSA_WITH_NULL_MD5 [RFC5246]
* 0x00,0x02 TLS_RSA_WITH_NULL_SHA [RFC5246]
* 0x00,0x03 TLS_RSA_EXPORT_WITH_RC4_40_MD5 [RFC4346]
* 0x00,0x04 TLS_RSA_WITH_RC4_128_MD5 [RFC5246]
* 0x00,0x05 TLS_RSA_WITH_RC4_128_SHA [RFC5246]
* 0x00,0x06 TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 [RFC4346]
* 0x00,0x07 TLS_RSA_WITH_IDEA_CBC_SHA [RFC5469]
* 0x00,0x08 TLS_RSA_EXPORT_WITH_DES40_CBC_SHA [RFC4346]
* 0x00,0x09 TLS_RSA_WITH_DES_CBC_SHA [RFC5469]
* 0x00,0x0A TLS_RSA_WITH_3DES_EDE_CBC_SHA [RFC5246]
* 0x00,0x0B TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA [RFC4346]
* 0x00,0x0C TLS_DH_DSS_WITH_DES_CBC_SHA [RFC5469]
* 0x00,0x0D TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA [RFC5246]
* 0x00,0x0E TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA [RFC4346]
* 0x00,0x0F TLS_DH_RSA_WITH_DES_CBC_SHA [RFC5469]
* 0x00,0x10 TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA [RFC5246]
* 0x00,0x11 TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA [RFC4346]
* 0x00,0x12 TLS_DHE_DSS_WITH_DES_CBC_SHA [RFC5469]
* 0x00,0x13 TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA [RFC5246]
* 0x00,0x14 TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA [RFC4346]
* 0x00,0x15 TLS_DHE_RSA_WITH_DES_CBC_SHA [RFC5469]
* 0x00,0x16 TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA [RFC5246]
* 0x00,0x17 TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 [RFC4346]
* 0x00,0x18 TLS_DH_anon_WITH_RC4_128_MD5 [RFC5246]
* 0x00,0x19 TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA [RFC4346]
* 0x00,0x1A TLS_DH_anon_WITH_DES_CBC_SHA [RFC5469]
* 0x00,0x1B TLS_DH_anon_WITH_3DES_EDE_CBC_SHA [RFC5246]
* 0x00,0x1C-1D Reserved to avoid conflicts with SSLv3 [RFC5246]
* 0x00,0x1E TLS_KRB5_WITH_DES_CBC_SHA [RFC2712]
* 0x00,0x1F TLS_KRB5_WITH_3DES_EDE_CBC_SHA [RFC2712]
* 0x00,0x20 TLS_KRB5_WITH_RC4_128_SHA [RFC2712]
* 0x00,0x21 TLS_KRB5_WITH_IDEA_CBC_SHA [RFC2712]
* 0x00,0x22 TLS_KRB5_WITH_DES_CBC_MD5 [RFC2712]
* 0x00,0x23 TLS_KRB5_WITH_3DES_EDE_CBC_MD5 [RFC2712]
* 0x00,0x24 TLS_KRB5_WITH_RC4_128_MD5 [RFC2712]
* 0x00,0x25 TLS_KRB5_WITH_IDEA_CBC_MD5 [RFC2712]
* 0x00,0x26 TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA [RFC2712]
* 0x00,0x27 TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA [RFC2712]
* 0x00,0x28 TLS_KRB5_EXPORT_WITH_RC4_40_SHA [RFC2712]
* 0x00,0x29 TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5 [RFC2712]
* 0x00,0x2A TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5 [RFC2712]
* 0x00,0x2B TLS_KRB5_EXPORT_WITH_RC4_40_MD5 [RFC2712]
* 0x00,0x2C TLS_PSK_WITH_NULL_SHA [RFC4785]
* 0x00,0x2D TLS_DHE_PSK_WITH_NULL_SHA [RFC4785]
* 0x00,0x2E TLS_RSA_PSK_WITH_NULL_SHA [RFC4785]
* 0x00,0x2F TLS_RSA_WITH_AES_128_CBC_SHA [RFC5246]
* 0x00,0x30 TLS_DH_DSS_WITH_AES_128_CBC_SHA [RFC5246]
* 0x00,0x31 TLS_DH_RSA_WITH_AES_128_CBC_SHA [RFC5246]
* 0x00,0x32 TLS_DHE_DSS_WITH_AES_128_CBC_SHA [RFC5246]
* 0x00,0x33 TLS_DHE_RSA_WITH_AES_128_CBC_SHA [RFC5246]
* 0x00,0x34 TLS_DH_anon_WITH_AES_128_CBC_SHA [RFC5246]
* 0x00,0x35 TLS_RSA_WITH_AES_256_CBC_SHA [RFC5246]
* 0x00,0x36 TLS_DH_DSS_WITH_AES_256_CBC_SHA [RFC5246]
* 0x00,0x37 TLS_DH_RSA_WITH_AES_256_CBC_SHA [RFC5246]
* 0x00,0x38 TLS_DHE_DSS_WITH_AES_256_CBC_SHA [RFC5246]
* 0x00,0x39 TLS_DHE_RSA_WITH_AES_256_CBC_SHA [RFC5246]
* 0x00,0x3A TLS_DH_anon_WITH_AES_256_CBC_SHA [RFC5246]
* 0x00,0x3B TLS_RSA_WITH_NULL_SHA256 [RFC5246]
* 0x00,0x3C TLS_RSA_WITH_AES_128_CBC_SHA256 [RFC5246]
* 0x00,0x3D TLS_RSA_WITH_AES_256_CBC_SHA256 [RFC5246]
* 0x00,0x3E TLS_DH_DSS_WITH_AES_128_CBC_SHA256 [RFC5246]
* 0x00,0x3F TLS_DH_RSA_WITH_AES_128_CBC_SHA256 [RFC5246]
* 0x00,0x40 TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 [RFC5246]
* 0x00,0x41 TLS_RSA_WITH_CAMELLIA_128_CBC_SHA [RFC5932]
* 0x00,0x42 TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA [RFC5932]
* 0x00,0x43 TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA [RFC5932]
* 0x00,0x44 TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA [RFC5932]
* 0x00,0x45 TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA [RFC5932]
* 0x00,0x46 TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA [RFC5932]
* 0x00,0x47-4F Reserved to avoid conflicts with
* deployed implementations [Pasi_Eronen]
* 0x00,0x50-58 Reserved to avoid conflicts [Pasi Eronen]
* 0x00,0x59-5C Reserved to avoid conflicts with
* deployed implementations [Pasi_Eronen]
* 0x00,0x5D-5F Unassigned
* 0x00,0x60-66 Reserved to avoid conflicts with widely
* deployed implementations [Pasi_Eronen]
* 0x00,0x67 TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 [RFC5246]
* 0x00,0x68 TLS_DH_DSS_WITH_AES_256_CBC_SHA256 [RFC5246]
* 0x00,0x69 TLS_DH_RSA_WITH_AES_256_CBC_SHA256 [RFC5246]
* 0x00,0x6A TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 [RFC5246]
* 0x00,0x6B TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 [RFC5246]
* 0x00,0x6C TLS_DH_anon_WITH_AES_128_CBC_SHA256 [RFC5246]
* 0x00,0x6D TLS_DH_anon_WITH_AES_256_CBC_SHA256 [RFC5246]
* 0x00,0x6E-83 Unassigned
* 0x00,0x84 TLS_RSA_WITH_CAMELLIA_256_CBC_SHA [RFC5932]
* 0x00,0x85 TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA [RFC5932]
* 0x00,0x86 TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA [RFC5932]
* 0x00,0x87 TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA [RFC5932]
* 0x00,0x88 TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA [RFC5932]
* 0x00,0x89 TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA [RFC5932]
* 0x00,0x8A TLS_PSK_WITH_RC4_128_SHA [RFC4279]
* 0x00,0x8B TLS_PSK_WITH_3DES_EDE_CBC_SHA [RFC4279]
* 0x00,0x8C TLS_PSK_WITH_AES_128_CBC_SHA [RFC4279]
* 0x00,0x8D TLS_PSK_WITH_AES_256_CBC_SHA [RFC4279]
* 0x00,0x8E TLS_DHE_PSK_WITH_RC4_128_SHA [RFC4279]
* 0x00,0x8F TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA [RFC4279]
* 0x00,0x90 TLS_DHE_PSK_WITH_AES_128_CBC_SHA [RFC4279]
* 0x00,0x91 TLS_DHE_PSK_WITH_AES_256_CBC_SHA [RFC4279]
* 0x00,0x92 TLS_RSA_PSK_WITH_RC4_128_SHA [RFC4279]
* 0x00,0x93 TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA [RFC4279]
* 0x00,0x94 TLS_RSA_PSK_WITH_AES_128_CBC_SHA [RFC4279]
* 0x00,0x95 TLS_RSA_PSK_WITH_AES_256_CBC_SHA [RFC4279]
* 0x00,0x96 TLS_RSA_WITH_SEED_CBC_SHA [RFC4162]
* 0x00,0x97 TLS_DH_DSS_WITH_SEED_CBC_SHA [RFC4162]
* 0x00,0x98 TLS_DH_RSA_WITH_SEED_CBC_SHA [RFC4162]
* 0x00,0x99 TLS_DHE_DSS_WITH_SEED_CBC_SHA [RFC4162]
* 0x00,0x9A TLS_DHE_RSA_WITH_SEED_CBC_SHA [RFC4162]
* 0x00,0x9B TLS_DH_anon_WITH_SEED_CBC_SHA [RFC4162]
* 0x00,0x9C TLS_RSA_WITH_AES_128_GCM_SHA256 [RFC5288]
* 0x00,0x9D TLS_RSA_WITH_AES_256_GCM_SHA384 [RFC5288]
* 0x00,0x9E TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 [RFC5288]
* 0x00,0x9F TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 [RFC5288]
* 0x00,0xA0 TLS_DH_RSA_WITH_AES_128_GCM_SHA256 [RFC5288]
* 0x00,0xA1 TLS_DH_RSA_WITH_AES_256_GCM_SHA384 [RFC5288]
* 0x00,0xA2 TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 [RFC5288]
* 0x00,0xA3 TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 [RFC5288]
* 0x00,0xA4 TLS_DH_DSS_WITH_AES_128_GCM_SHA256 [RFC5288]
* 0x00,0xA5 TLS_DH_DSS_WITH_AES_256_GCM_SHA384 [RFC5288]
* 0x00,0xA6 TLS_DH_anon_WITH_AES_128_GCM_SHA256 [RFC5288]
* 0x00,0xA7 TLS_DH_anon_WITH_AES_256_GCM_SHA384 [RFC5288]
* 0x00,0xA8 TLS_PSK_WITH_AES_128_GCM_SHA256 [RFC5487]
* 0x00,0xA9 TLS_PSK_WITH_AES_256_GCM_SHA384 [RFC5487]
* 0x00,0xAA TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 [RFC5487]
* 0x00,0xAB TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 [RFC5487]
* 0x00,0xAC TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 [RFC5487]
* 0x00,0xAD TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 [RFC5487]
* 0x00,0xAE TLS_PSK_WITH_AES_128_CBC_SHA256 [RFC5487]
* 0x00,0xAF TLS_PSK_WITH_AES_256_CBC_SHA384 [RFC5487]
* 0x00,0xB0 TLS_PSK_WITH_NULL_SHA256 [RFC5487]
* 0x00,0xB1 TLS_PSK_WITH_NULL_SHA384 [RFC5487]
* 0x00,0xB2 TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 [RFC5487]
* 0x00,0xB3 TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 [RFC5487]
* 0x00,0xB4 TLS_DHE_PSK_WITH_NULL_SHA256 [RFC5487]
* 0x00,0xB5 TLS_DHE_PSK_WITH_NULL_SHA384 [RFC5487]
* 0x00,0xB6 TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 [RFC5487]
* 0x00,0xB7 TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 [RFC5487]
* 0x00,0xB8 TLS_RSA_PSK_WITH_NULL_SHA256 [RFC5487]
* 0x00,0xB9 TLS_RSA_PSK_WITH_NULL_SHA384 [RFC5487]
* 0x00,0xBA TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 [RFC5932]
* 0x00,0xBB TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256 [RFC5932]
* 0x00,0xBC TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256 [RFC5932]
* 0x00,0xBD TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 [RFC5932]
* 0x00,0xBE TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 [RFC5932]
* 0x00,0xBF TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256 [RFC5932]
* 0x00,0xC0 TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 [RFC5932]
* 0x00,0xC1 TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256 [RFC5932]
* 0x00,0xC2 TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256 [RFC5932]
* 0x00,0xC3 TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 [RFC5932]
* 0x00,0xC4 TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 [RFC5932]
* 0x00,0xC5 TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256 [RFC5932]
* 0x00,0xC6-FE Unassigned
* 0x00,0xFF TLS_EMPTY_RENEGOTIATION_INFO_SCSV [RFC5746]
* 0x01-BF,* Unassigned
* 0xC0,0x01 TLS_ECDH_ECDSA_WITH_NULL_SHA [RFC4492]
* 0xC0,0x02 TLS_ECDH_ECDSA_WITH_RC4_128_SHA [RFC4492]
* 0xC0,0x03 TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA [RFC4492]
* 0xC0,0x04 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA [RFC4492]
* 0xC0,0x05 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA [RFC4492]
* 0xC0,0x06 TLS_ECDHE_ECDSA_WITH_NULL_SHA [RFC4492]
* 0xC0,0x07 TLS_ECDHE_ECDSA_WITH_RC4_128_SHA [RFC4492]
* 0xC0,0x08 TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA [RFC4492]
* 0xC0,0x09 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA [RFC4492]
* 0xC0,0x0A TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA [RFC4492]
* 0xC0,0x0B TLS_ECDH_RSA_WITH_NULL_SHA [RFC4492]
* 0xC0,0x0C TLS_ECDH_RSA_WITH_RC4_128_SHA [RFC4492]
* 0xC0,0x0D TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA [RFC4492]
* 0xC0,0x0E TLS_ECDH_RSA_WITH_AES_128_CBC_SHA [RFC4492]
* 0xC0,0x0F TLS_ECDH_RSA_WITH_AES_256_CBC_SHA [RFC4492]
* 0xC0,0x10 TLS_ECDHE_RSA_WITH_NULL_SHA [RFC4492]
* 0xC0,0x11 TLS_ECDHE_RSA_WITH_RC4_128_SHA [RFC4492]
* 0xC0,0x12 TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA [RFC4492]
* 0xC0,0x13 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA [RFC4492]
* 0xC0,0x14 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA [RFC4492]
* 0xC0,0x15 TLS_ECDH_anon_WITH_NULL_SHA [RFC4492]
* 0xC0,0x16 TLS_ECDH_anon_WITH_RC4_128_SHA [RFC4492]
* 0xC0,0x17 TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA [RFC4492]
* 0xC0,0x18 TLS_ECDH_anon_WITH_AES_128_CBC_SHA [RFC4492]
* 0xC0,0x19 TLS_ECDH_anon_WITH_AES_256_CBC_SHA [RFC4492]
* 0xC0,0x1A TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA [RFC5054]
* 0xC0,0x1B TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA [RFC5054]
* 0xC0,0x1C TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA [RFC5054]
* 0xC0,0x1D TLS_SRP_SHA_WITH_AES_128_CBC_SHA [RFC5054]
* 0xC0,0x1E TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA [RFC5054]
* 0xC0,0x1F TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA [RFC5054]
* 0xC0,0x20 TLS_SRP_SHA_WITH_AES_256_CBC_SHA [RFC5054]
* 0xC0,0x21 TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA [RFC5054]
* 0xC0,0x22 TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA [RFC5054]
* 0xC0,0x23 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 [RFC5289]
* 0xC0,0x24 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 [RFC5289]
* 0xC0,0x25 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 [RFC5289]
* 0xC0,0x26 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 [RFC5289]
* 0xC0,0x27 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 [RFC5289]
* 0xC0,0x28 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 [RFC5289]
* 0xC0,0x29 TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 [RFC5289]
* 0xC0,0x2A TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 [RFC5289]
* 0xC0,0x2B TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 [RFC5289]
* 0xC0,0x2C TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 [RFC5289]
* 0xC0,0x2D TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 [RFC5289]
* 0xC0,0x2E TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 [RFC5289]
* 0xC0,0x2F TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 [RFC5289]
* 0xC0,0x30 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 [RFC5289]
* 0xC0,0x31 TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 [RFC5289]
* 0xC0,0x32 TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 [RFC5289]
* 0xC0,0x33 TLS_ECDHE_PSK_WITH_RC4_128_SHA [RFC5489]
* 0xC0,0x34 TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA [RFC5489]
* 0xC0,0x35 TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA [RFC5489]
* 0xC0,0x36 TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA [RFC5489]
* 0xC0,0x37 TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 [RFC5489]
* 0xC0,0x38 TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 [RFC5489]
* 0xC0,0x39 TLS_ECDHE_PSK_WITH_NULL_SHA [RFC5489]
* 0xC0,0x3A TLS_ECDHE_PSK_WITH_NULL_SHA256 [RFC5489]
* 0xC0,0x3B TLS_ECDHE_PSK_WITH_NULL_SHA384 [RFC5489]
* 0xC0,0x3C-FF Unassigned
* 0xC1-FD,* Unassigned
* 0xFE,0x00-FD Unassigned
* 0xFE,0xFE-FF Reserved to avoid conflicts with widely
* deployed implementations [Pasi_Eronen]
* 0xFF,0x00-FF Reserved for Private Use [RFC5246]
*/
add("SSL_NULL_WITH_NULL_NULL",
0x0000, 1, K_NULL, B_NULL, F);
@ -516,191 +866,377 @@ final class CipherSuite implements Comparable {
// They are listed in preference order, most preferred first.
int p = DEFAULT_SUITES_PRIORITY * 2;
// shorten names to fit the following table cleanly.
int max = ProtocolVersion.LIMIT_MAX_VALUE;
int tls11 = ProtocolVersion.TLS11.v;
int tls12 = ProtocolVersion.TLS12.v;
// ID Key Exchange Cipher A obs suprt PRF
// ====== ============ ========= = === ===== ========
add("TLS_RSA_WITH_AES_128_CBC_SHA256",
0x003c, --p, K_RSA, B_AES_128, T, max, tls12, P_SHA256);
add("TLS_RSA_WITH_AES_256_CBC_SHA256",
0x003d, --p, K_RSA, B_AES_256, T, max, tls12, P_SHA256);
add("TLS_DHE_DSS_WITH_AES_128_CBC_SHA256",
0x0040, --p, K_DHE_DSS, B_AES_128, T, max, tls12, P_SHA256);
add("TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
0x0067, --p, K_DHE_RSA, B_AES_128, T, max, tls12, P_SHA256);
add("TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",
0x006a, --p, K_DHE_DSS, B_AES_256, T, max, tls12, P_SHA256);
add("TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
0x006b, --p, K_DHE_RSA, B_AES_256, T, max, tls12, P_SHA256);
add("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
0xc023, --p, K_ECDHE_ECDSA, B_AES_128, T, max, tls12, P_SHA256);
add("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
0xc024, --p, K_ECDHE_ECDSA, B_AES_256, T, max, tls12, P_SHA384);
add("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256",
0xc025, --p, K_ECDH_ECDSA, B_AES_128, T, max, tls12, P_SHA256);
add("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384",
0xc026, --p, K_ECDH_ECDSA, B_AES_256, T, max, tls12, P_SHA384);
add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
0xc027, --p, K_ECDHE_RSA, B_AES_128, T, max, tls12, P_SHA256);
add("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
0xc028, --p, K_ECDHE_RSA, B_AES_256, T, max, tls12, P_SHA384);
add("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256",
0xc029, --p, K_ECDH_RSA, B_AES_128, T, max, tls12, P_SHA256);
add("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384",
0xc02a, --p, K_ECDH_RSA, B_AES_256, T, max, tls12, P_SHA384);
add("SSL_RSA_WITH_RC4_128_MD5",
0x0004, --p, K_RSA, B_RC4_128, N);
0x0004, --p, K_RSA, B_RC4_128, N);
add("SSL_RSA_WITH_RC4_128_SHA",
0x0005, --p, K_RSA, B_RC4_128, N);
0x0005, --p, K_RSA, B_RC4_128, N);
add("TLS_RSA_WITH_AES_128_CBC_SHA",
0x002f, --p, K_RSA, B_AES_128, T);
0x002f, --p, K_RSA, B_AES_128, T);
add("TLS_RSA_WITH_AES_256_CBC_SHA",
0x0035, --p, K_RSA, B_AES_256, T);
0x0035, --p, K_RSA, B_AES_256, T);
add("TLS_ECDH_ECDSA_WITH_RC4_128_SHA",
0xC002, --p, K_ECDH_ECDSA, B_RC4_128, N);
0xC002, --p, K_ECDH_ECDSA, B_RC4_128, N);
add("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA",
0xC004, --p, K_ECDH_ECDSA, B_AES_128, T);
0xC004, --p, K_ECDH_ECDSA, B_AES_128, T);
add("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA",
0xC005, --p, K_ECDH_ECDSA, B_AES_256, T);
0xC005, --p, K_ECDH_ECDSA, B_AES_256, T);
add("TLS_ECDH_RSA_WITH_RC4_128_SHA",
0xC00C, --p, K_ECDH_RSA, B_RC4_128, N);
0xC00C, --p, K_ECDH_RSA, B_RC4_128, N);
add("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",
0xC00E, --p, K_ECDH_RSA, B_AES_128, T);
0xC00E, --p, K_ECDH_RSA, B_AES_128, T);
add("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA",
0xC00F, --p, K_ECDH_RSA, B_AES_256, T);
0xC00F, --p, K_ECDH_RSA, B_AES_256, T);
add("TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
0xC007, --p, K_ECDHE_ECDSA,B_RC4_128, N);
0xC007, --p, K_ECDHE_ECDSA, B_RC4_128, N);
add("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
0xC009, --p, K_ECDHE_ECDSA,B_AES_128, T);
0xC009, --p, K_ECDHE_ECDSA, B_AES_128, T);
add("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
0xC00A, --p, K_ECDHE_ECDSA,B_AES_256, T);
0xC00A, --p, K_ECDHE_ECDSA, B_AES_256, T);
add("TLS_ECDHE_RSA_WITH_RC4_128_SHA",
0xC011, --p, K_ECDHE_RSA, B_RC4_128, N);
0xC011, --p, K_ECDHE_RSA, B_RC4_128, N);
add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
0xC013, --p, K_ECDHE_RSA, B_AES_128, T);
0xC013, --p, K_ECDHE_RSA, B_AES_128, T);
add("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
0xC014, --p, K_ECDHE_RSA, B_AES_256, T);
0xC014, --p, K_ECDHE_RSA, B_AES_256, T);
add("TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
0x0033, --p, K_DHE_RSA, B_AES_128, T);
0x0033, --p, K_DHE_RSA, B_AES_128, T);
add("TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
0x0039, --p, K_DHE_RSA, B_AES_256, T);
0x0039, --p, K_DHE_RSA, B_AES_256, T);
add("TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
0x0032, --p, K_DHE_DSS, B_AES_128, T);
0x0032, --p, K_DHE_DSS, B_AES_128, T);
add("TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
0x0038, --p, K_DHE_DSS, B_AES_256, T);
0x0038, --p, K_DHE_DSS, B_AES_256, T);
add("SSL_RSA_WITH_3DES_EDE_CBC_SHA",
0x000a, --p, K_RSA, B_3DES, T);
0x000a, --p, K_RSA, B_3DES, T);
add("TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA",
0xC003, --p, K_ECDH_ECDSA, B_3DES, T);
0xC003, --p, K_ECDH_ECDSA, B_3DES, T);
add("TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA",
0xC00D, --p, K_ECDH_RSA, B_3DES, T);
0xC00D, --p, K_ECDH_RSA, B_3DES, T);
add("TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
0xC008, --p, K_ECDHE_ECDSA,B_3DES, T);
0xC008, --p, K_ECDHE_ECDSA, B_3DES, T);
add("TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
0xC012, --p, K_ECDHE_RSA, B_3DES, T);
0xC012, --p, K_ECDHE_RSA, B_3DES, T);
add("SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
0x0016, --p, K_DHE_RSA, B_3DES, T);
0x0016, --p, K_DHE_RSA, B_3DES, T);
add("SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
0x0013, --p, K_DHE_DSS, B_3DES, N);
add("SSL_RSA_WITH_DES_CBC_SHA",
0x0009, --p, K_RSA, B_DES, N);
add("SSL_DHE_RSA_WITH_DES_CBC_SHA",
0x0015, --p, K_DHE_RSA, B_DES, N);
add("SSL_DHE_DSS_WITH_DES_CBC_SHA",
0x0012, --p, K_DHE_DSS, B_DES, N);
add("SSL_RSA_EXPORT_WITH_RC4_40_MD5",
0x0003, --p, K_RSA_EXPORT, B_RC4_40, N);
add("SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
0x0008, --p, K_RSA_EXPORT, B_DES_40, N);
add("SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
0x0014, --p, K_DHE_RSA, B_DES_40, N);
add("SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
0x0011, --p, K_DHE_DSS, B_DES_40, N);
0x0013, --p, K_DHE_DSS, B_3DES, N);
// Renegotiation protection request Signalling Cipher Suite Value (SCSV)
add("TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
0x00ff, --p, K_SCSV, B_NULL, T);
0x00ff, --p, K_SCSV, B_NULL, T);
// Definition of the CipherSuites that are supported but not enabled
// by default.
// They are listed in preference order, preferred first.
p = DEFAULT_SUITES_PRIORITY;
// weak single-DES cipher suites
add("SSL_RSA_WITH_DES_CBC_SHA",
0x0009, --p, K_RSA, B_DES, N, tls12);
add("SSL_DHE_RSA_WITH_DES_CBC_SHA",
0x0015, --p, K_DHE_RSA, B_DES, N, tls12);
add("SSL_DHE_DSS_WITH_DES_CBC_SHA",
0x0012, --p, K_DHE_DSS, B_DES, N, tls12);
// Anonymous key exchange and the NULL ciphers
add("SSL_RSA_WITH_NULL_MD5",
0x0001, --p, K_RSA, B_NULL, N);
0x0001, --p, K_RSA, B_NULL, N);
add("SSL_RSA_WITH_NULL_SHA",
0x0002, --p, K_RSA, B_NULL, N);
0x0002, --p, K_RSA, B_NULL, N);
add("TLS_RSA_WITH_NULL_SHA256",
0x003b, --p, K_RSA, B_NULL, N, max, tls12, P_SHA256);
add("TLS_ECDH_ECDSA_WITH_NULL_SHA",
0xC001, --p, K_ECDH_ECDSA, B_NULL, N);
0xC001, --p, K_ECDH_ECDSA, B_NULL, N);
add("TLS_ECDH_RSA_WITH_NULL_SHA",
0xC00B, --p, K_ECDH_RSA, B_NULL, N);
0xC00B, --p, K_ECDH_RSA, B_NULL, N);
add("TLS_ECDHE_ECDSA_WITH_NULL_SHA",
0xC006, --p, K_ECDHE_ECDSA,B_NULL, N);
0xC006, --p, K_ECDHE_ECDSA, B_NULL, N);
add("TLS_ECDHE_RSA_WITH_NULL_SHA",
0xC010, --p, K_ECDHE_RSA, B_NULL, N);
0xC010, --p, K_ECDHE_RSA, B_NULL, N);
add("SSL_DH_anon_WITH_RC4_128_MD5",
0x0018, --p, K_DH_ANON, B_RC4_128, N);
0x0018, --p, K_DH_ANON, B_RC4_128, N);
add("TLS_DH_anon_WITH_AES_128_CBC_SHA",
0x0034, --p, K_DH_ANON, B_AES_128, N);
0x0034, --p, K_DH_ANON, B_AES_128, N);
add("TLS_DH_anon_WITH_AES_256_CBC_SHA",
0x003a, --p, K_DH_ANON, B_AES_256, N);
0x003a, --p, K_DH_ANON, B_AES_256, N);
add("SSL_DH_anon_WITH_3DES_EDE_CBC_SHA",
0x001b, --p, K_DH_ANON, B_3DES, N);
0x001b, --p, K_DH_ANON, B_3DES, N);
add("SSL_DH_anon_WITH_DES_CBC_SHA",
0x001a, --p, K_DH_ANON, B_DES, N);
0x001a, --p, K_DH_ANON, B_DES, N, tls12);
add("TLS_DH_anon_WITH_AES_128_CBC_SHA256",
0x006c, --p, K_DH_ANON, B_AES_128, N, max, tls12, P_SHA256);
add("TLS_DH_anon_WITH_AES_256_CBC_SHA256",
0x006d, --p, K_DH_ANON, B_AES_256, N, max, tls12, P_SHA256);
add("TLS_ECDH_anon_WITH_RC4_128_SHA",
0xC016, --p, K_ECDH_ANON, B_RC4_128, N);
0xC016, --p, K_ECDH_ANON, B_RC4_128, N);
add("TLS_ECDH_anon_WITH_AES_128_CBC_SHA",
0xC018, --p, K_ECDH_ANON, B_AES_128, T);
0xC018, --p, K_ECDH_ANON, B_AES_128, T);
add("TLS_ECDH_anon_WITH_AES_256_CBC_SHA",
0xC019, --p, K_ECDH_ANON, B_AES_256, T);
0xC019, --p, K_ECDH_ANON, B_AES_256, T);
add("TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA",
0xC017, --p, K_ECDH_ANON, B_3DES, T);
0xC017, --p, K_ECDH_ANON, B_3DES, T);
add("SSL_DH_anon_EXPORT_WITH_RC4_40_MD5",
0x0017, --p, K_DH_ANON, B_RC4_40, N);
0x0017, --p, K_DH_ANON, B_RC4_40, N, tls11);
add("SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
0x0019, --p, K_DH_ANON, B_DES_40, N);
0x0019, --p, K_DH_ANON, B_DES_40, N, tls11);
add("TLS_ECDH_anon_WITH_NULL_SHA",
0xC015, --p, K_ECDH_ANON, B_NULL, N);
0xC015, --p, K_ECDH_ANON, B_NULL, N);
add("SSL_RSA_EXPORT_WITH_RC4_40_MD5",
0x0003, --p, K_RSA_EXPORT, B_RC4_40, N, tls11);
add("SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
0x0008, --p, K_RSA_EXPORT, B_DES_40, N, tls11);
add("SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
0x0014, --p, K_DHE_RSA, B_DES_40, N, tls11);
add("SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
0x0011, --p, K_DHE_DSS, B_DES_40, N, tls11);
// Supported Kerberos ciphersuites from RFC2712
add("TLS_KRB5_WITH_RC4_128_SHA",
0x0020, --p, K_KRB5, B_RC4_128, N);
0x0020, --p, K_KRB5, B_RC4_128, N);
add("TLS_KRB5_WITH_RC4_128_MD5",
0x0024, --p, K_KRB5, B_RC4_128, N);
0x0024, --p, K_KRB5, B_RC4_128, N);
add("TLS_KRB5_WITH_3DES_EDE_CBC_SHA",
0x001f, --p, K_KRB5, B_3DES, N);
0x001f, --p, K_KRB5, B_3DES, N);
add("TLS_KRB5_WITH_3DES_EDE_CBC_MD5",
0x0023, --p, K_KRB5, B_3DES, N);
0x0023, --p, K_KRB5, B_3DES, N);
add("TLS_KRB5_WITH_DES_CBC_SHA",
0x001e, --p, K_KRB5, B_DES, N);
0x001e, --p, K_KRB5, B_DES, N, tls12);
add("TLS_KRB5_WITH_DES_CBC_MD5",
0x0022, --p, K_KRB5, B_DES, N);
0x0022, --p, K_KRB5, B_DES, N, tls12);
add("TLS_KRB5_EXPORT_WITH_RC4_40_SHA",
0x0028, --p, K_KRB5_EXPORT, B_RC4_40, N);
0x0028, --p, K_KRB5_EXPORT, B_RC4_40, N, tls11);
add("TLS_KRB5_EXPORT_WITH_RC4_40_MD5",
0x002b, --p, K_KRB5_EXPORT, B_RC4_40, N);
0x002b, --p, K_KRB5_EXPORT, B_RC4_40, N, tls11);
add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA",
0x0026, --p, K_KRB5_EXPORT, B_DES_40, N);
0x0026, --p, K_KRB5_EXPORT, B_DES_40, N, tls11);
add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5",
0x0029, --p, K_KRB5_EXPORT, B_DES_40, N);
0x0029, --p, K_KRB5_EXPORT, B_DES_40, N, tls11);
/*
* Other values from the TLS Cipher Suite Registry, as of August 2010.
*
* http://www.iana.org/assignments/tls-parameters/tls-parameters.xml
*
* Range Registration Procedures Notes
* 000-191 Standards Action Refers to value of first byte
* 192-254 Specification Required Refers to value of first byte
* 255 Reserved for Private Use Refers to value of first byte
*/
// Register the names of a few additional CipherSuites.
// Makes them show up as names instead of numbers in
// the debug output.
// remaining unsupported ciphersuites defined in RFC2246.
add("SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5", 0x0006);
add("SSL_RSA_WITH_IDEA_CBC_SHA", 0x0007);
add("SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA", 0x000b);
add("SSL_DH_DSS_WITH_DES_CBC_SHA", 0x000c);
add("SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA", 0x000d);
add("SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA", 0x000e);
add("SSL_DH_RSA_WITH_DES_CBC_SHA", 0x000f);
add("SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA", 0x0010);
add("SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5", 0x0006);
add("SSL_RSA_WITH_IDEA_CBC_SHA", 0x0007);
add("SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA", 0x000b);
add("SSL_DH_DSS_WITH_DES_CBC_SHA", 0x000c);
add("SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA", 0x000d);
add("SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA", 0x000e);
add("SSL_DH_RSA_WITH_DES_CBC_SHA", 0x000f);
add("SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA", 0x0010);
// SSL 3.0 Fortezza ciphersuites
add("SSL_FORTEZZA_DMS_WITH_NULL_SHA", 0x001c);
add("SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA", 0x001d);
add("SSL_FORTEZZA_DMS_WITH_NULL_SHA", 0x001c);
add("SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA", 0x001d);
// 1024/56 bit exportable ciphersuites from expired internet draft
add("SSL_RSA_EXPORT1024_WITH_DES_CBC_SHA", 0x0062);
add("SSL_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA", 0x0063);
add("SSL_RSA_EXPORT1024_WITH_RC4_56_SHA", 0x0064);
add("SSL_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA", 0x0065);
add("SSL_DHE_DSS_WITH_RC4_128_SHA", 0x0066);
add("SSL_RSA_EXPORT1024_WITH_DES_CBC_SHA", 0x0062);
add("SSL_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA", 0x0063);
add("SSL_RSA_EXPORT1024_WITH_RC4_56_SHA", 0x0064);
add("SSL_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA", 0x0065);
add("SSL_DHE_DSS_WITH_RC4_128_SHA", 0x0066);
// Netscape old and new SSL 3.0 FIPS ciphersuites
// see http://www.mozilla.org/projects/security/pki/nss/ssl/fips-ssl-ciphersuites.html
add("NETSCAPE_RSA_FIPS_WITH_3DES_EDE_CBC_SHA", 0xffe0);
add("NETSCAPE_RSA_FIPS_WITH_DES_CBC_SHA", 0xffe1);
add("SSL_RSA_FIPS_WITH_DES_CBC_SHA", 0xfefe);
add("SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA", 0xfeff);
add("NETSCAPE_RSA_FIPS_WITH_3DES_EDE_CBC_SHA", 0xffe0);
add("NETSCAPE_RSA_FIPS_WITH_DES_CBC_SHA", 0xffe1);
add("SSL_RSA_FIPS_WITH_DES_CBC_SHA", 0xfefe);
add("SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA", 0xfeff);
// Unsupported Kerberos cipher suites from RFC 2712
add("TLS_KRB5_WITH_IDEA_CBC_SHA", 0x0021);
add("TLS_KRB5_WITH_IDEA_CBC_MD5", 0x0025);
add("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA", 0x0027);
add("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5", 0x002a);
add("TLS_KRB5_WITH_IDEA_CBC_SHA", 0x0021);
add("TLS_KRB5_WITH_IDEA_CBC_MD5", 0x0025);
add("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA", 0x0027);
add("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5", 0x002a);
// Unsupported cipher suites from RFC 4162
add("TLS_RSA_WITH_SEED_CBC_SHA", 0x0096);
add("TLS_DH_DSS_WITH_SEED_CBC_SHA", 0x0097);
add("TLS_DH_RSA_WITH_SEED_CBC_SHA", 0x0098);
add("TLS_DHE_DSS_WITH_SEED_CBC_SHA", 0x0099);
add("TLS_DHE_RSA_WITH_SEED_CBC_SHA", 0x009a);
add("TLS_DH_anon_WITH_SEED_CBC_SHA", 0x009b);
// Unsupported cipher suites from RFC 4279
add("TLS_PSK_WITH_RC4_128_SHA", 0x008a);
add("TLS_PSK_WITH_3DES_EDE_CBC_SHA", 0x008b);
add("TLS_PSK_WITH_AES_128_CBC_SHA", 0x008c);
add("TLS_PSK_WITH_AES_256_CBC_SHA", 0x008d);
add("TLS_DHE_PSK_WITH_RC4_128_SHA", 0x008e);
add("TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA", 0x008f);
add("TLS_DHE_PSK_WITH_AES_128_CBC_SHA", 0x0090);
add("TLS_DHE_PSK_WITH_AES_256_CBC_SHA", 0x0091);
add("TLS_RSA_PSK_WITH_RC4_128_SHA", 0x0092);
add("TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA", 0x0093);
add("TLS_RSA_PSK_WITH_AES_128_CBC_SHA", 0x0094);
add("TLS_RSA_PSK_WITH_AES_256_CBC_SHA", 0x0095);
// Unsupported cipher suites from RFC 4785
add("TLS_PSK_WITH_NULL_SHA", 0x002c);
add("TLS_DHE_PSK_WITH_NULL_SHA", 0x002d);
add("TLS_RSA_PSK_WITH_NULL_SHA", 0x002e);
// Unsupported cipher suites from RFC 5246
add("TLS_DH_DSS_WITH_AES_128_CBC_SHA", 0x0030);
add("TLS_DH_RSA_WITH_AES_128_CBC_SHA", 0x0031);
add("TLS_DH_DSS_WITH_AES_256_CBC_SHA", 0x0036);
add("TLS_DH_RSA_WITH_AES_256_CBC_SHA", 0x0037);
add("TLS_DH_DSS_WITH_AES_128_CBC_SHA256", 0x003e);
add("TLS_DH_RSA_WITH_AES_128_CBC_SHA256", 0x003f);
add("TLS_DH_DSS_WITH_AES_256_CBC_SHA256", 0x0068);
add("TLS_DH_RSA_WITH_AES_256_CBC_SHA256", 0x0069);
// Unsupported cipher suites from RFC 5288
add("TLS_RSA_WITH_AES_128_GCM_SHA256", 0x009c);
add("TLS_RSA_WITH_AES_256_GCM_SHA384", 0x009d);
add("TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", 0x009e);
add("TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", 0x009f);
add("TLS_DH_RSA_WITH_AES_128_GCM_SHA256", 0x00a0);
add("TLS_DH_RSA_WITH_AES_256_GCM_SHA384", 0x00a1);
add("TLS_DHE_DSS_WITH_AES_128_GCM_SHA256", 0x00a2);
add("TLS_DHE_DSS_WITH_AES_256_GCM_SHA384", 0x00a3);
add("TLS_DH_DSS_WITH_AES_128_GCM_SHA256", 0x00a4);
add("TLS_DH_DSS_WITH_AES_256_GCM_SHA384", 0x00a5);
add("TLS_DH_anon_WITH_AES_128_GCM_SHA256", 0x00a6);
add("TLS_DH_anon_WITH_AES_256_GCM_SHA384", 0x00a7);
// Unsupported cipher suites from RFC 5487
add("TLS_PSK_WITH_AES_128_GCM_SHA256", 0x00a8);
add("TLS_PSK_WITH_AES_256_GCM_SHA384", 0x00a9);
add("TLS_DHE_PSK_WITH_AES_128_GCM_SHA256", 0x00aa);
add("TLS_DHE_PSK_WITH_AES_256_GCM_SHA384", 0x00ab);
add("TLS_RSA_PSK_WITH_AES_128_GCM_SHA256", 0x00ac);
add("TLS_RSA_PSK_WITH_AES_256_GCM_SHA384", 0x00ad);
add("TLS_PSK_WITH_AES_128_CBC_SHA256", 0x00ae);
add("TLS_PSK_WITH_AES_256_CBC_SHA384", 0x00af);
add("TLS_PSK_WITH_NULL_SHA256", 0x00b0);
add("TLS_PSK_WITH_NULL_SHA384", 0x00b1);
add("TLS_DHE_PSK_WITH_AES_128_CBC_SHA256", 0x00b2);
add("TLS_DHE_PSK_WITH_AES_256_CBC_SHA384", 0x00b3);
add("TLS_DHE_PSK_WITH_NULL_SHA256", 0x00b4);
add("TLS_DHE_PSK_WITH_NULL_SHA384", 0x00b5);
add("TLS_RSA_PSK_WITH_AES_128_CBC_SHA256", 0x00b6);
add("TLS_RSA_PSK_WITH_AES_256_CBC_SHA384", 0x00b7);
add("TLS_RSA_PSK_WITH_NULL_SHA256", 0x00b8);
add("TLS_RSA_PSK_WITH_NULL_SHA384", 0x00b9);
// Unsupported cipher suites from RFC 5932
add("TLS_RSA_WITH_CAMELLIA_128_CBC_SHA", 0x0041);
add("TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA", 0x0042);
add("TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA", 0x0043);
add("TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA", 0x0044);
add("TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA", 0x0045);
add("TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA", 0x0046);
add("TLS_RSA_WITH_CAMELLIA_256_CBC_SHA", 0x0084);
add("TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA", 0x0085);
add("TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA", 0x0086);
add("TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA", 0x0087);
add("TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA", 0x0088);
add("TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA", 0x0089);
add("TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256", 0x00ba);
add("TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256", 0x00bb);
add("TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256", 0x00bc);
add("TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256", 0x00bd);
add("TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256", 0x00be);
add("TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256", 0x00bf);
add("TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256", 0x00c0);
add("TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256", 0x00c1);
add("TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256", 0x00c2);
add("TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256", 0x00c3);
add("TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256", 0x00c4);
add("TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256", 0x00c5);
// Unsupported cipher suites from RFC 5054
add("TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA", 0xc01a);
add("TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA", 0xc01b);
add("TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA", 0xc01c);
add("TLS_SRP_SHA_WITH_AES_128_CBC_SHA", 0xc01d);
add("TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA", 0xc01e);
add("TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA", 0xc01f);
add("TLS_SRP_SHA_WITH_AES_256_CBC_SHA", 0xc020);
add("TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA", 0xc021);
add("TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA", 0xc022);
// Unsupported cipher suites from RFC 5289
add("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 0xc02b);
add("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 0xc02c);
add("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", 0xc02d);
add("TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384", 0xc02e);
add("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 0xc02f);
add("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 0xc030);
add("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", 0xc031);
add("TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384", 0xc032);
// Unsupported cipher suites from RFC 5489
add("TLS_ECDHE_PSK_WITH_RC4_128_SHA", 0xc033);
add("TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA", 0xc034);
add("TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA", 0xc035);
add("TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA", 0xc036);
add("TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256", 0xc037);
add("TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384", 0xc038);
add("TLS_ECDHE_PSK_WITH_NULL_SHA", 0xc039);
add("TLS_ECDHE_PSK_WITH_NULL_SHA256", 0xc03a);
add("TLS_ECDHE_PSK_WITH_NULL_SHA384", 0xc03b);
}
// ciphersuite SSL_NULL_WITH_NULL_NULL

View File

@ -23,7 +23,6 @@
* questions.
*/
package sun.security.ssl;
import java.io.*;
@ -45,12 +44,12 @@ import javax.net.ssl.*;
import javax.security.auth.Subject;
import com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager;
import sun.security.ssl.HandshakeMessage.*;
import sun.security.ssl.CipherSuite.*;
import static sun.security.ssl.CipherSuite.KeyExchange.*;
import sun.net.util.IPAddressUtil;
/**
* ClientHandshaker does the protocol handshaking from the point
* of view of a client. It is driven asychronously by handshake messages
@ -89,6 +88,10 @@ final class ClientHandshaker extends Handshaker {
*/
private ProtocolVersion maxProtocolVersion;
// To switch off the SNI extension.
private final static boolean enableSNIExtension =
Debug.getBooleanProperty("jsse.enableSNIExtension", true);
/*
* Constructors
*/
@ -190,7 +193,8 @@ final class ClientHandshaker extends Handshaker {
}
break;
case K_DH_ANON:
this.serverKeyExchange(new DH_ServerKeyExchange(input));
this.serverKeyExchange(new DH_ServerKeyExchange(
input, protocolVersion));
break;
case K_DHE_DSS:
case K_DHE_RSA:
@ -198,7 +202,8 @@ final class ClientHandshaker extends Handshaker {
this.serverKeyExchange(new DH_ServerKeyExchange(
input, serverKey,
clnt_random.random_bytes, svr_random.random_bytes,
messageLen));
messageLen,
localSupportedSignAlgs, protocolVersion));
} catch (GeneralSecurityException e) {
throwSSLException("Server key", e);
}
@ -209,7 +214,8 @@ final class ClientHandshaker extends Handshaker {
try {
this.serverKeyExchange(new ECDH_ServerKeyExchange
(input, serverKey, clnt_random.random_bytes,
svr_random.random_bytes));
svr_random.random_bytes,
localSupportedSignAlgs, protocolVersion));
} catch (GeneralSecurityException e) {
throwSSLException("Server key", e);
}
@ -219,8 +225,9 @@ final class ClientHandshaker extends Handshaker {
case K_DH_DSS:
case K_ECDH_ECDSA:
case K_ECDH_RSA:
throw new SSLProtocolException("Protocol violation: server sent"
+ " a server key exchange message for key exchange " + keyExchange);
throw new SSLProtocolException(
"Protocol violation: server sent a server key exchange"
+ "message for key exchange " + keyExchange);
case K_KRB5:
case K_KRB5_EXPORT:
throw new SSLProtocolException(
@ -243,10 +250,32 @@ final class ClientHandshaker extends Handshaker {
"Client certificate requested for "+
"kerberos cipher suite.");
}
certRequest = new CertificateRequest(input);
certRequest = new CertificateRequest(input, protocolVersion);
if (debug != null && Debug.isOn("handshake")) {
certRequest.print(System.out);
}
if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
Collection<SignatureAndHashAlgorithm> peerSignAlgs =
certRequest.getSignAlgorithms();
if (peerSignAlgs == null || peerSignAlgs.isEmpty()) {
throw new SSLHandshakeException(
"No peer supported signature algorithms");
}
Collection<SignatureAndHashAlgorithm> supportedPeerSignAlgs =
SignatureAndHashAlgorithm.getSupportedAlgorithms(
peerSignAlgs);
if (supportedPeerSignAlgs.isEmpty()) {
throw new SSLHandshakeException(
"No supported signature and hash algorithm in common");
}
setPeerSupportedSignAlgs(supportedPeerSignAlgs);
session.setPeerSupportedSignatureAlgorithms(
supportedPeerSignAlgs);
}
break;
case HandshakeMessage.ht_server_hello_done:
@ -254,7 +283,8 @@ final class ClientHandshaker extends Handshaker {
break;
case HandshakeMessage.ht_finished:
this.serverFinished(new Finished(protocolVersion, input));
this.serverFinished(
new Finished(protocolVersion, input, cipherSuite));
break;
default:
@ -345,11 +375,15 @@ final class ClientHandshaker extends Handshaker {
// check if the server selected protocol version is OK for us
ProtocolVersion mesgVersion = mesg.protocolVersion;
if (enabledProtocols.contains(mesgVersion) == false) {
throw new SSLHandshakeException
("Server chose unsupported or disabled protocol: " + mesgVersion);
if (!isNegotiable(mesgVersion)) {
throw new SSLHandshakeException(
"Server chose unsupported or disabled protocol: " +
mesgVersion);
}
handshakeHash.protocolDetermined(
mesgVersion.v >= ProtocolVersion.TLS12.v);
// Set protocolVersion and propagate to SSLSocket and the
// Handshake streams
setVersion(mesgVersion);
@ -425,10 +459,13 @@ final class ClientHandshaker extends Handshaker {
if (isNegotiable(mesg.cipherSuite) == false) {
fatalSE(Alerts.alert_illegal_parameter,
"Server selected improper ciphersuite " + cipherSuite);
"Server selected improper ciphersuite " + mesg.cipherSuite);
}
setCipherSuite(mesg.cipherSuite);
if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
handshakeHash.setFinishedAlg(cipherSuite.prfAlg.getPRFHashAlg());
}
if (mesg.compression_method != 0) {
fatalSE(Alerts.alert_illegal_parameter,
@ -507,7 +544,6 @@ final class ClientHandshaker extends Handshaker {
if (debug != null && Debug.isOn("session")) {
System.out.println("%% Server resumed " + session);
}
return;
} else {
// we wanted to resume, but the server refused
session = null;
@ -518,11 +554,21 @@ final class ClientHandshaker extends Handshaker {
}
}
if (resumingSession && session != null) {
if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
handshakeHash.setCertificateVerifyAlg(null);
}
setHandshakeSessionSE(session);
return;
}
// check extensions
for (HelloExtension ext : mesg.extensions.list()) {
ExtensionType type = ext.type;
if ((type != ExtensionType.EXT_ELLIPTIC_CURVES)
&& (type != ExtensionType.EXT_EC_POINT_FORMATS)
&& (type != ExtensionType.EXT_SERVER_NAME)
&& (type != ExtensionType.EXT_RENEGOTIATION_INFO)) {
fatalSE(Alerts.alert_unsupported_extension,
"Server sent an unsupported extension: " + type);
@ -531,7 +577,9 @@ final class ClientHandshaker extends Handshaker {
// Create a new session, we need to do the full handshake
session = new SSLSessionImpl(protocolVersion, cipherSuite,
getLocalSupportedSignAlgs(),
mesg.sessionId, getHostSE(), getPortSE());
setHandshakeSessionSE(session);
if (debug != null && Debug.isOn("handshake")) {
System.out.println("** " + cipherSuite);
}
@ -567,11 +615,13 @@ final class ClientHandshaker extends Handshaker {
if (debug != null && Debug.isOn("handshake")) {
mesg.print(System.out);
}
dh = new DHCrypt(mesg.getModulus(), mesg.getBase(), sslContext.getSecureRandom());
dh = new DHCrypt(mesg.getModulus(), mesg.getBase(),
sslContext.getSecureRandom());
serverDH = mesg.getServerPublicKey();
}
private void serverKeyExchange(ECDH_ServerKeyExchange mesg) throws IOException {
private void serverKeyExchange(ECDH_ServerKeyExchange mesg)
throws IOException {
if (debug != null && Debug.isOn("handshake")) {
mesg.print(System.out);
}
@ -665,9 +715,13 @@ final class ClientHandshaker extends Handshaker {
PublicKey publicKey = certs[0].getPublicKey();
// for EC, make sure we use a supported named curve
if (publicKey instanceof ECPublicKey) {
ECParameterSpec params = ((ECPublicKey)publicKey).getParams();
int index = SupportedEllipticCurvesExtension.getCurveIndex(params);
if (!SupportedEllipticCurvesExtension.isSupported(index)) {
ECParameterSpec params =
((ECPublicKey)publicKey).getParams();
int index =
SupportedEllipticCurvesExtension.getCurveIndex(
params);
if (!SupportedEllipticCurvesExtension.isSupported(
index)) {
publicKey = null;
}
}
@ -813,8 +867,9 @@ final class ClientHandshaker extends Handshaker {
throw new IOException("Hostname is required" +
" to use Kerberos cipher suites");
}
KerberosClientKeyExchange kerberosMsg = new KerberosClientKeyExchange
(hostname, isLoopbackSE(), getAccSE(), protocolVersion,
KerberosClientKeyExchange kerberosMsg =
new KerberosClientKeyExchange(
hostname, isLoopbackSE(), getAccSE(), protocolVersion,
sslContext.getSecureRandom());
// Record the principals involved in exchange
session.setPeerPrincipal(kerberosMsg.getPeerPrincipal());
@ -861,7 +916,8 @@ final class ClientHandshaker extends Handshaker {
case K_KRB5_EXPORT:
byte[] secretBytes =
((KerberosClientKeyExchange)m2).getUnencryptedPreMasterSecret();
preMasterSecret = new SecretKeySpec(secretBytes, "TlsPremasterSecret");
preMasterSecret = new SecretKeySpec(secretBytes,
"TlsPremasterSecret");
break;
case K_DHE_RSA:
case K_DHE_DSS:
@ -878,7 +934,8 @@ final class ClientHandshaker extends Handshaker {
preMasterSecret = ecdh.getAgreedSecret(serverKey);
break;
default:
throw new IOException("Internal error: unknown key exchange " + keyExchange);
throw new IOException("Internal error: unknown key exchange "
+ keyExchange);
}
calculateKeys(preMasterSecret, null);
@ -896,9 +953,32 @@ final class ClientHandshaker extends Handshaker {
if (signingKey != null) {
CertificateVerify m3;
try {
SignatureAndHashAlgorithm preferableSignatureAlgorithm = null;
if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
preferableSignatureAlgorithm =
SignatureAndHashAlgorithm.getPreferableAlgorithm(
peerSupportedSignAlgs, signingKey.getAlgorithm());
if (preferableSignatureAlgorithm == null) {
throw new SSLHandshakeException(
"No supported signature algorithm");
}
String hashAlg =
SignatureAndHashAlgorithm.getHashAlgorithmName(
preferableSignatureAlgorithm);
if (hashAlg == null || hashAlg.length() == 0) {
throw new SSLHandshakeException(
"No supported hash algorithm");
}
handshakeHash.setCertificateVerifyAlg(hashAlg);
}
m3 = new CertificateVerify(protocolVersion, handshakeHash,
signingKey, session.getMasterSecret(),
sslContext.getSecureRandom());
sslContext.getSecureRandom(),
preferableSignatureAlgorithm);
} catch (GeneralSecurityException e) {
fatalSE(Alerts.alert_handshake_failure,
"Error signing certificate verify", e);
@ -910,6 +990,10 @@ final class ClientHandshaker extends Handshaker {
}
m3.write(output);
output.doHashes();
} else {
if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
handshakeHash.setCertificateVerifyAlg(null);
}
}
/*
@ -930,8 +1014,8 @@ final class ClientHandshaker extends Handshaker {
mesg.print(System.out);
}
boolean verified = mesg.verify(protocolVersion, handshakeHash,
Finished.SERVER, session.getMasterSecret());
boolean verified = mesg.verify(handshakeHash, Finished.SERVER,
session.getMasterSecret());
if (!verified) {
fatalSE(Alerts.alert_illegal_parameter,
@ -988,7 +1072,7 @@ final class ClientHandshaker extends Handshaker {
private void sendChangeCipherAndFinish(boolean finishedTag)
throws IOException {
Finished mesg = new Finished(protocolVersion, handshakeHash,
Finished.CLIENT, session.getMasterSecret());
Finished.CLIENT, session.getMasterSecret(), cipherSuite);
/*
* Send the change_cipher_spec message, then the Finished message
@ -1022,7 +1106,7 @@ final class ClientHandshaker extends Handshaker {
SessionId sessionId = SSLSessionImpl.nullSession.getSessionId();
// a list of cipher suites sent by the client
CipherSuiteList cipherSuites = enabledCipherSuites;
CipherSuiteList cipherSuites = getActiveCipherSuites();
// set the max protocol version this client is supporting.
maxProtocolVersion = protocolVersion;
@ -1057,8 +1141,7 @@ final class ClientHandshaker extends Handshaker {
session = null;
}
if ((session != null) &&
(enabledProtocols.contains(sessionVersion) == false)) {
if ((session != null) && !isNegotiable(sessionVersion)) {
if (debug != null && Debug.isOn("session")) {
System.out.println("%% can't resume, protocol disabled");
}
@ -1088,7 +1171,7 @@ final class ClientHandshaker extends Handshaker {
*/
if (!enableNewSession) {
if (session == null) {
throw new SSLException(
throw new SSLHandshakeException(
"Can't reuse existing SSL client session");
}
@ -1105,7 +1188,7 @@ final class ClientHandshaker extends Handshaker {
}
if (session == null && !enableNewSession) {
throw new SSLException("No existing session to resume");
throw new SSLHandshakeException("No existing session to resume");
}
// exclude SCSV for secure renegotiation
@ -1131,14 +1214,52 @@ final class ClientHandshaker extends Handshaker {
}
if (!negotiable) {
throw new SSLException("No negotiable cipher suite");
throw new SSLHandshakeException("No negotiable cipher suite");
}
// Not a TLS1.2+ handshake
// For SSLv2Hello, HandshakeHash.reset() will be called, so we
// cannot call HandshakeHash.protocolDetermined() here. As it does
// not follow the spec that HandshakeHash.reset() can be only be
// called before protocolDetermined.
// if (maxProtocolVersion.v < ProtocolVersion.TLS12.v) {
// handshakeHash.protocolDetermined(false);
// }
// create the ClientHello message
ClientHello clientHelloMessage = new ClientHello(
sslContext.getSecureRandom(), maxProtocolVersion,
sessionId, cipherSuites);
// add signature_algorithm extension
if (maxProtocolVersion.v >= ProtocolVersion.TLS12.v) {
// we will always send the signature_algorithm extension
Collection<SignatureAndHashAlgorithm> localSignAlgs =
getLocalSupportedSignAlgs();
if (localSignAlgs.isEmpty()) {
throw new SSLHandshakeException(
"No supported signature algorithm");
}
clientHelloMessage.addSignatureAlgorithmsExtension(localSignAlgs);
}
// add server_name extension
if (enableSNIExtension) {
// We cannot use the hostname resolved from name services. For
// virtual hosting, multiple hostnames may be bound to the same IP
// address, so the hostname resolved from name services is not
// reliable.
String hostname = getRawHostnameSE();
// we only allow FQDN
if (hostname != null && hostname.indexOf('.') > 0 &&
!IPAddressUtil.isIPv4LiteralAddress(hostname) &&
!IPAddressUtil.isIPv6LiteralAddress(hostname)) {
clientHelloMessage.addServerNameIndicationExtension(hostname);
}
}
// reset the client random cookie
clnt_random = clientHelloMessage.clnt_random;
@ -1194,26 +1315,23 @@ final class ClientHandshaker extends Handshaker {
keyExchangeString = keyExchange.name;
}
String identificator = getHostnameVerificationSE();
if (tm instanceof X509ExtendedTrustManager) {
((X509ExtendedTrustManager)tm).checkServerTrusted(
(peerCerts != null ?
peerCerts.clone() :
null),
if (conn != null) {
((X509ExtendedTrustManager)tm).checkServerTrusted(
peerCerts.clone(),
keyExchangeString,
getHostSE(),
identificator);
} else {
if (identificator != null) {
throw new RuntimeException(
"trust manager does not support peer identification");
conn);
} else {
((X509ExtendedTrustManager)tm).checkServerTrusted(
peerCerts.clone(),
keyExchangeString,
engine);
}
tm.checkServerTrusted(
(peerCerts != null ?
peerCerts.clone() :
peerCerts),
keyExchangeString);
} else {
// Unlikely to happen, because we have wrapped the old
// X509TrustManager with the new X509ExtendedTrustManager.
throw new CertificateException(
"Improper X509TrustManager implementation");
}
} catch (CertificateException e) {
// This will throw an exception, so include the original error.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -27,6 +27,7 @@ package sun.security.ssl;
import java.io.PrintStream;
import java.security.AccessController;
import java.util.Locale;
import sun.security.action.GetPropertyAction;
@ -44,7 +45,7 @@ public class Debug {
static {
args = java.security.AccessController.doPrivileged(
new GetPropertyAction("javax.net.debug", ""));
args = args.toLowerCase();
args = args.toLowerCase(Locale.ENGLISH);
if (args.equals("help")) {
Help();
}
@ -114,7 +115,7 @@ public class Debug {
return false;
} else {
int n = 0;
option = option.toLowerCase();
option = option.toLowerCase(Locale.ENGLISH);
if (args.indexOf("all") != -1) {
return true;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -26,7 +26,13 @@
package sun.security.ssl;
import java.io.ByteArrayOutputStream;
import java.security.*;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Set;
/**
* Abstraction for the SSL/TLS hash of all handshake messages that is
@ -36,51 +42,161 @@ import java.security.*;
*
* This class transparently deals with cloneable and non-cloneable digests.
*
* This class now supports TLS 1.2 also. The key difference for TLS 1.2
* is that you cannot determine the hash algorithms for CertificateVerify
* at a early stage. On the other hand, it's simpler than TLS 1.1 (and earlier)
* that there is no messy MD5+SHA1 digests.
*
* You need to obey these conventions when using this class:
*
* 1. protocolDetermined(boolean isTLS12) should be called when the negotiated
* protocol version is determined.
*
* 2. Before protocolDetermined() is called, only update(), reset(),
* restrictCertificateVerifyAlgs(), setFinishedAlg(), and
* setCertificateVerifyAlg() can be called.
*
* 3. After protocolDetermined(*) is called. reset() cannot be called.
*
* 4. After protocolDetermined(false) is called, getFinishedHash() and
* getCertificateVerifyHash() cannot be called. After protocolDetermined(true)
* is called, getMD5Clone() and getSHAClone() cannot be called.
*
* 5. getMD5Clone() and getSHAClone() can only be called after
* protocolDetermined(false) is called.
*
* 6. getFinishedHash() and getCertificateVerifyHash() can only be called after
* all protocolDetermined(true), setCertificateVerifyAlg() and setFinishedAlg()
* have been called. If a CertificateVerify message is to be used, call
* setCertificateVerifyAlg() with the hash algorithm as the argument.
* Otherwise, you still must call setCertificateVerifyAlg(null) before
* calculating any hash value.
*
* Suggestions: Call protocolDetermined(), restrictCertificateVerifyAlgs(),
* setFinishedAlg(), and setCertificateVerifyAlg() as early as possible.
*
* Example:
* <pre>
* HandshakeHash hh = new HandshakeHash(...)
* hh.update(clientHelloBytes);
* hh.setFinishedAlg("SHA-256");
* hh.update(serverHelloBytes);
* ...
* hh.setCertificateVerifyAlg("SHA-384");
* hh.update(CertificateVerifyBytes);
* byte[] cvDigest = hh.getCertificateVerifyHash();
* ...
* hh.update(finished1);
* byte[] finDigest1 = hh.getFinishedHash();
* hh.update(finished2);
* byte[] finDigest2 = hh.getFinishedHash();
* </pre>
* If no CertificateVerify message is to be used, call
* <pre>
* hh.setCertificateVerifyAlg(null);
* </pre>
* This call can be made once you are certain that this message
* will never be used.
*/
final class HandshakeHash {
private final MessageDigest md5, sha;
// Common
// -1: unknown
// 1: <=TLS 1.1
// 2: TLS 1.2
private int version = -1;
private ByteArrayOutputStream data = new ByteArrayOutputStream();
private final boolean isServer;
// For TLS 1.1
private MessageDigest md5, sha;
private final int clonesNeeded; // needs to be saved for later use
// For TLS 1.2
// cvAlgDetermined == true means setCertificateVerifyAlg() is called
private boolean cvAlgDetermined = false;
private String cvAlg;
private MessageDigest finMD;
/**
* Create a new HandshakeHash. needCertificateVerify indicates whether
* a hash for the certificate verify message is required.
* a hash for the certificate verify message is required. The argument
* algs is a set of all possible hash algorithms that might be used in
* TLS 1.2. If the caller is sure that TLS 1.2 won't be used or no
* CertificateVerify message will be used, leave it null or empty.
*/
HandshakeHash(boolean needCertificateVerify) {
int n = needCertificateVerify ? 3 : 2;
try {
md5 = CloneableDigest.getDigest("MD5", n);
sha = CloneableDigest.getDigest("SHA", n);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException
("Algorithm MD5 or SHA not available", e);
}
}
void update(byte b) {
md5.update(b);
sha.update(b);
HandshakeHash(boolean isServer, boolean needCertificateVerify,
Set<String> algs) {
this.isServer = isServer;
clonesNeeded = needCertificateVerify ? 3 : 2;
}
void update(byte[] b, int offset, int len) {
md5.update(b, offset, len);
sha.update(b, offset, len);
switch (version) {
case 1:
md5.update(b, offset, len);
sha.update(b, offset, len);
break;
default:
if (finMD != null) {
finMD.update(b, offset, len);
}
data.write(b, offset, len);
break;
}
}
/**
* Reset the remaining digests. Note this does *not* reset the numbe of
* Reset the remaining digests. Note this does *not* reset the number of
* digest clones that can be obtained. Digests that have already been
* cloned and are gone remain gone.
*/
void reset() {
md5.reset();
sha.reset();
if (version != -1) {
throw new RuntimeException(
"reset() can be only be called before protocolDetermined");
}
data.reset();
}
void protocolDetermined(boolean isTLS12) {
// Do not set again, will ignore
if (version != -1) return;
version = isTLS12 ? 2 : 1;
switch (version) {
case 1:
// initiate md5, sha and call update on saved array
try {
md5 = CloneableDigest.getDigest("MD5", clonesNeeded);
sha = CloneableDigest.getDigest("SHA", clonesNeeded);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException
("Algorithm MD5 or SHA not available", e);
}
byte[] bytes = data.toByteArray();
update(bytes, 0, bytes.length);
break;
case 2:
break;
}
}
/////////////////////////////////////////////////////////////
// Below are old methods for pre-TLS 1.1
/////////////////////////////////////////////////////////////
/**
* Return a new MD5 digest updated with all data hashed so far.
*/
MessageDigest getMD5Clone() {
if (version != 1) {
throw new RuntimeException(
"getMD5Clone() can be only be called for TLS 1.1");
}
return cloneDigest(md5);
}
@ -88,6 +204,10 @@ final class HandshakeHash {
* Return a new SHA digest updated with all data hashed so far.
*/
MessageDigest getSHAClone() {
if (version != 1) {
throw new RuntimeException(
"getSHAClone() can be only be called for TLS 1.1");
}
return cloneDigest(sha);
}
@ -100,6 +220,181 @@ final class HandshakeHash {
}
}
/////////////////////////////////////////////////////////////
// Below are new methods for TLS 1.2
/////////////////////////////////////////////////////////////
private static String normalizeAlgName(String alg) {
alg = alg.toUpperCase(Locale.US);
if (alg.startsWith("SHA")) {
if (alg.length() == 3) {
return "SHA-1";
}
if (alg.charAt(3) != '-') {
return "SHA-" + alg.substring(3);
}
}
return alg;
}
/**
* Specifies the hash algorithm used in Finished. This should be called
* based in info in ServerHello.
* Can be called multiple times.
*/
void setFinishedAlg(String s) {
if (s == null) {
throw new RuntimeException(
"setFinishedAlg's argument cannot be null");
}
// Can be called multiple times, but only set once
if (finMD != null) return;
try {
finMD = CloneableDigest.getDigest(normalizeAlgName(s), 2);
} catch (NoSuchAlgorithmException e) {
throw new Error(e);
}
finMD.update(data.toByteArray());
}
/**
* Restricts the possible algorithms for the CertificateVerify. Called by
* the server based on info in CertRequest. The argument must be a subset
* of the argument with the same name in the constructor. The method can be
* called multiple times. If the caller is sure that no CertificateVerify
* message will be used, leave this argument null or empty.
*/
void restrictCertificateVerifyAlgs(Set<String> algs) {
if (version == 1) {
throw new RuntimeException(
"setCertificateVerifyAlg() cannot be called for TLS 1.1");
}
// Not used yet
}
/**
* Specifies the hash algorithm used in CertificateVerify.
* Can be called multiple times.
*/
void setCertificateVerifyAlg(String s) {
// Can be called multiple times, but only set once
if (cvAlgDetermined) return;
cvAlg = s == null ? null : normalizeAlgName(s);
cvAlgDetermined = true;
}
byte[] getAllHandshakeMessages() {
return data.toByteArray();
}
/**
* Calculates the hash in the CertificateVerify. Must be called right
* after setCertificateVerifyAlg()
*/
/*byte[] getCertificateVerifyHash() {
throw new Error("Do not call getCertificateVerifyHash()");
}*/
/**
* Calculates the hash in Finished. Must be called after setFinishedAlg().
* This method can be called twice, for Finished messages of the server
* side and client side respectively.
*/
byte[] getFinishedHash() {
try {
return cloneDigest(finMD).digest();
} catch (Exception e) {
throw new Error("BAD");
}
}
////////////////////////////////////////////////////////////////
// TEST
////////////////////////////////////////////////////////////////
public static void main(String[] args) throws Exception {
Test t = new Test();
t.test(null, "SHA-256");
t.test("", "SHA-256");
t.test("SHA-1", "SHA-256");
t.test("SHA-256", "SHA-256");
t.test("SHA-384", "SHA-256");
t.test("SHA-512", "SHA-256");
t.testSame("sha", "SHA-1");
t.testSame("SHA", "SHA-1");
t.testSame("SHA1", "SHA-1");
t.testSame("SHA-1", "SHA-1");
t.testSame("SHA256", "SHA-256");
t.testSame("SHA-256", "SHA-256");
}
static class Test {
void update(HandshakeHash hh, String s) {
hh.update(s.getBytes(), 0, s.length());
}
static byte[] digest(String alg, String data) throws Exception {
return MessageDigest.getInstance(alg).digest(data.getBytes());
}
static void equals(byte[] b1, byte[] b2) {
if (!Arrays.equals(b1, b2)) {
throw new RuntimeException("Bad");
}
}
void testSame(String a, String a2) {
System.out.println("testSame: " + a + " " + a2);
if (!HandshakeHash.normalizeAlgName(a).equals(a2)) {
throw new RuntimeException("Bad");
}
}
/**
* Special convention: when it's certain that CV will not be used at the
* very beginning, use null as cvAlg. If known at a late stage, use "".
*/
void test(String cvAlg, String finAlg) throws Exception {
System.out.println("test: " + cvAlg + " " + finAlg);
byte[] cv = null, f1, f2;
HandshakeHash hh = new HandshakeHash(true, true, null);
if (cvAlg == null) {
hh.setCertificateVerifyAlg(cvAlg);
}
update(hh, "ClientHello,");
hh.reset();
update(hh, "ClientHellov2,");
hh.setFinishedAlg(finAlg);
// Useless calls
hh.setFinishedAlg("SHA-1");
hh.setFinishedAlg("SHA-512");
update(hh, "More,");
if (cvAlg != null) {
if (cvAlg.isEmpty()) cvAlg = null;
hh.setCertificateVerifyAlg(cvAlg);
}
// Useless calls
hh.setCertificateVerifyAlg("SHA-1");
hh.setCertificateVerifyAlg(null);
hh.protocolDetermined(true);
if (cvAlg != null) {
cv = hh.getAllHandshakeMessages();
equals(cv, "ClientHellov2,More,".getBytes());
}
update(hh, "FIN1,");
f1 = hh.getFinishedHash();
equals(f1, digest(finAlg, "ClientHellov2,More,FIN1,"));
update(hh, "FIN2,");
f2 = hh.getFinishedHash();
equals(f2, digest(finAlg, "ClientHellov2,More,FIN1,FIN2,"));
}
}
}
/**

File diff suppressed because it is too large Load Diff

View File

@ -29,13 +29,12 @@ package sun.security.ssl;
import java.io.*;
import java.util.*;
import java.security.*;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.AccessController;
import java.security.AlgorithmConstraints;
import java.security.AccessControlContext;
import java.security.PrivilegedExceptionAction;
import java.security.PrivilegedActionException;
import java.security.cert.X509Certificate;
import javax.crypto.*;
import javax.crypto.spec.*;
@ -49,6 +48,8 @@ import sun.security.internal.interfaces.TlsMasterSecret;
import sun.security.ssl.HandshakeMessage.*;
import sun.security.ssl.CipherSuite.*;
import static sun.security.ssl.CipherSuite.PRF.*;
/**
* Handshaker ... processes handshake records from an SSL V3.0
* data stream, handling all the details of the handshake protocol.
@ -71,13 +72,48 @@ abstract class Handshaker {
byte[] clientVerifyData;
byte[] serverVerifyData;
// is it an initial negotiation or a renegotiation?
// Is it an initial negotiation or a renegotiation?
boolean isInitialHandshake;
// list of enabled protocols
ProtocolList enabledProtocols;
// List of enabled protocols
private ProtocolList enabledProtocols;
// List of enabled CipherSuites
private CipherSuiteList enabledCipherSuites;
// The endpoint identification protocol
String identificationProtocol;
// The cryptographic algorithm constraints
private AlgorithmConstraints algorithmConstraints = null;
// Local supported signature and algorithms
Collection<SignatureAndHashAlgorithm> localSupportedSignAlgs;
// Peer supported signature and algorithms
Collection<SignatureAndHashAlgorithm> peerSupportedSignAlgs;
/*
/*
* List of active protocols
*
* Active protocols is a subset of enabled protocols, and will
* contain only those protocols that have vaild cipher suites
* enabled.
*/
private ProtocolList activeProtocols;
/*
* List of active cipher suites
*
* Active cipher suites is a subset of enabled cipher suites, and will
* contain only those cipher suites available for the active protocols.
*/
private CipherSuiteList activeCipherSuites;
private boolean isClient;
private boolean needCertVerify;
SSLSocketImpl conn = null;
SSLEngineImpl engine = null;
@ -90,13 +126,6 @@ abstract class Handshaker {
RandomCookie clnt_random, svr_random;
SSLSessionImpl session;
// Temporary MD5 and SHA message digests. Must always be left
// in reset state after use.
private MessageDigest md5Tmp, shaTmp;
// list of enabled CipherSuites
CipherSuiteList enabledCipherSuites;
// current CipherSuite. Never null, initially SSL_NULL_WITH_NULL_NULL
CipherSuite cipherSuite;
@ -191,6 +220,7 @@ abstract class Handshaker {
this.sslContext = context;
this.isClient = isClient;
this.needCertVerify = needCertVerify;
this.activeProtocolVersion = activeProtocolVersion;
this.isInitialHandshake = isInitialHandshake;
this.secureRenegotiation = secureRenegotiation;
@ -200,23 +230,12 @@ abstract class Handshaker {
invalidated = false;
setCipherSuite(CipherSuite.C_NULL);
md5Tmp = JsseJce.getMD5();
shaTmp = JsseJce.getSHA();
//
// We accumulate digests of the handshake messages so that
// we can read/write CertificateVerify and Finished messages,
// getting assurance against some particular active attacks.
//
handshakeHash = new HandshakeHash(needCertVerify);
setEnabledProtocols(enabledProtocols);
if (conn != null) {
conn.getAppInputStream().r.setHandshakeHash(handshakeHash);
algorithmConstraints = new SSLAlgorithmConstraints(conn, true);
} else { // engine != null
engine.inputRecord.setHandshakeHash(handshakeHash);
algorithmConstraints = new SSLAlgorithmConstraints(engine, true);
}
@ -233,7 +252,7 @@ abstract class Handshaker {
// client's cert verify, those constants are in a convenient
// order to drastically simplify state machine checking.
//
state = -1;
state = -2; // initialized but not activated
}
/*
@ -268,6 +287,14 @@ abstract class Handshaker {
}
}
String getRawHostnameSE() {
if (conn != null) {
return conn.getRawHostname();
} else {
return engine.getPeerHost();
}
}
String getHostSE() {
if (conn != null) {
return conn.getHost();
@ -313,14 +340,6 @@ abstract class Handshaker {
}
}
String getHostnameVerificationSE() {
if (conn != null) {
return conn.getHostnameVerification();
} else {
return engine.getHostnameVerification();
}
}
AccessControlContext getAccSE() {
if (conn != null) {
return conn.getAcc();
@ -345,39 +364,139 @@ abstract class Handshaker {
void setVersion(ProtocolVersion protocolVersion) {
this.protocolVersion = protocolVersion;
setVersionSE(protocolVersion);
output.r.setVersion(protocolVersion);
}
/**
* Set the enabled protocols. Called from the constructor or
* SSLSocketImpl/SSLEngineImpl.setEnabledProtocols() (if the
* handshake is not yet in progress).
*/
void setEnabledProtocols(ProtocolList enabledProtocols) {
activeCipherSuites = null;
activeProtocols = null;
this.enabledProtocols = enabledProtocols;
}
/**
* Set the enabled cipher suites. Called from
* SSLSocketImpl/SSLEngineImpl.setEnabledCipherSuites() (if the
* handshake is not yet in progress).
*/
void setEnabledCipherSuites(CipherSuiteList enabledCipherSuites) {
activeCipherSuites = null;
activeProtocols = null;
this.enabledCipherSuites = enabledCipherSuites;
}
/**
* Set the algorithm constraints. Called from the constructor or
* SSLSocketImpl/SSLEngineImpl.setAlgorithmConstraints() (if the
* handshake is not yet in progress).
*/
void setAlgorithmConstraints(AlgorithmConstraints algorithmConstraints) {
activeCipherSuites = null;
activeProtocols = null;
this.algorithmConstraints =
new SSLAlgorithmConstraints(algorithmConstraints);
this.localSupportedSignAlgs = null;
}
Collection<SignatureAndHashAlgorithm> getLocalSupportedSignAlgs() {
if (localSupportedSignAlgs == null) {
localSupportedSignAlgs =
SignatureAndHashAlgorithm.getSupportedAlgorithms(
algorithmConstraints);
}
return localSupportedSignAlgs;
}
void setPeerSupportedSignAlgs(
Collection<SignatureAndHashAlgorithm> algorithms) {
peerSupportedSignAlgs =
new ArrayList<SignatureAndHashAlgorithm>(algorithms);
}
Collection<SignatureAndHashAlgorithm> getPeerSupportedSignAlgs() {
return peerSupportedSignAlgs;
}
/**
* Set the enabled protocols. Called from the constructor or
* SSLSocketImpl.setEnabledProtocols() (if the handshake is not yet
* in progress).
* Set the identification protocol. Called from the constructor or
* SSLSocketImpl/SSLEngineImpl.setIdentificationProtocol() (if the
* handshake is not yet in progress).
*/
void setEnabledProtocols(ProtocolList enabledProtocols) {
this.enabledProtocols = enabledProtocols;
void setIdentificationProtocol(String protocol) {
this.identificationProtocol = protocol;
}
/**
* Prior to handshaking, activate the handshake and initialize the version,
* input stream and output stream.
*/
void activate(ProtocolVersion helloVersion) throws IOException {
if (activeProtocols == null) {
activeProtocols = getActiveProtocols();
}
if (activeProtocols.collection().isEmpty() ||
activeProtocols.max.v == ProtocolVersion.NONE.v) {
throw new SSLHandshakeException("No appropriate protocol");
}
if (activeCipherSuites == null) {
activeCipherSuites = getActiveCipherSuites();
}
if (activeCipherSuites.collection().isEmpty()) {
throw new SSLHandshakeException("No appropriate cipher suite");
}
// temporary protocol version until the actual protocol version
// is negotiated in the Hello exchange. This affects the record
// version we sent with the ClientHello. Using max() as the record
// version is not really correct but some implementations fail to
// correctly negotiate TLS otherwise.
protocolVersion = enabledProtocols.max;
// version we sent with the ClientHello.
if (!isInitialHandshake) {
protocolVersion = activeProtocolVersion;
} else {
protocolVersion = activeProtocols.max;
}
ProtocolVersion helloVersion = enabledProtocols.helloVersion;
if (helloVersion == null || helloVersion.v == ProtocolVersion.NONE.v) {
helloVersion = activeProtocols.helloVersion;
}
// We accumulate digests of the handshake messages so that
// we can read/write CertificateVerify and Finished messages,
// getting assurance against some particular active attacks.
Set<String> localSupportedHashAlgorithms =
SignatureAndHashAlgorithm.getHashAlgorithmNames(
getLocalSupportedSignAlgs());
handshakeHash = new HandshakeHash(!isClient, needCertVerify,
localSupportedHashAlgorithms);
// Generate handshake input/output stream.
input = new HandshakeInStream(handshakeHash);
if (conn != null) {
output = new HandshakeOutStream(protocolVersion, helloVersion,
handshakeHash, conn);
conn.getAppInputStream().r.setHandshakeHash(handshakeHash);
conn.getAppInputStream().r.setHelloVersion(helloVersion);
conn.getAppOutputStream().r.setHelloVersion(helloVersion);
} else {
output = new HandshakeOutStream(protocolVersion, helloVersion,
handshakeHash, engine);
engine.inputRecord.setHandshakeHash(handshakeHash);
engine.inputRecord.setHelloVersion(helloVersion);
engine.outputRecord.setHelloVersion(helloVersion);
}
// move state to activated
state = -1;
}
/**
@ -392,20 +511,150 @@ abstract class Handshaker {
/**
* Check if the given ciphersuite is enabled and available.
* (Enabled ciphersuites are always available unless the status has
* changed due to change in JCE providers since it was enabled).
* Does not check if the required server certificates are available.
*/
boolean isNegotiable(CipherSuite s) {
return enabledCipherSuites.contains(s) && s.isNegotiable();
if (activeCipherSuites == null) {
activeCipherSuites = getActiveCipherSuites();
}
return activeCipherSuites.contains(s) && s.isNegotiable();
}
/**
* As long as handshaking has not started, we can
* Check if the given protocol version is enabled and available.
*/
boolean isNegotiable(ProtocolVersion protocolVersion) {
if (activeProtocols == null) {
activeProtocols = getActiveProtocols();
}
return activeProtocols.contains(protocolVersion);
}
/**
* Select a protocol version from the list. Called from
* ServerHandshaker to negotiate protocol version.
*
* Return the lower of the protocol version suggested in the
* clien hello and the highest supported by the server.
*/
ProtocolVersion selectProtocolVersion(ProtocolVersion protocolVersion) {
if (activeProtocols == null) {
activeProtocols = getActiveProtocols();
}
return activeProtocols.selectProtocolVersion(protocolVersion);
}
/**
* Get the active cipher suites.
*
* In TLS 1.1, many weak or vulnerable cipher suites were obsoleted,
* such as TLS_RSA_EXPORT_WITH_RC4_40_MD5. The implementation MUST NOT
* negotiate these cipher suites in TLS 1.1 or later mode.
*
* Therefore, when the active protocols only include TLS 1.1 or later,
* the client cannot request to negotiate those obsoleted cipher
* suites. That is, the obsoleted suites should not be included in the
* client hello. So we need to create a subset of the enabled cipher
* suites, the active cipher suites, which does not contain obsoleted
* cipher suites of the minimum active protocol.
*
* Return empty list instead of null if no active cipher suites.
*/
CipherSuiteList getActiveCipherSuites() {
if (activeCipherSuites == null) {
if (activeProtocols == null) {
activeProtocols = getActiveProtocols();
}
ArrayList<CipherSuite> suites = new ArrayList<CipherSuite>();
if (!(activeProtocols.collection().isEmpty()) &&
activeProtocols.min.v != ProtocolVersion.NONE.v) {
for (CipherSuite suite : enabledCipherSuites.collection()) {
if (suite.obsoleted > activeProtocols.min.v &&
suite.supported <= activeProtocols.max.v) {
if (algorithmConstraints.permits(
EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
suite.name, null)) {
suites.add(suite);
}
} else if (debug != null && Debug.isOn("verbose")) {
if (suite.obsoleted <= activeProtocols.min.v) {
System.out.println(
"Ignoring obsoleted cipher suite: " + suite);
} else {
System.out.println(
"Ignoring unsupported cipher suite: " + suite);
}
}
}
}
activeCipherSuites = new CipherSuiteList(suites);
}
return activeCipherSuites;
}
/*
* Get the active protocol versions.
*
* In TLS 1.1, many weak or vulnerable cipher suites were obsoleted,
* such as TLS_RSA_EXPORT_WITH_RC4_40_MD5. The implementation MUST NOT
* negotiate these cipher suites in TLS 1.1 or later mode.
*
* For example, if "TLS_RSA_EXPORT_WITH_RC4_40_MD5" is the
* only enabled cipher suite, the client cannot request TLS 1.1 or
* later, even though TLS 1.1 or later is enabled. We need to create a
* subset of the enabled protocols, called the active protocols, which
* contains protocols appropriate to the list of enabled Ciphersuites.
*
* Return empty list instead of null if no active protocol versions.
*/
ProtocolList getActiveProtocols() {
if (activeProtocols == null) {
ArrayList<ProtocolVersion> protocols =
new ArrayList<ProtocolVersion>(4);
for (ProtocolVersion protocol : enabledProtocols.collection()) {
boolean found = false;
for (CipherSuite suite : enabledCipherSuites.collection()) {
if (suite.isAvailable() && suite.obsoleted > protocol.v &&
suite.supported <= protocol.v) {
if (algorithmConstraints.permits(
EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
suite.name, null)) {
protocols.add(protocol);
found = true;
break;
} else if (debug != null && Debug.isOn("verbose")) {
System.out.println(
"Ignoring disabled cipher suite: " + suite +
" for " + protocol);
}
} else if (debug != null && Debug.isOn("verbose")) {
System.out.println(
"Ignoring unsupported cipher suite: " + suite +
" for " + protocol);
}
}
if (!found && (debug != null) && Debug.isOn("handshake")) {
System.out.println(
"No available cipher suite for " + protocol);
}
}
activeProtocols = new ProtocolList(protocols);
}
return activeProtocols;
}
/**
* As long as handshaking has not activated, we can
* change whether session creations are allowed.
*
* Callers should do their own checking if handshaking
* has started.
* has activated.
*/
void setEnableSessionCreation(boolean newSessions) {
enableNewSession = newSessions;
@ -419,12 +668,12 @@ abstract class Handshaker {
CipherBox box;
if (isClient) {
box = cipher.newCipher(protocolVersion, svrWriteKey, svrWriteIV,
false);
sslContext.getSecureRandom(), false);
svrWriteKey = null;
svrWriteIV = null;
} else {
box = cipher.newCipher(protocolVersion, clntWriteKey, clntWriteIV,
false);
sslContext.getSecureRandom(), false);
clntWriteKey = null;
clntWriteIV = null;
}
@ -439,12 +688,12 @@ abstract class Handshaker {
CipherBox box;
if (isClient) {
box = cipher.newCipher(protocolVersion, clntWriteKey, clntWriteIV,
true);
sslContext.getSecureRandom(), true);
clntWriteKey = null;
clntWriteIV = null;
} else {
box = cipher.newCipher(protocolVersion, svrWriteKey, svrWriteIV,
true);
sslContext.getSecureRandom(), true);
svrWriteKey = null;
svrWriteIV = null;
}
@ -501,6 +750,17 @@ abstract class Handshaker {
return session;
}
/*
* Set the handshake session
*/
void setHandshakeSessionSE(SSLSessionImpl handshakeSession) {
if (conn != null) {
conn.setHandshakeSession(handshakeSession);
} else {
engine.setHandshakeSession(handshakeSession);
}
}
/*
* Returns true if renegotiation is in use for this connection.
*/
@ -613,14 +873,21 @@ abstract class Handshaker {
}
/**
* Returns true iff the handshaker has been activated.
*
* In activated state, the handshaker may not send any messages out.
*/
boolean activated() {
return state >= -1;
}
/**
* Returns true iff the handshaker has sent any messages.
* Server kickstarting is not as neat as it should be; we
* need to create a new handshaker, this method lets us
* know if we should.
*/
boolean started() {
return state >= 0;
return state >= 0; // 0: HandshakeMessage.ht_hello_request
// 1: HandshakeMessage.ht_client_hello
}
@ -633,6 +900,7 @@ abstract class Handshaker {
if (state >= 0) {
return;
}
HandshakeMessage m = getKickstartMessage();
if (debug != null && Debug.isOn("handshake")) {
@ -746,9 +1014,6 @@ abstract class Handshaker {
*/
private SecretKey calculateMasterSecret(SecretKey preMasterSecret,
ProtocolVersion requestedVersion) {
TlsMasterSecretParameterSpec spec = new TlsMasterSecretParameterSpec
(preMasterSecret, protocolVersion.major, protocolVersion.minor,
clnt_random.random_bytes, svr_random.random_bytes);
if (debug != null && Debug.isOn("keygen")) {
HexDumpEncoder dump = new HexDumpEncoder();
@ -762,33 +1027,70 @@ abstract class Handshaker {
// benefit to doing it twice
}
// What algs/params do we need to use?
String masterAlg;
PRF prf;
if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
masterAlg = "SunTls12MasterSecret";
prf = cipherSuite.prfAlg;
} else {
masterAlg = "SunTlsMasterSecret";
prf = P_NONE;
}
String prfHashAlg = prf.getPRFHashAlg();
int prfHashLength = prf.getPRFHashLength();
int prfBlockSize = prf.getPRFBlockSize();
TlsMasterSecretParameterSpec spec = new TlsMasterSecretParameterSpec(
preMasterSecret, protocolVersion.major, protocolVersion.minor,
clnt_random.random_bytes, svr_random.random_bytes,
prfHashAlg, prfHashLength, prfBlockSize);
SecretKey masterSecret;
try {
KeyGenerator kg = JsseJce.getKeyGenerator("SunTlsMasterSecret");
KeyGenerator kg = JsseJce.getKeyGenerator(masterAlg);
kg.init(spec);
masterSecret = kg.generateKey();
} catch (GeneralSecurityException e) {
// For RSA premaster secrets, do not signal a protocol error
// due to the Bleichenbacher attack. See comments further down.
if (!preMasterSecret.getAlgorithm().equals("TlsRsaPremasterSecret")) {
if (!preMasterSecret.getAlgorithm().equals(
"TlsRsaPremasterSecret")) {
throw new ProviderException(e);
}
if (debug != null && Debug.isOn("handshake")) {
System.out.println("RSA master secret generation error:");
e.printStackTrace(System.out);
System.out.println("Generating new random premaster secret");
}
preMasterSecret = RSAClientKeyExchange.generateDummySecret(protocolVersion);
if (requestedVersion != null) {
preMasterSecret =
RSAClientKeyExchange.generateDummySecret(requestedVersion);
} else {
preMasterSecret =
RSAClientKeyExchange.generateDummySecret(protocolVersion);
}
// recursive call with new premaster secret
return calculateMasterSecret(preMasterSecret, null);
}
// if no version check requested (client side handshake),
// or version information is not available (not an RSA premaster secret),
// if no version check requested (client side handshake), or version
// information is not available (not an RSA premaster secret),
// return master secret immediately.
if ((requestedVersion == null) || !(masterSecret instanceof TlsMasterSecret)) {
if ((requestedVersion == null) ||
!(masterSecret instanceof TlsMasterSecret)) {
return masterSecret;
}
// we have checked the ClientKeyExchange message when reading TLS
// record, the following check is necessary to ensure that
// JCE provider does not ignore the checking, or the previous
// checking process bypassed the premaster secret version checking.
TlsMasterSecret tlsKey = (TlsMasterSecret)masterSecret;
int major = tlsKey.getMajorVersion();
int minor = tlsKey.getMinorVersion();
@ -800,13 +1102,21 @@ abstract class Handshaker {
// the specification says that it must be the maximum version supported
// by the client from its ClientHello message. However, many
// implementations send the negotiated version, so accept both
// NOTE that we may be comparing two unsupported version numbers in
// the second case, which is why we cannot use object reference
// equality in this special case
ProtocolVersion premasterVersion = ProtocolVersion.valueOf(major, minor);
boolean versionMismatch = (premasterVersion != protocolVersion) &&
(premasterVersion.v != requestedVersion.v);
// for SSL v3.0 and TLS v1.0.
// NOTE that we may be comparing two unsupported version numbers, which
// is why we cannot use object reference equality in this special case.
ProtocolVersion premasterVersion =
ProtocolVersion.valueOf(major, minor);
boolean versionMismatch = (premasterVersion.v != requestedVersion.v);
/*
* we never checked the client_version in server side
* for TLS v1.0 and SSL v3.0. For compatibility, we
* maintain this behavior.
*/
if (versionMismatch && requestedVersion.v <= ProtocolVersion.TLS10.v) {
versionMismatch = (premasterVersion.v != protocolVersion.v);
}
if (versionMismatch == false) {
// check passed, return key
@ -823,7 +1133,9 @@ abstract class Handshaker {
+ premasterVersion);
System.out.println("Generating new random premaster secret");
}
preMasterSecret = RSAClientKeyExchange.generateDummySecret(protocolVersion);
preMasterSecret =
RSAClientKeyExchange.generateDummySecret(requestedVersion);
// recursive call with new premaster secret
return calculateMasterSecret(preMasterSecret, null);
}
@ -849,24 +1161,41 @@ abstract class Handshaker {
int hashSize = cipherSuite.macAlg.size;
boolean is_exportable = cipherSuite.exportable;
BulkCipher cipher = cipherSuite.cipher;
int keySize = cipher.keySize;
int ivSize = cipher.ivSize;
int expandedKeySize = is_exportable ? cipher.expandedKeySize : 0;
TlsKeyMaterialParameterSpec spec = new TlsKeyMaterialParameterSpec
(masterKey, protocolVersion.major, protocolVersion.minor,
// Which algs/params do we need to use?
String keyMaterialAlg;
PRF prf;
if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
keyMaterialAlg = "SunTls12KeyMaterial";
prf = cipherSuite.prfAlg;
} else {
keyMaterialAlg = "SunTlsKeyMaterial";
prf = P_NONE;
}
String prfHashAlg = prf.getPRFHashAlg();
int prfHashLength = prf.getPRFHashLength();
int prfBlockSize = prf.getPRFBlockSize();
TlsKeyMaterialParameterSpec spec = new TlsKeyMaterialParameterSpec(
masterKey, protocolVersion.major, protocolVersion.minor,
clnt_random.random_bytes, svr_random.random_bytes,
cipher.algorithm, cipher.keySize, expandedKeySize,
cipher.ivSize, hashSize);
cipher.ivSize, hashSize,
prfHashAlg, prfHashLength, prfBlockSize);
try {
KeyGenerator kg = JsseJce.getKeyGenerator("SunTlsKeyMaterial");
KeyGenerator kg = JsseJce.getKeyGenerator(keyMaterialAlg);
kg.init(spec);
TlsKeyMaterialSpec keySpec = (TlsKeyMaterialSpec)kg.generateKey();
clntWriteKey = keySpec.getClientCipherKey();
svrWriteKey = keySpec.getServerCipherKey();
// Return null if IVs are not supposed to be generated.
// e.g. TLS 1.1+.
clntWriteIV = keySpec.getClientIv();
svrWriteIV = keySpec.getServerIv();
@ -914,7 +1243,12 @@ abstract class Handshaker {
System.out.println("Server write IV:");
printHex(dump, svrWriteIV.getIV());
} else {
System.out.println("... no IV used for this cipher");
if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
System.out.println(
"... no IV derived for this protocol");
} else {
System.out.println("... no IV used for this cipher");
}
}
System.out.flush();
}

View File

@ -50,7 +50,8 @@ import javax.net.ssl.SSLProtocolException;
*
* . UnknownExtension: used to represent all parsed extensions that we do not
* explicitly support.
* . ServerNameExtension: partially implemented server_name extension.
* . ServerNameExtension: the server_name extension.
* . SignatureAlgorithmsExtension: the signature_algorithms extension.
* . SupportedEllipticCurvesExtension: the ECC supported curves extension.
* . SupportedEllipticPointFormatsExtension: the ECC supported point formats
* (compressed/uncompressed) extension.
@ -78,6 +79,8 @@ final class HelloExtensions {
HelloExtension extension;
if (extType == ExtensionType.EXT_SERVER_NAME) {
extension = new ServerNameExtension(s, extlen);
} else if (extType == ExtensionType.EXT_SIGNATURE_ALGORITHMS) {
extension = new SignatureAlgorithmsExtension(s, extlen);
} else if (extType == ExtensionType.EXT_ELLIPTIC_CURVES) {
extension = new SupportedEllipticCurvesExtension(s, extlen);
} else if (extType == ExtensionType.EXT_EC_POINT_FORMATS) {
@ -266,31 +269,102 @@ final class UnknownExtension extends HelloExtension {
}
public String toString() {
return "Unsupported extension " + type + ", data: " + Debug.toString(data);
return "Unsupported extension " + type + ", data: " +
Debug.toString(data);
}
}
/*
* Support for the server_name extension is incomplete. Parsing is implemented
* so that we get nicer debug output, but we neither send it nor do we do
* act on it if we receive it.
* [RFC4366] To facilitate secure connections to servers that host multiple
* 'virtual' servers at a single underlying network address, clients MAY
* include an extension of type "server_name" in the (extended) client hello.
* The "extension_data" field of this extension SHALL contain "ServerNameList"
* where:
*
* struct {
* NameType name_type;
* select (name_type) {
* case host_name: HostName;
* } name;
* } ServerName;
*
* enum {
* host_name(0), (255)
* } NameType;
*
* opaque HostName<1..2^16-1>;
*
* struct {
* ServerName server_name_list<1..2^16-1>
* } ServerNameList;
*/
final class ServerNameExtension extends HelloExtension {
final static int NAME_HOST_NAME = 0;
private List<ServerName> names;
private int listLength; // ServerNameList length
ServerNameExtension(List<String> hostnames) throws IOException {
super(ExtensionType.EXT_SERVER_NAME);
listLength = 0;
names = new ArrayList<ServerName>(hostnames.size());
for (String hostname : hostnames) {
if (hostname != null && hostname.length() != 0) {
// we only support DNS hostname now.
ServerName serverName =
new ServerName(NAME_HOST_NAME, hostname);
names.add(serverName);
listLength += serverName.length;
}
}
// As we only support DNS hostname now, the hostname list must
// not contain more than one hostname
if (names.size() > 1) {
throw new SSLProtocolException(
"The ServerNameList MUST NOT contain more than " +
"one name of the same name_type");
}
// We only need to add "server_name" extension in ClientHello unless
// we support SNI in server side in the future. It is possible that
// the SNI is empty in ServerHello. As we don't support SNI in
// ServerHello now, we will throw exception for empty list for now.
if (listLength == 0) {
throw new SSLProtocolException(
"The ServerNameList cannot be empty");
}
}
ServerNameExtension(HandshakeInStream s, int len)
throws IOException {
super(ExtensionType.EXT_SERVER_NAME);
names = new ArrayList<ServerName>();
while (len > 0) {
ServerName name = new ServerName(s);
names.add(name);
len -= name.length + 2;
int remains = len;
if (len >= 2) { // "server_name" extension in ClientHello
listLength = s.getInt16(); // ServerNameList length
if (listLength == 0 || listLength + 2 != len) {
throw new SSLProtocolException(
"Invalid " + type + " extension");
}
remains -= 2;
names = new ArrayList<ServerName>();
while (remains > 0) {
ServerName name = new ServerName(s);
names.add(name);
remains -= name.length;
// we may need to check the duplicated ServerName type
}
} else if (len == 0) { // "server_name" extension in ServerHello
listLength = 0;
names = Collections.<ServerName>emptyList();
}
if (len != 0) {
if (remains != 0) {
throw new SSLProtocolException("Invalid server_name extension");
}
}
@ -301,10 +375,19 @@ final class ServerNameExtension extends HelloExtension {
final byte[] data;
final String hostname;
ServerName(int type, String hostname) throws IOException {
this.type = type; // NameType
this.hostname = hostname;
this.data = hostname.getBytes("UTF8"); // HostName
this.length = data.length + 3; // NameType: 1 byte
// HostName length: 2 bytes
}
ServerName(HandshakeInStream s) throws IOException {
length = s.getInt16(); // ServerNameList length
type = s.getInt8(); // NameType
data = s.getBytes16(); // HostName (length read in getBytes16)
length = data.length + 3; // NameType: 1 byte
// HostName length: 2 bytes
if (type == NAME_HOST_NAME) {
hostname = new String(data, "UTF8");
} else {
@ -322,15 +405,29 @@ final class ServerNameExtension extends HelloExtension {
}
int length() {
throw new RuntimeException("not yet supported");
return listLength == 0 ? 4 : 6 + listLength;
}
void send(HandshakeOutStream s) throws IOException {
throw new RuntimeException("not yet supported");
s.putInt16(type.id);
s.putInt16(listLength + 2);
if (listLength != 0) {
s.putInt16(listLength);
for (ServerName name : names) {
s.putInt8(name.type); // NameType
s.putBytes16(name.data); // HostName
}
}
}
public String toString() {
return "Unsupported extension " + type + ", " + names.toString();
StringBuffer buffer = new StringBuffer();
for (ServerName name : names) {
buffer.append("[" + name + "]");
}
return "Extension " + type + ", server_name: " + buffer;
}
}
@ -523,7 +620,8 @@ final class SupportedEllipticPointFormatsExtension extends HelloExtension {
final static int FMT_ANSIX962_COMPRESSED_CHAR2 = 2;
static final HelloExtension DEFAULT =
new SupportedEllipticPointFormatsExtension(new byte[] {FMT_UNCOMPRESSED});
new SupportedEllipticPointFormatsExtension(
new byte[] {FMT_UNCOMPRESSED});
private final byte[] formats;
@ -665,3 +763,105 @@ final class RenegotiationInfoExtension extends HelloExtension {
}
}
/*
* [RFC5246] The client uses the "signature_algorithms" extension to
* indicate to the server which signature/hash algorithm pairs may be
* used in digital signatures. The "extension_data" field of this
* extension contains a "supported_signature_algorithms" value.
*
* enum {
* none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5),
* sha512(6), (255)
* } HashAlgorithm;
*
* enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) }
* SignatureAlgorithm;
*
* struct {
* HashAlgorithm hash;
* SignatureAlgorithm signature;
* } SignatureAndHashAlgorithm;
*
* SignatureAndHashAlgorithm
* supported_signature_algorithms<2..2^16-2>;
*/
final class SignatureAlgorithmsExtension extends HelloExtension {
private Collection<SignatureAndHashAlgorithm> algorithms;
private int algorithmsLen; // length of supported_signature_algorithms
SignatureAlgorithmsExtension(
Collection<SignatureAndHashAlgorithm> signAlgs) {
super(ExtensionType.EXT_SIGNATURE_ALGORITHMS);
algorithms = new ArrayList<SignatureAndHashAlgorithm>(signAlgs);
algorithmsLen =
SignatureAndHashAlgorithm.sizeInRecord() * algorithms.size();
}
SignatureAlgorithmsExtension(HandshakeInStream s, int len)
throws IOException {
super(ExtensionType.EXT_SIGNATURE_ALGORITHMS);
algorithmsLen = s.getInt16();
if (algorithmsLen == 0 || algorithmsLen + 2 != len) {
throw new SSLProtocolException("Invalid " + type + " extension");
}
algorithms = new ArrayList<SignatureAndHashAlgorithm>();
int remains = algorithmsLen;
int sequence = 0;
while (remains > 1) { // needs at least two bytes
int hash = s.getInt8(); // hash algorithm
int signature = s.getInt8(); // signature algorithm
SignatureAndHashAlgorithm algorithm =
SignatureAndHashAlgorithm.valueOf(hash, signature, ++sequence);
algorithms.add(algorithm);
remains -= 2; // one byte for hash, one byte for signature
}
if (remains != 0) {
throw new SSLProtocolException("Invalid server_name extension");
}
}
Collection<SignatureAndHashAlgorithm> getSignAlgorithms() {
return algorithms;
}
@Override
int length() {
return 6 + algorithmsLen;
}
@Override
void send(HandshakeOutStream s) throws IOException {
s.putInt16(type.id);
s.putInt16(algorithmsLen + 2);
s.putInt16(algorithmsLen);
for (SignatureAndHashAlgorithm algorithm : algorithms) {
s.putInt8(algorithm.getHashValue()); // HashAlgorithm
s.putInt8(algorithm.getSignatureValue()); // SignatureAlgorithm
}
}
@Override
public String toString() {
StringBuffer buffer = new StringBuffer();
boolean opened = false;
for (SignatureAndHashAlgorithm signAlg : algorithms) {
if (opened) {
buffer.append(", " + signAlg.getAlgorithmName());
} else {
buffer.append(signAlg.getAlgorithmName());
opened = true;
}
}
return "Extension " + type + ", signature_algorithms: " + buffer;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -69,6 +69,7 @@ public class KerberosClientKeyExchange extends HandshakeMessage {
}
public KerberosClientKeyExchange() {
// empty
}
public KerberosClientKeyExchange(String serverName, boolean isLoopback,
@ -93,14 +94,17 @@ public class KerberosClientKeyExchange extends HandshakeMessage {
}
}
@Override
int messageType() {
return ht_client_key_exchange;
}
@Override
public int messageLength() {
return impl.messageLength();
}
@Override
public void send(HandshakeOutStream s) throws IOException {
impl.send(s);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -105,6 +105,10 @@ final class MAC {
algorithm = tls ? "HmacMD5" : "SslMacMD5";
} else if (macAlg == M_SHA) {
algorithm = tls ? "HmacSHA1" : "SslMacSHA1";
} else if (macAlg == M_SHA256) {
algorithm = "HmacSHA256"; // TLS 1.2+
} else if (macAlg == M_SHA384) {
algorithm = "HmacSHA384"; // TLS 1.2+
} else {
throw new RuntimeException("Unknown Mac " + macAlg);
}
@ -155,6 +159,42 @@ final class MAC {
return compute(type, bb, null, 0, bb.remaining());
}
/**
* Check whether the sequence number is close to wrap
*
* Sequence numbers are of type uint64 and may not exceed 2^64-1.
* Sequence numbers do not wrap. When the sequence number is near
* to wrap, we need to close the connection immediately.
*/
final boolean seqNumOverflow() {
/*
* Conservatively, we don't allow more records to be generated
* when there are only 2^8 sequence numbers left.
*/
return (block != null && mac != null &&
block[0] == 0xFF && block[1] == 0xFF &&
block[2] == 0xFF && block[3] == 0xFF &&
block[4] == 0xFF && block[5] == 0xFF &&
block[6] == 0xFF);
}
/*
* Check whether to renew the sequence number
*
* Sequence numbers are of type uint64 and may not exceed 2^64-1.
* Sequence numbers do not wrap. If a TLS
* implementation would need to wrap a sequence number, it must
* renegotiate instead.
*/
final boolean seqNumIsHuge() {
/*
* Conservatively, we should ask for renegotiation when there are
* only 2^48 sequence numbers left.
*/
return (block != null && mac != null &&
block[0] == 0xFF && block[1] == 0xFF);
}
// increment the sequence number in the block array
// it is a 64-bit number stored in big-endian format
private void incrementSequenceNumber() {
@ -168,7 +208,8 @@ final class MAC {
* 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) {
private byte[] compute(byte type, ByteBuffer bb, byte[] buf,
int offset, int len) {
if (macSize == 0) {
return nullMAC;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -38,8 +38,12 @@ import java.util.*;
final class ProtocolList {
private static final ProtocolList SUPPORTED;
private static final ProtocolList CLIENT_DEFAULT;
private static final ProtocolList SERVER_DEFAULT;
// the sorted protocol version list
private final ArrayList<ProtocolVersion> protocols;
private final Collection<ProtocolVersion> protocols;
private String[] protocolNames;
// the minimum and maximum ProtocolVersions in this list
@ -49,30 +53,45 @@ final class ProtocolList {
final ProtocolVersion helloVersion;
ProtocolList(String[] names) {
this(convert(names));
}
ProtocolList(ArrayList<ProtocolVersion> versions) {
this.protocols = versions;
if ((protocols.size() == 1) &&
protocols.contains(ProtocolVersion.SSL20Hello)) {
throw new IllegalArgumentException("SSLv2Hello cannot be " +
"enabled unless at least one other supported version " +
"is also enabled.");
}
if (protocols.size() != 0) {
Collections.sort(protocols);
min = protocols.get(0);
max = protocols.get(protocols.size() - 1);
helloVersion = protocols.get(0);
} else {
min = ProtocolVersion.NONE;
max = ProtocolVersion.NONE;
helloVersion = ProtocolVersion.NONE;
}
}
private static ArrayList<ProtocolVersion> convert(String[] names) {
if (names == null) {
throw new IllegalArgumentException("Protocols may not be null");
}
protocols = new ArrayList<ProtocolVersion>(3);
ArrayList<ProtocolVersion> versions = new ArrayList<ProtocolVersion>(3);
for (int i = 0; i < names.length; i++ ) {
ProtocolVersion version = ProtocolVersion.valueOf(names[i]);
if (protocols.contains(version) == false) {
protocols.add(version);
if (versions.contains(version) == false) {
versions.add(version);
}
}
if ((protocols.size() == 1)
&& protocols.contains(ProtocolVersion.SSL20Hello)) {
throw new IllegalArgumentException("SSLv2Hello" +
"cannot be enabled unless TLSv1 or SSLv3 is also enabled");
}
min = contains(ProtocolVersion.SSL30) ? ProtocolVersion.SSL30
: ProtocolVersion.TLS10;
max = contains(ProtocolVersion.TLS10) ? ProtocolVersion.TLS10
: ProtocolVersion.SSL30;
if (protocols.contains(ProtocolVersion.SSL20Hello)) {
helloVersion = ProtocolVersion.SSL20Hello;
} else {
helloVersion = min;
}
return versions;
}
/**
@ -87,6 +106,37 @@ final class ProtocolList {
return protocols.contains(protocolVersion);
}
/**
* Return a reference to the internal Collection of CipherSuites.
* The Collection MUST NOT be modified.
*/
Collection<ProtocolVersion> collection() {
return protocols;
}
/**
* Select a protocol version from the list.
*
* Return the lower of the protocol version of that suggested by
* the <code>protocolVersion</code> and the highest version of this
* protocol list, or null if no protocol version is available.
*
* The method is used by TLS server to negotiated the protocol
* version between client suggested protocol version in the
* client hello and protocol versions supported by the server.
*/
ProtocolVersion selectProtocolVersion(ProtocolVersion protocolVersion) {
ProtocolVersion selectedVersion = null;
for (ProtocolVersion pv : protocols) {
if (pv.v > protocolVersion.v) {
break; // Safe to break here as this.protocols is sorted
}
selectedVersion = pv;
}
return selectedVersion;
}
/**
* Return an array with the names of the ProtocolVersions in this list.
*/
@ -106,11 +156,18 @@ final class ProtocolList {
}
/**
* Return the list of default enabled protocols. Currently, this
* is identical to the supported protocols.
* Return the list of default enabled protocols.
*/
static ProtocolList getDefault() {
return SUPPORTED;
static ProtocolList getDefault(boolean isServer) {
return isServer ? SERVER_DEFAULT : CLIENT_DEFAULT;
}
/**
* Return whether a protocol list is the original default enabled
* protocols. See: SSLSocket/SSLEngine.setEnabledProtocols()
*/
static boolean isDefaultProtocolList(ProtocolList protocols) {
return protocols == CLIENT_DEFAULT || protocols == SERVER_DEFAULT;
}
/**
@ -123,6 +180,13 @@ final class ProtocolList {
static {
if (SunJSSE.isFIPS()) {
SUPPORTED = new ProtocolList(new String[] {
ProtocolVersion.TLS10.name,
ProtocolVersion.TLS11.name,
ProtocolVersion.TLS12.name
});
SERVER_DEFAULT = SUPPORTED;
CLIENT_DEFAULT = new ProtocolList(new String[] {
ProtocolVersion.TLS10.name
});
} else {
@ -130,6 +194,24 @@ final class ProtocolList {
ProtocolVersion.SSL20Hello.name,
ProtocolVersion.SSL30.name,
ProtocolVersion.TLS10.name,
ProtocolVersion.TLS11.name,
ProtocolVersion.TLS12.name
});
SERVER_DEFAULT = SUPPORTED;
/*
* RFC 5246 says that sending SSLv2 backward-compatible
* hello SHOULD NOT be done any longer.
*
* We are not enabling TLS 1.1/1.2 by default yet on clients
* out of concern for interop with existing
* SSLv3/TLS1.0-only servers. When these versions of TLS
* gain more traction, we'll enable them.
*/
CLIENT_DEFAULT = new ProtocolList(new String[] {
ProtocolVersion.SSL30.name,
ProtocolVersion.TLS10.name
});
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -45,9 +45,15 @@ package sun.security.ssl;
* @author Andreas Sterbenz
* @since 1.4.1
*/
public final class ProtocolVersion {
public final class ProtocolVersion implements Comparable<ProtocolVersion> {
// dummy protocol version value for invalid SSLSession
// The limit of maximum protocol version
final static int LIMIT_MAX_VALUE = 0xFFFF;
// The limit of minimum protocol version
final static int LIMIT_MIN_VALUE = 0x0000;
// Dummy protocol version value for invalid SSLSession
final static ProtocolVersion NONE = new ProtocolVersion(-1, "NONE");
// If enabled, send/ accept SSLv2 hello messages
@ -61,22 +67,24 @@ public final class ProtocolVersion {
final static ProtocolVersion TLS10 = new ProtocolVersion(0x0301, "TLSv1");
// TLS 1.1
// not supported yet, but added for better readability of the debug trace
final static ProtocolVersion TLS11 = new ProtocolVersion(0x0302, "TLSv1.1");
// TLS 1.2
final static ProtocolVersion TLS12 = new ProtocolVersion(0x0303, "TLSv1.2");
private static final boolean FIPS = SunJSSE.isFIPS();
// minimum version we implement (SSL 3.0)
final static ProtocolVersion MIN = FIPS ? TLS10 : SSL30;
// maximum version we implement (TLS 1.0)
final static ProtocolVersion MAX = TLS10;
// maximum version we implement (TLS 1.2)
final static ProtocolVersion MAX = TLS12;
// ProtocolVersion to use by default (TLS 1.0)
final static ProtocolVersion DEFAULT = TLS10;
// Default version for hello messages (SSLv2Hello)
final static ProtocolVersion DEFAULT_HELLO = FIPS ? TLS10 : SSL20Hello;
final static ProtocolVersion DEFAULT_HELLO = FIPS ? TLS10 : SSL30;
// version in 16 bit MSB format as it appears in records and
// messages, i.e. 0x0301 for TLS 1.0
@ -104,6 +112,8 @@ public final class ProtocolVersion {
return TLS10;
} else if (v == TLS11.v) {
return TLS11;
} else if (v == TLS12.v) {
return TLS12;
} else if (v == SSL20Hello.v) {
return SSL20Hello;
} else {
@ -134,18 +144,20 @@ public final class ProtocolVersion {
if (name == null) {
throw new IllegalArgumentException("Protocol cannot be null");
}
if (FIPS) {
if (name.equals(TLS10.name)) {
return TLS10;
} else {
throw new IllegalArgumentException
("Only TLS 1.0 allowed in FIPS mode");
}
if (FIPS && (name.equals(SSL30.name) || name.equals(SSL20Hello.name))) {
throw new IllegalArgumentException
("Only TLS 1.0 or later allowed in FIPS mode");
}
if (name.equals(SSL30.name)) {
return SSL30;
} else if (name.equals(TLS10.name)) {
return TLS10;
} else if (name.equals(TLS11.name)) {
return TLS11;
} else if (name.equals(TLS12.name)) {
return TLS12;
} else if (name.equals(SSL20Hello.name)) {
return SSL20Hello;
} else {
@ -157,4 +169,10 @@ public final class ProtocolVersion {
return name;
}
/**
* Compares this object with the specified object for order.
*/
public int compareTo(ProtocolVersion protocolVersion) {
return this.v - protocolVersion.v;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -55,20 +55,17 @@ final class RSAClientKeyExchange extends HandshakeMessage {
* requested in its client hello version). However, we (and other
* implementations) used to send the active negotiated version. The
* system property below allows to toggle the behavior.
*
* Default is "false" (old behavior) for compatibility reasons. This
* will be changed in the future.
*/
private final static String PROP_NAME =
"com.sun.net.ssl.rsaPreMasterSecretFix";
/*
* Default is "false" (old behavior) for compatibility reasons in
* SSLv3/TLSv1. Later protocols (TLSv1.1+) do not use this property.
*/
private final static boolean rsaPreMasterSecretFix =
Debug.getBooleanProperty(PROP_NAME, false);
int messageType() {
return ht_client_key_exchange;
}
/*
* The following field values were encrypted with the server's public
* key (or temp key from server key exchange msg) and are presented
@ -78,14 +75,14 @@ final class RSAClientKeyExchange extends HandshakeMessage {
SecretKey preMaster;
private byte[] encrypted; // same size as public modulus
/*
* Client randomly creates a pre-master secret and encrypts it
* using the server's RSA public key; only the server can decrypt
* it, using its RSA private key. Result is the same size as the
* server's public key, and uses PKCS #1 block format 02.
*/
RSAClientKeyExchange(ProtocolVersion protocolVersion, ProtocolVersion maxVersion,
RSAClientKeyExchange(ProtocolVersion protocolVersion,
ProtocolVersion maxVersion,
SecureRandom generator, PublicKey publicKey) throws IOException {
if (publicKey.getAlgorithm().equals("RSA") == false) {
throw new SSLKeyException("Public key not of type RSA");
@ -94,7 +91,7 @@ final class RSAClientKeyExchange extends HandshakeMessage {
int major, minor;
if (rsaPreMasterSecretFix) {
if (rsaPreMasterSecretFix || maxVersion.v >= ProtocolVersion.TLS11.v) {
major = maxVersion.major;
minor = maxVersion.minor;
} else {
@ -103,7 +100,9 @@ final class RSAClientKeyExchange extends HandshakeMessage {
}
try {
KeyGenerator kg = JsseJce.getKeyGenerator("SunTlsRsaPremasterSecret");
String s = ((protocolVersion.v >= ProtocolVersion.TLS12.v) ?
"SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret");
KeyGenerator kg = JsseJce.getKeyGenerator(s);
kg.init(new TlsRsaPremasterSecretParameterSpec(major, minor));
preMaster = kg.generateKey();
@ -120,14 +119,15 @@ final class RSAClientKeyExchange extends HandshakeMessage {
* Server gets the PKCS #1 (block format 02) data, decrypts
* it with its private key.
*/
RSAClientKeyExchange(ProtocolVersion currentVersion, HandshakeInStream input,
RSAClientKeyExchange(ProtocolVersion currentVersion,
ProtocolVersion maxVersion,
SecureRandom generator, HandshakeInStream input,
int messageSize, PrivateKey privateKey) throws IOException {
if (privateKey.getAlgorithm().equals("RSA") == false) {
throw new SSLKeyException("Private key not of type RSA");
}
this.protocolVersion = currentVersion;
if (currentVersion.v >= ProtocolVersion.TLS10.v) {
encrypted = input.getBytes16();
} else {
@ -143,31 +143,109 @@ final class RSAClientKeyExchange extends HandshakeMessage {
cipher.init(Cipher.UNWRAP_MODE, privateKey);
preMaster = (SecretKey)cipher.unwrap(encrypted,
"TlsRsaPremasterSecret", Cipher.SECRET_KEY);
// polish the premaster secret
preMaster = polishPreMasterSecretKey(currentVersion, maxVersion,
generator, preMaster, null);
} catch (Exception e) {
/*
* Bogus decrypted ClientKeyExchange? If so, conjure a
* a random preMaster secret that will fail later during
* Finished message processing. This is a countermeasure against
* the "interactive RSA PKCS#1 encryption envelop attack" reported
* in June 1998. Preserving the executation path will
* mitigate timing attacks and force consistent error handling
* that will prevent an attacking client from differentiating
* different kinds of decrypted ClientKeyExchange bogosities.
*/
if (debug != null && Debug.isOn("handshake")) {
System.out.println("Error decrypting premaster secret:");
e.printStackTrace(System.out);
System.out.println("Generating random secret");
}
preMaster = generateDummySecret(currentVersion);
// polish the premaster secret
preMaster =
polishPreMasterSecretKey(currentVersion, maxVersion,
generator, null, e);
}
}
/**
* To avoid vulnerabilities described by section 7.4.7.1, RFC 5246,
* treating incorrectly formatted message blocks and/or mismatched
* version numbers in a manner indistinguishable from correctly
* formatted RSA blocks.
*
* RFC 5246 describes the approach as :
*
* 1. Generate a string R of 46 random bytes
*
* 2. Decrypt the message to recover the plaintext M
*
* 3. If the PKCS#1 padding is not correct, or the length of message
* M is not exactly 48 bytes:
* pre_master_secret = ClientHello.client_version || R
* else If ClientHello.client_version <= TLS 1.0, and version
* number check is explicitly disabled:
* pre_master_secret = M
* else:
* pre_master_secret = ClientHello.client_version || M[2..47]
*/
private SecretKey polishPreMasterSecretKey(ProtocolVersion currentVersion,
ProtocolVersion clientHelloVersion, SecureRandom generator,
SecretKey secretKey, Exception failoverException) {
this.protocolVersion = clientHelloVersion;
if (failoverException == null && secretKey != null) {
// check the length
byte[] encoded = secretKey.getEncoded();
if (encoded == null) { // unable to get the encoded key
if (debug != null && Debug.isOn("handshake")) {
System.out.println(
"unable to get the plaintext of the premaster secret");
}
// We are not always able to get the encoded key of the
// premaster secret. Pass the cheking to master secret
// calculation.
return secretKey;
} else if (encoded.length == 48) {
// check the version
if (clientHelloVersion.major == encoded[0] &&
clientHelloVersion.minor == encoded[1]) {
return secretKey;
} else if (clientHelloVersion.v <= ProtocolVersion.TLS10.v) {
/*
* we never checked the client_version in server side
* for TLS v1.0 and SSL v3.0. For compatibility, we
* maintain this behavior.
*/
if (currentVersion.major == encoded[0] &&
currentVersion.minor == encoded[1]) {
this.protocolVersion = currentVersion;
return secretKey;
}
}
if (debug != null && Debug.isOn("handshake")) {
System.out.println("Mismatching Protocol Versions, " +
"ClientHello.client_version is " + clientHelloVersion +
", while PreMasterSecret.client_version is " +
ProtocolVersion.valueOf(encoded[0], encoded[1]));
}
} else {
if (debug != null && Debug.isOn("handshake")) {
System.out.println(
"incorrect length of premaster secret: " +
encoded.length);
}
}
}
if (debug != null && Debug.isOn("handshake")) {
if (failoverException != null) {
System.out.println("Error decrypting premaster secret:");
failoverException.printStackTrace(System.out);
}
System.out.println("Generating random secret");
}
return generateDummySecret(clientHelloVersion);
}
// generate a premaster secret with the specified version number
static SecretKey generateDummySecret(ProtocolVersion version) {
try {
KeyGenerator kg =
JsseJce.getKeyGenerator("SunTlsRsaPremasterSecret");
String s = ((version.v >= ProtocolVersion.TLS12.v) ?
"SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret");
KeyGenerator kg = JsseJce.getKeyGenerator(s);
kg.init(new TlsRsaPremasterSecretParameterSpec
(version.major, version.minor));
return kg.generateKey();
@ -176,6 +254,12 @@ final class RSAClientKeyExchange extends HandshakeMessage {
}
}
@Override
int messageType() {
return ht_client_key_exchange;
}
@Override
int messageLength() {
if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
return encrypted.length + 2;
@ -184,6 +268,7 @@ final class RSAClientKeyExchange extends HandshakeMessage {
}
}
@Override
void send(HandshakeOutStream s) throws IOException {
if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
s.putBytes16(encrypted);
@ -192,7 +277,9 @@ final class RSAClientKeyExchange extends HandshakeMessage {
}
}
@Override
void print(PrintStream s) throws IOException {
s.println("*** ClientKeyExchange, RSA PreMasterSecret, " + protocolVersion);
s.println("*** ClientKeyExchange, RSA PreMasterSecret, " +
protocolVersion);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -47,11 +47,12 @@ interface Record {
static final byte ct_handshake = 22;
static final byte ct_application_data = 23;
static final int headerSize = 5; // SSLv3 record header
static final int maxExpansion = 1024; // for bad compression
static final int trailerSize = 20; // SHA1 hash size
static final int maxDataSize = 16384; // 2^14 bytes of data
static final int maxPadding = 256; // block cipher padding
static final int headerSize = 5; // SSLv3 record header
static final int maxExpansion = 1024; // for bad compression
static final int trailerSize = 20; // SHA1 hash size
static final int maxDataSize = 16384; // 2^14 bytes of data
static final int maxPadding = 256; // block cipher padding
static final int maxIVLength = 256; // block length
/*
* SSL has a maximum record size. It's header, (compressed) data,
@ -59,8 +60,9 @@ interface Record {
* Some compression algorithms have rare cases where they expand the data.
* As we don't support compression at this time, leave that out.
*/
static final int maxRecordSize =
static final int maxRecordSize =
headerSize // header
+ maxIVLength // iv
+ maxDataSize // data
+ maxPadding // padding
+ trailerSize; // MAC
@ -74,7 +76,7 @@ interface Record {
* The maximum large record size is defined as maxRecordSize plus 2^14,
* this is the amount OpenSSL is using.
*/
static final int maxLargeRecordSize =
static final int maxLargeRecordSize =
maxRecordSize // Max size with a conforming implemenation
+ maxDataSize; // extra 2^14 bytes for large data packets.
@ -84,7 +86,11 @@ interface Record {
* They only contain 2 and 1 bytes of data, respectively.
* Allocate a smaller array.
*/
static final int maxAlertRecordSize =
headerSize + 2 + maxPadding + trailerSize;
static final int maxAlertRecordSize =
headerSize // header
+ maxIVLength // iv
+ 2 // alert
+ maxPadding // padding
+ trailerSize; // MAC
}

View File

@ -0,0 +1,469 @@
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.security.ssl;
import java.security.AlgorithmConstraints;
import java.security.CryptoPrimitive;
import java.security.AlgorithmParameters;
import javax.net.ssl.*;
import java.security.Key;
import java.util.Set;
import java.util.HashSet;
import sun.security.util.DisabledAlgorithmConstraints;
import sun.security.ssl.CipherSuite.*;
/**
* Algorithm constraints for disabled algorithms property
*
* See the "jdk.certpath.disabledAlgorithms" specification in java.security
* for the syntax of the disabled algorithm string.
*/
final class SSLAlgorithmConstraints implements AlgorithmConstraints {
private final static AlgorithmConstraints tlsDisabledAlgConstraints =
new TLSDisabledAlgConstraints();
private final static AlgorithmConstraints x509DisabledAlgConstraints =
new X509DisabledAlgConstraints();
private AlgorithmConstraints userAlgConstraints = null;
private AlgorithmConstraints peerAlgConstraints = null;
private boolean enabledX509DisabledAlgConstraints = true;
SSLAlgorithmConstraints(AlgorithmConstraints algorithmConstraints) {
userAlgConstraints = algorithmConstraints;
}
SSLAlgorithmConstraints(SSLSocket socket,
boolean withDefaultCertPathConstraints) {
if (socket != null) {
userAlgConstraints =
socket.getSSLParameters().getAlgorithmConstraints();
}
if (!withDefaultCertPathConstraints) {
enabledX509DisabledAlgConstraints = false;
}
}
SSLAlgorithmConstraints(SSLEngine engine,
boolean withDefaultCertPathConstraints) {
if (engine != null) {
userAlgConstraints =
engine.getSSLParameters().getAlgorithmConstraints();
}
if (!withDefaultCertPathConstraints) {
enabledX509DisabledAlgConstraints = false;
}
}
SSLAlgorithmConstraints(SSLSocket socket, String[] supportedAlgorithms,
boolean withDefaultCertPathConstraints) {
if (socket != null) {
userAlgConstraints =
socket.getSSLParameters().getAlgorithmConstraints();
peerAlgConstraints =
new SupportedSignatureAlgorithmConstraints(supportedAlgorithms);
}
if (!withDefaultCertPathConstraints) {
enabledX509DisabledAlgConstraints = false;
}
}
SSLAlgorithmConstraints(SSLEngine engine, String[] supportedAlgorithms,
boolean withDefaultCertPathConstraints) {
if (engine != null) {
userAlgConstraints =
engine.getSSLParameters().getAlgorithmConstraints();
peerAlgConstraints =
new SupportedSignatureAlgorithmConstraints(supportedAlgorithms);
}
if (!withDefaultCertPathConstraints) {
enabledX509DisabledAlgConstraints = false;
}
}
public boolean permits(Set<CryptoPrimitive> primitives,
String algorithm, AlgorithmParameters parameters) {
boolean permitted = true;
if (peerAlgConstraints != null) {
permitted = peerAlgConstraints.permits(
primitives, algorithm, parameters);
}
if (permitted && userAlgConstraints != null) {
permitted = userAlgConstraints.permits(
primitives, algorithm, parameters);
}
if (permitted) {
permitted = tlsDisabledAlgConstraints.permits(
primitives, algorithm, parameters);
}
if (permitted && enabledX509DisabledAlgConstraints) {
permitted = x509DisabledAlgConstraints.permits(
primitives, algorithm, parameters);
}
return permitted;
}
public boolean permits(Set<CryptoPrimitive> primitives, Key key) {
boolean permitted = true;
if (peerAlgConstraints != null) {
permitted = peerAlgConstraints.permits(primitives, key);
}
if (permitted && userAlgConstraints != null) {
permitted = userAlgConstraints.permits(primitives, key);
}
if (permitted) {
permitted = tlsDisabledAlgConstraints.permits(primitives, key);
}
if (permitted && enabledX509DisabledAlgConstraints) {
permitted = x509DisabledAlgConstraints.permits(primitives, key);
}
return permitted;
}
public boolean permits(Set<CryptoPrimitive> primitives,
String algorithm, Key key, AlgorithmParameters parameters) {
boolean permitted = true;
if (peerAlgConstraints != null) {
permitted = peerAlgConstraints.permits(
primitives, algorithm, key, parameters);
}
if (permitted && userAlgConstraints != null) {
permitted = userAlgConstraints.permits(
primitives, algorithm, key, parameters);
}
if (permitted) {
permitted = tlsDisabledAlgConstraints.permits(
primitives, algorithm, key, parameters);
}
if (permitted && enabledX509DisabledAlgConstraints) {
permitted = x509DisabledAlgConstraints.permits(
primitives, algorithm, key, parameters);
}
return permitted;
}
static private class SupportedSignatureAlgorithmConstraints
implements AlgorithmConstraints {
// supported signature algorithms
private String[] supportedAlgorithms;
SupportedSignatureAlgorithmConstraints(String[] supportedAlgorithms) {
if (supportedAlgorithms != null) {
this.supportedAlgorithms = supportedAlgorithms.clone();
} else {
this.supportedAlgorithms = null;
}
}
public boolean permits(Set<CryptoPrimitive> primitives,
String algorithm, AlgorithmParameters parameters) {
if (algorithm == null || algorithm.length() == 0) {
throw new IllegalArgumentException(
"No algorithm name specified");
}
if (primitives == null || primitives.isEmpty()) {
throw new IllegalArgumentException(
"No cryptographic primitive specified");
}
if (supportedAlgorithms == null ||
supportedAlgorithms.length == 0) {
return false;
}
// trim the MGF part: <digest>with<encryption>and<mgf>
int position = algorithm.indexOf("and");
if (position > 0) {
algorithm = algorithm.substring(0, position);
}
for (String supportedAlgorithm : supportedAlgorithms) {
if (algorithm.equalsIgnoreCase(supportedAlgorithm)) {
return true;
}
}
return false;
}
final public boolean permits(Set<CryptoPrimitive> primitives, Key key) {
return true;
}
final public boolean permits(Set<CryptoPrimitive> primitives,
String algorithm, Key key, AlgorithmParameters parameters) {
if (algorithm == null || algorithm.length() == 0) {
throw new IllegalArgumentException(
"No algorithm name specified");
}
return permits(primitives, algorithm, parameters);
}
}
static private class BasicDisabledAlgConstraints
extends DisabledAlgorithmConstraints {
BasicDisabledAlgConstraints(String propertyName) {
super(propertyName);
}
protected Set<String> decomposes(KeyExchange keyExchange,
boolean forCertPathOnly) {
Set<String> components = new HashSet<String>();
switch (keyExchange) {
case K_NULL:
if (!forCertPathOnly) {
components.add("NULL");
}
break;
case K_RSA:
components.add("RSA");
break;
case K_RSA_EXPORT:
components.add("RSA");
components.add("RSA_EXPORT");
break;
case K_DH_RSA:
components.add("RSA");
components.add("DH");
components.add("DiffieHellman");
components.add("DH_RSA");
break;
case K_DH_DSS:
components.add("DSA");
components.add("DSS");
components.add("DH");
components.add("DiffieHellman");
components.add("DH_DSS");
break;
case K_DHE_DSS:
components.add("DSA");
components.add("DSS");
components.add("DH");
components.add("DHE");
components.add("DiffieHellman");
components.add("DHE_DSS");
break;
case K_DHE_RSA:
components.add("RSA");
components.add("DH");
components.add("DHE");
components.add("DiffieHellman");
components.add("DHE_RSA");
break;
case K_DH_ANON:
if (!forCertPathOnly) {
components.add("ANON");
components.add("DH");
components.add("DiffieHellman");
components.add("DH_ANON");
}
break;
case K_ECDH_ECDSA:
components.add("ECDH");
components.add("ECDSA");
components.add("ECDH_ECDSA");
break;
case K_ECDH_RSA:
components.add("ECDH");
components.add("RSA");
components.add("ECDH_RSA");
break;
case K_ECDHE_ECDSA:
components.add("ECDHE");
components.add("ECDSA");
components.add("ECDHE_ECDSA");
break;
case K_ECDHE_RSA:
components.add("ECDHE");
components.add("RSA");
components.add("ECDHE_RSA");
break;
case K_ECDH_ANON:
if (!forCertPathOnly) {
components.add("ECDH");
components.add("ANON");
components.add("ECDH_ANON");
}
break;
case K_KRB5:
if (!forCertPathOnly) {
components.add("KRB5");
}
break;
case K_KRB5_EXPORT:
if (!forCertPathOnly) {
components.add("KRB5_EXPORT");
}
break;
default:
// ignore
}
return components;
}
protected Set<String> decomposes(BulkCipher bulkCipher) {
Set<String> components = new HashSet<String>();
if (bulkCipher.transformation != null) {
components.addAll(super.decomposes(bulkCipher.transformation));
}
return components;
}
protected Set<String> decomposes(MacAlg macAlg) {
Set<String> components = new HashSet<String>();
if (macAlg == CipherSuite.M_MD5) {
components.add("MD5");
components.add("HmacMD5");
} else if (macAlg == CipherSuite.M_SHA) {
components.add("SHA1");
components.add("SHA-1");
components.add("HmacSHA1");
} else if (macAlg == CipherSuite.M_SHA256) {
components.add("SHA256");
components.add("SHA-256");
components.add("HmacSHA256");
} else if (macAlg == CipherSuite.M_SHA384) {
components.add("SHA384");
components.add("SHA-384");
components.add("HmacSHA384");
}
return components;
}
}
static private class TLSDisabledAlgConstraints
extends BasicDisabledAlgConstraints {
TLSDisabledAlgConstraints() {
super(DisabledAlgorithmConstraints.PROPERTY_TLS_DISABLED_ALGS);
}
@Override
protected Set<String> decomposes(String algorithm) {
if (algorithm.startsWith("SSL_") || algorithm.startsWith("TLS_")) {
CipherSuite cipherSuite = null;
try {
cipherSuite = CipherSuite.valueOf(algorithm);
} catch (IllegalArgumentException iae) {
// ignore: unknown or unsupported ciphersuite
}
if (cipherSuite != null) {
Set<String> components = new HashSet<String>();
if(cipherSuite.keyExchange != null) {
components.addAll(
decomposes(cipherSuite.keyExchange, false));
}
if (cipherSuite.cipher != null) {
components.addAll(decomposes(cipherSuite.cipher));
}
if (cipherSuite.macAlg != null) {
components.addAll(decomposes(cipherSuite.macAlg));
}
return components;
}
}
return super.decomposes(algorithm);
}
}
static private class X509DisabledAlgConstraints
extends BasicDisabledAlgConstraints {
X509DisabledAlgConstraints() {
super(DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS);
}
@Override
protected Set<String> decomposes(String algorithm) {
if (algorithm.startsWith("SSL_") || algorithm.startsWith("TLS_")) {
CipherSuite cipherSuite = null;
try {
cipherSuite = CipherSuite.valueOf(algorithm);
} catch (IllegalArgumentException iae) {
// ignore: unknown or unsupported ciphersuite
}
if (cipherSuite != null) {
Set<String> components = new HashSet<String>();
if(cipherSuite.keyExchange != null) {
components.addAll(
decomposes(cipherSuite.keyExchange, true));
}
// Certification path algorithm constraints do not apply
// to cipherSuite.cipher and cipherSuite.macAlg.
return components;
}
}
return super.decomposes(algorithm);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -27,11 +27,15 @@ package sun.security.ssl;
import java.net.Socket;
import java.util.*;
import java.security.*;
import java.security.cert.*;
import java.security.cert.Certificate;
import javax.net.ssl.*;
import sun.security.provider.certpath.AlgorithmChecker;
public class SSLContextImpl extends SSLContextSpi {
private static final Debug debug = Debug.getInstance("ssl");
@ -82,7 +86,8 @@ public class SSLContextImpl extends SSLContextSpi {
if (sr == null) {
secureRandom = JsseJce.getSecureRandom();
} else {
if (SunJSSE.isFIPS() && (sr.getProvider() != SunJSSE.cryptoProvider)) {
if (SunJSSE.isFIPS() &&
(sr.getProvider() != SunJSSE.cryptoProvider)) {
throw new KeyManagementException
("FIPS mode: SecureRandom must be from provider "
+ SunJSSE.cryptoProvider.getName());
@ -111,11 +116,18 @@ public class SSLContextImpl extends SSLContextSpi {
// We only use the first instance of X509TrustManager passed to us.
for (int i = 0; tm != null && i < tm.length; i++) {
if (tm[i] instanceof X509TrustManager) {
if (SunJSSE.isFIPS() && !(tm[i] instanceof X509TrustManagerImpl)) {
if (SunJSSE.isFIPS() &&
!(tm[i] instanceof X509TrustManagerImpl)) {
throw new KeyManagementException
("FIPS mode: only SunJSSE TrustManagers may be used");
}
return (X509TrustManager)tm[i];
if (tm[i] instanceof X509ExtendedTrustManager) {
return (X509TrustManager)tm[i];
} else {
return new AbstractTrustManagerWrapper(
(X509TrustManager)tm[i]);
}
}
}
@ -153,7 +165,7 @@ public class SSLContextImpl extends SSLContextSpi {
"SSLContext.init(): need an " +
"X509ExtendedKeyManager for SSLEngine use");
}
return new AbstractWrapper((X509KeyManager)km);
return new AbstractKeyManagerWrapper((X509KeyManager)km);
}
// nothing found, return a dummy X509ExtendedKeyManager
@ -217,9 +229,179 @@ public class SSLContextImpl extends SSLContextSpi {
}
final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager
implements X509TrustManager {
private final X509TrustManager tm;
AbstractTrustManagerWrapper(X509TrustManager tm) {
this.tm = tm;
}
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
tm.checkClientTrusted(chain, authType);
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
tm.checkServerTrusted(chain, authType);
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return tm.getAcceptedIssuers();
}
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType,
Socket socket) throws CertificateException {
tm.checkClientTrusted(chain, authType);
checkAdditionalTrust(chain, authType, socket, true);
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType,
Socket socket) throws CertificateException {
tm.checkServerTrusted(chain, authType);
checkAdditionalTrust(chain, authType, socket, false);
}
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType,
SSLEngine engine) throws CertificateException {
tm.checkClientTrusted(chain, authType);
checkAdditionalTrust(chain, authType, engine, true);
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType,
SSLEngine engine) throws CertificateException {
tm.checkServerTrusted(chain, authType);
checkAdditionalTrust(chain, authType, engine, false);
}
private void checkAdditionalTrust(X509Certificate[] chain, String authType,
Socket socket, boolean isClient) throws CertificateException {
if (socket != null && socket.isConnected() &&
socket instanceof SSLSocket) {
SSLSocket sslSocket = (SSLSocket)socket;
SSLSession session = sslSocket.getHandshakeSession();
if (session == null) {
throw new CertificateException("No handshake session");
}
// check endpoint identity
String identityAlg = sslSocket.getSSLParameters().
getEndpointIdentificationAlgorithm();
if (identityAlg != null && identityAlg.length() != 0) {
String hostname = session.getPeerHost();
X509TrustManagerImpl.checkIdentity(
hostname, chain[0], identityAlg);
}
// try the best to check the algorithm constraints
ProtocolVersion protocolVersion =
ProtocolVersion.valueOf(session.getProtocol());
AlgorithmConstraints constraints = null;
if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
if (session instanceof ExtendedSSLSession) {
ExtendedSSLSession extSession =
(ExtendedSSLSession)session;
String[] peerSupportedSignAlgs =
extSession.getLocalSupportedSignatureAlgorithms();
constraints = new SSLAlgorithmConstraints(
sslSocket, peerSupportedSignAlgs, true);
} else {
constraints =
new SSLAlgorithmConstraints(sslSocket, true);
}
} else {
constraints = new SSLAlgorithmConstraints(sslSocket, true);
}
AlgorithmChecker checker = new AlgorithmChecker(constraints);
try {
checker.init(false);
// a forward checker, need to check from trust to target
for (int i = chain.length - 1; i >= 0; i--) {
Certificate cert = chain[i];
// We don't care about the unresolved critical extensions.
checker.check(cert, Collections.<String>emptySet());
}
} catch (CertPathValidatorException cpve) {
throw new CertificateException(
"Certificates does not conform to algorithm constraints");
}
}
}
private void checkAdditionalTrust(X509Certificate[] chain, String authType,
SSLEngine engine, boolean isClient) throws CertificateException {
if (engine != null) {
SSLSession session = engine.getHandshakeSession();
if (session == null) {
throw new CertificateException("No handshake session");
}
// check endpoint identity
String identityAlg = engine.getSSLParameters().
getEndpointIdentificationAlgorithm();
if (identityAlg != null && identityAlg.length() != 0) {
String hostname = session.getPeerHost();
X509TrustManagerImpl.checkIdentity(
hostname, chain[0], identityAlg);
}
// try the best to check the algorithm constraints
ProtocolVersion protocolVersion =
ProtocolVersion.valueOf(session.getProtocol());
AlgorithmConstraints constraints = null;
if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
if (session instanceof ExtendedSSLSession) {
ExtendedSSLSession extSession =
(ExtendedSSLSession)session;
String[] peerSupportedSignAlgs =
extSession.getLocalSupportedSignatureAlgorithms();
constraints = new SSLAlgorithmConstraints(
engine, peerSupportedSignAlgs, true);
} else {
constraints =
new SSLAlgorithmConstraints(engine, true);
}
} else {
constraints = new SSLAlgorithmConstraints(engine, true);
}
AlgorithmChecker checker = new AlgorithmChecker(constraints);
try {
checker.init(false);
// A forward checker, need to check from trust to target
for (int i = chain.length - 1; i >= 0; i--) {
Certificate cert = chain[i];
// We don't care about the unresolved critical extensions.
checker.check(cert, Collections.<String>emptySet());
}
} catch (CertPathValidatorException cpve) {
throw new CertificateException(
"Certificates does not conform to algorithm constraints");
}
}
}
}
// Dummy X509TrustManager implementation, rejects all peer certificates.
// Used if the application did not specify a proper X509TrustManager.
final class DummyX509TrustManager implements X509TrustManager {
final class DummyX509TrustManager extends X509ExtendedTrustManager
implements X509TrustManager {
static final X509TrustManager INSTANCE = new DummyX509TrustManager();
@ -234,6 +416,7 @@ final class DummyX509TrustManager implements X509TrustManager {
* validated and is trusted for client SSL authentication.
* If not, it throws an exception.
*/
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
throw new CertificateException(
@ -247,6 +430,7 @@ final class DummyX509TrustManager implements X509TrustManager {
* validated and is trusted for server SSL authentication.
* If not, it throws an exception.
*/
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
throw new CertificateException(
@ -257,19 +441,48 @@ final class DummyX509TrustManager implements X509TrustManager {
* Return an array of issuer certificates which are trusted
* for authenticating peers.
*/
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType,
Socket socket) throws CertificateException {
throw new CertificateException(
"No X509TrustManager implementation available");
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType,
Socket socket) throws CertificateException {
throw new CertificateException(
"No X509TrustManager implementation available");
}
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType,
SSLEngine engine) throws CertificateException {
throw new CertificateException(
"No X509TrustManager implementation available");
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType,
SSLEngine engine) throws CertificateException {
throw new CertificateException(
"No X509TrustManager implementation available");
}
}
/*
* A wrapper class to turn a X509KeyManager into an X509ExtendedKeyManager
*/
final class AbstractWrapper extends X509ExtendedKeyManager {
final class AbstractKeyManagerWrapper extends X509ExtendedKeyManager {
private final X509KeyManager km;
AbstractWrapper(X509KeyManager km) {
AbstractKeyManagerWrapper(X509KeyManager km) {
this.km = km;
}

View File

@ -200,8 +200,10 @@ final public class SSLEngineImpl extends SSLEngine {
* is associated with a session at the same time. (TLS/IETF may
* change that to add client authentication w/o new key exchg.)
*/
private SSLSessionImpl sess;
private Handshaker handshaker;
private Handshaker handshaker;
private SSLSessionImpl sess;
private volatile SSLSessionImpl handshakeSession;
/*
* Client authentication be off, requested, or required.
@ -240,26 +242,30 @@ final public class SSLEngineImpl extends SSLEngine {
* session is changed.
*/
private byte doClientAuth;
private CipherSuiteList enabledCipherSuites;
private boolean enableSessionCreation = true;
EngineInputRecord inputRecord;
EngineOutputRecord outputRecord;
private AccessControlContext acc;
// hostname identification algorithm, the hostname identification is
// disabled by default.
private String identificationAlg = null;
// The cipher suites enabled for use on this connection.
private CipherSuiteList enabledCipherSuites;
// the endpoint identification protocol
private String identificationProtocol = null;
// The cryptographic algorithm constraints
private AlgorithmConstraints algorithmConstraints = null;
// Have we been told whether we're client or server?
private boolean serverModeSet = false;
private boolean roleIsServer;
/*
* The protocols we support are SSL Version 3.0) and
* TLS (version 3.1).
* In addition we support a pseudo protocol called
* SSLv2Hello which when set will result in an SSL v2 Hello
* being sent with SSLv3 or TLSv1 version info.
* The protocol versions enabled for use on this connection.
*
* Note: we support a pseudo protocol called SSLv2Hello which when
* set will result in an SSL v2 Hello being sent with SSL (version 3.0)
* or TLS (version 3.1, 3.2, etc.) version info.
*/
private ProtocolList enabledProtocols;
@ -342,6 +348,7 @@ final public class SSLEngineImpl extends SSLEngine {
sslContext = ctx;
sess = SSLSessionImpl.nullSession;
handshakeSession = null;
/*
* State is cs_START until we initialize the handshaker.
@ -368,7 +375,7 @@ final public class SSLEngineImpl extends SSLEngine {
serverVerifyData = new byte[0];
enabledCipherSuites = CipherSuiteList.getDefault();
enabledProtocols = ProtocolList.getDefault();
enabledProtocols = ProtocolList.getDefault(roleIsServer);
wrapLock = new Object();
unwrapLock = new Object();
@ -405,8 +412,8 @@ final public class SSLEngineImpl extends SSLEngine {
* . if the engine is already closed, throw an Exception (internal error)
*
* . otherwise (cs_START or cs_DATA), create the appropriate handshaker
* object, initialize it, and advance the connection state (to
* cs_HANDSHAKE or cs_RENEGOTIATE, respectively).
* object and advance the connection state (to cs_HANDSHAKE or
* cs_RENEGOTIATE, respectively).
*
* This method is called right after a new engine is created, when
* starting renegotiation, or when changing client/server mode of the
@ -454,12 +461,8 @@ final public class SSLEngineImpl extends SSLEngine {
protocolVersion, connectionState == cs_HANDSHAKE,
secureRenegotiation, clientVerifyData, serverVerifyData);
}
handshaker.enabledCipherSuites = enabledCipherSuites;
handshaker.setEnabledCipherSuites(enabledCipherSuites);
handshaker.setEnableSessionCreation(enableSessionCreation);
if (connectionState == cs_RENEGOTIATE) {
// don't use SSLv2Hello when renegotiating
handshaker.output.r.setHelloVersion(protocolVersion);
}
}
/*
@ -686,7 +689,15 @@ final public class SSLEngineImpl extends SSLEngine {
// to its HandshakeOutStream, which calls back into
// SSLSocketImpl.writeRecord() to send it.
//
if (!handshaker.started()) {
if (!handshaker.activated()) {
// prior to handshaking, activate the handshake
if (connectionState == cs_RENEGOTIATE) {
// don't use SSLv2Hello when renegotiating
handshaker.activate(protocolVersion);
} else {
handshaker.activate(null);
}
if (handshaker instanceof ClientHandshaker) {
// send client hello
handshaker.kickstart();
@ -696,6 +707,7 @@ final public class SSLEngineImpl extends SSLEngine {
} else {
// we want to renegotiate, send hello request
handshaker.kickstart();
// hello request is not included in the handshake
// hashes, reset them
handshaker.handshakeHash.reset();
@ -982,6 +994,15 @@ final public class SSLEngineImpl extends SSLEngine {
* in it.
*/
initHandshaker();
if (!handshaker.activated()) {
// prior to handshaking, activate the handshake
if (connectionState == cs_RENEGOTIATE) {
// don't use SSLv2Hello when renegotiating
handshaker.activate(protocolVersion);
} else {
handshaker.activate(null);
}
}
/*
* process the handshake record ... may contain just
@ -1007,6 +1028,7 @@ final public class SSLEngineImpl extends SSLEngine {
serverVerifyData = handshaker.getServerVerifyData();
sess = handshaker.getSession();
handshakeSession = null;
if (!writer.hasOutboundData()) {
hsStatus = HandshakeStatus.FINISHED;
}
@ -1081,6 +1103,26 @@ final public class SSLEngineImpl extends SSLEngine {
}
break;
} // switch
/*
* We only need to check the sequence number state for
* non-handshaking record.
*
* Note that in order to maintain the handshake status
* properly, we check the sequence number after the last
* record reading process. As we request renegotiation
* or close the connection for wrapped sequence number
* when there is enough sequence number space left to
* handle a few more records, so the sequence number
* of the last record cannot be wrapped.
*/
if (connectionState < cs_ERROR && !isInboundDone() &&
(hsStatus == HandshakeStatus.NOT_HANDSHAKING)) {
if (checkSequenceNumber(readMAC,
inputRecord.contentType())) {
hsStatus = getHSStatus(null);
}
}
} // synchronized (this)
}
@ -1229,7 +1271,29 @@ final public class SSLEngineImpl extends SSLEngine {
EngineArgs ea) throws IOException {
// eventually compress as well.
return writer.writeRecord(eor, ea, writeMAC, writeCipher);
HandshakeStatus hsStatus =
writer.writeRecord(eor, ea, writeMAC, writeCipher);
/*
* We only need to check the sequence number state for
* non-handshaking record.
*
* Note that in order to maintain the handshake status
* properly, we check the sequence number after the last
* record writing process. As we request renegotiation
* or close the connection for wrapped sequence number
* when there is enough sequence number space left to
* handle a few more records, so the sequence number
* of the last record cannot be wrapped.
*/
if (connectionState < cs_ERROR && !isOutboundDone() &&
(hsStatus == HandshakeStatus.NOT_HANDSHAKING)) {
if (checkSequenceNumber(writeMAC, eor.contentType())) {
hsStatus = getHSStatus(null);
}
}
return hsStatus;
}
/*
@ -1238,12 +1302,88 @@ final public class SSLEngineImpl extends SSLEngine {
void writeRecord(EngineOutputRecord eor) throws IOException {
// eventually compress as well.
writer.writeRecord(eor, writeMAC, writeCipher);
/*
* Check the sequence number state
*
* Note that in order to maintain the connection I/O
* properly, we check the sequence number after the last
* record writing process. As we request renegotiation
* or close the connection for wrapped sequence number
* when there is enough sequence number space left to
* handle a few more records, so the sequence number
* of the last record cannot be wrapped.
*/
if ((connectionState < cs_ERROR) && !isOutboundDone()) {
checkSequenceNumber(writeMAC, eor.contentType());
}
}
//
// Close code
//
/**
* Check the sequence number state
*
* RFC 4346 states that, "Sequence numbers are of type uint64 and
* may not exceed 2^64-1. Sequence numbers do not wrap. If a TLS
* implementation would need to wrap a sequence number, it must
* renegotiate instead."
*
* Return true if the handshake status may be changed.
*/
private boolean checkSequenceNumber(MAC mac, byte type)
throws IOException {
/*
* Don't bother to check the sequence number for error or
* closed connections, or NULL MAC
*/
if (connectionState >= cs_ERROR || mac == MAC.NULL) {
return false;
}
/*
* Conservatively, close the connection immediately when the
* sequence number is close to overflow
*/
if (mac.seqNumOverflow()) {
/*
* TLS protocols do not define a error alert for sequence
* number overflow. We use handshake_failure error alert
* for handshaking and bad_record_mac for other records.
*/
if (debug != null && Debug.isOn("ssl")) {
System.out.println(threadName() +
", sequence number extremely close to overflow " +
"(2^64-1 packets). Closing connection.");
}
fatal(Alerts.alert_handshake_failure, "sequence number overflow");
return true; // make the compiler happy
}
/*
* Ask for renegotiation when need to renew sequence number.
*
* Don't bother to kickstart the renegotiation when the local is
* asking for it.
*/
if ((type != Record.ct_handshake) && mac.seqNumIsHuge()) {
if (debug != null && Debug.isOn("ssl")) {
System.out.println(threadName() + ", request renegotiation " +
"to avoid sequence number overflow");
}
beginHandshake();
return true;
}
return false;
}
/**
* Signals that no more outbound application data will be sent
* on this <code>SSLEngine</code>.
@ -1394,6 +1534,15 @@ final public class SSLEngineImpl extends SSLEngine {
return sess;
}
@Override
synchronized public SSLSession getHandshakeSession() {
return handshakeSession;
}
synchronized void setHandshakeSession(SSLSessionImpl session) {
handshakeSession = session;
}
/**
* Returns a delegated <code>Runnable</code> task for
* this <code>SSLEngine</code>.
@ -1495,6 +1644,9 @@ final public class SSLEngineImpl extends SSLEngine {
inboundDone = true;
sess.invalidate();
if (handshakeSession != null) {
handshakeSession.invalidate();
}
/*
* If we haven't even started handshaking yet, no need
@ -1594,10 +1746,18 @@ final public class SSLEngineImpl extends SSLEngine {
* Emit alerts. Caller must have synchronized with "this".
*/
private void sendAlert(byte level, byte description) {
// the connectionState cannot be cs_START
if (connectionState >= cs_CLOSED) {
return;
}
// For initial handshaking, don't send alert message to peer if
// handshaker has not started.
if (connectionState == cs_HANDSHAKE &&
(handshaker == null || !handshaker.started())) {
return;
}
EngineOutputRecord r = new EngineOutputRecord(Record.ct_alert, this);
r.setVersion(protocolVersion);
@ -1647,7 +1807,7 @@ final public class SSLEngineImpl extends SSLEngine {
synchronized public void setEnableSessionCreation(boolean flag) {
enableSessionCreation = flag;
if ((handshaker != null) && !handshaker.started()) {
if ((handshaker != null) && !handshaker.activated()) {
handshaker.setEnableSessionCreation(enableSessionCreation);
}
}
@ -1675,7 +1835,7 @@ final public class SSLEngineImpl extends SSLEngine {
if ((handshaker != null) &&
(handshaker instanceof ServerHandshaker) &&
!handshaker.started()) {
!handshaker.activated()) {
((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
}
}
@ -1698,7 +1858,7 @@ final public class SSLEngineImpl extends SSLEngine {
if ((handshaker != null) &&
(handshaker instanceof ServerHandshaker) &&
!handshaker.started()) {
!handshaker.activated()) {
((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
}
}
@ -1717,6 +1877,16 @@ final public class SSLEngineImpl extends SSLEngine {
switch (connectionState) {
case cs_START:
/*
* If we need to change the engine mode and the enabled
* protocols haven't specifically been set by the user,
* change them to the corresponding default ones.
*/
if (roleIsServer != (!flag) &&
ProtocolList.isDefaultProtocolList(enabledProtocols)) {
enabledProtocols = ProtocolList.getDefault(!flag);
}
roleIsServer = !flag;
serverModeSet = true;
break;
@ -1730,7 +1900,17 @@ final public class SSLEngineImpl extends SSLEngine {
* have the streams.
*/
assert(handshaker != null);
if (!handshaker.started()) {
if (!handshaker.activated()) {
/*
* If we need to change the engine mode and the enabled
* protocols haven't specifically been set by the user,
* change them to the corresponding default ones.
*/
if (roleIsServer != (!flag) &&
ProtocolList.isDefaultProtocolList(enabledProtocols)) {
enabledProtocols = ProtocolList.getDefault(!flag);
}
roleIsServer = !flag;
connectionState = cs_START;
initHandshaker();
@ -1786,8 +1966,8 @@ final public class SSLEngineImpl extends SSLEngine {
*/
synchronized public void setEnabledCipherSuites(String[] suites) {
enabledCipherSuites = new CipherSuiteList(suites);
if ((handshaker != null) && !handshaker.started()) {
handshaker.enabledCipherSuites = enabledCipherSuites;
if ((handshaker != null) && !handshaker.activated()) {
handshaker.setEnabledCipherSuites(enabledCipherSuites);
}
}
@ -1809,7 +1989,7 @@ final public class SSLEngineImpl extends SSLEngine {
/**
* Returns the protocols that are supported by this implementation.
* A subset of the supported protocols may be enabled for this connection
* @ returns an array of protocol names.
* @return an array of protocol names.
*/
public String[] getSupportedProtocols() {
return ProtocolList.getSupported().toStringArray();
@ -1826,7 +2006,7 @@ final public class SSLEngineImpl extends SSLEngine {
*/
synchronized public void setEnabledProtocols(String[] protocols) {
enabledProtocols = new ProtocolList(protocols);
if ((handshaker != null) && !handshaker.started()) {
if ((handshaker != null) && !handshaker.activated()) {
handshaker.setEnabledProtocols(enabledProtocols);
}
}
@ -1836,28 +2016,31 @@ final public class SSLEngineImpl extends SSLEngine {
}
/**
* Try to configure the endpoint identification algorithm of the engine.
*
* @param identificationAlgorithm the algorithm used to check the
* endpoint identity.
* @return true if the identification algorithm configuration success.
* Returns the SSLParameters in effect for this SSLEngine.
*/
synchronized public boolean trySetHostnameVerification(
String identificationAlgorithm) {
if (sslContext.getX509TrustManager() instanceof
X509ExtendedTrustManager) {
this.identificationAlg = identificationAlgorithm;
return true;
} else {
return false;
}
synchronized public SSLParameters getSSLParameters() {
SSLParameters params = super.getSSLParameters();
// the super implementation does not handle the following parameters
params.setEndpointIdentificationAlgorithm(identificationProtocol);
params.setAlgorithmConstraints(algorithmConstraints);
return params;
}
/**
* Returns the endpoint identification algorithm of the engine.
* Applies SSLParameters to this engine.
*/
synchronized public String getHostnameVerification() {
return identificationAlg;
synchronized public void setSSLParameters(SSLParameters params) {
super.setSSLParameters(params);
// the super implementation does not handle the following parameters
identificationProtocol = params.getEndpointIdentificationAlgorithm();
algorithmConstraints = params.getAlgorithmConstraints();
if ((handshaker != null) && !handshaker.started()) {
handshaker.setIdentificationProtocol(identificationProtocol);
handshaker.setAlgorithmConstraints(algorithmConstraints);
}
}
/**

View File

@ -31,11 +31,14 @@ import java.net.InetAddress;
import java.net.Socket;
import java.net.ServerSocket;
import java.security.AlgorithmConstraints;
import java.util.*;
import javax.net.ServerSocketFactory;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLParameters;
/**
@ -83,6 +86,12 @@ class SSLServerSocketImpl extends SSLServerSocket
/* could enabledCipherSuites ever complete handshaking? */
private boolean checkedEnabled = false;
// the endpoint identification protocol to use by default
private String identificationProtocol = null;
// The cryptographic algorithm constraints
private AlgorithmConstraints algorithmConstraints = null;
/**
* Create an SSL server socket on a port, using a non-default
* authentication context and a specified connection backlog.
@ -145,7 +154,7 @@ class SSLServerSocketImpl extends SSLServerSocket
}
sslContext = context;
enabledCipherSuites = CipherSuiteList.getDefault();
enabledProtocols = ProtocolList.getDefault();
enabledProtocols = ProtocolList.getDefault(true);
}
/**
@ -238,6 +247,16 @@ class SSLServerSocketImpl extends SSLServerSocket
* rejoining the already-negotiated SSL connection.
*/
public void setUseClientMode(boolean flag) {
/*
* If we need to change the socket mode and the enabled
* protocols haven't specifically been set by the user,
* change them to the corresponding default ones.
*/
if (useServerMode != (!flag) &&
ProtocolList.isDefaultProtocolList(enabledProtocols)) {
enabledProtocols = ProtocolList.getDefault(!flag);
}
useServerMode = !flag;
}
@ -262,6 +281,29 @@ class SSLServerSocketImpl extends SSLServerSocket
return enableSessionCreation;
}
/**
* Returns the SSLParameters in effect for newly accepted connections.
*/
synchronized public SSLParameters getSSLParameters() {
SSLParameters params = super.getSSLParameters();
// the super implementation does not handle the following parameters
params.setEndpointIdentificationAlgorithm(identificationProtocol);
params.setAlgorithmConstraints(algorithmConstraints);
return params;
}
/**
* Applies SSLParameters to newly accepted connections.
*/
synchronized public void setSSLParameters(SSLParameters params) {
super.setSSLParameters(params);
// the super implementation does not handle the following parameters
identificationProtocol = params.getEndpointIdentificationAlgorithm();
algorithmConstraints = params.getAlgorithmConstraints();
}
/**
* Accept a new SSL connection. This server identifies itself with
@ -269,67 +311,15 @@ class SSLServerSocketImpl extends SSLServerSocket
* presented during construction.
*/
public Socket accept() throws IOException {
checkEnabledSuites();
SSLSocketImpl s = new SSLSocketImpl(sslContext, useServerMode,
enabledCipherSuites, doClientAuth, enableSessionCreation,
enabledProtocols);
enabledProtocols, identificationProtocol, algorithmConstraints);
implAccept(s);
s.doneConnect();
return s;
}
/*
* This is a sometimes helpful diagnostic check that is performed
* once for each ServerSocket to verify that the initial set of
* enabled suites are capable of supporting a successful handshake.
*/
private void checkEnabledSuites() throws IOException {
//
// We want to report an error if no cipher suites were actually
// enabled, since this is an error users are known to make. Then
// they get vastly confused by having clients report an error!
//
synchronized (this) {
if (checkedEnabled) {
return;
}
if (useServerMode == false) {
return;
}
SSLSocketImpl tmp = new SSLSocketImpl(sslContext, useServerMode,
enabledCipherSuites, doClientAuth,
enableSessionCreation, enabledProtocols);
try {
ServerHandshaker handshaker = tmp.getServerHandshaker();
for (Iterator<CipherSuite> t = enabledCipherSuites.iterator();
t.hasNext();) {
CipherSuite suite = t.next();
if (handshaker.trySetCipherSuite(suite)) {
checkedEnabled = true;
return;
}
}
} finally {
tmp.closeSocket();
}
//
// diagnostic text here is currently appropriate
// since it's only certificate unavailability that can
// cause such problems ... but that might change someday.
//
throw new SSLException("No available certificate or key corresponds"
+ " to the SSL cipher suites which are enabled.");
}
}
/**
* Provides a brief description of this SSL socket.
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -31,6 +31,8 @@ import java.net.*;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import java.util.Arrays;
import java.util.Collection;
import java.security.Principal;
import java.security.PrivateKey;
@ -47,6 +49,8 @@ import javax.net.ssl.SSLSessionBindingEvent;
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLPermission;
import javax.net.ssl.SSLException;
import javax.net.ssl.ExtendedSSLSession;
import javax.security.auth.x500.X500Principal;
@ -71,7 +75,7 @@ import static sun.security.ssl.CipherSuite.KeyExchange.*;
*
* @author David Brownell
*/
final class SSLSessionImpl implements SSLSession {
final class SSLSessionImpl extends ExtendedSSLSession {
/*
* we only really need a single null session
@ -89,7 +93,7 @@ final class SSLSessionImpl implements SSLSession {
private final SessionId sessionId;
private X509Certificate[] peerCerts;
private byte compressionMethod;
private final CipherSuite cipherSuite;
private CipherSuite cipherSuite;
private SecretKey masterSecret;
/*
@ -105,6 +109,8 @@ final class SSLSessionImpl implements SSLSession {
private boolean invalidated;
private X509Certificate[] localCerts;
private PrivateKey localPrivateKey;
private String[] localSupportedSignAlgs;
private String[] peerSupportedSignAlgs;
// Principals for non-certificate based cipher suites
private Principal peerPrincipal;
@ -132,8 +138,8 @@ final class SSLSessionImpl implements SSLSession {
* first opened and before handshaking begins.
*/
private SSLSessionImpl() {
this(ProtocolVersion.NONE, CipherSuite.C_NULL,
new SessionId(false, null), null, -1);
this(ProtocolVersion.NONE, CipherSuite.C_NULL, null,
new SessionId(false, null), null, -1);
}
/*
@ -142,8 +148,9 @@ final class SSLSessionImpl implements SSLSession {
* is intended mostly for use by serves.
*/
SSLSessionImpl(ProtocolVersion protocolVersion, CipherSuite cipherSuite,
Collection<SignatureAndHashAlgorithm> algorithms,
SecureRandom generator, String host, int port) {
this(protocolVersion, cipherSuite,
this(protocolVersion, cipherSuite, algorithms,
new SessionId(defaultRejoinable, generator), host, port);
}
@ -151,6 +158,7 @@ final class SSLSessionImpl implements SSLSession {
* Record a new session, using a given cipher spec and session ID.
*/
SSLSessionImpl(ProtocolVersion protocolVersion, CipherSuite cipherSuite,
Collection<SignatureAndHashAlgorithm> algorithms,
SessionId id, String host, int port) {
this.protocolVersion = protocolVersion;
sessionId = id;
@ -161,9 +169,11 @@ final class SSLSessionImpl implements SSLSession {
this.host = host;
this.port = port;
sessionCount = ++counter;
localSupportedSignAlgs =
SignatureAndHashAlgorithm.getAlgorithmNames(algorithms);
if (debug != null && Debug.isOn("session")) {
System.out.println("%% Created: " + this);
System.out.println("%% Initialized: " + this);
}
}
@ -196,6 +206,12 @@ final class SSLSessionImpl implements SSLSession {
localPrivateKey = privateKey;
}
void setPeerSupportedSignatureAlgorithms(
Collection<SignatureAndHashAlgorithm> algorithms) {
peerSupportedSignAlgs =
SignatureAndHashAlgorithm.getAlgorithmNames(algorithms);
}
/**
* Set the peer principal.
*/
@ -292,6 +308,17 @@ final class SSLSessionImpl implements SSLSession {
return cipherSuite;
}
/**
* Resets the cipher spec in use on this session
*/
void setSuite(CipherSuite suite) {
cipherSuite = suite;
if (debug != null && Debug.isOn("session")) {
System.out.println("%% Negotiating: " + this);
}
}
/**
* Returns the name of the cipher suite in use on this session
*/
@ -718,6 +745,30 @@ final class SSLSessionImpl implements SSLSession {
return getPacketBufferSize() - Record.headerSize;
}
/**
* Gets an array of supported signature algorithms that the local side is
* willing to verify.
*/
public String[] getLocalSupportedSignatureAlgorithms() {
if (localSupportedSignAlgs != null) {
return localSupportedSignAlgs.clone();
}
return new String[0];
}
/**
* Gets an array of supported signature algorithms that the peer is
* able to verify.
*/
public String[] getPeerSupportedSignatureAlgorithms() {
if (peerSupportedSignAlgs != null) {
return peerSupportedSignAlgs.clone();
}
return new String[0];
}
/** Returns a string representation of this SSL session */
public String toString() {
return "[Session-" + sessionCount

View File

@ -32,6 +32,7 @@ import java.security.GeneralSecurityException;
import java.security.AccessController;
import java.security.AccessControlContext;
import java.security.PrivilegedAction;
import java.security.AlgorithmConstraints;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
@ -194,15 +195,27 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
*/
private byte doClientAuth;
private boolean roleIsServer;
private CipherSuiteList enabledCipherSuites;
private boolean enableSessionCreation = true;
private String host;
private boolean autoClose = true;
private AccessControlContext acc;
// hostname identification algorithm, the hostname identification is
// disabled by default.
private String identificationAlg = null;
/*
* We cannot use the hostname resolved from name services. For
* virtual hosting, multiple hostnames may be bound to the same IP
* address, so the hostname resolved from name services is not
* reliable.
*/
private String rawHostname;
// The cipher suites enabled for use on this connection.
private CipherSuiteList enabledCipherSuites;
// The endpoint identification protocol
private String identificationProtocol = null;
// The cryptographic algorithm constraints
private AlgorithmConstraints algorithmConstraints = null;
/*
* READ ME * READ ME * READ ME * READ ME * READ ME * READ ME *
@ -312,8 +325,9 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
* is associated with a session at the same time. (TLS/IETF may
* change that to add client authentication w/o new key exchg.)
*/
private SSLSessionImpl sess;
private Handshaker handshaker;
private Handshaker handshaker;
private SSLSessionImpl sess;
private volatile SSLSessionImpl handshakeSession;
/*
@ -341,11 +355,11 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
private AppOutputStream output;
/*
* The protocols we support are SSL Version 3.0) and
* TLS (version 3.1).
* In addition we support a pseudo protocol called
* SSLv2Hello which when set will result in an SSL v2 Hello
* being sent with SSLv3 or TLSv1 version info.
* The protocol versions enabled for use on this connection.
*
* Note: we support a pseudo protocol called SSLv2Hello which when
* set will result in an SSL v2 Hello being sent with SSL (version 3.0)
* or TLS (version 3.1, 3.2, etc.) version info.
*/
private ProtocolList enabledProtocols;
@ -374,6 +388,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
throws IOException, UnknownHostException {
super();
this.host = host;
this.rawHostname = host;
init(context, false);
SocketAddress socketAddress =
host != null ? new InetSocketAddress(host, port) :
@ -416,6 +431,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
throws IOException, UnknownHostException {
super();
this.host = host;
this.rawHostname = host;
init(context, false);
bind(new InetSocketAddress(localAddr, localPort));
SocketAddress socketAddress =
@ -455,11 +471,15 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
*/
SSLSocketImpl(SSLContextImpl context, boolean serverMode,
CipherSuiteList suites, byte clientAuth,
boolean sessionCreation, ProtocolList protocols)
throws IOException {
boolean sessionCreation, ProtocolList protocols,
String identificationProtocol,
AlgorithmConstraints algorithmConstraints) throws IOException {
super();
doClientAuth = clientAuth;
enableSessionCreation = sessionCreation;
this.identificationProtocol = identificationProtocol;
this.algorithmConstraints = algorithmConstraints;
init(context, serverMode);
/*
@ -506,6 +526,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
throw new SocketException("Underlying socket is not connected");
}
this.host = host;
this.rawHostname = host;
init(context, false);
this.autoClose = autoClose;
doneConnect();
@ -517,6 +538,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
private void init(SSLContextImpl context, boolean isServer) {
sslContext = context;
sess = SSLSessionImpl.nullSession;
handshakeSession = null;
/*
* role is as specified, state is START until after
@ -541,7 +563,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
serverVerifyData = new byte[0];
enabledCipherSuites = CipherSuiteList.getDefault();
enabledProtocols = ProtocolList.getDefault();
enabledProtocols = ProtocolList.getDefault(roleIsServer);
inrec = null;
// save the acc
@ -764,6 +786,21 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
r.addMAC(writeMAC);
r.encrypt(writeCipher);
r.write(sockOutput);
/*
* Check the sequence number state
*
* Note that in order to maintain the connection I/O
* properly, we check the sequence number after the last
* record writing process. As we request renegotiation
* or close the connection for wrapped sequence number
* when there is enough sequence number space left to
* handle a few more records, so the sequence number
* of the last record cannot be wrapped.
*/
if (connectionState < cs_ERROR) {
checkSequenceNumber(writeMAC, r.contentType());
}
}
@ -883,6 +920,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
}
}
// if (!r.decompress(c))
// fatal(Alerts.alert_decompression_failure,
// "decompression failure");
@ -905,6 +943,15 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
* in it.
*/
initHandshaker();
if (!handshaker.activated()) {
// prior to handshaking, activate the handshake
if (connectionState == cs_RENEGOTIATE) {
// don't use SSLv2Hello when renegotiating
handshaker.activate(protocolVersion);
} else {
handshaker.activate(null);
}
}
/*
* process the handshake record ... may contain just
@ -930,6 +977,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
serverVerifyData = handshaker.getServerVerifyData();
sess = handshaker.getSession();
handshakeSession = null;
handshaker = null;
connectionState = cs_DATA;
@ -949,9 +997,8 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
if (needAppData || connectionState != cs_DATA) {
continue;
} else {
return;
}
break;
case Record.ct_application_data:
// Pass this right back up to the application.
@ -971,7 +1018,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
}
r.setAppDataValid(true);
return;
break;
case Record.ct_alert:
recvAlert(r);
@ -1010,6 +1057,23 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
}
continue;
} // switch
/*
* Check the sequence number state
*
* Note that in order to maintain the connection I/O
* properly, we check the sequence number after the last
* record reading process. As we request renegotiation
* or close the connection for wrapped sequence number
* when there is enough sequence number space left to
* handle a few more records, so the sequence number
* of the last record cannot be wrapped.
*/
if (connectionState < cs_ERROR) {
checkSequenceNumber(readMAC, r.contentType());
}
return;
} // synchronized (this)
}
@ -1021,6 +1085,61 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
} // synchronized (readLock)
}
/**
* Check the sequence number state
*
* RFC 4346 states that, "Sequence numbers are of type uint64 and
* may not exceed 2^64-1. Sequence numbers do not wrap. If a TLS
* implementation would need to wrap a sequence number, it must
* renegotiate instead."
*/
private void checkSequenceNumber(MAC mac, byte type)
throws IOException {
/*
* Don't bother to check the sequence number for error or
* closed connections, or NULL MAC.
*/
if (connectionState >= cs_ERROR || mac == MAC.NULL) {
return;
}
/*
* Conservatively, close the connection immediately when the
* sequence number is close to overflow
*/
if (mac.seqNumOverflow()) {
/*
* TLS protocols do not define a error alert for sequence
* number overflow. We use handshake_failure error alert
* for handshaking and bad_record_mac for other records.
*/
if (debug != null && Debug.isOn("ssl")) {
System.out.println(threadName() +
", sequence number extremely close to overflow " +
"(2^64-1 packets). Closing connection.");
}
fatal(Alerts.alert_handshake_failure, "sequence number overflow");
}
/*
* Ask for renegotiation when need to renew sequence number.
*
* Don't bother to kickstart the renegotiation when the local is
* asking for it.
*/
if ((type != Record.ct_handshake) && mac.seqNumIsHuge()) {
if (debug != null && Debug.isOn("ssl")) {
System.out.println(threadName() + ", request renegotiation " +
"to avoid sequence number overflow");
}
startHandshake();
}
}
//
// HANDSHAKE RELATED CODE
//
@ -1033,28 +1152,10 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
}
/**
* Initialize and get the server handshaker. Used by SSLServerSocketImpl
* for the ciphersuite availability test *only*.
* Return the AppOutputStream. For use by Handshaker only.
*/
ServerHandshaker getServerHandshaker() throws SSLException {
initHandshaker();
// The connection state would have been set to cs_HANDSHAKE during the
// handshaking initializing, however the caller may not have the
// the low level connection's established, which is not consistent with
// the HANDSHAKE state. As if it is unconnected, we need to reset the
// connection state to cs_START.
if (!isConnected()) {
connectionState = cs_START;
}
// Make sure that we get a ServerHandshaker.
// This should never happen.
if (!(handshaker instanceof ServerHandshaker)) {
throw new SSLProtocolException("unexpected handshaker instance");
}
return (ServerHandshaker)handshaker;
AppOutputStream getAppOutputStream() {
return output;
}
/**
@ -1066,8 +1167,8 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
* . if the socket is already closed, throw an Exception (internal error)
*
* . otherwise (cs_START or cs_DATA), create the appropriate handshaker
* object, initialize it, and advance the connection state (to
* cs_HANDSHAKE or cs_RENEGOTIATE, respectively).
* object, and advance the connection state (to cs_HANDSHAKE or
* cs_RENEGOTIATE, respectively).
*
* This method is called right after a new socket is created, when
* starting renegotiation, or when changing client/ server mode of the
@ -1115,12 +1216,8 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
protocolVersion, connectionState == cs_HANDSHAKE,
secureRenegotiation, clientVerifyData, serverVerifyData);
}
handshaker.enabledCipherSuites = enabledCipherSuites;
handshaker.setEnabledCipherSuites(enabledCipherSuites);
handshaker.setEnableSessionCreation(enableSessionCreation);
if (connectionState == cs_RENEGOTIATE) {
// don't use SSLv2Hello when renegotiating
handshaker.output.r.setHelloVersion(protocolVersion);
}
}
/**
@ -1135,6 +1232,8 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
// one thread performs the handshake
synchronized (handshakeLock) {
if (getConnectionState() == cs_HANDSHAKE) {
kickstartHandshake();
/*
* All initial handshaking goes through this
* InputRecord until we have a valid SSL connection.
@ -1157,7 +1256,6 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
inrec.enableFormatChecks();
}
kickstartHandshake();
readRecord(inrec, false);
inrec = null;
}
@ -1211,6 +1309,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
* on servers when renegotiating).
*/
private synchronized void kickstartHandshake() throws IOException {
switch (connectionState) {
case cs_HANDSHAKE:
@ -1257,7 +1356,15 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
// to its HandshakeOutStream, which calls back into
// SSLSocketImpl.writeRecord() to send it.
//
if (!handshaker.started()) {
if (!handshaker.activated()) {
// prior to handshaking, activate the handshake
if (connectionState == cs_RENEGOTIATE) {
// don't use SSLv2Hello when renegotiating
handshaker.activate(protocolVersion);
} else {
handshaker.activate(null);
}
if (handshaker instanceof ClientHandshaker) {
// send client hello
handshaker.kickstart();
@ -1646,6 +1753,9 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
input.r.close();
}
sess.invalidate();
if (handshakeSession != null) {
handshakeSession.invalidate();
}
int oldState = connectionState;
connectionState = cs_ERROR;
@ -1752,10 +1862,18 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
* Emit alerts. Caller must have synchronized with "this".
*/
private void sendAlert(byte level, byte description) {
// the connectionState cannot be cs_START
if (connectionState >= cs_SENT_CLOSE) {
return;
}
// For initial handshaking, don't send alert message to peer if
// handshaker has not started.
if (connectionState == cs_HANDSHAKE &&
(handshaker == null || !handshaker.started())) {
return;
}
OutputRecord r = new OutputRecord(Record.ct_alert);
r.setVersion(protocolVersion);
@ -1878,9 +1996,14 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
return host;
}
synchronized String getRawHostname() {
return rawHostname;
}
// ONLY used by HttpsClient to setup the URI specified hostname
synchronized public void setHost(String host) {
this.host = host;
this.rawHostname = host;
}
/**
@ -1951,6 +2074,15 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
}
}
@Override
synchronized public SSLSession getHandshakeSession() {
return handshakeSession;
}
synchronized void setHandshakeSession(SSLSessionImpl session) {
handshakeSession = session;
}
/**
* Controls whether new connections may cause creation of new SSL
* sessions.
@ -1962,7 +2094,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
synchronized public void setEnableSessionCreation(boolean flag) {
enableSessionCreation = flag;
if ((handshaker != null) && !handshaker.started()) {
if ((handshaker != null) && !handshaker.activated()) {
handshaker.setEnableSessionCreation(enableSessionCreation);
}
}
@ -1990,7 +2122,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
if ((handshaker != null) &&
(handshaker instanceof ServerHandshaker) &&
!handshaker.started()) {
!handshaker.activated()) {
((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
}
}
@ -2013,7 +2145,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
if ((handshaker != null) &&
(handshaker instanceof ServerHandshaker) &&
!handshaker.started()) {
!handshaker.activated()) {
((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
}
}
@ -2032,6 +2164,15 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
switch (connectionState) {
case cs_START:
/*
* If we need to change the socket mode and the enabled
* protocols haven't specifically been set by the user,
* change them to the corresponding default ones.
*/
if (roleIsServer != (!flag) &&
ProtocolList.isDefaultProtocolList(enabledProtocols)) {
enabledProtocols = ProtocolList.getDefault(!flag);
}
roleIsServer = !flag;
break;
@ -2044,7 +2185,16 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
* have the streams.
*/
assert(handshaker != null);
if (!handshaker.started()) {
if (!handshaker.activated()) {
/*
* If we need to change the socket mode and the enabled
* protocols haven't specifically been set by the user,
* change them to the corresponding default ones.
*/
if (roleIsServer != (!flag) &&
ProtocolList.isDefaultProtocolList(enabledProtocols)) {
enabledProtocols = ProtocolList.getDefault(!flag);
}
roleIsServer = !flag;
connectionState = cs_START;
initHandshaker();
@ -2095,8 +2245,8 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
*/
synchronized public void setEnabledCipherSuites(String[] suites) {
enabledCipherSuites = new CipherSuiteList(suites);
if ((handshaker != null) && !handshaker.started()) {
handshaker.enabledCipherSuites = enabledCipherSuites;
if ((handshaker != null) && !handshaker.activated()) {
handshaker.setEnabledCipherSuites(enabledCipherSuites);
}
}
@ -2118,7 +2268,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
/**
* Returns the protocols that are supported by this implementation.
* A subset of the supported protocols may be enabled for this connection
* @ returns an array of protocol names.
* @return an array of protocol names.
*/
public String[] getSupportedProtocols() {
return ProtocolList.getSupported().toStringArray();
@ -2135,7 +2285,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
*/
synchronized public void setEnabledProtocols(String[] protocols) {
enabledProtocols = new ProtocolList(protocols);
if ((handshaker != null) && !handshaker.started()) {
if ((handshaker != null) && !handshaker.activated()) {
handshaker.setEnabledProtocols(enabledProtocols);
}
}
@ -2194,28 +2344,31 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
}
/**
* Try to configure the endpoint identification algorithm of the socket.
*
* @param identificationAlgorithm the algorithm used to check the
* endpoint identity.
* @return true if the identification algorithm configuration success.
* Returns the SSLParameters in effect for this SSLSocket.
*/
synchronized public boolean trySetHostnameVerification(
String identificationAlgorithm) {
if (sslContext.getX509TrustManager() instanceof
X509ExtendedTrustManager) {
this.identificationAlg = identificationAlgorithm;
return true;
} else {
return false;
}
synchronized public SSLParameters getSSLParameters() {
SSLParameters params = super.getSSLParameters();
// the super implementation does not handle the following parameters
params.setEndpointIdentificationAlgorithm(identificationProtocol);
params.setAlgorithmConstraints(algorithmConstraints);
return params;
}
/**
* Returns the endpoint identification algorithm of the socket.
* Applies SSLParameters to this socket.
*/
synchronized public String getHostnameVerification() {
return identificationAlg;
synchronized public void setSSLParameters(SSLParameters params) {
super.setSSLParameters(params);
// the super implementation does not handle the following parameters
identificationProtocol = params.getEndpointIdentificationAlgorithm();
algorithmConstraints = params.getAlgorithmConstraints();
if ((handshaker != null) && !handshaker.started()) {
handshaker.setIdentificationProtocol(identificationProtocol);
handshaker.setAlgorithmConstraints(algorithmConstraints);
}
}
//

Some files were not shown because too many files have changed in this diff Show More