提交 8385d6e8 编写于 作者: A alanb

Merge

...@@ -148,14 +148,9 @@ include $(BUILDDIR)/common/Library.gmk ...@@ -148,14 +148,9 @@ include $(BUILDDIR)/common/Library.gmk
# #
ifeq ($(PLATFORM), windows) ifeq ($(PLATFORM), windows)
STATIC_LIBRARY_DIR = $(OBJDIR)/static STATIC_LIBRARY = $(OBJDIR)/static/$(LIBPREFIX)$(LIBRARY).lib
STATIC_LIBRARY_NAME = $(LIBPREFIX)$(LIBRARY).lib
STATIC_LIBRARY = $(STATIC_LIBRARY_DIR)/$(STATIC_LIBRARY_NAME)
$(STATIC_LIBRARY_DIR): $(OBJDIR) $(STATIC_LIBRARY): $(FILES_o)
@$(MKDIR) $(STATIC_LIBRARY_DIR)
$(STATIC_LIBRARY): $(STATIC_LIBRARY_DIR)
@$(prep-target) @$(prep-target)
$(LIBEXE) -nologo -out:$@ $(FILES_o) $(LIBEXE) -nologo -out:$@ $(FILES_o)
......
/* /*
* 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,7 +864,8 @@ public final class JceKeyStore extends KeyStoreSpi { ...@@ -863,7 +864,8 @@ 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(
"Keystore was tampered with, or "
+ "password was incorrect"); + "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,7 +155,8 @@ final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey { ...@@ -155,7 +155,8 @@ 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(
sk.getAlgorithm()) &&
Arrays.equals(password, sk.getEncoded()); Arrays.equals(password, sk.getEncoded());
} }
}; };
......
/* /*
* 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); byte[] seed = concat(serverRandom, clientRandom);
keyBlock = doPRF(masterSecret, LABEL_KEY_EXPANSION, seed, keyBlock = doTLS12PRF(masterSecret, LABEL_KEY_EXPANSION, seed,
keyBlockLen, spec.getPRFHashAlg(),
spec.getPRFHashLength(), spec.getPRFBlockSize());
} else if (protocolVersion >= 0x0301) {
// TLS 1.0/1.1
md5 = MessageDigest.getInstance("MD5");
sha = MessageDigest.getInstance("SHA1");
byte[] seed = concat(serverRandom, clientRandom);
keyBlock = doTLS10PRF(masterSecret, LABEL_KEY_EXPANSION, seed,
keyBlockLen, md5, sha); 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 java.security;
import java.util.Set;
/**
* This interface specifies constraints for cryptographic algorithms,
* keys (key sizes), and other algorithm parameters.
* <p>
* {@code AlgorithmConstraints} objects are immutable. An implementation
* of this interface should not provide methods that can change the state
* of an instance once it has been created.
* <p>
* Note that {@code AlgorithmConstraints} can be used to represent the
* restrictions described by the security properties
* {@code jdk.certpath.disabledAlgorithms} and
* {@code jdk.tls.disabledAlgorithms}, or could be used by a
* concrete {@code PKIXCertPathChecker} to check whether a specified
* certificate in the certification path contains the required algorithm
* constraints.
*
* @see javax.net.ssl.SSLParameters#getAlgorithmConstraints
* @see javax.net.ssl.SSLParameters#setAlgorithmConstraints(AlgorithmConstraints)
*
* @since 1.7
*/
public interface AlgorithmConstraints {
/**
* Determines whether an algorithm is granted permission for the
* specified cryptographic primitives.
*
* @param primitives a set of cryptographic primitives
* @param algorithm the algorithm name
* @param parameters the algorithm parameters, or null if no additional
* parameters
*
* @return true if the algorithm is permitted and can be used for all
* of the specified cryptographic primitives
*
* @throws IllegalArgumentException if primitives or algorithm is null
* or empty
*/
public boolean permits(Set<CryptoPrimitive> primitives,
String algorithm, AlgorithmParameters parameters);
/**
* Determines whether a key is granted permission for the specified
* cryptographic primitives.
* <p>
* This method is usually used to check key size and key usage.
*
* @param primitives a set of cryptographic primitives
* @param key the key
*
* @return true if the key can be used for all of the specified
* cryptographic primitives
*
* @throws IllegalArgumentException if primitives is null or empty,
* or the key is null
*/
public boolean permits(Set<CryptoPrimitive> primitives, Key key);
/**
* Determines whether an algorithm and the corresponding key are granted
* permission for the specified cryptographic primitives.
*
* @param primitives a set of cryptographic primitives
* @param algorithm the algorithm name
* @param key the key
* @param parameters the algorithm parameters, or null if no additional
* parameters
*
* @return true if the key and the algorithm can be used for all of the
* specified cryptographic primitives
*
* @throws IllegalArgumentException if primitives or algorithm is null
* or empty, or the key is null
*/
public boolean permits(Set<CryptoPrimitive> primitives,
String algorithm, Key key, AlgorithmParameters parameters);
}
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.security;
/**
* An enumeration of cryptographic primitives.
*
* @since 1.7
*/
public enum CryptoPrimitive {
/**
* Hash function
*/
MESSAGE_DIGEST,
/**
* Cryptographic random number generator
*/
SECURE_RANDOM,
/**
* Symmetric primitive: block cipher
*/
BLOCK_CIPHER,
/**
* Symmetric primitive: stream cipher
*/
STREAM_CIPHER,
/**
* Symmetric primitive: message authentication code
*/
MAC,
/**
* Symmetric primitive: key wrap
*/
KEY_WRAP,
/**
* Asymmetric primitive: public key encryption
*/
PUBLIC_KEY_ENCRYPTION,
/**
* Asymmetric primitive: signature scheme
*/
SIGNATURE,
/**
* Asymmetric primitive: key encapsulation mechanism
*/
KEY_ENCAPSULATION,
/**
* Asymmetric primitive: key agreement and key distribution
*/
KEY_AGREEMENT
}
/*
* 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) 2009, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * 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,95 +25,336 @@ ...@@ -25,95 +25,336 @@
package sun.security.provider.certpath; package sun.security.provider.certpath;
import java.util.Set; import java.security.AlgorithmConstraints;
import java.security.CryptoPrimitive;
import java.util.Collection; import java.util.Collection;
import java.util.Locale; import java.util.Collections;
import java.util.Set;
import java.util.EnumSet;
import java.util.HashSet;
import java.math.BigInteger;
import java.security.PublicKey;
import java.security.KeyFactory;
import java.security.AlgorithmParameters;
import java.security.NoSuchAlgorithmException;
import java.security.GeneralSecurityException;
import java.security.cert.Certificate; import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.security.cert.X509CRL; import java.security.cert.X509CRL;
import java.security.cert.CertPathValidatorException; import java.security.cert.X509Certificate;
import java.security.cert.PKIXCertPathChecker; import java.security.cert.PKIXCertPathChecker;
import java.security.cert.TrustAnchor;
import java.security.cert.CRLException;
import java.security.cert.CertificateException;
import java.security.cert.CertPathValidatorException;
import java.io.IOException;
import java.security.interfaces.*;
import java.security.spec.*;
import sun.security.util.DisabledAlgorithmConstraints;
import sun.security.x509.X509CertImpl;
import sun.security.x509.X509CRLImpl;
import sun.security.x509.AlgorithmId; import sun.security.x509.AlgorithmId;
/** /**
* AlgorithmChecker is a <code>PKIXCertPathChecker</code> that checks that * A <code>PKIXCertPathChecker</code> implementation to check whether a
* the signature algorithm of the specified certificate is not disabled. * specified certificate contains the required algorithm constraints.
* <p>
* Certificate fields such as the subject public key, the signature
* algorithm, key usage, extended key usage, etc. need to conform to
* the specified algorithm constraints.
* *
* @author Xuelei Fan * @see PKIXCertPathChecker
* @see PKIXParameters
*/ */
final public class AlgorithmChecker extends PKIXCertPathChecker { final public class AlgorithmChecker extends PKIXCertPathChecker {
// the disabled algorithms private final AlgorithmConstraints constraints;
private static final String[] disabledAlgorithms = new String[] {"md2"}; private final PublicKey trustedPubKey;
private PublicKey prevPubKey;
// singleton instance private final static Set<CryptoPrimitive> SIGNATURE_PRIMITIVE_SET =
static final AlgorithmChecker INSTANCE = new AlgorithmChecker(); EnumSet.of(CryptoPrimitive.SIGNATURE);
private final static DisabledAlgorithmConstraints
certPathDefaultConstraints = new DisabledAlgorithmConstraints(
DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS);
/** /**
* Default Constructor * Create a new <code>AlgorithmChecker</code> with the algorithm
* constraints specified in security property
* "jdk.certpath.disabledAlgorithms".
*
* @param anchor the trust anchor selected to validate the target
* certificate
*/ */
private AlgorithmChecker() { public AlgorithmChecker(TrustAnchor anchor) {
// do nothing this(anchor, certPathDefaultConstraints);
} }
/** /**
* Return a AlgorithmChecker instance. * Create a new <code>AlgorithmChecker</code> with the
* given {@code AlgorithmConstraints}.
* <p>
* Note that this constructor will be used to check a certification
* path where the trust anchor is unknown, or a certificate list which may
* contain the trust anchor. This constructor is used by SunJSSE.
*
* @param constraints the algorithm constraints (or null)
*/ */
static AlgorithmChecker getInstance() { public AlgorithmChecker(AlgorithmConstraints constraints) {
return INSTANCE; this.prevPubKey = null;
this.trustedPubKey = null;
this.constraints = constraints;
} }
/** /**
* Initializes the internal state of the checker from parameters * Create a new <code>AlgorithmChecker</code> with the
* specified in the constructor. * given <code>TrustAnchor</code> and <code>AlgorithmConstraints</code>.
*
* @param anchor the trust anchor selected to validate the target
* certificate
* @param constraints the algorithm constraints (or null)
*
* @throws IllegalArgumentException if the <code>anchor</code> is null
*/ */
public AlgorithmChecker(TrustAnchor anchor,
AlgorithmConstraints constraints) {
if (anchor == null) {
throw new IllegalArgumentException(
"The trust anchor cannot be null");
}
if (anchor.getTrustedCert() != null) {
this.trustedPubKey = anchor.getTrustedCert().getPublicKey();
} else {
this.trustedPubKey = anchor.getCAPublicKey();
}
this.prevPubKey = trustedPubKey;
this.constraints = constraints;
}
@Override
public void init(boolean forward) throws CertPathValidatorException { public void init(boolean forward) throws CertPathValidatorException {
// do nothing // Note that this class does not support forward mode.
if (!forward) {
if (trustedPubKey != null) {
prevPubKey = trustedPubKey;
} else {
prevPubKey = null;
}
} else {
throw new
CertPathValidatorException("forward checking not supported");
}
} }
@Override
public boolean isForwardCheckingSupported() { public boolean isForwardCheckingSupported() {
// Note that as this class does not support forward mode, the method
// will always returns false.
return false; return false;
} }
@Override
public Set<String> getSupportedExtensions() { public Set<String> getSupportedExtensions() {
return null; return null;
} }
/** @Override
* Checks the signature algorithm of the specified certificate. public void check(Certificate cert,
*/ Collection<String> unresolvedCritExts)
public void check(Certificate cert, Collection<String> unresolvedCritExts)
throws CertPathValidatorException { throws CertPathValidatorException {
check(cert);
if (!(cert instanceof X509Certificate) || constraints == null) {
// ignore the check for non-x.509 certificate or null constraints
return;
} }
public static void check(Certificate cert) X509CertImpl x509Cert = null;
throws CertPathValidatorException { try {
X509Certificate xcert = (X509Certificate)cert; x509Cert = X509CertImpl.toImpl((X509Certificate)cert);
check(xcert.getSigAlgName()); } catch (CertificateException ce) {
throw new CertPathValidatorException(ce);
} }
static void check(AlgorithmId aid) throws CertPathValidatorException { PublicKey currPubKey = x509Cert.getPublicKey();
check(aid.getName()); String currSigAlg = x509Cert.getSigAlgName();
AlgorithmId algorithmId = null;
try {
algorithmId = (AlgorithmId)x509Cert.get(X509CertImpl.SIG_ALG);
} catch (CertificateException ce) {
throw new CertPathValidatorException(ce);
} }
static void check(X509CRL crl) throws CertPathValidatorException { AlgorithmParameters currSigAlgParams = algorithmId.getParameters();
check(crl.getSigAlgName());
// Check the current signature algorithm
if (!constraints.permits(
SIGNATURE_PRIMITIVE_SET,
currSigAlg, currSigAlgParams)) {
throw new CertPathValidatorException(
"Algorithm constraints check failed: " + currSigAlg);
} }
private static void check(String algName) // check the key usage and key size
throws CertPathValidatorException { boolean[] keyUsage = x509Cert.getKeyUsage();
if (keyUsage != null && keyUsage.length < 9) {
throw new CertPathValidatorException(
"incorrect KeyUsage extension");
}
if (keyUsage != null) {
Set<CryptoPrimitive> primitives =
EnumSet.noneOf(CryptoPrimitive.class);
if (keyUsage[0] || keyUsage[1] || keyUsage[5] || keyUsage[6]) {
// keyUsage[0]: KeyUsage.digitalSignature
// keyUsage[1]: KeyUsage.nonRepudiation
// keyUsage[5]: KeyUsage.keyCertSign
// keyUsage[6]: KeyUsage.cRLSign
primitives.add(CryptoPrimitive.SIGNATURE);
}
if (keyUsage[2]) { // KeyUsage.keyEncipherment
primitives.add(CryptoPrimitive.KEY_ENCAPSULATION);
}
if (keyUsage[3]) { // KeyUsage.dataEncipherment
primitives.add(CryptoPrimitive.PUBLIC_KEY_ENCRYPTION);
}
if (keyUsage[4]) { // KeyUsage.keyAgreement
primitives.add(CryptoPrimitive.KEY_AGREEMENT);
}
// KeyUsage.encipherOnly and KeyUsage.decipherOnly are
// undefined in the absence of the keyAgreement bit.
if (!primitives.isEmpty()) {
if (!constraints.permits(primitives, currPubKey)) {
throw new CertPathValidatorException(
"algorithm constraints check failed");
}
}
}
String lowerCaseAlgName = algName.toLowerCase(Locale.ENGLISH); // Check with previous cert for signature algorithm and public key
if (prevPubKey != null) {
if (currSigAlg != null) {
if (!constraints.permits(
SIGNATURE_PRIMITIVE_SET,
currSigAlg, prevPubKey, currSigAlgParams)) {
throw new CertPathValidatorException(
"Algorithm constraints check failed: " + currSigAlg);
}
}
for (String disabled : disabledAlgorithms) { // Inherit key parameters from previous key
// checking the signature algorithm name if (currPubKey instanceof DSAPublicKey &&
if (lowerCaseAlgName.indexOf(disabled) != -1) { ((DSAPublicKey)currPubKey).getParams() == null) {
// Inherit DSA parameters from previous key
if (!(prevPubKey instanceof DSAPublicKey)) {
throw new CertPathValidatorException("Input key is not " +
"of a appropriate type for inheriting parameters");
}
DSAParams params = ((DSAPublicKey)prevPubKey).getParams();
if (params == null) {
throw new CertPathValidatorException( throw new CertPathValidatorException(
"algorithm check failed: " + algName + " is disabled"); "Key parameters missing");
}
try {
BigInteger y = ((DSAPublicKey)currPubKey).getY();
KeyFactory kf = KeyFactory.getInstance("DSA");
DSAPublicKeySpec ks = new DSAPublicKeySpec(y,
params.getP(),
params.getQ(),
params.getG());
currPubKey = kf.generatePublic(ks);
} catch (GeneralSecurityException e) {
throw new CertPathValidatorException("Unable to generate " +
"key with inherited parameters: " + e.getMessage(), e);
}
}
}
// reset the previous public key
prevPubKey = currPubKey;
// check the extended key usage, ignore the check now
// List<String> extendedKeyUsages = x509Cert.getExtendedKeyUsage();
// DO NOT remove any unresolved critical extensions
}
/**
* Try to set the trust anchor of the checker.
* <p>
* If there is no trust anchor specified and the checker has not started,
* set the trust anchor.
*
* @param anchor the trust anchor selected to validate the target
* certificate
*/
void trySetTrustAnchor(TrustAnchor anchor) {
// Don't bother if the check has started or trust anchor has already
// specified.
if (prevPubKey == null) {
if (anchor == null) {
throw new IllegalArgumentException(
"The trust anchor cannot be null");
}
// Don't bother to change the trustedPubKey.
if (anchor.getTrustedCert() != null) {
prevPubKey = anchor.getTrustedCert().getPublicKey();
} else {
prevPubKey = anchor.getCAPublicKey();
}
} }
} }
/**
* Check the signature algorithm with the specified public key.
*
* @param key the public key to verify the CRL signature
* @param crl the target CRL
*/
static void check(PublicKey key, X509CRL crl)
throws CertPathValidatorException {
X509CRLImpl x509CRLImpl = null;
try {
x509CRLImpl = X509CRLImpl.toImpl(crl);
} catch (CRLException ce) {
throw new CertPathValidatorException(ce);
}
AlgorithmId algorithmId = x509CRLImpl.getSigAlgId();
check(key, algorithmId);
}
/**
* Check the signature algorithm with the specified public key.
*
* @param key the public key to verify the CRL signature
* @param crl the target CRL
*/
static void check(PublicKey key, AlgorithmId algorithmId)
throws CertPathValidatorException {
String sigAlgName = algorithmId.getName();
AlgorithmParameters sigAlgParams = algorithmId.getParameters();
if (!certPathDefaultConstraints.permits(
SIGNATURE_PRIMITIVE_SET, sigAlgName, key, sigAlgParams)) {
throw new CertPathValidatorException(
"algorithm check failed: " + sigAlgName + " is disabled");
}
} }
} }
/* /*
* Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * 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
...@@ -289,16 +289,6 @@ class DistributionPointFetcher { ...@@ -289,16 +289,6 @@ class DistributionPointFetcher {
X500Name certIssuer = (X500Name) certImpl.getIssuerDN(); X500Name certIssuer = (X500Name) certImpl.getIssuerDN();
X500Name crlIssuer = (X500Name) crlImpl.getIssuerDN(); X500Name crlIssuer = (X500Name) crlImpl.getIssuerDN();
// check the crl signature algorithm
try {
AlgorithmChecker.check(crl);
} catch (CertPathValidatorException cpve) {
if (debug != null) {
debug.println("CRL signature algorithm check failed: " + cpve);
}
return false;
}
// if crlIssuer is set, verify that it matches the issuer of the // if crlIssuer is set, verify that it matches the issuer of the
// CRL and the CRL contains an IDP extension with the indirectCRL // CRL and the CRL contains an IDP extension with the indirectCRL
// boolean asserted. Otherwise, verify that the CRL issuer matches the // boolean asserted. Otherwise, verify that the CRL issuer matches the
...@@ -637,6 +627,16 @@ class DistributionPointFetcher { ...@@ -637,6 +627,16 @@ class DistributionPointFetcher {
} }
} }
// check the crl signature algorithm
try {
AlgorithmChecker.check(prevKey, crl);
} catch (CertPathValidatorException cpve) {
if (debug != null) {
debug.println("CRL signature algorithm check failed: " + cpve);
}
return false;
}
// validate the signature on the CRL // validate the signature on the CRL
try { try {
crl.verify(prevKey, provider); crl.verify(prevKey, provider);
......
/* /*
* Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * 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
...@@ -718,11 +718,6 @@ class ForwardBuilder extends Builder { ...@@ -718,11 +718,6 @@ class ForwardBuilder extends Builder {
/* we don't perform any validation of the trusted cert */ /* we don't perform any validation of the trusted cert */
if (!isTrustedCert) { if (!isTrustedCert) {
/*
* check that the signature algorithm is not disabled.
*/
AlgorithmChecker.check(cert);
/* /*
* Check CRITICAL private extensions for user checkers that * Check CRITICAL private extensions for user checkers that
* support forward checking (forwardCheckers) and remove * support forward checking (forwardCheckers) and remove
......
/* /*
* 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
...@@ -327,6 +327,10 @@ class OCSPChecker extends PKIXCertPathChecker { ...@@ -327,6 +327,10 @@ class OCSPChecker extends PKIXCertPathChecker {
"(set using the OCSP security properties)."); "(set using the OCSP security properties).");
} }
// The algorithm constraints of the OCSP trusted responder certificate
// does not need to be checked in this code. The constraints will be
// checked when the responder's certificate is validated.
CertId certId = null; CertId certId = null;
OCSPResponse response = null; OCSPResponse response = null;
try { try {
......
/* /*
* 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
...@@ -32,6 +32,7 @@ import java.security.cert.CertificateException; ...@@ -32,6 +32,7 @@ import java.security.cert.CertificateException;
import java.security.cert.CertificateParsingException; import java.security.cert.CertificateParsingException;
import java.security.cert.CertPathValidatorException; import java.security.cert.CertPathValidatorException;
import java.security.cert.CRLReason; import java.security.cert.CRLReason;
import java.security.cert.TrustAnchor;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.util.Collections; import java.util.Collections;
import java.util.Date; import java.util.Date;
...@@ -371,6 +372,13 @@ public final class OCSPResponse { ...@@ -371,6 +372,13 @@ public final class OCSPResponse {
"OCSP responses", cpe); "OCSP responses", cpe);
} }
// Check algorithm constraints specified in security property
// "jdk.certpath.disabledAlgorithms".
AlgorithmChecker algChecker = new AlgorithmChecker(
new TrustAnchor(responderCert, null));
algChecker.init(false);
algChecker.check(cert, Collections.<String>emptySet());
// check the validity // check the validity
try { try {
if (dateCheckedAgainst == null) { if (dateCheckedAgainst == null) {
...@@ -422,6 +430,10 @@ public final class OCSPResponse { ...@@ -422,6 +430,10 @@ public final class OCSPResponse {
// Confirm that the signed response was generated using the public // Confirm that the signed response was generated using the public
// key from the trusted responder cert // key from the trusted responder cert
if (responderCert != null) { if (responderCert != null) {
// Check algorithm constraints specified in security property
// "jdk.certpath.disabledAlgorithms".
AlgorithmChecker.check(responderCert.getPublicKey(), sigAlgId);
if (!verifyResponse(responseDataDer, responderCert, if (!verifyResponse(responseDataDer, responderCert,
sigAlgId, signature)) { sigAlgId, signature)) {
throw new CertPathValidatorException( throw new CertPathValidatorException(
......
/* /*
* Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * 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
...@@ -275,7 +275,7 @@ public class PKIXCertPathValidator extends CertPathValidatorSpi { ...@@ -275,7 +275,7 @@ public class PKIXCertPathValidator extends CertPathValidatorSpi {
int certPathLen = certList.size(); int certPathLen = certList.size();
basicChecker = new BasicChecker(anchor, testDate, sigProvider, false); basicChecker = new BasicChecker(anchor, testDate, sigProvider, false);
AlgorithmChecker algorithmChecker= AlgorithmChecker.getInstance(); AlgorithmChecker algorithmChecker = new AlgorithmChecker(anchor);
KeyChecker keyChecker = new KeyChecker(certPathLen, KeyChecker keyChecker = new KeyChecker(certPathLen,
pkixParam.getTargetCertConstraints()); pkixParam.getTargetCertConstraints());
ConstraintsChecker constraintsChecker = ConstraintsChecker constraintsChecker =
......
/* /*
* Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * 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
...@@ -347,9 +347,6 @@ class ReverseBuilder extends Builder { ...@@ -347,9 +347,6 @@ class ReverseBuilder extends Builder {
return; return;
} }
/* check that the signature algorithm is not disabled. */
AlgorithmChecker.check(cert);
/* /*
* check for looping - abort a loop if * check for looping - abort a loop if
* ((we encounter the same certificate twice) AND * ((we encounter the same certificate twice) AND
...@@ -470,9 +467,16 @@ class ReverseBuilder extends Builder { ...@@ -470,9 +467,16 @@ class ReverseBuilder extends Builder {
if (unresolvedCritExts == null) { if (unresolvedCritExts == null) {
unresolvedCritExts = Collections.<String>emptySet(); unresolvedCritExts = Collections.<String>emptySet();
} }
/*
* Check that the signature algorithm is not disabled.
*/
currentState.algorithmChecker.check(cert, unresolvedCritExts);
for (PKIXCertPathChecker checker : currentState.userCheckers) { for (PKIXCertPathChecker checker : currentState.userCheckers) {
checker.check(cert, unresolvedCritExts); checker.check(cert, unresolvedCritExts);
} }
/* /*
* Look at the remaining extensions and remove any ones we have * Look at the remaining extensions and remove any ones we have
* already checked. If there are any left, throw an exception! * already checked. If there are any left, throw an exception!
......
/* /*
* Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * 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
...@@ -96,6 +96,9 @@ class ReverseState implements State { ...@@ -96,6 +96,9 @@ class ReverseState implements State {
/* the checker used for revocation status */ /* the checker used for revocation status */
public CrlRevocationChecker crlChecker; public CrlRevocationChecker crlChecker;
/* the algorithm checker */
AlgorithmChecker algorithmChecker;
/* the trust anchor used to validate the path */ /* the trust anchor used to validate the path */
TrustAnchor trustAnchor; TrustAnchor trustAnchor;
...@@ -241,6 +244,14 @@ class ReverseState implements State { ...@@ -241,6 +244,14 @@ class ReverseState implements State {
updateState(anchor.getCAPublicKey(), caName); updateState(anchor.getCAPublicKey(), caName);
} }
// The user specified AlgorithmChecker may not be
// able to set the trust anchor until now.
for (PKIXCertPathChecker checker : userCheckers) {
if (checker instanceof AlgorithmChecker) {
((AlgorithmChecker)checker).trySetTrustAnchor(anchor);
}
}
init = false; init = false;
} }
......
/* /*
* Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * 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
...@@ -302,6 +302,7 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -302,6 +302,7 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
// init the crl checker // init the crl checker
currentState.crlChecker = currentState.crlChecker =
new CrlRevocationChecker(null, buildParams, null, onlyEECert); new CrlRevocationChecker(null, buildParams, null, onlyEECert);
currentState.algorithmChecker = new AlgorithmChecker(anchor);
try { try {
depthFirstSearchReverse(null, currentState, depthFirstSearchReverse(null, currentState,
new ReverseBuilder(buildParams, targetSubjectDN), adjacencyList, new ReverseBuilder(buildParams, targetSubjectDN), adjacencyList,
...@@ -475,29 +476,41 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -475,29 +476,41 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
userCheckers.add(mustCheck, policyChecker); userCheckers.add(mustCheck, policyChecker);
mustCheck++; mustCheck++;
// add the algorithm checker
userCheckers.add(mustCheck,
new AlgorithmChecker(builder.trustAnchor));
mustCheck++;
if (nextState.keyParamsNeeded()) { if (nextState.keyParamsNeeded()) {
PublicKey rootKey = cert.getPublicKey(); PublicKey rootKey = cert.getPublicKey();
if (builder.trustAnchor.getTrustedCert() == null) { if (builder.trustAnchor.getTrustedCert() == null) {
rootKey = builder.trustAnchor.getCAPublicKey(); rootKey = builder.trustAnchor.getCAPublicKey();
if (debug != null) if (debug != null)
debug.println("SunCertPathBuilder.depthFirstSearchForward" + debug.println(
" using buildParams public key: " + "SunCertPathBuilder.depthFirstSearchForward " +
"using buildParams public key: " +
rootKey.toString()); rootKey.toString());
} }
TrustAnchor anchor = new TrustAnchor TrustAnchor anchor = new TrustAnchor
(cert.getSubjectX500Principal(), rootKey, null); (cert.getSubjectX500Principal(), rootKey, null);
// add the basic checker
basicChecker = new BasicChecker(anchor, basicChecker = new BasicChecker(anchor,
builder.date, builder.date,
buildParams.getSigProvider(), buildParams.getSigProvider(),
true); true);
userCheckers.add(mustCheck, basicChecker); userCheckers.add(mustCheck, basicChecker);
mustCheck++; mustCheck++;
// add the crl revocation checker
if (buildParams.isRevocationEnabled()) { if (buildParams.isRevocationEnabled()) {
userCheckers.add(mustCheck, new CrlRevocationChecker userCheckers.add(mustCheck, new CrlRevocationChecker
(anchor, buildParams, null, onlyEECert)); (anchor, buildParams, null, onlyEECert));
mustCheck++; mustCheck++;
} }
} }
// Why we don't need BasicChecker and CrlRevocationChecker
// if nextState.keyParamsNeeded() is false?
for (int i=0; i<appendedCerts.size(); i++) { for (int i=0; i<appendedCerts.size(); i++) {
X509Certificate currCert = appendedCerts.get(i); X509Certificate currCert = appendedCerts.get(i);
...@@ -513,10 +526,18 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -513,10 +526,18 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
for (int j=0; j<userCheckers.size(); j++) { for (int j=0; j<userCheckers.size(); j++) {
PKIXCertPathChecker currChecker = userCheckers.get(j); PKIXCertPathChecker currChecker = userCheckers.get(j);
if (j < mustCheck || if (j < mustCheck ||
!currChecker.isForwardCheckingSupported()) !currChecker.isForwardCheckingSupported()) {
{
if (i == 0) { if (i == 0) {
currChecker.init(false); currChecker.init(false);
// The user specified
// AlgorithmChecker may not be
// able to set the trust anchor until now.
if (j >= mustCheck &&
currChecker instanceof AlgorithmChecker) {
((AlgorithmChecker)currChecker).
trySetTrustAnchor(builder.trustAnchor);
}
} }
try { try {
......
/* /*
* 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");
......
...@@ -38,6 +38,7 @@ import javax.crypto.spec.SecretKeySpec; ...@@ -38,6 +38,7 @@ import javax.crypto.spec.SecretKeySpec;
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 static sun.security.ssl.CipherSuite.PRF.*;
import static sun.security.ssl.JsseJce.*; import static sun.security.ssl.JsseJce.*;
/** /**
...@@ -102,12 +103,15 @@ final class CipherSuite implements Comparable { ...@@ -102,12 +103,15 @@ final class CipherSuite implements Comparable {
// by default // by default
final int priority; final int priority;
// key exchange, bulk cipher, and mac algorithms. See those classes below. // key exchange, bulk cipher, mac and prf algorithms. See those
// classes below.
final KeyExchange keyExchange; final KeyExchange keyExchange;
final BulkCipher cipher; final BulkCipher cipher;
final MacAlg macAlg; final MacAlg macAlg;
final PRF prfAlg;
// whether a CipherSuite qualifies as exportable under 512/40 bit rules. // whether a CipherSuite qualifies as exportable under 512/40 bit rules.
// TLS 1.1+ (RFC 4346) must not negotiate to these suites.
final boolean exportable; final boolean exportable;
// true iff implemented and enabled at compile time // true iff implemented and enabled at compile time
...@@ -116,9 +120,15 @@ final class CipherSuite implements Comparable { ...@@ -116,9 +120,15 @@ final class CipherSuite implements Comparable {
// obsoleted since protocol version // obsoleted since protocol version
final int obsoleted; final int obsoleted;
// supported since protocol version
final int supported;
/**
* Constructor for implemented CipherSuites.
*/
private CipherSuite(String name, int id, int priority, private CipherSuite(String name, int id, int priority,
KeyExchange keyExchange, BulkCipher cipher, KeyExchange keyExchange, BulkCipher cipher,
boolean allowed, int obsoleted) { boolean allowed, int obsoleted, int supported, PRF prfAlg) {
this.name = name; this.name = name;
this.id = id; this.id = id;
this.priority = priority; this.priority = priority;
...@@ -129,6 +139,10 @@ final class CipherSuite implements Comparable { ...@@ -129,6 +139,10 @@ final class CipherSuite implements Comparable {
macAlg = M_MD5; macAlg = M_MD5;
} else if (name.endsWith("_SHA")) { } else if (name.endsWith("_SHA")) {
macAlg = M_SHA; macAlg = M_SHA;
} else if (name.endsWith("_SHA256")) {
macAlg = M_SHA256;
} else if (name.endsWith("_SHA384")) {
macAlg = M_SHA384;
} else if (name.endsWith("_NULL")) { } else if (name.endsWith("_NULL")) {
macAlg = M_NULL; macAlg = M_NULL;
} else if (name.endsWith("_SCSV")) { } else if (name.endsWith("_SCSV")) {
...@@ -142,8 +156,13 @@ final class CipherSuite implements Comparable { ...@@ -142,8 +156,13 @@ final class CipherSuite implements Comparable {
allowed &= cipher.allowed; allowed &= cipher.allowed;
this.allowed = allowed; this.allowed = allowed;
this.obsoleted = obsoleted; this.obsoleted = obsoleted;
this.supported = supported;
this.prfAlg = prfAlg;
} }
/**
* Constructor for unimplemented CipherSuites.
*/
private CipherSuite(String name, int id) { private CipherSuite(String name, int id) {
this.name = name; this.name = name;
this.id = id; this.id = id;
...@@ -155,6 +174,8 @@ final class CipherSuite implements Comparable { ...@@ -155,6 +174,8 @@ final class CipherSuite implements Comparable {
this.macAlg = null; this.macAlg = null;
this.exportable = false; this.exportable = false;
this.obsoleted = ProtocolVersion.LIMIT_MAX_VALUE; this.obsoleted = ProtocolVersion.LIMIT_MAX_VALUE;
this.supported = ProtocolVersion.LIMIT_MIN_VALUE;
this.prfAlg = P_NONE;
} }
/** /**
...@@ -236,12 +257,17 @@ final class CipherSuite implements Comparable { ...@@ -236,12 +257,17 @@ final class CipherSuite implements Comparable {
return nameMap.values(); return nameMap.values();
} }
/*
* Use this method when all of the values need to be specified.
* This is primarily used when defining a new ciphersuite for
* TLS 1.2+ that doesn't use the "default" PRF.
*/
private static void add(String name, int id, int priority, private static void add(String name, int id, int priority,
KeyExchange keyExchange, BulkCipher cipher, KeyExchange keyExchange, BulkCipher cipher,
boolean allowed, int obsoleted) { boolean allowed, int obsoleted, int supported, PRF prf) {
CipherSuite c = new CipherSuite(name, id, priority, keyExchange, CipherSuite c = new CipherSuite(name, id, priority, keyExchange,
cipher, allowed, obsoleted); cipher, allowed, obsoleted, supported, prf);
if (idMap.put(id, c) != null) { if (idMap.put(id, c) != null) {
throw new RuntimeException("Duplicate ciphersuite definition: " throw new RuntimeException("Duplicate ciphersuite definition: "
+ id + ", " + name); + id + ", " + name);
...@@ -254,12 +280,41 @@ final class CipherSuite implements Comparable { ...@@ -254,12 +280,41 @@ final class CipherSuite implements Comparable {
} }
} }
/*
* Use this method when there is no lower protocol limit where this
* suite can be used, and the PRF is P_SHA256. That is, the
* existing ciphersuites. From RFC 5246:
*
* All cipher suites in this document use P_SHA256.
*/
private static void add(String name, int id, int priority,
KeyExchange keyExchange, BulkCipher cipher,
boolean allowed, int obsoleted) {
// If this is an obsoleted suite, then don't let the TLS 1.2
// protocol have a valid PRF value.
PRF prf = P_SHA256;
if (obsoleted < ProtocolVersion.TLS12.v) {
prf = P_NONE;
}
add(name, id, priority, keyExchange, cipher, allowed, obsoleted,
ProtocolVersion.LIMIT_MIN_VALUE, prf);
}
/*
* Use this method when there is no upper protocol limit. That is,
* suites which have not been obsoleted.
*/
private static void add(String name, int id, int priority, private static void add(String name, int id, int priority,
KeyExchange keyExchange, BulkCipher cipher, boolean allowed) { KeyExchange keyExchange, BulkCipher cipher, boolean allowed) {
add(name, id, priority, keyExchange, add(name, id, priority, keyExchange,
cipher, allowed, ProtocolVersion.LIMIT_MAX_VALUE); cipher, allowed, ProtocolVersion.LIMIT_MAX_VALUE);
} }
/*
* Use this method to define an unimplemented suite. This provides
* a number<->name mapping that can be used for debugging.
*/
private static void add(String name, int id) { private static void add(String name, int id) {
CipherSuite c = new CipherSuite(name, id); CipherSuite c = new CipherSuite(name, id);
if (idMap.put(id, c) != null) { if (idMap.put(id, c) != null) {
...@@ -459,7 +514,7 @@ final class CipherSuite implements Comparable { ...@@ -459,7 +514,7 @@ final class CipherSuite implements Comparable {
/** /**
* An SSL/TLS key MAC algorithm. * An SSL/TLS key MAC algorithm.
* *
* Also contains a factory method to obtain in initialized MAC * Also contains a factory method to obtain an initialized MAC
* for this algorithm. * for this algorithm.
*/ */
final static class MacAlg { final static class MacAlg {
...@@ -519,6 +574,48 @@ final class CipherSuite implements Comparable { ...@@ -519,6 +574,48 @@ final class CipherSuite implements Comparable {
final static MacAlg M_NULL = new MacAlg("NULL", 0); final static MacAlg M_NULL = new MacAlg("NULL", 0);
final static MacAlg M_MD5 = new MacAlg("MD5", 16); final static MacAlg M_MD5 = new MacAlg("MD5", 16);
final static MacAlg M_SHA = new MacAlg("SHA", 20); final static MacAlg M_SHA = new MacAlg("SHA", 20);
final static MacAlg M_SHA256 = new MacAlg("SHA256", 32);
final static MacAlg M_SHA384 = new MacAlg("SHA384", 48);
// PRFs (PseudoRandom Function) from TLS specifications.
//
// TLS 1.1- uses a single MD5/SHA1-based PRF algorithm for generating
// the necessary material.
//
// In TLS 1.2+, all existing/known CipherSuites use SHA256, however
// new Ciphersuites (e.g. RFC 5288) can define specific PRF hash
// algorithms.
static enum PRF {
// PRF algorithms
P_NONE( "NONE", 0, 0),
P_SHA256("SHA-256", 32, 64),
P_SHA384("SHA-384", 48, 128),
P_SHA512("SHA-512", 64, 128); // not currently used.
// PRF characteristics
private final String prfHashAlg;
private final int prfHashLength;
private final int prfBlockSize;
PRF(String prfHashAlg, int prfHashLength, int prfBlockSize) {
this.prfHashAlg = prfHashAlg;
this.prfHashLength = prfHashLength;
this.prfBlockSize = prfBlockSize;
}
String getPRFHashAlg() {
return prfHashAlg;
}
int getPRFHashLength() {
return prfHashLength;
}
int getPRFBlockSize() {
return prfBlockSize;
}
}
static { static {
idMap = new HashMap<Integer,CipherSuite>(); idMap = new HashMap<Integer,CipherSuite>();
...@@ -769,6 +866,43 @@ final class CipherSuite implements Comparable { ...@@ -769,6 +866,43 @@ final class CipherSuite implements Comparable {
// They are listed in preference order, most preferred first. // They are listed in preference order, most preferred first.
int p = DEFAULT_SUITES_PRIORITY * 2; int p = DEFAULT_SUITES_PRIORITY * 2;
// shorten names to fit the following table cleanly.
int max = ProtocolVersion.LIMIT_MAX_VALUE;
int tls11 = ProtocolVersion.TLS11.v;
int tls12 = ProtocolVersion.TLS12.v;
// ID Key Exchange Cipher A obs suprt PRF
// ====== ============ ========= = === ===== ========
add("TLS_RSA_WITH_AES_128_CBC_SHA256",
0x003c, --p, K_RSA, B_AES_128, T, max, tls12, P_SHA256);
add("TLS_RSA_WITH_AES_256_CBC_SHA256",
0x003d, --p, K_RSA, B_AES_256, T, max, tls12, P_SHA256);
add("TLS_DHE_DSS_WITH_AES_128_CBC_SHA256",
0x0040, --p, K_DHE_DSS, B_AES_128, T, max, tls12, P_SHA256);
add("TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
0x0067, --p, K_DHE_RSA, B_AES_128, T, max, tls12, P_SHA256);
add("TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",
0x006a, --p, K_DHE_DSS, B_AES_256, T, max, tls12, P_SHA256);
add("TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
0x006b, --p, K_DHE_RSA, B_AES_256, T, max, tls12, P_SHA256);
add("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
0xc023, --p, K_ECDHE_ECDSA, B_AES_128, T, max, tls12, P_SHA256);
add("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
0xc024, --p, K_ECDHE_ECDSA, B_AES_256, T, max, tls12, P_SHA384);
add("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256",
0xc025, --p, K_ECDH_ECDSA, B_AES_128, T, max, tls12, P_SHA256);
add("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384",
0xc026, --p, K_ECDH_ECDSA, B_AES_256, T, max, tls12, P_SHA384);
add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
0xc027, --p, K_ECDHE_RSA, B_AES_128, T, max, tls12, P_SHA256);
add("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
0xc028, --p, K_ECDHE_RSA, B_AES_256, T, max, tls12, P_SHA384);
add("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256",
0xc029, --p, K_ECDH_RSA, B_AES_128, T, max, tls12, P_SHA256);
add("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384",
0xc02a, --p, K_ECDH_RSA, B_AES_256, T, max, tls12, P_SHA384);
add("SSL_RSA_WITH_RC4_128_MD5", add("SSL_RSA_WITH_RC4_128_MD5",
0x0004, --p, K_RSA, B_RC4_128, N); 0x0004, --p, K_RSA, B_RC4_128, N);
add("SSL_RSA_WITH_RC4_128_SHA", add("SSL_RSA_WITH_RC4_128_SHA",
...@@ -792,11 +926,11 @@ final class CipherSuite implements Comparable { ...@@ -792,11 +926,11 @@ final class CipherSuite implements Comparable {
0xC00F, --p, K_ECDH_RSA, B_AES_256, T); 0xC00F, --p, K_ECDH_RSA, B_AES_256, T);
add("TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", add("TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
0xC007, --p, K_ECDHE_ECDSA,B_RC4_128, N); 0xC007, --p, K_ECDHE_ECDSA, B_RC4_128, N);
add("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", add("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
0xC009, --p, K_ECDHE_ECDSA,B_AES_128, T); 0xC009, --p, K_ECDHE_ECDSA, B_AES_128, T);
add("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", add("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
0xC00A, --p, K_ECDHE_ECDSA,B_AES_256, T); 0xC00A, --p, K_ECDHE_ECDSA, B_AES_256, T);
add("TLS_ECDHE_RSA_WITH_RC4_128_SHA", add("TLS_ECDHE_RSA_WITH_RC4_128_SHA",
0xC011, --p, K_ECDHE_RSA, B_RC4_128, N); 0xC011, --p, K_ECDHE_RSA, B_RC4_128, N);
add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
...@@ -820,31 +954,13 @@ final class CipherSuite implements Comparable { ...@@ -820,31 +954,13 @@ final class CipherSuite implements Comparable {
add("TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA", add("TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA",
0xC00D, --p, K_ECDH_RSA, B_3DES, T); 0xC00D, --p, K_ECDH_RSA, B_3DES, T);
add("TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", add("TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
0xC008, --p, K_ECDHE_ECDSA,B_3DES, T); 0xC008, --p, K_ECDHE_ECDSA, B_3DES, T);
add("TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", add("TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
0xC012, --p, K_ECDHE_RSA, B_3DES, T); 0xC012, --p, K_ECDHE_RSA, B_3DES, T);
add("SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA", add("SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
0x0016, --p, K_DHE_RSA, B_3DES, T); 0x0016, --p, K_DHE_RSA, B_3DES, T);
add("SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA", add("SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
0x0013, --p, K_DHE_DSS, B_3DES, N); 0x0013, --p, K_DHE_DSS, B_3DES, N);
add("SSL_RSA_WITH_DES_CBC_SHA",
0x0009, --p, K_RSA, B_DES, N);
add("SSL_DHE_RSA_WITH_DES_CBC_SHA",
0x0015, --p, K_DHE_RSA, B_DES, N);
add("SSL_DHE_DSS_WITH_DES_CBC_SHA",
0x0012, --p, K_DHE_DSS, B_DES, N);
add("SSL_RSA_EXPORT_WITH_RC4_40_MD5",
0x0003, --p, K_RSA_EXPORT, B_RC4_40, N,
ProtocolVersion.TLS11.v);
add("SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
0x0008, --p, K_RSA_EXPORT, B_DES_40, N,
ProtocolVersion.TLS11.v);
add("SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
0x0014, --p, K_DHE_RSA, B_DES_40, N,
ProtocolVersion.TLS11.v);
add("SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
0x0011, --p, K_DHE_DSS, B_DES_40, N,
ProtocolVersion.TLS11.v);
// Renegotiation protection request Signalling Cipher Suite Value (SCSV) // Renegotiation protection request Signalling Cipher Suite Value (SCSV)
add("TLS_EMPTY_RENEGOTIATION_INFO_SCSV", add("TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
...@@ -855,17 +971,28 @@ final class CipherSuite implements Comparable { ...@@ -855,17 +971,28 @@ final class CipherSuite implements Comparable {
// They are listed in preference order, preferred first. // They are listed in preference order, preferred first.
p = DEFAULT_SUITES_PRIORITY; p = DEFAULT_SUITES_PRIORITY;
// weak single-DES cipher suites
add("SSL_RSA_WITH_DES_CBC_SHA",
0x0009, --p, K_RSA, B_DES, N, tls12);
add("SSL_DHE_RSA_WITH_DES_CBC_SHA",
0x0015, --p, K_DHE_RSA, B_DES, N, tls12);
add("SSL_DHE_DSS_WITH_DES_CBC_SHA",
0x0012, --p, K_DHE_DSS, B_DES, N, tls12);
// Anonymous key exchange and the NULL ciphers // Anonymous key exchange and the NULL ciphers
add("SSL_RSA_WITH_NULL_MD5", add("SSL_RSA_WITH_NULL_MD5",
0x0001, --p, K_RSA, B_NULL, N); 0x0001, --p, K_RSA, B_NULL, N);
add("SSL_RSA_WITH_NULL_SHA", add("SSL_RSA_WITH_NULL_SHA",
0x0002, --p, K_RSA, B_NULL, N); 0x0002, --p, K_RSA, B_NULL, N);
add("TLS_RSA_WITH_NULL_SHA256",
0x003b, --p, K_RSA, B_NULL, N, max, tls12, P_SHA256);
add("TLS_ECDH_ECDSA_WITH_NULL_SHA", add("TLS_ECDH_ECDSA_WITH_NULL_SHA",
0xC001, --p, K_ECDH_ECDSA, B_NULL, N); 0xC001, --p, K_ECDH_ECDSA, B_NULL, N);
add("TLS_ECDH_RSA_WITH_NULL_SHA", add("TLS_ECDH_RSA_WITH_NULL_SHA",
0xC00B, --p, K_ECDH_RSA, B_NULL, N); 0xC00B, --p, K_ECDH_RSA, B_NULL, N);
add("TLS_ECDHE_ECDSA_WITH_NULL_SHA", add("TLS_ECDHE_ECDSA_WITH_NULL_SHA",
0xC006, --p, K_ECDHE_ECDSA,B_NULL, N); 0xC006, --p, K_ECDHE_ECDSA, B_NULL, N);
add("TLS_ECDHE_RSA_WITH_NULL_SHA", add("TLS_ECDHE_RSA_WITH_NULL_SHA",
0xC010, --p, K_ECDHE_RSA, B_NULL, N); 0xC010, --p, K_ECDHE_RSA, B_NULL, N);
...@@ -878,7 +1005,12 @@ final class CipherSuite implements Comparable { ...@@ -878,7 +1005,12 @@ final class CipherSuite implements Comparable {
add("SSL_DH_anon_WITH_3DES_EDE_CBC_SHA", add("SSL_DH_anon_WITH_3DES_EDE_CBC_SHA",
0x001b, --p, K_DH_ANON, B_3DES, N); 0x001b, --p, K_DH_ANON, B_3DES, N);
add("SSL_DH_anon_WITH_DES_CBC_SHA", add("SSL_DH_anon_WITH_DES_CBC_SHA",
0x001a, --p, K_DH_ANON, B_DES, N); 0x001a, --p, K_DH_ANON, B_DES, N, tls12);
add("TLS_DH_anon_WITH_AES_128_CBC_SHA256",
0x006c, --p, K_DH_ANON, B_AES_128, N, max, tls12, P_SHA256);
add("TLS_DH_anon_WITH_AES_256_CBC_SHA256",
0x006d, --p, K_DH_ANON, B_AES_256, N, max, tls12, P_SHA256);
add("TLS_ECDH_anon_WITH_RC4_128_SHA", add("TLS_ECDH_anon_WITH_RC4_128_SHA",
0xC016, --p, K_ECDH_ANON, B_RC4_128, N); 0xC016, --p, K_ECDH_ANON, B_RC4_128, N);
...@@ -890,15 +1022,22 @@ final class CipherSuite implements Comparable { ...@@ -890,15 +1022,22 @@ final class CipherSuite implements Comparable {
0xC017, --p, K_ECDH_ANON, B_3DES, T); 0xC017, --p, K_ECDH_ANON, B_3DES, T);
add("SSL_DH_anon_EXPORT_WITH_RC4_40_MD5", add("SSL_DH_anon_EXPORT_WITH_RC4_40_MD5",
0x0017, --p, K_DH_ANON, B_RC4_40, N, 0x0017, --p, K_DH_ANON, B_RC4_40, N, tls11);
ProtocolVersion.TLS11.v);
add("SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA", add("SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
0x0019, --p, K_DH_ANON, B_DES_40, N, 0x0019, --p, K_DH_ANON, B_DES_40, N, tls11);
ProtocolVersion.TLS11.v);
add("TLS_ECDH_anon_WITH_NULL_SHA", add("TLS_ECDH_anon_WITH_NULL_SHA",
0xC015, --p, K_ECDH_ANON, B_NULL, N); 0xC015, --p, K_ECDH_ANON, B_NULL, N);
add("SSL_RSA_EXPORT_WITH_RC4_40_MD5",
0x0003, --p, K_RSA_EXPORT, B_RC4_40, N, tls11);
add("SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
0x0008, --p, K_RSA_EXPORT, B_DES_40, N, tls11);
add("SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
0x0014, --p, K_DHE_RSA, B_DES_40, N, tls11);
add("SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
0x0011, --p, K_DHE_DSS, B_DES_40, N, tls11);
// Supported Kerberos ciphersuites from RFC2712 // Supported Kerberos ciphersuites from RFC2712
add("TLS_KRB5_WITH_RC4_128_SHA", add("TLS_KRB5_WITH_RC4_128_SHA",
0x0020, --p, K_KRB5, B_RC4_128, N); 0x0020, --p, K_KRB5, B_RC4_128, N);
...@@ -909,21 +1048,17 @@ final class CipherSuite implements Comparable { ...@@ -909,21 +1048,17 @@ final class CipherSuite implements Comparable {
add("TLS_KRB5_WITH_3DES_EDE_CBC_MD5", add("TLS_KRB5_WITH_3DES_EDE_CBC_MD5",
0x0023, --p, K_KRB5, B_3DES, N); 0x0023, --p, K_KRB5, B_3DES, N);
add("TLS_KRB5_WITH_DES_CBC_SHA", add("TLS_KRB5_WITH_DES_CBC_SHA",
0x001e, --p, K_KRB5, B_DES, N); 0x001e, --p, K_KRB5, B_DES, N, tls12);
add("TLS_KRB5_WITH_DES_CBC_MD5", add("TLS_KRB5_WITH_DES_CBC_MD5",
0x0022, --p, K_KRB5, B_DES, N); 0x0022, --p, K_KRB5, B_DES, N, tls12);
add("TLS_KRB5_EXPORT_WITH_RC4_40_SHA", add("TLS_KRB5_EXPORT_WITH_RC4_40_SHA",
0x0028, --p, K_KRB5_EXPORT, B_RC4_40, N, 0x0028, --p, K_KRB5_EXPORT, B_RC4_40, N, tls11);
ProtocolVersion.TLS11.v);
add("TLS_KRB5_EXPORT_WITH_RC4_40_MD5", add("TLS_KRB5_EXPORT_WITH_RC4_40_MD5",
0x002b, --p, K_KRB5_EXPORT, B_RC4_40, N, 0x002b, --p, K_KRB5_EXPORT, B_RC4_40, N, tls11);
ProtocolVersion.TLS11.v);
add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA", add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA",
0x0026, --p, K_KRB5_EXPORT, B_DES_40, N, 0x0026, --p, K_KRB5_EXPORT, B_DES_40, N, tls11);
ProtocolVersion.TLS11.v);
add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5", add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5",
0x0029, --p, K_KRB5_EXPORT, B_DES_40, N, 0x0029, --p, K_KRB5_EXPORT, B_DES_40, N, tls11);
ProtocolVersion.TLS11.v);
/* /*
* Other values from the TLS Cipher Suite Registry, as of August 2010. * Other values from the TLS Cipher Suite Registry, as of August 2010.
...@@ -1006,19 +1141,10 @@ final class CipherSuite implements Comparable { ...@@ -1006,19 +1141,10 @@ final class CipherSuite implements Comparable {
add("TLS_DH_RSA_WITH_AES_128_CBC_SHA", 0x0031); add("TLS_DH_RSA_WITH_AES_128_CBC_SHA", 0x0031);
add("TLS_DH_DSS_WITH_AES_256_CBC_SHA", 0x0036); add("TLS_DH_DSS_WITH_AES_256_CBC_SHA", 0x0036);
add("TLS_DH_RSA_WITH_AES_256_CBC_SHA", 0x0037); add("TLS_DH_RSA_WITH_AES_256_CBC_SHA", 0x0037);
add("TLS_RSA_WITH_NULL_SHA256", 0x003b);
add("TLS_RSA_WITH_AES_128_CBC_SHA256", 0x003c);
add("TLS_RSA_WITH_AES_256_CBC_SHA256", 0x003d);
add("TLS_DH_DSS_WITH_AES_128_CBC_SHA256", 0x003e); add("TLS_DH_DSS_WITH_AES_128_CBC_SHA256", 0x003e);
add("TLS_DH_RSA_WITH_AES_128_CBC_SHA256", 0x003f); add("TLS_DH_RSA_WITH_AES_128_CBC_SHA256", 0x003f);
add("TLS_DHE_DSS_WITH_AES_128_CBC_SHA256", 0x0040);
add("TLS_DHE_RSA_WITH_AES_128_CBC_SHA256", 0x0067);
add("TLS_DH_DSS_WITH_AES_256_CBC_SHA256", 0x0068); add("TLS_DH_DSS_WITH_AES_256_CBC_SHA256", 0x0068);
add("TLS_DH_RSA_WITH_AES_256_CBC_SHA256", 0x0069); add("TLS_DH_RSA_WITH_AES_256_CBC_SHA256", 0x0069);
add("TLS_DHE_DSS_WITH_AES_256_CBC_SHA256", 0x006a);
add("TLS_DHE_RSA_WITH_AES_256_CBC_SHA256", 0x006b);
add("TLS_DH_anon_WITH_AES_128_CBC_SHA256", 0x006c);
add("TLS_DH_anon_WITH_AES_256_CBC_SHA256", 0x006d);
// Unsupported cipher suites from RFC 5288 // Unsupported cipher suites from RFC 5288
add("TLS_RSA_WITH_AES_128_GCM_SHA256", 0x009c); add("TLS_RSA_WITH_AES_128_GCM_SHA256", 0x009c);
...@@ -1092,14 +1218,6 @@ final class CipherSuite implements Comparable { ...@@ -1092,14 +1218,6 @@ final class CipherSuite implements Comparable {
add("TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA", 0xc022); add("TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA", 0xc022);
// Unsupported cipher suites from RFC 5289 // Unsupported cipher suites from RFC 5289
add("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", 0xc023);
add("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", 0xc024);
add("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256", 0xc025);
add("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384", 0xc026);
add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", 0xc027);
add("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", 0xc028);
add("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256", 0xc029);
add("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384", 0xc02a);
add("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 0xc02b); add("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 0xc02b);
add("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 0xc02c); add("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 0xc02c);
add("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", 0xc02d); add("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", 0xc02d);
......
...@@ -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) {
if (conn != null) {
((X509ExtendedTrustManager)tm).checkServerTrusted( ((X509ExtendedTrustManager)tm).checkServerTrusted(
(peerCerts != null ? peerCerts.clone(),
peerCerts.clone() :
null),
keyExchangeString, keyExchangeString,
getHostSE(), conn);
identificator);
} else { } else {
if (identificator != null) { ((X509ExtendedTrustManager)tm).checkServerTrusted(
throw new RuntimeException( peerCerts.clone(),
"trust manager does not support peer identification"); keyExchangeString,
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) {
switch (version) {
case 1:
md5.update(b, offset, len); md5.update(b, offset, len);
sha.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,"));
}
}
} }
/** /**
......
...@@ -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();
......
/* /*
* 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
......
此差异已折叠。
此差异已折叠。
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
*/ */
import java.io.*; import java.io.*;
import java.util.*;
class Utils { class Utils {
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册