changeset 11789:25934d0d38fe jdk8u101-b03

Merge
author asaha
date Sat, 21 May 2016 23:38:15 -0700
parents 0c3ed12cdaf5 (current diff) 1d33a3a732dd (diff)
children ebc56c2e8035
files .hgtags
diffstat 7 files changed, 322 insertions(+), 159 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Fri Apr 08 01:05:28 2016 +0300
+++ b/.hgtags	Sat May 21 23:38:15 2016 -0700
@@ -567,6 +567,7 @@
 f08584a0fde9344b0aa4766984266ca68b9a5018 jdk8u77-b01
 1a3e81c05703bb36def80a57681e1692c866f621 jdk8u77-b02
 c44179bce874a97e93ffd7b76a226af417e017a4 jdk8u77-b03
+8c3f4e540348daed7263bae092b0e5f212478b00 jdk8u77-b31
 71f59a00df6c8f3bd5c6d6631a4988a431adab56 jdk8u91-b00
 7ade7a1ab10ff893f62cce9440b4a839aa19c250 jdk8u91-b13
 f8725698a870b6be82fad578e78a55910b259975 jdk8u91-b14
@@ -586,6 +587,7 @@
 ea965fea71f612d65013192aa637d88e05915b10 jdk8u92-b00
 cc8d0d6c6f9543120836e70e0aa3fa9c9b6fe0f3 jdk8u92-b13
 4f06a20cdc59ce9742e6538ff4b9040baba0778a jdk8u92-b14
+5875e297cfcf18304b4b062dc44fa9be312ad6e8 jdk8u92-b31
 f6cc9dbb5db5883385c91bb71ca02081220aaf3d jdk8u81-b00
 00f8f39308687cde45f23282871c46cc6c2f10b3 jdk8u101-b01
 6042757c329b1b96fa6bc931e09306794f5c50c0 jdk8u101-b02
--- a/src/windows/classes/sun/security/mscapi/KeyStore.java	Fri Apr 08 01:05:28 2016 +0300
+++ b/src/windows/classes/sun/security/mscapi/KeyStore.java	Sat May 21 23:38:15 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, 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
@@ -189,8 +189,10 @@
 
     /*
      * The keystore entries.
+     * Keys in the map are unique aliases (thus can differ from
+     * KeyEntry.getAlias())
      */
