Merge
This commit is contained in:
commit
fba090f3e8
@ -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 \
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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 \
|
||||
|
@ -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
|
||||
|
@ -355,7 +355,6 @@ JavaMain(void * _args)
|
||||
|
||||
JavaVM *vm = 0;
|
||||
JNIEnv *env = 0;
|
||||
jstring mainClassName;
|
||||
jclass mainClass;
|
||||
jmethodID mainID;
|
||||
jobjectArray mainArgs;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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])) &&
|
||||
|
@ -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++) {
|
||||
|
@ -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);
|
||||
|
@ -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>).
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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";
|
||||
}
|
||||
|
@ -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>.
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
}
|
||||
|
58
jdk/src/share/classes/java/io/SerialCallbackContext.java
Normal file
58
jdk/src/share/classes/java/io/SerialCallbackContext.java
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
*
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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]
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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<SocketAddress,ByteBuffer>() {
|
||||
* 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, (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);
|
||||
}
|
@ -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} </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>
|
||||
|
@ -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;
|
||||
}
|
||||
|
108
jdk/src/share/classes/java/security/AlgorithmConstraints.java
Normal file
108
jdk/src/share/classes/java/security/AlgorithmConstraints.java
Normal 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);
|
||||
|
||||
}
|
83
jdk/src/share/classes/java/security/CryptoPrimitive.java
Normal file
83
jdk/src/share/classes/java/security/CryptoPrimitive.java
Normal 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
|
||||
}
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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."));
|
||||
}
|
||||
}
|
||||
|
@ -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>.
|
||||
|
@ -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" />
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
86
jdk/src/share/classes/javax/net/ssl/ExtendedSSLSession.java
Normal file
86
jdk/src/share/classes/javax/net/ssl/ExtendedSSLSession.java
Normal 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 & 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 & 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();
|
||||
}
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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 & Reference </a>
|
||||
* for information about standard algorithm names.
|
||||
*
|
||||
* @see X509ExtendedTrustManager
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public void setEndpointIdentificationAlgorithm(String algorithm) {
|
||||
this.identificationAlgorithm = algorithm;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
}
|
@ -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");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
//
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -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();
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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(
|
||||
|
@ -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 =
|
||||
|
@ -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!
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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");
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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
|
||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user