8020424: The NSS version should be detected before running crypto tests
authorascarpino
Mon, 29 Jul 2013 13:43:24 -0700
changeset 19067 5271291b7121
parent 19066 daf668acb10e
child 19068 f2358d18923a
8020424: The NSS version should be detected before running crypto tests Reviewed-by: valeriep
jdk/test/ProblemList.txt
jdk/test/sun/security/pkcs11/KeyStore/SecretKeysBasic.java
jdk/test/sun/security/pkcs11/PKCS11Test.java
jdk/test/sun/security/pkcs11/README
jdk/test/sun/security/pkcs11/ec/ReadCertificates.java
jdk/test/sun/security/pkcs11/ec/TestCurves.java
jdk/test/sun/security/pkcs11/ec/TestECDH.java
jdk/test/sun/security/pkcs11/ec/TestECDH2.java
jdk/test/sun/security/pkcs11/ec/TestECDSA.java
jdk/test/sun/security/pkcs11/ec/TestECDSA2.java
jdk/test/sun/security/pkcs11/ec/TestECGenSpec.java
jdk/test/sun/security/pkcs11/ec/TestKeyFactory.java
--- a/jdk/test/ProblemList.txt	Fri Jul 19 11:34:33 2013 -0700
+++ b/jdk/test/ProblemList.txt	Mon Jul 29 13:43:24 2013 -0700
@@ -255,32 +255,12 @@
 
 # jdk_security
 
-# 8012971 PKCS11Test hiding exception failures
-sun/security/pkcs11/KeyStore/SecretKeysBasic.java		solaris-all
-sun/security/pkcs11/KeyStore/SecretKeysBasic.java		linux-all
-sun/security/pkcs11/ec/TestCurves.java				solaris-all
-sun/security/pkcs11/ec/TestCurves.java				linux-all
-sun/security/pkcs11/ec/TestECDH.java				solaris-all
-sun/security/pkcs11/ec/TestECDH2.java				solaris-all
-sun/security/pkcs11/ec/TestECDH2.java				linux-all
-sun/security/pkcs11/ec/TestECDSA.java				solaris-all
-sun/security/pkcs11/ec/TestECDSA.java				linux-all
-sun/security/pkcs11/ec/TestECDSA2.java				solaris-all
-sun/security/pkcs11/ec/TestECDSA2.java				linux-all
-sun/security/pkcs11/ec/TestECGenSpec.java			solaris-all
-sun/security/pkcs11/ec/TestECGenSpec.java			linux-all
-sun/security/pkcs11/ec/TestKeyFactory.java			solaris-all
-sun/security/pkcs11/ec/TestKeyFactory.java			linux-all
+# 7157786
+sun/security/pkcs11/ec/TestKeyFactory.java                      generic-all
 
 # 7164518: no PortUnreachableException on Mac
 sun/security/krb5/auto/Unreachable.java                         macosx-all
 
-# 7193793
-sun/security/pkcs11/ec/TestECDH.java				linux-all
-
-# 7198198: the test also fails on SuSE Linux
-sun/security/pkcs11/ec/ReadCertificates.java                    linux-all
-
 # 7147060
 com/sun/org/apache/xml/internal/security/transforms/ClassLoaderTest.java	generic-all
 
@@ -290,9 +270,6 @@
 sun/security/pkcs11/ec/ReadPKCS12.java                          solaris-all
 sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java            solaris-all
 
-# 8005247
-sun/security/pkcs11/ec/TestECDSA.java				solaris-all
-
 # 8009438
 sun/security/pkcs11/Secmod/AddPrivateKey.java			linux-all
 sun/security/pkcs11/Secmod/TrustAnchors.java 			linux-all
--- a/jdk/test/sun/security/pkcs11/KeyStore/SecretKeysBasic.java	Fri Jul 19 11:34:33 2013 -0700
+++ b/jdk/test/sun/security/pkcs11/KeyStore/SecretKeysBasic.java	Mon Jul 29 13:43:24 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2013 Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,16 +23,10 @@
 
 import java.io.*;
 import java.util.*;
