提交 31d15533 编写于 作者: X xuelei

6916074: Add support for TLS 1.2

6985179: To support Server Name Indication extension for JSSE client
Summary: Introduces the algorithm constraints to support signature and hash algorithm selection. Includes contributions from wetmore and weijung.
Reviewed-by: wetmore, weijun
上级 73f7c6a8
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -253,7 +253,8 @@ final class AESCrypt extends SymmetricCipher implements AESConstants ...@@ -253,7 +253,8 @@ final class AESCrypt extends SymmetricCipher implements AESConstants
for (j = 0; j < 8; j++) { for (j = 0; j < 8; j++) {
if (AA[i][j] != 0) { if (AA[i][j] != 0) {
AA[i][j] = (byte) 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++) { for (t = 0; t < 4; t++) {
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -92,7 +92,8 @@ public final class ARCFOURCipher extends CipherSpi { ...@@ -92,7 +92,8 @@ public final class ARCFOURCipher extends CipherSpi {
} }
// core crypt code. OFB style, so works for both encryption and decryption // 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) { if (is < 0) {
// doFinal() was called, need to reset the cipher to initial state // doFinal() was called, need to reset the cipher to initial state
init(lastKey); init(lastKey);
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -31,8 +31,8 @@ import javax.crypto.*; ...@@ -31,8 +31,8 @@ import javax.crypto.*;
import javax.crypto.spec.*; import javax.crypto.spec.*;
/** /**
* This class implements the DESede algorithm (DES-EDE, tripleDES) in its various * This class implements the DESede algorithm (DES-EDE, tripleDES) in
* modes (<code>ECB</code>, <code>CFB</code>, <code>OFB</code>, * its various modes (<code>ECB</code>, <code>CFB</code>, <code>OFB</code>,
* <code>CBC</code>, <code>PCBC</code>) and padding schemes * <code>CBC</code>, <code>PCBC</code>) and padding schemes
* (<code>PKCS5Padding</code>, <code>NoPadding</code>, * (<code>PKCS5Padding</code>, <code>NoPadding</code>,
* <code>ISO10126Padding</code>). * <code>ISO10126Padding</code>).
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -190,7 +190,8 @@ javax.crypto.interfaces.DHPrivateKey, Serializable { ...@@ -190,7 +190,8 @@ javax.crypto.interfaces.DHPrivateKey, Serializable {
ike.initCause(e); ike.initCause(e);
throw ike; throw ike;
} catch (IOException e) { } 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); ike.initCause(e);
throw ike; throw ike;
} }
...@@ -300,7 +301,8 @@ javax.crypto.interfaces.DHPrivateKey, Serializable { ...@@ -300,7 +301,8 @@ javax.crypto.interfaces.DHPrivateKey, Serializable {
DerInputStream in = new DerInputStream(this.key); DerInputStream in = new DerInputStream(this.key);
this.x = in.getBigInteger(); this.x = in.getBigInteger();
} catch (IOException e) { } 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); ike.initCause(e);
throw ike; throw ike;
} }
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -180,7 +180,8 @@ javax.crypto.interfaces.DHPublicKey, Serializable { ...@@ -180,7 +180,8 @@ javax.crypto.interfaces.DHPublicKey, Serializable {
throw new InvalidKeyException("Private-value length too big"); throw new InvalidKeyException("Private-value length too big");
} catch (IOException e) { } 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 { ...@@ -281,7 +282,8 @@ javax.crypto.interfaces.DHPublicKey, Serializable {
DerInputStream in = new DerInputStream(this.key); DerInputStream in = new DerInputStream(this.key);
this.y = in.getBigInteger(); this.y = in.getBigInteger();
} catch (IOException e) { } catch (IOException e) {
throw new InvalidKeyException("Error parsing key encoding: " + e.toString()); throw new InvalidKeyException(
"Error parsing key encoding: " + e.toString());
} }
} }
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -764,7 +764,8 @@ public final class JceKeyStore extends KeyStoreSpi { ...@@ -764,7 +764,8 @@ public final class JceKeyStore extends KeyStoreSpi {
cf = (CertificateFactory)cfs.get(certType); cf = (CertificateFactory)cfs.get(certType);
} else { } else {
// create new certificate factory // create new certificate factory
cf = CertificateFactory.getInstance(certType); cf = CertificateFactory.getInstance(
certType);
// store the certificate factory so we can // store the certificate factory so we can
// reuse it later // reuse it later
cfs.put(certType, cf); cfs.put(certType, cf);
...@@ -863,8 +864,9 @@ public final class JceKeyStore extends KeyStoreSpi { ...@@ -863,8 +864,9 @@ public final class JceKeyStore extends KeyStoreSpi {
dis.readFully(actual); dis.readFully(actual);
for (int i = 0; i < computed.length; i++) { for (int i = 0; i < computed.length; i++) {
if (computed[i] != actual[i]) { if (computed[i] != actual[i]) {
throw new IOException("Keystore was tampered with, or " throw new IOException(
+ "password was incorrect"); "Keystore was tampered with, or "
+ "password was incorrect");
} }
} }
} }
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -139,7 +139,8 @@ public final class OAEPParameters extends AlgorithmParametersSpi { ...@@ -139,7 +139,8 @@ public final class OAEPParameters extends AlgorithmParametersSpi {
if (!val.getOID().equals((Object) OID_MGF1)) { if (!val.getOID().equals((Object) OID_MGF1)) {
throw new IOException("Only MGF1 mgf is supported"); 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()); String mgfDigestName = convertToStandardName(params.getName());
if (mgfDigestName.equals("SHA-1")) { if (mgfDigestName.equals("SHA-1")) {
mgfSpec = MGF1ParameterSpec.SHA1; mgfSpec = MGF1ParameterSpec.SHA1;
...@@ -150,7 +151,8 @@ public final class OAEPParameters extends AlgorithmParametersSpi { ...@@ -150,7 +151,8 @@ public final class OAEPParameters extends AlgorithmParametersSpi {
} else if (mgfDigestName.equals("SHA-512")) { } else if (mgfDigestName.equals("SHA-512")) {
mgfSpec = MGF1ParameterSpec.SHA512; mgfSpec = MGF1ParameterSpec.SHA512;
} else { } else {
throw new IOException("Unrecognized message digest algorithm"); throw new IOException(
"Unrecognized message digest algorithm");
} }
} else if (data.isContextSpecific((byte) 0x02)) { } else if (data.isContextSpecific((byte) 0x02)) {
// pSource algid // pSource algid
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -121,8 +121,8 @@ final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey { ...@@ -121,8 +121,8 @@ final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey {
this.key = deriveKey(prf, passwdBytes, salt, iterCount, keyLength); this.key = deriveKey(prf, passwdBytes, salt, iterCount, keyLength);
} }
private static byte[] deriveKey(final Mac prf, final byte[] password, byte[] salt, private static byte[] deriveKey(final Mac prf, final byte[] password,
int iterCount, int keyLengthInBit) { byte[] salt, int iterCount, int keyLengthInBit) {
int keyLength = keyLengthInBit/8; int keyLength = keyLengthInBit/8;
byte[] key = new byte[keyLength]; byte[] key = new byte[keyLength];
try { try {
...@@ -155,8 +155,9 @@ final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey { ...@@ -155,8 +155,9 @@ final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey {
if (this == obj) return true; if (this == obj) return true;
if (this.getClass() != obj.getClass()) return false; if (this.getClass() != obj.getClass()) return false;
SecretKey sk = (SecretKey)obj; SecretKey sk = (SecretKey)obj;
return prf.getAlgorithm().equalsIgnoreCase(sk.getAlgorithm()) && return prf.getAlgorithm().equalsIgnoreCase(
Arrays.equals(password, sk.getEncoded()); sk.getAlgorithm()) &&
Arrays.equals(password, sk.getEncoded());
} }
}; };
prf.init(macKey); prf.init(macKey);
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -206,7 +206,8 @@ final class PKCS12PBECipherCore { ...@@ -206,7 +206,8 @@ final class PKCS12PBECipherCore {
(algo.equalsIgnoreCase("RC2")?"RC2_40":algo), "SunJCE"); (algo.equalsIgnoreCase("RC2")?"RC2_40":algo), "SunJCE");
} catch (GeneralSecurityException gse) { } catch (GeneralSecurityException gse) {
// should never happen // should never happen
throw new RuntimeException("SunJCE provider is not configured properly"); throw new RuntimeException(
"SunJCE provider is not configured properly");
} }
try { try {
params.init(pbeSpec); params.init(pbeSpec);
...@@ -316,7 +317,8 @@ final class PKCS12PBECipherCore { ...@@ -316,7 +317,8 @@ final class PKCS12PBECipherCore {
try { try {
paramSpec = params.getParameterSpec(PBEParameterSpec.class); paramSpec = params.getParameterSpec(PBEParameterSpec.class);
} catch (InvalidParameterSpecException ipse) { } catch (InvalidParameterSpecException ipse) {
throw new InvalidAlgorithmParameterException("requires PBE parameters"); throw new InvalidAlgorithmParameterException(
"requires PBE parameters");
} }
} }
implInit(opmode, key, paramSpec, random); implInit(opmode, key, paramSpec, random);
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -423,15 +423,31 @@ public final class SunJCE extends Provider { ...@@ -423,15 +423,31 @@ public final class SunJCE extends Provider {
/* /*
* SSL/TLS mechanisms * 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", put("KeyGenerator.SunTlsPrf",
"com.sun.crypto.provider.TlsPrfGenerator"); "com.sun.crypto.provider.TlsPrfGenerator$V10");
put("KeyGenerator.SunTlsRsaPremasterSecret", put("KeyGenerator.SunTls12Prf",
"com.sun.crypto.provider.TlsRsaPremasterSecretGenerator"); "com.sun.crypto.provider.TlsPrfGenerator$V12");
put("KeyGenerator.SunTlsMasterSecret", put("KeyGenerator.SunTlsMasterSecret",
"com.sun.crypto.provider.TlsMasterSecretGenerator"); "com.sun.crypto.provider.TlsMasterSecretGenerator");
put("Alg.Alias.KeyGenerator.SunTls12MasterSecret",
"SunTlsMasterSecret");
put("KeyGenerator.SunTlsKeyMaterial", 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; return null;
} }
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -65,12 +65,14 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi { ...@@ -65,12 +65,14 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
} }
this.spec = (TlsKeyMaterialParameterSpec)params; this.spec = (TlsKeyMaterialParameterSpec)params;
if ("RAW".equals(spec.getMasterSecret().getFormat()) == false) { 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(); protocolVersion = (spec.getMajorVersion() << 8)
if ((protocolVersion < 0x0300) || (protocolVersion > 0x0302)) { | spec.getMinorVersion();
throw new InvalidAlgorithmParameterException if ((protocolVersion < 0x0300) || (protocolVersion > 0x0303)) {
("Only SSL 3.0, TLS 1.0, and TLS 1.1 supported"); 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 { ...@@ -80,8 +82,8 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
protected SecretKey engineGenerateKey() { protected SecretKey engineGenerateKey() {
if (spec == null) { if (spec == null) {
throw new IllegalStateException throw new IllegalStateException(
("TlsKeyMaterialGenerator must be initialized"); "TlsKeyMaterialGenerator must be initialized");
} }
try { try {
return engineGenerateKey0(); return engineGenerateKey0();
...@@ -99,8 +101,8 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi { ...@@ -99,8 +101,8 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
SecretKey clientMacKey = null; SecretKey clientMacKey = null;
SecretKey serverMacKey = null; SecretKey serverMacKey = null;
SecretKey clientCipherKey = null; SecretKey clientCipherKey = null;
IvParameterSpec clientIv = null;
SecretKey serverCipherKey = null; SecretKey serverCipherKey = null;
IvParameterSpec clientIv = null;
IvParameterSpec serverIv = null; IvParameterSpec serverIv = null;
int macLength = spec.getMacKeyLength(); int macLength = spec.getMacKeyLength();
...@@ -109,21 +111,33 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi { ...@@ -109,21 +111,33 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
int keyLength = spec.getCipherKeyLength(); int keyLength = spec.getCipherKeyLength();
int ivLength = spec.getIvLength(); int ivLength = spec.getIvLength();
int keyBlockLen = macLength + keyLength + (isExportable ? 0 : ivLength); int keyBlockLen = macLength + keyLength
+ (isExportable ? 0 : ivLength);
keyBlockLen <<= 1; keyBlockLen <<= 1;
byte[] keyBlock = new byte[keyBlockLen]; byte[] keyBlock = new byte[keyBlockLen];
MessageDigest md5 = MessageDigest.getInstance("MD5"); // These may be used again later for exportable suite calculations.
MessageDigest sha = MessageDigest.getInstance("SHA1"); MessageDigest md5 = null;
MessageDigest sha = null;
// generate key block // generate key block
if (protocolVersion >= 0x0301) { if (protocolVersion >= 0x0303) {
// TLS // TLS 1.2
byte[] seed = concat(serverRandom, clientRandom);
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); byte[] seed = concat(serverRandom, clientRandom);
keyBlock = doPRF(masterSecret, LABEL_KEY_EXPANSION, seed, keyBlock = doTLS10PRF(masterSecret, LABEL_KEY_EXPANSION, seed,
keyBlockLen, md5, sha); keyBlockLen, md5, sha);
} else { } else {
// SSL // SSL
md5 = MessageDigest.getInstance("MD5");
sha = MessageDigest.getInstance("SHA1");
keyBlock = new byte[keyBlockLen]; keyBlock = new byte[keyBlockLen];
byte[] tmp = new byte[20]; byte[] tmp = new byte[20];
...@@ -169,6 +183,7 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi { ...@@ -169,6 +183,7 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
String alg = spec.getCipherAlgorithm(); String alg = spec.getCipherAlgorithm();
// cipher keys
byte[] clientKeyBytes = new byte[keyLength]; byte[] clientKeyBytes = new byte[keyLength];
System.arraycopy(keyBlock, ofs, clientKeyBytes, 0, keyLength); System.arraycopy(keyBlock, ofs, clientKeyBytes, 0, keyLength);
ofs += keyLength; ofs += keyLength;
...@@ -182,6 +197,7 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi { ...@@ -182,6 +197,7 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
clientCipherKey = new SecretKeySpec(clientKeyBytes, alg); clientCipherKey = new SecretKeySpec(clientKeyBytes, alg);
serverCipherKey = new SecretKeySpec(serverKeyBytes, alg); serverCipherKey = new SecretKeySpec(serverKeyBytes, alg);
// IV keys if needed.
if (ivLength != 0) { if (ivLength != 0) {
tmp = new byte[ivLength]; tmp = new byte[ivLength];
...@@ -194,21 +210,28 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi { ...@@ -194,21 +210,28 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
serverIv = new IvParameterSpec(tmp); serverIv = new IvParameterSpec(tmp);
} }
} else { } else {
// if exportable suites, calculate the alternate
// cipher key expansion and IV generation // 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); byte[] seed = concat(clientRandom, serverRandom);
tmp = doPRF(clientKeyBytes, LABEL_CLIENT_WRITE_KEY, seed, tmp = doTLS10PRF(clientKeyBytes, LABEL_CLIENT_WRITE_KEY, seed,
expandedKeyLength, md5, sha); expandedKeyLength, md5, sha);
clientCipherKey = new SecretKeySpec(tmp, alg); clientCipherKey = new SecretKeySpec(tmp, alg);
tmp = doPRF(serverKeyBytes, LABEL_SERVER_WRITE_KEY, seed, tmp = doTLS10PRF(serverKeyBytes, LABEL_SERVER_WRITE_KEY, seed,
expandedKeyLength, md5, sha); expandedKeyLength, md5, sha);
serverCipherKey = new SecretKeySpec(tmp, alg); serverCipherKey = new SecretKeySpec(tmp, alg);
if (ivLength != 0) { if (ivLength != 0) {
tmp = new byte[ivLength]; tmp = new byte[ivLength];
byte[] block = doPRF(null, LABEL_IV_BLOCK, seed, byte[] block = doTLS10PRF(null, LABEL_IV_BLOCK, seed,
ivLength << 1, md5, sha); ivLength << 1, md5, sha);
System.arraycopy(block, 0, tmp, 0, ivLength); System.arraycopy(block, 0, tmp, 0, ivLength);
clientIv = new IvParameterSpec(tmp); clientIv = new IvParameterSpec(tmp);
...@@ -216,6 +239,7 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi { ...@@ -216,6 +239,7 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
serverIv = new IvParameterSpec(tmp); serverIv = new IvParameterSpec(tmp);
} }
} else { } else {
// SSLv3
tmp = new byte[expandedKeyLength]; tmp = new byte[expandedKeyLength];
md5.update(clientKeyBytes); md5.update(clientKeyBytes);
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -64,12 +64,14 @@ public final class TlsMasterSecretGenerator extends KeyGeneratorSpi { ...@@ -64,12 +64,14 @@ public final class TlsMasterSecretGenerator extends KeyGeneratorSpi {
} }
this.spec = (TlsMasterSecretParameterSpec)params; this.spec = (TlsMasterSecretParameterSpec)params;
if ("RAW".equals(spec.getPremasterSecret().getFormat()) == false) { 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(); protocolVersion = (spec.getMajorVersion() << 8)
if ((protocolVersion < 0x0300) || (protocolVersion > 0x0302)) { | spec.getMinorVersion();
throw new InvalidAlgorithmParameterException if ((protocolVersion < 0x0300) || (protocolVersion > 0x0303)) {
("Only SSL 3.0, TLS 1.0, and TLS 1.1 supported"); 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 { ...@@ -79,8 +81,8 @@ public final class TlsMasterSecretGenerator extends KeyGeneratorSpi {
protected SecretKey engineGenerateKey() { protected SecretKey engineGenerateKey() {
if (spec == null) { if (spec == null) {
throw new IllegalStateException throw new IllegalStateException(
("TlsMasterSecretGenerator must be initialized"); "TlsMasterSecretGenerator must be initialized");
} }
SecretKey premasterKey = spec.getPremasterSecret(); SecretKey premasterKey = spec.getPremasterSecret();
byte[] premaster = premasterKey.getEncoded(); byte[] premaster = premasterKey.getEncoded();
...@@ -103,7 +105,11 @@ public final class TlsMasterSecretGenerator extends KeyGeneratorSpi { ...@@ -103,7 +105,11 @@ public final class TlsMasterSecretGenerator extends KeyGeneratorSpi {
if (protocolVersion >= 0x0301) { if (protocolVersion >= 0x0301) {
byte[] seed = concat(clientRandom, serverRandom); 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 { } else {
master = new byte[48]; master = new byte[48];
MessageDigest md5 = MessageDigest.getInstance("MD5"); MessageDigest md5 = MessageDigest.getInstance("MD5");
...@@ -124,7 +130,8 @@ public final class TlsMasterSecretGenerator extends KeyGeneratorSpi { ...@@ -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) { } catch (NoSuchAlgorithmException e) {
throw new ProviderException(e); throw new ProviderException(e);
} catch (DigestException e) { } catch (DigestException e) {
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -37,11 +37,15 @@ import sun.security.internal.spec.TlsPrfParameterSpec; ...@@ -37,11 +37,15 @@ import sun.security.internal.spec.TlsPrfParameterSpec;
/** /**
* KeyGenerator implementation for the TLS PRF function. * 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 * @author Andreas Sterbenz
* @since 1.6 * @since 1.6
*/ */
public final class TlsPrfGenerator extends KeyGeneratorSpi { abstract class TlsPrfGenerator extends KeyGeneratorSpi {
// magic constants and utility functions, also used by other files // magic constants and utility functions, also used by other files
// in this package // in this package
...@@ -69,8 +73,10 @@ public final class TlsPrfGenerator extends KeyGeneratorSpi { ...@@ -69,8 +73,10 @@ public final class TlsPrfGenerator extends KeyGeneratorSpi {
* TLS HMAC "inner" and "outer" padding. This isn't a function * TLS HMAC "inner" and "outer" padding. This isn't a function
* of the digest algorithm. * of the digest algorithm.
*/ */
private static final byte[] HMAC_ipad = genPad((byte)0x36, 64); private static final byte[] HMAC_ipad64 = genPad((byte)0x36, 64);
private static final byte[] HMAC_opad = genPad((byte)0x5c, 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", ...) // SSL3 magic mix constants ("A", "BB", "CCC", ...)
final static byte[][] SSL3_CONST = genConst(); final static byte[][] SSL3_CONST = genConst();
...@@ -123,8 +129,8 @@ public final class TlsPrfGenerator extends KeyGeneratorSpi { ...@@ -123,8 +129,8 @@ public final class TlsPrfGenerator extends KeyGeneratorSpi {
this.spec = (TlsPrfParameterSpec)params; this.spec = (TlsPrfParameterSpec)params;
SecretKey key = spec.getSecret(); SecretKey key = spec.getSecret();
if ((key != null) && ("RAW".equals(key.getFormat()) == false)) { if ((key != null) && ("RAW".equals(key.getFormat()) == false)) {
throw new InvalidAlgorithmParameterException throw new InvalidAlgorithmParameterException(
("Key encoding format must be RAW"); "Key encoding format must be RAW");
} }
} }
...@@ -132,17 +138,21 @@ public final class TlsPrfGenerator extends KeyGeneratorSpi { ...@@ -132,17 +138,21 @@ public final class TlsPrfGenerator extends KeyGeneratorSpi {
throw new InvalidParameterException(MSG); throw new InvalidParameterException(MSG);
} }
protected SecretKey engineGenerateKey() { SecretKey engineGenerateKey0(boolean tls12) {
if (spec == null) { if (spec == null) {
throw new IllegalStateException throw new IllegalStateException(
("TlsPrfGenerator must be initialized"); "TlsPrfGenerator must be initialized");
} }
SecretKey key = spec.getSecret(); SecretKey key = spec.getSecret();
byte[] secret = (key == null) ? null : key.getEncoded(); byte[] secret = (key == null) ? null : key.getEncoded();
try { try {
byte[] labelBytes = spec.getLabel().getBytes("UTF8"); byte[] labelBytes = spec.getLabel().getBytes("UTF8");
int n = spec.getOutputLength(); 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"); return new SecretKeySpec(prfBytes, "TlsPrf");
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {
throw new ProviderException("Could not generate PRF", e); throw new ProviderException("Could not generate PRF", e);
...@@ -151,16 +161,67 @@ public final class TlsPrfGenerator extends KeyGeneratorSpi { ...@@ -151,16 +161,67 @@ public final class TlsPrfGenerator extends KeyGeneratorSpi {
} }
} }
static final byte[] doPRF(byte[] secret, byte[] labelBytes, byte[] seed, static byte[] doTLS12PRF(byte[] secret, byte[] labelBytes,
int outputLength) throws NoSuchAlgorithmException, DigestException { 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 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 md5 = MessageDigest.getInstance("MD5");
MessageDigest sha = MessageDigest.getInstance("SHA1"); MessageDigest sha = MessageDigest.getInstance("SHA1");
return doPRF(secret, labelBytes, seed, outputLength, md5, sha); return doTLS10PRF(secret, labelBytes, seed, outputLength, md5, sha);
} }
static final byte[] doPRF(byte[] secret, byte[] labelBytes, byte[] seed, static byte[] doTLS10PRF(byte[] secret, byte[] labelBytes,
int outputLength, MessageDigest md5, MessageDigest sha) byte[] seed, int outputLength, MessageDigest md5,
throws DigestException { MessageDigest sha) throws DigestException {
/* /*
* Split the secret into two halves S1 and S2 of same length. * 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 * S1 is taken from the first half of the secret, S2 from the
...@@ -183,10 +244,12 @@ public final class TlsPrfGenerator extends KeyGeneratorSpi { ...@@ -183,10 +244,12 @@ public final class TlsPrfGenerator extends KeyGeneratorSpi {
byte[] output = new byte[outputLength]; byte[] output = new byte[outputLength];
// P_MD5(S1, label + seed) // 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) // 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; return output;
} }
...@@ -201,16 +264,13 @@ public final class TlsPrfGenerator extends KeyGeneratorSpi { ...@@ -201,16 +264,13 @@ public final class TlsPrfGenerator extends KeyGeneratorSpi {
* @param seed the seed * @param seed the seed
* @param output the output array * @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[] 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 * modify the padding used, by XORing the key into our copy of that
* padding. That's to avoid doing that for each HMAC computation. * 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++) { for (int i = 0; i < secLen; i++) {
pad1[i] ^= secret[i + secOff]; pad1[i] ^= secret[i + secOff];
pad2[i] ^= secret[i + secOff]; pad2[i] ^= secret[i + secOff];
...@@ -275,7 +335,34 @@ public final class TlsPrfGenerator extends KeyGeneratorSpi { ...@@ -275,7 +335,34 @@ public final class TlsPrfGenerator extends KeyGeneratorSpi {
} }
remaining -= k; 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);
}
}
} }
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -69,8 +69,8 @@ public final class TlsRsaPremasterSecretGenerator extends KeyGeneratorSpi { ...@@ -69,8 +69,8 @@ public final class TlsRsaPremasterSecretGenerator extends KeyGeneratorSpi {
protected SecretKey engineGenerateKey() { protected SecretKey engineGenerateKey() {
if (spec == null) { if (spec == null) {
throw new IllegalStateException throw new IllegalStateException(
("TlsRsaPremasterSecretGenerator must be initialized"); "TlsRsaPremasterSecretGenerator must be initialized");
} }
if (random == null) { if (random == null) {
random = new SecureRandom(); random = new SecureRandom();
......
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.net.ssl;
/**
* Extends the <code>SSLSession</code> interface to support additional
* session attributes.
*
* @since 1.7
*/
public abstract class ExtendedSSLSession implements SSLSession {
/**
* Obtains an array of supported signature algorithms that the local side
* is willing to use.
* <p>
* Note: this method is used to indicate to the peer which signature
* algorithms may be used for digital signatures in TLS 1.2. It is
* not meaningful for TLS versions prior to 1.2.
* <p>
* The signature algorithm name must be a standard Java Security
* name (such as "SHA1withRSA", "SHA256withECDSA", and so on).
* See Appendix A in the <a href=
* "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
* Java Cryptography Architecture API Specification &amp; Reference </a>
* for information about standard algorithm names.
* <p>
* Note: the local supported signature algorithms should conform to
* the algorithm constraints specified by
* {@link SSLParameters#getAlgorithmConstraints getAlgorithmConstraints()}
* method in <code>SSLParameters</code>.
*
* @return An array of supported signature algorithms, in descending
* order of preference. The return value is an empty array if
* no signature algorithm is supported.
*
* @see SSLParameters#getAlgorithmConstraints
*/
public abstract String[] getLocalSupportedSignatureAlgorithms();
/**
* Obtains an array of supported signature algorithms that the peer is
* able to use.
* <p>
* Note: this method is used to indicate to the local side which signature
* algorithms may be used for digital signatures in TLS 1.2. It is
* not meaningful for TLS versions prior to 1.2.
* <p>
* The signature algorithm name must be a standard Java Security
* name (such as "SHA1withRSA", "SHA256withECDSA", and so on).
* See Appendix A in the <a href=
* "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
* Java Cryptography Architecture API Specification &amp; Reference </a>
* for information about standard algorithm names.
*
* @return An array of supported signature algorithms, in descending
* order of preference. The return value is an empty array if
* the peer has not sent the supported signature algorithms.
*
* @see X509KeyManager
* @see X509ExtendedKeyManager
*/
public abstract String[] getPeerSupportedSignatureAlgorithms();
}
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -188,19 +188,8 @@ class HttpsURLConnection extends HttpURLConnection ...@@ -188,19 +188,8 @@ class HttpsURLConnection extends HttpURLConnection
* <p> * <p>
* The default implementation will deny such connections. * The default implementation will deny such connections.
*/ */
private static HostnameVerifier defaultHostnameVerifier; private static HostnameVerifier defaultHostnameVerifier =
new DefaultHostnameVerifier();
/**
* Initialize the default <code>HostnameVerifier</code>.
*/
static {
try {
defaultHostnameVerifier =
new sun.net.www.protocol.https.DefaultHostnameVerifier();
} catch (NoClassDefFoundError e) {
defaultHostnameVerifier = new DefaultHostnameVerifier();
}
}
/* /*
* The initial default <code>HostnameVerifier</code>. Should be * The initial default <code>HostnameVerifier</code>. Should be
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -967,6 +967,47 @@ public abstract class SSLEngine { ...@@ -967,6 +967,47 @@ public abstract class SSLEngine {
public abstract SSLSession getSession(); 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. * Initiates handshaking (initial or renegotiation) on this SSLEngine.
* <P> * <P>
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -25,24 +25,29 @@ ...@@ -25,24 +25,29 @@
package javax.net.ssl; package javax.net.ssl;
import java.security.AlgorithmConstraints;
/** /**
* Encapsulates parameters for an SSL/TLS connection. The parameters * Encapsulates parameters for an SSL/TLS connection. The parameters
* are the list of ciphersuites to be accepted in an SSL/TLS handshake, * 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 * the list of protocols to be allowed, the endpoint identification
* request or require client authentication. * 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. * <p>
* SSLParameters can be created via the constructors in this class.
* Objects can also be obtained using the <code>getSSLParameters()</code> * Objects can also be obtained using the <code>getSSLParameters()</code>
* methods in * methods in
* {@link SSLSocket#getSSLParameters SSLSocket} and * {@link SSLSocket#getSSLParameters SSLSocket} and
* {@link SSLServerSocket#getSSLParameters SSLServerSocket} and
* {@link SSLEngine#getSSLParameters SSLEngine} or the * {@link SSLEngine#getSSLParameters SSLEngine} or the
* {@link SSLContext#getDefaultSSLParameters getDefaultSSLParameters()} and * {@link SSLContext#getDefaultSSLParameters getDefaultSSLParameters()} and
* {@link SSLContext#getSupportedSSLParameters getSupportedSSLParameters()} * {@link SSLContext#getSupportedSSLParameters getSupportedSSLParameters()}
* methods in <code>SSLContext</code>. * methods in <code>SSLContext</code>.
* * <p>
* <P>SSLParameters can be applied to a connection via the methods * SSLParameters can be applied to a connection via the methods
* {@link SSLSocket#setSSLParameters SSLSocket.setSSLParameters()} and * {@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 SSLSocket
* @see SSLEngine * @see SSLEngine
...@@ -56,11 +61,13 @@ public class SSLParameters { ...@@ -56,11 +61,13 @@ public class SSLParameters {
private String[] protocols; private String[] protocols;
private boolean wantClientAuth; private boolean wantClientAuth;
private boolean needClientAuth; private boolean needClientAuth;
private String identificationAlgorithm;
private AlgorithmConstraints algorithmConstraints;
/** /**
* Constructs SSLParameters. * Constructs SSLParameters.
* * <p>
* <p>The cipherSuites and protocols values are set to <code>null</code>, * The cipherSuites and protocols values are set to <code>null</code>,
* wantClientAuth and needClientAuth are set to <code>false</code>. * wantClientAuth and needClientAuth are set to <code>false</code>.
*/ */
public SSLParameters() { public SSLParameters() {
...@@ -69,6 +76,7 @@ public class SSLParameters { ...@@ -69,6 +76,7 @@ public class SSLParameters {
/** /**
* Constructs SSLParameters from the specified array of ciphersuites. * Constructs SSLParameters from the specified array of ciphersuites.
* <p>
* Calling this constructor is equivalent to calling the no-args * Calling this constructor is equivalent to calling the no-args
* constructor followed by * constructor followed by
* <code>setCipherSuites(cipherSuites);</code>. * <code>setCipherSuites(cipherSuites);</code>.
...@@ -82,6 +90,7 @@ public class SSLParameters { ...@@ -82,6 +90,7 @@ public class SSLParameters {
/** /**
* Constructs SSLParameters from the specified array of ciphersuites * Constructs SSLParameters from the specified array of ciphersuites
* and protocols. * and protocols.
* <p>
* Calling this constructor is equivalent to calling the no-args * Calling this constructor is equivalent to calling the no-args
* constructor followed by * constructor followed by
* <code>setCipherSuites(cipherSuites); setProtocols(protocols);</code>. * <code>setCipherSuites(cipherSuites); setProtocols(protocols);</code>.
...@@ -178,4 +187,71 @@ public class SSLParameters { ...@@ -178,4 +187,71 @@ public class SSLParameters {
this.needClientAuth = needClientAuth; this.needClientAuth = needClientAuth;
} }
/**
* Returns the cryptographic algorithm constraints.
*
* @return the cryptographic algorithm constraints, or null if the
* constraints have not been set
*
* @see #setAlgorithmConstraints(AlgorithmConstraints)
*
* @since 1.7
*/
public AlgorithmConstraints getAlgorithmConstraints() {
return algorithmConstraints;
}
/**
* Sets the cryptographic algorithm constraints, which will be used
* in addition to any configured by the runtime environment.
* <p>
* If the <code>constraints</code> parameter is non-null, every
* cryptographic algorithm, key and algorithm parameters used in the
* SSL/TLS handshake must be permitted by the constraints.
*
* @param constraints the algorithm constraints (or null)
*
* @since 1.7
*/
public void setAlgorithmConstraints(AlgorithmConstraints constraints) {
// the constraints object is immutable
this.algorithmConstraints = constraints;
}
/**
* Gets the endpoint identification algorithm.
*
* @return the endpoint identification algorithm, or null if none
* has been set.
*
* @see X509ExtendedTrustManager
* @see #setEndpointIdentificationAlgorithm(String)
*
* @since 1.7
*/
public String getEndpointIdentificationAlgorithm() {
return identificationAlgorithm;
}
/**
* Sets the endpoint identification algorithm.
* <p>
* If the <code>algorithm</code> parameter is non-null or non-empty, the
* endpoint identification/verification procedures must be handled during
* SSL/TLS handshaking. This is to prevent man-in-the-middle attacks.
*
* @param algorithm The standard string name of the endpoint
* identification algorithm (or null). See Appendix A in the <a href=
* "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
* Java Cryptography Architecture API Specification &amp; Reference </a>
* for information about standard algorithm names.
*
* @see X509ExtendedTrustManager
*
* @since 1.7
*/
public void setEndpointIdentificationAlgorithm(String algorithm) {
this.identificationAlgorithm = algorithm;
}
} }
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -56,8 +56,8 @@ import java.net.*; ...@@ -56,8 +56,8 @@ import java.net.*;
* @since 1.4 * @since 1.4
* @author David Brownell * @author David Brownell
*/ */
public abstract class SSLServerSocket extends ServerSocket public abstract class SSLServerSocket extends ServerSocket {
{
/** /**
* Used only by subclasses. * Used only by subclasses.
* <P> * <P>
...@@ -449,8 +449,79 @@ public abstract class SSLServerSocket extends ServerSocket ...@@ -449,8 +449,79 @@ public abstract class SSLServerSocket extends ServerSocket
* *
* @return true indicates that sessions may be created; this * @return true indicates that sessions may be created; this
* is the default. false indicates that an existing * is the default. false indicates that an existing
* session must be resumed. * session must be resumed
* @see #setEnableSessionCreation(boolean) * @see #setEnableSessionCreation(boolean)
*/ */
public abstract boolean getEnableSessionCreation(); 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);
}
}
} }
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -370,6 +370,51 @@ public abstract class SSLSocket extends Socket ...@@ -370,6 +370,51 @@ public abstract class SSLSocket extends Socket
public abstract SSLSession getSession(); 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 * Registers an event listener to receive notifications that an
* SSL handshake has completed on this connection. * SSL handshake has completed on this connection.
......
/*
* 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;
}
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -109,6 +109,10 @@ final class HttpsClient extends HttpClient ...@@ -109,6 +109,10 @@ final class HttpsClient extends HttpClient
// HTTPS uses a different default port number than HTTP. // HTTPS uses a different default port number than HTTP.
private static final int httpsPortNumber = 443; 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) */ /** Returns the default HTTPS port (443) */
@Override @Override
protected int getDefaultPort() { return httpsPortNumber; } protected int getDefaultPort() { return httpsPortNumber; }
...@@ -427,13 +431,93 @@ final class HttpsClient extends HttpClient ...@@ -427,13 +431,93 @@ final class HttpsClient extends HttpClient
} }
s.addHandshakeCompletedListener(this); s.addHandshakeCompletedListener(this);
// if the HostnameVerifier is not set, try to enable endpoint // We have two hostname verification approaches. One is in
// identification during handshaking // SSL/TLS socket layer, where the algorithm is configured with
boolean enabledIdentification = false; // SSLParameters.setEndpointIdentificationAlgorithm(), and the
if (hv instanceof DefaultHostnameVerifier && // hostname verification is done by X509ExtendedTrustManager when
(s instanceof SSLSocketImpl) && // the algorithm is "HTTPS". The other one is in HTTPS layer,
((SSLSocketImpl)s).trySetHostnameVerification("HTTPS")) { // where the algorithm is customized by
enabledIdentification = true; // 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(); s.startHandshake();
...@@ -449,7 +533,7 @@ final class HttpsClient extends HttpClient ...@@ -449,7 +533,7 @@ final class HttpsClient extends HttpClient
} }
// check URL spoofing if it has not been checked under handshaking // check URL spoofing if it has not been checked under handshaking
if (!enabledIdentification) { if (needToCheckSpoofing) {
checkURLSpoofing(hv); checkURLSpoofing(hv);
} }
} else { } else {
...@@ -463,8 +547,7 @@ final class HttpsClient extends HttpClient ...@@ -463,8 +547,7 @@ final class HttpsClient extends HttpClient
// Server identity checking is done according to RFC 2818: HTTP over TLS // Server identity checking is done according to RFC 2818: HTTP over TLS
// Section 3.1 Server Identity // Section 3.1 Server Identity
private void checkURLSpoofing(HostnameVerifier hostnameVerifier) private void checkURLSpoofing(HostnameVerifier hostnameVerifier)
throws IOException throws IOException {
{
// //
// Get authenticated server name, if any // Get authenticated server name, if any
// //
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -38,7 +38,8 @@ import javax.crypto.SecretKey; ...@@ -38,7 +38,8 @@ import javax.crypto.SecretKey;
* *
* @since 1.6 * @since 1.6
* @author Andreas Sterbenz * @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 @Deprecated
public interface TlsMasterSecret extends SecretKey { public interface TlsMasterSecret extends SecretKey {
......
...@@ -39,7 +39,8 @@ import javax.crypto.SecretKey; ...@@ -39,7 +39,8 @@ import javax.crypto.SecretKey;
* *
* @since 1.6 * @since 1.6
* @author Andreas Sterbenz * @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 @Deprecated
public class TlsKeyMaterialParameterSpec implements AlgorithmParameterSpec { public class TlsKeyMaterialParameterSpec implements AlgorithmParameterSpec {
...@@ -50,6 +51,9 @@ public class TlsKeyMaterialParameterSpec implements AlgorithmParameterSpec { ...@@ -50,6 +51,9 @@ public class TlsKeyMaterialParameterSpec implements AlgorithmParameterSpec {
private final String cipherAlgorithm; private final String cipherAlgorithm;
private final int cipherKeyLength, ivLength, macKeyLength; private final int cipherKeyLength, ivLength, macKeyLength;
private final int expandedCipherKeyLength; // == 0 for domestic ciphersuites private final int expandedCipherKeyLength; // == 0 for domestic ciphersuites
private final String prfHashAlg;
private final int prfHashLength;
private final int prfBlockSize;
/** /**
* Constructs a new TlsKeyMaterialParameterSpec. * Constructs a new TlsKeyMaterialParameterSpec.
...@@ -71,6 +75,12 @@ public class TlsKeyMaterialParameterSpec implements AlgorithmParameterSpec { ...@@ -71,6 +75,12 @@ public class TlsKeyMaterialParameterSpec implements AlgorithmParameterSpec {
* @param ivLength the length in bytes of the initialization vector * @param ivLength the length in bytes of the initialization vector
* to be generated, or 0 if no initialization vector is required * 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 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, * @throws NullPointerException if masterSecret, clientRandom,
* serverRandom, or cipherAlgorithm are null * serverRandom, or cipherAlgorithm are null
...@@ -82,7 +92,8 @@ public class TlsKeyMaterialParameterSpec implements AlgorithmParameterSpec { ...@@ -82,7 +92,8 @@ public class TlsKeyMaterialParameterSpec implements AlgorithmParameterSpec {
public TlsKeyMaterialParameterSpec(SecretKey masterSecret, public TlsKeyMaterialParameterSpec(SecretKey masterSecret,
int majorVersion, int minorVersion, byte[] clientRandom, int majorVersion, int minorVersion, byte[] clientRandom,
byte[] serverRandom, String cipherAlgorithm, int cipherKeyLength, 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) { if (masterSecret.getAlgorithm().equals("TlsMasterSecret") == false) {
throw new IllegalArgumentException("Not a TLS master secret"); throw new IllegalArgumentException("Not a TLS master secret");
} }
...@@ -101,6 +112,9 @@ public class TlsKeyMaterialParameterSpec implements AlgorithmParameterSpec { ...@@ -101,6 +112,9 @@ public class TlsKeyMaterialParameterSpec implements AlgorithmParameterSpec {
this.expandedCipherKeyLength = checkSign(expandedCipherKeyLength); this.expandedCipherKeyLength = checkSign(expandedCipherKeyLength);
this.ivLength = checkSign(ivLength); this.ivLength = checkSign(ivLength);
this.macKeyLength = checkSign(macKeyLength); this.macKeyLength = checkSign(macKeyLength);
this.prfHashAlg = prfHashAlg;
this.prfHashLength = prfHashLength;
this.prfBlockSize = prfBlockSize;
} }
private static int checkSign(int k) { private static int checkSign(int k) {
...@@ -216,4 +230,30 @@ public class TlsKeyMaterialParameterSpec implements AlgorithmParameterSpec { ...@@ -216,4 +230,30 @@ public class TlsKeyMaterialParameterSpec implements AlgorithmParameterSpec {
return macKeyLength; 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;
}
} }
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -39,7 +39,8 @@ import javax.crypto.spec.IvParameterSpec; ...@@ -39,7 +39,8 @@ import javax.crypto.spec.IvParameterSpec;
* *
* @since 1.6 * @since 1.6
* @author Andreas Sterbenz * @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 @Deprecated
public class TlsKeyMaterialSpec implements KeySpec, SecretKey { public class TlsKeyMaterialSpec implements KeySpec, SecretKey {
...@@ -80,7 +81,8 @@ public class TlsKeyMaterialSpec implements KeySpec, SecretKey { ...@@ -80,7 +81,8 @@ public class TlsKeyMaterialSpec implements KeySpec, SecretKey {
*/ */
public TlsKeyMaterialSpec(SecretKey clientMacKey, SecretKey serverMacKey, public TlsKeyMaterialSpec(SecretKey clientMacKey, SecretKey serverMacKey,
SecretKey clientCipherKey, SecretKey serverCipherKey) { SecretKey clientCipherKey, SecretKey serverCipherKey) {
this(clientMacKey, serverMacKey, clientCipherKey, null, serverCipherKey, null); this(clientMacKey, serverMacKey, clientCipherKey, null,
serverCipherKey, null);
} }
/** /**
......
...@@ -39,7 +39,8 @@ import javax.crypto.SecretKey; ...@@ -39,7 +39,8 @@ import javax.crypto.SecretKey;
* *
* @since 1.6 * @since 1.6
* @author Andreas Sterbenz * @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 @Deprecated
public class TlsMasterSecretParameterSpec implements AlgorithmParameterSpec { public class TlsMasterSecretParameterSpec implements AlgorithmParameterSpec {
...@@ -47,6 +48,9 @@ public class TlsMasterSecretParameterSpec implements AlgorithmParameterSpec { ...@@ -47,6 +48,9 @@ public class TlsMasterSecretParameterSpec implements AlgorithmParameterSpec {
private final SecretKey premasterSecret; private final SecretKey premasterSecret;
private final int majorVersion, minorVersion; private final int majorVersion, minorVersion;
private final byte[] clientRandom, serverRandom; private final byte[] clientRandom, serverRandom;
private final String prfHashAlg;
private final int prfHashLength;
private final int prfBlockSize;
/** /**
* Constructs a new TlsMasterSecretParameterSpec. * Constructs a new TlsMasterSecretParameterSpec.
...@@ -60,6 +64,12 @@ public class TlsMasterSecretParameterSpec implements AlgorithmParameterSpec { ...@@ -60,6 +64,12 @@ public class TlsMasterSecretParameterSpec implements AlgorithmParameterSpec {
* @param minorVersion the minor number of the protocol version * @param minorVersion the minor number of the protocol version
* @param clientRandom the client's random value * @param clientRandom the client's random value
* @param serverRandom the server'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, * @throws NullPointerException if premasterSecret, clientRandom,
* or serverRandom are null * or serverRandom are null
...@@ -68,7 +78,8 @@ public class TlsMasterSecretParameterSpec implements AlgorithmParameterSpec { ...@@ -68,7 +78,8 @@ public class TlsMasterSecretParameterSpec implements AlgorithmParameterSpec {
*/ */
public TlsMasterSecretParameterSpec(SecretKey premasterSecret, public TlsMasterSecretParameterSpec(SecretKey premasterSecret,
int majorVersion, int minorVersion, int majorVersion, int minorVersion,
byte[] clientRandom, byte[] serverRandom) { byte[] clientRandom, byte[] serverRandom,
String prfHashAlg, int prfHashLength, int prfBlockSize) {
if (premasterSecret == null) { if (premasterSecret == null) {
throw new NullPointerException("premasterSecret must not be null"); throw new NullPointerException("premasterSecret must not be null");
} }
...@@ -77,6 +88,9 @@ public class TlsMasterSecretParameterSpec implements AlgorithmParameterSpec { ...@@ -77,6 +88,9 @@ public class TlsMasterSecretParameterSpec implements AlgorithmParameterSpec {
this.minorVersion = checkVersion(minorVersion); this.minorVersion = checkVersion(minorVersion);
this.clientRandom = clientRandom.clone(); this.clientRandom = clientRandom.clone();
this.serverRandom = serverRandom.clone(); this.serverRandom = serverRandom.clone();
this.prfHashAlg = prfHashAlg;
this.prfHashLength = prfHashLength;
this.prfBlockSize = prfBlockSize;
} }
static int checkVersion(int version) { static int checkVersion(int version) {
...@@ -132,4 +146,30 @@ public class TlsMasterSecretParameterSpec implements AlgorithmParameterSpec { ...@@ -132,4 +146,30 @@ public class TlsMasterSecretParameterSpec implements AlgorithmParameterSpec {
return serverRandom.clone(); 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;
}
} }
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -38,7 +38,8 @@ import javax.crypto.SecretKey; ...@@ -38,7 +38,8 @@ import javax.crypto.SecretKey;
* *
* @since 1.6 * @since 1.6
* @author Andreas Sterbenz * @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 @Deprecated
public class TlsPrfParameterSpec implements AlgorithmParameterSpec { public class TlsPrfParameterSpec implements AlgorithmParameterSpec {
...@@ -47,6 +48,9 @@ public class TlsPrfParameterSpec implements AlgorithmParameterSpec { ...@@ -47,6 +48,9 @@ public class TlsPrfParameterSpec implements AlgorithmParameterSpec {
private final String label; private final String label;
private final byte[] seed; private final byte[] seed;
private final int outputLength; private final int outputLength;
private final String prfHashAlg;
private final int prfHashLength;
private final int prfBlockSize;
/** /**
* Constructs a new TlsPrfParameterSpec. * Constructs a new TlsPrfParameterSpec.
...@@ -55,11 +59,19 @@ public class TlsPrfParameterSpec implements AlgorithmParameterSpec { ...@@ -55,11 +59,19 @@ public class TlsPrfParameterSpec implements AlgorithmParameterSpec {
* @param label the label to use in the calculation * @param label the label to use in the calculation
* @param seed the random seed 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 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 NullPointerException if label or seed is null
* @throws IllegalArgumentException if outputLength is negative * @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)) { if ((label == null) || (seed == null)) {
throw new NullPointerException("label and seed must not be null"); throw new NullPointerException("label and seed must not be null");
} }
...@@ -70,6 +82,9 @@ public class TlsPrfParameterSpec implements AlgorithmParameterSpec { ...@@ -70,6 +82,9 @@ public class TlsPrfParameterSpec implements AlgorithmParameterSpec {
this.label = label; this.label = label;
this.seed = seed.clone(); this.seed = seed.clone();
this.outputLength = outputLength; this.outputLength = outputLength;
this.prfHashAlg = prfHashAlg;
this.prfHashLength = prfHashLength;
this.prfBlockSize = prfBlockSize;
} }
/** /**
...@@ -110,4 +125,33 @@ public class TlsPrfParameterSpec implements AlgorithmParameterSpec { ...@@ -110,4 +125,33 @@ public class TlsPrfParameterSpec implements AlgorithmParameterSpec {
return outputLength; 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;
}
} }
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -36,10 +36,12 @@ import java.security.spec.AlgorithmParameterSpec; ...@@ -36,10 +36,12 @@ import java.security.spec.AlgorithmParameterSpec;
* *
* @since 1.6 * @since 1.6
* @author Andreas Sterbenz * @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 @Deprecated
public class TlsRsaPremasterSecretParameterSpec implements AlgorithmParameterSpec { public class TlsRsaPremasterSecretParameterSpec
implements AlgorithmParameterSpec {
private final int majorVersion; private final int majorVersion;
private final int minorVersion; private final int minorVersion;
...@@ -58,10 +60,12 @@ public class TlsRsaPremasterSecretParameterSpec implements AlgorithmParameterSpe ...@@ -58,10 +60,12 @@ public class TlsRsaPremasterSecretParameterSpec implements AlgorithmParameterSpe
* @throws IllegalArgumentException if minorVersion or majorVersion are * @throws IllegalArgumentException if minorVersion or majorVersion are
* negative or larger than 255 * negative or larger than 255
*/ */
public TlsRsaPremasterSecretParameterSpec(int majorVersion, int minorVersion) { public TlsRsaPremasterSecretParameterSpec(int majorVersion,
this.majorVersion = TlsMasterSecretParameterSpec.checkVersion(majorVersion); int minorVersion) {
this.minorVersion = TlsMasterSecretParameterSpec.checkVersion(minorVersion); this.majorVersion =
} TlsMasterSecretParameterSpec.checkVersion(majorVersion);
this.minorVersion =
TlsMasterSecretParameterSpec.checkVersion(minorVersion); }
/** /**
* Returns the major version. * Returns the major version.
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -655,6 +655,25 @@ public final class SunPKCS11 extends AuthProvider { ...@@ -655,6 +655,25 @@ public final class SunPKCS11 extends AuthProvider {
d(SIG, "SHA512withRSA", P11Signature, d(SIG, "SHA512withRSA", P11Signature,
m(CKM_SHA512_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509)); 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", d(KG, "SunTlsRsaPremasterSecret",
"sun.security.pkcs11.P11TlsRsaPremasterSecretGenerator", "sun.security.pkcs11.P11TlsRsaPremasterSecretGenerator",
m(CKM_SSL3_PRE_MASTER_KEY_GEN, CKM_TLS_PRE_MASTER_KEY_GEN)); m(CKM_SSL3_PRE_MASTER_KEY_GEN, CKM_TLS_PRE_MASTER_KEY_GEN));
...@@ -887,7 +906,8 @@ public final class SunPKCS11 extends AuthProvider { ...@@ -887,7 +906,8 @@ public final class SunPKCS11 extends AuthProvider {
return (aliases == null) ? null : Arrays.asList(aliases); 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) { if (token.isValid() == false) {
throw new NoSuchAlgorithmException("Token has been removed"); throw new NoSuchAlgorithmException("Token has been removed");
} }
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -49,7 +49,7 @@ import sun.security.x509.AlgorithmId; ...@@ -49,7 +49,7 @@ import sun.security.x509.AlgorithmId;
public abstract class RSASignature extends SignatureSpi { public abstract class RSASignature extends SignatureSpi {
// we sign an ASN.1 SEQUENCE of AlgorithmId and digest // 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) // this means the encoded length is (8 + digestOID.length + digest.length)
private static final int baseLength = 8; private static final int baseLength = 8;
...@@ -104,7 +104,8 @@ public abstract class RSASignature extends SignatureSpi { ...@@ -104,7 +104,8 @@ public abstract class RSASignature extends SignatureSpi {
// initialize for signing. See JCA doc // initialize for signing. See JCA doc
protected void engineInitSign(PrivateKey privateKey, SecureRandom random) protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
throws InvalidKeyException { throws InvalidKeyException {
RSAPrivateKey rsaKey = (RSAPrivateKey)RSAKeyFactory.toRSAKey(privateKey); RSAPrivateKey rsaKey =
(RSAPrivateKey)RSAKeyFactory.toRSAKey(privateKey);
this.privateKey = rsaKey; this.privateKey = rsaKey;
this.publicKey = null; this.publicKey = null;
initCommon(rsaKey, random); initCommon(rsaKey, random);
...@@ -212,7 +213,8 @@ public abstract class RSASignature extends SignatureSpi { ...@@ -212,7 +213,8 @@ public abstract class RSASignature extends SignatureSpi {
DerOutputStream out = new DerOutputStream(); DerOutputStream out = new DerOutputStream();
new AlgorithmId(oid).encode(out); new AlgorithmId(oid).encode(out);
out.putOctetString(digest); out.putOctetString(digest);
DerValue result = new DerValue(DerValue.tag_Sequence, out.toByteArray()); DerValue result =
new DerValue(DerValue.tag_Sequence, out.toByteArray());
return result.toByteArray(); return result.toByteArray();
} }
...@@ -229,7 +231,8 @@ public abstract class RSASignature extends SignatureSpi { ...@@ -229,7 +231,8 @@ public abstract class RSASignature extends SignatureSpi {
} }
AlgorithmId algId = AlgorithmId.parse(values[0]); AlgorithmId algId = AlgorithmId.parse(values[0]);
if (algId.getOID().equals(oid) == false) { if (algId.getOID().equals(oid) == false) {
throw new IOException("ObjectIdentifier mismatch: " + algId.getOID()); throw new IOException("ObjectIdentifier mismatch: "
+ algId.getOID());
} }
if (algId.getEncodedParams() != null) { if (algId.getEncodedParams() != null) {
throw new IOException("Unexpected AlgorithmId parameters"); throw new IOException("Unexpected AlgorithmId parameters");
......
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
* questions. * questions.
*/ */
package sun.security.ssl; package sun.security.ssl;
import java.io.*; import java.io.*;
...@@ -45,12 +44,12 @@ import javax.net.ssl.*; ...@@ -45,12 +44,12 @@ import javax.net.ssl.*;
import javax.security.auth.Subject; import javax.security.auth.Subject;
import com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager;
import sun.security.ssl.HandshakeMessage.*; import sun.security.ssl.HandshakeMessage.*;
import sun.security.ssl.CipherSuite.*; import sun.security.ssl.CipherSuite.*;
import static sun.security.ssl.CipherSuite.KeyExchange.*; import static sun.security.ssl.CipherSuite.KeyExchange.*;
import sun.net.util.IPAddressUtil;
/** /**
* ClientHandshaker does the protocol handshaking from the point * ClientHandshaker does the protocol handshaking from the point
* of view of a client. It is driven asychronously by handshake messages * of view of a client. It is driven asychronously by handshake messages
...@@ -89,6 +88,10 @@ final class ClientHandshaker extends Handshaker { ...@@ -89,6 +88,10 @@ final class ClientHandshaker extends Handshaker {
*/ */
private ProtocolVersion maxProtocolVersion; private ProtocolVersion maxProtocolVersion;
// To switch off the SNI extension.
private final static boolean enableSNIExtension =
Debug.getBooleanProperty("jsse.enableSNIExtension", true);
/* /*
* Constructors * Constructors
*/ */
...@@ -190,7 +193,8 @@ final class ClientHandshaker extends Handshaker { ...@@ -190,7 +193,8 @@ final class ClientHandshaker extends Handshaker {
} }
break; break;
case K_DH_ANON: case K_DH_ANON:
this.serverKeyExchange(new DH_ServerKeyExchange(input)); this.serverKeyExchange(new DH_ServerKeyExchange(
input, protocolVersion));
break; break;
case K_DHE_DSS: case K_DHE_DSS:
case K_DHE_RSA: case K_DHE_RSA:
...@@ -198,7 +202,8 @@ final class ClientHandshaker extends Handshaker { ...@@ -198,7 +202,8 @@ final class ClientHandshaker extends Handshaker {
this.serverKeyExchange(new DH_ServerKeyExchange( this.serverKeyExchange(new DH_ServerKeyExchange(
input, serverKey, input, serverKey,
clnt_random.random_bytes, svr_random.random_bytes, clnt_random.random_bytes, svr_random.random_bytes,
messageLen)); messageLen,
localSupportedSignAlgs, protocolVersion));
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {
throwSSLException("Server key", e); throwSSLException("Server key", e);
} }
...@@ -209,7 +214,8 @@ final class ClientHandshaker extends Handshaker { ...@@ -209,7 +214,8 @@ final class ClientHandshaker extends Handshaker {
try { try {
this.serverKeyExchange(new ECDH_ServerKeyExchange this.serverKeyExchange(new ECDH_ServerKeyExchange
(input, serverKey, clnt_random.random_bytes, (input, serverKey, clnt_random.random_bytes,
svr_random.random_bytes)); svr_random.random_bytes,
localSupportedSignAlgs, protocolVersion));
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {
throwSSLException("Server key", e); throwSSLException("Server key", e);
} }
...@@ -219,8 +225,9 @@ final class ClientHandshaker extends Handshaker { ...@@ -219,8 +225,9 @@ final class ClientHandshaker extends Handshaker {
case K_DH_DSS: case K_DH_DSS:
case K_ECDH_ECDSA: case K_ECDH_ECDSA:
case K_ECDH_RSA: case K_ECDH_RSA:
throw new SSLProtocolException("Protocol violation: server sent" throw new SSLProtocolException(
+ " a server key exchange message for key exchange " + keyExchange); "Protocol violation: server sent a server key exchange"
+ "message for key exchange " + keyExchange);
case K_KRB5: case K_KRB5:
case K_KRB5_EXPORT: case K_KRB5_EXPORT:
throw new SSLProtocolException( throw new SSLProtocolException(
...@@ -243,10 +250,32 @@ final class ClientHandshaker extends Handshaker { ...@@ -243,10 +250,32 @@ final class ClientHandshaker extends Handshaker {
"Client certificate requested for "+ "Client certificate requested for "+
"kerberos cipher suite."); "kerberos cipher suite.");
} }
certRequest = new CertificateRequest(input); certRequest = new CertificateRequest(input, protocolVersion);
if (debug != null && Debug.isOn("handshake")) { if (debug != null && Debug.isOn("handshake")) {
certRequest.print(System.out); 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; break;
case HandshakeMessage.ht_server_hello_done: case HandshakeMessage.ht_server_hello_done:
...@@ -254,7 +283,8 @@ final class ClientHandshaker extends Handshaker { ...@@ -254,7 +283,8 @@ final class ClientHandshaker extends Handshaker {
break; break;
case HandshakeMessage.ht_finished: case HandshakeMessage.ht_finished:
this.serverFinished(new Finished(protocolVersion, input)); this.serverFinished(
new Finished(protocolVersion, input, cipherSuite));
break; break;
default: default:
...@@ -351,6 +381,9 @@ final class ClientHandshaker extends Handshaker { ...@@ -351,6 +381,9 @@ final class ClientHandshaker extends Handshaker {
mesgVersion); mesgVersion);
} }
handshakeHash.protocolDetermined(
mesgVersion.v >= ProtocolVersion.TLS12.v);
// Set protocolVersion and propagate to SSLSocket and the // Set protocolVersion and propagate to SSLSocket and the
// Handshake streams // Handshake streams
setVersion(mesgVersion); setVersion(mesgVersion);
...@@ -426,10 +459,13 @@ final class ClientHandshaker extends Handshaker { ...@@ -426,10 +459,13 @@ final class ClientHandshaker extends Handshaker {
if (isNegotiable(mesg.cipherSuite) == false) { if (isNegotiable(mesg.cipherSuite) == false) {
fatalSE(Alerts.alert_illegal_parameter, fatalSE(Alerts.alert_illegal_parameter,
"Server selected improper ciphersuite " + cipherSuite); "Server selected improper ciphersuite " + mesg.cipherSuite);
} }
setCipherSuite(mesg.cipherSuite); setCipherSuite(mesg.cipherSuite);
if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
handshakeHash.setFinishedAlg(cipherSuite.prfAlg.getPRFHashAlg());
}
if (mesg.compression_method != 0) { if (mesg.compression_method != 0) {
fatalSE(Alerts.alert_illegal_parameter, fatalSE(Alerts.alert_illegal_parameter,
...@@ -508,7 +544,6 @@ final class ClientHandshaker extends Handshaker { ...@@ -508,7 +544,6 @@ final class ClientHandshaker extends Handshaker {
if (debug != null && Debug.isOn("session")) { if (debug != null && Debug.isOn("session")) {
System.out.println("%% Server resumed " + session); System.out.println("%% Server resumed " + session);
} }
return;
} else { } else {
// we wanted to resume, but the server refused // we wanted to resume, but the server refused
session = null; session = null;
...@@ -519,11 +554,21 @@ final class ClientHandshaker extends Handshaker { ...@@ -519,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 // check extensions
for (HelloExtension ext : mesg.extensions.list()) { for (HelloExtension ext : mesg.extensions.list()) {
ExtensionType type = ext.type; ExtensionType type = ext.type;
if ((type != ExtensionType.EXT_ELLIPTIC_CURVES) if ((type != ExtensionType.EXT_ELLIPTIC_CURVES)
&& (type != ExtensionType.EXT_EC_POINT_FORMATS) && (type != ExtensionType.EXT_EC_POINT_FORMATS)
&& (type != ExtensionType.EXT_SERVER_NAME)
&& (type != ExtensionType.EXT_RENEGOTIATION_INFO)) { && (type != ExtensionType.EXT_RENEGOTIATION_INFO)) {
fatalSE(Alerts.alert_unsupported_extension, fatalSE(Alerts.alert_unsupported_extension,
"Server sent an unsupported extension: " + type); "Server sent an unsupported extension: " + type);
...@@ -532,7 +577,9 @@ final class ClientHandshaker extends Handshaker { ...@@ -532,7 +577,9 @@ final class ClientHandshaker extends Handshaker {
// Create a new session, we need to do the full handshake // Create a new session, we need to do the full handshake
session = new SSLSessionImpl(protocolVersion, cipherSuite, session = new SSLSessionImpl(protocolVersion, cipherSuite,
getLocalSupportedSignAlgs(),
mesg.sessionId, getHostSE(), getPortSE()); mesg.sessionId, getHostSE(), getPortSE());
setHandshakeSessionSE(session);
if (debug != null && Debug.isOn("handshake")) { if (debug != null && Debug.isOn("handshake")) {
System.out.println("** " + cipherSuite); System.out.println("** " + cipherSuite);
} }
...@@ -568,11 +615,13 @@ final class ClientHandshaker extends Handshaker { ...@@ -568,11 +615,13 @@ final class ClientHandshaker extends Handshaker {
if (debug != null && Debug.isOn("handshake")) { if (debug != null && Debug.isOn("handshake")) {
mesg.print(System.out); 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(); 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")) { if (debug != null && Debug.isOn("handshake")) {
mesg.print(System.out); mesg.print(System.out);
} }
...@@ -666,9 +715,13 @@ final class ClientHandshaker extends Handshaker { ...@@ -666,9 +715,13 @@ final class ClientHandshaker extends Handshaker {
PublicKey publicKey = certs[0].getPublicKey(); PublicKey publicKey = certs[0].getPublicKey();
// for EC, make sure we use a supported named curve // for EC, make sure we use a supported named curve
if (publicKey instanceof ECPublicKey) { if (publicKey instanceof ECPublicKey) {
ECParameterSpec params = ((ECPublicKey)publicKey).getParams(); ECParameterSpec params =
int index = SupportedEllipticCurvesExtension.getCurveIndex(params); ((ECPublicKey)publicKey).getParams();
if (!SupportedEllipticCurvesExtension.isSupported(index)) { int index =
SupportedEllipticCurvesExtension.getCurveIndex(
params);
if (!SupportedEllipticCurvesExtension.isSupported(
index)) {
publicKey = null; publicKey = null;
} }
} }
...@@ -814,8 +867,9 @@ final class ClientHandshaker extends Handshaker { ...@@ -814,8 +867,9 @@ final class ClientHandshaker extends Handshaker {
throw new IOException("Hostname is required" + throw new IOException("Hostname is required" +
" to use Kerberos cipher suites"); " to use Kerberos cipher suites");
} }
KerberosClientKeyExchange kerberosMsg = new KerberosClientKeyExchange KerberosClientKeyExchange kerberosMsg =
(hostname, isLoopbackSE(), getAccSE(), protocolVersion, new KerberosClientKeyExchange(
hostname, isLoopbackSE(), getAccSE(), protocolVersion,
sslContext.getSecureRandom()); sslContext.getSecureRandom());
// Record the principals involved in exchange // Record the principals involved in exchange
session.setPeerPrincipal(kerberosMsg.getPeerPrincipal()); session.setPeerPrincipal(kerberosMsg.getPeerPrincipal());
...@@ -862,7 +916,8 @@ final class ClientHandshaker extends Handshaker { ...@@ -862,7 +916,8 @@ final class ClientHandshaker extends Handshaker {
case K_KRB5_EXPORT: case K_KRB5_EXPORT:
byte[] secretBytes = byte[] secretBytes =
((KerberosClientKeyExchange)m2).getUnencryptedPreMasterSecret(); ((KerberosClientKeyExchange)m2).getUnencryptedPreMasterSecret();
preMasterSecret = new SecretKeySpec(secretBytes, "TlsPremasterSecret"); preMasterSecret = new SecretKeySpec(secretBytes,
"TlsPremasterSecret");
break; break;
case K_DHE_RSA: case K_DHE_RSA:
case K_DHE_DSS: case K_DHE_DSS:
...@@ -879,7 +934,8 @@ final class ClientHandshaker extends Handshaker { ...@@ -879,7 +934,8 @@ final class ClientHandshaker extends Handshaker {
preMasterSecret = ecdh.getAgreedSecret(serverKey); preMasterSecret = ecdh.getAgreedSecret(serverKey);
break; break;
default: default:
throw new IOException("Internal error: unknown key exchange " + keyExchange); throw new IOException("Internal error: unknown key exchange "
+ keyExchange);
} }
calculateKeys(preMasterSecret, null); calculateKeys(preMasterSecret, null);
...@@ -897,9 +953,32 @@ final class ClientHandshaker extends Handshaker { ...@@ -897,9 +953,32 @@ final class ClientHandshaker extends Handshaker {
if (signingKey != null) { if (signingKey != null) {
CertificateVerify m3; CertificateVerify m3;
try { 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, m3 = new CertificateVerify(protocolVersion, handshakeHash,
signingKey, session.getMasterSecret(), signingKey, session.getMasterSecret(),
sslContext.getSecureRandom()); sslContext.getSecureRandom(),
preferableSignatureAlgorithm);
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {
fatalSE(Alerts.alert_handshake_failure, fatalSE(Alerts.alert_handshake_failure,
"Error signing certificate verify", e); "Error signing certificate verify", e);
...@@ -911,6 +990,10 @@ final class ClientHandshaker extends Handshaker { ...@@ -911,6 +990,10 @@ final class ClientHandshaker extends Handshaker {
} }
m3.write(output); m3.write(output);
output.doHashes(); output.doHashes();
} else {
if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
handshakeHash.setCertificateVerifyAlg(null);
}
} }
/* /*
...@@ -931,8 +1014,8 @@ final class ClientHandshaker extends Handshaker { ...@@ -931,8 +1014,8 @@ final class ClientHandshaker extends Handshaker {
mesg.print(System.out); mesg.print(System.out);
} }
boolean verified = mesg.verify(protocolVersion, handshakeHash, boolean verified = mesg.verify(handshakeHash, Finished.SERVER,
Finished.SERVER, session.getMasterSecret()); session.getMasterSecret());
if (!verified) { if (!verified) {
fatalSE(Alerts.alert_illegal_parameter, fatalSE(Alerts.alert_illegal_parameter,
...@@ -989,7 +1072,7 @@ final class ClientHandshaker extends Handshaker { ...@@ -989,7 +1072,7 @@ final class ClientHandshaker extends Handshaker {
private void sendChangeCipherAndFinish(boolean finishedTag) private void sendChangeCipherAndFinish(boolean finishedTag)
throws IOException { throws IOException {
Finished mesg = new Finished(protocolVersion, handshakeHash, 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 * Send the change_cipher_spec message, then the Finished message
...@@ -1134,11 +1217,49 @@ final class ClientHandshaker extends Handshaker { ...@@ -1134,11 +1217,49 @@ final class ClientHandshaker extends Handshaker {
throw new SSLHandshakeException("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 // create the ClientHello message
ClientHello clientHelloMessage = new ClientHello( ClientHello clientHelloMessage = new ClientHello(
sslContext.getSecureRandom(), maxProtocolVersion, sslContext.getSecureRandom(), maxProtocolVersion,
sessionId, cipherSuites); 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 // reset the client random cookie
clnt_random = clientHelloMessage.clnt_random; clnt_random = clientHelloMessage.clnt_random;
...@@ -1194,26 +1315,23 @@ final class ClientHandshaker extends Handshaker { ...@@ -1194,26 +1315,23 @@ final class ClientHandshaker extends Handshaker {
keyExchangeString = keyExchange.name; keyExchangeString = keyExchange.name;
} }
String identificator = getHostnameVerificationSE();
if (tm instanceof X509ExtendedTrustManager) { if (tm instanceof X509ExtendedTrustManager) {
((X509ExtendedTrustManager)tm).checkServerTrusted( if (conn != null) {
(peerCerts != null ? ((X509ExtendedTrustManager)tm).checkServerTrusted(
peerCerts.clone() : peerCerts.clone(),
null),
keyExchangeString, keyExchangeString,
getHostSE(), conn);
identificator); } else {
} else { ((X509ExtendedTrustManager)tm).checkServerTrusted(
if (identificator != null) { peerCerts.clone(),
throw new RuntimeException( keyExchangeString,
"trust manager does not support peer identification"); engine);
} }
} else {
tm.checkServerTrusted( // Unlikely to happen, because we have wrapped the old
(peerCerts != null ? // X509TrustManager with the new X509ExtendedTrustManager.
peerCerts.clone() : throw new CertificateException(
peerCerts), "Improper X509TrustManager implementation");
keyExchangeString);
} }
} catch (CertificateException e) { } catch (CertificateException e) {
// This will throw an exception, so include the original error. // This will throw an exception, so include the original error.
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -26,7 +26,13 @@ ...@@ -26,7 +26,13 @@
package sun.security.ssl; package sun.security.ssl;
import java.io.ByteArrayOutputStream;
import java.security.*; 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 * Abstraction for the SSL/TLS hash of all handshake messages that is
...@@ -36,51 +42,161 @@ import java.security.*; ...@@ -36,51 +42,161 @@ import java.security.*;
* *
* This class transparently deals with cloneable and non-cloneable digests. * 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 { 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 * 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) { HandshakeHash(boolean isServer, boolean needCertificateVerify,
int n = needCertificateVerify ? 3 : 2; Set<String> algs) {
try { this.isServer = isServer;
md5 = CloneableDigest.getDigest("MD5", n); clonesNeeded = needCertificateVerify ? 3 : 2;
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);
} }
void update(byte[] b, int offset, int len) { void update(byte[] b, int offset, int len) {
md5.update(b, offset, len); switch (version) {
sha.update(b, offset, len); 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 * digest clones that can be obtained. Digests that have already been
* cloned and are gone remain gone. * cloned and are gone remain gone.
*/ */
void reset() { void reset() {
md5.reset(); if (version != -1) {
sha.reset(); 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. * Return a new MD5 digest updated with all data hashed so far.
*/ */
MessageDigest getMD5Clone() { MessageDigest getMD5Clone() {
if (version != 1) {
throw new RuntimeException(
"getMD5Clone() can be only be called for TLS 1.1");
}
return cloneDigest(md5); return cloneDigest(md5);
} }
...@@ -88,6 +204,10 @@ final class HandshakeHash { ...@@ -88,6 +204,10 @@ final class HandshakeHash {
* Return a new SHA digest updated with all data hashed so far. * Return a new SHA digest updated with all data hashed so far.
*/ */
MessageDigest getSHAClone() { MessageDigest getSHAClone() {
if (version != 1) {
throw new RuntimeException(
"getSHAClone() can be only be called for TLS 1.1");
}
return cloneDigest(sha); return cloneDigest(sha);
} }
...@@ -100,6 +220,181 @@ final class HandshakeHash { ...@@ -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,"));
}
}
} }
/** /**
......
...@@ -29,13 +29,12 @@ package sun.security.ssl; ...@@ -29,13 +29,12 @@ package sun.security.ssl;
import java.io.*; import java.io.*;
import java.util.*; import java.util.*;
import java.security.*; import java.security.*;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.AccessController; import java.security.AccessController;
import java.security.AlgorithmConstraints;
import java.security.AccessControlContext; import java.security.AccessControlContext;
import java.security.PrivilegedExceptionAction; import java.security.PrivilegedExceptionAction;
import java.security.PrivilegedActionException; import java.security.PrivilegedActionException;
import java.security.cert.X509Certificate;
import javax.crypto.*; import javax.crypto.*;
import javax.crypto.spec.*; import javax.crypto.spec.*;
...@@ -49,6 +48,8 @@ import sun.security.internal.interfaces.TlsMasterSecret; ...@@ -49,6 +48,8 @@ import sun.security.internal.interfaces.TlsMasterSecret;
import sun.security.ssl.HandshakeMessage.*; import sun.security.ssl.HandshakeMessage.*;
import sun.security.ssl.CipherSuite.*; import sun.security.ssl.CipherSuite.*;
import static sun.security.ssl.CipherSuite.PRF.*;
/** /**
* Handshaker ... processes handshake records from an SSL V3.0 * Handshaker ... processes handshake records from an SSL V3.0
* data stream, handling all the details of the handshake protocol. * data stream, handling all the details of the handshake protocol.
...@@ -80,6 +81,20 @@ abstract class Handshaker { ...@@ -80,6 +81,20 @@ abstract class Handshaker {
// List of enabled CipherSuites // List of enabled CipherSuites
private CipherSuiteList enabledCipherSuites; 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 * List of active protocols
* *
...@@ -98,6 +113,7 @@ abstract class Handshaker { ...@@ -98,6 +113,7 @@ abstract class Handshaker {
private CipherSuiteList activeCipherSuites; private CipherSuiteList activeCipherSuites;
private boolean isClient; private boolean isClient;
private boolean needCertVerify;
SSLSocketImpl conn = null; SSLSocketImpl conn = null;
SSLEngineImpl engine = null; SSLEngineImpl engine = null;
...@@ -110,10 +126,6 @@ abstract class Handshaker { ...@@ -110,10 +126,6 @@ abstract class Handshaker {
RandomCookie clnt_random, svr_random; RandomCookie clnt_random, svr_random;
SSLSessionImpl session; SSLSessionImpl session;
// Temporary MD5 and SHA message digests. Must always be left
// in reset state after use.
private MessageDigest md5Tmp, shaTmp;
// current CipherSuite. Never null, initially SSL_NULL_WITH_NULL_NULL // current CipherSuite. Never null, initially SSL_NULL_WITH_NULL_NULL
CipherSuite cipherSuite; CipherSuite cipherSuite;
...@@ -208,6 +220,7 @@ abstract class Handshaker { ...@@ -208,6 +220,7 @@ abstract class Handshaker {
this.sslContext = context; this.sslContext = context;
this.isClient = isClient; this.isClient = isClient;
this.needCertVerify = needCertVerify;
this.activeProtocolVersion = activeProtocolVersion; this.activeProtocolVersion = activeProtocolVersion;
this.isInitialHandshake = isInitialHandshake; this.isInitialHandshake = isInitialHandshake;
this.secureRenegotiation = secureRenegotiation; this.secureRenegotiation = secureRenegotiation;
...@@ -217,23 +230,12 @@ abstract class Handshaker { ...@@ -217,23 +230,12 @@ abstract class Handshaker {
invalidated = false; invalidated = false;
setCipherSuite(CipherSuite.C_NULL); 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); setEnabledProtocols(enabledProtocols);
if (conn != null) { if (conn != null) {
conn.getAppInputStream().r.setHandshakeHash(handshakeHash); algorithmConstraints = new SSLAlgorithmConstraints(conn, true);
} else { // engine != null } else { // engine != null
engine.inputRecord.setHandshakeHash(handshakeHash); algorithmConstraints = new SSLAlgorithmConstraints(engine, true);
} }
...@@ -285,6 +287,14 @@ abstract class Handshaker { ...@@ -285,6 +287,14 @@ abstract class Handshaker {
} }
} }
String getRawHostnameSE() {
if (conn != null) {
return conn.getRawHostname();
} else {
return engine.getPeerHost();
}
}
String getHostSE() { String getHostSE() {
if (conn != null) { if (conn != null) {
return conn.getHost(); return conn.getHost();
...@@ -330,14 +340,6 @@ abstract class Handshaker { ...@@ -330,14 +340,6 @@ abstract class Handshaker {
} }
} }
String getHostnameVerificationSE() {
if (conn != null) {
return conn.getHostnameVerification();
} else {
return engine.getHostnameVerification();
}
}
AccessControlContext getAccSE() { AccessControlContext getAccSE() {
if (conn != null) { if (conn != null) {
return conn.getAcc(); return conn.getAcc();
...@@ -366,7 +368,6 @@ abstract class Handshaker { ...@@ -366,7 +368,6 @@ abstract class Handshaker {
output.r.setVersion(protocolVersion); output.r.setVersion(protocolVersion);
} }
/** /**
* Set the enabled protocols. Called from the constructor or * Set the enabled protocols. Called from the constructor or
* SSLSocketImpl/SSLEngineImpl.setEnabledProtocols() (if the * SSLSocketImpl/SSLEngineImpl.setEnabledProtocols() (if the
...@@ -390,6 +391,49 @@ abstract class Handshaker { ...@@ -390,6 +391,49 @@ abstract class Handshaker {
this.enabledCipherSuites = enabledCipherSuites; 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 identification protocol. Called from the constructor or
* SSLSocketImpl/SSLEngineImpl.setIdentificationProtocol() (if the
* handshake is not yet in progress).
*/
void setIdentificationProtocol(String protocol) {
this.identificationProtocol = protocol;
}
/** /**
* Prior to handshaking, activate the handshake and initialize the version, * Prior to handshaking, activate the handshake and initialize the version,
...@@ -426,16 +470,27 @@ abstract class Handshaker { ...@@ -426,16 +470,27 @@ abstract class Handshaker {
helloVersion = activeProtocols.helloVersion; helloVersion = activeProtocols.helloVersion;
} }
input = new HandshakeInStream(handshakeHash); // 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) { if (conn != null) {
output = new HandshakeOutStream(protocolVersion, helloVersion, output = new HandshakeOutStream(protocolVersion, helloVersion,
handshakeHash, conn); handshakeHash, conn);
conn.getAppInputStream().r.setHandshakeHash(handshakeHash);
conn.getAppInputStream().r.setHelloVersion(helloVersion); conn.getAppInputStream().r.setHelloVersion(helloVersion);
conn.getAppOutputStream().r.setHelloVersion(helloVersion); conn.getAppOutputStream().r.setHelloVersion(helloVersion);
} else { } else {
output = new HandshakeOutStream(protocolVersion, helloVersion, output = new HandshakeOutStream(protocolVersion, helloVersion,
handshakeHash, engine); handshakeHash, engine);
engine.inputRecord.setHandshakeHash(handshakeHash);
engine.inputRecord.setHelloVersion(helloVersion); engine.inputRecord.setHelloVersion(helloVersion);
engine.outputRecord.setHelloVersion(helloVersion); engine.outputRecord.setHelloVersion(helloVersion);
} }
...@@ -501,7 +556,7 @@ abstract class Handshaker { ...@@ -501,7 +556,7 @@ abstract class Handshaker {
* *
* Therefore, when the active protocols only include TLS 1.1 or later, * Therefore, when the active protocols only include TLS 1.1 or later,
* the client cannot request to negotiate those obsoleted cipher * the client cannot request to negotiate those obsoleted cipher
* suites, that's, the obsoleted suites should not be included in the * 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 * client hello. So we need to create a subset of the enabled cipher
* suites, the active cipher suites, which does not contain obsoleted * suites, the active cipher suites, which does not contain obsoleted
* cipher suites of the minimum active protocol. * cipher suites of the minimum active protocol.
...@@ -518,11 +573,21 @@ abstract class Handshaker { ...@@ -518,11 +573,21 @@ abstract class Handshaker {
if (!(activeProtocols.collection().isEmpty()) && if (!(activeProtocols.collection().isEmpty()) &&
activeProtocols.min.v != ProtocolVersion.NONE.v) { activeProtocols.min.v != ProtocolVersion.NONE.v) {
for (CipherSuite suite : enabledCipherSuites.collection()) { for (CipherSuite suite : enabledCipherSuites.collection()) {
if (suite.obsoleted > activeProtocols.min.v) { if (suite.obsoleted > activeProtocols.min.v &&
suites.add(suite); suite.supported <= activeProtocols.max.v) {
} else if (debug != null && Debug.isOn("handshake")) { if (algorithmConstraints.permits(
System.out.println( EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
"Ignoring obsoleted cipher suite: " + suite); 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);
}
} }
} }
} }
...@@ -550,14 +615,27 @@ abstract class Handshaker { ...@@ -550,14 +615,27 @@ abstract class Handshaker {
ProtocolList getActiveProtocols() { ProtocolList getActiveProtocols() {
if (activeProtocols == null) { if (activeProtocols == null) {
ArrayList<ProtocolVersion> protocols = ArrayList<ProtocolVersion> protocols =
new ArrayList<ProtocolVersion>(3); new ArrayList<ProtocolVersion>(4);
for (ProtocolVersion protocol : enabledProtocols.collection()) { for (ProtocolVersion protocol : enabledProtocols.collection()) {
boolean found = false; boolean found = false;
for (CipherSuite suite : enabledCipherSuites.collection()) { for (CipherSuite suite : enabledCipherSuites.collection()) {
if (suite.isAvailable() && suite.obsoleted > protocol.v) { if (suite.isAvailable() && suite.obsoleted > protocol.v &&
protocols.add(protocol); suite.supported <= protocol.v) {
found = true; if (algorithmConstraints.permits(
break; 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")) { if (!found && (debug != null) && Debug.isOn("handshake")) {
...@@ -672,6 +750,17 @@ abstract class Handshaker { ...@@ -672,6 +750,17 @@ abstract class Handshaker {
return session; 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. * Returns true if renegotiation is in use for this connection.
*/ */
...@@ -798,7 +887,7 @@ abstract class Handshaker { ...@@ -798,7 +887,7 @@ abstract class Handshaker {
*/ */
boolean started() { boolean started() {
return state >= 0; // 0: HandshakeMessage.ht_hello_request return state >= 0; // 0: HandshakeMessage.ht_hello_request
// 1: HandshakeMessage.ht_hello_request // 1: HandshakeMessage.ht_client_hello
} }
...@@ -926,10 +1015,6 @@ abstract class Handshaker { ...@@ -926,10 +1015,6 @@ abstract class Handshaker {
private SecretKey calculateMasterSecret(SecretKey preMasterSecret, private SecretKey calculateMasterSecret(SecretKey preMasterSecret,
ProtocolVersion requestedVersion) { 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")) { if (debug != null && Debug.isOn("keygen")) {
HexDumpEncoder dump = new HexDumpEncoder(); HexDumpEncoder dump = new HexDumpEncoder();
...@@ -942,15 +1027,37 @@ abstract class Handshaker { ...@@ -942,15 +1027,37 @@ abstract class Handshaker {
// benefit to doing it twice // 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; SecretKey masterSecret;
try { try {
KeyGenerator kg = JsseJce.getKeyGenerator("SunTlsMasterSecret"); KeyGenerator kg = JsseJce.getKeyGenerator(masterAlg);
kg.init(spec); kg.init(spec);
masterSecret = kg.generateKey(); masterSecret = kg.generateKey();
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {
// For RSA premaster secrets, do not signal a protocol error // For RSA premaster secrets, do not signal a protocol error
// due to the Bleichenbacher attack. See comments further down. // due to the Bleichenbacher attack. See comments further down.
if (!preMasterSecret.getAlgorithm().equals("TlsRsaPremasterSecret")) { if (!preMasterSecret.getAlgorithm().equals(
"TlsRsaPremasterSecret")) {
throw new ProviderException(e); throw new ProviderException(e);
} }
...@@ -1056,14 +1163,31 @@ abstract class Handshaker { ...@@ -1056,14 +1163,31 @@ abstract class Handshaker {
BulkCipher cipher = cipherSuite.cipher; BulkCipher cipher = cipherSuite.cipher;
int expandedKeySize = is_exportable ? cipher.expandedKeySize : 0; int expandedKeySize = is_exportable ? cipher.expandedKeySize : 0;
TlsKeyMaterialParameterSpec spec = new TlsKeyMaterialParameterSpec // Which algs/params do we need to use?
(masterKey, protocolVersion.major, protocolVersion.minor, 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, clnt_random.random_bytes, svr_random.random_bytes,
cipher.algorithm, cipher.keySize, expandedKeySize, cipher.algorithm, cipher.keySize, expandedKeySize,
cipher.ivSize, hashSize); cipher.ivSize, hashSize,
prfHashAlg, prfHashLength, prfBlockSize);
try { try {
KeyGenerator kg = JsseJce.getKeyGenerator("SunTlsKeyMaterial"); KeyGenerator kg = JsseJce.getKeyGenerator(keyMaterialAlg);
kg.init(spec); kg.init(spec);
TlsKeyMaterialSpec keySpec = (TlsKeyMaterialSpec)kg.generateKey(); TlsKeyMaterialSpec keySpec = (TlsKeyMaterialSpec)kg.generateKey();
......
...@@ -50,7 +50,8 @@ import javax.net.ssl.SSLProtocolException; ...@@ -50,7 +50,8 @@ import javax.net.ssl.SSLProtocolException;
* *
* . UnknownExtension: used to represent all parsed extensions that we do not * . UnknownExtension: used to represent all parsed extensions that we do not
* explicitly support. * explicitly support.
* . ServerNameExtension: partially implemented server_name extension. * . ServerNameExtension: the server_name extension.
* . SignatureAlgorithmsExtension: the signature_algorithms extension.
* . SupportedEllipticCurvesExtension: the ECC supported curves extension. * . SupportedEllipticCurvesExtension: the ECC supported curves extension.
* . SupportedEllipticPointFormatsExtension: the ECC supported point formats * . SupportedEllipticPointFormatsExtension: the ECC supported point formats
* (compressed/uncompressed) extension. * (compressed/uncompressed) extension.
...@@ -78,6 +79,8 @@ final class HelloExtensions { ...@@ -78,6 +79,8 @@ final class HelloExtensions {
HelloExtension extension; HelloExtension extension;
if (extType == ExtensionType.EXT_SERVER_NAME) { if (extType == ExtensionType.EXT_SERVER_NAME) {
extension = new ServerNameExtension(s, extlen); extension = new ServerNameExtension(s, extlen);
} else if (extType == ExtensionType.EXT_SIGNATURE_ALGORITHMS) {
extension = new SignatureAlgorithmsExtension(s, extlen);
} else if (extType == ExtensionType.EXT_ELLIPTIC_CURVES) { } else if (extType == ExtensionType.EXT_ELLIPTIC_CURVES) {
extension = new SupportedEllipticCurvesExtension(s, extlen); extension = new SupportedEllipticCurvesExtension(s, extlen);
} else if (extType == ExtensionType.EXT_EC_POINT_FORMATS) { } else if (extType == ExtensionType.EXT_EC_POINT_FORMATS) {
...@@ -266,31 +269,102 @@ final class UnknownExtension extends HelloExtension { ...@@ -266,31 +269,102 @@ final class UnknownExtension extends HelloExtension {
} }
public String toString() { 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 * [RFC4366] To facilitate secure connections to servers that host multiple
* so that we get nicer debug output, but we neither send it nor do we do * 'virtual' servers at a single underlying network address, clients MAY
* act on it if we receive it. * 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 class ServerNameExtension extends HelloExtension {
final static int NAME_HOST_NAME = 0; final static int NAME_HOST_NAME = 0;
private List<ServerName> names; 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) ServerNameExtension(HandshakeInStream s, int len)
throws IOException { throws IOException {
super(ExtensionType.EXT_SERVER_NAME); super(ExtensionType.EXT_SERVER_NAME);
names = new ArrayList<ServerName>();
while (len > 0) { int remains = len;
ServerName name = new ServerName(s); if (len >= 2) { // "server_name" extension in ClientHello
names.add(name); listLength = s.getInt16(); // ServerNameList length
len -= name.length + 2; 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"); throw new SSLProtocolException("Invalid server_name extension");
} }
} }
...@@ -301,10 +375,19 @@ final class ServerNameExtension extends HelloExtension { ...@@ -301,10 +375,19 @@ final class ServerNameExtension extends HelloExtension {
final byte[] data; final byte[] data;
final String hostname; 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 { ServerName(HandshakeInStream s) throws IOException {
length = s.getInt16(); // ServerNameList length
type = s.getInt8(); // NameType type = s.getInt8(); // NameType
data = s.getBytes16(); // HostName (length read in getBytes16) data = s.getBytes16(); // HostName (length read in getBytes16)
length = data.length + 3; // NameType: 1 byte
// HostName length: 2 bytes
if (type == NAME_HOST_NAME) { if (type == NAME_HOST_NAME) {
hostname = new String(data, "UTF8"); hostname = new String(data, "UTF8");
} else { } else {
...@@ -322,15 +405,29 @@ final class ServerNameExtension extends HelloExtension { ...@@ -322,15 +405,29 @@ final class ServerNameExtension extends HelloExtension {
} }
int length() { int length() {
throw new RuntimeException("not yet supported"); return listLength == 0 ? 4 : 6 + listLength;
} }
void send(HandshakeOutStream s) throws IOException { 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() { 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 { ...@@ -523,7 +620,8 @@ final class SupportedEllipticPointFormatsExtension extends HelloExtension {
final static int FMT_ANSIX962_COMPRESSED_CHAR2 = 2; final static int FMT_ANSIX962_COMPRESSED_CHAR2 = 2;
static final HelloExtension DEFAULT = static final HelloExtension DEFAULT =
new SupportedEllipticPointFormatsExtension(new byte[] {FMT_UNCOMPRESSED}); new SupportedEllipticPointFormatsExtension(
new byte[] {FMT_UNCOMPRESSED});
private final byte[] formats; private final byte[] formats;
...@@ -665,3 +763,105 @@ final class RenegotiationInfoExtension extends HelloExtension { ...@@ -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;
}
}
...@@ -105,6 +105,10 @@ final class MAC { ...@@ -105,6 +105,10 @@ final class MAC {
algorithm = tls ? "HmacMD5" : "SslMacMD5"; algorithm = tls ? "HmacMD5" : "SslMacMD5";
} else if (macAlg == M_SHA) { } else if (macAlg == M_SHA) {
algorithm = tls ? "HmacSHA1" : "SslMacSHA1"; 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 { } else {
throw new RuntimeException("Unknown Mac " + macAlg); throw new RuntimeException("Unknown Mac " + macAlg);
} }
...@@ -204,7 +208,8 @@ final class MAC { ...@@ -204,7 +208,8 @@ final class MAC {
* Compute based on either buffer type, either bb.position/limit * Compute based on either buffer type, either bb.position/limit
* or buf/offset/len. * 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) { if (macSize == 0) {
return nullMAC; return nullMAC;
......
...@@ -181,7 +181,8 @@ final class ProtocolList { ...@@ -181,7 +181,8 @@ final class ProtocolList {
if (SunJSSE.isFIPS()) { if (SunJSSE.isFIPS()) {
SUPPORTED = new ProtocolList(new String[] { SUPPORTED = new ProtocolList(new String[] {
ProtocolVersion.TLS10.name, ProtocolVersion.TLS10.name,
ProtocolVersion.TLS11.name ProtocolVersion.TLS11.name,
ProtocolVersion.TLS12.name
}); });
SERVER_DEFAULT = SUPPORTED; SERVER_DEFAULT = SUPPORTED;
...@@ -193,10 +194,21 @@ final class ProtocolList { ...@@ -193,10 +194,21 @@ final class ProtocolList {
ProtocolVersion.SSL20Hello.name, ProtocolVersion.SSL20Hello.name,
ProtocolVersion.SSL30.name, ProtocolVersion.SSL30.name,
ProtocolVersion.TLS10.name, ProtocolVersion.TLS10.name,
ProtocolVersion.TLS11.name ProtocolVersion.TLS11.name,
ProtocolVersion.TLS12.name
}); });
SERVER_DEFAULT = SUPPORTED; 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[] { CLIENT_DEFAULT = new ProtocolList(new String[] {
ProtocolVersion.SSL30.name, ProtocolVersion.SSL30.name,
ProtocolVersion.TLS10.name ProtocolVersion.TLS10.name
......
...@@ -50,6 +50,9 @@ public final class ProtocolVersion implements Comparable<ProtocolVersion> { ...@@ -50,6 +50,9 @@ public final class ProtocolVersion implements Comparable<ProtocolVersion> {
// The limit of maximum protocol version // The limit of maximum protocol version
final static int LIMIT_MAX_VALUE = 0xFFFF; 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 // Dummy protocol version value for invalid SSLSession
final static ProtocolVersion NONE = new ProtocolVersion(-1, "NONE"); final static ProtocolVersion NONE = new ProtocolVersion(-1, "NONE");
...@@ -74,8 +77,8 @@ public final class ProtocolVersion implements Comparable<ProtocolVersion> { ...@@ -74,8 +77,8 @@ public final class ProtocolVersion implements Comparable<ProtocolVersion> {
// minimum version we implement (SSL 3.0) // minimum version we implement (SSL 3.0)
final static ProtocolVersion MIN = FIPS ? TLS10 : SSL30; final static ProtocolVersion MIN = FIPS ? TLS10 : SSL30;
// maximum version we implement (TLS 1.1) // maximum version we implement (TLS 1.2)
final static ProtocolVersion MAX = TLS11; final static ProtocolVersion MAX = TLS12;
// ProtocolVersion to use by default (TLS 1.0) // ProtocolVersion to use by default (TLS 1.0)
final static ProtocolVersion DEFAULT = TLS10; final static ProtocolVersion DEFAULT = TLS10;
......
...@@ -100,8 +100,9 @@ final class RSAClientKeyExchange extends HandshakeMessage { ...@@ -100,8 +100,9 @@ final class RSAClientKeyExchange extends HandshakeMessage {
} }
try { try {
KeyGenerator kg = String s = ((protocolVersion.v >= ProtocolVersion.TLS12.v) ?
JsseJce.getKeyGenerator("SunTlsRsaPremasterSecret"); "SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret");
KeyGenerator kg = JsseJce.getKeyGenerator(s);
kg.init(new TlsRsaPremasterSecretParameterSpec(major, minor)); kg.init(new TlsRsaPremasterSecretParameterSpec(major, minor));
preMaster = kg.generateKey(); preMaster = kg.generateKey();
...@@ -242,8 +243,9 @@ final class RSAClientKeyExchange extends HandshakeMessage { ...@@ -242,8 +243,9 @@ final class RSAClientKeyExchange extends HandshakeMessage {
// generate a premaster secret with the specified version number // generate a premaster secret with the specified version number
static SecretKey generateDummySecret(ProtocolVersion version) { static SecretKey generateDummySecret(ProtocolVersion version) {
try { try {
KeyGenerator kg = String s = ((version.v >= ProtocolVersion.TLS12.v) ?
JsseJce.getKeyGenerator("SunTlsRsaPremasterSecret"); "SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret");
KeyGenerator kg = JsseJce.getKeyGenerator(s);
kg.init(new TlsRsaPremasterSecretParameterSpec kg.init(new TlsRsaPremasterSecretParameterSpec
(version.major, version.minor)); (version.major, version.minor));
return kg.generateKey(); return kg.generateKey();
......
...@@ -129,7 +129,8 @@ public abstract class SunJSSE extends java.security.Provider { ...@@ -129,7 +129,8 @@ public abstract class SunJSSE extends java.security.Provider {
return t; return t;
} }
private SunJSSE(java.security.Provider cryptoProvider, String providerName) { private SunJSSE(java.security.Provider cryptoProvider,
String providerName) {
super("SunJSSE", 1.6d, fipsInfo + providerName + ")"); super("SunJSSE", 1.6d, fipsInfo + providerName + ")");
subclassCheck(); subclassCheck();
if (cryptoProvider == null) { if (cryptoProvider == null) {
...@@ -213,6 +214,8 @@ public abstract class SunJSSE extends java.security.Provider { ...@@ -213,6 +214,8 @@ public abstract class SunJSSE extends java.security.Provider {
"sun.security.ssl.SSLContextImpl"); "sun.security.ssl.SSLContextImpl");
put("SSLContext.TLSv1.1", put("SSLContext.TLSv1.1",
"sun.security.ssl.SSLContextImpl"); "sun.security.ssl.SSLContextImpl");
put("SSLContext.TLSv1.2",
"sun.security.ssl.SSLContextImpl");
put("SSLContext.Default", put("SSLContext.Default",
"sun.security.ssl.DefaultSSLContextImpl"); "sun.security.ssl.DefaultSSLContextImpl");
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -97,17 +97,22 @@ public class TestMasterSecret extends Utils { ...@@ -97,17 +97,22 @@ public class TestMasterSecret extends Utils {
System.out.print("."); System.out.print(".");
n++; n++;
KeyGenerator kg = KeyGenerator.getInstance("SunTlsMasterSecret", provider); KeyGenerator kg =
SecretKey premasterKey = new SecretKeySpec(premaster, algorithm); KeyGenerator.getInstance("SunTlsMasterSecret", provider);
TlsMasterSecretParameterSpec spec = new TlsMasterSecretParameterSpec SecretKey premasterKey =
(premasterKey, protoMajor, protoMinor, clientRandom, serverRandom); new SecretKeySpec(premaster, algorithm);
TlsMasterSecretParameterSpec spec =
new TlsMasterSecretParameterSpec(premasterKey, protoMajor,
protoMinor, clientRandom, serverRandom,
null, -1, -1);
kg.init(spec); kg.init(spec);
TlsMasterSecret key = (TlsMasterSecret)kg.generateKey(); TlsMasterSecret key = (TlsMasterSecret)kg.generateKey();
byte[] enc = key.getEncoded(); byte[] enc = key.getEncoded();
if (Arrays.equals(master, enc) == false) { if (Arrays.equals(master, enc) == false) {
throw new Exception("mismatch line: " + lineNumber); throw new Exception("mismatch line: " + lineNumber);
} }
if ((preMajor != key.getMajorVersion()) || (preMinor != key.getMinorVersion())) { if ((preMajor != key.getMajorVersion()) ||
(preMinor != key.getMinorVersion())) {
throw new Exception("version mismatch line: " + lineNumber); throw new Exception("version mismatch line: " + lineNumber);
} }
} else { } else {
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册