FULL PRODUCT VERSION :
java version "1.8.0_31"
Java(TM) SE Runtime Environment (build 1.8.0_31-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.31-b07, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Linux sentinel-dev-25 2.6.32.12-0.7-default #1 SMP 2010-05-20 11:14:20 +0200 x86_64 x86_64 x86_64 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
Cannot load cacerts in java8 when FIPS is enabled.
I was able to load the same in jre7u72 builds. It shouldnt be a cacerts issue since i copied the java7 cacerts to java8 and the problem still remains. Suspecting the changes to sunpkcs11 in java8 to cause this.
Following exception is seen while loading cacerts using a test tool. The same works fine in
Exception in thread "main" java.lang.RuntimeException: java.security.NoSuchProviderException: no such provider: SunEC
at sun.security.util.ECUtil.getKeyFactory(ECUtil.java:96)
at sun.security.util.ECUtil.decodeX509ECPublicKey(ECUtil.java:102)
at sun.security.pkcs11.P11ECKeyFactory.engineGeneratePublic(P11ECKeyFactory.java:170)
at java.security.KeyFactory.generatePublic(KeyFactory.java:334)
at sun.security.x509.X509Key.buildX509Key(X509Key.java:223)
at sun.security.x509.X509Key.parse(X509Key.java:170)
at sun.security.x509.CertificateX509Key.<init>(CertificateX509Key.java:75)
at sun.security.x509.X509CertInfo.parse(X509CertInfo.java:667)
at sun.security.x509.X509CertInfo.<init>(X509CertInfo.java:167)
at sun.security.x509.X509CertImpl.parse(X509CertImpl.java:1806)
at sun.security.x509.X509CertImpl.<init>(X509CertImpl.java:195)
at sun.security.provider.X509Factory.engineGenerateCertificate(X509Factory.java:99)
at java.security.cert.CertificateFactory.generateCertificate(CertificateFactory.java:339)
at sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:747)
at sun.security.provider.JavaKeyStore$JKS.engineLoad(JavaKeyStore.java:55)
at java.security.KeyStore.load(KeyStore.java:1433)
at TestKeyStoreFIPS.main(TestKeyStoreFIPS.java:46)
Caused by: java.security.NoSuchProviderException: no such provider: SunEC
at sun.security.jca.GetInstance.getService(GetInstance.java:83)
at sun.security.jca.GetInstance.getInstance(GetInstance.java:206)
at java.security.KeyFactory.getInstance(KeyFactory.java:211)
at sun.security.util.ECUtil.getKeyFactory(ECUtil.java:94)
REGRESSION. Last worked in version 7u76
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Setup and NSS DB:
1. export LD_LIBRARY_PATH=/usr/lib64
2. mkdir /tmp/fips/nssdb
3. modutil -create -dbdir nssdb/
4. modutil -fips true -dbdir nssdb
5. modutil -changepw "NSS FIPS 140-2 Certificate DB" -dbdir nssdb
(provide a complex password like password1!)
Run the testcase provided to load cacerts. First run it using java7 and then run with java8
/tmp/java7/bin/java -Dnss.lib=/usr/lib64 -Dnss.db=/tmp/fips/nssdb -Djavax.net.ssl.keyStorePassword=password1! TestKeyStoreFIPS /tmp/jre8/lib/security/cacerts changeit
/tmp/java8/jbin/ava -Dnss.lib=/usr/lib64 -Dnss.db=/tmp/fips/nssdb -Djavax.net.ssl.keyStorePassword=password1! TestKeyStoreFIPS /tmp/jre8/lib/security/cacerts changeit
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The list of all certificates in ca certs. While running the tool, output should be following.
FIPS test success
digicertassuredidrootca : X.509
trustcenterclass2caii : X.509
thawtepremiumserverca : X.509
swisssignplatinumg2ca : X.509
swisssignsilverg2ca : X.509
thawteserverca : X.509
equifaxsecureebusinessca1 : X.509
....
ACTUAL -
FIPS test success
Exception in thread "main" java.lang.RuntimeException: java.security.NoSuchProviderException: no such provider: SunEC
at sun.security.util.ECUtil.getKeyFactory(ECUtil.java:96)
at sun.security.util.ECUtil.decodeX509ECPublicKey(ECUtil.java:102)
at sun.security.pkcs11.P11ECKeyFactory.engineGeneratePublic(P11ECKeyFactory.java:170)
at java.security.KeyFactory.generatePublic(KeyFactory.java:334)
at sun.security.x509.X509Key.buildX509Key(X509Key.java:223)
at sun.security.x509.X509Key.parse(X509Key.java:170)
at sun.security.x509.CertificateX509Key.<init>(CertificateX509Key.java:75)
at sun.security.x509.X509CertInfo.parse(X509CertInfo.java:667)
at sun.security.x509.X509CertInfo.<init>(X509CertInfo.java:167)
at sun.security.x509.X509CertImpl.parse(X509CertImpl.java:1806)
at sun.security.x509.X509CertImpl.<init>(X509CertImpl.java:195)
at sun.security.provider.X509Factory.engineGenerateCertificate(X509Factory.java:99)
at java.security.cert.CertificateFactory.generateCertificate(CertificateFactory.java:339)
at sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:747)
at sun.security.provider.JavaKeyStore$JKS.engineLoad(JavaKeyStore.java:55)
at java.security.KeyStore.load(KeyStore.java:1433)
at TestKeyStoreFIPS.main(TestKeyStoreFIPS.java:46)
Caused by: java.security.NoSuchProviderException: no such provider: SunEC
at sun.security.jca.GetInstance.getService(GetInstance.java:83)
at sun.security.jca.GetInstance.getInstance(GetInstance.java:206)
at java.security.KeyFactory.getInstance(KeyFactory.java:211)
at sun.security.util.ECUtil.getKeyFactory(ECUtil.java:94)
... 16 more
ERROR MESSAGES/STACK TRACES THAT OCCUR :
FIPS test success
Exception in thread "main" java.lang.RuntimeException: java.security.NoSuchProviderException: no such provider: SunEC
at sun.security.util.ECUtil.getKeyFactory(ECUtil.java:96)
at sun.security.util.ECUtil.decodeX509ECPublicKey(ECUtil.java:102)
at sun.security.pkcs11.P11ECKeyFactory.engineGeneratePublic(P11ECKeyFactory.java:170)
at java.security.KeyFactory.generatePublic(KeyFactory.java:334)
at sun.security.x509.X509Key.buildX509Key(X509Key.java:223)
at sun.security.x509.X509Key.parse(X509Key.java:170)
at sun.security.x509.CertificateX509Key.<init>(CertificateX509Key.java:75)
at sun.security.x509.X509CertInfo.parse(X509CertInfo.java:667)
at sun.security.x509.X509CertInfo.<init>(X509CertInfo.java:167)
at sun.security.x509.X509CertImpl.parse(X509CertImpl.java:1806)
at sun.security.x509.X509CertImpl.<init>(X509CertImpl.java:195)
at sun.security.provider.X509Factory.engineGenerateCertificate(X509Factory.java:99)
at java.security.cert.CertificateFactory.generateCertificate(CertificateFactory.java:339)
at sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:747)
at sun.security.provider.JavaKeyStore$JKS.engineLoad(JavaKeyStore.java:55)
at java.security.KeyStore.load(KeyStore.java:1433)
at TestKeyStoreFIPS.main(TestKeyStoreFIPS.java:46)
Caused by: java.security.NoSuchProviderException: no such provider: SunEC
at sun.security.jca.GetInstance.getService(GetInstance.java:83)
at sun.security.jca.GetInstance.getInstance(GetInstance.java:206)
at java.security.KeyFactory.getInstance(KeyFactory.java:211)
at sun.security.util.ECUtil.getKeyFactory(ECUtil.java:94)
... 16 more
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.security.Provider;
import java.security.Security;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import sun.security.provider.Sun;
import sun.security.rsa.SunRsaSign;
public class TestKeyStoreFIPS {
public static final String NSS_LIB_DIR_PROP = "nss.lib";
public static final String NSS_DB_DIR_PROP = "nss.db";
public static final String SUN_JSSE = "SunJSSE";
public static List<String> disabledAlgs = new ArrayList<String>();
public static final String CONFIG = "config/configuration.properties";
private static final Logger logger = Logger.getLogger(TestKeyStoreFIPS.class.getName());
/**
* @param args
*/
public static void main(String[] args) throws Exception{
if(args.length != 2){
System.out.println("Usage eg: java -Dnss.lib=/usr/lib64 -Dnss.db=/tmp/fips/nssdb -Djavax.net.ssl.keyStorePassword=password1! TestKeyStoreFIPS /tmp/jre8/lib/security/cacerts changeit");
System.exit(1);
}
enablePkcs11Jsse(System.getProperty(NSS_LIB_DIR_PROP), System.getProperty(NSS_DB_DIR_PROP));
testFips();
String file = args[0];
char[] keystorePassword = args[1].toCharArray();
FileInputStream keystoreStream = new FileInputStream(file);
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(keystoreStream, keystorePassword);
Enumeration<String> aliases = keyStore.aliases();
while(aliases.hasMoreElements()){
String alias = aliases.nextElement();
System.out.println(alias + " : " + keyStore.getCertificate(alias).getType());
}
}
private static void testFips(){
String keyPass = System.getProperty("javax.net.ssl.keyStorePassword");
KeyStore store;
try {
store = KeyStore.getInstance("PKCS11");
if (keyPass != null) {
store.load(null, keyPass.toCharArray());
} else {
store.load(null, null);
}
System.out.println("FIPS test success");
} catch (Throwable e) {
e.printStackTrace();
store = null;
System.out.println("FIPS test failed");
}
}
/**
* Configures a PKCS11 based provider and replace the existing JSSE provider
* with one configured against the newly added PKCS11 based provider.
*/
public static void enablePkcs11Jsse( String libDir, String dbDir) throws Exception {
removeAllProviders();
Provider nss = getNSSFIPSProvider( libDir, dbDir);
removeDisabledAlgos(nss);
Security.insertProviderAt(nss, 1);
Provider sunJsse = new com.sun.net.ssl.internal.ssl.Provider(nss);
removeDisabledAlgos(sunJsse);
Security.insertProviderAt(sunJsse,2);
Sun sun = new Sun();
removeDisabledAlgos(sun);
Security.insertProviderAt(sun,3);
SunRsaSign sunrsa = new SunRsaSign();
removeDisabledAlgos(sunrsa);
Security.insertProviderAt(sunrsa,4);
}
/**
* Loads and returns an instance of the NSS provider in FIPS mode
*
* @return
* @throws IOException
*/
private static Provider getNSSFIPSProvider( String libDir, String dbDir) throws Exception {
if(libDir == null || dbDir == null) {
throw new Exception(NSS_LIB_DIR_PROP + " or " + NSS_DB_DIR_PROP + " not set.");
}
Properties props = new Properties();
props.put("name", "NSSfips");
props.put("nssLibraryDirectory", libDir);
props.put("nssSecmodDirectory", dbDir);
props.put("nssModule", "fips");
props.put("nssDbMode", "readWrite");
return createProvider(props);
}
private static Provider createProvider(Properties props) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
props.store(out, null);
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
Provider ret = new sun.security.pkcs11.SunPKCS11(in);
if (logger.isLoggable(Level.FINE)) {
// Log all of the registered services
for (Map.Entry<Object, Object> entry : ret.entrySet()) {
logger.log(Level.FINE, "{0} = {1}", new Object[]{entry.getKey(), entry.getValue()});
}
}
return ret;
}
/**
* Remove all default providers except Sun and SunRsaSign
*/
private static void removeAllProviders(){
Provider[] providers = Security.getProviders();
for(Provider prov : providers){
Security.removeProvider(prov.getName());
}
}
/**
* Remove invalid algorithms
* @param provider
*/
private static void removeDisabledAlgos(Provider provider){
for(String alg : disabledAlgs){
if(provider.getProperty(alg) != null){
logger.info("Removing algorithm " + alg + " from provider " + provider);
provider.remove(alg);
}
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Replace cacerts with a dummy keystore.