提交 4e8290f9 编写于 作者: X xuelei

8028192: Use of PKCS11-NSS provider in FIPS mode broken

Reviewed-by: ahgross, ascarpino, asmotrak
上级 fea66171
/* /*
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2014, 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,6 +39,8 @@ import javax.crypto.spec.OAEPParameterSpec; ...@@ -39,6 +39,8 @@ import javax.crypto.spec.OAEPParameterSpec;
import sun.security.rsa.*; import sun.security.rsa.*;
import sun.security.jca.Providers; import sun.security.jca.Providers;
import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
import sun.security.util.KeyUtil;
/** /**
* RSA cipher implementation. Supports RSA en/decryption and signing/verifying * RSA cipher implementation. Supports RSA en/decryption and signing/verifying
...@@ -91,8 +93,8 @@ public final class RSACipher extends CipherSpi { ...@@ -91,8 +93,8 @@ public final class RSACipher extends CipherSpi {
// padding object // padding object
private RSAPadding padding; private RSAPadding padding;
// cipher parameter for OAEP padding // cipher parameter for OAEP padding and TLS RSA premaster secret
private OAEPParameterSpec spec = null; private AlgorithmParameterSpec spec = null;
// buffer for the data // buffer for the data
private byte[] buffer; private byte[] buffer;
...@@ -110,6 +112,9 @@ public final class RSACipher extends CipherSpi { ...@@ -110,6 +112,9 @@ public final class RSACipher extends CipherSpi {
// hash algorithm for OAEP // hash algorithm for OAEP
private String oaepHashAlgorithm = "SHA-1"; private String oaepHashAlgorithm = "SHA-1";
// the source of randomness
private SecureRandom random;
public RSACipher() { public RSACipher() {
paddingType = PAD_PKCS1; paddingType = PAD_PKCS1;
} }
...@@ -175,7 +180,7 @@ public final class RSACipher extends CipherSpi { ...@@ -175,7 +180,7 @@ public final class RSACipher extends CipherSpi {
// see JCE spec // see JCE spec
protected AlgorithmParameters engineGetParameters() { protected AlgorithmParameters engineGetParameters() {
if (spec != null) { if (spec != null && spec instanceof OAEPParameterSpec) {
try { try {
AlgorithmParameters params = AlgorithmParameters params =
AlgorithmParameters.getInstance("OAEP", AlgorithmParameters.getInstance("OAEP",
...@@ -276,8 +281,13 @@ public final class RSACipher extends CipherSpi { ...@@ -276,8 +281,13 @@ public final class RSACipher extends CipherSpi {
buffer = new byte[n]; buffer = new byte[n];
} else if (paddingType == PAD_PKCS1) { } else if (paddingType == PAD_PKCS1) {
if (params != null) { if (params != null) {
throw new InvalidAlgorithmParameterException if (!(params instanceof TlsRsaPremasterSecretParameterSpec)) {
("Parameters not supported"); throw new InvalidAlgorithmParameterException(
"Parameters not supported");
}
spec = params;
this.random = random; // for TLS RSA premaster secret
} }
int blockType = (mode <= MODE_DECRYPT) ? RSAPadding.PAD_BLOCKTYPE_2 int blockType = (mode <= MODE_DECRYPT) ? RSAPadding.PAD_BLOCKTYPE_2
: RSAPadding.PAD_BLOCKTYPE_1; : RSAPadding.PAD_BLOCKTYPE_1;
...@@ -293,19 +303,18 @@ public final class RSACipher extends CipherSpi { ...@@ -293,19 +303,18 @@ public final class RSACipher extends CipherSpi {
throw new InvalidKeyException throw new InvalidKeyException
("OAEP cannot be used to sign or verify signatures"); ("OAEP cannot be used to sign or verify signatures");
} }
OAEPParameterSpec myParams;
if (params != null) { if (params != null) {
if (!(params instanceof OAEPParameterSpec)) { if (!(params instanceof OAEPParameterSpec)) {
throw new InvalidAlgorithmParameterException throw new InvalidAlgorithmParameterException
("Wrong Parameters for OAEP Padding"); ("Wrong Parameters for OAEP Padding");
} }
myParams = (OAEPParameterSpec) params; spec = params;
} else { } else {
myParams = new OAEPParameterSpec(oaepHashAlgorithm, "MGF1", spec = new OAEPParameterSpec(oaepHashAlgorithm, "MGF1",
MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT); MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT);
} }
padding = RSAPadding.getInstance(RSAPadding.PAD_OAEP_MGF1, n, padding = RSAPadding.getInstance(RSAPadding.PAD_OAEP_MGF1, n,
random, myParams); random, (OAEPParameterSpec)spec);
if (encrypt) { if (encrypt) {
int k = padding.getMaxDataSize(); int k = padding.getMaxDataSize();
buffer = new byte[k]; buffer = new byte[k];
...@@ -420,17 +429,40 @@ public final class RSACipher extends CipherSpi { ...@@ -420,17 +429,40 @@ public final class RSACipher extends CipherSpi {
if (wrappedKey.length > buffer.length) { if (wrappedKey.length > buffer.length) {
throw new InvalidKeyException("Key is too long for unwrapping"); throw new InvalidKeyException("Key is too long for unwrapping");
} }
boolean isTlsRsaPremasterSecret =
algorithm.equals("TlsRsaPremasterSecret");
Exception failover = null;
byte[] encoded = null;
update(wrappedKey, 0, wrappedKey.length); update(wrappedKey, 0, wrappedKey.length);
try { try {
byte[] encoded = doFinal(); encoded = doFinal();
return ConstructKeys.constructKey(encoded, algorithm, type);
} catch (BadPaddingException e) { } catch (BadPaddingException e) {
// should not occur if (isTlsRsaPremasterSecret) {
throw new InvalidKeyException("Unwrapping failed", e); failover = e;
} else {
throw new InvalidKeyException("Unwrapping failed", e);
}
} catch (IllegalBlockSizeException e) { } catch (IllegalBlockSizeException e) {
// should not occur, handled with length check above // should not occur, handled with length check above
throw new InvalidKeyException("Unwrapping failed", e); throw new InvalidKeyException("Unwrapping failed", e);
} }
if (isTlsRsaPremasterSecret) {
if (!(spec instanceof TlsRsaPremasterSecretParameterSpec)) {
throw new IllegalStateException(
"No TlsRsaPremasterSecretParameterSpec specified");
}
// polish the TLS premaster secret
encoded = KeyUtil.checkTlsPreMasterSecretKey(
((TlsRsaPremasterSecretParameterSpec)spec).getClientVersion(),
((TlsRsaPremasterSecretParameterSpec)spec).getServerVersion(),
random, encoded, (failover != null));
}
return ConstructKeys.constructKey(encoded, algorithm, type);
} }
// see JCE spec // see JCE spec
...@@ -438,5 +470,4 @@ public final class RSACipher extends CipherSpi { ...@@ -438,5 +470,4 @@ public final class RSACipher extends CipherSpi {
RSAKey rsaKey = RSAKeyFactory.toRSAKey(key); RSAKey rsaKey = RSAKeyFactory.toRSAKey(key);
return rsaKey.getModulus().bitLength(); return rsaKey.getModulus().bitLength();
} }
} }
/* /*
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2014, 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,7 +56,7 @@ public final class TlsRsaPremasterSecretGenerator extends KeyGeneratorSpi { ...@@ -56,7 +56,7 @@ public final class TlsRsaPremasterSecretGenerator extends KeyGeneratorSpi {
protected void engineInit(AlgorithmParameterSpec params, protected void engineInit(AlgorithmParameterSpec params,
SecureRandom random) throws InvalidAlgorithmParameterException { SecureRandom random) throws InvalidAlgorithmParameterException {
if (params instanceof TlsRsaPremasterSecretParameterSpec == false) { if (!(params instanceof TlsRsaPremasterSecretParameterSpec)) {
throw new InvalidAlgorithmParameterException(MSG); throw new InvalidAlgorithmParameterException(MSG);
} }
this.spec = (TlsRsaPremasterSecretParameterSpec)params; this.spec = (TlsRsaPremasterSecretParameterSpec)params;
...@@ -67,21 +67,20 @@ public final class TlsRsaPremasterSecretGenerator extends KeyGeneratorSpi { ...@@ -67,21 +67,20 @@ public final class TlsRsaPremasterSecretGenerator extends KeyGeneratorSpi {
throw new InvalidParameterException(MSG); throw new InvalidParameterException(MSG);
} }
// Only can be used in client side to generate TLS RSA premaster secret.
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");
} }
byte[] b = spec.getEncodedSecret();
if (b == null) { if (random == null) {
if (random == null) { random = new SecureRandom();
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"); return new SecretKeySpec(b, "TlsRsaPremasterSecret");
} }
......
...@@ -26,11 +26,11 @@ ...@@ -26,11 +26,11 @@
package sun.security.internal.spec; package sun.security.internal.spec;
import java.security.spec.AlgorithmParameterSpec; import java.security.spec.AlgorithmParameterSpec;
import java.security.AccessController;
import java.security.PrivilegedAction;
/** /**
* Parameters for SSL/TLS RSA Premaster secret generation. * Parameters for SSL/TLS RSA premaster secret.
* This class is used by SSL/TLS client to initialize KeyGenerators of the
* type "TlsRsaPremasterSecret".
* *
* <p>Instances of this class are immutable. * <p>Instances of this class are immutable.
* *
...@@ -43,90 +43,108 @@ import java.security.spec.AlgorithmParameterSpec; ...@@ -43,90 +43,108 @@ import java.security.spec.AlgorithmParameterSpec;
public class TlsRsaPremasterSecretParameterSpec public class TlsRsaPremasterSecretParameterSpec
implements AlgorithmParameterSpec { implements AlgorithmParameterSpec {
private final int majorVersion; /*
private final int minorVersion; * The TLS spec says that the version in the RSA premaster secret must
private final byte[] encodedSecret; * be the maximum version supported by the client (i.e. the version it
* requested in its client hello version). However, we (and other
* implementations) used to send the active negotiated version. The
* system property below allows to toggle the behavior.
*/
private final static String PROP_NAME =
"com.sun.net.ssl.rsaPreMasterSecretFix";
/*
* Default is "false" (old behavior) for compatibility reasons in
* SSLv3/TLSv1. Later protocols (TLSv1.1+) do not use this property.
*/
private final static boolean rsaPreMasterSecretFix =
AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
public Boolean run() {
String value = System.getProperty(PROP_NAME);
if (value != null && value.equalsIgnoreCase("true")) {
return Boolean.TRUE;
}
return Boolean.FALSE;
}
});
private final int clientVersion;
private final int serverVersion;
/** /**
* Constructs a new TlsRsaPremasterSecretParameterSpec. * 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.
* *
* @param majorVersion the major number of the protocol version * @param clientVersion the version of the TLS protocol by which the
* @param minorVersion the minor number of the protocol version * client wishes to communicate during this session
* @param serverVersion the negotiated version of the TLS protocol which
* contains the lower of that suggested by the client in the client
* hello and the highest supported by the server.
* *
* @throws IllegalArgumentException if minorVersion or majorVersion are * @throws IllegalArgumentException if clientVersion or serverVersion are
* negative or larger than 255 * negative or larger than (2^16 - 1)
*/ */
public TlsRsaPremasterSecretParameterSpec(int majorVersion, public TlsRsaPremasterSecretParameterSpec(
int minorVersion) { int clientVersion, int serverVersion) {
this.majorVersion =
TlsMasterSecretParameterSpec.checkVersion(majorVersion); this.clientVersion = checkVersion(clientVersion);
this.minorVersion = this.serverVersion = checkVersion(serverVersion);
TlsMasterSecretParameterSpec.checkVersion(minorVersion);
this.encodedSecret = null;
} }
/** /**
* Constructs a new TlsRsaPremasterSecretParameterSpec. * Returns the version of the TLS protocol by which the client wishes to
* <P> * communicate during this session.
* 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 * @return the version of the TLS protocol in ClientHello message
* negative or larger than 255, or encodedSecret is not exactly 48 bytes.
*/ */
public TlsRsaPremasterSecretParameterSpec(int majorVersion, public int getClientVersion() {
int minorVersion, byte[] encodedSecret) { return clientVersion;
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. * Returns the negotiated version of the TLS protocol which contains the
* lower of that suggested by the client in the client hello and the
* highest supported by the server.
* *
* @return the major version. * @return the negotiated version of the TLS protocol in ServerHello message
*/ */
public int getMajorVersion() { public int getServerVersion() {
return majorVersion; return serverVersion;
} }
/** /**
* Returns the minor version. * Returns the major version used in RSA premaster secret.
* *
* @return the minor version. * @return the major version used in RSA premaster secret.
*/ */
public int getMinorVersion() { public int getMajorVersion() {
return minorVersion; if (rsaPreMasterSecretFix || clientVersion >= 0x0302) {
// 0x0302: TLSv1.1
return (clientVersion >>> 8) & 0xFF;
}
return (serverVersion >>> 8) & 0xFF;
} }
/** /**
* Returns the encoded secret. * Returns the minor version used in RSA premaster secret.
* *
* @return the encoded secret, may be null if no encoded secret. * @return the minor version used in RSA premaster secret.
*/ */
public byte[] getEncodedSecret() { public int getMinorVersion() {
return encodedSecret == null ? null : encodedSecret.clone(); if (rsaPreMasterSecretFix || clientVersion >= 0x0302) {
// 0x0302: TLSv1.1
return clientVersion & 0xFF;
}
return serverVersion & 0xFF;
}
private int checkVersion(int version) {
if ((version < 0) || (version > 0xFFFF)) {
throw new IllegalArgumentException(
"Version must be between 0 and 65,535");
}
return version;
} }
} }
...@@ -37,6 +37,8 @@ import javax.crypto.spec.*; ...@@ -37,6 +37,8 @@ import javax.crypto.spec.*;
import static sun.security.pkcs11.TemplateManager.*; import static sun.security.pkcs11.TemplateManager.*;
import sun.security.pkcs11.wrapper.*; import sun.security.pkcs11.wrapper.*;
import static sun.security.pkcs11.wrapper.PKCS11Constants.*; import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
import sun.security.util.KeyUtil;
/** /**
* RSA Cipher implementation class. We currently only support * RSA Cipher implementation class. We currently only support
...@@ -102,6 +104,12 @@ final class P11RSACipher extends CipherSpi { ...@@ -102,6 +104,12 @@ final class P11RSACipher extends CipherSpi {
// maximum output size. this is the length of the key // maximum output size. this is the length of the key
private int outputSize; private int outputSize;
// cipher parameter for TLS RSA premaster secret
private AlgorithmParameterSpec spec = null;
// the source of randomness
private SecureRandom random;
P11RSACipher(Token token, String algorithm, long mechanism) P11RSACipher(Token token, String algorithm, long mechanism)
throws PKCS11Exception { throws PKCS11Exception {
super(); super();
...@@ -165,8 +173,12 @@ final class P11RSACipher extends CipherSpi { ...@@ -165,8 +173,12 @@ final class P11RSACipher extends CipherSpi {
AlgorithmParameterSpec params, SecureRandom random) AlgorithmParameterSpec params, SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException { throws InvalidKeyException, InvalidAlgorithmParameterException {
if (params != null) { if (params != null) {
throw new InvalidAlgorithmParameterException if (!(params instanceof TlsRsaPremasterSecretParameterSpec)) {
("Parameters not supported"); throw new InvalidAlgorithmParameterException(
"Parameters not supported");
}
spec = params;
this.random = random; // for TLS RSA premaster secret
} }
implInit(opmode, key); implInit(opmode, key);
} }
...@@ -176,8 +188,8 @@ final class P11RSACipher extends CipherSpi { ...@@ -176,8 +188,8 @@ final class P11RSACipher extends CipherSpi {
SecureRandom random) SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException { throws InvalidKeyException, InvalidAlgorithmParameterException {
if (params != null) { if (params != null) {
throw new InvalidAlgorithmParameterException throw new InvalidAlgorithmParameterException(
("Parameters not supported"); "Parameters not supported");
} }
implInit(opmode, key); implInit(opmode, key);
} }
...@@ -452,21 +464,101 @@ final class P11RSACipher extends CipherSpi { ...@@ -452,21 +464,101 @@ final class P11RSACipher extends CipherSpi {
protected Key engineUnwrap(byte[] wrappedKey, String algorithm, protected Key engineUnwrap(byte[] wrappedKey, String algorithm,
int type) throws InvalidKeyException, NoSuchAlgorithmException { int type) throws InvalidKeyException, NoSuchAlgorithmException {
// XXX implement unwrap using C_Unwrap() for all keys boolean isTlsRsaPremasterSecret =
implInit(Cipher.DECRYPT_MODE, p11Key); algorithm.equals("TlsRsaPremasterSecret");
if (wrappedKey.length > maxInputSize) { Exception failover = null;
throw new InvalidKeyException("Key is too long for unwrapping");
SecureRandom secureRandom = random;
if (secureRandom == null && isTlsRsaPremasterSecret) {
secureRandom = new SecureRandom();
} }
implUpdate(wrappedKey, 0, wrappedKey.length);
try { // Should C_Unwrap be preferred for non-TLS RSA premaster secret?
byte[] encoded = doFinal(); if (token.supportsRawSecretKeyImport()) {
// XXX implement unwrap using C_Unwrap() for all keys
implInit(Cipher.DECRYPT_MODE, p11Key);
if (wrappedKey.length > maxInputSize) {
throw new InvalidKeyException("Key is too long for unwrapping");
}
byte[] encoded = null;
implUpdate(wrappedKey, 0, wrappedKey.length);
try {
encoded = doFinal();
} catch (BadPaddingException e) {
if (isTlsRsaPremasterSecret) {
failover = e;
} else {
throw new InvalidKeyException("Unwrapping failed", e);
}
} catch (IllegalBlockSizeException e) {
// should not occur, handled with length check above
throw new InvalidKeyException("Unwrapping failed", e);
}
if (isTlsRsaPremasterSecret) {
if (!(spec instanceof TlsRsaPremasterSecretParameterSpec)) {
throw new IllegalStateException(
"No TlsRsaPremasterSecretParameterSpec specified");
}
// polish the TLS premaster secret
TlsRsaPremasterSecretParameterSpec psps =
(TlsRsaPremasterSecretParameterSpec)spec;
encoded = KeyUtil.checkTlsPreMasterSecretKey(
psps.getClientVersion(), psps.getServerVersion(),
secureRandom, encoded, (failover != null));
}
return ConstructKeys.constructKey(encoded, algorithm, type); return ConstructKeys.constructKey(encoded, algorithm, type);
} catch (BadPaddingException e) { } else {
// should not occur Session s = null;
throw new InvalidKeyException("Unwrapping failed", e); SecretKey secretKey = null;
} catch (IllegalBlockSizeException e) { try {
// should not occur, handled with length check above try {
throw new InvalidKeyException("Unwrapping failed", e); 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);
secretKey = P11Key.secretKey(s, keyID,
algorithm, 48 << 3, attributes);
} catch (PKCS11Exception e) {
if (isTlsRsaPremasterSecret) {
failover = e;
} else {
throw new InvalidKeyException("unwrap() failed", e);
}
}
if (isTlsRsaPremasterSecret) {
byte[] replacer = new byte[48];
if (failover == null) {
// Does smart compiler dispose this operation?
secureRandom.nextBytes(replacer);
}
TlsRsaPremasterSecretParameterSpec psps =
(TlsRsaPremasterSecretParameterSpec)spec;
// Please use the tricky failover and replacer byte array
// as the parameters so that smart compiler won't dispose
// the unused variable .
secretKey = polishPreMasterSecretKey(token, s,
failover, replacer, secretKey,
psps.getClientVersion(), psps.getServerVersion());
}
return secretKey;
} finally {
token.releaseSession(s);
}
} }
} }
...@@ -475,6 +567,34 @@ final class P11RSACipher extends CipherSpi { ...@@ -475,6 +567,34 @@ final class P11RSACipher extends CipherSpi {
int n = P11KeyFactory.convertKey(token, key, algorithm).length(); int n = P11KeyFactory.convertKey(token, key, algorithm).length();
return n; return n;
} }
private static SecretKey polishPreMasterSecretKey(
Token token, Session session,
Exception failover, byte[] replacer, SecretKey secretKey,
int clientVersion, int serverVersion) {
if (failover != null) {
CK_VERSION version = new CK_VERSION(
(clientVersion >>> 8) & 0xFF, clientVersion & 0xFF);
try {
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(CKM_TLS_PRE_MASTER_KEY_GEN, version),
new CK_MECHANISM(CKM_SSL3_PRE_MASTER_KEY_GEN, version),
attributes);
return P11Key.secretKey(session,
keyID, "TlsRsaPremasterSecret", 48 << 3, attributes);
} catch (PKCS11Exception e) {
throw new ProviderException(
"Could not generate premaster secret", e);
}
}
return secretKey;
}
} }
final class ConstructKeys { final class ConstructKeys {
......
...@@ -73,7 +73,7 @@ final class P11TlsRsaPremasterSecretGenerator extends KeyGeneratorSpi { ...@@ -73,7 +73,7 @@ final class P11TlsRsaPremasterSecretGenerator extends KeyGeneratorSpi {
protected void engineInit(AlgorithmParameterSpec params, protected void engineInit(AlgorithmParameterSpec params,
SecureRandom random) throws InvalidAlgorithmParameterException { SecureRandom random) throws InvalidAlgorithmParameterException {
if (params instanceof TlsRsaPremasterSecretParameterSpec == false) { if (!(params instanceof TlsRsaPremasterSecretParameterSpec)) {
throw new InvalidAlgorithmParameterException(MSG); throw new InvalidAlgorithmParameterException(MSG);
} }
this.spec = (TlsRsaPremasterSecretParameterSpec)params; this.spec = (TlsRsaPremasterSecretParameterSpec)params;
...@@ -83,38 +83,32 @@ final class P11TlsRsaPremasterSecretGenerator extends KeyGeneratorSpi { ...@@ -83,38 +83,32 @@ final class P11TlsRsaPremasterSecretGenerator extends KeyGeneratorSpi {
throw new InvalidParameterException(MSG); throw new InvalidParameterException(MSG);
} }
// Only can be used in client side to generate TLS RSA premaster secret.
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");
} }
byte[] b = spec.getEncodedSecret(); CK_VERSION version = new CK_VERSION(
if (b == null) {
CK_VERSION version = new CK_VERSION(
spec.getMajorVersion(), spec.getMinorVersion()); spec.getMajorVersion(), spec.getMinorVersion());
Session session = null; Session session = null;
try { try {
session = token.getObjSession(); session = token.getObjSession();
CK_ATTRIBUTE[] attributes = token.getAttributes( CK_ATTRIBUTE[] attributes = token.getAttributes(
O_GENERATE, CKO_SECRET_KEY, O_GENERATE, CKO_SECRET_KEY,
CKK_GENERIC_SECRET, new CK_ATTRIBUTE[0]); CKK_GENERIC_SECRET, new CK_ATTRIBUTE[0]);
long keyID = token.p11.C_GenerateKey(session.id(), long keyID = token.p11.C_GenerateKey(session.id(),
new CK_MECHANISM(mechanism, version), attributes); new CK_MECHANISM(mechanism, version), attributes);
SecretKey key = P11Key.secretKey(session, SecretKey key = P11Key.secretKey(session,
keyID, "TlsRsaPremasterSecret", 48 << 3, attributes); keyID, "TlsRsaPremasterSecret", 48 << 3, attributes);
return key; return key;
} catch (PKCS11Exception e) { } catch (PKCS11Exception e) {
throw new ProviderException( throw new ProviderException(
"Could not generate premaster secret", e); "Could not generate premaster secret", e);
} finally { } finally {
token.releaseSession(session); token.releaseSession(session);
}
} }
// Won't worry, the TlsRsaPremasterSecret will be soon converted to
// TlsMasterSecret.
return new SecretKeySpec(b, "TlsRsaPremasterSecret");
} }
} }
...@@ -36,6 +36,7 @@ import javax.security.auth.login.LoginException; ...@@ -36,6 +36,7 @@ import javax.security.auth.login.LoginException;
import sun.security.jca.JCAUtil; import sun.security.jca.JCAUtil;
import sun.security.pkcs11.wrapper.*; import sun.security.pkcs11.wrapper.*;
import static sun.security.pkcs11.TemplateManager.*;
import static sun.security.pkcs11.wrapper.PKCS11Constants.*; import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
/** /**
...@@ -122,6 +123,9 @@ class Token implements Serializable { ...@@ -122,6 +123,9 @@ class Token implements Serializable {
private final static CK_MECHANISM_INFO INVALID_MECH = private final static CK_MECHANISM_INFO INVALID_MECH =
new CK_MECHANISM_INFO(0, 0, 0); new CK_MECHANISM_INFO(0, 0, 0);
// flag indicating whether the token supports raw secret key material import
private Boolean supportsRawSecretKeyImport;
Token(SunPKCS11 provider) throws PKCS11Exception { Token(SunPKCS11 provider) throws PKCS11Exception {
this.provider = provider; this.provider = provider;
this.removable = provider.removable; this.removable = provider.removable;
...@@ -160,6 +164,36 @@ class Token implements Serializable { ...@@ -160,6 +164,36 @@ class Token implements Serializable {
return writeProtected; return writeProtected;
} }
// return whether the token supports raw secret key material import
boolean supportsRawSecretKeyImport() {
if (supportsRawSecretKeyImport == null) {
SecureRandom random = JCAUtil.getSecureRandom();
byte[] encoded = new byte[48];
random.nextBytes(encoded);
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[3];
attributes[0] = new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY);
attributes[1] = new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_GENERIC_SECRET);
attributes[2] = new CK_ATTRIBUTE(CKA_VALUE, encoded);
Session session = null;
try {
attributes = getAttributes(O_IMPORT,
CKO_SECRET_KEY, CKK_GENERIC_SECRET, attributes);
session = getObjSession();
long keyID = p11.C_CreateObject(session.id(), attributes);
supportsRawSecretKeyImport = Boolean.TRUE;
} catch (PKCS11Exception e) {
supportsRawSecretKeyImport = Boolean.FALSE;
} finally {
releaseSession(session);
}
}
return supportsRawSecretKeyImport;
}
// return whether we are logged in // return whether we are logged in
// uses cached result if current. session is optional and may be null // uses cached result if current. session is optional and may be null
boolean isLoggedIn(Session session) throws PKCS11Exception { boolean isLoggedIn(Session session) throws PKCS11Exception {
......
...@@ -48,23 +48,6 @@ import sun.security.util.KeyUtil; ...@@ -48,23 +48,6 @@ import sun.security.util.KeyUtil;
*/ */
final class RSAClientKeyExchange extends HandshakeMessage { final class RSAClientKeyExchange extends HandshakeMessage {
/**
* The TLS spec says that the version in the RSA premaster secret must
* be the maximum version supported by the client (i.e. the version it
* requested in its client hello version). However, we (and other
* implementations) used to send the active negotiated version. The
* system property below allows to toggle the behavior.
*/
private final static String PROP_NAME =
"com.sun.net.ssl.rsaPreMasterSecretFix";
/*
* Default is "false" (old behavior) for compatibility reasons in
* SSLv3/TLSv1. Later protocols (TLSv1.1+) do not use this property.
*/
private final static boolean rsaPreMasterSecretFix =
Debug.getBooleanProperty(PROP_NAME, false);
/* /*
* The following field values were encrypted with the server's public * The following field values were encrypted with the server's public
* key (or temp key from server key exchange msg) and are presented * key (or temp key from server key exchange msg) and are presented
...@@ -88,22 +71,12 @@ final class RSAClientKeyExchange extends HandshakeMessage { ...@@ -88,22 +71,12 @@ final class RSAClientKeyExchange extends HandshakeMessage {
} }
this.protocolVersion = protocolVersion; this.protocolVersion = protocolVersion;
int major, minor;
if (rsaPreMasterSecretFix || maxVersion.v >= ProtocolVersion.TLS11.v) {
major = maxVersion.major;
minor = maxVersion.minor;
} else {
major = protocolVersion.major;
minor = protocolVersion.minor;
}
try { try {
String s = ((protocolVersion.v >= ProtocolVersion.TLS12.v) ? String s = ((protocolVersion.v >= ProtocolVersion.TLS12.v) ?
"SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret"); "SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret");
KeyGenerator kg = JsseJce.getKeyGenerator(s); KeyGenerator kg = JsseJce.getKeyGenerator(s);
kg.init(new TlsRsaPremasterSecretParameterSpec(major, minor), kg.init(new TlsRsaPremasterSecretParameterSpec(
generator); maxVersion.v, protocolVersion.v), generator);
preMaster = kg.generateKey(); preMaster = kg.generateKey();
Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1); Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1);
...@@ -138,18 +111,16 @@ final class RSAClientKeyExchange extends HandshakeMessage { ...@@ -138,18 +111,16 @@ final class RSAClientKeyExchange extends HandshakeMessage {
} }
} }
Exception failover = null;
byte[] encoded = null;
try { try {
Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1); Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1);
// Cannot generate key here, please don't use Cipher.UNWRAP_MODE! cipher.init(Cipher.UNWRAP_MODE, privateKey,
cipher.init(Cipher.DECRYPT_MODE, privateKey); new TlsRsaPremasterSecretParameterSpec(
encoded = cipher.doFinal(encrypted); maxVersion.v, currentVersion.v),
} catch (BadPaddingException bpe) { generator);
failover = bpe; preMaster = (SecretKey)cipher.unwrap(encrypted,
encoded = null; "TlsRsaPremasterSecret", Cipher.SECRET_KEY);
} catch (IllegalBlockSizeException ibse) { } catch (InvalidKeyException ibk) {
// the message it too big to process with RSA // the message is too big to process with RSA
throw new SSLProtocolException( throw new SSLProtocolException(
"Unable to process PreMasterSecret, may be too big"); "Unable to process PreMasterSecret, may be too big");
} catch (Exception e) { } catch (Exception e) {
...@@ -160,124 +131,6 @@ final class RSAClientKeyExchange extends HandshakeMessage { ...@@ -160,124 +131,6 @@ final class RSAClientKeyExchange extends HandshakeMessage {
} }
throw new RuntimeException("Could not generate dummy secret", e); throw new RuntimeException("Could not generate dummy secret", e);
} }
// polish the premaster secret
preMaster = polishPreMasterSecretKey(
currentVersion, maxVersion, generator, encoded, failover);
}
/**
* To avoid vulnerabilities described by section 7.4.7.1, RFC 5246,
* treating incorrectly formatted message blocks and/or mismatched
* version numbers in a manner indistinguishable from correctly
* formatted RSA blocks.
*
* RFC 5246 describes the approach as :
*
* 1. Generate a string R of 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 = R
* else If ClientHello.client_version <= TLS 1.0, and version
* number check is explicitly disabled:
* premaster secret = M
* else If M[0..1] != ClientHello.client_version:
* premaster secret = R
* else:
* premaster secret = M
*
* Note that #2 has completed before the call of this method.
*/
private SecretKey polishPreMasterSecretKey(ProtocolVersion currentVersion,
ProtocolVersion clientHelloVersion, SecureRandom generator,
byte[] encoded, Exception failoverException) {
this.protocolVersion = clientHelloVersion;
if (generator == null) {
generator = new SecureRandom();
}
byte[] random = new byte[48];
generator.nextBytes(random);
if (failoverException == null && encoded != null) {
// check the length
if (encoded.length != 48) {
if (debug != null && Debug.isOn("handshake")) {
System.out.println(
"incorrect length of premaster secret: " +
encoded.length);
}
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") &&
failoverException != null) {
System.out.println("Error decrypting premaster secret:");
failoverException.printStackTrace(System.out);
}
return generatePreMasterSecret(clientHelloVersion, random, generator);
}
// generate a premaster secret with the specified version number
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");
}
try {
String s = ((version.v >= ProtocolVersion.TLS12.v) ?
"SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret");
KeyGenerator kg = JsseJce.getKeyGenerator(s);
kg.init(new TlsRsaPremasterSecretParameterSpec(
version.major, version.minor, encodedSecret), generator);
return kg.generateKey();
} 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);
}
} }
@Override @Override
......
/* /*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2014, 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.InvalidKeyException; ...@@ -32,6 +32,7 @@ import java.security.InvalidKeyException;
import java.security.interfaces.ECKey; import java.security.interfaces.ECKey;
import java.security.interfaces.RSAKey; import java.security.interfaces.RSAKey;
import java.security.interfaces.DSAKey; import java.security.interfaces.DSAKey;
import java.security.SecureRandom;
import java.security.spec.KeySpec; import java.security.spec.KeySpec;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
import javax.crypto.interfaces.DHKey; import javax.crypto.interfaces.DHKey;
...@@ -156,6 +157,79 @@ public final class KeyUtil { ...@@ -156,6 +157,79 @@ public final class KeyUtil {
providerName.startsWith("SunPKCS11")); providerName.startsWith("SunPKCS11"));
} }
/**
* Check the format of TLS PreMasterSecret.
* <P>
* To avoid vulnerabilities described by section 7.4.7.1, RFC 5246,
* treating incorrectly formatted message blocks and/or mismatched
* version numbers in a manner indistinguishable from correctly
* formatted RSA blocks.
*
* RFC 5246 describes the approach as :
*
* 1. Generate a string R of 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 = R
* else If ClientHello.client_version <= TLS 1.0, and version
* number check is explicitly disabled:
* premaster secret = M
* else If M[0..1] != ClientHello.client_version:
* premaster secret = R
* else:
* premaster secret = M
*
* Note that #2 should have completed before the call to this method.
*
* @param clientVersion the version of the TLS protocol by which the
* client wishes to communicate during this session
* @param serverVersion the negotiated version of the TLS protocol which
* contains the lower of that suggested by the client in the client
* hello and the highest supported by the server.
* @param encoded the encoded key in its "RAW" encoding format
* @param isFailover whether or not the previous decryption of the
* encrypted PreMasterSecret message run into problem
* @return the polished PreMasterSecret key in its "RAW" encoding format
*/
public static byte[] checkTlsPreMasterSecretKey(
int clientVersion, int serverVersion, SecureRandom random,
byte[] encoded, boolean isFailOver) {
if (random == null) {
random = new SecureRandom();
}
byte[] replacer = new byte[48];
random.nextBytes(replacer);
if (!isFailOver && (encoded != null)) {
// check the length
if (encoded.length != 48) {
// private, don't need to clone the byte array.
return replacer;
}
int encodedVersion =
((encoded[0] & 0xFF) << 8) | (encoded[1] & 0xFF);
if (clientVersion != encodedVersion) {
if (clientVersion > 0x0301 || // 0x0301: TLSv1
serverVersion != encodedVersion) {
encoded = replacer;
} // Otherwise, 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.
}
// private, don't need to clone the byte array.
return encoded;
}
// private, don't need to clone the byte array.
return replacer;
}
/** /**
* Returns whether the Diffie-Hellman public key is valid or not. * Returns whether the Diffie-Hellman public key is valid or not.
* *
......
...@@ -35,6 +35,8 @@ import javax.crypto.*; ...@@ -35,6 +35,8 @@ import javax.crypto.*;
import javax.crypto.spec.*; import javax.crypto.spec.*;
import sun.security.rsa.RSAKeyFactory; import sun.security.rsa.RSAKeyFactory;
import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
import sun.security.util.KeyUtil;
/** /**
* RSA cipher implementation using the Microsoft Crypto API. * RSA cipher implementation using the Microsoft Crypto API.
...@@ -92,9 +94,16 @@ public final class RSACipher extends CipherSpi { ...@@ -92,9 +94,16 @@ public final class RSACipher extends CipherSpi {
// the public key, if we were initialized using a public key // the public key, if we were initialized using a public key
private sun.security.mscapi.Key publicKey; private sun.security.mscapi.Key publicKey;
// the private key, if we were initialized using a private key // the private key, if we were initialized using a private key
private sun.security.mscapi.Key privateKey; private sun.security.mscapi.Key privateKey;
// cipher parameter for TLS RSA premaster secret
private AlgorithmParameterSpec spec = null;
// the source of randomness
private SecureRandom random;
public RSACipher() { public RSACipher() {
paddingType = PAD_PKCS1; paddingType = PAD_PKCS1;
} }
...@@ -155,8 +164,12 @@ public final class RSACipher extends CipherSpi { ...@@ -155,8 +164,12 @@ public final class RSACipher extends CipherSpi {
throws InvalidKeyException, InvalidAlgorithmParameterException { throws InvalidKeyException, InvalidAlgorithmParameterException {
if (params != null) { if (params != null) {
throw new InvalidAlgorithmParameterException if (!(params instanceof TlsRsaPremasterSecretParameterSpec)) {
("Parameters not supported"); throw new InvalidAlgorithmParameterException(
"Parameters not supported");
}
spec = params;
this.random = random; // for TLS RSA premaster secret
} }
init(opmode, key); init(opmode, key);
} }
...@@ -356,39 +369,47 @@ public final class RSACipher extends CipherSpi { ...@@ -356,39 +369,47 @@ public final class RSACipher extends CipherSpi {
} }
// see JCE spec // see JCE spec
protected java.security.Key engineUnwrap(byte[] wrappedKey, String algorithm, protected java.security.Key engineUnwrap(byte[] wrappedKey,
String algorithm,
int type) throws InvalidKeyException, NoSuchAlgorithmException { int type) throws InvalidKeyException, NoSuchAlgorithmException {
if (wrappedKey.length > buffer.length) { if (wrappedKey.length > buffer.length) {
throw new InvalidKeyException("Key is too long for unwrapping"); throw new InvalidKeyException("Key is too long for unwrapping");
} }
update(wrappedKey, 0, wrappedKey.length);
try { boolean isTlsRsaPremasterSecret =
byte[] encoding = doFinal(); algorithm.equals("TlsRsaPremasterSecret");
Exception failover = null;
switch (type) { byte[] encoded = null;
case Cipher.PUBLIC_KEY:
return constructPublicKey(encoding, algorithm);
case Cipher.PRIVATE_KEY:
return constructPrivateKey(encoding, algorithm);
case Cipher.SECRET_KEY:
return constructSecretKey(encoding, algorithm);
default:
throw new InvalidKeyException("Unknown key type " + type);
}
update(wrappedKey, 0, wrappedKey.length);
try {
encoded = doFinal();
} catch (BadPaddingException e) { } catch (BadPaddingException e) {
// should not occur if (isTlsRsaPremasterSecret) {
throw new InvalidKeyException("Unwrapping failed", e); failover = e;
} else {
throw new InvalidKeyException("Unwrapping failed", e);
}
} catch (IllegalBlockSizeException e) { } catch (IllegalBlockSizeException e) {
// should not occur, handled with length check above // should not occur, handled with length check above
throw new InvalidKeyException("Unwrapping failed", e); throw new InvalidKeyException("Unwrapping failed", e);
} }
if (isTlsRsaPremasterSecret) {
if (!(spec instanceof TlsRsaPremasterSecretParameterSpec)) {
throw new IllegalStateException(
"No TlsRsaPremasterSecretParameterSpec specified");
}
// polish the TLS premaster secret
encoded = KeyUtil.checkTlsPreMasterSecretKey(
((TlsRsaPremasterSecretParameterSpec)spec).getClientVersion(),
((TlsRsaPremasterSecretParameterSpec)spec).getServerVersion(),
random, encoded, (failover != null));
}
return constructKey(encoded, algorithm, type);
} }
// see JCE spec // see JCE spec
...@@ -452,6 +473,22 @@ public final class RSACipher extends CipherSpi { ...@@ -452,6 +473,22 @@ public final class RSACipher extends CipherSpi {
return new SecretKeySpec(encodedKey, encodedKeyAlgorithm); return new SecretKeySpec(encodedKey, encodedKeyAlgorithm);
} }
private static Key constructKey(byte[] encodedKey,
String encodedKeyAlgorithm,
int keyType) throws InvalidKeyException, NoSuchAlgorithmException {
switch (keyType) {
case Cipher.PUBLIC_KEY:
return constructPublicKey(encodedKey, encodedKeyAlgorithm);
case Cipher.PRIVATE_KEY:
return constructPrivateKey(encodedKey, encodedKeyAlgorithm);
case Cipher.SECRET_KEY:
return constructSecretKey(encodedKey, encodedKeyAlgorithm);
default:
throw new InvalidKeyException("Unknown key type " + keyType);
}
}
/* /*
* Encrypt/decrypt a data buffer using Microsoft Crypto API with HCRYPTKEY. * Encrypt/decrypt a data buffer using Microsoft Crypto API with HCRYPTKEY.
* It expects and returns ciphertext data in big-endian form. * It expects and returns ciphertext data in big-endian form.
......
...@@ -33,6 +33,7 @@ import java.security.Provider; ...@@ -33,6 +33,7 @@ import java.security.Provider;
import javax.crypto.KeyGenerator; import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
import java.util.Formatter;
import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec; import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
...@@ -52,27 +53,51 @@ public class TestPremaster { ...@@ -52,27 +53,51 @@ public class TestPremaster {
System.out.println("OK: " + e); System.out.println("OK: " + e);
} }
test(kg, 3, 0); int[] protocolVersions = {0x0300, 0x0301, 0x0302, 0x0400};
test(kg, 3, 1); for (int clientVersion : protocolVersions) {
test(kg, 3, 2); for (int serverVersion : protocolVersions) {
test(kg, 4, 0); test(kg, clientVersion, serverVersion);
if (serverVersion >= clientVersion) {
break;
}
}
}
System.out.println("Done."); System.out.println("Done.");
} }
private static void test(KeyGenerator kg, int major, int minor) private static void test(KeyGenerator kg,
throws Exception { int clientVersion, int serverVersion) throws Exception {
System.out.printf(
"Testing RSA pre-master secret key generation between " +
"client (0x%04X) and server(0x%04X)%n",
clientVersion, serverVersion);
kg.init(new TlsRsaPremasterSecretParameterSpec(
clientVersion, serverVersion));
kg.init(new TlsRsaPremasterSecretParameterSpec(major, minor));
SecretKey key = kg.generateKey(); SecretKey key = kg.generateKey();
byte[] encoded = key.getEncoded(); byte[] encoded = key.getEncoded();
if (encoded.length != 48) { if (encoded != null) { // raw key material may be not extractable
throw new Exception("length: " + encoded.length); if (encoded.length != 48) {
} throw new Exception("length: " + encoded.length);
if ((encoded[0] != major) || (encoded[1] != minor)) { }
throw new Exception("version mismatch: " + encoded[0] + int v = versionOf(encoded[0], encoded[1]);
"." + encoded[1]); if (clientVersion != v) {
} if (serverVersion != v || clientVersion >= 0x0302) {
System.out.println("OK: " + major + "." + minor); throw new Exception(String.format(
"version mismatch: (0x%04X) rather than (0x%04X) " +
"is used in pre-master secret", v, clientVersion));
}
System.out.printf("Use compatible version (0x%04X)%n", v);
}
System.out.println("Passed, version matches!");
} else {
System.out.println("Raw key material is not extractable");
}
}
private static int versionOf(int major, int minor) {
return ((major & 0xFF) << 8) | (minor & 0xFF);
} }
} }
...@@ -472,8 +472,21 @@ public class CipherTest { ...@@ -472,8 +472,21 @@ public class CipherTest {
return false; return false;
} }
// No ECDH-capable certificate in key store. May restructure
// this in the future.
if (cipherSuite.contains("ECDHE_ECDSA") ||
cipherSuite.contains("ECDH_ECDSA") ||
cipherSuite.contains("ECDH_RSA")) {
System.out.println("Skipping unsupported test for " +
cipherSuite + " of " + protocol);
return false;
}
// skip SSLv2Hello protocol // skip SSLv2Hello protocol
if (protocol.equals("SSLv2Hello")) { //
// skip TLSv1.2 protocol, we have not implement "SunTls12Prf" and
// SunTls12RsaPremasterSecret in SunPKCS11 provider
if (protocol.equals("SSLv2Hello") || protocol.equals("TLSv1.2")) {
System.out.println("Skipping unsupported test for " + System.out.println("Skipping unsupported test for " +
cipherSuite + " of " + protocol); cipherSuite + " of " + protocol);
return false; return false;
......
/* /*
* Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 2014, 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
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
/* /*
* @test * @test
* @bug 6313675 6323647 * @bug 6313675 6323647 8028192
* @summary Verify that all ciphersuites work in FIPS mode * @summary Verify that all ciphersuites work in FIPS mode
* @library .. * @library ..
* @ignore JSSE supported cipher suites are changed with CR 6916074, * @ignore JSSE supported cipher suites are changed with CR 6916074,
...@@ -44,9 +44,13 @@ public class ClientJSSEServerJSSE extends SecmodTest { ...@@ -44,9 +44,13 @@ public class ClientJSSEServerJSSE extends SecmodTest {
return; return;
} }
if ("sparc".equals(System.getProperty("os.arch")) == false) { String arch = System.getProperty("os.arch");
// we have not updated other platforms with the proper NSS libraries yet if (!("sparc".equals(arch) || "sparcv9".equals(arch))) {
System.out.println("Test currently works only on solaris-sparc, skipping"); // we have not updated other platforms with the proper NSS
// libraries yet
System.out.println(
"Test currently works only on solaris-sparc " +
"and solaris-sparcv9. Skipping on " + arch);
return; return;
} }
......
...@@ -34,6 +34,7 @@ import java.security.Provider; ...@@ -34,6 +34,7 @@ import java.security.Provider;
import javax.crypto.KeyGenerator; import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
import java.util.Formatter;
import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec; import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
...@@ -59,27 +60,51 @@ public class TestPremaster extends PKCS11Test { ...@@ -59,27 +60,51 @@ public class TestPremaster extends PKCS11Test {
System.out.println("OK: " + e); System.out.println("OK: " + e);
} }
test(kg, 3, 0); int[] protocolVersions = {0x0300, 0x0301, 0x0302, 0x0400};
test(kg, 3, 1); for (int clientVersion : protocolVersions) {
test(kg, 3, 2); for (int serverVersion : protocolVersions) {
test(kg, 4, 0); test(kg, clientVersion, serverVersion);
if (serverVersion >= clientVersion) {
break;
}
}
}
System.out.println("Done."); System.out.println("Done.");
} }
private static void test(KeyGenerator kg, int major, int minor) private static void test(KeyGenerator kg,
throws Exception { int clientVersion, int serverVersion) throws Exception {
kg.init(new TlsRsaPremasterSecretParameterSpec(major, minor)); System.out.printf(
"Testing RSA pre-master secret key generation between " +
"client (0x%04X) and server(0x%04X)%n",
clientVersion, serverVersion);
kg.init(new TlsRsaPremasterSecretParameterSpec(
clientVersion, serverVersion));
SecretKey key = kg.generateKey(); SecretKey key = kg.generateKey();
byte[] encoded = key.getEncoded(); byte[] encoded = key.getEncoded();
if (encoded.length != 48) { if (encoded != null) { // raw key material may be not extractable
throw new Exception("length: " + encoded.length); if (encoded.length != 48) {
} throw new Exception("length: " + encoded.length);
if ((encoded[0] != major) || (encoded[1] != minor)) { }
throw new Exception("version mismatch: " + encoded[0] + int v = versionOf(encoded[0], encoded[1]);
"." + encoded[1]); if (clientVersion != v) {
} if (serverVersion != v || clientVersion >= 0x0302) {
System.out.println("OK: " + major + "." + minor); throw new Exception(String.format(
"version mismatch: (0x%04X) rather than (0x%04X) " +
"is used in pre-master secret", v, clientVersion));
}
System.out.printf("Use compatible version (0x%04X)%n", v);
}
System.out.println("Passed, version matches!");
} else {
System.out.println("Raw key material is not extractable");
}
} }
private static int versionOf(int major, int minor) {
return ((major & 0xFF) << 8) | (minor & 0xFF);
}
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册