-import java.lang.reflect.*;
-
 import java.security.*;
-import java.security.cert.*;
-import java.security.spec.*;
-import java.security.interfaces.*;
-import java.math.BigInteger;
-
 import javax.crypto.*;
 import javax.crypto.spec.*;
+import javax.xml.bind.DatatypeConverter;
 
 public class SecretKeysBasic extends PKCS11Test {
 
@@ -94,6 +88,17 @@
             SecretKey expected,
             boolean saveBeforeCheck)
             throws Exception {
+
+        // A bug in NSS 3.12 (Mozilla bug 471665) causes AES key lengths
+        // to be read incorrectly.  Checking for improper 16 byte length
+        // in key string.
+        if (isNSS(provider) && expected.getAlgorithm().equals("AES") &&
+                (getNSSVersion() >= 3.12 && getNSSVersion() <= 3.122)) {
+            System.out.println("NSS 3.12 bug returns incorrect AES key "+
+                    "length breaking key storage. Aborting...");
+            return true;
+        }
+
         if (saveBeforeCheck) {
             ks.setKeyEntry(alias, expected, null, null);
         }
@@ -127,7 +132,7 @@
         System.out.println("\tALGO=" + key.getAlgorithm());
         if (key.getFormat() != null) {
             System.out.println("\t[" + key.getFormat() + "] VALUE=" +
-                    new BigInteger(key.getEncoded()));
+                    DatatypeConverter.printHexBinary(key.getEncoded()));
         } else {
             System.out.println("\tVALUE=n/a");
         }
--- a/jdk/test/sun/security/pkcs11/PKCS11Test.java	Fri Jul 19 11:34:33 2013 -0700
+++ b/jdk/test/sun/security/pkcs11/PKCS11Test.java	Mon Jul 29 13:43:24 2013 -0700
@@ -54,6 +54,11 @@
 
     static String NSPR_PREFIX = "";
 
+    // NSS version info
+    public static enum ECCState { None, Basic, Extended };
+    static double nss_version = -1;
+    static ECCState nss_ecc_status = ECCState.Extended;
+
     // The NSS library we need to search for in getNSSLibDir()
     // Default is "libsoftokn3.so", listed as "softokn3"
     // The other is "libnss3.so", listed as "nss3".
@@ -217,6 +222,104 @@
         return true;
     }
 
