8048622: Enhance tests for PKCS11 keystores with NSS
authorasmotrak
Mon, 14 Sep 2015 19:54:58 +0300
changeset 32635 d7e4ba3c2e0d
parent 32634 614f8e5859aa
child 32636 54b7d7690122
8048622: Enhance tests for PKCS11 keystores with NSS Reviewed-by: vinnie
jdk/test/sun/security/pkcs11/PKCS11Test.java
jdk/test/sun/security/pkcs11/Secmod/AddPrivateKey.java
jdk/test/sun/security/pkcs11/Secmod/AddTrustedCert.java
jdk/test/sun/security/pkcs11/Secmod/Crypto.java
jdk/test/sun/security/pkcs11/Secmod/GetPrivateKey.java
jdk/test/sun/security/pkcs11/Secmod/LoadKeystore.java
--- a/jdk/test/sun/security/pkcs11/PKCS11Test.java	Mon Sep 14 19:49:28 2015 +0300
+++ b/jdk/test/sun/security/pkcs11/PKCS11Test.java	Mon Sep 14 19:54:58 2015 +0300
@@ -33,6 +33,8 @@
 
 public abstract class PKCS11Test {
 
+    static final String PKCS11 = "PKCS11";
+
     // directory of the test source
     static final String BASE = System.getProperty("test.src", ".");
 
@@ -644,4 +646,12 @@
             return "";
         }
     }
+
+    static byte[] generateData(int length) {
+        byte data[] = new byte[length];
+        for (int i=0; i<data.length; i++) {
+            data[i] = (byte) (i % 256);
+        }
+        return data;
+    }
 }
--- a/jdk/test/sun/security/pkcs11/Secmod/AddPrivateKey.java	Mon Sep 14 19:49:28 2015 +0300
+++ b/jdk/test/sun/security/pkcs11/Secmod/AddPrivateKey.java	Mon Sep 14 19:54:58 2015 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2015, 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
@@ -28,7 +28,6 @@
  * @author Andreas Sterbenz
  * @library ..
  * @run main/othervm AddPrivateKey
- * @key randomness
  */
 
 import java.io.*;