-    private Collection<KeyEntry> entries = new ArrayList<KeyEntry>();
+    private Map<String,KeyEntry> entries = new HashMap<>();
 
     /*
      * The keystore name.
@@ -250,13 +252,10 @@
         if (engineIsKeyEntry(alias) == false)
             return null;
 
-        for (KeyEntry entry : entries) {
-            if (alias.equals(entry.getAlias())) {
-                return entry.getPrivateKey();
-            }
-        }
-
-        return null;
+        KeyEntry entry = entries.get(alias);
+        return (entry == null)
+                ? null
+                : entry.getPrivateKey();
     }
 
     /**
@@ -276,15 +275,13 @@
             return null;
         }
 
-        for (KeyEntry entry : entries) {
-            if (alias.equals(entry.getAlias())) {
-                X509Certificate[] certChain = entry.getCertificateChain();
-
-                return certChain.clone();
-            }
-        }
-
-        return null;
+        KeyEntry entry = entries.get(alias);
+        X509Certificate[] certChain = (entry == null)
+                ? null
+                : entry.getCertificateChain();
+        return (certChain == null)
+                ? null
+                : certChain.clone();
     }
 
     /**
@@ -308,15 +305,13 @@
             return null;
         }
 
-        for (KeyEntry entry : entries) {
-            if (alias.equals(entry.getAlias()))
-            {
-                X509Certificate[] certChain = entry.getCertificateChain();
-                return certChain.length == 0 ? null : certChain[0];
-            }
-        }
-
-        return null;
+        KeyEntry entry = entries.get(alias);
+        X509Certificate[] certChain = (entry == null)
+                ? null
+                : entry.getCertificateChain();
+        return (certChain == null || certChain.length == 0)
+                ? null
+                : certChain[0];
     }
 
     /**
@@ -380,29 +375,32 @@
 
         if (key instanceof RSAPrivateCrtKey) {
 
-            KeyEntry entry = null;
-            boolean found = false;
+            KeyEntry entry = entries.get(alias);
 
-            for (KeyEntry e : entries) {
-                if (alias.equals(e.getAlias())) {
-                    found = true;
-                    entry = e;
-                    break;
+            X509Certificate[] xchain;
+            if (chain != null) {
+                if (chain instanceof X509Certificate[]) {
+                    xchain = (X509Certificate[]) chain;
+                } else {
+                    xchain = new X509Certificate[chain.length];
+                    System.arraycopy(chain, 0, xchain, 0, chain.length);
                 }
+            } else {
+                xchain = null;
             }
 
-            if (! found) {
+            if (entry == null) {
                 entry =
                     //TODO new KeyEntry(alias, key, (X509Certificate[]) chain);
-                    new KeyEntry(alias, null, (X509Certificate[]) chain);
-                entries.add(entry);
+                    new KeyEntry(alias, null, xchain);
+                storeWithUniqueAlias(alias, entry);
             }
 
             entry.setAlias(alias);
 
             try {
                 entry.setPrivateKey((RSAPrivateCrtKey) key);
-                entry.setCertificateChain((X509Certificate[]) chain);
+                entry.setCertificateChain(xchain);
 
             } catch (CertificateException ce) {
                 throw new KeyStoreException(ce);
@@ -474,23 +472,14 @@
             // TODO - build CryptoAPI chain?
             X509Certificate[] chain =
                 new X509Certificate[]{ (X509Certificate) cert };
-            KeyEntry entry = null;
-            boolean found = false;
+            KeyEntry entry = entries.get(alias);
 
-            for (KeyEntry e : entries) {
-                if (alias.equals(e.getAlias())) {
-                    found = true;
-                    entry = e;
-                    break;
-                }
+            if (entry == null) {
+                entry =
+                    new KeyEntry(alias, null, chain);
+                storeWithUniqueAlias(alias, entry);
             }
 
-            if (! found) {
-                entry =
-                    new KeyEntry(alias, null, chain);
-                entries.add(entry);
-
-            }
             if (entry.getPrivateKey() == null) { // trusted-cert entry
                 entry.setAlias(alias);
 
@@ -522,32 +511,26 @@
             throw new KeyStoreException("alias must not be null");
         }
 
-        for (KeyEntry entry : entries) {
-            if (alias.equals(entry.getAlias())) {
+        KeyEntry entry = entries.remove(alias);
+        if (entry != null) {
+            // Get end-entity certificate and remove from system cert store
+            X509Certificate[] certChain = entry.getCertificateChain();
+            if (certChain != null) {
 
-                // Get end-entity certificate and remove from system cert store
-                X509Certificate[] certChain = entry.getCertificateChain();
-                if (certChain != null) {
+                try {
 
-                    try {
-
-                        byte[] encoding = certChain[0].getEncoded();
-                        removeCertificate(getName(), alias, encoding,
+                    byte[] encoding = certChain[0].getEncoded();
+                    removeCertificate(getName(), entry.getAlias(), encoding,
                             encoding.length);
 
-                    } catch (CertificateException e) {
-                        throw new KeyStoreException("Cannot remove entry: " +
-                            e);
-                    }
+                } catch (CertificateException e) {
+                    throw new KeyStoreException("Cannot remove entry: ", e);
                 }
-                Key privateKey = entry.getPrivateKey();
-                if (privateKey != null) {
-                    destroyKeyContainer(
-                        Key.getContainerName(privateKey.getHCryptProvider()));
-                }
-
-                entries.remove(entry);
-                break;
+            }
+            Key privateKey = entry.getPrivateKey();
+            if (privateKey != null) {
+                destroyKeyContainer(
+                    Key.getContainerName(privateKey.getHCryptProvider()));
             }
         }
     }
@@ -558,8 +541,7 @@
      * @return enumeration of the alias names
      */
     public Enumeration<String> engineAliases() {
-
-        final Iterator<KeyEntry> iter = entries.iterator();
+        final Iterator<String> iter = entries.keySet().iterator();
 
         return new Enumeration<String>()
         {
@@ -570,8 +552,7 @@
 
             public String nextElement()
             {
-                KeyEntry entry = iter.next();
-                return entry.getAlias();
+                return iter.next();
             }
         };
     }