+    // Check the provider being used is NSS
+    public static boolean isNSS(Provider p) {
+        return p.getName().toUpperCase().equals("SUNPKCS11-NSS");
+    }
+
+    static double getNSSVersion() {
+        if (nss_version == -1)
+            getNSSInfo();
+        return nss_version;
+    }
+
+    static ECCState getNSSECC() {
+        if (nss_version == -1)
+            getNSSInfo();
+        return nss_ecc_status;
+    }
+
+    /* Read the library to find out the verison */
+    static void getNSSInfo() {
+        String nssHeader = "$Header: NSS";
+        boolean found = false;
+        String s = null;
+        int i = 0;
+        String libfile = "";
+
+        try {
+            libfile = getNSSLibDir() + System.mapLibraryName(nss_library);
+            FileInputStream is = new FileInputStream(libfile);
+            byte[] data = new byte[1000];
+            int read = 0;
+
+            while (is.available() > 0) {
+                if (read == 0) {
+                    read = is.read(data, 0, 1000);
+                } else {
+                    // Prepend last 100 bytes in case the header was split
+                    // between the reads.
+                    System.arraycopy(data, 900, data, 0, 100);
+                    read = 100 + is.read(data, 100, 900);
+                }
+
+                s = new String(data, 0, read);
+                if ((i = s.indexOf(nssHeader)) > 0) {
+                    found = true;
+                    // If the nssHeader is before 920 we can break, otherwise
+                    // we may not have the whole header so do another read.  If
+                    // no bytes are in the stream, that is ok, found is true.
+                    if (i < 920) {
+                        break;
+                    }
+                }
+            }
+
+            is.close();
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        if (!found) {
+            System.out.println("NSS version not found, set to 0.0: "+libfile);
+            nss_version = 0.0;
+            return;
+        }
+
+        // the index after whitespace after nssHeader
+        int afterheader = s.indexOf("NSS", i) + 4;
+        String version = s.substring(afterheader, s.indexOf(' ', afterheader));
+
+        // If a "dot dot" release, strip the extra dots for double parsing
+        String[] dot = version.split("\\.");
+        if (dot.length > 2) {
+            version = dot[0]+"."+dot[1];
+            for (int j = 2; dot.length > j; j++) {
+                version += dot[j];
+            }
+        }
+
+        // Convert to double for easier version value checking
+        try {
+            nss_version = Double.parseDouble(version);
+        } catch (NumberFormatException e) {
+            System.out.println("Failed to parse NSS version. Set to 0.0");
+            e.printStackTrace();
+        }
+
+        System.out.print("NSS version = "+version+".  ");
+
+        // Check for ECC
+        if (s.indexOf("Basic") > 0) {
+            nss_ecc_status = ECCState.Basic;
+            System.out.println("ECC Basic.");
+        } else if (s.indexOf("Extended") > 0) {
+            nss_ecc_status = ECCState.Extended;
+            System.out.println("ECC Extended.");
+        }
+    }
+
     // Used to set the nss_library file to search for libsoftokn3.so
     public static void useNSS() {
         nss_library = "nss3";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/pkcs11/README	Mon Jul 29 13:43:24 2013 -0700
@@ -0,0 +1,22 @@
+This README is to keep a list facts and known workaround for the pkcs11 java tests
+perform as a result of bugs or features in NSS or other pkcs11 libraries.
+
+- NSS ECC None/Basic/Extended
+The tests detect the NSS library support for Elliptic Curves as to not
+report incorrect failures.  PKCS11 reports back CKR_DOMAIN_PARAMS_INVALID
+when the curve is not supported.
+
+- Default libsoftokn3.so
+By default PKCS11Test.java will look for libsoftokn3.so.  There are a number of
+tests, particularly in Secmod, that need libnss3.so.  The method useNSS() in
+PKCS11test.java is to change the search and version checking to libnss3.
+
+ECC Basic supports is secp256r1, secp384r1, and secp521r1.
+
+- A bug in NSS 3.12 (Mozilla bug 471665) causes AES key lengths to be
+read incorrectly. KeyStore/SecretKeysBasic.java tiggers this bug and
+knows to avoid it.
+
+- A number of EC tests fail because of a DER bug in NSS 3.11.  The best guess
+is Mozilla bug 480280.  Those tests that abort execution with a PASS result
+are:  TestECDH2, TestECDSA, TestECDSA2 and TestECGenSpec.
--- a/jdk/test/sun/security/pkcs11/ec/ReadCertificates.java	Fri Jul 19 11:34:33 2013 -0700
+++ b/jdk/test/sun/security/pkcs11/ec/ReadCertificates.java	Mon Jul 29 13:43:24 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -113,6 +113,20 @@
                 System.out.println("Warning: " + e.getMessage() +
                 ". Trying another provider...");
                 cert.verify(key);
+            } catch (InvalidKeyException e) {
+                // The root cause of the exception might be NSS not having
+                // "ECC Extended" support curves.  If so, we can ignore it.
+                Throwable t = e;
+                while (t.getCause() != null) {
+                    t = t.getCause();
+                }
+                if (t instanceof sun.security.pkcs11.wrapper.PKCS11Exception &&
+                        t.getMessage().equals("CKR_DOMAIN_PARAMS_INVALID") &&
+                        isNSS(p) && getNSSECC() == ECCState.Basic) {
+                    System.out.println("Failed as expected. NSS Basic ECC.");
+                    continue;
+                }
+                throw e;
             }
         }
 
--- a/jdk/test/sun/security/pkcs11/ec/TestCurves.java	Fri Jul 19 11:34:33 2013 -0700
+++ b/jdk/test/sun/security/pkcs11/ec/TestCurves.java	Mon Jul 29 13:43:24 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -50,6 +50,12 @@
             return;
         }
 