@@ -43,6 +42,13 @@
 // all providers.
 public class AddPrivateKey extends SecmodTest {
 
+    private static final String ALIAS1 = "entry1";
+    private static final String ALIAS2 = "entry2";
+    private static final String ALIAS3 = "entry3";
+    private static final int MAX_LINE = 85;
+    private static final int DATA_LENGTH = 4096;
+    private static final byte[] DATA = generateData(DATA_LENGTH);
+
     public static void main(String[] args) throws Exception {
         if (initSecmod() == false) {
             return;
@@ -57,7 +63,7 @@
         System.out.println();
         Security.addProvider(p);
 
-        KeyStore ks = KeyStore.getInstance("PKCS11", p);
+        KeyStore ks = KeyStore.getInstance(PKCS11, p);
         ks.load(null, password);
         for (String alias : aliases(ks)) {
             System.out.println("Deleting: " + alias);
@@ -65,25 +71,28 @@
         }
 
         KeyStore jks = KeyStore.getInstance("JKS");
-        InputStream in = new FileInputStream(new File(BASE, "keystore.jks"));
-        char[] jkspass = "passphrase".toCharArray();
-        jks.load(in, jkspass);
-        List<PrivateKeyEntry> entries = new ArrayList<PrivateKeyEntry>();
-        for (String alias : Collections.list(jks.aliases())) {
-            if (jks.entryInstanceOf(alias, PrivateKeyEntry.class)) {
-                PrivateKeyEntry entry = (PrivateKeyEntry)jks.getEntry(alias, new PasswordProtection(jkspass));
-                String algorithm = entry.getPrivateKey().getAlgorithm();
-                System.out.println("-Entry " + alias + " (" + algorithm + ")");
-                if ((supportsEC == false) && algorithm.equals("EC")) {
-                    System.out.println("EC not supported by provider, skipping");
-                    continue;
-                }
-                if ((supportsEC == false) && algorithm.equals("DSA")) {
-                    System.out.println("Provider does not appear to have CKA_NETSCAPE_DB fix, skipping");
-                    continue;
-                }
-                test(p, entry);
-            } // else ignore
+        try (InputStream in = new FileInputStream(BASE + SEP + "keystore.jks")) {
+            char[] jkspass = "passphrase".toCharArray();
+            jks.load(in, jkspass);
+            for (String alias : Collections.list(jks.aliases())) {
+                if (jks.entryInstanceOf(alias, PrivateKeyEntry.class)) {
+                    PrivateKeyEntry entry = (PrivateKeyEntry)jks.getEntry(alias,
+                            new PasswordProtection(jkspass));
+                    String algorithm = entry.getPrivateKey().getAlgorithm();
+                    System.out.printf("-Entry %s (%s)%n", alias, algorithm);
+                    if ((supportsEC == false) && algorithm.equals("EC")) {
+                        System.out.println("EC not supported by provider, "
+                                + "skipping");
+                        continue;
+                    }
+                    if ((supportsEC == false) && algorithm.equals("DSA")) {
+                        System.out.println("Provider does not appear to have "
+                                + "CKA_NETSCAPE_DB fix, skipping");
+                        continue;
+                    }
+                    test(p, entry);
+                } // else ignore
+            }
         }
         System.out.println("OK");
     }
@@ -92,10 +101,6 @@
         return Collections.list(ks.aliases());
     }
 
-    private final static String ALIAS1 = "entry1";
-    private final static String ALIAS2 = "entry2";
-    private final static String ALIAS3 = "entry3";
-
     private static void test(Provider p, PrivateKeyEntry entry) throws Exception {
         PrivateKey key = entry.getPrivateKey();
         X509Certificate[] chain = (X509Certificate[])entry.getCertificateChain();
@@ -122,11 +127,8 @@
 
         PrivateKey key2 = (PrivateKey)ks.getKey(ALIAS1, null);
         System.out.println(toString(key2));
-        X509Certificate[] chain2 = (X509Certificate[])ks.getCertificateChain(ALIAS1);
-        // NSS makes token keys always sensitive, skip this check
-//      if (key.equals(key2) == false) {
-//          throw new Exception("key mismatch");
-//      }
+        X509Certificate[] chain2 =
+                (X509Certificate[]) ks.getCertificateChain(ALIAS1);
         if (Arrays.equals(chain, chain2) == false) {
             throw new Exception("chain mismatch");
         }
@@ -154,7 +156,8 @@
 
         PrivateKey key4 = (PrivateKey)ks.getKey(ALIAS2, null);
         System.out.println(toString(key4));
-        X509Certificate[] chain4 = (X509Certificate[])ks.getCertificateChain(ALIAS2);
+        X509Certificate[] chain4 = (X509Certificate[])
+                ks.getCertificateChain(ALIAS2);
         if (Arrays.equals(chain, chain4) == false) {
             throw new Exception("chain mismatch");
         }
@@ -172,7 +175,8 @@
 
         PrivateKey key5 = (PrivateKey)ks.getKey(ALIAS3, null);
         System.out.println(toString(key5));
-        X509Certificate[] chain5 = (X509Certificate[])ks.getCertificateChain(ALIAS3);
+        X509Certificate[] chain5 = (X509Certificate[])
+                ks.getCertificateChain(ALIAS3);
         if (Arrays.equals(chain, chain5) == false) {
             throw new Exception("chain mismatch");
         }
@@ -186,24 +190,22 @@
         System.out.println("OK");
     }
 
-    private final static byte[] DATA = new byte[4096];
-
-    static {
-        Random random = new Random();
-        random.nextBytes(DATA);
-    }
-
-    private static void sign(Provider p, PrivateKey privateKey, PublicKey publicKey) throws Exception {
+    private static void sign(Provider p, PrivateKey privateKey,
+            PublicKey publicKey) throws Exception {
         String keyAlg = privateKey.getAlgorithm();
         String alg;
-        if (keyAlg.equals("RSA")) {
-            alg = "SHA1withRSA";
-        } else if (keyAlg.equals("DSA")) {
-            alg = "SHA1withDSA";
-        } else if (keyAlg.equals("EC")) {
-            alg = "SHA1withECDSA";
-        } else {
-            throw new Exception("Unknown algorithm " + keyAlg);
+        switch (keyAlg) {
+            case "RSA":
+                alg = "SHA1withRSA";
+                break;
+            case "DSA":
+                alg = "SHA1withDSA";
+                break;
+            case "EC":
+                alg = "SHA1withECDSA";
+                break;
+            default:
+                throw new Exception("Unknown algorithm " + keyAlg);
         }
         Signature s = Signature.getInstance(alg, p);
         s.initSign(privateKey);
@@ -217,8 +219,6 @@
         }
     }
 
-    private final static int MAX_LINE = 85;
-
     private static String toString(Object o) {
         String s = String.valueOf(o).split("\n")[0];
         return (s.length() <= MAX_LINE) ? s : s.substring(0, MAX_LINE);
--- a/jdk/test/sun/security/pkcs11/Secmod/AddTrustedCert.java	Mon Sep 14 19:49:28 2015 +0300
+++ b/jdk/test/sun/security/pkcs11/Secmod/AddTrustedCert.java	Mon Sep 14 19:54:58 2015 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, 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
@@ -44,29 +44,47 @@
             return;
         }
 
-        InputStream in = new FileInputStream(BASE + SEP + "anchor.cer");
-        CertificateFactory factory = CertificateFactory.getInstance("X.509");
-        X509Certificate cert = (X509Certificate)factory.generateCertificate(in);
-        in.close();
-//      System.out.println(cert);
+        X509Certificate cert;
+        try (InputStream in = new FileInputStream(BASE + SEP + "anchor.cer")) {
+            CertificateFactory factory =
+                    CertificateFactory.getInstance("X.509");
+            cert = (X509Certificate)factory.generateCertificate(in);
+        }
 
         String configName = BASE + SEP + "nss.cfg";
         Provider p = getSunPKCS11(configName);
 
         System.out.println(p);
         Security.addProvider(p);
-        KeyStore ks = KeyStore.getInstance("PKCS11", p);
+        KeyStore ks = KeyStore.getInstance(PKCS11, p);
         ks.load(null, password);
-        Collection<String> aliases = new TreeSet<String>(Collections.list(ks.aliases()));
+        Collection<String> aliases = new TreeSet<>(Collections.list(
+                ks.aliases()));
         System.out.println("entries: " + aliases.size());
         System.out.println(aliases);
         int size1 = aliases.size();
 
         String alias = "anchor";
-        ks.setCertificateEntry(alias, cert);
+        if (ks.containsAlias(alias)) {
+            throw new Exception("Alias exists: " + alias);
+        }
+
         ks.setCertificateEntry(alias, cert);
+        KeyStore.Entry first = ks.getEntry(alias, null);
+        System.out.println("first entry = " + first);
+        if (!ks.entryInstanceOf(alias, TrustedCertificateEntry.class)) {
+            throw new Exception("Unexpected first entry type: " + first);
+        }
 
-        aliases = new TreeSet<String>(Collections.list(ks.aliases()));
+        ks.setCertificateEntry(alias, cert);
+        KeyStore.Entry second = ks.getEntry(alias, null);
+        System.out.println("second entry = " + second);
+        if (!ks.entryInstanceOf(alias, TrustedCertificateEntry.class)) {
+            throw new Exception("Unexpected second entry type: "
+                    + second);
+        }
+
+        aliases = new TreeSet<>(Collections.list(ks.aliases()));
         System.out.println("entries: " + aliases.size());
         System.out.println(aliases);
         int size2 = aliases.size();
@@ -79,8 +97,12 @@
             throw new Exception("KeyStore returned incorrect certificate");
         }
 
+        ks.deleteEntry(alias);
+        if (ks.containsAlias(alias)) {
+            throw new Exception("Alias still exists: " + alias);
+        }
+
         System.out.println("OK");
-
     }
 
 }
