diff --git a/src/share/classes/com/sun/crypto/provider/RSACipher.java b/src/share/classes/com/sun/crypto/provider/RSACipher.java index 6902d4b8b313d63dca7d18098f125082268ba556..d1d8cf3ef23abd7aa86732f78ac59aa2d936154e 100644 --- a/src/share/classes/com/sun/crypto/provider/RSACipher.java +++ b/src/share/classes/com/sun/crypto/provider/RSACipher.java @@ -1,5 +1,5 @@ /* - * 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. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,8 @@ import javax.crypto.spec.OAEPParameterSpec; import sun.security.rsa.*; 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 @@ -91,8 +93,8 @@ public final class RSACipher extends CipherSpi { // padding object private RSAPadding padding; - // cipher parameter for OAEP padding - private OAEPParameterSpec spec = null; + // cipher parameter for OAEP padding and TLS RSA premaster secret + private AlgorithmParameterSpec spec = null; // buffer for the data private byte[] buffer; @@ -110,6 +112,9 @@ public final class RSACipher extends CipherSpi { // hash algorithm for OAEP private String oaepHashAlgorithm = "SHA-1"; + // the source of randomness + private SecureRandom random; + public RSACipher() { paddingType = PAD_PKCS1; } @@ -175,7 +180,7 @@ public final class RSACipher extends CipherSpi { // see JCE spec protected AlgorithmParameters engineGetParameters() { - if (spec != null) { + if (spec != null && spec instanceof OAEPParameterSpec) { try { AlgorithmParameters params = AlgorithmParameters.getInstance("OAEP", @@ -276,8 +281,13 @@ public final class RSACipher extends CipherSpi { buffer = new byte[n]; } else if (paddingType == PAD_PKCS1) { if (params != null) { - throw new InvalidAlgorithmParameterException - ("Parameters not supported"); + if (!(params instanceof TlsRsaPremasterSecretParameterSpec)) { + 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 : RSAPadding.PAD_BLOCKTYPE_1; @@ -293,19 +303,18 @@ public final class RSACipher extends CipherSpi { throw new InvalidKeyException ("OAEP cannot be used to sign or verify signatures"); } - OAEPParameterSpec myParams; if (params != null) { if (!(params instanceof OAEPParameterSpec)) { throw new InvalidAlgorithmParameterException ("Wrong Parameters for OAEP Padding"); } - myParams = (OAEPParameterSpec) params; + spec = params; } else { - myParams = new OAEPParameterSpec(oaepHashAlgorithm, "MGF1", + spec = new OAEPParameterSpec(oaepHashAlgorithm, "MGF1", MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT); } padding = RSAPadding.getInstance(RSAPadding.PAD_OAEP_MGF1, n, - random, myParams); + random, (OAEPParameterSpec)spec); if (encrypt) { int k = padding.getMaxDataSize(); buffer = new byte[k]; @@ -420,17 +429,40 @@ public final class RSACipher extends CipherSpi { if (wrappedKey.length > buffer.length) { 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); try { - byte[] encoded = doFinal(); - return ConstructKeys.constructKey(encoded, algorithm, type); + encoded = doFinal(); } catch (BadPaddingException e) { - // should not occur - throw new InvalidKeyException("Unwrapping failed", 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 + encoded = KeyUtil.checkTlsPreMasterSecretKey( + ((TlsRsaPremasterSecretParameterSpec)spec).getClientVersion(), + ((TlsRsaPremasterSecretParameterSpec)spec).getServerVersion(), + random, encoded, (failover != null)); + } + + return ConstructKeys.constructKey(encoded, algorithm, type); } // see JCE spec @@ -438,5 +470,4 @@ public final class RSACipher extends CipherSpi { RSAKey rsaKey = RSAKeyFactory.toRSAKey(key); return rsaKey.getModulus().bitLength(); } - } diff --git a/src/share/classes/com/sun/crypto/provider/TlsRsaPremasterSecretGenerator.java b/src/share/classes/com/sun/crypto/provider/TlsRsaPremasterSecretGenerator.java index ef9098f24f750144cb7e06bf7d25122b0a6463d3..2a25cb64d5cbc279edfa038121a489086442ac38 100644 --- a/src/share/classes/com/sun/crypto/provider/TlsRsaPremasterSecretGenerator.java +++ b/src/share/classes/com/sun/crypto/provider/TlsRsaPremasterSecretGenerator.java @@ -1,5 +1,5 @@ /* - * 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. * * This code is free software; you can redistribute it and/or modify it @@ -56,7 +56,7 @@ public final class TlsRsaPremasterSecretGenerator extends KeyGeneratorSpi { protected void engineInit(AlgorithmParameterSpec params, SecureRandom random) throws InvalidAlgorithmParameterException { - if (params instanceof TlsRsaPremasterSecretParameterSpec == false) { + if (!(params instanceof TlsRsaPremasterSecretParameterSpec)) { throw new InvalidAlgorithmParameterException(MSG); } this.spec = (TlsRsaPremasterSecretParameterSpec)params; @@ -67,21 +67,20 @@ public final class TlsRsaPremasterSecretGenerator extends KeyGeneratorSpi { throw new InvalidParameterException(MSG); } + // Only can be used in client side to generate TLS RSA premaster secret. protected SecretKey engineGenerateKey() { if (spec == null) { throw new IllegalStateException( "TlsRsaPremasterSecretGenerator must be initialized"); } - 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(); + + if (random == null) { + random = new SecureRandom(); } + byte[] b = new byte[48]; + random.nextBytes(b); + b[0] = (byte)spec.getMajorVersion(); + b[1] = (byte)spec.getMinorVersion(); return new SecretKeySpec(b, "TlsRsaPremasterSecret"); } diff --git a/src/share/classes/sun/security/internal/spec/TlsRsaPremasterSecretParameterSpec.java b/src/share/classes/sun/security/internal/spec/TlsRsaPremasterSecretParameterSpec.java index a38a7faecf20f9c57bc19b4f531ce320e01c4d27..0741499b9a78674e8c9a38e86fecceea3dbc2acc 100644 --- a/src/share/classes/sun/security/internal/spec/TlsRsaPremasterSecretParameterSpec.java +++ b/src/share/classes/sun/security/internal/spec/TlsRsaPremasterSecretParameterSpec.java @@ -26,11 +26,11 @@ package sun.security.internal.spec; import java.security.spec.AlgorithmParameterSpec; +import java.security.AccessController; +import java.security.PrivilegedAction; /** - * Parameters for SSL/TLS RSA Premaster secret generation. - * This class is used by SSL/TLS client to initialize KeyGenerators of the - * type "TlsRsaPremasterSecret". + * Parameters for SSL/TLS RSA premaster secret. * *
Instances of this class are immutable.
*
@@ -43,90 +43,108 @@ import java.security.spec.AlgorithmParameterSpec;
public class TlsRsaPremasterSecretParameterSpec
implements AlgorithmParameterSpec {
- private final int majorVersion;
- private final int minorVersion;
- private final byte[] encodedSecret;
+ /*
+ * 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 =
+ AccessController.doPrivileged(new PrivilegedAction
- * 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 minorVersion the minor number of the protocol version
+ * @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.
*
- * @throws IllegalArgumentException if minorVersion or majorVersion are
- * negative or larger than 255
+ * @throws IllegalArgumentException if clientVersion or serverVersion are
+ * negative or larger than (2^16 - 1)
*/
- public TlsRsaPremasterSecretParameterSpec(int majorVersion,
- int minorVersion) {
- this.majorVersion =
- TlsMasterSecretParameterSpec.checkVersion(majorVersion);
- this.minorVersion =
- TlsMasterSecretParameterSpec.checkVersion(minorVersion);
- this.encodedSecret = null;
+ public TlsRsaPremasterSecretParameterSpec(
+ int clientVersion, int serverVersion) {
+
+ this.clientVersion = checkVersion(clientVersion);
+ this.serverVersion = checkVersion(serverVersion);
}
/**
- * Constructs a new TlsRsaPremasterSecretParameterSpec.
- *
- * 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.
- *
- * 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
+ * Returns the version of the TLS protocol by which the client wishes to
+ * communicate during this session.
*
- * @throws IllegalArgumentException if minorVersion or majorVersion are
- * negative or larger than 255, or encodedSecret is not exactly 48 bytes.
+ * @return the version of the TLS protocol in ClientHello message
*/
- 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();
+ public int getClientVersion() {
+ return clientVersion;
}
/**
- * 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() {
- return majorVersion;
+ public int getServerVersion() {
+ 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() {
- return minorVersion;
+ public int getMajorVersion() {
+ 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() {
- return encodedSecret == null ? null : encodedSecret.clone();
+ public int getMinorVersion() {
+ 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;
}
}
diff --git a/src/share/classes/sun/security/pkcs11/P11RSACipher.java b/src/share/classes/sun/security/pkcs11/P11RSACipher.java
index e2ff0fc73e465fd0badcd1e136d388311ece27c6..253b8913a825416cab32ddf948f13dec0684c8b8 100644
--- a/src/share/classes/sun/security/pkcs11/P11RSACipher.java
+++ b/src/share/classes/sun/security/pkcs11/P11RSACipher.java
@@ -37,6 +37,8 @@ import javax.crypto.spec.*;
import static sun.security.pkcs11.TemplateManager.*;
import sun.security.pkcs11.wrapper.*;
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
@@ -102,6 +104,12 @@ final class P11RSACipher extends CipherSpi {
// maximum output size. this is the length of the key
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)
throws PKCS11Exception {
super();
@@ -165,8 +173,12 @@ final class P11RSACipher extends CipherSpi {
AlgorithmParameterSpec params, SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException {
if (params != null) {
- throw new InvalidAlgorithmParameterException
- ("Parameters not supported");
+ if (!(params instanceof TlsRsaPremasterSecretParameterSpec)) {
+ throw new InvalidAlgorithmParameterException(
+ "Parameters not supported");
+ }
+ spec = params;
+ this.random = random; // for TLS RSA premaster secret
}
implInit(opmode, key);
}
@@ -176,8 +188,8 @@ final class P11RSACipher extends CipherSpi {
SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException {
if (params != null) {
- throw new InvalidAlgorithmParameterException
- ("Parameters not supported");
+ throw new InvalidAlgorithmParameterException(
+ "Parameters not supported");
}
implInit(opmode, key);
}
@@ -452,21 +464,101 @@ final class P11RSACipher extends CipherSpi {
protected Key engineUnwrap(byte[] wrappedKey, String algorithm,
int type) throws InvalidKeyException, NoSuchAlgorithmException {
- // 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");
+ boolean isTlsRsaPremasterSecret =
+ algorithm.equals("TlsRsaPremasterSecret");
+ Exception failover = null;
+
+ SecureRandom secureRandom = random;
+ if (secureRandom == null && isTlsRsaPremasterSecret) {
+ secureRandom = new SecureRandom();
}
- implUpdate(wrappedKey, 0, wrappedKey.length);
- try {
- byte[] encoded = doFinal();
+
+ // Should C_Unwrap be preferred for non-TLS RSA premaster secret?
+ 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);
- } catch (BadPaddingException e) {
- // should not occur
- throw new InvalidKeyException("Unwrapping failed", e);
- } catch (IllegalBlockSizeException e) {
- // should not occur, handled with length check above
- throw new InvalidKeyException("Unwrapping failed", e);
+ } else {
+ Session s = null;
+ SecretKey secretKey = null;
+ try {
+ 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);
+ 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 {
int n = P11KeyFactory.convertKey(token, key, algorithm).length();
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 {
diff --git a/src/share/classes/sun/security/pkcs11/P11TlsRsaPremasterSecretGenerator.java b/src/share/classes/sun/security/pkcs11/P11TlsRsaPremasterSecretGenerator.java
index ff9b183ee26427e23ab6a9415f1addf6b6f9af6b..21c853794bc8e60888d843990223cff6b232c665 100644
--- a/src/share/classes/sun/security/pkcs11/P11TlsRsaPremasterSecretGenerator.java
+++ b/src/share/classes/sun/security/pkcs11/P11TlsRsaPremasterSecretGenerator.java
@@ -73,7 +73,7 @@ final class P11TlsRsaPremasterSecretGenerator extends KeyGeneratorSpi {
protected void engineInit(AlgorithmParameterSpec params,
SecureRandom random) throws InvalidAlgorithmParameterException {
- if (params instanceof TlsRsaPremasterSecretParameterSpec == false) {
+ if (!(params instanceof TlsRsaPremasterSecretParameterSpec)) {
throw new InvalidAlgorithmParameterException(MSG);
}
this.spec = (TlsRsaPremasterSecretParameterSpec)params;
@@ -83,38 +83,32 @@ final class P11TlsRsaPremasterSecretGenerator extends KeyGeneratorSpi {
throw new InvalidParameterException(MSG);
}
+ // Only can be used in client side to generate TLS RSA premaster secret.
protected SecretKey engineGenerateKey() {
if (spec == null) {
throw new IllegalStateException
("TlsRsaPremasterSecretGenerator must be initialized");
}
- byte[] b = spec.getEncodedSecret();
- if (b == null) {
- CK_VERSION version = new CK_VERSION(
+ 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);
- }
+ 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");
}
}
diff --git a/src/share/classes/sun/security/pkcs11/Token.java b/src/share/classes/sun/security/pkcs11/Token.java
index b97ab0cc9987a0cd2fddaa3ad599af9f40f81929..39d301ae7b8ee42c0ecf8b277665304dc9b9d064 100644
--- a/src/share/classes/sun/security/pkcs11/Token.java
+++ b/src/share/classes/sun/security/pkcs11/Token.java
@@ -36,6 +36,7 @@ import javax.security.auth.login.LoginException;
import sun.security.jca.JCAUtil;
import sun.security.pkcs11.wrapper.*;
+import static sun.security.pkcs11.TemplateManager.*;
import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
/**
@@ -122,6 +123,9 @@ class Token implements Serializable {
private final static CK_MECHANISM_INFO INVALID_MECH =
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 {
this.provider = provider;
this.removable = provider.removable;
@@ -160,6 +164,36 @@ class Token implements Serializable {
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
// uses cached result if current. session is optional and may be null
boolean isLoggedIn(Session session) throws PKCS11Exception {
diff --git a/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java b/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java
index 36e4310fef1e0b46e3f612485151f0f6950a5ed0..870d3ea3d5545655cc07373d8c8a299d8f8835eb 100644
--- a/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java
+++ b/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java
@@ -48,23 +48,6 @@ import sun.security.util.KeyUtil;
*/
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
* key (or temp key from server key exchange msg) and are presented
@@ -88,22 +71,12 @@ final class RSAClientKeyExchange extends HandshakeMessage {
}
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 {
String s = ((protocolVersion.v >= ProtocolVersion.TLS12.v) ?
"SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret");
KeyGenerator kg = JsseJce.getKeyGenerator(s);
- kg.init(new TlsRsaPremasterSecretParameterSpec(major, minor),
- generator);
+ kg.init(new TlsRsaPremasterSecretParameterSpec(
+ maxVersion.v, protocolVersion.v), generator);
preMaster = kg.generateKey();
Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1);
@@ -138,18 +111,16 @@ final class RSAClientKeyExchange extends HandshakeMessage {
}
}
- Exception failover = null;
- byte[] encoded = null;
try {
Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1);
- // 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
+ cipher.init(Cipher.UNWRAP_MODE, privateKey,
+ new TlsRsaPremasterSecretParameterSpec(
+ maxVersion.v, currentVersion.v),
+ generator);
+ preMaster = (SecretKey)cipher.unwrap(encrypted,
+ "TlsRsaPremasterSecret", Cipher.SECRET_KEY);
+ } catch (InvalidKeyException ibk) {
+ // the message is too big to process with RSA
throw new SSLProtocolException(
"Unable to process PreMasterSecret, may be too big");
} catch (Exception e) {
@@ -160,124 +131,6 @@ final class RSAClientKeyExchange extends HandshakeMessage {
}
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
diff --git a/src/share/classes/sun/security/util/KeyUtil.java b/src/share/classes/sun/security/util/KeyUtil.java
index cbaa8a5e23a5ba1429526a82b8c2da6f7a7e8093..9c881b8031c662b2514d93f290441d72a772fa14 100644
--- a/src/share/classes/sun/security/util/KeyUtil.java
+++ b/src/share/classes/sun/security/util/KeyUtil.java
@@ -1,5 +1,5 @@
/*
- * 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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -32,6 +32,7 @@ import java.security.InvalidKeyException;
import java.security.interfaces.ECKey;
import java.security.interfaces.RSAKey;
import java.security.interfaces.DSAKey;
+import java.security.SecureRandom;
import java.security.spec.KeySpec;
import javax.crypto.SecretKey;
import javax.crypto.interfaces.DHKey;
@@ -156,6 +157,79 @@ public final class KeyUtil {
providerName.startsWith("SunPKCS11"));
}
+ /**
+ * Check the format of TLS PreMasterSecret.
+ *
+ * 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.
*
diff --git a/src/windows/classes/sun/security/mscapi/RSACipher.java b/src/windows/classes/sun/security/mscapi/RSACipher.java
index 7ab29629a18f35e6db0128ebf25132706e10e53d..023725b62050b94e775eef149fe028d61c6ea410 100644
--- a/src/windows/classes/sun/security/mscapi/RSACipher.java
+++ b/src/windows/classes/sun/security/mscapi/RSACipher.java
@@ -35,6 +35,8 @@ import javax.crypto.*;
import javax.crypto.spec.*;
import sun.security.rsa.RSAKeyFactory;
+import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
+import sun.security.util.KeyUtil;
/**
* RSA cipher implementation using the Microsoft Crypto API.
@@ -92,9 +94,16 @@ public final class RSACipher extends CipherSpi {
// the public key, if we were initialized using a public key
private sun.security.mscapi.Key publicKey;
+
// the private key, if we were initialized using a private key
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() {
paddingType = PAD_PKCS1;
}
@@ -155,8 +164,12 @@ public final class RSACipher extends CipherSpi {
throws InvalidKeyException, InvalidAlgorithmParameterException {
if (params != null) {
- throw new InvalidAlgorithmParameterException
- ("Parameters not supported");
+ if (!(params instanceof TlsRsaPremasterSecretParameterSpec)) {
+ throw new InvalidAlgorithmParameterException(
+ "Parameters not supported");
+ }
+ spec = params;
+ this.random = random; // for TLS RSA premaster secret
}
init(opmode, key);
}
@@ -356,39 +369,47 @@ public final class RSACipher extends CipherSpi {
}
// 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 {
if (wrappedKey.length > buffer.length) {
throw new InvalidKeyException("Key is too long for unwrapping");
}
- update(wrappedKey, 0, wrappedKey.length);
- try {
- byte[] encoding = doFinal();
-
- switch (type) {
- 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);
- }
+ boolean isTlsRsaPremasterSecret =
+ algorithm.equals("TlsRsaPremasterSecret");
+ Exception failover = null;
+ byte[] encoded = null;
+ update(wrappedKey, 0, wrappedKey.length);
+ try {
+ encoded = doFinal();
} catch (BadPaddingException e) {
- // should not occur
- throw new InvalidKeyException("Unwrapping failed", 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
+ encoded = KeyUtil.checkTlsPreMasterSecretKey(
+ ((TlsRsaPremasterSecretParameterSpec)spec).getClientVersion(),
+ ((TlsRsaPremasterSecretParameterSpec)spec).getServerVersion(),
+ random, encoded, (failover != null));
+ }
+
+ return constructKey(encoded, algorithm, type);
}
// see JCE spec
@@ -452,6 +473,22 @@ public final class RSACipher extends CipherSpi {
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.
* It expects and returns ciphertext data in big-endian form.
diff --git a/test/com/sun/crypto/provider/TLS/TestPremaster.java b/test/com/sun/crypto/provider/TLS/TestPremaster.java
index bbbfbb6bdb366d0b1a11d5ed1768bf79d9fc5f54..f19e7546ddd44f5a07f658a4397fdc311446bc37 100644
--- a/test/com/sun/crypto/provider/TLS/TestPremaster.java
+++ b/test/com/sun/crypto/provider/TLS/TestPremaster.java
@@ -33,6 +33,7 @@ import java.security.Provider;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
+import java.util.Formatter;
import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
@@ -52,27 +53,51 @@ public class TestPremaster {
System.out.println("OK: " + e);
}
- test(kg, 3, 0);
- test(kg, 3, 1);
- test(kg, 3, 2);
- test(kg, 4, 0);
+ int[] protocolVersions = {0x0300, 0x0301, 0x0302, 0x0400};
+ for (int clientVersion : protocolVersions) {
+ for (int serverVersion : protocolVersions) {
+ test(kg, clientVersion, serverVersion);
+ if (serverVersion >= clientVersion) {
+ break;
+ }
+ }
+ }
System.out.println("Done.");
}
- private static void test(KeyGenerator kg, int major, int minor)
- throws Exception {
+ private static void test(KeyGenerator kg,
+ 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();
byte[] encoded = key.getEncoded();
- if (encoded.length != 48) {
- throw new Exception("length: " + encoded.length);
- }
- if ((encoded[0] != major) || (encoded[1] != minor)) {
- throw new Exception("version mismatch: " + encoded[0] +
- "." + encoded[1]);
- }
- System.out.println("OK: " + major + "." + minor);
+ if (encoded != null) { // raw key material may be not extractable
+ if (encoded.length != 48) {
+ throw new Exception("length: " + encoded.length);
+ }
+ int v = versionOf(encoded[0], encoded[1]);
+ if (clientVersion != v) {
+ if (serverVersion != v || clientVersion >= 0x0302) {
+ 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);
}
}
diff --git a/test/sun/security/pkcs11/fips/CipherTest.java b/test/sun/security/pkcs11/fips/CipherTest.java
index e85a3a6853faee26d73cc4be967add136bda37a5..dd627d356b570b86e0c252f992a65b0271139818 100644
--- a/test/sun/security/pkcs11/fips/CipherTest.java
+++ b/test/sun/security/pkcs11/fips/CipherTest.java
@@ -472,8 +472,21 @@ public class CipherTest {
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
- 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 " +
cipherSuite + " of " + protocol);
return false;
diff --git a/test/sun/security/pkcs11/fips/ClientJSSEServerJSSE.java b/test/sun/security/pkcs11/fips/ClientJSSEServerJSSE.java
index 98dbdeea5e47cb99889f30fdee39f8a70a71d2c5..483e36f29b40d1c9bb5fcc5083991cda82b5852c 100644
--- a/test/sun/security/pkcs11/fips/ClientJSSEServerJSSE.java
+++ b/test/sun/security/pkcs11/fips/ClientJSSEServerJSSE.java
@@ -1,5 +1,5 @@
/*
- * 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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 6313675 6323647
+ * @bug 6313675 6323647 8028192
* @summary Verify that all ciphersuites work in FIPS mode
* @library ..
* @ignore JSSE supported cipher suites are changed with CR 6916074,
@@ -44,9 +44,13 @@ public class ClientJSSEServerJSSE extends SecmodTest {
return;
}
- if ("sparc".equals(System.getProperty("os.arch")) == false) {
- // we have not updated other platforms with the proper NSS libraries yet
- System.out.println("Test currently works only on solaris-sparc, skipping");
+ String arch = System.getProperty("os.arch");
+ if (!("sparc".equals(arch) || "sparcv9".equals(arch))) {
+ // 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;
}
diff --git a/test/sun/security/pkcs11/tls/TestPremaster.java b/test/sun/security/pkcs11/tls/TestPremaster.java
index f7a51041ead67f3a16a1dcdf26988d4551bf6b82..05e8efb0f2897b6890ceed151a97edbed07b797d 100644
--- a/test/sun/security/pkcs11/tls/TestPremaster.java
+++ b/test/sun/security/pkcs11/tls/TestPremaster.java
@@ -34,6 +34,7 @@ import java.security.Provider;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
+import java.util.Formatter;
import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
@@ -59,27 +60,51 @@ public class TestPremaster extends PKCS11Test {
System.out.println("OK: " + e);
}
- test(kg, 3, 0);
- test(kg, 3, 1);
- test(kg, 3, 2);
- test(kg, 4, 0);
+ int[] protocolVersions = {0x0300, 0x0301, 0x0302, 0x0400};
+ for (int clientVersion : protocolVersions) {
+ for (int serverVersion : protocolVersions) {
+ test(kg, clientVersion, serverVersion);
+ if (serverVersion >= clientVersion) {
+ break;
+ }
+ }
+ }
System.out.println("Done.");
}
- private static void test(KeyGenerator kg, int major, int minor)
- throws Exception {
+ private static void test(KeyGenerator kg,
+ 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();
byte[] encoded = key.getEncoded();
- if (encoded.length != 48) {
- throw new Exception("length: " + encoded.length);
- }
- if ((encoded[0] != major) || (encoded[1] != minor)) {
- throw new Exception("version mismatch: " + encoded[0] +
- "." + encoded[1]);
- }
- System.out.println("OK: " + major + "." + minor);
+ if (encoded != null) { // raw key material may be not extractable
+ if (encoded.length != 48) {
+ throw new Exception("length: " + encoded.length);
+ }
+ int v = versionOf(encoded[0], encoded[1]);
+ if (clientVersion != v) {
+ if (serverVersion != v || clientVersion >= 0x0302) {
+ 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);
+ }
+
}