mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-18 06:15:16 +00:00
8023069: Enhance TLS connections
Also reviewed by Alexander Fomin and Andrew Gross Reviewed-by: wetmore
This commit is contained in:
parent
aed9248e0b
commit
0961a179cf
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2013, 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
|
||||
@ -72,13 +72,17 @@ public final class TlsRsaPremasterSecretGenerator extends KeyGeneratorSpi {
|
||||
throw new IllegalStateException(
|
||||
"TlsRsaPremasterSecretGenerator must be initialized");
|
||||
}
|
||||
if (random == null) {
|
||||
random = new SecureRandom();
|
||||
byte[] b = spec.getEncodedSecret();
|
||||
if (b == null) {
|
||||
if (random == null) {
|
||||
random = new SecureRandom();
|
||||
}
|
||||
b = new byte[48];
|
||||
random.nextBytes(b);
|
||||
b[0] = (byte)spec.getMajorVersion();
|
||||
b[1] = (byte)spec.getMinorVersion();
|
||||
}
|
||||
byte[] b = new byte[48];
|
||||
random.nextBytes(b);
|
||||
b[0] = (byte)spec.getMajorVersion();
|
||||
b[1] = (byte)spec.getMinorVersion();
|
||||
|
||||
return new SecretKeySpec(b, "TlsRsaPremasterSecret");
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -45,11 +45,12 @@ public class TlsRsaPremasterSecretParameterSpec
|
||||
|
||||
private final int majorVersion;
|
||||
private final int minorVersion;
|
||||
private final byte[] encodedSecret;
|
||||
|
||||
/**
|
||||
* Constructs a new TlsRsaPremasterSecretParameterSpec.
|
||||
*
|
||||
* <p>The version numbers will be placed inside the premaster secret to
|
||||
* <P>
|
||||
* The version numbers will be placed inside the premaster secret to
|
||||
* detect version rollbacks attacks as described in the TLS specification.
|
||||
* Note that they do not indicate the protocol version negotiated for
|
||||
* the handshake.
|
||||
@ -65,7 +66,42 @@ public class TlsRsaPremasterSecretParameterSpec
|
||||
this.majorVersion =
|
||||
TlsMasterSecretParameterSpec.checkVersion(majorVersion);
|
||||
this.minorVersion =
|
||||
TlsMasterSecretParameterSpec.checkVersion(minorVersion); }
|
||||
TlsMasterSecretParameterSpec.checkVersion(minorVersion);
|
||||
this.encodedSecret = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new TlsRsaPremasterSecretParameterSpec.
|
||||
* <P>
|
||||
* The version numbers will be placed inside the premaster secret to
|
||||
* detect version rollbacks attacks as described in the TLS specification.
|
||||
* Note that they do not indicate the protocol version negotiated for
|
||||
* the handshake.
|
||||
* <P>
|
||||
* Usually, the encoded secret key is a random number that acts as
|
||||
* dummy pre_master_secret to avoid vulnerabilities described by
|
||||
* section 7.4.7.1, RFC 5246.
|
||||
*
|
||||
* @param majorVersion the major number of the protocol version
|
||||
* @param minorVersion the minor number of the protocol version
|
||||
* @param encodedSecret the encoded secret key
|
||||
*
|
||||
* @throws IllegalArgumentException if minorVersion or majorVersion are
|
||||
* negative or larger than 255, or encodedSecret is not exactly 48 bytes.
|
||||
*/
|
||||
public TlsRsaPremasterSecretParameterSpec(int majorVersion,
|
||||
int minorVersion, byte[] encodedSecret) {
|
||||
this.majorVersion =
|
||||
TlsMasterSecretParameterSpec.checkVersion(majorVersion);
|
||||
this.minorVersion =
|
||||
TlsMasterSecretParameterSpec.checkVersion(minorVersion);
|
||||
|
||||
if (encodedSecret == null || encodedSecret.length != 48) {
|
||||
throw new IllegalArgumentException(
|
||||
"Encoded secret is not exactly 48 bytes");
|
||||
}
|
||||
this.encodedSecret = encodedSecret.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the major version.
|
||||
@ -84,4 +120,13 @@ public class TlsRsaPremasterSecretParameterSpec
|
||||
public int getMinorVersion() {
|
||||
return minorVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the encoded secret.
|
||||
*
|
||||
* @return the encoded secret, may be null if no encoded secret.
|
||||
*/
|
||||
public byte[] getEncodedSecret() {
|
||||
return encodedSecret == null ? null : encodedSecret.clone();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2013, 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
|
||||
@ -451,30 +451,7 @@ final class P11RSACipher extends CipherSpi {
|
||||
// see JCE spec
|
||||
protected Key engineUnwrap(byte[] wrappedKey, String algorithm,
|
||||
int type) throws InvalidKeyException, NoSuchAlgorithmException {
|
||||
if (algorithm.equals("TlsRsaPremasterSecret")) {
|
||||
// the instance variable "session" has been initialized for
|
||||
// decrypt mode, so use a local variable instead.
|
||||
Session s = null;
|
||||
try {
|
||||
s = token.getObjSession();
|
||||
long keyType = CKK_GENERIC_SECRET;
|
||||
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
||||
new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
|
||||
new CK_ATTRIBUTE(CKA_KEY_TYPE, keyType),
|
||||
};
|
||||
attributes = token.getAttributes
|
||||
(O_IMPORT, CKO_SECRET_KEY, keyType, attributes);
|
||||
long keyID = token.p11.C_UnwrapKey(s.id(),
|
||||
new CK_MECHANISM(mechanism), p11Key.keyID, wrappedKey,
|
||||
attributes);
|
||||
return P11Key.secretKey(s, keyID, algorithm, 48 << 3,
|
||||
attributes);
|
||||
} catch (PKCS11Exception e) {
|
||||
throw new InvalidKeyException("unwrap() failed", e);
|
||||
} finally {
|
||||
token.releaseSession(s);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX implement unwrap using C_Unwrap() for all keys
|
||||
implInit(Cipher.DECRYPT_MODE, p11Key);
|
||||
if (wrappedKey.length > maxInputSize) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2013, 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
|
||||
@ -88,23 +88,33 @@ final class P11TlsRsaPremasterSecretGenerator extends KeyGeneratorSpi {
|
||||
throw new IllegalStateException
|
||||
("TlsRsaPremasterSecretGenerator must be initialized");
|
||||
}
|
||||
CK_VERSION version =
|
||||
new CK_VERSION(spec.getMajorVersion(), spec.getMinorVersion());
|
||||
Session session = null;
|
||||
try {
|
||||
session = token.getObjSession();
|
||||
CK_ATTRIBUTE[] attributes = token.getAttributes
|
||||
(O_GENERATE, CKO_SECRET_KEY, CKK_GENERIC_SECRET, new CK_ATTRIBUTE[0]);
|
||||
long keyID = token.p11.C_GenerateKey
|
||||
(session.id(), new CK_MECHANISM(mechanism, version), attributes);
|
||||
SecretKey key = P11Key.secretKey
|
||||
(session, keyID, "TlsRsaPremasterSecret", 48 << 3, attributes);
|
||||
return key;
|
||||
} catch (PKCS11Exception e) {
|
||||
throw new ProviderException("Could not generate premaster secret", e);
|
||||
} finally {
|
||||
token.releaseSession(session);
|
||||
|
||||
byte[] b = spec.getEncodedSecret();
|
||||
if (b == null) {
|
||||
CK_VERSION version = new CK_VERSION(
|
||||
spec.getMajorVersion(), spec.getMinorVersion());
|
||||
Session session = null;
|
||||
try {
|
||||
session = token.getObjSession();
|
||||
CK_ATTRIBUTE[] attributes = token.getAttributes(
|
||||
O_GENERATE, CKO_SECRET_KEY,
|
||||
CKK_GENERIC_SECRET, new CK_ATTRIBUTE[0]);
|
||||
long keyID = token.p11.C_GenerateKey(session.id(),
|
||||
new CK_MECHANISM(mechanism, version), attributes);
|
||||
SecretKey key = P11Key.secretKey(session,
|
||||
keyID, "TlsRsaPremasterSecret", 48 << 3, attributes);
|
||||
return key;
|
||||
} catch (PKCS11Exception e) {
|
||||
throw new ProviderException(
|
||||
"Could not generate premaster secret", e);
|
||||
} finally {
|
||||
token.releaseSession(session);
|
||||
}
|
||||
}
|
||||
|
||||
// Won't worry, the TlsRsaPremasterSecret will be soon converted to
|
||||
// TlsMasterSecret.
|
||||
return new SecretKeySpec(b, "TlsRsaPremasterSecret");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2013 Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2013, 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
|
||||
@ -318,33 +318,53 @@ public final class RSAPadding {
|
||||
|
||||
/**
|
||||
* PKCS#1 v1.5 unpadding (blocktype 1 and 2).
|
||||
*
|
||||
* Note that we want to make it a constant-time operation
|
||||
*/
|
||||
private byte[] unpadV15(byte[] padded) throws BadPaddingException {
|
||||
int k = 0;
|
||||
BadPaddingException bpe = null;
|
||||
|
||||
if (padded[k++] != 0) {
|
||||
throw new BadPaddingException("Data must start with zero");
|
||||
bpe = new BadPaddingException("Data must start with zero");
|
||||
}
|
||||
if (padded[k++] != type) {
|
||||
throw new BadPaddingException("Blocktype mismatch: " + padded[1]);
|
||||
if (padded[k++] != type && bpe == null) {
|
||||
bpe = new BadPaddingException("Blocktype mismatch: " + padded[1]);
|
||||
}
|
||||
while (true) {
|
||||
int p = 0;
|
||||
while (k < padded.length) {
|
||||
int b = padded[k++] & 0xff;
|
||||
if (b == 0) {
|
||||
break;
|
||||
if (b == 0 && p == 0) {
|
||||
p = k;
|
||||
}
|
||||
if (k == padded.length) {
|
||||
throw new BadPaddingException("Padding string not terminated");
|
||||
if (k == padded.length && p == 0 && bpe == null) {
|
||||
bpe = new BadPaddingException("Padding string not terminated");
|
||||
}
|
||||
if ((type == PAD_BLOCKTYPE_1) && (b != 0xff)) {
|
||||
throw new BadPaddingException("Padding byte not 0xff: " + b);
|
||||
if ((type == PAD_BLOCKTYPE_1) && (b != 0xff) &&
|
||||
p == 0 && bpe == null) {
|
||||
bpe = new BadPaddingException("Padding byte not 0xff: " + b);
|
||||
}
|
||||
}
|
||||
int n = padded.length - k;
|
||||
if (n > maxDataSize) {
|
||||
throw new BadPaddingException("Padding string too short");
|
||||
int n = padded.length - p;
|
||||
if (n > maxDataSize && bpe == null) {
|
||||
bpe = new BadPaddingException("Padding string too short");
|
||||
}
|
||||
|
||||
// copy useless padding array for a constant-time method
|
||||
//
|
||||
// Is it necessary?
|
||||
byte[] padding = new byte[p];
|
||||
System.arraycopy(padded, 0, padding, 0, p);
|
||||
|
||||
byte[] data = new byte[n];
|
||||
System.arraycopy(padded, padded.length - n, data, 0, n);
|
||||
System.arraycopy(padded, p, data, 0, n);
|
||||
|
||||
if (bpe == null) {
|
||||
bpe = new BadPaddingException("Unused exception");
|
||||
} else {
|
||||
throw bpe;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
@ -1085,94 +1085,23 @@ abstract class Handshaker {
|
||||
clnt_random.random_bytes, svr_random.random_bytes,
|
||||
prfHashAlg, prfHashLength, prfBlockSize);
|
||||
|
||||
SecretKey masterSecret;
|
||||
try {
|
||||
KeyGenerator kg = JsseJce.getKeyGenerator(masterAlg);
|
||||
kg.init(spec);
|
||||
masterSecret = kg.generateKey();
|
||||
} catch (GeneralSecurityException e) {
|
||||
return kg.generateKey();
|
||||
} catch (InvalidAlgorithmParameterException |
|
||||
NoSuchAlgorithmException iae) {
|
||||
// unlikely to happen, otherwise, must be a provider exception
|
||||
//
|
||||
// For RSA premaster secrets, do not signal a protocol error
|
||||
// due to the Bleichenbacher attack. See comments further down.
|
||||
if (!preMasterSecret.getAlgorithm().equals(
|
||||
"TlsRsaPremasterSecret")) {
|
||||
throw new ProviderException(e);
|
||||
}
|
||||
|
||||
if (debug != null && Debug.isOn("handshake")) {
|
||||
System.out.println("RSA master secret generation error:");
|
||||
e.printStackTrace(System.out);
|
||||
iae.printStackTrace(System.out);
|
||||
}
|
||||
throw new ProviderException(iae);
|
||||
|
||||
if (requestedVersion != null) {
|
||||
preMasterSecret =
|
||||
RSAClientKeyExchange.generateDummySecret(requestedVersion);
|
||||
} else {
|
||||
preMasterSecret =
|
||||
RSAClientKeyExchange.generateDummySecret(protocolVersion);
|
||||
}
|
||||
|
||||
// recursive call with new premaster secret
|
||||
return calculateMasterSecret(preMasterSecret, null);
|
||||
}
|
||||
|
||||
// if no version check requested (client side handshake), or version
|
||||
// information is not available (not an RSA premaster secret),
|
||||
// return master secret immediately.
|
||||
if ((requestedVersion == null) ||
|
||||
!(masterSecret instanceof TlsMasterSecret)) {
|
||||
return masterSecret;
|
||||
}
|
||||
|
||||
// we have checked the ClientKeyExchange message when reading TLS
|
||||
// record, the following check is necessary to ensure that
|
||||
// JCE provider does not ignore the checking, or the previous
|
||||
// checking process bypassed the premaster secret version checking.
|
||||
TlsMasterSecret tlsKey = (TlsMasterSecret)masterSecret;
|
||||
int major = tlsKey.getMajorVersion();
|
||||
int minor = tlsKey.getMinorVersion();
|
||||
if ((major < 0) || (minor < 0)) {
|
||||
return masterSecret;
|
||||
}
|
||||
|
||||
// check if the premaster secret version is ok
|
||||
// the specification says that it must be the maximum version supported
|
||||
// by the client from its ClientHello message. However, many
|
||||
// implementations send the negotiated version, so accept both
|
||||
// for SSL v3.0 and TLS v1.0.
|
||||
// NOTE that we may be comparing two unsupported version numbers, which
|
||||
// is why we cannot use object reference equality in this special case.
|
||||
ProtocolVersion premasterVersion =
|
||||
ProtocolVersion.valueOf(major, minor);
|
||||
boolean versionMismatch = (premasterVersion.v != requestedVersion.v);
|
||||
|
||||
/*
|
||||
* we never checked the client_version in server side
|
||||
* for TLS v1.0 and SSL v3.0. For compatibility, we
|
||||
* maintain this behavior.
|
||||
*/
|
||||
if (versionMismatch && requestedVersion.v <= ProtocolVersion.TLS10.v) {
|
||||
versionMismatch = (premasterVersion.v != protocolVersion.v);
|
||||
}
|
||||
|
||||
if (versionMismatch == false) {
|
||||
// check passed, return key
|
||||
return masterSecret;
|
||||
}
|
||||
|
||||
// Due to the Bleichenbacher attack, do not signal a protocol error.
|
||||
// Generate a random premaster secret and continue with the handshake,
|
||||
// which will fail when verifying the finished messages.
|
||||
// For more information, see comments in PreMasterSecret.
|
||||
if (debug != null && Debug.isOn("handshake")) {
|
||||
System.out.println("RSA PreMasterSecret version error: expected"
|
||||
+ protocolVersion + " or " + requestedVersion + ", decrypted: "
|
||||
+ premasterVersion);
|
||||
}
|
||||
preMasterSecret =
|
||||
RSAClientKeyExchange.generateDummySecret(requestedVersion);
|
||||
|
||||
// recursive call with new premaster secret
|
||||
return calculateMasterSecret(preMasterSecret, null);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2013, 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
|
||||
@ -133,26 +133,37 @@ final class RSAClientKeyExchange extends HandshakeMessage {
|
||||
} else {
|
||||
encrypted = new byte [messageSize];
|
||||
if (input.read(encrypted) != messageSize) {
|
||||
throw new SSLProtocolException
|
||||
("SSL: read PreMasterSecret: short read");
|
||||
throw new SSLProtocolException(
|
||||
"SSL: read PreMasterSecret: short read");
|
||||
}
|
||||
}
|
||||
|
||||
Exception failover = null;
|
||||
byte[] encoded = null;
|
||||
try {
|
||||
Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1);
|
||||
cipher.init(Cipher.UNWRAP_MODE, privateKey);
|
||||
preMaster = (SecretKey)cipher.unwrap(encrypted,
|
||||
"TlsRsaPremasterSecret", Cipher.SECRET_KEY);
|
||||
|
||||
// polish the premaster secret
|
||||
preMaster = polishPreMasterSecretKey(currentVersion, maxVersion,
|
||||
generator, preMaster, null);
|
||||
// Cannot generate key here, please don't use Cipher.UNWRAP_MODE!
|
||||
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
||||
encoded = cipher.doFinal(encrypted);
|
||||
} catch (BadPaddingException bpe) {
|
||||
failover = bpe;
|
||||
encoded = null;
|
||||
} catch (IllegalBlockSizeException ibse) {
|
||||
// the message it too big to process with RSA
|
||||
throw new SSLProtocolException(
|
||||
"Unable to process PreMasterSecret, may be too big");
|
||||
} catch (Exception e) {
|
||||
// polish the premaster secret
|
||||
preMaster =
|
||||
polishPreMasterSecretKey(currentVersion, maxVersion,
|
||||
generator, null, e);
|
||||
// unlikely to happen, otherwise, must be a provider exception
|
||||
if (debug != null && Debug.isOn("handshake")) {
|
||||
System.out.println("RSA premaster secret decryption error:");
|
||||
e.printStackTrace(System.out);
|
||||
}
|
||||
throw new RuntimeException("Could not generate dummy secret", e);
|
||||
}
|
||||
|
||||
// polish the premaster secret
|
||||
preMaster = polishPreMasterSecretKey(
|
||||
currentVersion, maxVersion, generator, encoded, failover);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -163,85 +174,74 @@ final class RSAClientKeyExchange extends HandshakeMessage {
|
||||
*
|
||||
* RFC 5246 describes the approach as :
|
||||
*
|
||||
* 1. Generate a string R of 46 random bytes
|
||||
* 1. Generate a string R of 48 random bytes
|
||||
*
|
||||
* 2. Decrypt the message to recover the plaintext M
|
||||
*
|
||||
* 3. If the PKCS#1 padding is not correct, or the length of message
|
||||
* M is not exactly 48 bytes:
|
||||
* pre_master_secret = ClientHello.client_version || R
|
||||
* pre_master_secret = R
|
||||
* else If ClientHello.client_version <= TLS 1.0, and version
|
||||
* number check is explicitly disabled:
|
||||
* pre_master_secret = M
|
||||
* premaster secret = M
|
||||
* else If M[0..1] != ClientHello.client_version:
|
||||
* premaster secret = R
|
||||
* else:
|
||||
* pre_master_secret = ClientHello.client_version || M[2..47]
|
||||
* premaster secret = M
|
||||
*
|
||||
* Note that #2 has completed before the call of this method.
|
||||
*/
|
||||
private SecretKey polishPreMasterSecretKey(ProtocolVersion currentVersion,
|
||||
ProtocolVersion clientHelloVersion, SecureRandom generator,
|
||||
SecretKey secretKey, Exception failoverException) {
|
||||
byte[] encoded, Exception failoverException) {
|
||||
|
||||
this.protocolVersion = clientHelloVersion;
|
||||
if (generator == null) {
|
||||
generator = new SecureRandom();
|
||||
}
|
||||
byte[] random = new byte[48];
|
||||
generator.nextBytes(random);
|
||||
|
||||
if (failoverException == null && secretKey != null) {
|
||||
if (failoverException == null && encoded != null) {
|
||||
// check the length
|
||||
byte[] encoded = secretKey.getEncoded();
|
||||
if (encoded == null) { // unable to get the encoded key
|
||||
if (debug != null && Debug.isOn("handshake")) {
|
||||
System.out.println(
|
||||
"unable to get the plaintext of the premaster secret");
|
||||
}
|
||||
|
||||
int keySize = KeyUtil.getKeySize(secretKey);
|
||||
if (keySize > 0 && keySize != 384) { // 384 = 48 * 8
|
||||
if (debug != null && Debug.isOn("handshake")) {
|
||||
System.out.println(
|
||||
"incorrect length of premaster secret: " +
|
||||
(keySize/8));
|
||||
}
|
||||
|
||||
return generateDummySecret(clientHelloVersion);
|
||||
}
|
||||
|
||||
// The key size is exactly 48 bytes or not accessible.
|
||||
//
|
||||
// Conservatively, pass the checking to master secret
|
||||
// calculation.
|
||||
return secretKey;
|
||||
} else if (encoded.length == 48) {
|
||||
// check the version
|
||||
if (clientHelloVersion.major == encoded[0] &&
|
||||
clientHelloVersion.minor == encoded[1]) {
|
||||
|
||||
return secretKey;
|
||||
} else if (clientHelloVersion.v <= ProtocolVersion.TLS10.v &&
|
||||
currentVersion.major == encoded[0] &&
|
||||
currentVersion.minor == encoded[1]) {
|
||||
/*
|
||||
* For compatibility, we maintain the behavior that the
|
||||
* version in pre_master_secret can be the negotiated
|
||||
* version for TLS v1.0 and SSL v3.0.
|
||||
*/
|
||||
this.protocolVersion = currentVersion;
|
||||
return secretKey;
|
||||
}
|
||||
|
||||
if (debug != null && Debug.isOn("handshake")) {
|
||||
System.out.println("Mismatching Protocol Versions, " +
|
||||
"ClientHello.client_version is " + clientHelloVersion +
|
||||
", while PreMasterSecret.client_version is " +
|
||||
ProtocolVersion.valueOf(encoded[0], encoded[1]));
|
||||
}
|
||||
|
||||
return generateDummySecret(clientHelloVersion);
|
||||
} else {
|
||||
if (encoded.length != 48) {
|
||||
if (debug != null && Debug.isOn("handshake")) {
|
||||
System.out.println(
|
||||
"incorrect length of premaster secret: " +
|
||||
encoded.length);
|
||||
}
|
||||
|
||||
return generateDummySecret(clientHelloVersion);
|
||||
return generatePreMasterSecret(
|
||||
clientHelloVersion, random, generator);
|
||||
}
|
||||
|
||||
if (clientHelloVersion.major != encoded[0] ||
|
||||
clientHelloVersion.minor != encoded[1]) {
|
||||
|
||||
if (clientHelloVersion.v <= ProtocolVersion.TLS10.v &&
|
||||
currentVersion.major == encoded[0] &&
|
||||
currentVersion.minor == encoded[1]) {
|
||||
/*
|
||||
* For compatibility, we maintain the behavior that the
|
||||
* version in pre_master_secret can be the negotiated
|
||||
* version for TLS v1.0 and SSL v3.0.
|
||||
*/
|
||||
this.protocolVersion = currentVersion;
|
||||
} else {
|
||||
if (debug != null && Debug.isOn("handshake")) {
|
||||
System.out.println("Mismatching Protocol Versions, " +
|
||||
"ClientHello.client_version is " +
|
||||
clientHelloVersion +
|
||||
", while PreMasterSecret.client_version is " +
|
||||
ProtocolVersion.valueOf(encoded[0], encoded[1]));
|
||||
}
|
||||
|
||||
encoded = random;
|
||||
}
|
||||
}
|
||||
|
||||
return generatePreMasterSecret(
|
||||
clientHelloVersion, encoded, generator);
|
||||
}
|
||||
|
||||
if (debug != null && Debug.isOn("handshake") &&
|
||||
@ -250,11 +250,14 @@ final class RSAClientKeyExchange extends HandshakeMessage {
|
||||
failoverException.printStackTrace(System.out);
|
||||
}
|
||||
|
||||
return generateDummySecret(clientHelloVersion);
|
||||
return generatePreMasterSecret(clientHelloVersion, random, generator);
|
||||
}
|
||||
|
||||
// generate a premaster secret with the specified version number
|
||||
static SecretKey generateDummySecret(ProtocolVersion version) {
|
||||
private static SecretKey generatePreMasterSecret(
|
||||
ProtocolVersion version, byte[] encodedSecret,
|
||||
SecureRandom generator) {
|
||||
|
||||
if (debug != null && Debug.isOn("handshake")) {
|
||||
System.out.println("Generating a random fake premaster secret");
|
||||
}
|
||||
@ -263,11 +266,17 @@ final class RSAClientKeyExchange extends HandshakeMessage {
|
||||
String s = ((version.v >= ProtocolVersion.TLS12.v) ?
|
||||
"SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret");
|
||||
KeyGenerator kg = JsseJce.getKeyGenerator(s);
|
||||
kg.init(new TlsRsaPremasterSecretParameterSpec
|
||||
(version.major, version.minor));
|
||||
kg.init(new TlsRsaPremasterSecretParameterSpec(
|
||||
version.major, version.minor, encodedSecret), generator);
|
||||
return kg.generateKey();
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw new RuntimeException("Could not generate dummy secret", e);
|
||||
} catch (InvalidAlgorithmParameterException |
|
||||
NoSuchAlgorithmException iae) {
|
||||
// unlikely to happen, otherwise, must be a provider exception
|
||||
if (debug != null && Debug.isOn("handshake")) {
|
||||
System.out.println("RSA premaster secret generation error:");
|
||||
iae.printStackTrace(System.out);
|
||||
}
|
||||
throw new RuntimeException("Could not generate dummy secret", iae);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user