@@ -584,15 +565,7 @@
      * @return true if the alias exists, false otherwise
      */
     public boolean engineContainsAlias(String alias) {
-        for (Enumeration<String> enumerator = engineAliases();
-            enumerator.hasMoreElements();)
-        {
-            String a = enumerator.nextElement();
-
-            if (a.equals(alias))
-                return true;
-        }
-        return false;
+        return entries.containsKey(alias);
     }
 
     /**
@@ -617,13 +590,8 @@
             return false;
         }
 
-        for (KeyEntry entry : entries) {
-            if (alias.equals(entry.getAlias())) {
-                return entry.getPrivateKey() != null;
-            }
-        }
-
-        return false;
+        KeyEntry entry = entries.get(alias);
+        return entry != null && entry.getPrivateKey() != null;
     }
 
     /**
@@ -633,15 +601,14 @@
      * @return true if the entry identified by the given alias is a
      * <i>trusted certificate entry</i>, false otherwise.
      */
-    public boolean engineIsCertificateEntry(String alias)
-    {
-        for (KeyEntry entry : entries) {
-            if (alias.equals(entry.getAlias())) {
-                return entry.getPrivateKey() == null;
-            }
+    public boolean engineIsCertificateEntry(String alias) {
+
+        if (alias == null) {
+            return false;
         }
 
-        return false;
+        KeyEntry entry = entries.get(alias);
+        return entry != null && entry.getPrivateKey() == null;
     }
 
     /**
@@ -660,9 +627,10 @@
      * @return the (alias) name of the first entry with matching certificate,
      * or null if no such entry exists in this keystore.
      */
-    public String engineGetCertificateAlias(Certificate cert)
-    {
-        for (KeyEntry entry : entries) {
+    public String engineGetCertificateAlias(Certificate cert) {
+
+        for (Map.Entry<String,KeyEntry> mapEntry : entries.entrySet()) {
+            KeyEntry entry = mapEntry.getValue();
             if (entry.certChain != null && entry.certChain[0].equals(cert)) {
                 return entry.getAlias();
             }
@@ -755,7 +723,7 @@
         try {
 
             // Load keys and/or certificate chains
-            loadKeysOrCertificateChains(getName(), entries);
+            loadKeysOrCertificateChains(getName());
 
         } catch (KeyStoreException e) {
             throw new IOException(e);
@@ -763,12 +731,31 @@
     }
 
     /**
+     * Stores the given entry into the map, making sure
+     * the alias, used as the key is unique.
+     * If the same alias already exists, it tries to append
+     * a suffix  (1), (2), etc to it until it finds a unique
+     * value.
+     */
+    private void storeWithUniqueAlias(String alias, KeyEntry entry) {
+        String uniqAlias = alias;
+        int uniqNum = 1;
+
+        while (true) {
+            if (entries.putIfAbsent(uniqAlias, entry) == null) {
+                break;
+            }
+            uniqAlias = alias + " (" + (uniqNum++) + ")";
+        }
+    }
+
+
+    /**
      * Generates a certificate chain from the collection of
      * certificates and stores the result into a key entry.
      */
     private void generateCertificateChain(String alias,
-        Collection<? extends Certificate> certCollection,
-        Collection<KeyEntry> entries)
+        Collection<? extends Certificate> certCollection)
     {
         try
         {
@@ -782,10 +769,8 @@
                 certChain[i] = (X509Certificate) iter.next();
             }
 
-            KeyEntry entry = new KeyEntry(alias, null, certChain);
-
-            // Add cert chain
-            entries.add(entry);
+            storeWithUniqueAlias(alias,
+                    new KeyEntry(alias, null, certChain));
         }
         catch (Throwable e)
         {
@@ -800,8 +785,7 @@
      */
     private void generateRSAKeyAndCertificateChain(String alias,
         long hCryptProv, long hCryptKey, int keyLength,
-        Collection<? extends Certificate> certCollection,
-        Collection<KeyEntry> entries)
+        Collection<? extends Certificate> certCollection)
     {
         try
         {
@@ -815,11 +799,9 @@
                 certChain[i] = (X509Certificate) iter.next();
             }
 
-            KeyEntry entry = new KeyEntry(alias, new RSAPrivateKey(hCryptProv,
-                hCryptKey, keyLength), certChain);
-
-            // Add cert chain
-            entries.add(entry);
+            storeWithUniqueAlias(alias, new KeyEntry(alias,
+                    new RSAPrivateKey(hCryptProv, hCryptKey, keyLength),
+                    certChain));
         }
         catch (Throwable e)
         {
@@ -876,8 +858,8 @@
      * @param name Name of keystore.
      * @param entries Collection of key/certificate.
      */
-    private native void loadKeysOrCertificateChains(String name,
-        Collection<KeyEntry> entries) throws KeyStoreException;
+    private native void loadKeysOrCertificateChains(String name)
+            throws KeyStoreException;
 
     /**
      * Stores a DER-encoded certificate into the certificate store
--- a/src/windows/native/sun/security/mscapi/security.cpp	Fri Apr 08 01:05:28 2016 +0300
+++ b/src/windows/native/sun/security/mscapi/security.cpp	Sat May 21 23:38:15 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, 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
@@ -266,7 +266,7 @@
  * Signature: (Ljava/lang/String;Ljava/util/Collection;)V
  */
 JNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_loadKeysOrCertificateChains
-  (JNIEnv *env, jobject obj, jstring jCertStoreName, jobject jCollections)
+  (JNIEnv *env, jobject obj, jstring jCertStoreName)
 {
     /**
      * Certificate in cert store has enhanced key usage extension
@@ -325,7 +325,7 @@
         // Determine method ID to generate certificate chain
         jmethodID mGenCertChain = env->GetMethodID(clazzOfThis,
                                                    "generateCertificateChain",
-                                                   "(Ljava/lang/String;Ljava/util/Collection;Ljava/util/Collection;)V");
+                                                   "(Ljava/lang/String;Ljava/util/Collection;)V");
         if (mGenCertChain == NULL) {
             __leave;
         }
@@ -333,7 +333,7 @@
         // Determine method ID to generate RSA certificate chain
         jmethodID mGenRSAKeyAndCertChain = env->GetMethodID(clazzOfThis,
                                                    "generateRSAKeyAndCertificateChain",
-                                                   "(Ljava/lang/String;JJILjava/util/Collection;Ljava/util/Collection;)V");
+                                                   "(Ljava/lang/String;JJILjava/util/Collection;)V");
         if (mGenRSAKeyAndCertChain == NULL) {
             __leave;
         }
@@ -360,38 +360,37 @@
             } else {
                 // Private key is available
 
-            BOOL bGetUserKey = ::CryptGetUserKey(hCryptProv, dwKeySpec, &hUserKey);
+                BOOL bGetUserKey = ::CryptGetUserKey(hCryptProv, dwKeySpec, &hUserKey);
 
-            // Skip certificate if cannot find private key
-            if (bGetUserKey == FALSE)
-            {
-                if (bCallerFreeProv)
-                    ::CryptReleaseContext(hCryptProv, NULL);
+                // Skip certificate if cannot find private key
+                if (bGetUserKey == FALSE)
+                {
+                    if (bCallerFreeProv)
+                        ::CryptReleaseContext(hCryptProv, NULL);
 
-                continue;
-            }
+                    continue;
+                }
 
-            // Set cipher mode to ECB
-            DWORD dwCipherMode = CRYPT_MODE_ECB;
-            ::CryptSetKeyParam(hUserKey, KP_MODE, (BYTE*)&dwCipherMode, NULL);
+                // Set cipher mode to ECB
+                DWORD dwCipherMode = CRYPT_MODE_ECB;
+                ::CryptSetKeyParam(hUserKey, KP_MODE, (BYTE*)&dwCipherMode, NULL);
 
 
-            // If the private key is present in smart card, we may not be able to
-            // determine the key length by using the private key handle. However,
-            // since public/private key pairs must have the same length, we could
-            // determine the key length of the private key by using the public key
-            // in the certificate.
-            dwPublicKeyLength = ::CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
-                                                               &(pCertContext->pCertInfo->SubjectPublicKeyInfo));
+                // If the private key is present in smart card, we may not be able to
+                // determine the key length by using the private key handle. However,
+                // since public/private key pairs must have the same length, we could
+                // determine the key length of the private key by using the public key
+                // in the certificate.
+                dwPublicKeyLength = ::CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+                        &(pCertContext->pCertInfo->SubjectPublicKeyInfo));
 
-}
+            }
             PCCERT_CHAIN_CONTEXT pCertChainContext = NULL;
 
             // Build certificate chain by using system certificate store.
             // Add cert chain into collection for any key usage.
             //
-            if (GetCertificateChain(OID_EKU_ANY, pCertContext,
-                &pCertChainContext))
+            if (GetCertificateChain(OID_EKU_ANY, pCertContext, &pCertChainContext))
             {
 
                 for (unsigned int i=0; i < pCertChainContext->cChain; i++)
@@ -450,26 +449,26 @@
                         // collection
                         env->CallVoidMethod(obj, mGenCertChain,
                             env->NewStringUTF(pszNameString),
-                            jArrayList, jCollections);
+                            jArrayList);
                     }
                     else
                     {
-                    // Determine key type: RSA or DSA
-                    DWORD dwData = CALG_RSA_KEYX;
-                    DWORD dwSize = sizeof(DWORD);
-                    ::CryptGetKeyParam(hUserKey, KP_ALGID, (BYTE*)&dwData,
-                        &dwSize, NULL);
+                        // Determine key type: RSA or DSA
+                        DWORD dwData = CALG_RSA_KEYX;
+                        DWORD dwSize = sizeof(DWORD);
+                        ::CryptGetKeyParam(hUserKey, KP_ALGID, (BYTE*)&dwData,
+                                &dwSize, NULL);
 
-                    if ((dwData & ALG_TYPE_RSA) == ALG_TYPE_RSA)
-                    {
-                        // Generate RSA certificate chain and store into cert
-                        // chain collection
-                        env->CallVoidMethod(obj, mGenRSAKeyAndCertChain,
-                            env->NewStringUTF(pszNameString),
-                            (jlong) hCryptProv, (jlong) hUserKey,
-                            dwPublicKeyLength, jArrayList, jCollections);
+                        if ((dwData & ALG_TYPE_RSA) == ALG_TYPE_RSA)
+                        {
+                            // Generate RSA certificate chain and store into cert
+                            // chain collection
+                            env->CallVoidMethod(obj, mGenRSAKeyAndCertChain,
+                                    env->NewStringUTF(pszNameString),
+                                    (jlong) hCryptProv, (jlong) hUserKey,
+                                    dwPublicKeyLength, jArrayList);
+                        }
                     }
-}
                 }
 
                 // Free cert chain
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/mscapi/CastError.java	Sat May 21 23:38:15 2016 -0700
@@ -0,0 +1,54 @@
+/*
+ * 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.File;
+import java.io.FileInputStream;
+import java.security.KeyStore;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+
+/**
+ * @test
+ * @bug 8143913
+ * @requires os.family == "windows"
+ * @summary MSCAPI keystore should accept Certificate[] in setEntry()
+ */
+
+public class CastError {
+    public static void main(String[] args) throws Exception {
+        KeyStore ks = KeyStore.getInstance("JKS");
+        FileInputStream fis = new FileInputStream(
+                new File(System.getProperty("test.src"),
+                        "../tools/jarsigner/JarSigning.keystore"));
+        ks.load(fis, "bbbbbb".toCharArray());
+
+        PrivateKey pk = (PrivateKey) ks.getKey("c", "bbbbbb".toCharArray());
+        Certificate cert = ks.getCertificate("c");
+
+        ks = KeyStore.getInstance("Windows-MY");
+        ks.load(null, null);
+
+        ks.setKeyEntry("8143913", pk, null, new Certificate[]{cert});
+        ks.deleteEntry("8143913");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/mscapi/nonUniqueAliases/NonUniqueAliases.sh	Sat May 21 23:38:15 2016 -0700
@@ -0,0 +1,100 @@
+#!/bin/sh
+
+#
+# Copyright (c) 2016, 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.
+#
+
+
+# @test
+# @ignore Uses certutil.exe that isn't guaranteed to be installed
+# @bug 6483657
+# @requires os.family == "windows"
+# @run shell NonUniqueAliases.sh
+# @summary Test "keytool -list" displays correcly same named certificates
+
+# set a few environment variables so that the shell-script can run stand-alone
+# in the source directory
+if [ "${TESTSRC}" = "" ] ; then
+   TESTSRC="."
+fi
+
+if [ "${TESTCLASSES}" = "" ] ; then
+   TESTCLASSES="."
+fi
+
+if [ "${TESTJAVA}" = "" ] ; then
+   echo "TESTJAVA not set.  Test cannot execute."
+   echo "FAILED!!!"
+   exit 1
+fi
+
+OS=`uname -s`
+case "$OS" in
+    Windows* | CYGWIN* )
+
+        # 'uname -m' does not give us enough information -
+        #  should rely on $PROCESSOR_IDENTIFIER (as is done in Defs-windows.gmk),
+        #  but JTREG does not pass this env variable when executing a shell script.
+        #
+        #  execute test program - rely on it to exit if platform unsupported
+
+        echo "removing the alias NonUniqueName if it already exists"
+        certutil -user -delstore MY NonUniqueName
+
+        echo "Importing 1st certificate into MY keystore using certutil tool"
+        certutil -user -addstore MY ${TESTSRC}/nonUniq1.pem
+
+        echo "Importing 2nd certificate into MY keystore using certutil tool"
+        certutil -user -addstore MY ${TESTSRC}/nonUniq2.pem
+
+        echo "Listing certificates with keytool"
+        ${TESTJAVA}/bin/keytool ${TESTTOOLVMOPTS} -list -storetype Windows-My
+
+        echo "Counting expected entries"
+        count0=`${TESTJAVA}/bin/keytool ${TESTTOOLVMOPTS} -list -storetype Windows-My | grep 'NonUniqueName,' | wc -l`
+
+        if [ ! $count0 = 1 ]; then
+            echo "error: unexpected number of entries ($count0) in the Windows-MY store"
+            certutil -user -delstore MY NonUniqueName
+            exit 115
+        fi
+
+        echo "Counting expected entries"
+        count1=`${TESTJAVA}/bin/keytool ${TESTTOOLVMOPTS} -list -storetype Windows-My | grep 'NonUniqueName (1),' | wc -l`
+
+        if [ ! $count1 = 1 ]; then
+            echo "error: unexpected number of entries ($count1) in the Windows-MY store"
+            certutil -user -delstore MY NonUniqueName
+            exit 116
+        fi
+
+        echo "Cleaning up"
+        certutil -user -delstore MY NonUniqueName
+
+        exit 0
+        ;;
+
+    * )
+        echo "This test is not intended for '$OS' - passing test"
+        exit 0
+        ;;
+esac
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/mscapi/nonUniqueAliases/nonUniq1.pem	Sat May 21 23:38:15 2016 -0700
@@ -0,0 +1,13 @@
+-----BEGIN CERTIFICATE-----
+MIIB/jCCAWegAwIBAgIJANy5XBGM4BSuMA0GCSqGSIb3DQEBCwUAMBgxFjAUBgNV
+BAMMDU5vblVuaXF1ZU5hbWUwHhcNMTYwNDAxMTcyMjQ0WhcNMTYwNzEwMTcyMjQ0
+WjAYMRYwFAYDVQQDDA1Ob25VbmlxdWVOYW1lMIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQDI0hlED2YFVgTaVLKWvsqB9JN9EJpUWECkB97fJwb1x99dHf0TO2p6
+HPPvkvjBiAMEZYbojCz+WpNhG1Ilu/UgKwPyHh1pL6kRcEhlS2G3i7p9SDLHWlk0
+xfdhSZERgd6ROpDnY7eaj1CTdVCSyEATs4FFyNtN9Q39jyeCU++ksQIDAQABo1Aw
+TjAdBgNVHQ4EFgQUpW/Wtw/OOTdnFTL7afIkNjuCVr8wHwYDVR0jBBgwFoAUpW/W
+tw/OOTdnFTL7afIkNjuCVr8wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOB
+gQAWC+xX1cGNNp3F6dAb5tKKJGgQwsjfrjDP0/AirWc7Im1kTCpVPT61Ayt0bHgH
+n3hGivKmO7ChQAI3QsDMDKWE98tF6afPltBOoWh2a9tPd65JSD1HfkG+Wc1IZ5gL
+8rKp1tdKTEG2A+qXRN/e6DdtMsgDrK1iPfX+rer53TC+Yg==
+-----END CERTIFICATE-----
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/mscapi/nonUniqueAliases/nonUniq2.pem	Sat May 21 23:38:15 2016 -0700
@@ -0,0 +1,13 @@
+-----BEGIN CERTIFICATE-----
+MIIB/jCCAWegAwIBAgIJAPyQune5t/SZMA0GCSqGSIb3DQEBCwUAMBgxFjAUBgNV
+BAMMDU5vblVuaXF1ZU5hbWUwHhcNMTYwNDAxMTcyMzI0WhcNMTYwNzEwMTcyMzI0
+WjAYMRYwFAYDVQQDDA1Ob25VbmlxdWVOYW1lMIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQDeSu/pPzL9hA1kjA2Rs13LpN2lNrisbYg/Vj/swGDMJnVCzS3IFQQy
+71515mru+ngrHnfPSo4FKUhZPJzET2D7CruR65SzhQ96SHGoR8rhmL41KRBKELuR
+3MoarLFziFzeIil4NZg55xp6TE/WCXRfi7HNdIgoKQGLoIhehVGN8QIDAQABo1Aw
+TjAdBgNVHQ4EFgQUxFw79pLSf5Ul3zLqi/Mc6pSxEtswHwYDVR0jBBgwFoAUxFw7
+9pLSf5Ul3zLqi/Mc6pSxEtswDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOB
+gQDPilBcFpFrjwqb+lJxDxXK992KjNUS8yFLo1DQ/LBTaoHvy/U5zxzRq+nvSaaf
+h+RIKqTwIbuBhSjrXVdJ/gzob/UlPC7IDo7FVbZwOHqTkqEum8jQEpX67hEevw9s
++reyqGhLsCtQK6uBTd2Nt9uOVCHrWNzWgQewkVYAUM5QpA==
+-----END CERTIFICATE-----