+        if (isNSS(p) && getNSSVersion() >= 3.11 && getNSSVersion() < 3.12) {
+            System.out.println("NSS 3.11 has a DER issue that recent " +
+                    "version do not.");
+            return;
+        }
+
         Random random = new Random();
         byte[] data = new byte[2048];
         random.nextBytes(data);
@@ -61,8 +67,29 @@
             KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", p);
             kpg.initialize(params);
             KeyPair kp1, kp2;
-            kp1 = kpg.generateKeyPair();
-            kp2 = kpg.generateKeyPair();
+
+            try {
+                kp1 = kpg.generateKeyPair();
+                kp2 = kpg.generateKeyPair();
+            } catch (Exception e) {
+                // The root cause of the exception might be NSS not having
+                // "ECC Extended" support curves.  If so, we can ignore it.
+                if (e instanceof java.security.ProviderException) {
+                    Throwable t = e.getCause();
+                    if (t instanceof
+                            sun.security.pkcs11.wrapper.PKCS11Exception &&
+                            t.getMessage().equals("CKR_DOMAIN_PARAMS_INVALID") &&
+                            isNSS(p) && (getNSSECC() == ECCState.Basic) &&
+                            (!params.toString().startsWith("secp256r1") &&
+                            !params.toString().startsWith("secp384r1") &&
+                            !params.toString().startsWith("secp521r1"))) {
+                        System.out.println("NSS Basic ECC.  Failure expected");
+                        continue;
+                    }
+                }
+
+                throw e;
+            }
 
             testSigning(p, "SHA1withECDSA", data, kp1, kp2);
             testSigning(p, "SHA224withECDSA", data, kp1, kp2);
@@ -97,8 +124,9 @@
         int end;
         String curve;
         Vector<ECParameterSpec> results = new Vector<ECParameterSpec>();
-        String kcProp =
-            p.getProperty("AlgorithmParameters.EC SupportedCurves");
+        // Get Curves to test from SunEC.
+        String kcProp = Security.getProvider("SunEC").
+                getProperty("AlgorithmParameters.EC SupportedCurves");
 
         if (kcProp == null) {
             throw new RuntimeException(
--- a/jdk/test/sun/security/pkcs11/ec/TestECDH.java	Fri Jul 19 11:34:33 2013 -0700
+++ b/jdk/test/sun/security/pkcs11/ec/TestECDH.java	Mon Jul 29 13:43:24 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -61,6 +61,11 @@
             return;
         }
 
+        if (isNSS(p) && getNSSECC() == ECCState.Basic) {
+            System.out.println("NSS only supports Basic ECC.  Skipping..");
+            return;
+        }
+
         /*
          * PKCS11Test.main will remove this provider if needed
          */
--- a/jdk/test/sun/security/pkcs11/ec/TestECDH2.java	Fri Jul 19 11:34:33 2013 -0700
+++ b/jdk/test/sun/security/pkcs11/ec/TestECDH2.java	Mon Jul 29 13:43:24 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -106,6 +106,13 @@
             return;
         }
 
+        if (isNSS(provider) && getNSSVersion() >= 3.11 &&
+                getNSSVersion() < 3.12) {
+            System.out.println("NSS 3.11 has a DER issue that recent " +
+                    "version do not.");
+            return;
+        }
+
         kf = KeyFactory.getInstance("EC", provider);
         kpg = KeyPairGenerator.getInstance("EC", provider);
 
--- a/jdk/test/sun/security/pkcs11/ec/TestECDSA.java	Fri Jul 19 11:34:33 2013 -0700
+++ b/jdk/test/sun/security/pkcs11/ec/TestECDSA.java	Mon Jul 29 13:43:24 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,9 +30,7 @@
  * @library ../../../../java/security/testlibrary
  */
 
-import java.io.*;
 import java.util.*;
-import java.math.BigInteger;
 
 import java.security.*;
 import java.security.spec.*;
@@ -117,6 +115,13 @@
             return;
         }
 