--- a/jdk/test/sun/security/pkcs11/Secmod/Crypto.java	Mon Sep 14 19:49:28 2015 +0300
+++ b/jdk/test/sun/security/pkcs11/Secmod/Crypto.java	Mon Sep 14 19:54:58 2015 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, 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
@@ -28,11 +28,8 @@
  * @author Andreas Sterbenz
  * @library ..
  * @run main/othervm Crypto
- * @key randomness
  */
 
-import java.util.*;
-
 import java.security.*;
 
 public class Crypto extends SecmodTest {
@@ -51,9 +48,7 @@
         System.out.println(kp.getPublic());
         System.out.println(kp.getPrivate());
 
-        SecureRandom random = new SecureRandom();
-        byte[] data = new byte[2048];
-        random.nextBytes(data);
+        byte[] data = generateData(2048);
 
         Signature sig = Signature.getInstance("SHA1withRSA", p);
         sig.initSign(kp.getPrivate());
--- a/jdk/test/sun/security/pkcs11/Secmod/GetPrivateKey.java	Mon Sep 14 19:49:28 2015 +0300
+++ b/jdk/test/sun/security/pkcs11/Secmod/GetPrivateKey.java	Mon Sep 14 19:54:58 2015 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, 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
@@ -24,11 +24,11 @@
 /**
  * @test
  * @bug 6273877 6322208 6275523
- * @summary make sure we can access the NSS softtoken KeyStore and use a private key
+ * @summary make sure we can access the NSS softtoken KeyStore
+ *          and use a private key
  * @author Andreas Sterbenz
  * @library ..
  * @run main/othervm GetPrivateKey
- * @key randomness
  */
 
 import java.util.*;
@@ -49,18 +49,17 @@
 
         System.out.println(p);
         Security.addProvider(p);
-        KeyStore ks = KeyStore.getInstance("PKCS11", p);
+        KeyStore ks = KeyStore.getInstance(PKCS11, p);
         ks.load(null, password);
-        Collection<String> aliases = new TreeSet<String>(Collections.list(ks.aliases()));
+        Collection<String> aliases = new TreeSet<>(
+                Collections.list(ks.aliases()));
         System.out.println("entries: " + aliases.size());
         System.out.println(aliases);
 
         PrivateKey privateKey = (PrivateKey)ks.getKey(keyAlias, password);
         System.out.println(privateKey);
 
-        byte[] data = new byte[1024];
-        Random random = new Random();
-        random.nextBytes(data);
+        byte[] data = generateData(1024);
 
         System.out.println("Signing...");
         Signature signature = Signature.getInstance("MD5withRSA");
@@ -68,7 +67,8 @@
         signature.update(data);
         byte[] sig = signature.sign();
 
-        X509Certificate[] chain = (X509Certificate[])ks.getCertificateChain(keyAlias);
+        X509Certificate[] chain =
+                (X509Certificate[]) ks.getCertificateChain(keyAlias);
         signature.initVerify(chain[0].getPublicKey());
         signature.update(data);
         boolean ok = signature.verify(sig);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/pkcs11/Secmod/LoadKeystore.java	Mon Sep 14 19:54:58 2015 +0300
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2015, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.Provider;
+import java.security.Security;
+import java.security.UnrecoverableKeyException;
+import java.util.Collections;
+
+/*
+ * @test
+ * @bug 8048622 8134232
+ * @summary Checks that PKCS#11 keystore can't be loaded with wrong password
+ * @library ../
+ * @run main/othervm LoadKeystore
+ */
+public class LoadKeystore extends SecmodTest {
+
+    public static void main(String[] args) throws Exception {
+        if (!initSecmod()) {
+            return;
+        }
+
+        String configName = BASE + SEP + "nss.cfg";
+        Provider p = getSunPKCS11(configName);
+
+        System.out.println("Add provider " + p);
+        System.out.println();
+        Security.addProvider(p);
+
+        try {
+            System.out.println("Load keystore with wrong type");
+            KeyStore.getInstance("unknown", p);
+            throw new RuntimeException("Expected exception not thrown");
+        } catch(KeyStoreException e) {
+            System.out.println("Expected exception: " + e);
+        }
+
+        KeyStore ks = KeyStore.getInstance("PKCS11", p);
+        if (!"PKCS11".equals(ks.getType())) {
+            throw new RuntimeException("Unexpected keystore type: "
+                    + ks.getType());
+        }
+        if (!p.equals(ks.getProvider())) {
+            throw new RuntimeException("Unexpected keystore provider: "
+                    + ks.getProvider());
+        }
+
+        try {
+            System.out.println("Load keystore with wrong password");
+            ks.load(null, "wrong".toCharArray());
+            throw new RuntimeException("Expected exception not thrown");
+        } catch(IOException e) {
+            System.out.println("Expected exception: " + e);
+            Throwable cause = e.getCause();
+            if (!(cause instanceof UnrecoverableKeyException)) {
+                e.printStackTrace(System.out);
+                throw new RuntimeException("Unexpected cause: " + cause);
+            }
+            System.out.println("Expected cause: " + cause);
+        }
+
+        System.out.println("Load keystore with correct password");
+        ks.load(null, password);
+        for (String alias : Collections.list(ks.aliases())) {
+            System.out.println("Alias: " + alias);
+        }
+
+        System.out.println("Test passed");
+    }
+
+}