+        if (isNSS(provider) && getNSSVersion() >= 3.11 &&
+                getNSSVersion() < 3.12) {
+            System.out.println("NSS 3.11 has a DER issue that recent " +
+                    "version do not.");
+            return;
+        }
+
         /*
          * PKCS11Test.main will remove this provider if needed
          */
@@ -136,10 +141,14 @@
             return;
         }
 
-        test(provider, pub192, priv192, sig192);
-        test(provider, pub163, priv163, sig163);
+        if (getNSSECC() != ECCState.Basic) {
+            test(provider, pub192, priv192, sig192);
+            test(provider, pub163, priv163, sig163);
+            test(provider, pub571, priv571, sig571);
+        } else {
+            System.out.println("ECC Basic only, skipping 192, 163 and 571.");
+        }
         test(provider, pub521, priv521, sig521);
-        test(provider, pub571, priv571, sig571);
 
         long stop = System.currentTimeMillis();
         System.out.println("All tests passed (" + (stop - start) + " ms).");
--- a/jdk/test/sun/security/pkcs11/ec/TestECDSA2.java	Fri Jul 19 11:34:33 2013 -0700
+++ b/jdk/test/sun/security/pkcs11/ec/TestECDSA2.java	Mon Jul 29 13:43:24 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -104,6 +104,13 @@
             return;
         }
 
+        if (isNSS(provider) && getNSSVersion() >= 3.11 &&
+                getNSSVersion() < 3.12) {
+            System.out.println("NSS 3.11 has a DER issue that recent " +
+                    "version do not.");
+            return;
+        }
+
         kf = KeyFactory.getInstance("EC", provider);
 
         long start = System.currentTimeMillis();
--- a/jdk/test/sun/security/pkcs11/ec/TestECGenSpec.java	Fri Jul 19 11:34:33 2013 -0700
+++ b/jdk/test/sun/security/pkcs11/ec/TestECGenSpec.java	Mon Jul 29 13:43:24 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2013 Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -47,9 +47,20 @@
             return;
         }
 
-        String[] names = { "NIST P-192", "sect163k1", "1.3.132.0.26", "X9.62 c2tnb239v1"};
-        int[] lengths = {192, 163, 233, 239};
-        for (int i = 0; i < names.length; i++) {
+        if (isNSS(p) && getNSSVersion() >= 3.11 && getNSSVersion() < 3.12) {
+            System.out.println("NSS 3.11 has a DER issue that recent " +
+                    "version do not.");
+            return;
+        }
+
+        String[] names = { "secp256r1", "NIST P-192", "sect163k1", "1.3.132.0.26",
+            "X9.62 c2tnb239v1"};
+        int curves = 1;
+        if (getNSSECC() == ECCState.Extended) {
+            curves = names.length;
+        }
+        int[] lengths = {256, 192, 163, 233, 239};
+        for (int i = 0; i < curves; i++) {
             String name = names[i];
             int len = lengths[i];
             System.out.println("Testing " + name + "...");
--- a/jdk/test/sun/security/pkcs11/ec/TestKeyFactory.java	Fri Jul 19 11:34:33 2013 -0700
+++ b/jdk/test/sun/security/pkcs11/ec/TestKeyFactory.java	Mon Jul 29 13:43:24 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2013 Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -119,11 +119,17 @@
             System.out.println("Provider does not support EC, skipping");
             return;
         }
-        int[] keyLengths = {192, 163, 521, 409};
+        int[] keyLengths = {192, 163, 409, 521};
+        int len = 0;
+        if (getNSSECC() == ECCState.Basic) {
+            System.out.println("NSS Basic ECC only. Skipping 192, 163, & 409");
+            len = 3;
+        }
         KeyFactory kf = KeyFactory.getInstance("EC", p);
-        for (int len : keyLengths) {
+        for (; keyLengths.length > len ; len++) {
+            System.out.println("Length "+keyLengths[len]);
             KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", p);
-            kpg.initialize(len);
+            kpg.initialize(keyLengths[len]);
             KeyPair kp = kpg.generateKeyPair();
             test(kf, kp.getPrivate());
             test(kf, kp.getPublic());