changeset 43514:0405ddec4224

Merge
author prr
date Thu, 26 Jan 2017 09:19:33 -0800
parents 7cb602dc9001 230afa43a3b5
children a089f3441356
files jdk/make/copy/Copy-jdk.crypto.token.gmk jdk/make/lib/Lib-jdk.crypto.token.gmk jdk/src/jdk.crypto.token/share/classes/module-info.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/Config.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/KeyCache.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/P11Cipher.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/P11DHKeyFactory.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/P11DSAKeyFactory.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/P11Digest.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/P11ECDHKeyAgreement.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/P11ECKeyFactory.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/P11Key.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/P11KeyAgreement.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/P11KeyFactory.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/P11KeyGenerator.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/P11KeyPairGenerator.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/P11KeyStore.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/P11Mac.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/P11RSACipher.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/P11RSAKeyFactory.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/P11SecretKeyFactory.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/P11SecureRandom.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/P11Signature.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/P11TlsMasterSecretGenerator.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/P11TlsPrfGenerator.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/P11TlsRsaPremasterSecretGenerator.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/P11Util.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/Secmod.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/Session.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/SessionManager.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/SunPKCS11.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/TemplateManager.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/Token.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/wrapper/CK_AES_CTR_PARAMS.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/wrapper/CK_ATTRIBUTE.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/wrapper/CK_CREATEMUTEX.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/wrapper/CK_C_INITIALIZE_ARGS.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/wrapper/CK_DATE.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/wrapper/CK_DESTROYMUTEX.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/wrapper/CK_ECDH1_DERIVE_PARAMS.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/wrapper/CK_ECDH2_DERIVE_PARAMS.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/wrapper/CK_INFO.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/wrapper/CK_LOCKMUTEX.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/wrapper/CK_MECHANISM.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/wrapper/CK_MECHANISM_INFO.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/wrapper/CK_NOTIFY.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/wrapper/CK_PBE_PARAMS.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/wrapper/CK_PKCS5_PBKD2_PARAMS.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/wrapper/CK_RSA_PKCS_OAEP_PARAMS.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/wrapper/CK_RSA_PKCS_PSS_PARAMS.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/wrapper/CK_SESSION_INFO.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/wrapper/CK_SLOT_INFO.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/wrapper/CK_SSL3_KEY_MAT_OUT.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/wrapper/CK_SSL3_KEY_MAT_PARAMS.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/wrapper/CK_SSL3_MASTER_KEY_DERIVE_PARAMS.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/wrapper/CK_SSL3_RANDOM_DATA.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/wrapper/CK_TLS_PRF_PARAMS.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/wrapper/CK_TOKEN_INFO.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/wrapper/CK_UNLOCKMUTEX.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/wrapper/CK_VERSION.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/wrapper/CK_X9_42_DH1_DERIVE_PARAMS.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/wrapper/CK_X9_42_DH2_DERIVE_PARAMS.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/wrapper/Constants.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/wrapper/Functions.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/wrapper/PKCS11.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/wrapper/PKCS11Constants.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/wrapper/PKCS11Exception.java jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/wrapper/PKCS11RuntimeException.java jdk/src/jdk.crypto.token/share/legal/pkcs11cryptotoken.md jdk/src/jdk.crypto.token/share/legal/pkcs11wrapper.md jdk/src/jdk.crypto.token/share/native/libj2pkcs11/j2secmod.c jdk/src/jdk.crypto.token/share/native/libj2pkcs11/j2secmod.h jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_convert.c jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_crypt.c jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_digest.c jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_dual.c jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_general.c jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_keymgmt.c jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_mutex.c jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_objmgmt.c jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_sessmgmt.c jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_sign.c jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_util.c jdk/src/jdk.crypto.token/share/native/libj2pkcs11/pkcs-11v2-20a3.h jdk/src/jdk.crypto.token/share/native/libj2pkcs11/pkcs11.h jdk/src/jdk.crypto.token/share/native/libj2pkcs11/pkcs11f.h jdk/src/jdk.crypto.token/share/native/libj2pkcs11/pkcs11t.h jdk/src/jdk.crypto.token/share/native/libj2pkcs11/pkcs11wrapper.h jdk/src/jdk.crypto.token/solaris/conf/security/sunpkcs11-solaris.cfg jdk/src/jdk.crypto.token/unix/native/libj2pkcs11/j2secmod_md.c jdk/src/jdk.crypto.token/unix/native/libj2pkcs11/j2secmod_md.h jdk/src/jdk.crypto.token/unix/native/libj2pkcs11/p11_md.c jdk/src/jdk.crypto.token/unix/native/libj2pkcs11/p11_md.h jdk/src/jdk.crypto.token/windows/native/libj2pkcs11/j2secmod_md.c jdk/src/jdk.crypto.token/windows/native/libj2pkcs11/j2secmod_md.h jdk/src/jdk.crypto.token/windows/native/libj2pkcs11/p11_md.c jdk/src/jdk.crypto.token/windows/native/libj2pkcs11/p11_md.h
diffstat 452 files changed, 43953 insertions(+), 38045 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Tue Jan 24 18:44:13 2017 +0300
+++ b/.hgtags	Thu Jan 26 09:19:33 2017 -0800
@@ -396,3 +396,4 @@
 37b95df0042ae0687324e1f7dc4a2519e230e704 jdk-9+151
 ab2c8b03c3284fcbdd157551a66f807e3a182d9b jdk-9+152
 d7034ff7f8e257e81c9f95c7785dd4eaaa3c2afc jdk-9+153
+8c70d170e62c0c58b5bc3ba666bd140399b98c9c jdk-10+0
--- a/common/bin/unshuffle_list.txt	Tue Jan 24 18:44:13 2017 +0300
+++ b/common/bin/unshuffle_list.txt	Thu Jan 26 09:19:33 2017 -0800
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2014, 2017, 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
@@ -1266,33 +1266,33 @@
 jdk/src/jdk.crypto.ec/share/native/libsunec/impl : jdk/src/share/native/sun/security/ec/impl
 jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi : jdk/src/windows/classes/sun/security/mscapi
 jdk/src/jdk.crypto.mscapi/windows/native/libsunmscapi : jdk/src/windows/native/sun/security/mscapi
-jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11 : jdk/src/share/classes/sun/security/pkcs11
-jdk/src/jdk.crypto.token/share/native/libj2pkcs11/j2secmod.c : jdk/src/share/native/sun/security/pkcs11/j2secmod.c
-jdk/src/jdk.crypto.token/share/native/libj2pkcs11/j2secmod.h : jdk/src/share/native/sun/security/pkcs11/j2secmod.h
-jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_convert.c : jdk/src/share/native/sun/security/pkcs11/wrapper/p11_convert.c
-jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_crypt.c : jdk/src/share/native/sun/security/pkcs11/wrapper/p11_crypt.c
-jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_digest.c : jdk/src/share/native/sun/security/pkcs11/wrapper/p11_digest.c
-jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_dual.c : jdk/src/share/native/sun/security/pkcs11/wrapper/p11_dual.c
-jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_general.c : jdk/src/share/native/sun/security/pkcs11/wrapper/p11_general.c
-jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_keymgmt.c : jdk/src/share/native/sun/security/pkcs11/wrapper/p11_keymgmt.c
-jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_mutex.c : jdk/src/share/native/sun/security/pkcs11/wrapper/p11_mutex.c
-jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_objmgmt.c : jdk/src/share/native/sun/security/pkcs11/wrapper/p11_objmgmt.c
-jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_sessmgmt.c : jdk/src/share/native/sun/security/pkcs11/wrapper/p11_sessmgmt.c
-jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_sign.c : jdk/src/share/native/sun/security/pkcs11/wrapper/p11_sign.c
-jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_util.c : jdk/src/share/native/sun/security/pkcs11/wrapper/p11_util.c
-jdk/src/jdk.crypto.token/share/native/libj2pkcs11/pkcs11f.h : jdk/src/share/native/sun/security/pkcs11/wrapper/pkcs11f.h
-jdk/src/jdk.crypto.token/share/native/libj2pkcs11/pkcs11.h : jdk/src/share/native/sun/security/pkcs11/wrapper/pkcs11.h
-jdk/src/jdk.crypto.token/share/native/libj2pkcs11/pkcs11t.h : jdk/src/share/native/sun/security/pkcs11/wrapper/pkcs11t.h
-jdk/src/jdk.crypto.token/share/native/libj2pkcs11/pkcs-11v2-20a3.h : jdk/src/share/native/sun/security/pkcs11/wrapper/pkcs-11v2-20a3.h
-jdk/src/jdk.crypto.token/share/native/libj2pkcs11/pkcs11wrapper.h : jdk/src/share/native/sun/security/pkcs11/wrapper/pkcs11wrapper.h
-jdk/src/jdk.crypto.token/unix/native/libj2pkcs11/j2secmod_md.c : jdk/src/solaris/native/sun/security/pkcs11/j2secmod_md.c
-jdk/src/jdk.crypto.token/unix/native/libj2pkcs11/j2secmod_md.h : jdk/src/solaris/native/sun/security/pkcs11/j2secmod_md.h
-jdk/src/jdk.crypto.token/unix/native/libj2pkcs11/p11_md.c : jdk/src/solaris/native/sun/security/pkcs11/wrapper/p11_md.c
-jdk/src/jdk.crypto.token/unix/native/libj2pkcs11/p11_md.h : jdk/src/solaris/native/sun/security/pkcs11/wrapper/p11_md.h
-jdk/src/jdk.crypto.token/windows/native/libj2pkcs11/j2secmod_md.c : jdk/src/windows/native/sun/security/pkcs11/j2secmod_md.c
-jdk/src/jdk.crypto.token/windows/native/libj2pkcs11/j2secmod_md.h : jdk/src/windows/native/sun/security/pkcs11/j2secmod_md.h
-jdk/src/jdk.crypto.token/windows/native/libj2pkcs11/p11_md.c : jdk/src/windows/native/sun/security/pkcs11/wrapper/p11_md.c
-jdk/src/jdk.crypto.token/windows/native/libj2pkcs11/p11_md.h : jdk/src/windows/native/sun/security/pkcs11/wrapper/p11_md.h
+jdk/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11 : jdk/src/share/classes/sun/security/pkcs11
+jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/j2secmod.c : jdk/src/share/native/sun/security/pkcs11/j2secmod.c
+jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/j2secmod.h : jdk/src/share/native/sun/security/pkcs11/j2secmod.h
+jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_convert.c : jdk/src/share/native/sun/security/pkcs11/wrapper/p11_convert.c
+jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_crypt.c : jdk/src/share/native/sun/security/pkcs11/wrapper/p11_crypt.c
+jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_digest.c : jdk/src/share/native/sun/security/pkcs11/wrapper/p11_digest.c
+jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_dual.c : jdk/src/share/native/sun/security/pkcs11/wrapper/p11_dual.c
+jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_general.c : jdk/src/share/native/sun/security/pkcs11/wrapper/p11_general.c
+jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_keymgmt.c : jdk/src/share/native/sun/security/pkcs11/wrapper/p11_keymgmt.c
+jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_mutex.c : jdk/src/share/native/sun/security/pkcs11/wrapper/p11_mutex.c
+jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_objmgmt.c : jdk/src/share/native/sun/security/pkcs11/wrapper/p11_objmgmt.c
+jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_sessmgmt.c : jdk/src/share/native/sun/security/pkcs11/wrapper/p11_sessmgmt.c
+jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_sign.c : jdk/src/share/native/sun/security/pkcs11/wrapper/p11_sign.c
+jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_util.c : jdk/src/share/native/sun/security/pkcs11/wrapper/p11_util.c
+jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11f.h : jdk/src/share/native/sun/security/pkcs11/wrapper/pkcs11f.h
+jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11.h : jdk/src/share/native/sun/security/pkcs11/wrapper/pkcs11.h
+jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11t.h : jdk/src/share/native/sun/security/pkcs11/wrapper/pkcs11t.h
+jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs-11v2-20a3.h : jdk/src/share/native/sun/security/pkcs11/wrapper/pkcs-11v2-20a3.h
+jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11wrapper.h : jdk/src/share/native/sun/security/pkcs11/wrapper/pkcs11wrapper.h
+jdk/src/jdk.crypto.cryptoki/unix/native/libj2pkcs11/j2secmod_md.c : jdk/src/solaris/native/sun/security/pkcs11/j2secmod_md.c
+jdk/src/jdk.crypto.cryptoki/unix/native/libj2pkcs11/j2secmod_md.h : jdk/src/solaris/native/sun/security/pkcs11/j2secmod_md.h
+jdk/src/jdk.crypto.cryptoki/unix/native/libj2pkcs11/p11_md.c : jdk/src/solaris/native/sun/security/pkcs11/wrapper/p11_md.c
+jdk/src/jdk.crypto.cryptoki/unix/native/libj2pkcs11/p11_md.h : jdk/src/solaris/native/sun/security/pkcs11/wrapper/p11_md.h
+jdk/src/jdk.crypto.cryptoki/windows/native/libj2pkcs11/j2secmod_md.c : jdk/src/windows/native/sun/security/pkcs11/j2secmod_md.c
+jdk/src/jdk.crypto.cryptoki/windows/native/libj2pkcs11/j2secmod_md.h : jdk/src/windows/native/sun/security/pkcs11/j2secmod_md.h
+jdk/src/jdk.crypto.cryptoki/windows/native/libj2pkcs11/p11_md.c : jdk/src/windows/native/sun/security/pkcs11/wrapper/p11_md.c
+jdk/src/jdk.crypto.cryptoki/windows/native/libj2pkcs11/p11_md.h : jdk/src/windows/native/sun/security/pkcs11/wrapper/p11_md.h
 jdk/src/java.desktop/macosx/native/libosx/CFileManager.m : jdk/src/macosx/native/com/apple/eio/CFileManager.m
 jdk/src/java.base/macosx/native/libosxsecurity/KeystoreImpl.m : jdk/src/macosx/native/apple/security/KeystoreImpl.m
 jdk/src/jdk.hprof.agent/share/classes/com/sun/demo/jvmti/hprof : jdk/src/share/classes/com/sun/demo/jvmti/hprof
--- a/common/nb_native/nbproject/configurations.xml	Tue Jan 24 18:44:13 2017 +0300
+++ b/common/nb_native/nbproject/configurations.xml	Thu Jan 26 09:19:33 2017 -0800
@@ -2166,7 +2166,7 @@
               </df>
             </df>
           </df>
-          <df name="jdk.crypto.token">
+          <df name="jdk.crypto.cryptoki">
             <df name="share">
               <df name="native">
                 <df name="libj2pkcs11">
@@ -29422,35 +29422,35 @@
         <cTool flags="5">
         </cTool>
       </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/j2secmod.c"
-            ex="false"
-            tool="0"
-            flavor2="3">
-        <cTool flags="5">
-        </cTool>
-      </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_convert.c"
-            ex="false"
-            tool="0"
-            flavor2="3">
-        <cTool flags="5">
-        </cTool>
-      </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_crypt.c"
-            ex="false"
-            tool="0"
-            flavor2="3">
-        <cTool flags="5">
-        </cTool>
-      </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_digest.c"
-            ex="false"
-            tool="0"
-            flavor2="3">
-        <cTool flags="5">
-        </cTool>
-      </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_dual.c"
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/j2secmod.c"
+            ex="false"
+            tool="0"
+            flavor2="3">
+        <cTool flags="5">
+        </cTool>
+      </item>
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_convert.c"
+            ex="false"
+            tool="0"
+            flavor2="3">
+        <cTool flags="5">
+        </cTool>
+      </item>
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_crypt.c"
+            ex="false"
+            tool="0"
+            flavor2="3">
+        <cTool flags="5">
+        </cTool>
+      </item>
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_digest.c"
+            ex="false"
+            tool="0"
+            flavor2="3">
+        <cTool flags="5">
+        </cTool>
+      </item>
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_dual.c"
             ex="false"
             tool="0"
             flavor2="2">
@@ -29460,63 +29460,63 @@
           </preprocessorList>
         </cTool>
       </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_general.c"
-            ex="false"
-            tool="0"
-            flavor2="3">
-        <cTool flags="5">
-        </cTool>
-      </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_keymgmt.c"
-            ex="false"
-            tool="0"
-            flavor2="3">
-        <cTool flags="5">
-        </cTool>
-      </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_mutex.c"
-            ex="false"
-            tool="0"
-            flavor2="3">
-        <cTool flags="5">
-        </cTool>
-      </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_objmgmt.c"
-            ex="false"
-            tool="0"
-            flavor2="3">
-        <cTool flags="5">
-        </cTool>
-      </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_sessmgmt.c"
-            ex="false"
-            tool="0"
-            flavor2="3">
-        <cTool flags="5">
-        </cTool>
-      </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_sign.c"
-            ex="false"
-            tool="0"
-            flavor2="3">
-        <cTool flags="5">
-        </cTool>
-      </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_util.c"
-            ex="false"
-            tool="0"
-            flavor2="3">
-        <cTool flags="5">
-        </cTool>
-      </item>
-      <item path="../../jdk/src/jdk.crypto.token/unix/native/libj2pkcs11/j2secmod_md.c"
-            ex="false"
-            tool="0"
-            flavor2="3">
-        <cTool flags="5">
-        </cTool>
-      </item>
-      <item path="../../jdk/src/jdk.crypto.token/unix/native/libj2pkcs11/p11_md.c"
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_general.c"
+            ex="false"
+            tool="0"
+            flavor2="3">
+        <cTool flags="5">
+        </cTool>
+      </item>
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_keymgmt.c"
+            ex="false"
+            tool="0"
+            flavor2="3">
+        <cTool flags="5">
+        </cTool>
+      </item>
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_mutex.c"
+            ex="false"
+            tool="0"
+            flavor2="3">
+        <cTool flags="5">
+        </cTool>
+      </item>
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_objmgmt.c"
+            ex="false"
+            tool="0"
+            flavor2="3">
+        <cTool flags="5">
+        </cTool>
+      </item>
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_sessmgmt.c"
+            ex="false"
+            tool="0"
+            flavor2="3">
+        <cTool flags="5">
+        </cTool>
+      </item>
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_sign.c"
+            ex="false"
+            tool="0"
+            flavor2="3">
+        <cTool flags="5">
+        </cTool>
+      </item>
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_util.c"
+            ex="false"
+            tool="0"
+            flavor2="3">
+        <cTool flags="5">
+        </cTool>
+      </item>
+      <item path="../../jdk/src/jdk.crypto.cryptoki/unix/native/libj2pkcs11/j2secmod_md.c"
+            ex="false"
+            tool="0"
+            flavor2="3">
+        <cTool flags="5">
+        </cTool>
+      </item>
+      <item path="../../jdk/src/jdk.crypto.cryptoki/unix/native/libj2pkcs11/p11_md.c"
             ex="false"
             tool="0"
             flavor2="3">
@@ -31752,18 +31752,18 @@
           </preprocessorList>
         </ccTool>
       </folder>
-      <folder path="0/jdk/src/jdk.crypto.token">
-        <cTool>
-          <incDir>
-            <pElem>../../jdk/src/java.base/share/native/include</pElem>
-            <pElem>../../jdk/src/java.base/macosx/native/include</pElem>
-            <pElem>../../jdk/src/java.base/unix/native/include</pElem>
-            <pElem>../../jdk/src/java.base/share/native/libjava</pElem>
-            <pElem>../../jdk/src/java.base/unix/native/libjava</pElem>
-            <pElem>../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11</pElem>
-            <pElem>../../jdk/src/jdk.crypto.token/unix/native/libj2pkcs11</pElem>
-            <pElem>../../jdk/src/java.base/macosx/native/libjava</pElem>
-            <pElem>../../build/support/headers/jdk.crypto.token</pElem>
+      <folder path="0/jdk/src/jdk.crypto.cryptoki">
+        <cTool>
+          <incDir>
+            <pElem>../../jdk/src/java.base/share/native/include</pElem>
+            <pElem>../../jdk/src/java.base/macosx/native/include</pElem>
+            <pElem>../../jdk/src/java.base/unix/native/include</pElem>
+            <pElem>../../jdk/src/java.base/share/native/libjava</pElem>
+            <pElem>../../jdk/src/java.base/unix/native/libjava</pElem>
+            <pElem>../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11</pElem>
+            <pElem>../../jdk/src/jdk.crypto.cryptoki/unix/native/libj2pkcs11</pElem>
+            <pElem>../../jdk/src/java.base/macosx/native/libjava</pElem>
+            <pElem>../../build/support/headers/jdk.crypto.cryptoki</pElem>
             <pElem>../../make</pElem>
           </incDir>
           <preprocessorList>
@@ -31772,7 +31772,7 @@
           </preprocessorList>
         </cTool>
       </folder>
-      <folder path="0/jdk/src/jdk.crypto.token/unix">
+      <folder path="0/jdk/src/jdk.crypto.cryptoki/unix">
         <cTool>
           <preprocessorList>
             <Elem>THIS_FILE="j2secmod_md.c"</Elem>
@@ -44741,14 +44741,14 @@
           </preprocessorList>
         </cTool>
       </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/j2secmod.c"
-            ex="false"
-            tool="0"
-            flavor2="0">
-        <cTool flags="4">
-        </cTool>
-      </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_convert.c"
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/j2secmod.c"
+            ex="false"
+            tool="0"
+            flavor2="0">
+        <cTool flags="4">
+        </cTool>
+      </item>
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_convert.c"
             ex="false"
             tool="0"
             flavor2="0">
@@ -44758,7 +44758,7 @@
           </preprocessorList>
         </cTool>
       </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_crypt.c"
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_crypt.c"
             ex="false"
             tool="0"
             flavor2="0">
@@ -44768,7 +44768,7 @@
           </preprocessorList>
         </cTool>
       </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_digest.c"
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_digest.c"
             ex="false"
             tool="0"
             flavor2="0">
@@ -44778,7 +44778,7 @@
           </preprocessorList>
         </cTool>
       </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_dual.c"
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_dual.c"
             ex="false"
             tool="0"
             flavor2="0">
@@ -44788,7 +44788,7 @@
           </preprocessorList>
         </cTool>
       </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_general.c"
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_general.c"
             ex="false"
             tool="0"
             flavor2="0">
@@ -44798,7 +44798,7 @@
           </preprocessorList>
         </cTool>
       </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_keymgmt.c"
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_keymgmt.c"
             ex="false"
             tool="0"
             flavor2="0">
@@ -44808,7 +44808,7 @@
           </preprocessorList>
         </cTool>
       </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_mutex.c"
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_mutex.c"
             ex="false"
             tool="0"
             flavor2="0">
@@ -44818,7 +44818,7 @@
           </preprocessorList>
         </cTool>
       </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_objmgmt.c"
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_objmgmt.c"
             ex="false"
             tool="0"
             flavor2="0">
@@ -44828,7 +44828,7 @@
           </preprocessorList>
         </cTool>
       </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_sessmgmt.c"
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_sessmgmt.c"
             ex="false"
             tool="0"
             flavor2="0">
@@ -44838,7 +44838,7 @@
           </preprocessorList>
         </cTool>
       </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_sign.c"
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_sign.c"
             ex="false"
             tool="0"
             flavor2="0">
@@ -44848,7 +44848,7 @@
           </preprocessorList>
         </cTool>
       </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_util.c"
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_util.c"
             ex="false"
             tool="0"
             flavor2="0">
@@ -44858,14 +44858,14 @@
           </preprocessorList>
         </cTool>
       </item>
-      <item path="../../jdk/src/jdk.crypto.token/unix/native/libj2pkcs11/j2secmod_md.c"
-            ex="false"
-            tool="0"
-            flavor2="0">
-        <cTool flags="4">
-        </cTool>
-      </item>
-      <item path="../../jdk/src/jdk.crypto.token/unix/native/libj2pkcs11/p11_md.c"
+      <item path="../../jdk/src/jdk.crypto.cryptoki/unix/native/libj2pkcs11/j2secmod_md.c"
+            ex="false"
+            tool="0"
+            flavor2="0">
+        <cTool flags="4">
+        </cTool>
+      </item>
+      <item path="../../jdk/src/jdk.crypto.cryptoki/unix/native/libj2pkcs11/p11_md.c"
             ex="false"
             tool="0"
             flavor2="0">
@@ -47795,18 +47795,18 @@
           </preprocessorList>
         </ccTool>
       </folder>
-      <folder path="0/jdk/src/jdk.crypto.token">
-        <cTool>
-          <incDir>
-            <pElem>../../jdk/src/java.base/share/native/include</pElem>
-            <pElem>../../jdk/src/java.base/linux/native/include</pElem>
-            <pElem>../../jdk/src/java.base/unix/native/include</pElem>
-            <pElem>../../jdk/src/java.base/share/native/libjava</pElem>
-            <pElem>../../jdk/src/java.base/unix/native/libjava</pElem>
-            <pElem>../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11</pElem>
-            <pElem>../../jdk/src/jdk.crypto.token/unix/native/libj2pkcs11</pElem>
-            <pElem>../../jdk/src/java.base/linux/native/libjava</pElem>
-            <pElem>../../build/support/headers/jdk.crypto.token</pElem>
+      <folder path="0/jdk/src/jdk.crypto.cryptoki">
+        <cTool>
+          <incDir>
+            <pElem>../../jdk/src/java.base/share/native/include</pElem>
+            <pElem>../../jdk/src/java.base/linux/native/include</pElem>
+            <pElem>../../jdk/src/java.base/unix/native/include</pElem>
+            <pElem>../../jdk/src/java.base/share/native/libjava</pElem>
+            <pElem>../../jdk/src/java.base/unix/native/libjava</pElem>
+            <pElem>../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11</pElem>
+            <pElem>../../jdk/src/jdk.crypto.cryptoki/unix/native/libj2pkcs11</pElem>
+            <pElem>../../jdk/src/java.base/linux/native/libjava</pElem>
+            <pElem>../../build/support/headers/jdk.crypto.cryptoki</pElem>
             <pElem>../../make</pElem>
           </incDir>
           <preprocessorList>
@@ -47815,7 +47815,7 @@
           </preprocessorList>
         </cTool>
       </folder>
-      <folder path="0/jdk/src/jdk.crypto.token/unix">
+      <folder path="0/jdk/src/jdk.crypto.cryptoki/unix">
         <cTool>
           <preprocessorList>
             <Elem>THIS_FILE="j2secmod_md.c"</Elem>
@@ -62728,14 +62728,14 @@
           </preprocessorList>
         </cTool>
       </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/j2secmod.c"
-            ex="false"
-            tool="0"
-            flavor2="0">
-        <cTool flags="2">
-        </cTool>
-      </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_convert.c"
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/j2secmod.c"
+            ex="false"
+            tool="0"
+            flavor2="0">
+        <cTool flags="2">
+        </cTool>
+      </item>
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_convert.c"
             ex="false"
             tool="0"
             flavor2="0">
@@ -62745,7 +62745,7 @@
           </preprocessorList>
         </cTool>
       </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_crypt.c"
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_crypt.c"
             ex="false"
             tool="0"
             flavor2="0">
@@ -62755,7 +62755,7 @@
           </preprocessorList>
         </cTool>
       </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_digest.c"
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_digest.c"
             ex="false"
             tool="0"
             flavor2="0">
@@ -62765,7 +62765,7 @@
           </preprocessorList>
         </cTool>
       </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_dual.c"
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_dual.c"
             ex="false"
             tool="0"
             flavor2="0">
@@ -62775,7 +62775,7 @@
           </preprocessorList>
         </cTool>
       </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_general.c"
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_general.c"
             ex="false"
             tool="0"
             flavor2="0">
@@ -62785,7 +62785,7 @@
           </preprocessorList>
         </cTool>
       </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_keymgmt.c"
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_keymgmt.c"
             ex="false"
             tool="0"
             flavor2="0">
@@ -62795,7 +62795,7 @@
           </preprocessorList>
         </cTool>
       </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_mutex.c"
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_mutex.c"
             ex="false"
             tool="0"
             flavor2="0">
@@ -62805,7 +62805,7 @@
           </preprocessorList>
         </cTool>
       </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_objmgmt.c"
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_objmgmt.c"
             ex="false"
             tool="0"
             flavor2="0">
@@ -62815,7 +62815,7 @@
           </preprocessorList>
         </cTool>
       </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_sessmgmt.c"
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_sessmgmt.c"
             ex="false"
             tool="0"
             flavor2="0">
@@ -62825,7 +62825,7 @@
           </preprocessorList>
         </cTool>
       </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_sign.c"
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_sign.c"
             ex="false"
             tool="0"
             flavor2="0">
@@ -62835,7 +62835,7 @@
           </preprocessorList>
         </cTool>
       </item>
-      <item path="../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_util.c"
+      <item path="../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_util.c"
             ex="false"
             tool="0"
             flavor2="0">
@@ -62845,14 +62845,14 @@
           </preprocessorList>
         </cTool>
       </item>
-      <item path="../../jdk/src/jdk.crypto.token/unix/native/libj2pkcs11/j2secmod_md.c"
-            ex="false"
-            tool="0"
-            flavor2="0">
-        <cTool flags="2">
-        </cTool>
-      </item>
-      <item path="../../jdk/src/jdk.crypto.token/unix/native/libj2pkcs11/p11_md.c"
+      <item path="../../jdk/src/jdk.crypto.cryptoki/unix/native/libj2pkcs11/j2secmod_md.c"
+            ex="false"
+            tool="0"
+            flavor2="0">
+        <cTool flags="2">
+        </cTool>
+      </item>
+      <item path="../../jdk/src/jdk.crypto.cryptoki/unix/native/libj2pkcs11/p11_md.c"
             ex="false"
             tool="0"
             flavor2="0">
@@ -66281,18 +66281,18 @@
           </preprocessorList>
         </ccTool>
       </folder>
-      <folder path="0/jdk/src/jdk.crypto.token">
-        <cTool>
-          <incDir>
-            <pElem>../../jdk/src/java.base/share/native/include</pElem>
-            <pElem>../../jdk/src/java.base/solaris/native/include</pElem>
-            <pElem>../../jdk/src/java.base/unix/native/include</pElem>
-            <pElem>../../jdk/src/java.base/share/native/libjava</pElem>
-            <pElem>../../jdk/src/java.base/unix/native/libjava</pElem>
-            <pElem>../../jdk/src/jdk.crypto.token/share/native/libj2pkcs11</pElem>
-            <pElem>../../jdk/src/jdk.crypto.token/unix/native/libj2pkcs11</pElem>
-            <pElem>../../jdk/src/java.base/solaris/native/libjava</pElem>
-            <pElem>../../build/support/headers/jdk.crypto.token</pElem>
+      <folder path="0/jdk/src/jdk.crypto.cryptoki">
+        <cTool>
+          <incDir>
+            <pElem>../../jdk/src/java.base/share/native/include</pElem>
+            <pElem>../../jdk/src/java.base/solaris/native/include</pElem>
+            <pElem>../../jdk/src/java.base/unix/native/include</pElem>
+            <pElem>../../jdk/src/java.base/share/native/libjava</pElem>
+            <pElem>../../jdk/src/java.base/unix/native/libjava</pElem>
+            <pElem>../../jdk/src/jdk.crypto.cryptoki/share/native/libj2pkcs11</pElem>
+            <pElem>../../jdk/src/jdk.crypto.cryptoki/unix/native/libj2pkcs11</pElem>
+            <pElem>../../jdk/src/java.base/solaris/native/libjava</pElem>
+            <pElem>../../build/support/headers/jdk.crypto.cryptoki</pElem>
             <pElem>../../make</pElem>
           </incDir>
           <preprocessorList>
@@ -66301,7 +66301,7 @@
           </preprocessorList>
         </cTool>
       </folder>
-      <folder path="0/jdk/src/jdk.crypto.token/unix">
+      <folder path="0/jdk/src/jdk.crypto.cryptoki/unix">
         <cTool>
           <preprocessorList>
             <Elem>THIS_FILE="j2secmod_md.c"</Elem>
--- a/corba/src/java.corba/share/classes/com/sun/jndi/cosnaming/CNBindingEnumeration.java	Tue Jan 24 18:44:13 2017 +0300
+++ b/corba/src/java.corba/share/classes/com/sun/jndi/cosnaming/CNBindingEnumeration.java	Thu Jan 26 09:19:33 2017 -0800
@@ -33,6 +33,8 @@
 
 import org.omg.CosNaming.*;
 
+import com.sun.jndi.toolkit.corba.CorbaUtils;
+
 /**
   * Implements the JNDI NamingEnumeration interface for COS
   * Naming. Gets hold of a list of bindings from the COS Naming Server
@@ -212,7 +214,10 @@
         Name cname = CNNameParser.cosNameToName(bndg.binding_name);
 
         try {
-            obj = NamingManager.getObjectInstance(obj, cname, _ctx, _env);
+            // Check whether object factory codebase is trusted
+            if (CorbaUtils.isObjectFactoryTrusted(obj)) {
+                obj = NamingManager.getObjectInstance(obj, cname, _ctx, _env);
+            }
         } catch (NamingException e) {
             throw e;
         } catch (Exception e) {
--- a/corba/src/java.corba/share/classes/com/sun/jndi/cosnaming/CNCtx.java	Tue Jan 24 18:44:13 2017 +0300
+++ b/corba/src/java.corba/share/classes/com/sun/jndi/cosnaming/CNCtx.java	Thu Jan 26 09:19:33 2017 -0800
@@ -36,6 +36,8 @@
 import java.io.InputStreamReader;
 import java.io.BufferedReader;
 import java.io.IOException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 
 import org.omg.CosNaming.*;
 import org.omg.CosNaming.NamingContextPackage.*;
@@ -82,6 +84,19 @@
     private static final String FED_PROP = "com.sun.jndi.cosnaming.federation";
     boolean federation = false;
 
+    /**
+     * Determines whether classes may be loaded from an arbitrary URL code base.
+     */
+    public static final boolean trustURLCodebase;
+    static {
+        // System property to control whether classes may be loaded from an
+        // arbitrary URL code base
+        PrivilegedAction<String> act = () -> System.getProperty(
+            "com.sun.jndi.cosnaming.object.trustURLCodebase", "false");
+        String trust = AccessController.doPrivileged(act);
+        trustURLCodebase = "true".equalsIgnoreCase(trust);
+    }
+
     // Reference counter for tracking _orb references
     OrbReuseTracker orbTracker = null;
     int enumCount;
@@ -534,12 +549,16 @@
             if (name.size() == 0 )
                 return this; // %%% should clone() so that env can be changed
             NameComponent[] path = CNNameParser.nameToCosName(name);
+            java.lang.Object answer = null;
 
             try {
-                java.lang.Object answer = callResolve(path);
-
+                answer = callResolve(path);
                 try {
-                    return NamingManager.getObjectInstance(answer, name, this, _env);
+                    // Check whether object factory codebase is trusted
+                    if (CorbaUtils.isObjectFactoryTrusted(answer)) {
+                        answer = NamingManager.getObjectInstance(
+                            answer, name, this, _env);
+                    }
                 } catch (NamingException e) {
                     throw e;
                 } catch (Exception e) {
@@ -552,6 +571,7 @@
                 javax.naming.Context cctx = getContinuationContext(cpe);
                 return cctx.lookup(cpe.getRemainingName());
             }
+            return answer;
     }
 
     /**
--- a/corba/src/java.corba/share/classes/com/sun/jndi/cosnaming/ExceptionMapper.java	Tue Jan 24 18:44:13 2017 +0300
+++ b/corba/src/java.corba/share/classes/com/sun/jndi/cosnaming/ExceptionMapper.java	Thu Jan 26 09:19:33 2017 -0800
@@ -33,6 +33,8 @@
 import org.omg.CosNaming.NamingContextPackage.*;
 import org.omg.CORBA.*;
 
+import com.sun.jndi.toolkit.corba.CorbaUtils;
+
 /**
   * A convenience class to map the COS Naming exceptions to the JNDI exceptions.
   * @author Raj Krishnamurthy
@@ -202,10 +204,13 @@
             // Not a context, use object factory to transform object.
 
             Name cname = CNNameParser.cosNameToName(resolvedName);
-            java.lang.Object resolvedObj2;
+            java.lang.Object resolvedObj2 = null;
             try {
-                resolvedObj2 = NamingManager.getObjectInstance(resolvedObj,
-                    cname, ctx, ctx._env);
+                // Check whether object factory codebase is trusted
+                if (CorbaUtils.isObjectFactoryTrusted(resolvedObj)) {
+                    resolvedObj2 = NamingManager.getObjectInstance(resolvedObj,
+                        cname, ctx, ctx._env);
+                }
             } catch (NamingException ge) {
                 throw ge;
             } catch (Exception ge) {
--- a/corba/src/java.corba/share/classes/com/sun/jndi/toolkit/corba/CorbaUtils.java	Tue Jan 24 18:44:13 2017 +0300
+++ b/corba/src/java.corba/share/classes/com/sun/jndi/toolkit/corba/CorbaUtils.java	Thu Jan 26 09:19:33 2017 -0800
@@ -36,11 +36,12 @@
 
 import org.omg.CORBA.ORB;
 
-import javax.naming.Context;
-import javax.naming.ConfigurationException;
+import javax.naming.*;
 import javax.rmi.CORBA.Stub;
 import javax.rmi.PortableRemoteObject;
 
+import com.sun.jndi.cosnaming.CNCtx;
+
 import java.io.UnsupportedEncodingException;
 import java.net.MalformedURLException;
 import java.net.URLDecoder;
@@ -183,6 +184,32 @@
     }
 
     /**
+     * Check whether object factory code base is trusted.
+     * Classes may only be loaded from an arbitrary URL code base when
+     * the system property com.sun.jndi.rmi.object.trustURLCodebase
+     * has been set to "true".
+     */
+    public static boolean isObjectFactoryTrusted(Object obj)
+        throws NamingException {
+
+        // Extract Reference, if possible
+        Reference ref = null;
+        if (obj instanceof Reference) {
+            ref = (Reference) obj;
+        } else if (obj instanceof Referenceable) {
+            ref = ((Referenceable)(obj)).getReference();
+        }
+
+        if (ref != null && ref.getFactoryClassLocation() != null &&
+                !CNCtx.trustURLCodebase) {
+            throw new ConfigurationException(
+                "The object factory is untrusted. Set the system property" +
+                " 'com.sun.jndi.cosnaming.object.trustURLCodebase' to 'true'.");
+        }
+        return true;
+    }
+
+    /**
      * Decode a URI string (according to RFC 2396).
      */
     public static final String decode(String s) throws MalformedURLException {
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp	Tue Jan 24 18:44:13 2017 +0300
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp	Thu Jan 26 09:19:33 2017 -0800
@@ -1025,16 +1025,20 @@
 
 static int skip_annotation_value(const u1*, int, int); // fwd decl
 
+// Safely increment index by val if does not pass limit
+#define SAFE_ADD(index, limit, val) \
+if (index >= limit - val) return limit; \
+index += val;
+
 // Skip an annotation.  Return >=limit if there is any problem.
 static int skip_annotation(const u1* buffer, int limit, int index) {
   assert(buffer != NULL, "invariant");
   // annotation := atype:u2 do(nmem:u2) {member:u2 value}
   // value := switch (tag:u1) { ... }
-  index += 2;  // skip atype
-  if ((index += 2) >= limit)  return limit;  // read nmem
+  SAFE_ADD(index, limit, 4); // skip atype and read nmem
   int nmem = Bytes::get_Java_u2((address)buffer + index - 2);
   while (--nmem >= 0 && index < limit) {
-    index += 2; // skip member
+    SAFE_ADD(index, limit, 2); // skip member
     index = skip_annotation_value(buffer, limit, index);
   }
   return index;
@@ -1052,7 +1056,7 @@
   //   case @: annotation;
   //   case s: s_con:u2;
   // }
-  if ((index += 1) >= limit)  return limit;  // read tag
+  SAFE_ADD(index, limit, 1); // read tag
   const u1 tag = buffer[index - 1];
   switch (tag) {
     case 'B':
@@ -1065,14 +1069,14 @@
     case 'J':
     case 'c':
     case 's':
-      index += 2;  // skip con or s_con
+      SAFE_ADD(index, limit, 2);  // skip con or s_con
       break;
     case 'e':
-      index += 4;  // skip e_class, e_name
+      SAFE_ADD(index, limit, 4);  // skip e_class, e_name
       break;
     case '[':
     {
-      if ((index += 2) >= limit)  return limit;  // read nval
+      SAFE_ADD(index, limit, 2); // read nval
       int nval = Bytes::get_Java_u2((address)buffer + index - 2);
       while (--nval >= 0 && index < limit) {
         index = skip_annotation_value(buffer, limit, index);
@@ -1101,8 +1105,8 @@
   assert(loader_data != NULL, "invariant");
 
   // annotations := do(nann:u2) {annotation}
-  int index = 0;
-  if ((index += 2) >= limit)  return;  // read nann
+  int index = 2; // read nann
+  if (index >= limit)  return;
   int nann = Bytes::get_Java_u2((address)buffer + index - 2);
   enum {  // initial annotation layout
     atype_off = 0,      // utf8 such as 'Ljava/lang/annotation/Retention;'
@@ -1121,7 +1125,8 @@
     s_size = 9,
     min_size = 6        // smallest possible size (zero members)
   };
-  while ((--nann) >= 0 && (index - 2 + min_size <= limit)) {
+  // Cannot add min_size to index in case of overflow MAX_INT
+  while ((--nann) >= 0 && (index - 2 <= limit - min_size)) {
     int index0 = index;
     index = skip_annotation(buffer, limit, index);
     const u1* const abase = buffer + index0;
@@ -1253,13 +1258,14 @@
         runtime_visible_annotations_length = attribute_length;
         runtime_visible_annotations = cfs->get_u1_buffer();
         assert(runtime_visible_annotations != NULL, "null visible annotations");
+        cfs->guarantee_more(runtime_visible_annotations_length, CHECK);
         parse_annotations(cp,
                           runtime_visible_annotations,
                           runtime_visible_annotations_length,
                           parsed_annotations,
                           _loader_data,
                           CHECK);
-        cfs->skip_u1(runtime_visible_annotations_length, CHECK);
+        cfs->skip_u1_fast(runtime_visible_annotations_length);
       } else if (attribute_name == vmSymbols::tag_runtime_invisible_annotations()) {
         if (runtime_invisible_annotations_exists) {
           classfile_parse_error(
@@ -2574,13 +2580,14 @@
         runtime_visible_annotations_length = method_attribute_length;
         runtime_visible_annotations = cfs->get_u1_buffer();
         assert(runtime_visible_annotations != NULL, "null visible annotations");
+        cfs->guarantee_more(runtime_visible_annotations_length, CHECK_NULL);
         parse_annotations(cp,
                           runtime_visible_annotations,
                           runtime_visible_annotations_length,
                           &parsed_annotations,
                           _loader_data,
                           CHECK_NULL);
-        cfs->skip_u1(runtime_visible_annotations_length, CHECK_NULL);
+        cfs->skip_u1_fast(runtime_visible_annotations_length);
       } else if (method_attribute_name == vmSymbols::tag_runtime_invisible_annotations()) {
         if (runtime_invisible_annotations_exists) {
           classfile_parse_error(
@@ -3285,13 +3292,14 @@
         runtime_visible_annotations_length = attribute_length;
         runtime_visible_annotations = cfs->get_u1_buffer();
         assert(runtime_visible_annotations != NULL, "null visible annotations");
+        cfs->guarantee_more(runtime_visible_annotations_length, CHECK);
         parse_annotations(cp,
                           runtime_visible_annotations,
                           runtime_visible_annotations_length,
                           parsed_annotations,
                           _loader_data,
                           CHECK);
-        cfs->skip_u1(runtime_visible_annotations_length, CHECK);
+        cfs->skip_u1_fast(runtime_visible_annotations_length);
       } else if (tag == vmSymbols::tag_runtime_invisible_annotations()) {
         if (runtime_invisible_annotations_exists) {
           classfile_parse_error(
--- a/hotspot/src/share/vm/classfile/stackMapFrame.cpp	Tue Jan 24 18:44:13 2017 +0300
+++ b/hotspot/src/share/vm/classfile/stackMapFrame.cpp	Thu Jan 26 09:19:33 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -155,47 +155,8 @@
   return i;
 }
 
-bool StackMapFrame::has_flag_match_exception(
-    const StackMapFrame* target) const {
-  // We allow flags of {UninitThis} to assign to {} if-and-only-if the
-  // target frame does not depend upon the current type.
-  // This is slightly too strict, as we need only enforce that the
-  // slots that were initialized by the <init> (the things that were
-  // UninitializedThis before initialize_object() converted them) are unused.
-  // However we didn't save that information so we'll enforce this upon
-  // anything that might have been initialized.  This is a rare situation
-  // and javac never generates code that would end up here, but some profilers
-  // (such as NetBeans) might, when adding exception handlers in <init>
-  // methods to cover the invokespecial instruction.  See 7020118.
-
-  assert(max_locals() == target->max_locals() &&
-         stack_size() == target->stack_size(), "StackMap sizes must match");
-
-  VerificationType top = VerificationType::top_type();
-  VerificationType this_type = verifier()->current_type();
-
-  if (!flag_this_uninit() || target->flags() != 0) {
-    return false;
-  }
-
-  for (int i = 0; i < target->locals_size(); ++i) {
-    if (locals()[i] == this_type && target->locals()[i] != top) {
-      return false;
-    }
-  }
-
-  for (int i = 0; i < target->stack_size(); ++i) {
-    if (stack()[i] == this_type && target->stack()[i] != top) {
-      return false;
-    }
-  }
-
-  return true;
-}
-
 bool StackMapFrame::is_assignable_to(
-    const StackMapFrame* target, bool is_exception_handler,
-    ErrorContext* ctx, TRAPS) const {
+    const StackMapFrame* target, ErrorContext* ctx, TRAPS) const {
   if (_max_locals != target->max_locals()) {
     *ctx = ErrorContext::locals_size_mismatch(
         _offset, (StackMapFrame*)this, (StackMapFrame*)target);
@@ -226,8 +187,7 @@
     return false;
   }
 
-  bool match_flags = (_flags | target->flags()) == target->flags();
-  if (match_flags || is_exception_handler && has_flag_match_exception(target)) {
+  if ((_flags | target->flags()) == target->flags()) {
     return true;
   } else {
     *ctx = ErrorContext::bad_flags(target->offset(),
--- a/hotspot/src/share/vm/classfile/stackMapFrame.hpp	Tue Jan 24 18:44:13 2017 +0300
+++ b/hotspot/src/share/vm/classfile/stackMapFrame.hpp	Thu Jan 26 09:19:33 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -167,8 +167,7 @@
 
   // Return true if this stack map frame is assignable to target.
   bool is_assignable_to(
-      const StackMapFrame* target, bool is_exception_handler,
-      ErrorContext* ctx, TRAPS) const;
+      const StackMapFrame* target, ErrorContext* ctx, TRAPS) const;
 
   inline void set_mark() {
 #ifdef ASSERT
@@ -290,8 +289,6 @@
   int is_assignable_to(
     VerificationType* src, VerificationType* target, int32_t len, TRAPS) const;
 
-  bool has_flag_match_exception(const StackMapFrame* target) const;
-
   TypeOrigin stack_top_ctx();
 
   void print_on(outputStream* str) const;
--- a/hotspot/src/share/vm/classfile/stackMapTable.cpp	Tue Jan 24 18:44:13 2017 +0300
+++ b/hotspot/src/share/vm/classfile/stackMapTable.cpp	Thu Jan 26 09:19:33 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -70,26 +70,25 @@
 
 bool StackMapTable::match_stackmap(
     StackMapFrame* frame, int32_t target,
-    bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const {
+    bool match, bool update, ErrorContext* ctx, TRAPS) const {
   int index = get_index_from_offset(target);
-  return match_stackmap(frame, target, index, match, update, handler, ctx, THREAD);
+  return match_stackmap(frame, target, index, match, update, ctx, THREAD);
 }
 
 // Match and/or update current_frame to the frame in stackmap table with
 // specified offset and frame index. Return true if the two frames match.
-// handler is true if the frame in stackmap_table is for an exception handler.
 //
-// The values of match and update are:                  _match__update__handler
+// The values of match and update are:                  _match__update
 //
-// checking a branch target:                             true   false   false
-// checking an exception handler:                        true   false   true
+// checking a branch target:                             true   false
+// checking an exception handler:                        true   false
 // linear bytecode verification following an
-// unconditional branch:                                 false  true    false
+// unconditional branch:                                 false  true
 // linear bytecode verification not following an
-// unconditional branch:                                 true   true    false
+// unconditional branch:                                 true   true
 bool StackMapTable::match_stackmap(
     StackMapFrame* frame, int32_t target, int32_t frame_index,
-    bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const {
+    bool match, bool update, ErrorContext* ctx, TRAPS) const {
   if (frame_index < 0 || frame_index >= _frame_count) {
     *ctx = ErrorContext::missing_stackmap(frame->offset());
     frame->verifier()->verify_error(
@@ -102,7 +101,7 @@
   if (match) {
     // Has direct control flow from last instruction, need to match the two
     // frames.
-    result = frame->is_assignable_to(stackmap_frame, handler,
+    result = frame->is_assignable_to(stackmap_frame,
         ctx, CHECK_VERIFY_(frame->verifier(), result));
   }
   if (update) {
@@ -126,7 +125,7 @@
     StackMapFrame* frame, int32_t target, TRAPS) const {
   ErrorContext ctx;
   bool match = match_stackmap(
-    frame, target, true, false, false, &ctx, CHECK_VERIFY(frame->verifier()));
+    frame, target, true, false, &ctx, CHECK_VERIFY(frame->verifier()));
   if (!match || (target < 0 || target >= _code_length)) {
     frame->verifier()->verify_error(ctx,
         "Inconsistent stackmap frames at branch target %d", target);
--- a/hotspot/src/share/vm/classfile/stackMapTable.hpp	Tue Jan 24 18:44:13 2017 +0300
+++ b/hotspot/src/share/vm/classfile/stackMapTable.hpp	Thu Jan 26 09:19:33 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -60,12 +60,12 @@
   // specified offset. Return true if the two frames match.
   bool match_stackmap(
     StackMapFrame* current_frame, int32_t offset,
-    bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const;
+    bool match, bool update, ErrorContext* ctx, TRAPS) const;
   // Match and/or update current_frame to the frame in stackmap table with
   // specified offset and frame index. Return true if the two frames match.
   bool match_stackmap(
     StackMapFrame* current_frame, int32_t offset, int32_t frame_index,
-    bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const;
+    bool match, bool update, ErrorContext* ctx, TRAPS) const;
 
   // Check jump instructions. Make sure there are no uninitialized
   // instances on backward branch.
--- a/hotspot/src/share/vm/classfile/verifier.cpp	Tue Jan 24 18:44:13 2017 +0300
+++ b/hotspot/src/share/vm/classfile/verifier.cpp	Thu Jan 26 09:19:33 2017 -0800
@@ -541,19 +541,13 @@
     stack_map_frame* sm_frame = sm_table->entries();
     streamIndentor si2(ss);
     int current_offset = -1;
-    // Subtract two from StackMapAttribute length because the length includes
-    // two bytes for number of table entries.
-    size_t sm_table_space = method->stackmap_data()->length() - 2;
+    address end_of_sm_table = (address)sm_table + method->stackmap_data()->length();
     for (u2 i = 0; i < sm_table->number_of_entries(); ++i) {
       ss->indent();
-      size_t sm_frame_size = sm_frame->size();
-      // If the size of the next stackmap exceeds the length of the entire
-      // stackmap table then print a truncated message and return.
-      if (sm_frame_size > sm_table_space) {
+      if (!sm_frame->verify((address)sm_frame, end_of_sm_table)) {
         sm_frame->print_truncated(ss, current_offset);
         return;
       }
-      sm_table_space -= sm_frame_size;
       sm_frame->print_on(ss, current_offset);
       ss->cr();
       current_offset += sm_frame->offset_delta();
@@ -1863,7 +1857,7 @@
       // If matched, current_frame will be updated by this method.
       bool matches = stackmap_table->match_stackmap(
         current_frame, this_offset, stackmap_index,
-        !no_control_flow, true, false, &ctx, CHECK_VERIFY_(this, 0));
+        !no_control_flow, true, &ctx, CHECK_VERIFY_(this, 0));
       if (!matches) {
         // report type error
         verify_error(ctx, "Instruction type does not match stack map");
@@ -1913,7 +1907,7 @@
       }
       ErrorContext ctx;
       bool matches = stackmap_table->match_stackmap(
-        new_frame, handler_pc, true, false, true, &ctx, CHECK_VERIFY(this));
+        new_frame, handler_pc, true, false, &ctx, CHECK_VERIFY(this));
       if (!matches) {
         verify_error(ctx, "Stack map does not match the one at "
             "exception handler %d", handler_pc);
--- a/hotspot/test/runtime/handlerInTry/LoadHandlerInTry.java	Tue Jan 24 18:44:13 2017 +0300
+++ b/hotspot/test/runtime/handlerInTry/LoadHandlerInTry.java	Thu Jan 26 09:19:33 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -24,7 +24,7 @@
 /*
  * @test
  * @bug 8075118
- * @summary Allow a ctor to call super() from a switch bytecode.
+ * @summary JVM stuck in infinite loop during verification
  * @compile HandlerInTry.jasm
  * @compile IsolatedHandlerInTry.jasm
  * @run main/othervm -Xverify:all LoadHandlerInTry
@@ -70,9 +70,10 @@
         System.out.println("Regression test for bug 8075118");
         try {
             Class newClass = Class.forName("HandlerInTry");
-        } catch (Exception e) {
-            System.out.println("Failed: Exception was thrown: " + e.toString());
-            throw e;
+            throw new RuntimeException(
+                 "Failed to throw VerifyError for HandlerInTry");
+        } catch (java.lang.VerifyError e) {
+            System.out.println("Passed: VerifyError exception was thrown");
         }
 
         try {
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl.java	Tue Jan 24 18:44:13 2017 +0300
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl.java	Thu Jan 26 09:19:33 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -37,6 +37,7 @@
 import java.io.ObjectOutputStream;
 import java.io.ObjectStreamField;
 import java.io.Serializable;
+import java.lang.RuntimePermission;
 import java.lang.module.Configuration;
 import java.lang.module.ModuleDescriptor;
 import java.lang.module.ModuleFinder;
@@ -45,7 +46,11 @@
 import java.lang.reflect.Layer;
 import java.lang.reflect.Module;
 import java.security.AccessController;
+import java.security.CodeSigner;
+import java.security.CodeSource;
+import java.security.PermissionCollection;
 import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
@@ -177,6 +182,7 @@
             _loadedExternalExtensionFunctions = mapEF;
         }
 
+        @Override
         public Class<?> loadClass(String name) throws ClassNotFoundException {
             Class<?> ret = null;
             // The _loadedExternalExtensionFunctions will be empty when the
@@ -196,6 +202,10 @@
         Class defineClass(final byte[] b) {
             return defineClass(null, b, 0, b.length);
         }
+
+        Class defineClass(final byte[] b, ProtectionDomain pd) {
+            return defineClass(null, b, 0, b.length, pd);
+        }
     }
 
 
@@ -482,16 +492,24 @@
 
             // the module needs access to runtime classes
             Module thisModule = TemplatesImpl.class.getModule();
-
+            // the module also needs permission to access each package
+            // that is exported to it
+            PermissionCollection perms =
+                new RuntimePermission("*").newPermissionCollection();
             Arrays.asList(Constants.PKGS_USED_BY_TRANSLET_CLASSES).forEach(p -> {
                 thisModule.addExports(p, m);
+                perms.add(new RuntimePermission("accessClassInPackage." + p));
             });
 
-            // java.xml needs to instanitate the translet class
+            CodeSource codeSource = new CodeSource(null, (CodeSigner[])null);
+            ProtectionDomain pd = new ProtectionDomain(codeSource, perms,
+                                                       loader, null);
+
+            // java.xml needs to instantiate the translet class
             thisModule.addReads(m);
 
             for (int i = 0; i < classCount; i++) {
-                _class[i] = loader.defineClass(_bytecodes[i]);
+                _class[i] = loader.defineClass(_bytecodes[i], pd);
                 final Class superClass = _class[i].getSuperclass();
 
                 // Check if this is the main class
--- a/jaxp/test/javax/xml/jaxp/unittest/transform/TransformerTest.java	Tue Jan 24 18:44:13 2017 +0300
+++ b/jaxp/test/javax/xml/jaxp/unittest/transform/TransformerTest.java	Thu Jan 26 09:19:33 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, 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,6 +24,7 @@
 package transform;
 
 import static jaxp.library.JAXPTestUtilities.getSystemProperty;
+import static jaxp.library.JAXPTestUtilities.tryRunWithTmpPermission;
 
 import java.io.BufferedReader;
 import java.io.ByteArrayInputStream;
@@ -217,7 +218,7 @@
      * @summary Test for JDK-6272879
      */
     @Test
-    public final void testBug6272879() throws IOException, TransformerException {
+    public final void testBug6272879() throws Exception {
         final String xsl =
                 "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>" + LINE_SEPARATOR +
                 "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">" + LINE_SEPARATOR +
@@ -274,9 +275,11 @@
 
         System.out.println("Result after transformation:");
         System.out.println("============================");
-        OutputFormat format = new OutputFormat();
-        format.setIndenting(true);
-        new XMLSerializer(System.out, format).serialize(document);
+        tryRunWithTmpPermission(() -> {
+            OutputFormat format = new OutputFormat();
+            format.setIndenting(true);
+            new XMLSerializer(System.out, format).serialize(document);
+        }, new RuntimePermission("accessClassInPackage.com.sun.org.apache.xml.internal.serialize"));
         System.out.println();
 
         System.out.println("Node content for element valeur2:");
@@ -529,7 +532,7 @@
             }
         }
 
-        public void run()  throws IOException, TransformerException {
+        public void run()  throws Exception {
             printSnippet("Source:", sourceXml);
 
             printSnippet("Stylesheet:", xsl);
@@ -545,9 +548,11 @@
 
             System.out.println("Result after transformation:");
             System.out.println("============================");
-            OutputFormat format = new OutputFormat();
-            format.setIndenting(true);
-            new XMLSerializer(System.out, format).serialize(document);
+            tryRunWithTmpPermission(() -> {
+                OutputFormat format = new OutputFormat();
+                format.setIndenting(true);
+                new XMLSerializer(System.out, format).serialize(document);
+            }, new RuntimePermission("accessClassInPackage.com.sun.org.apache.xml.internal.serialize"));
             System.out.println();
 
             checkNodeNS(document.getElementsByTagName("test1").item(0), "ns2", "ns2", null);
@@ -566,9 +571,7 @@
      *          definitions to reset the default namespace
      */
     @Test
-    public final void testBug8162598() throws IOException,
-        TransformerException
-    {
+    public final void testBug8162598() throws Exception {
         new Test8162598().run();
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/copy/Copy-jdk.crypto.cryptoki.gmk	Thu Jan 26 09:19:33 2017 -0800
@@ -0,0 +1,45 @@
+#
+# Copyright (c) 2014, 2017, 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.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# 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.
+#
+
+include CopyCommon.gmk
+
+################################################################################
+
+ifeq ($(OPENJDK_TARGET_OS), solaris)
+
+  SUNPKCS11_CFG_SRC := \
+      $(JDK_TOPDIR)/src/jdk.crypto.cryptoki/solaris/conf/security/sunpkcs11-solaris.cfg
+  SUNPKCS11_CFG_DST := $(CONF_DST_DIR)/security/sunpkcs11-solaris.cfg
+
+  $(SUNPKCS11_CFG_DST): $(SUNPKCS11_CFG_SRC)
+	$(call install-file)
+
+  SECURITY_PKCS11_CONF_FILES += $(SUNPKCS11_CFG_DST)
+
+  TARGETS := $(SUNPKCS11_CFG_DST)
+
+endif
+
+################################################################################
--- a/jdk/make/copy/Copy-jdk.crypto.token.gmk	Tue Jan 24 18:44:13 2017 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-#
-# Copyright (c) 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
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.  Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# 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.
-#
-
-include CopyCommon.gmk
-
-################################################################################
-
-ifeq ($(OPENJDK_TARGET_OS), solaris)
-
-  SUNPKCS11_CFG_SRC := \
-      $(JDK_TOPDIR)/src/jdk.crypto.token/solaris/conf/security/sunpkcs11-solaris.cfg
-  SUNPKCS11_CFG_DST := $(CONF_DST_DIR)/security/sunpkcs11-solaris.cfg
-
-  $(SUNPKCS11_CFG_DST): $(SUNPKCS11_CFG_SRC)
-	$(call install-file)
-
-  SECURITY_PKCS11_CONF_FILES += $(SUNPKCS11_CFG_DST)
-
-  TARGETS := $(SUNPKCS11_CFG_DST)
-
-endif
-
-################################################################################
--- a/jdk/make/gensrc/GensrcLocaleData.gmk	Tue Jan 24 18:44:13 2017 +0300
+++ b/jdk/make/gensrc/GensrcLocaleData.gmk	Thu Jan 26 09:19:33 2017 -0800
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2017, 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
@@ -89,8 +89,8 @@
   $1_NON_BASE_LOCALES := $$(subst zh-MO,zh-MO$$(SPACE)zh-Hant-MO, $$($1_NON_BASE_LOCALES))
   $1_NON_BASE_LOCALES := $$(subst zh-TW,zh-TW$$(SPACE)zh-Hant-TW, $$($1_NON_BASE_LOCALES))
 
-# Adding implict locales nn-NO and nb-NO
-  $1_NON_BASE_LOCALES += nn-NO  nb-NO
+# Adding implict locales nb nn-NO and nb-NO
+  $1_NON_BASE_LOCALES += nb  nn-NO  nb-NO
   $1_NON_BASE_LOCALES := $$(sort $$($1_NON_BASE_LOCALES))
 
   ALL_BASE_LOCALES += $$($1_BASE_LOCALES)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/lib/Lib-jdk.crypto.cryptoki.gmk	Thu Jan 26 09:19:33 2017 -0800
@@ -0,0 +1,56 @@
+#
+# Copyright (c) 2011, 2017, 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.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# 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.
+#
+
+include LibCommon.gmk
+
+################################################################################
+
+LIBJ2PKCS11_SRC := $(JDK_TOPDIR)/src/jdk.crypto.cryptoki/share/native/libj2pkcs11 \
+    $(JDK_TOPDIR)/src/jdk.crypto.cryptoki/$(OPENJDK_TARGET_OS_TYPE)/native/libj2pkcs11
+
+$(eval $(call SetupNativeCompilation,BUILD_LIBJ2PKCS11, \
+    LIBRARY := j2pkcs11, \
+    OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
+    SRC := $(LIBJ2PKCS11_SRC), \
+    OPTIMIZATION := LOW, \
+    CFLAGS := $(CFLAGS_JDKLIB) $(addprefix -I, $(LIBJ2PKCS11_SRC)) \
+        $(LIBJAVA_HEADER_FLAGS) \
+        -I$(SUPPORT_OUTPUTDIR)/headers/jdk.crypto.cryptoki, \
+    MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libj2pkcs11/mapfile-vers, \
+    LDFLAGS := $(LDFLAGS_JDKLIB) \
+        $(call SET_SHARED_LIBRARY_ORIGIN), \
+    LIBS_unix := $(LIBDL), \
+    LIBS_solaris := -lc, \
+    VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
+    RC_FLAGS := $(RC_FLAGS) \
+        -D "JDK_FNAME=j2pkcs11.dll" \
+        -D "JDK_INTERNAL_NAME=j2pkcs11" \
+        -D "JDK_FTYPE=0x2L", \
+    OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libj2pkcs11, \
+))
+
+TARGETS += $(BUILD_LIBJ2PKCS11)
+
+################################################################################
--- a/jdk/make/lib/Lib-jdk.crypto.token.gmk	Tue Jan 24 18:44:13 2017 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-#
-# Copyright (c) 2011, 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.  Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# 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.
-#
-
-include LibCommon.gmk
-
-################################################################################
-
-LIBJ2PKCS11_SRC := $(JDK_TOPDIR)/src/jdk.crypto.token/share/native/libj2pkcs11 \
-    $(JDK_TOPDIR)/src/jdk.crypto.token/$(OPENJDK_TARGET_OS_TYPE)/native/libj2pkcs11
-
-$(eval $(call SetupNativeCompilation,BUILD_LIBJ2PKCS11, \
-    LIBRARY := j2pkcs11, \
-    OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
-    SRC := $(LIBJ2PKCS11_SRC), \
-    OPTIMIZATION := LOW, \
-    CFLAGS := $(CFLAGS_JDKLIB) $(addprefix -I, $(LIBJ2PKCS11_SRC)) \
-        $(LIBJAVA_HEADER_FLAGS) \
-        -I$(SUPPORT_OUTPUTDIR)/headers/jdk.crypto.token, \
-    MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libj2pkcs11/mapfile-vers, \
-    LDFLAGS := $(LDFLAGS_JDKLIB) \
-        $(call SET_SHARED_LIBRARY_ORIGIN), \
-    LIBS_unix := $(LIBDL), \
-    LIBS_solaris := -lc, \
-    VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
-    RC_FLAGS := $(RC_FLAGS) \
-        -D "JDK_FNAME=j2pkcs11.dll" \
-        -D "JDK_INTERNAL_NAME=j2pkcs11" \
-        -D "JDK_FTYPE=0x2L", \
-    OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libj2pkcs11, \
-))
-
-TARGETS += $(BUILD_LIBJ2PKCS11)
-
-################################################################################
--- a/jdk/make/src/classes/build/tools/cldrconverter/Bundle.java	Tue Jan 24 18:44:13 2017 +0300
+++ b/jdk/make/src/classes/build/tools/cldrconverter/Bundle.java	Thu Jan 26 09:19:33 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, 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
@@ -389,6 +389,18 @@
                 }
             }
         }
+        // replace empty era names with parentMap era names
+        for (String key : ERA_KEYS) {
+            Object value = myMap.get(key);
+            if (value != null && value instanceof String[]) {
+                String[] eraStrings = (String[]) value;
+                for (String eraString : eraStrings) {
+                    if (eraString == null || eraString.isEmpty()) {
+                        fillInElements(parentsMap, key, value);
+                    }
+                }
+            }
+        }
 
         // Remove all duplicates
         if (Objects.nonNull(parentsMap)) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/src/classes/build/tools/taglet/Incubating.java	Thu Jan 26 09:19:33 2017 -0800
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2017, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package build.tools.taglet;
+
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Set;
+import com.sun.source.doctree.DocTree;
+import jdk.javadoc.doclet.taglet.Taglet;
+import static jdk.javadoc.doclet.taglet.Taglet.Location.*;
+
+/**
+ * An inline tag to conveniently insert a standard Incubating warning.  For
+ * use by members in Incubator Modules.
+ */
+public class Incubating implements Taglet {
+
+    /** Returns the set of locations in which a taglet may be used. */
+    @Override
+    public Set<Location> getAllowedLocations() {
+        return EnumSet.of(OVERVIEW, MODULE, PACKAGE, TYPE);
+    }
+
+    @Override
+    public boolean isInlineTag() {
+        return true;
+    }
+
+    @Override
+    public String getName() {
+        return "Incubating";
+    }
+
+    private static final String MESSAGE =
+        "<BR><b><a href=\"http://openjdk.java.net/jeps/11\">Incubating Feature.</a>"
+                + " Will be removed in a future release.</b>";
+
+    @Override
+    public String toString(DocTree tag) {
+        return MESSAGE;
+    }
+
+    @Override
+    public String toString(List<? extends DocTree> tags) {
+        return MESSAGE;
+    }
+}
+
--- a/jdk/src/java.base/share/classes/java/net/URLClassLoader.java	Tue Jan 24 18:44:13 2017 +0300
+++ b/jdk/src/java.base/share/classes/java/net/URLClassLoader.java	Thu Jan 26 09:19:33 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -66,16 +66,16 @@
  * refer to a directory. Otherwise, the URL is assumed to refer to a JAR file
  * which will be opened as needed.
  * <p>
+ * This class loader supports the loading of classes and resources from the
+ * contents of a <a href="../util/jar/JarFile.html#multirelease">multi-release</a>
+ * JAR file that is referred to by a given URL.
+ * <p>
  * The AccessControlContext of the thread that created the instance of
  * URLClassLoader will be used when subsequently loading classes and
  * resources.
  * <p>
  * The classes that are loaded are by default granted permission only to
  * access the URLs specified when the URLClassLoader was created.
- * <p>
- * This class loader supports the loading of classes from the contents of a
- * <a href="../util/jar/JarFile.html#multirelease">multi-release</a> JAR file
- * that is referred to by a given URL.
  *
  * @author  David Connelly
  * @since   1.2
--- a/jdk/src/java.base/share/classes/java/security/AlgorithmParameterGenerator.java	Tue Jan 24 18:44:13 2017 +0300
+++ b/jdk/src/java.base/share/classes/java/security/AlgorithmParameterGenerator.java	Thu Jan 26 09:19:33 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -71,7 +71,7 @@
  * following standard {@code AlgorithmParameterGenerator} algorithms and
  * keysizes in parentheses:
  * <ul>
- * <li>{@code DiffieHellman} (1024, 2048, 4096)</li>
+ * <li>{@code DiffieHellman} (1024, 2048)</li>
  * <li>{@code DSA} (1024, 2048)</li>
  * </ul>
  * These algorithms are described in the <a href=
--- a/jdk/src/java.base/share/classes/module-info.java	Tue Jan 24 18:44:13 2017 +0300
+++ b/jdk/src/java.base/share/classes/module-info.java	Thu Jan 26 09:19:33 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, 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
@@ -219,7 +219,7 @@
         java.security.jgss;
     exports sun.nio.ch to
         java.management,
-        jdk.crypto.token,
+        jdk.crypto.cryptoki,
         jdk.sctp,
         jdk.unsupported;
     exports sun.nio.cs to
@@ -244,13 +244,13 @@
         java.desktop,
         java.security.jgss;
     exports sun.security.internal.interfaces to
-        jdk.crypto.token;
+        jdk.crypto.cryptoki;
     exports sun.security.internal.spec to
-        jdk.crypto.token;
+        jdk.crypto.cryptoki;
     exports sun.security.jca to
         java.smartcardio,
         jdk.crypto.ec,
-        jdk.crypto.token,
+        jdk.crypto.cryptoki,
         jdk.naming.dns;
     exports sun.security.pkcs to
         jdk.crypto.ec,
@@ -258,13 +258,13 @@
     exports sun.security.provider to
         java.rmi,
         java.security.jgss,
-        jdk.crypto.token,
+        jdk.crypto.cryptoki,
         jdk.policytool,
         jdk.security.auth;
     exports sun.security.provider.certpath to
         java.naming;
     exports sun.security.rsa to
-        jdk.crypto.token;
+        jdk.crypto.cryptoki;
     exports sun.security.ssl to
         java.security.jgss;
     exports sun.security.timestamp to
@@ -280,14 +280,14 @@
         java.smartcardio,
         java.xml.crypto,
         jdk.crypto.ec,
-        jdk.crypto.token,
+        jdk.crypto.cryptoki,
         jdk.jartool,
         jdk.policytool,
         jdk.security.auth,
         jdk.security.jgss;
     exports sun.security.x509 to
         jdk.crypto.ec,
-        jdk.crypto.token,
+        jdk.crypto.cryptoki,
         jdk.jartool,
         jdk.security.auth;
     exports sun.security.validator to
--- a/jdk/src/java.base/share/classes/sun/security/provider/PolicyFile.java	Tue Jan 24 18:44:13 2017 +0300
+++ b/jdk/src/java.base/share/classes/sun/security/provider/PolicyFile.java	Thu Jan 26 09:19:33 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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,7 +32,6 @@
 import java.net.URI;
 import java.nio.file.Paths;
 import java.util.*;
-import java.text.MessageFormat;
 import java.security.*;
 import java.security.cert.Certificate;
 import java.security.cert.X509Certificate;
@@ -579,10 +578,9 @@
                 k.add(policy);
                 return k;
             });
-            MessageFormat form = new MessageFormat(ResourcesMgr.getString
-                (POLICY + ".error.parsing.policy.message"));
             Object[] source = {policy, pe.getLocalizedMessage()};
-            System.err.println(form.format(source));
+            System.err.println(LocalizedMessage.getMessage
+                (POLICY + ".error.parsing.policy.message", source));
             if (debug != null) {
                 pe.printStackTrace();
             }
@@ -805,32 +803,30 @@
                         }
                     }
                 } catch (java.lang.reflect.InvocationTargetException ite) {
-                    MessageFormat form = new MessageFormat
-                        (ResourcesMgr.getString
-                         (POLICY +
-                          ".error.adding.Permission.perm.message"));
                     Object[] source = {pe.permission,
                                        ite.getTargetException().toString()};
-                    System.err.println(form.format(source));
+                    System.err.println(
+                        LocalizedMessage.getMessage(
+                            POLICY + ".error.adding.Permission.perm.message",
+                            source));
                 } catch (Exception e) {
-                    MessageFormat form = new MessageFormat
-                        (ResourcesMgr.getString
-                         (POLICY +
-                          ".error.adding.Permission.perm.message"));
                     Object[] source = {pe.permission,
                                        e.toString()};
-                    System.err.println(form.format(source));
+                    System.err.println(
+                        LocalizedMessage.getMessage(
+                            POLICY + ".error.adding.Permission.perm.message",
+                            source));
                 }
             }
 
             // No need to sync because noone has access to newInfo yet
             newInfo.policyEntries.add(entry);
         } catch (Exception e) {
-            MessageFormat form = new MessageFormat(ResourcesMgr.getString
-                                         (POLICY
-                                         + ".error.adding.Entry.message"));
             Object[] source = {e.toString()};
-            System.err.println(form.format(source));
+            System.err.println(
+                LocalizedMessage.getMessage(
+                    POLICY + ".error.adding.Entry.message",
+                    source));
         }
         if (debug != null)
             debug.println();
@@ -1803,29 +1799,29 @@
             } else if (prefix.equalsIgnoreCase("alias")) {
                 // get the suffix and perform keystore alias replacement
                 if (colonIndex == -1) {
-                    MessageFormat form = new MessageFormat
-                        (ResourcesMgr.getString
-                        ("alias.name.not.provided.pe.name."));
                     Object[] source = {pe.name};
-                    throw new Exception(form.format(source));
+                    throw new Exception(
+                        LocalizedMessage.getMessage(
+                            "alias.name.not.provided.pe.name.",
+                            source));
                 }
                 suffix = value.substring(colonIndex+1);
                 if ((suffix = getDN(suffix, keystore)) == null) {
-                    MessageFormat form = new MessageFormat
-                        (ResourcesMgr.getString
-                        ("unable.to.perform.substitution.on.alias.suffix"));
                     Object[] source = {value.substring(colonIndex+1)};
-                    throw new Exception(form.format(source));
+                    throw new Exception(
+                        LocalizedMessage.getMessage(
+                            "unable.to.perform.substitution.on.alias.suffix",
+                            source));
                 }
 
                 sb.append(X500PRINCIPAL + " \"" + suffix + "\"");
                 startIndex = e+2;
             } else {
-                MessageFormat form = new MessageFormat
-                        (ResourcesMgr.getString
-                        ("substitution.value.prefix.unsupported"));
                 Object[] source = {prefix};
-                throw new Exception(form.format(source));
+                throw new Exception(
+                    LocalizedMessage.getMessage(
+                        "substitution.value.prefix.unsupported",
+                        source));
             }
         }
 
@@ -2039,7 +2035,7 @@
             super(type);
             if (type == null) {
                 throw new NullPointerException
-                    (ResourcesMgr.getString("type.can.t.be.null"));
+                    (LocalizedMessage.getMessage("type.can.t.be.null"));
             }
             this.type = type;
             this.name = name;
--- a/jdk/src/java.base/share/classes/sun/security/provider/PolicyParser.java	Tue Jan 24 18:44:13 2017 +0300
+++ b/jdk/src/java.base/share/classes/sun/security/provider/PolicyParser.java	Thu Jan 26 09:19:33 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -26,18 +26,14 @@
 package sun.security.provider;
 
 import java.io.*;
-import java.lang.RuntimePermission;
-import java.net.SocketPermission;
-import java.net.URL;
 import java.security.GeneralSecurityException;
 import java.security.Principal;
-import java.text.MessageFormat;
 import java.util.*;
 import javax.security.auth.x500.X500Principal;
 
 import sun.security.util.Debug;
 import sun.security.util.PropertyExpander;
-import sun.security.util.ResourcesMgr;
+import sun.security.util.LocalizedMessage;
 
 /**
  * The policy for a Java runtime (specifying
@@ -209,13 +205,12 @@
                     if (!domainEntries.containsKey(domainName)) {
                         domainEntries.put(domainName, de);
                     } else {
-                        MessageFormat form =
-                            new MessageFormat(ResourcesMgr.getString(
-                                "duplicate.keystore.domain.name"));
+                        LocalizedMessage localizedMsg =
+                            new LocalizedMessage("duplicate.keystore.domain.name");
                         Object[] source = {domainName};
                         String msg = "duplicate keystore domain name: " +
                                      domainName;
-                        throw new ParsingException(msg, form, source);
+                        throw new ParsingException(msg, localizedMsg, source);
                     }
                 }
             } else {
@@ -225,7 +220,7 @@
         }
 
         if (keyStoreUrlString == null && storePassURL != null) {
-            throw new ParsingException(ResourcesMgr.getString
+            throw new ParsingException(LocalizedMessage.getMessage
                 ("keystorePasswordURL.can.not.be.specified.without.also.specifying.keystore"));
         }
     }
@@ -367,7 +362,7 @@
             keyStoreType = match("quoted string");
         } else {
             throw new ParsingException(st.lineno(),
-                        ResourcesMgr.getString("expected.keystore.type"));
+                LocalizedMessage.getMessage("expected.keystore.type"));
         }
 
         // parse keystore provider
@@ -380,7 +375,7 @@
             keyStoreProvider = match("quoted string");
         } else {
             throw new ParsingException(st.lineno(),
-                        ResourcesMgr.getString("expected.keystore.provider"));
+                LocalizedMessage.getMessage("expected.keystore.provider"));
         }
     }
 
@@ -430,7 +425,7 @@
                 if (e.codeBase != null)
                     throw new ParsingException(
                             st.lineno(),
-                            ResourcesMgr.getString
+                            LocalizedMessage.getMessage
                                 ("multiple.Codebase.expressions"));
                 e.codeBase = match("quoted string");
                 peekAndMatch(",");
@@ -438,8 +433,8 @@
                 if (e.signedBy != null)
                     throw new ParsingException(
                             st.lineno(),
-                            ResourcesMgr.getString(
-                                "multiple.SignedBy.expressions"));
+                            LocalizedMessage.getMessage
+                                ("multiple.SignedBy.expressions"));
                 e.signedBy = match("quoted string");
 
                 // verify syntax of the aliases
@@ -457,8 +452,8 @@
                 if (actr <= cctr)
                     throw new ParsingException(
                             st.lineno(),
-                            ResourcesMgr.getString(
-                                "SignedBy.has.empty.alias"));
+                            LocalizedMessage.getMessage
+                                ("SignedBy.has.empty.alias"));
 
                 peekAndMatch(",");
             } else if (peekAndMatch("Principal")) {
@@ -500,7 +495,7 @@
                         }
                         throw new ParsingException
                                 (st.lineno(),
-                                 ResourcesMgr.getString
+                                LocalizedMessage.getMessage
                                     ("can.not.specify.Principal.with.a.wildcard.class.without.a.wildcard.name"));
                     }
                 }
@@ -537,8 +532,8 @@
 
             } else {
                 throw new ParsingException(st.lineno(),
-                                  ResourcesMgr.getString(
-                                      "expected.codeBase.or.SignedBy.or.Principal"));
+                    LocalizedMessage.getMessage
+                        ("expected.codeBase.or.SignedBy.or.Principal"));
             }
         }
 
@@ -561,8 +556,8 @@
             } else {
                 throw new
                     ParsingException(st.lineno(),
-                                     ResourcesMgr.getString(
-                                        "expected.permission.entry"));
+                        LocalizedMessage.getMessage
+                            ("expected.permission.entry"));
             }
         }
         match("}");
@@ -738,15 +733,14 @@
         switch (lookahead) {
         case StreamTokenizer.TT_NUMBER:
             throw new ParsingException(st.lineno(), expect,
-                                       ResourcesMgr.getString("number.") +
-                                       String.valueOf(st.nval));
+                LocalizedMessage.getMessage("number.") +
+                    String.valueOf(st.nval));
         case StreamTokenizer.TT_EOF:
-            MessageFormat form = new MessageFormat(
-                    ResourcesMgr.getString
-                            ("expected.expect.read.end.of.file."));
+            LocalizedMessage localizedMsg = new LocalizedMessage
+                ("expected.expect.read.end.of.file.");
             Object[] source = {expect};
             String msg = "expected [" + expect + "], read [end of file]";
-            throw new ParsingException(msg, form, source);
+            throw new ParsingException(msg, localizedMsg, source);
         case StreamTokenizer.TT_WORD:
             if (expect.equalsIgnoreCase(st.sval)) {
                 lookahead = st.nextToken();
@@ -832,10 +826,10 @@
             switch (lookahead) {
             case StreamTokenizer.TT_NUMBER:
                 throw new ParsingException(st.lineno(), ";",
-                                          ResourcesMgr.getString("number.") +
-                                          String.valueOf(st.nval));
+                        LocalizedMessage.getMessage("number.") +
+                            String.valueOf(st.nval));
             case StreamTokenizer.TT_EOF:
-                throw new ParsingException(ResourcesMgr.getString
+                throw new ParsingException(LocalizedMessage.getMessage
                         ("expected.read.end.of.file."));
             default:
                 lookahead = st.nextToken();
@@ -993,8 +987,8 @@
          */
         public PrincipalEntry(String principalClass, String principalName) {
             if (principalClass == null || principalName == null)
-                throw new NullPointerException(ResourcesMgr.getString(
-                                  "null.principalClass.or.principalName"));
+                throw new NullPointerException(LocalizedMessage.getMessage
+                    ("null.principalClass.or.principalName"));
             this.principalClass = principalClass;
             this.principalName = principalName;
         }
@@ -1244,11 +1238,11 @@
             if (!entries.containsKey(keystoreName)) {
                 entries.put(keystoreName, entry);
             } else {
-                MessageFormat form = new MessageFormat(ResourcesMgr.getString(
-                    "duplicate.keystore.name"));
+                LocalizedMessage localizedMsg = new LocalizedMessage
+                    ("duplicate.keystore.name");
                 Object[] source = {keystoreName};
                 String msg = "duplicate keystore name: " + keystoreName;
-                throw new ParsingException(msg, form, source);
+                throw new ParsingException(msg, localizedMsg, source);
             }
         }
 
@@ -1320,7 +1314,7 @@
         private static final long serialVersionUID = -4330692689482574072L;
 
         private String i18nMessage;
-        private MessageFormat form;
+        private LocalizedMessage localizedMsg;
         private Object[] source;
 
         /**
@@ -1336,10 +1330,10 @@
             i18nMessage = msg;
         }
 
-        public ParsingException(String msg, MessageFormat form,
+        public ParsingException(String msg, LocalizedMessage localizedMsg,
                                 Object[] source) {
             super(msg);
-            this.form = form;
+            this.localizedMsg = localizedMsg;
             this.source = source;
         }
 
@@ -1347,7 +1341,7 @@
             super("line " + line + ": " + msg);
             // don't call form.format unless getLocalizedMessage is called
             // to avoid unnecessary permission checks
-            form = new MessageFormat(ResourcesMgr.getString("line.number.msg"));
+            localizedMsg = new LocalizedMessage("line.number.msg");
             source = new Object[] {line, msg};
         }
 
@@ -1356,14 +1350,14 @@
                 "], found [" + actual + "]");
             // don't call form.format unless getLocalizedMessage is called
             // to avoid unnecessary permission checks
-            form = new MessageFormat(ResourcesMgr.getString
-                ("line.number.expected.expect.found.actual."));
+            localizedMsg = new LocalizedMessage
+                ("line.number.expected.expect.found.actual.");
             source = new Object[] {line, expect, actual};
         }
 
         @Override
         public String getLocalizedMessage() {
-            return i18nMessage != null ? i18nMessage : form.format(source);
+            return i18nMessage != null ? i18nMessage : localizedMsg.format(source);
         }
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/util/LocalizedMessage.java	Thu Jan 26 09:19:33 2017 -0800
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2017, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package sun.security.util;
+
+/**
+ * This class produces formatted and localized messages describing security
+ * issues. Some messages may be required when the VM is not fully booted. In
+ * this case, localization resources and classes used for message formatting
+ * may not be available. When the VM is not booted, the message will not be
+ * localized, and it will be formatted using simplified message formatting
+ * code that is contained in this class.
+ */
+
+/*
+ * Some of this code is executed before the VM is fully booted. Some import
+ * statements have been omitted to help prevent accidental use of classes that
+ * may not be available during boot.
+ */
+
+public class LocalizedMessage {
+
+    private static final Resources resources = new Resources();
+
+    private final String key;
+
+    /**
+     * A LocalizedMessage can be instantiated with a key and formatted with
+     * arguments later in the style of MessageFormat. This organization
+     * allows the actual formatting (and associated permission checks) to be
+     * avoided unless the resulting string is needed.
+     * @param key
+     */
+    public LocalizedMessage(String key) {
+        this.key = key;
+    }
+
+    /**
+     * Return a localized string corresponding to the key stored in this
+     * object, formatted with the provided arguments. When the VM is booted,
+     * this method will obtain the correct localized message and format it
+     * using java.text.MessageFormat. Otherwise, a non-localized string is
+     * returned, and the formatting is performed by simplified formatting code.
+     *
+     * @param arguments The arguments that should be placed in the message
+     * @return A formatted message string
+     */
+    public String format(Object... arguments) {
+        return getMessage(key, arguments);
+    }
+
+    /**
+     * Return a non-localized string corresponding to the provided key, and
+     * formatted with the provided arguments. All strings are obtained from
+     * sun.security.util.Resources, and the formatting only supports
+     * simple positional argument replacement (e.g. {1}).
+     *
+     * @param key The key of the desired string in Resources
+     * @param arguments The arguments that should be placed in the message
+     * @return A formatted message string
+     */
+    public static String getMessageUnbooted(String key,
+                                            Object... arguments) {
+
+        String value = resources.getString(key);
+        if (arguments == null || arguments.length == 0) {
+            return value;
+        }
+        // Classes like StringTokenizer may not be loaded, so parsing
+        //   is performed with String methods
+        StringBuilder sb = new StringBuilder();
+        int nextBraceIndex;
+        while ((nextBraceIndex = value.indexOf('{')) >= 0) {
+
+            String firstPart = value.substring(0, nextBraceIndex);
+            sb.append(firstPart);
+            value = value.substring(nextBraceIndex + 1);
+
+            // look for closing brace and argument index
+            nextBraceIndex = value.indexOf('}');
+            if (nextBraceIndex < 0) {
+                // no closing brace
+                // MessageFormat would throw IllegalArgumentException, but
+                //   that exception class may not be loaded yet
+                throw new RuntimeException("Unmatched braces");
+            }
+            String indexStr = value.substring(0, nextBraceIndex);
+            try {
+                int index = Integer.parseInt(indexStr);
+                sb.append(arguments[index]);
+            }
+            catch(NumberFormatException e) {
+                // argument index is not an integer
+                throw new RuntimeException("not an integer: " + indexStr);
+            }
+            value = value.substring(nextBraceIndex + 1);
+        }
+        sb.append(value);
+        return sb.toString();
+    }
+
+    /**
+     * Return a localized string corresponding to the provided key, and
+     * formatted with the provided arguments. When the VM is booted, this
+     * method will obtain the correct localized message and format it using
+     * java.text.MessageFormat. Otherwise, a non-localized string is returned,
+     * and the formatting is performed by simplified formatting code.
+     *
+     * @param key The key of the desired string in the security resource bundle
+     * @param arguments The arguments that should be placed in the message
+     * @return A formatted message string
+     */
+    public static String getMessage(String key,
+                                    Object... arguments) {
+
+        if (jdk.internal.misc.VM.isBooted()) {
+            // Localization and formatting resources are available
+            String value = ResourcesMgr.getString(key);
+            if (arguments == null) {
+                return value;
+            }
+            java.text.MessageFormat form = new java.text.MessageFormat(value);
+            return form.format(arguments);
+        } else {
+            return getMessageUnbooted(key, arguments);
+        }
+    }
+
+}
--- a/jdk/src/java.base/share/classes/sun/security/util/ResourcesMgr.java	Tue Jan 24 18:44:13 2017 +0300
+++ b/jdk/src/java.base/share/classes/sun/security/util/ResourcesMgr.java	Thu Jan 26 09:19:33 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, 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
@@ -34,37 +34,24 @@
  */
 public class ResourcesMgr {
     // intended for java.security, javax.security and sun.security resources
-    private final static String RESOURCES = "sun.security.util.Resources";
-    private final static String AUTH_RESOURCES = "sun.security.util.AuthResources";
-
     private final static Map<String, ResourceBundle> bundles = new ConcurrentHashMap<>();
 
     public static String getString(String s) {
-        ResourceBundle bundle = bundles.get(RESOURCES);
-        if (bundle == null) {
-
-            // only load if/when needed
-            bundle = java.security.AccessController.doPrivileged(
-                new java.security.PrivilegedAction<java.util.ResourceBundle>() {
-                public java.util.ResourceBundle run() {
-                    return (java.util.ResourceBundle.getBundle
-                                ("sun.security.util.Resources"));
-                }
-            });
-        }
-
-        return bundle.getString(s);
+        return getBundle("sun.security.util.Resources").getString(s);
     }
 
     public static String getAuthResourceString(String s) {
-        if (VM.initLevel() == 3) {
-            // cannot trigger loading of any resource bundle as
-            // it depends on the system class loader fully initialized.
-            throw new InternalError("system class loader is being initialized");
+        return getBundle("sun.security.util.AuthResources").getString(s);
+    }
+
+    private static ResourceBundle getBundle(String bundleName) {
+        if (!VM.isBooted()) {
+            // don't expect this be called before the system is fully initialized.
+            // This triggers loading of any resource bundle that should be
+            // be done during initialization of system class loader.
+            throw new InternalError("Expected to use ResourceBundle only after booted");
         }
-
-        return bundles.computeIfAbsent(AUTH_RESOURCES, ResourceBundle::getBundle)
-                      .getString(s);
+        return bundles.computeIfAbsent(bundleName, ResourceBundle::getBundle);
     }
 
 }
--- a/jdk/src/java.base/share/classes/sun/util/cldr/CLDRLocaleProviderAdapter.java	Tue Jan 24 18:44:13 2017 +0300
+++ b/jdk/src/java.base/share/classes/sun/util/cldr/CLDRLocaleProviderAdapter.java	Thu Jan 26 09:19:33 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, 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
@@ -195,9 +195,26 @@
         return parent;
     }
 
+    /**
+     * This method returns equivalent CLDR supported locale for zh-HK,
+     * no, no-NO locales so that COMPAT locales do not precede
+     * those locales during ResourceBundle search path.
+     */
+    private static Locale getEquivalentLoc(Locale locale) {
+        switch (locale.toString()) {
+            case "zh_HK":
+                return Locale.forLanguageTag("zh-Hant-HK");
+            case "no":
+            case "no_NO":
+                return Locale.forLanguageTag("nb");
+        }
+        return locale;
+    }
+
     @Override
     public boolean isSupportedProviderLocale(Locale locale, Set<String> langtags) {
-        return Locale.ROOT.equals(locale) ||
-            langtags.contains(locale.stripExtensions().toLanguageTag());
+        return Locale.ROOT.equals(locale)
+                || langtags.contains(locale.stripExtensions().toLanguageTag())
+                || langtags.contains(getEquivalentLoc(locale).toLanguageTag());
     }
 }
--- a/jdk/src/java.base/share/lib/security/default.policy	Tue Jan 24 18:44:13 2017 +0300
+++ b/jdk/src/java.base/share/lib/security/default.policy	Thu Jan 26 09:19:33 2017 -0800
@@ -137,7 +137,7 @@
     permission java.security.SecurityPermission "removeProviderProperty.SunEC";
 };
 
-grant codeBase "jrt:/jdk.crypto.token" {
+grant codeBase "jrt:/jdk.crypto.cryptoki" {
     permission java.lang.RuntimePermission
                    "accessClassInPackage.sun.security.*";
     permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.cryptoki/share/classes/module-info.java	Thu Jan 26 09:19:33 2017 -0800
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2014, 2017, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+module jdk.crypto.cryptoki {
+    // Depends on SunEC provider for EC related functionality
+    requires jdk.crypto.ec;
+    provides java.security.Provider with sun.security.pkcs11.SunPKCS11;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java	Thu Jan 26 09:19:33 2017 -0800
@@ -0,0 +1,1008 @@
+/*
+ * Copyright (c) 2003, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package sun.security.pkcs11;
+
+import java.io.*;
+import static java.io.StreamTokenizer.*;
+import java.math.BigInteger;
+import java.util.*;
+
+import java.security.*;
+
+import sun.security.util.PropertyExpander;
+
+import sun.security.pkcs11.wrapper.*;
+import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
+import static sun.security.pkcs11.wrapper.CK_ATTRIBUTE.*;
+
+import static sun.security.pkcs11.TemplateManager.*;
+
+/**
+ * Configuration container and file parsing.
+ *
+ * @author  Andreas Sterbenz
+ * @since   1.5
+ */
+final class Config {
+
+    static final int ERR_HALT       = 1;
+    static final int ERR_IGNORE_ALL = 2;
+    static final int ERR_IGNORE_LIB = 3;
+
+    // same as allowSingleThreadedModules but controlled via a system property
+    // and applied to all providers. if set to false, no SunPKCS11 instances
+    // will accept single threaded modules regardless of the setting in their
+    // config files.
+    private static final boolean staticAllowSingleThreadedModules;
+    private static final String osName;
+    private static final String osArch;
+
+    static {
+        List<String> props = AccessController.doPrivileged(
+            new PrivilegedAction<>() {
+                @Override
+                public List<String> run() {
+                    return List.of(
+                        System.getProperty(
+                            "sun.security.pkcs11.allowSingleThreadedModules",
+                            "true"),
+                        System.getProperty("os.name"),
+                        System.getProperty("os.arch"));
+                }
+            }
+        );
+        if ("false".equalsIgnoreCase(props.get(0))) {
+            staticAllowSingleThreadedModules = false;
+        } else {
+            staticAllowSingleThreadedModules = true;
+        }
+        osName = props.get(1);
+        osArch = props.get(2);
+    }
+
+    private final static boolean DEBUG = false;
+
+    private static void debug(Object o) {
+        if (DEBUG) {
+            System.out.println(o);
+        }
+    }
+
+    // file name containing this configuration
+    private String filename;
+
+    // Reader and StringTokenizer used during parsing
+    private Reader reader;
+
+    private StreamTokenizer st;
+
+    private Set<String> parsedKeywords;
+
+    // name suffix of the provider
+    private String name;
+
+    // name of the PKCS#11 library
+    private String library;
+
+    // description to pass to the provider class
+    private String description;
+
+    // slotID of the slot to use
+    private int slotID = -1;
+
+    // slot to use, specified as index in the slotlist
+    private int slotListIndex = -1;
+
+    // set of enabled mechanisms (or null to use default)
+    private Set<Long> enabledMechanisms;
+
+    // set of disabled mechanisms
+    private Set<Long> disabledMechanisms;
+
+    // whether to print debug info during startup
+    private boolean showInfo = false;
+
+    // template manager, initialized from parsed attributes
+    private TemplateManager templateManager;
+
+    // how to handle error during startup, one of ERR_
+    private int handleStartupErrors = ERR_HALT;
+
+    // flag indicating whether the P11KeyStore should
+    // be more tolerant of input parameters
+    private boolean keyStoreCompatibilityMode = true;
+
+    // flag indicating whether we need to explicitly cancel operations
+    // see Token
+    private boolean explicitCancel = true;
+
+    // how often to test for token insertion, if no token is present
+    private int insertionCheckInterval = 2000;
+
+    // flag inidicating whether to omit the call to C_Initialize()
+    // should be used only if we are running within a process that
+    // has already called it (e.g. Plugin inside of Mozilla/NSS)
+    private boolean omitInitialize = false;
+
+    // whether to allow modules that only support single threaded access.
+    // they cannot be used safely from multiple PKCS#11 consumers in the
+    // same process, for example NSS and SunPKCS11
+    private boolean allowSingleThreadedModules = true;
+
+    // name of the C function that returns the PKCS#11 functionlist
+    // This option primarily exists for the deprecated
+    // Secmod.Module.getProvider() method.
+    private String functionList = "C_GetFunctionList";
+
+    // whether to use NSS secmod mode. Implicitly set if nssLibraryDirectory,
+    // nssSecmodDirectory, or nssModule is specified.
+    private boolean nssUseSecmod;
+
+    // location of the NSS library files (libnss3.so, etc.)
+    private String nssLibraryDirectory;
+
+    // location of secmod.db
+    private String nssSecmodDirectory;
+
+    // which NSS module to use
+    private String nssModule;
+
+    private Secmod.DbMode nssDbMode = Secmod.DbMode.READ_WRITE;
+
+    // Whether the P11KeyStore should specify the CKA_NETSCAPE_DB attribute
+    // when creating private keys. Only valid if nssUseSecmod is true.
+    private boolean nssNetscapeDbWorkaround = true;
+
+    // Special init argument string for the NSS softtoken.
+    // This is used when using the NSS softtoken directly without secmod mode.
+    private String nssArgs;
+
+    // whether to use NSS trust attributes for the KeyStore of this provider
+    // this option is for internal use by the SunPKCS11 code only and
+    // works only for NSS providers created via the Secmod API
+    private boolean nssUseSecmodTrust = false;
+
+    // Flag to indicate whether the X9.63 encoding for EC points shall be used
+    // (true) or whether that encoding shall be wrapped in an ASN.1 OctetString
+    // (false).
+    private boolean useEcX963Encoding = false;
+
+    // Flag to indicate whether NSS should favour performance (false) or
+    // memory footprint (true).
+    private boolean nssOptimizeSpace = false;
+
+    Config(String fn) throws IOException {
+        this.filename = fn;
+        if (filename.startsWith("--")) {
+            // inline config
+            String config = filename.substring(2).replace("\\n", "\n");
+            reader = new StringReader(config);
+        } else {
+            reader = new BufferedReader(new InputStreamReader
+                (new FileInputStream(expand(filename))));
+        }
+        parsedKeywords = new HashSet<String>();
+        st = new StreamTokenizer(reader);
+        setupTokenizer();
+        parse();
+    }
+
+    String getFileName() {
+        return filename;
+    }
+
+    String getName() {
+        return name;
+    }
+
+    String getLibrary() {
+        return library;
+    }
+
+    String getDescription() {
+        if (description != null) {
+            return description;
+        }
+        return "SunPKCS11-" + name + " using library " + library;
+    }
+
+    int getSlotID() {
+        return slotID;
+    }
+
+    int getSlotListIndex() {
+        if ((slotID == -1) && (slotListIndex == -1)) {
+            // if neither is set, default to first slot
+            return 0;
+        } else {
+            return slotListIndex;
+        }
+    }
+
+    boolean getShowInfo() {
+        return (SunPKCS11.debug != null) || showInfo;
+    }
+
+    TemplateManager getTemplateManager() {
+        if (templateManager == null) {
+            templateManager = new TemplateManager();
+        }
+        return templateManager;
+    }
+
+    boolean isEnabled(long m) {
+        if (enabledMechanisms != null) {
+            return enabledMechanisms.contains(Long.valueOf(m));
+        }
+        if (disabledMechanisms != null) {
+            return !disabledMechanisms.contains(Long.valueOf(m));
+        }
+        return true;
+    }
+
+    int getHandleStartupErrors() {
+        return handleStartupErrors;
+    }
+
+    boolean getKeyStoreCompatibilityMode() {
+        return keyStoreCompatibilityMode;
+    }
+
+    boolean getExplicitCancel() {
+        return explicitCancel;
+    }
+
+    int getInsertionCheckInterval() {
+        return insertionCheckInterval;
+    }
+
+    boolean getOmitInitialize() {
+        return omitInitialize;
+    }
+
+    boolean getAllowSingleThreadedModules() {
+        return staticAllowSingleThreadedModules && allowSingleThreadedModules;
+    }
+
+    String getFunctionList() {
+        return functionList;
+    }
+
+    boolean getNssUseSecmod() {
+        return nssUseSecmod;
+    }
+
+    String getNssLibraryDirectory() {
+        return nssLibraryDirectory;
+    }
+
+    String getNssSecmodDirectory() {
+        return nssSecmodDirectory;
+    }
+
+    String getNssModule() {
+        return nssModule;
+    }
+
+    Secmod.DbMode getNssDbMode() {
+        return nssDbMode;
+    }
+
+    public boolean getNssNetscapeDbWorkaround() {
+        return nssUseSecmod && nssNetscapeDbWorkaround;
+    }
+
+    String getNssArgs() {
+        return nssArgs;
+    }
+
+    boolean getNssUseSecmodTrust() {
+        return nssUseSecmodTrust;
+    }
+
+    boolean getUseEcX963Encoding() {
+        return useEcX963Encoding;
+    }
+
+    boolean getNssOptimizeSpace() {
+        return nssOptimizeSpace;
+    }
+
+    private static String expand(final String s) throws IOException {
+        try {
+            return PropertyExpander.expand(s);
+        } catch (Exception e) {
+            throw new RuntimeException(e.getMessage());
+        }
+    }
+
+    private void setupTokenizer() {
+        st.resetSyntax();
+        st.wordChars('a', 'z');
+        st.wordChars('A', 'Z');
+        st.wordChars('0', '9');
+        st.wordChars(':', ':');
+        st.wordChars('.', '.');
+        st.wordChars('_', '_');
+        st.wordChars('-', '-');
+        st.wordChars('/', '/');
+        st.wordChars('\\', '\\');
+        st.wordChars('$', '$');
+        st.wordChars('{', '{'); // need {} for property subst
+        st.wordChars('}', '}');
+        st.wordChars('*', '*');
+        st.wordChars('+', '+');
+        st.wordChars('~', '~');
+        // XXX check ASCII table and add all other characters except special
+
+        // special: #="(),
+        st.whitespaceChars(0, ' ');
+        st.commentChar('#');
+        st.eolIsSignificant(true);
+        st.quoteChar('\"');
+    }
+
+    private ConfigurationException excToken(String msg) {
+        return new ConfigurationException(msg + " " + st);
+    }
+
+    private ConfigurationException excLine(String msg) {
+        return new ConfigurationException(msg + ", line " + st.lineno());
+    }
+
+    private void parse() throws IOException {
+        while (true) {
+            int token = nextToken();
+            if (token == TT_EOF) {
+                break;
+            }
+            if (token == TT_EOL) {
+                continue;
+            }
+            if (token != TT_WORD) {
+                throw excToken("Unexpected token:");
+            }
+            String word = st.sval;
+            if (word.equals("name")) {
+                name = parseStringEntry(word);
+            } else if (word.equals("library")) {
+                library = parseLibrary(word);
+            } else if (word.equals("description")) {
+                parseDescription(word);
+            } else if (word.equals("slot")) {
+                parseSlotID(word);
+            } else if (word.equals("slotListIndex")) {
+                parseSlotListIndex(word);
+            } else if (word.equals("enabledMechanisms")) {
+                parseEnabledMechanisms(word);
+            } else if (word.equals("disabledMechanisms")) {
+                parseDisabledMechanisms(word);
+            } else if (word.equals("attributes")) {
+                parseAttributes(word);
+            } else if (word.equals("handleStartupErrors")) {
+                parseHandleStartupErrors(word);
+            } else if (word.endsWith("insertionCheckInterval")) {
+                insertionCheckInterval = parseIntegerEntry(word);
+                if (insertionCheckInterval < 100) {
+                    throw excLine(word + " must be at least 100 ms");
+                }
+            } else if (word.equals("showInfo")) {
+                showInfo = parseBooleanEntry(word);
+            } else if (word.equals("keyStoreCompatibilityMode")) {
+                keyStoreCompatibilityMode = parseBooleanEntry(word);
+            } else if (word.equals("explicitCancel")) {
+                explicitCancel = parseBooleanEntry(word);
+            } else if (word.equals("omitInitialize")) {
+                omitInitialize = parseBooleanEntry(word);
+            } else if (word.equals("allowSingleThreadedModules")) {
+                allowSingleThreadedModules = parseBooleanEntry(word);
+            } else if (word.equals("functionList")) {
+                functionList = parseStringEntry(word);
+            } else if (word.equals("nssUseSecmod")) {
+                nssUseSecmod = parseBooleanEntry(word);
+            } else if (word.equals("nssLibraryDirectory")) {
+                nssLibraryDirectory = parseLibrary(word);
+                nssUseSecmod = true;
+            } else if (word.equals("nssSecmodDirectory")) {
+                nssSecmodDirectory = expand(parseStringEntry(word));
+                nssUseSecmod = true;
+            } else if (word.equals("nssModule")) {
+                nssModule = parseStringEntry(word);
+                nssUseSecmod = true;
+            } else if (word.equals("nssDbMode")) {
+                String mode = parseStringEntry(word);
+                if (mode.equals("readWrite")) {
+                    nssDbMode = Secmod.DbMode.READ_WRITE;
+                } else if (mode.equals("readOnly")) {
+                    nssDbMode = Secmod.DbMode.READ_ONLY;
+                } else if (mode.equals("noDb")) {
+                    nssDbMode = Secmod.DbMode.NO_DB;
+                } else {
+                    throw excToken("nssDbMode must be one of readWrite, readOnly, and noDb:");
+                }
+                nssUseSecmod = true;
+            } else if (word.equals("nssNetscapeDbWorkaround")) {
+                nssNetscapeDbWorkaround = parseBooleanEntry(word);
+                nssUseSecmod = true;
+            } else if (word.equals("nssArgs")) {
+                parseNSSArgs(word);
+            } else if (word.equals("nssUseSecmodTrust")) {
+                nssUseSecmodTrust = parseBooleanEntry(word);
+            } else if (word.equals("useEcX963Encoding")) {
+                useEcX963Encoding = parseBooleanEntry(word);
+            } else if (word.equals("nssOptimizeSpace")) {
+                nssOptimizeSpace = parseBooleanEntry(word);
+            } else {
+                throw new ConfigurationException
+                        ("Unknown keyword '" + word + "', line " + st.lineno());
+            }
+            parsedKeywords.add(word);
+        }
+        reader.close();
+        reader = null;
+        st = null;
+        parsedKeywords = null;
+        if (name == null) {
+            throw new ConfigurationException("name must be specified");
+        }
+        if (nssUseSecmod == false) {
+            if (library == null) {
+                throw new ConfigurationException("library must be specified");
+            }
+        } else {
+            if (library != null) {
+                throw new ConfigurationException
+                    ("library must not be specified in NSS mode");
+            }
+            if ((slotID != -1) || (slotListIndex != -1)) {
+                throw new ConfigurationException
+                    ("slot and slotListIndex must not be specified in NSS mode");
+            }
+            if (nssArgs != null) {
+                throw new ConfigurationException
+                    ("nssArgs must not be specified in NSS mode");
+            }
+            if (nssUseSecmodTrust != false) {
+                throw new ConfigurationException("nssUseSecmodTrust is an "
+                    + "internal option and must not be specified in NSS mode");
+            }
+        }
+    }
+
+    //
+    // Parsing helper methods
+    //
+
+    private int nextToken() throws IOException {
+        int token = st.nextToken();
+        debug(st);
+        return token;
+    }
+
+    private void parseEquals() throws IOException {
+        int token = nextToken();
+        if (token != '=') {
+            throw excToken("Expected '=', read");
+        }
+    }
+
+    private void parseOpenBraces() throws IOException {
+        while (true) {
+            int token = nextToken();
+            if (token == TT_EOL) {
+                continue;
+            }
+            if ((token == TT_WORD) && st.sval.equals("{")) {
+                return;
+            }
+            throw excToken("Expected '{', read");
+        }
+    }
+
+    private boolean isCloseBraces(int token) {
+        return (token == TT_WORD) && st.sval.equals("}");
+    }
+
+    private String parseWord() throws IOException {
+        int token = nextToken();
+        if (token != TT_WORD) {
+            throw excToken("Unexpected value:");
+        }
+        return st.sval;
+    }
+
+    private String parseStringEntry(String keyword) throws IOException {
+        checkDup(keyword);
+        parseEquals();
+
+        int token = nextToken();
+        if (token != TT_WORD && token != '\"') {
+            // not a word token nor a string enclosed by double quotes
+            throw excToken("Unexpected value:");
+        }
+        String value = st.sval;
+
+        debug(keyword + ": " + value);
+        return value;
+    }
+
+    private boolean parseBooleanEntry(String keyword) throws IOException {
+        checkDup(keyword);
+        parseEquals();
+        boolean value = parseBoolean();
+        debug(keyword + ": " + value);
+        return value;
+    }
+
+    private int parseIntegerEntry(String keyword) throws IOException {
+        checkDup(keyword);
+        parseEquals();
+        int value = decodeNumber(parseWord());
+        debug(keyword + ": " + value);
+        return value;
+    }
+
+    private boolean parseBoolean() throws IOException {
+        String val = parseWord();
+        switch (val) {
+            case "true":
+                return true;
+            case "false":
+                return false;
+            default:
+                throw excToken("Expected boolean value, read:");
+        }
+    }
+
+    private String parseLine() throws IOException {
+        // allow quoted string as part of line
+        String s = null;
+        while (true) {
+            int token = nextToken();
+            if ((token == TT_EOL) || (token == TT_EOF)) {
+                break;
+            }
+            if (token != TT_WORD && token != '\"') {
+                throw excToken("Unexpected value");
+            }
+            if (s == null) {
+                s = st.sval;
+            } else {
+                s = s + " " + st.sval;
+            }
+        }
+        if (s == null) {
+            throw excToken("Unexpected empty line");
+        }
+        return s;
+    }
+
+    private int decodeNumber(String str) throws IOException {
+        try {
+            if (str.startsWith("0x") || str.startsWith("0X")) {
+                return Integer.parseInt(str.substring(2), 16);
+            } else {
+                return Integer.parseInt(str);
+            }
+        } catch (NumberFormatException e) {
+            throw excToken("Expected number, read");
+        }
+    }
+
+    private static boolean isNumber(String s) {
+        if (s.length() == 0) {
+            return false;
+        }
+        char ch = s.charAt(0);
+        return ((ch >= '0') && (ch <= '9'));
+    }
+
+    private void parseComma() throws IOException {
+        int token = nextToken();
+        if (token != ',') {
+            throw excToken("Expected ',', read");
+        }
+    }
+
+    private static boolean isByteArray(String val) {
+        return val.startsWith("0h");
+    }
+
+    private byte[] decodeByteArray(String str) throws IOException {
+        if (str.startsWith("0h") == false) {
+            throw excToken("Expected byte array value, read");
+        }
+        str = str.substring(2);
+        // XXX proper hex parsing
+        try {
+            return new BigInteger(str, 16).toByteArray();
+        } catch (NumberFormatException e) {
+            throw excToken("Expected byte array value, read");
+        }
+    }
+
+    private void checkDup(String keyword) throws IOException {
+        if (parsedKeywords.contains(keyword)) {
+            throw excLine(keyword + " must only be specified once");
+        }
+    }
+
+    //
+    // individual entry parsing methods
+    //
+
+    private String parseLibrary(String keyword) throws IOException {
+        checkDup(keyword);
+        parseEquals();
+        String lib = parseLine();
+        lib = expand(lib);
+        int i = lib.indexOf("/$ISA/");
+        if (i != -1) {
+            // replace "/$ISA/" with "/sparcv9/" on 64-bit Solaris SPARC
+            // and with "/amd64/" on Solaris AMD64.
+            // On all other platforms, just turn it into a "/"
+            String prefix = lib.substring(0, i);
+            String suffix = lib.substring(i + 5);
+            if (osName.equals("SunOS") && osArch.equals("sparcv9")) {
+                lib = prefix + "/sparcv9" + suffix;
+            } else if (osName.equals("SunOS") && osArch.equals("amd64")) {
+                lib = prefix + "/amd64" + suffix;
+            } else {
+                lib = prefix + suffix;
+            }
+        }
+        debug(keyword + ": " + lib);
+
+        // Check to see if full path is specified to prevent the DLL
+        // preloading attack
+        if (!(new File(lib)).isAbsolute()) {
+            throw new ConfigurationException(
+                "Absolute path required for library value: " + lib);
+        }
+        return lib;
+    }
+
+    private void parseDescription(String keyword) throws IOException {
+        checkDup(keyword);
+        parseEquals();
+        description = parseLine();
+        debug("description: " + description);
+    }
+
+    private void parseSlotID(String keyword) throws IOException {
+        if (slotID >= 0) {
+            throw excLine("Duplicate slot definition");
+        }
+        if (slotListIndex >= 0) {
+            throw excLine
+                ("Only one of slot and slotListIndex must be specified");
+        }
+        parseEquals();
+        String slotString = parseWord();
+        slotID = decodeNumber(slotString);
+        debug("slot: " + slotID);
+    }
+
+    private void parseSlotListIndex(String keyword) throws IOException {
+        if (slotListIndex >= 0) {
+            throw excLine("Duplicate slotListIndex definition");
+        }
+        if (slotID >= 0) {
+            throw excLine
+                ("Only one of slot and slotListIndex must be specified");
+        }
+        parseEquals();
+        String slotString = parseWord();
+        slotListIndex = decodeNumber(slotString);
+        debug("slotListIndex: " + slotListIndex);
+    }
+
+    private void parseEnabledMechanisms(String keyword) throws IOException {
+        enabledMechanisms = parseMechanisms(keyword);
+    }
+
+    private void parseDisabledMechanisms(String keyword) throws IOException {
+        disabledMechanisms = parseMechanisms(keyword);
+    }
+
+    private Set<Long> parseMechanisms(String keyword) throws IOException {
+        checkDup(keyword);
+        Set<Long> mechs = new HashSet<Long>();
+        parseEquals();
+        parseOpenBraces();
+        while (true) {
+            int token = nextToken();
+            if (isCloseBraces(token)) {
+                break;
+            }
+            if (token == TT_EOL) {
+                continue;
+            }
+            if (token != TT_WORD) {
+                throw excToken("Expected mechanism, read");
+            }
+            long mech = parseMechanism(st.sval);
+            mechs.add(Long.valueOf(mech));
+        }
+        if (DEBUG) {
+            System.out.print("mechanisms: [");
+            for (Long mech : mechs) {
+                System.out.print(Functions.getMechanismName(mech));
+                System.out.print(", ");
+            }
+            System.out.println("]");
+        }
+        return mechs;
+    }
+
+    private long parseMechanism(String mech) throws IOException {
+        if (isNumber(mech)) {
+            return decodeNumber(mech);
+        } else {
+            try {
+                return Functions.getMechanismId(mech);
+            } catch (IllegalArgumentException e) {
+                throw excLine("Unknown mechanism: " + mech);
+            }
+        }
+    }
+
+    private void parseAttributes(String keyword) throws IOException {
+        if (templateManager == null) {
+            templateManager = new TemplateManager();
+        }
+        int token = nextToken();
+        if (token == '=') {
+            String s = parseWord();
+            if (s.equals("compatibility") == false) {
+                throw excLine("Expected 'compatibility', read " + s);
+            }
+            setCompatibilityAttributes();
+            return;
+        }
+        if (token != '(') {
+            throw excToken("Expected '(' or '=', read");
+        }
+        String op = parseOperation();
+        parseComma();
+        long objectClass = parseObjectClass();
+        parseComma();
+        long keyAlg = parseKeyAlgorithm();
+        token = nextToken();
+        if (token != ')') {
+            throw excToken("Expected ')', read");
+        }
+        parseEquals();
+        parseOpenBraces();
+        List<CK_ATTRIBUTE> attributes = new ArrayList<CK_ATTRIBUTE>();
+        while (true) {
+            token = nextToken();
+            if (isCloseBraces(token)) {
+                break;
+            }
+            if (token == TT_EOL) {
+                continue;
+            }
+            if (token != TT_WORD) {
+                throw excToken("Expected mechanism, read");
+            }
+            String attributeName = st.sval;
+            long attributeId = decodeAttributeName(attributeName);
+            parseEquals();
+            String attributeValue = parseWord();
+            attributes.add(decodeAttributeValue(attributeId, attributeValue));
+        }
+        templateManager.addTemplate
+                (op, objectClass, keyAlg, attributes.toArray(CK_A0));
+    }
+
+    private void setCompatibilityAttributes() {
+        // all secret keys
+        templateManager.addTemplate(O_ANY, CKO_SECRET_KEY, PCKK_ANY,
+        new CK_ATTRIBUTE[] {
+            TOKEN_FALSE,
+            SENSITIVE_FALSE,
+            EXTRACTABLE_TRUE,
+            ENCRYPT_TRUE,
+            DECRYPT_TRUE,
+            WRAP_TRUE,
+            UNWRAP_TRUE,
+        });
+
+        // generic secret keys are special
+        // They are used as MAC keys plus for the SSL/TLS (pre)master secrets
+        templateManager.addTemplate(O_ANY, CKO_SECRET_KEY, CKK_GENERIC_SECRET,
+        new CK_ATTRIBUTE[] {
+            SIGN_TRUE,
+            VERIFY_TRUE,
+            ENCRYPT_NULL,
+            DECRYPT_NULL,
+            WRAP_NULL,
+            UNWRAP_NULL,
+            DERIVE_TRUE,
+        });
+
+        // all private and public keys
+        templateManager.addTemplate(O_ANY, CKO_PRIVATE_KEY, PCKK_ANY,
+        new CK_ATTRIBUTE[] {
+            TOKEN_FALSE,
+            SENSITIVE_FALSE,
+            EXTRACTABLE_TRUE,
+        });
+        templateManager.addTemplate(O_ANY, CKO_PUBLIC_KEY, PCKK_ANY,
+        new CK_ATTRIBUTE[] {
+            TOKEN_FALSE,
+        });
+
+        // additional attributes for RSA private keys
+        templateManager.addTemplate(O_ANY, CKO_PRIVATE_KEY, CKK_RSA,
+        new CK_ATTRIBUTE[] {
+            DECRYPT_TRUE,
+            SIGN_TRUE,
+            SIGN_RECOVER_TRUE,
+            UNWRAP_TRUE,
+        });
+        // additional attributes for RSA public keys
+        templateManager.addTemplate(O_ANY, CKO_PUBLIC_KEY, CKK_RSA,
+        new CK_ATTRIBUTE[] {
+            ENCRYPT_TRUE,
+            VERIFY_TRUE,
+            VERIFY_RECOVER_TRUE,
+            WRAP_TRUE,
+        });
+
+        // additional attributes for DSA private keys
+        templateManager.addTemplate(O_ANY, CKO_PRIVATE_KEY, CKK_DSA,
+        new CK_ATTRIBUTE[] {
+            SIGN_TRUE,
+        });
+        // additional attributes for DSA public keys
+        templateManager.addTemplate(O_ANY, CKO_PUBLIC_KEY, CKK_DSA,
+        new CK_ATTRIBUTE[] {
+            VERIFY_TRUE,
+        });
+
+        // additional attributes for DH private keys
+        templateManager.addTemplate(O_ANY, CKO_PRIVATE_KEY, CKK_DH,
+        new CK_ATTRIBUTE[] {
+            DERIVE_TRUE,
+        });
+
+        // additional attributes for EC private keys
+        templateManager.addTemplate(O_ANY, CKO_PRIVATE_KEY, CKK_EC,
+        new CK_ATTRIBUTE[] {
+            SIGN_TRUE,
+            DERIVE_TRUE,
+        });
+        // additional attributes for EC public keys
+        templateManager.addTemplate(O_ANY, CKO_PUBLIC_KEY, CKK_EC,
+        new CK_ATTRIBUTE[] {
+            VERIFY_TRUE,
+        });
+    }
+
+    private final static CK_ATTRIBUTE[] CK_A0 = new CK_ATTRIBUTE[0];
+
+    private String parseOperation() throws IOException {
+        String op = parseWord();
+        switch (op) {
+            case "*":
+                return TemplateManager.O_ANY;
+            case "generate":
+                return TemplateManager.O_GENERATE;
+            case "import":
+                return TemplateManager.O_IMPORT;
+            default:
+                throw excLine("Unknown operation " + op);
+        }
+    }
+
+    private long parseObjectClass() throws IOException {
+        String name = parseWord();
+        try {
+            return Functions.getObjectClassId(name);
+        } catch (IllegalArgumentException e) {
+            throw excLine("Unknown object class " + name);
+        }
+    }
+
+    private long parseKeyAlgorithm() throws IOException {
+        String name = parseWord();
+        if (isNumber(name)) {
+            return decodeNumber(name);
+        } else {
+            try {
+                return Functions.getKeyId(name);
+            } catch (IllegalArgumentException e) {
+                throw excLine("Unknown key algorithm " + name);
+            }
+        }
+    }
+
+    private long decodeAttributeName(String name) throws IOException {
+        if (isNumber(name)) {
+            return decodeNumber(name);
+        } else {
+            try {
+                return Functions.getAttributeId(name);
+            } catch (IllegalArgumentException e) {
+                throw excLine("Unknown attribute name " + name);
+            }
+        }
+    }
+
+    private CK_ATTRIBUTE decodeAttributeValue(long id, String value)
+            throws IOException {
+        if (value.equals("null")) {
+            return new CK_ATTRIBUTE(id);
+        } else if (value.equals("true")) {
+            return new CK_ATTRIBUTE(id, true);
+        } else if (value.equals("false")) {
+            return new CK_ATTRIBUTE(id, false);
+        } else if (isByteArray(value)) {
+            return new CK_ATTRIBUTE(id, decodeByteArray(value));
+        } else if (isNumber(value)) {
+            return new CK_ATTRIBUTE(id, Integer.valueOf(decodeNumber(value)));
+        } else {
+            throw excLine("Unknown attribute value " + value);
+        }
+    }
+
+    private void parseNSSArgs(String keyword) throws IOException {
+        checkDup(keyword);
+        parseEquals();
+        int token = nextToken();
+        if (token != '"') {
+            throw excToken("Expected quoted string");
+        }
+        nssArgs = expand(st.sval);
+        debug("nssArgs: " + nssArgs);
+    }
+
+    private void parseHandleStartupErrors(String keyword) throws IOException {
+        checkDup(keyword);
+        parseEquals();
+        String val = parseWord();
+        if (val.equals("ignoreAll")) {
+            handleStartupErrors = ERR_IGNORE_ALL;
+        } else if (val.equals("ignoreMissingLibrary")) {
+            handleStartupErrors = ERR_IGNORE_LIB;
+        } else if (val.equals("halt")) {
+            handleStartupErrors = ERR_HALT;
+        } else {
+            throw excToken("Invalid value for handleStartupErrors:");
+        }
+        debug("handleStartupErrors: " + handleStartupErrors);
+    }
+
+}
+
+class ConfigurationException extends IOException {
+    private static final long serialVersionUID = 254492758807673194L;
+    ConfigurationException(String msg) {
+        super(msg);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/KeyCache.java	Thu Jan 26 09:19:33 2017 -0800
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2003, 2011, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package sun.security.pkcs11;
+
+import java.util.*;
+import java.lang.ref.*;
+
+import java.security.Key;
+
+import sun.security.util.Cache;
+
+/**
+ * Key to P11Key translation cache. The PKCS#11 token can only perform
+ * operations on keys stored on the token (permanently or temporarily). That
+ * means that in order to allow the PKCS#11 provider to use keys from other
+ * providers, we need to transparently convert them to P11Keys. The engines
+ * do that using (Secret)KeyFactories, which in turn use this class as a
+ * cache.
+ *
+ * There are two KeyCache instances per provider, one for secret keys and
+ * one for public and private keys.
+ *
+ * @author  Andreas Sterbenz
+ * @since   1.5
+ */
+final class KeyCache {
+
+    private final Cache<IdentityWrapper, P11Key> strongCache;
+
+    private WeakReference<Map<Key,P11Key>> cacheReference;
+
+    KeyCache() {
+        strongCache = Cache.newHardMemoryCache(16);
+    }
+
+    private static final class IdentityWrapper {
+        final Object obj;
+        IdentityWrapper(Object obj) {
+            this.obj = obj;
+        }
+        public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (o instanceof IdentityWrapper == false) {
+                return false;
+            }
+            IdentityWrapper other = (IdentityWrapper)o;
+            return this.obj == other.obj;
+        }
+        public int hashCode() {
+            return System.identityHashCode(obj);
+        }
+    }
+
+    synchronized P11Key get(Key key) {
+        P11Key p11Key = strongCache.get(new IdentityWrapper(key));
+        if (p11Key != null) {
+            return p11Key;
+        }
+        Map<Key,P11Key> map =
+                (cacheReference == null) ? null : cacheReference.get();
+        if (map == null) {
+            return null;
+        }
+        return map.get(key);
+    }
+
+    synchronized void put(Key key, P11Key p11Key) {
+        strongCache.put(new IdentityWrapper(key), p11Key);
+        Map<Key,P11Key> map =
+                (cacheReference == null) ? null : cacheReference.get();
+        if (map == null) {
+            map = new IdentityHashMap<>();
+            cacheReference = new WeakReference<>(map);
+        }
+        map.put(key, p11Key);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Cipher.java	Thu Jan 26 09:19:33 2017 -0800
@@ -0,0 +1,929 @@
+/*
+ * Copyright (c) 2003, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package sun.security.pkcs11;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.Locale;
+
+import java.security.*;
+import java.security.spec.*;
+
+import javax.crypto.*;
+import javax.crypto.spec.*;
+
+import sun.nio.ch.DirectBuffer;
+import sun.security.jca.JCAUtil;
+import sun.security.pkcs11.wrapper.*;
+import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
+
+/**
+ * Cipher implementation class. This class currently supports
+ * DES, DESede, AES, ARCFOUR, and Blowfish.
+ *
+ * This class is designed to support ECB, CBC, CTR with NoPadding
+ * and ECB, CBC with PKCS5Padding. It will use its own padding impl
+ * if the native mechanism does not support padding.
+ *
+ * Note that PKCS#11 currently only supports ECB, CBC, and CTR.
+ * There are no provisions for other modes such as CFB, OFB, and PCBC.
+ *
+ * @author  Andreas Sterbenz
+ * @since   1.5
+ */
+final class P11Cipher extends CipherSpi {
+
+    // mode constant for ECB mode
+    private final static int MODE_ECB = 3;
+    // mode constant for CBC mode
+    private final static int MODE_CBC = 4;
+    // mode constant for CTR mode
+    private final static int MODE_CTR = 5;
+
+    // padding constant for NoPadding
+    private final static int PAD_NONE = 5;
+    // padding constant for PKCS5Padding
+    private final static int PAD_PKCS5 = 6;
+
+    private static interface Padding {
+        // ENC: format the specified buffer with padding bytes and return the
+        // actual padding length
+        int setPaddingBytes(byte[] paddingBuffer, int padLen);
+
+        // DEC: return the length of trailing padding bytes given the specified
+        // padded data
+        int unpad(byte[] paddedData, int len)
+                throws BadPaddingException, IllegalBlockSizeException;
+    }
+
+    private static class PKCS5Padding implements Padding {
+
+        private final int blockSize;
+
+        PKCS5Padding(int blockSize)
+                throws NoSuchPaddingException {
+            if (blockSize == 0) {
+                throw new NoSuchPaddingException
+                        ("PKCS#5 padding not supported with stream ciphers");
+            }
+            this.blockSize = blockSize;
+        }
+
+        public int setPaddingBytes(byte[] paddingBuffer, int padLen) {
+            Arrays.fill(paddingBuffer, 0, padLen, (byte) (padLen & 0x007f));
+            return padLen;
+        }
+
+        public int unpad(byte[] paddedData, int len)
+                throws BadPaddingException, IllegalBlockSizeException {
+            if ((len < 1) || (len % blockSize != 0)) {
+                throw new IllegalBlockSizeException
+                    ("Input length must be multiples of " + blockSize);
+            }
+            byte padValue = paddedData[len - 1];
+            if (padValue < 1 || padValue > blockSize) {
+                throw new BadPaddingException("Invalid pad value!");
+            }
+            // sanity check padding bytes
+            int padStartIndex = len - padValue;
+            for (int i = padStartIndex; i < len; i++) {
+                if (paddedData[i] != padValue) {
+                    throw new BadPaddingException("Invalid pad bytes!");
+                }
+            }
+            return padValue;
+        }
+    }
+
+    // token instance
+    private final Token token;
+
+    // algorithm name
+    private final String algorithm;
+
+    // name of the key algorithm, e.g. DES instead of algorithm DES/CBC/...
+    private final String keyAlgorithm;
+
+    // mechanism id
+    private final long mechanism;
+
+    // associated session, if any
+    private Session session;
+
+    // key, if init() was called
+    private P11Key p11Key;
+
+    // flag indicating whether an operation is initialized
+    private boolean initialized;
+
+    // falg indicating encrypt or decrypt mode
+    private boolean encrypt;
+
+    // mode, one of MODE_* above (MODE_ECB for stream ciphers)
+    private int blockMode;
+
+    // block size, 0 for stream ciphers
+    private final int blockSize;
+
+    // padding type, on of PAD_* above (PAD_NONE for stream ciphers)
+    private int paddingType;
+
+    // when the padding is requested but unsupported by the native mechanism,
+    // we use the following to do padding and necessary data buffering.
+    // padding object which generate padding and unpad the decrypted data
+    private Padding paddingObj;
+    // buffer for holding back the block which contains padding bytes
+    private byte[] padBuffer;
+    private int padBufferLen;
+
+    // original IV, if in MODE_CBC or MODE_CTR
+    private byte[] iv;
+
+    // number of bytes buffered internally by the native mechanism and padBuffer
+    // if we do the padding
+    private int bytesBuffered;
+
+    // length of key size in bytes; currently only used by AES given its oid
+    // specification mandates a fixed size of the key
+    private int fixedKeySize = -1;
+
+    P11Cipher(Token token, String algorithm, long mechanism)
+            throws PKCS11Exception, NoSuchAlgorithmException {
+        super();
+        this.token = token;
+        this.algorithm = algorithm;
+        this.mechanism = mechanism;
+
+        String[] algoParts = algorithm.split("/");
+
+        if (algoParts[0].startsWith("AES")) {
+            blockSize = 16;
+            int index = algoParts[0].indexOf('_');
+            if (index != -1) {
+                // should be well-formed since we specify what we support
+                fixedKeySize = Integer.parseInt(algoParts[0].substring(index+1))/8;
+            }
+            keyAlgorithm = "AES";
+        } else {
+            keyAlgorithm = algoParts[0];
+            if (keyAlgorithm.equals("RC4") ||
+                    keyAlgorithm.equals("ARCFOUR")) {
+                blockSize = 0;
+            } else { // DES, DESede, Blowfish
+                blockSize = 8;
+            }
+        }
+        this.blockMode =
+            (algoParts.length > 1 ? parseMode(algoParts[1]) : MODE_ECB);
+        String defPadding = (blockSize == 0 ? "NoPadding" : "PKCS5Padding");
+        String paddingStr =
+                (algoParts.length > 2 ? algoParts[2] : defPadding);
+        try {
+            engineSetPadding(paddingStr);
+        } catch (NoSuchPaddingException nspe) {
+            // should not happen
+            throw new ProviderException(nspe);
+        }
+    }
+
+    protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
+        // Disallow change of mode for now since currently it's explicitly
+        // defined in transformation strings
+        throw new NoSuchAlgorithmException("Unsupported mode " + mode);
+    }
+
+    private int parseMode(String mode) throws NoSuchAlgorithmException {
+        mode = mode.toUpperCase(Locale.ENGLISH);
+        int result;
+        if (mode.equals("ECB")) {
+            result = MODE_ECB;
+        } else if (mode.equals("CBC")) {
+            if (blockSize == 0) {
+                throw new NoSuchAlgorithmException
+                        ("CBC mode not supported with stream ciphers");
+            }
+            result = MODE_CBC;
+        } else if (mode.equals("CTR")) {
+            result = MODE_CTR;
+        } else {
+            throw new NoSuchAlgorithmException("Unsupported mode " + mode);
+        }
+        return result;
+    }
+
+    // see JCE spec
+    protected void engineSetPadding(String padding)
+            throws NoSuchPaddingException {
+        paddingObj = null;
+        padBuffer = null;
+        padding = padding.toUpperCase(Locale.ENGLISH);
+        if (padding.equals("NOPADDING")) {
+            paddingType = PAD_NONE;
+        } else if (padding.equals("PKCS5PADDING")) {
+            if (this.blockMode == MODE_CTR) {
+                throw new NoSuchPaddingException
+                    ("PKCS#5 padding not supported with CTR mode");
+            }
+            paddingType = PAD_PKCS5;
+            if (mechanism != CKM_DES_CBC_PAD && mechanism != CKM_DES3_CBC_PAD &&
+                    mechanism != CKM_AES_CBC_PAD) {
+                // no native padding support; use our own padding impl
+                paddingObj = new PKCS5Padding(blockSize);
+                padBuffer = new byte[blockSize];
+            }
+        } else {
+            throw new NoSuchPaddingException("Unsupported padding " + padding);
+        }
+    }
+
+    // see JCE spec
+    protected int engineGetBlockSize() {
+        return blockSize;
+    }
+
+    // see JCE spec
+    protected int engineGetOutputSize(int inputLen) {
+        return doFinalLength(inputLen);
+    }
+
+    // see JCE spec
+    protected byte[] engineGetIV() {
+        return (iv == null) ? null : iv.clone();
+    }
+
+    // see JCE spec
+    protected AlgorithmParameters engineGetParameters() {
+        if (iv == null) {
+            return null;
+        }
+        IvParameterSpec ivSpec = new IvParameterSpec(iv);
+        try {
+            AlgorithmParameters params =
+                    AlgorithmParameters.getInstance(keyAlgorithm,
+                    P11Util.getSunJceProvider());
+            params.init(ivSpec);
+            return params;
+        } catch (GeneralSecurityException e) {
+            // NoSuchAlgorithmException, NoSuchProviderException
+            // InvalidParameterSpecException
+            throw new ProviderException("Could not encode parameters", e);
+        }
+    }
+
+    // see JCE spec
+    protected void engineInit(int opmode, Key key, SecureRandom random)
+            throws InvalidKeyException {
+        try {
+            implInit(opmode, key, null, random);
+        } catch (InvalidAlgorithmParameterException e) {
+            throw new InvalidKeyException("init() failed", e);
+        }
+    }
+
+    // see JCE spec
+    protected void engineInit(int opmode, Key key,
+            AlgorithmParameterSpec params, SecureRandom random)
+            throws InvalidKeyException, InvalidAlgorithmParameterException {
+        byte[] ivValue;
+        if (params != null) {
+            if (params instanceof IvParameterSpec == false) {
+                throw new InvalidAlgorithmParameterException
+                        ("Only IvParameterSpec supported");
+            }
+            IvParameterSpec ivSpec = (IvParameterSpec) params;
+            ivValue = ivSpec.getIV();
+        } else {
+            ivValue = null;
+        }
+        implInit(opmode, key, ivValue, random);
+    }
+
+    // see JCE spec
+    protected void engineInit(int opmode, Key key, AlgorithmParameters params,
+            SecureRandom random)
+            throws InvalidKeyException, InvalidAlgorithmParameterException {
+        byte[] ivValue;
+        if (params != null) {
+            try {
+                IvParameterSpec ivSpec =
+                        params.getParameterSpec(IvParameterSpec.class);
+                ivValue = ivSpec.getIV();
+            } catch (InvalidParameterSpecException e) {
+                throw new InvalidAlgorithmParameterException
+                        ("Could not decode IV", e);
+            }
+        } else {
+            ivValue = null;
+        }
+        implInit(opmode, key, ivValue, random);
+    }
+
+    // actual init() implementation
+    private void implInit(int opmode, Key key, byte[] iv,
+            SecureRandom random)
+            throws InvalidKeyException, InvalidAlgorithmParameterException {
+        reset(true);
+        if (fixedKeySize != -1 && key.getEncoded().length != fixedKeySize) {
+            throw new InvalidKeyException("Key size is invalid");
+        }
+        switch (opmode) {
+            case Cipher.ENCRYPT_MODE:
+                encrypt = true;
+                break;
+            case Cipher.DECRYPT_MODE:
+                encrypt = false;
+                break;
+            default:
+                throw new InvalidAlgorithmParameterException
+                        ("Unsupported mode: " + opmode);
+        }
+        if (blockMode == MODE_ECB) { // ECB or stream cipher
+            if (iv != null) {
+                if (blockSize == 0) {
+                    throw new InvalidAlgorithmParameterException
+                            ("IV not used with stream ciphers");
+                } else {
+                    throw new InvalidAlgorithmParameterException
+                            ("IV not used in ECB mode");
+                }
+            }
+        } else { // MODE_CBC or MODE_CTR
+            if (iv == null) {
+                if (encrypt == false) {
+                    String exMsg =
+                        (blockMode == MODE_CBC ?
+                         "IV must be specified for decryption in CBC mode" :
+                         "IV must be specified for decryption in CTR mode");
+                    throw new InvalidAlgorithmParameterException(exMsg);
+                }
+                // generate random IV
+                if (random == null) {
+                    random = JCAUtil.getSecureRandom();
+                }
+                iv = new byte[blockSize];
+                random.nextBytes(iv);
+            } else {
+                if (iv.length != blockSize) {
+                    throw new InvalidAlgorithmParameterException
+                            ("IV length must match block size");
+                }
+            }
+        }
+        this.iv = iv;
+        p11Key = P11SecretKeyFactory.convertKey(token, key, keyAlgorithm);
+        try {
+            initialize();
+        } catch (PKCS11Exception e) {
+            throw new InvalidKeyException("Could not initialize cipher", e);
+        }
+    }
+
+    private void cancelOperation() {
+        if (initialized == false) {
+            return;
+        }
+
+        if ((session == null) || (token.explicitCancel == false)) {
+            return;
+        }
+        try {
+            if (session.hasObjects() == false) {
+                session = token.killSession(session);
+                return;
+            } else {
+                // cancel operation by finishing it
+                int bufLen = doFinalLength(0);
+                byte[] buffer = new byte[bufLen];
+                if (encrypt) {
+                    token.p11.C_EncryptFinal(session.id(), 0, buffer, 0, bufLen);
+                } else {
+                    token.p11.C_DecryptFinal(session.id(), 0, buffer, 0, bufLen);
+                }
+            }
+        } catch (PKCS11Exception e) {
+            throw new ProviderException("Cancel failed", e);
+        }
+    }
+
+    private void ensureInitialized() throws PKCS11Exception {
+        if (initialized == false) {
+            initialize();
+        }
+    }
+
+    private void initialize() throws PKCS11Exception {
+        if (session == null) {
+            session = token.getOpSession();
+        }
+        CK_MECHANISM mechParams = (blockMode == MODE_CTR?
+            new CK_MECHANISM(mechanism, new CK_AES_CTR_PARAMS(iv)) :
+            new CK_MECHANISM(mechanism, iv));
+
+        try {
+            if (encrypt) {
+                token.p11.C_EncryptInit(session.id(), mechParams, p11Key.keyID);
+            } else {
+                token.p11.C_DecryptInit(session.id(), mechParams, p11Key.keyID);
+            }
+        } catch (PKCS11Exception ex) {
+            // release session when initialization failed
+            session = token.releaseSession(session);
+            throw ex;
+        }
+        bytesBuffered = 0;
+        padBufferLen = 0;
+        initialized = true;
+    }
+
+    // if update(inLen) is called, how big does the output buffer have to be?
+    private int updateLength(int inLen) {
+        if (inLen <= 0) {
+            return 0;
+        }
+
+        int result = inLen + bytesBuffered;
+        if (blockSize != 0 && blockMode != MODE_CTR) {
+            // minus the number of bytes in the last incomplete block.
+            result -= (result & (blockSize - 1));
+        }
+        return result;
+    }
+
+    // if doFinal(inLen) is called, how big does the output buffer have to be?
+    private int doFinalLength(int inLen) {
+        if (inLen < 0) {
+            return 0;
+        }
+
+        int result = inLen + bytesBuffered;
+        if (blockSize != 0 && encrypt && paddingType != PAD_NONE) {
+            // add the number of bytes to make the last block complete.
+            result += (blockSize - (result & (blockSize - 1)));
+        }
+        return result;
+    }
+
+    // reset the states to the pre-initialized values
+    private void reset(boolean doCancel) {
+        if (doCancel) cancelOperation();
+
+        initialized = false;
+        bytesBuffered = 0;
+        padBufferLen = 0;
+        if (session != null) {
+            session = token.releaseSession(session);
+        }
+    }
+
+    // see JCE spec
+    protected byte[] engineUpdate(byte[] in, int inOfs, int inLen) {
+        try {
+            byte[] out = new byte[updateLength(inLen)];
+            int n = engineUpdate(in, inOfs, inLen, out, 0);
+            return P11Util.convert(out, 0, n);
+        } catch (ShortBufferException e) {
+            // convert since the output length is calculated by updateLength()
+            throw new ProviderException(e);
+        }
+    }
+
+    // see JCE spec
+    protected int engineUpdate(byte[] in, int inOfs, int inLen, byte[] out,
+            int outOfs) throws ShortBufferException {
+        int outLen = out.length - outOfs;
+        return implUpdate(in, inOfs, inLen, out, outOfs, outLen);
+    }
+
+    // see JCE spec
+    @Override
+    protected int engineUpdate(ByteBuffer inBuffer, ByteBuffer outBuffer)
+            throws ShortBufferException {
+        return implUpdate(inBuffer, outBuffer);
+    }
+
+    // see JCE spec
+    protected byte[] engineDoFinal(byte[] in, int inOfs, int inLen)
+            throws IllegalBlockSizeException, BadPaddingException {
+        try {
+            byte[] out = new byte[doFinalLength(inLen)];
+            int n = engineDoFinal(in, inOfs, inLen, out, 0);
+            return P11Util.convert(out, 0, n);
+        } catch (ShortBufferException e) {
+            // convert since the output length is calculated by doFinalLength()
+            throw new ProviderException(e);
+        }
+    }
+
+    // see JCE spec
+    protected int engineDoFinal(byte[] in, int inOfs, int inLen, byte[] out,
+            int outOfs) throws ShortBufferException, IllegalBlockSizeException,
+            BadPaddingException {
+        int n = 0;
+        if ((inLen != 0) && (in != null)) {
+            n = engineUpdate(in, inOfs, inLen, out, outOfs);
+            outOfs += n;
+        }
+        n += implDoFinal(out, outOfs, out.length - outOfs);
+        return n;
+    }
+
+    // see JCE spec
+    @Override
+    protected int engineDoFinal(ByteBuffer inBuffer, ByteBuffer outBuffer)
+            throws ShortBufferException, IllegalBlockSizeException,
+            BadPaddingException {
+        int n = engineUpdate(inBuffer, outBuffer);
+        n += implDoFinal(outBuffer);
+        return n;
+    }
+
+    private int implUpdate(byte[] in, int inOfs, int inLen,
+            byte[] out, int outOfs, int outLen) throws ShortBufferException {
+        if (outLen < updateLength(inLen)) {
+            throw new ShortBufferException();
+        }
+        try {
+            ensureInitialized();
+            int k = 0;
+            if (encrypt) {
+                k = token.p11.C_EncryptUpdate(session.id(), 0, in, inOfs, inLen,
+                        0, out, outOfs, outLen);
+            } else {
+                int newPadBufferLen = 0;
+                if (paddingObj != null) {
+                    if (padBufferLen != 0) {
+                        // NSS throws up when called with data not in multiple
+                        // of blocks. Try to work around this by holding the
+                        // extra data in padBuffer.
+                        if (padBufferLen != padBuffer.length) {
+                            int bufCapacity = padBuffer.length - padBufferLen;
+                            if (inLen > bufCapacity) {
+                                bufferInputBytes(in, inOfs, bufCapacity);
+                                inOfs += bufCapacity;
+                                inLen -= bufCapacity;
+                            } else {
+                                bufferInputBytes(in, inOfs, inLen);
+                                return 0;
+                            }
+                        }
+                        k = token.p11.C_DecryptUpdate(session.id(),
+                                0, padBuffer, 0, padBufferLen,
+                                0, out, outOfs, outLen);
+                        padBufferLen = 0;
+                    }
+                    newPadBufferLen = inLen & (blockSize - 1);
+                    if (newPadBufferLen == 0) {
+                        newPadBufferLen = padBuffer.length;
+                    }
+                    inLen -= newPadBufferLen;
+                }
+                if (inLen > 0) {
+                    k += token.p11.C_DecryptUpdate(session.id(), 0, in, inOfs,
+                            inLen, 0, out, (outOfs + k), (outLen - k));
+                }
+                // update 'padBuffer' if using our own padding impl.
+                if (paddingObj != null) {
+                    bufferInputBytes(in, inOfs + inLen, newPadBufferLen);
+                }
+            }
+            bytesBuffered += (inLen - k);
+            return k;
+        } catch (PKCS11Exception e) {
+            if (e.getErrorCode() == CKR_BUFFER_TOO_SMALL) {
+                throw (ShortBufferException)
+                        (new ShortBufferException().initCause(e));
+            }
+            reset(false);
+            throw new ProviderException("update() failed", e);
+        }
+    }
+
+    private int implUpdate(ByteBuffer inBuffer, ByteBuffer outBuffer)
+            throws ShortBufferException {
+        int inLen = inBuffer.remaining();
+        if (inLen <= 0) {
+            return 0;
+        }
+
+        int outLen = outBuffer.remaining();
+        if (outLen < updateLength(inLen)) {
+            throw new ShortBufferException();
+        }
+        int origPos = inBuffer.position();
+        try {
+            ensureInitialized();
+
+            long inAddr = 0;
+            int inOfs = 0;
+            byte[] inArray = null;
+
+            if (inBuffer instanceof DirectBuffer) {
+                inAddr = ((DirectBuffer) inBuffer).address();
+                inOfs = origPos;
+            } else if (inBuffer.hasArray()) {
+                inArray = inBuffer.array();
+                inOfs = (origPos + inBuffer.arrayOffset());
+            }
+
+            long outAddr = 0;
+            int outOfs = 0;
+            byte[] outArray = null;
+            if (outBuffer instanceof DirectBuffer) {
+                outAddr = ((DirectBuffer) outBuffer).address();
+                outOfs = outBuffer.position();
+            } else {
+                if (outBuffer.hasArray()) {
+                    outArray = outBuffer.array();
+                    outOfs = (outBuffer.position() + outBuffer.arrayOffset());
+                } else {
+                    outArray = new byte[outLen];
+                }
+            }
+
+            int k = 0;
+            if (encrypt) {
+                if (inAddr == 0 && inArray == null) {
+                    inArray = new byte[inLen];
+                    inBuffer.get(inArray);
+                } else {
+                    inBuffer.position(origPos + inLen);
+                }
+                k = token.p11.C_EncryptUpdate(session.id(),
+                        inAddr, inArray, inOfs, inLen,
+                        outAddr, outArray, outOfs, outLen);
+            } else {
+                int newPadBufferLen = 0;
+                if (paddingObj != null) {
+                    if (padBufferLen != 0) {
+                        // NSS throws up when called with data not in multiple
+                        // of blocks. Try to work around this by holding the
+                        // extra data in padBuffer.
+                        if (padBufferLen != padBuffer.length) {
+                            int bufCapacity = padBuffer.length - padBufferLen;
+                            if (inLen > bufCapacity) {
+                                bufferInputBytes(inBuffer, bufCapacity);
+                                inOfs += bufCapacity;
+                                inLen -= bufCapacity;
+                            } else {
+                                bufferInputBytes(inBuffer, inLen);
+                                return 0;
+                            }
+                        }
+                        k = token.p11.C_DecryptUpdate(session.id(), 0,
+                                padBuffer, 0, padBufferLen, outAddr, outArray,
+                                outOfs, outLen);
+                        padBufferLen = 0;
+                    }
+                    newPadBufferLen = inLen & (blockSize - 1);
+                    if (newPadBufferLen == 0) {
+                        newPadBufferLen = padBuffer.length;
+                    }
+                    inLen -= newPadBufferLen;
+                }
+                if (inLen > 0) {
+                    if (inAddr == 0 && inArray == null) {
+                        inArray = new byte[inLen];
+                        inBuffer.get(inArray);
+                    } else {
+                        inBuffer.position(inBuffer.position() + inLen);
+                    }
+                    k += token.p11.C_DecryptUpdate(session.id(), inAddr,
+                            inArray, inOfs, inLen, outAddr, outArray,
+                            (outOfs + k), (outLen - k));
+                }
+                // update 'padBuffer' if using our own padding impl.
+                if (paddingObj != null && newPadBufferLen != 0) {
+                    bufferInputBytes(inBuffer, newPadBufferLen);
+                }
+            }
+            bytesBuffered += (inLen - k);
+            if (!(outBuffer instanceof DirectBuffer) &&
+                    !outBuffer.hasArray()) {
+                outBuffer.put(outArray, outOfs, k);
+            } else {
+                outBuffer.position(outBuffer.position() + k);
+            }
+            return k;
+        } catch (PKCS11Exception e) {
+            // Reset input buffer to its original position for
+            inBuffer.position(origPos);
+            if (e.getErrorCode() == CKR_BUFFER_TOO_SMALL) {
+                throw (ShortBufferException)
+                        (new ShortBufferException().initCause(e));
+            }
+            reset(false);
+            throw new ProviderException("update() failed", e);
+        }
+    }
+
+    private int implDoFinal(byte[] out, int outOfs, int outLen)
+            throws ShortBufferException, IllegalBlockSizeException,
+            BadPaddingException {
+        int requiredOutLen = doFinalLength(0);
+        if (outLen < requiredOutLen) {
+            throw new ShortBufferException();
+        }
+        boolean doCancel = true;
+        try {
+            ensureInitialized();
+            int k = 0;
+            if (encrypt) {
+                if (paddingObj != null) {
+                    int actualPadLen = paddingObj.setPaddingBytes(padBuffer,
+                            requiredOutLen - bytesBuffered);
+                    k = token.p11.C_EncryptUpdate(session.id(),
+                            0, padBuffer, 0, actualPadLen,
+                            0, out, outOfs, outLen);
+                }
+                k += token.p11.C_EncryptFinal(session.id(),
+                        0, out, (outOfs + k), (outLen - k));
+                doCancel = false;
+            } else {
+                // Special handling to match SunJCE provider behavior
+                if (bytesBuffered == 0 && padBufferLen == 0) {
+                    return 0;
+                }
+                if (paddingObj != null) {
+                    if (padBufferLen != 0) {
+                        k = token.p11.C_DecryptUpdate(session.id(), 0,
+                                padBuffer, 0, padBufferLen, 0, padBuffer, 0,
+                                padBuffer.length);
+                    }
+                    k += token.p11.C_DecryptFinal(session.id(), 0, padBuffer, k,
+                            padBuffer.length - k);
+                    doCancel = false;
+
+                    int actualPadLen = paddingObj.unpad(padBuffer, k);
+                    k -= actualPadLen;
+                    System.arraycopy(padBuffer, 0, out, outOfs, k);
+                } else {
+                    k = token.p11.C_DecryptFinal(session.id(), 0, out, outOfs,
+                            outLen);
+                    doCancel = false;
+                }
+            }
+            return k;
+        } catch (PKCS11Exception e) {
+            doCancel = false;
+            handleException(e);
+            throw new ProviderException("doFinal() failed", e);
+        } finally {
+            reset(doCancel);
+        }
+    }
+
+    private int implDoFinal(ByteBuffer outBuffer)
+            throws ShortBufferException, IllegalBlockSizeException,
+            BadPaddingException {
+        int outLen = outBuffer.remaining();
+        int requiredOutLen = doFinalLength(0);
+        if (outLen < requiredOutLen) {
+            throw new ShortBufferException();
+        }
+
+        boolean doCancel = true;
+        try {
+            ensureInitialized();
+
+            long outAddr = 0;
+            byte[] outArray = null;
+            int outOfs = 0;
+            if (outBuffer instanceof DirectBuffer) {
+                outAddr = ((DirectBuffer) outBuffer).address();
+                outOfs = outBuffer.position();
+            } else {
+                if (outBuffer.hasArray()) {
+                    outArray = outBuffer.array();
+                    outOfs = outBuffer.position() + outBuffer.arrayOffset();
+                } else {
+                    outArray = new byte[outLen];
+                }
+            }
+
+            int k = 0;
+
+            if (encrypt) {
+                if (paddingObj != null) {
+                    int actualPadLen = paddingObj.setPaddingBytes(padBuffer,
+                            requiredOutLen - bytesBuffered);
+                    k = token.p11.C_EncryptUpdate(session.id(),
+                            0, padBuffer, 0, actualPadLen,
+                            outAddr, outArray, outOfs, outLen);
+                }
+                k += token.p11.C_EncryptFinal(session.id(),
+                        outAddr, outArray, (outOfs + k), (outLen - k));
+                doCancel = false;
+            } else {
+                // Special handling to match SunJCE provider behavior
+                if (bytesBuffered == 0 && padBufferLen == 0) {
+                    return 0;
+                }
+
+                if (paddingObj != null) {
+                    if (padBufferLen != 0) {
+                        k = token.p11.C_DecryptUpdate(session.id(),
+                                0, padBuffer, 0, padBufferLen,
+                                0, padBuffer, 0, padBuffer.length);
+                        padBufferLen = 0;
+                    }
+                    k += token.p11.C_DecryptFinal(session.id(),
+                            0, padBuffer, k, padBuffer.length - k);
+                    doCancel = false;
+
+                    int actualPadLen = paddingObj.unpad(padBuffer, k);
+                    k -= actualPadLen;
+                    outArray = padBuffer;
+                    outOfs = 0;
+                } else {
+                    k = token.p11.C_DecryptFinal(session.id(),
+                            outAddr, outArray, outOfs, outLen);
+                    doCancel = false;
+                }
+            }
+            if ((!encrypt && paddingObj != null) ||
+                    (!(outBuffer instanceof DirectBuffer) &&
+                    !outBuffer.hasArray())) {
+                outBuffer.put(outArray, outOfs, k);
+            } else {
+                outBuffer.position(outBuffer.position() + k);
+            }
+            return k;
+        } catch (PKCS11Exception e) {
+            doCancel = false;
+            handleException(e);
+            throw new ProviderException("doFinal() failed", e);
+        } finally {
+            reset(doCancel);
+        }
+    }
+
+    private void handleException(PKCS11Exception e)
+            throws ShortBufferException, IllegalBlockSizeException {
+        long errorCode = e.getErrorCode();
+        if (errorCode == CKR_BUFFER_TOO_SMALL) {
+            throw (ShortBufferException)
+                    (new ShortBufferException().initCause(e));
+        } else if (errorCode == CKR_DATA_LEN_RANGE ||
+                   errorCode == CKR_ENCRYPTED_DATA_LEN_RANGE) {
+            throw (IllegalBlockSizeException)
+                    (new IllegalBlockSizeException(e.toString()).initCause(e));
+        }
+    }
+
+    // see JCE spec
+    protected byte[] engineWrap(Key key) throws IllegalBlockSizeException,
+            InvalidKeyException {
+        // XXX key wrapping
+        throw new UnsupportedOperationException("engineWrap()");
+    }
+
+    // see JCE spec
+    protected Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm,
+            int wrappedKeyType)
+            throws InvalidKeyException, NoSuchAlgorithmException {
+        // XXX key unwrapping
+        throw new UnsupportedOperationException("engineUnwrap()");
+    }
+
+    // see JCE spec
+    @Override
+    protected int engineGetKeySize(Key key) throws InvalidKeyException {
+        int n = P11SecretKeyFactory.convertKey
+                (token, key, keyAlgorithm).length();
+        return n;
+    }
+
+    private final void bufferInputBytes(byte[] in, int inOfs, int len) {
+        System.arraycopy(in, inOfs, padBuffer, padBufferLen, len);
+        padBufferLen += len;
+        bytesBuffered += len;
+    }
+
+    private final void bufferInputBytes(ByteBuffer inBuffer, int len) {
+        inBuffer.get(padBuffer, padBufferLen, len);
+        padBufferLen += len;
+        bytesBuffered += len;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11DHKeyFactory.java	Thu Jan 26 09:19:33 2017 -0800
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2003, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package sun.security.pkcs11;
+
+import java.math.BigInteger;
+
+import java.security.*;
+import java.security.spec.*;
+
+import javax.crypto.interfaces.*;
+import javax.crypto.spec.*;
+
+import static sun.security.pkcs11.TemplateManager.*;
+import sun.security.pkcs11.wrapper.*;
+import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
+
+/**
+ * DH KeyFactory implementation.
+ *
+ * @author  Andreas Sterbenz
+ * @since   1.5
+ */
+final class P11DHKeyFactory extends P11KeyFactory {
+
+    P11DHKeyFactory(Token token, String algorithm) {
+        super(token, algorithm);
+    }
+
+    PublicKey implTranslatePublicKey(PublicKey key) throws InvalidKeyException {
+        try {
+            if (key instanceof DHPublicKey) {
+                DHPublicKey dhKey = (DHPublicKey)key;
+                DHParameterSpec params = dhKey.getParams();
+                return generatePublic(
+                    dhKey.getY(),
+                    params.getP(),
+                    params.getG()
+                );
+            } else if ("X.509".equals(key.getFormat())) {
+                // let SunJCE provider parse for us, then recurse
+                try {
+                    KeyFactory factory = implGetSoftwareFactory();
+                    key = (PublicKey)factory.translateKey(key);
+                    return implTranslatePublicKey(key);
+                } catch (GeneralSecurityException e) {
+                    throw new InvalidKeyException("Could not translate key", e);
+                }
+            } else {
+                throw new InvalidKeyException("PublicKey must be instance "
+                        + "of DHPublicKey or have X.509 encoding");
+            }
+        } catch (PKCS11Exception e) {
+            throw new InvalidKeyException("Could not create DH public key", e);
+        }
+    }
+
+    PrivateKey implTranslatePrivateKey(PrivateKey key)
+            throws InvalidKeyException {
+        try {
+            if (key instanceof DHPrivateKey) {
+                DHPrivateKey dhKey = (DHPrivateKey)key;
+                DHParameterSpec params = dhKey.getParams();
+                return generatePrivate(
+                    dhKey.getX(),
+                    params.getP(),
+                    params.getG()
+                );
+            } else if ("PKCS#8".equals(key.getFormat())) {
+                // let SunJCE provider parse for us, then recurse
+                try {
+                    KeyFactory factory = implGetSoftwareFactory();
+                    key = (PrivateKey)factory.translateKey(key);
+                    return implTranslatePrivateKey(key);
+                } catch (GeneralSecurityException e) {
+                    throw new InvalidKeyException("Could not translate key", e);
+                }
+            } else {
+                throw new InvalidKeyException("PrivateKey must be instance "
+                        + "of DHPrivateKey or have PKCS#8 encoding");
+            }
+        } catch (PKCS11Exception e) {
+            throw new InvalidKeyException("Could not create DH private key", e);
+        }
+    }
+
+    // see JCA spec
+    protected PublicKey engineGeneratePublic(KeySpec keySpec)
+            throws InvalidKeySpecException {
+        token.ensureValid();
+        if (keySpec instanceof X509EncodedKeySpec) {
+            try {
+                KeyFactory factory = implGetSoftwareFactory();
+                PublicKey key = factory.generatePublic(keySpec);
+                return implTranslatePublicKey(key);
+            } catch (GeneralSecurityException e) {
+                throw new InvalidKeySpecException
+                        ("Could not create DH public key", e);
+            }
+        }
+        if (keySpec instanceof DHPublicKeySpec == false) {
+            throw new InvalidKeySpecException("Only DHPublicKeySpec and "
+                + "X509EncodedKeySpec supported for DH public keys");
+        }
+        try {
+            DHPublicKeySpec ds = (DHPublicKeySpec)keySpec;
+            return generatePublic(
+                ds.getY(),
+                ds.getP(),
+                ds.getG()
+            );
+        } catch (PKCS11Exception e) {
+            throw new InvalidKeySpecException
+                ("Could not create DH public key", e);
+        }
+    }
+
+    // see JCA spec
+    protected PrivateKey engineGeneratePrivate(KeySpec keySpec)
+            throws InvalidKeySpecException {
+        token.ensureValid();
+        if (keySpec instanceof PKCS8EncodedKeySpec) {
+            try {
+                KeyFactory factory = implGetSoftwareFactory();
+                PrivateKey key = factory.generatePrivate(keySpec);
+                return implTranslatePrivateKey(key);
+            } catch (GeneralSecurityException e) {
+                throw new InvalidKeySpecException
+                        ("Could not create DH private key", e);
+            }
+        }
+        if (keySpec instanceof DHPrivateKeySpec == false) {
+            throw new InvalidKeySpecException("Only DHPrivateKeySpec and "
+                + "PKCS8EncodedKeySpec supported for DH private keys");
+        }
+        try {
+            DHPrivateKeySpec ds = (DHPrivateKeySpec)keySpec;
+            return generatePrivate(
+                ds.getX(),
+                ds.getP(),
+                ds.getG()
+            );
+        } catch (PKCS11Exception e) {
+            throw new InvalidKeySpecException
+                ("Could not create DH private key", e);
+        }
+    }
+
+    private PublicKey generatePublic(BigInteger y, BigInteger p, BigInteger g)
+            throws PKCS11Exception {
+        CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
+            new CK_ATTRIBUTE(CKA_CLASS, CKO_PUBLIC_KEY),
+            new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_DH),
+            new CK_ATTRIBUTE(CKA_VALUE, y),
+            new CK_ATTRIBUTE(CKA_PRIME, p),
+            new CK_ATTRIBUTE(CKA_BASE, g),
+        };
+        attributes = token.getAttributes
+                (O_IMPORT, CKO_PUBLIC_KEY, CKK_DH, attributes);
+        Session session = null;
+        try {
+            session = token.getObjSession();
+            long keyID = token.p11.C_CreateObject(session.id(), attributes);
+            return P11Key.publicKey
+                (session, keyID, "DH", p.bitLength(), attributes);
+        } finally {
+            token.releaseSession(session);
+        }
+    }
+
+    private PrivateKey generatePrivate(BigInteger x, BigInteger p,
+            BigInteger g) throws PKCS11Exception {
+        CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
+            new CK_ATTRIBUTE(CKA_CLASS, CKO_PRIVATE_KEY),
+            new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_DH),
+            new CK_ATTRIBUTE(CKA_VALUE, x),
+            new CK_ATTRIBUTE(CKA_PRIME, p),
+            new CK_ATTRIBUTE(CKA_BASE, g),
+        };
+        attributes = token.getAttributes
+                (O_IMPORT, CKO_PRIVATE_KEY, CKK_DH, attributes);
+        Session session = null;
+        try {
+            session = token.getObjSession();
+            long keyID = token.p11.C_CreateObject(session.id(), attributes);
+            return P11Key.privateKey
+                (session, keyID, "DH", p.bitLength(), attributes);
+        } finally {
+            token.releaseSession(session);
+        }
+    }
+
+    <T extends KeySpec> T implGetPublicKeySpec(P11Key key, Class<T> keySpec,
+            Session[] session) throws PKCS11Exception, InvalidKeySpecException {
+        if (DHPublicKeySpec.class.isAssignableFrom(keySpec)) {
+            session[0] = token.getObjSession();
+            CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
+                new CK_ATTRIBUTE(CKA_VALUE),
+                new CK_ATTRIBUTE(CKA_PRIME),
+                new CK_ATTRIBUTE(CKA_BASE),
+            };
+            token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
+            KeySpec spec = new DHPublicKeySpec(
+                attributes[0].getBigInteger(),
+                attributes[1].getBigInteger(),
+                attributes[2].getBigInteger()
+            );
+            return keySpec.cast(spec);
+        } else { // X.509 handled in superclass
+            throw new InvalidKeySpecException("Only DHPublicKeySpec and "
+                + "X509EncodedKeySpec supported for DH public keys");
+        }
+    }
+
+    <T extends KeySpec> T implGetPrivateKeySpec(P11Key key, Class<T> keySpec,
+            Session[] session) throws PKCS11Exception, InvalidKeySpecException {
+        if (DHPrivateKeySpec.class.isAssignableFrom(keySpec)) {
+            session[0] = token.getObjSession();
+            CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
+                new CK_ATTRIBUTE(CKA_VALUE),
+                new CK_ATTRIBUTE(CKA_PRIME),
+                new CK_ATTRIBUTE(CKA_BASE),
+            };
+            token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
+            KeySpec spec = new DHPrivateKeySpec(
+                attributes[0].getBigInteger(),
+                attributes[1].getBigInteger(),
+                attributes[2].getBigInteger()
+            );
+            return keySpec.cast(spec);
+        } else { // PKCS#8 handled in superclass
+            throw new InvalidKeySpecException("Only DHPrivateKeySpec "
+                + "and PKCS8EncodedKeySpec supported for DH private keys");
+        }
+    }
+
+    KeyFactory implGetSoftwareFactory() throws GeneralSecurityException {
+        return KeyFactory.getInstance("DH", P11Util.getSunJceProvider());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11DSAKeyFactory.java	Thu Jan 26 09:19:33 2017 -0800
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2003, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package sun.security.pkcs11;
+
+import java.math.BigInteger;
+
+import java.security.*;
+import java.security.interfaces.*;
+import java.security.spec.*;
+
+import static sun.security.pkcs11.TemplateManager.*;
+import sun.security.pkcs11.wrapper.*;
+import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
+
+/**
+ * DSA KeyFactory implementation.
+ *
+ * @author  Andreas Sterbenz
+ * @since   1.5
+ */
+final class P11DSAKeyFactory extends P11KeyFactory {
+
+    P11DSAKeyFactory(Token token, String algorithm) {
+        super(token, algorithm);
+    }
+
+    PublicKey implTranslatePublicKey(PublicKey key) throws InvalidKeyException {
+        try {
+            if (key instanceof DSAPublicKey) {
+                DSAPublicKey dsaKey = (DSAPublicKey)key;
+                DSAParams params = dsaKey.getParams();
+                return generatePublic(
+                    dsaKey.getY(),
+                    params.getP(),
+                    params.getQ(),
+                    params.getG()
+                );
+            } else if ("X.509".equals(key.getFormat())) {
+                // let Sun provider parse for us, then recurse
+                byte[] encoded = key.getEncoded();
+                key = new sun.security.provider.DSAPublicKey(encoded);
+                return implTranslatePublicKey(key);
+            } else {
+                throw new InvalidKeyException("PublicKey must be instance "
+                        + "of DSAPublicKey or have X.509 encoding");
+            }
+        } catch (PKCS11Exception e) {
+            throw new InvalidKeyException("Could not create DSA public key", e);
+        }
+    }
+
+    PrivateKey implTranslatePrivateKey(PrivateKey key)
+            throws InvalidKeyException {
+        try {
+            if (key instanceof DSAPrivateKey) {
+                DSAPrivateKey dsaKey = (DSAPrivateKey)key;
+                DSAParams params = dsaKey.getParams();
+                return generatePrivate(
+                    dsaKey.getX(),
+                    params.getP(),
+                    params.getQ(),
+                    params.getG()
+                );
+            } else if ("PKCS#8".equals(key.getFormat())) {
+                // let Sun provider parse for us, then recurse
+                byte[] encoded = key.getEncoded();
+                key = new sun.security.provider.DSAPrivateKey(encoded);
+                return implTranslatePrivateKey(key);
+            } else {
+                throw new InvalidKeyException("PrivateKey must be instance "
+                        + "of DSAPrivateKey or have PKCS#8 encoding");
+            }
+        } catch (PKCS11Exception e) {
+            throw new InvalidKeyException("Could not create DSA private key", e);
+        }
+    }
+
+    // see JCA spec
+    protected PublicKey engineGeneratePublic(KeySpec keySpec)
+            throws InvalidKeySpecException {
+        token.ensureValid();
+        if (keySpec instanceof X509EncodedKeySpec) {
+            try {
+                byte[] encoded = ((X509EncodedKeySpec)keySpec).getEncoded();
+                PublicKey key = new sun.security.provider.DSAPublicKey(encoded);
+                return implTranslatePublicKey(key);
+            } catch (InvalidKeyException e) {
+                throw new InvalidKeySpecException
+                        ("Could not create DSA public key", e);
+            }
+        }
+        if (keySpec instanceof DSAPublicKeySpec == false) {
+            throw new InvalidKeySpecException("Only DSAPublicKeySpec and "
+                + "X509EncodedKeySpec supported for DSA public keys");
+        }
+        try {
+            DSAPublicKeySpec ds = (DSAPublicKeySpec)keySpec;
+            return generatePublic(
+                ds.getY(),
+                ds.getP(),
+                ds.getQ(),
+                ds.getG()
+            );
+        } catch (PKCS11Exception e) {
+            throw new InvalidKeySpecException
+                ("Could not create DSA public key", e);
+        }
+    }
+
+    // see JCA spec
+    protected PrivateKey engineGeneratePrivate(KeySpec keySpec)
+            throws InvalidKeySpecException {
+        token.ensureValid();
+        if (keySpec instanceof PKCS8EncodedKeySpec) {
+            try {
+                byte[] encoded = ((PKCS8EncodedKeySpec)keySpec).getEncoded();
+                PrivateKey key = new sun.security.provider.DSAPrivateKey(encoded);
+                return implTranslatePrivateKey(key);
+            } catch (GeneralSecurityException e) {
+                throw new InvalidKeySpecException
+                        ("Could not create DSA private key", e);
+            }
+        }
+        if (keySpec instanceof DSAPrivateKeySpec == false) {
+            throw new InvalidKeySpecException("Only DSAPrivateKeySpec and "
+                + "PKCS8EncodedKeySpec supported for DSA private keys");
+        }
+        try {
+            DSAPrivateKeySpec ds = (DSAPrivateKeySpec)keySpec;
+            return generatePrivate(
+                ds.getX(),
+                ds.getP(),
+                ds.getQ(),
+                ds.getG()
+            );
+        } catch (PKCS11Exception e) {
+            throw new InvalidKeySpecException
+                ("Could not create DSA private key", e);
+        }
+    }
+
+    private PublicKey generatePublic(BigInteger y, BigInteger p, BigInteger q,
+            BigInteger g) throws PKCS11Exception {
+        CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
+            new CK_ATTRIBUTE(CKA_CLASS, CKO_PUBLIC_KEY),
+            new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_DSA),
+            new CK_ATTRIBUTE(CKA_VALUE, y),
+            new CK_ATTRIBUTE(CKA_PRIME, p),
+            new CK_ATTRIBUTE(CKA_SUBPRIME, q),
+            new CK_ATTRIBUTE(CKA_BASE, g),
+        };
+        attributes = token.getAttributes
+                (O_IMPORT, CKO_PUBLIC_KEY, CKK_DSA, attributes);
+        Session session = null;
+        try {
+            session = token.getObjSession();
+            long keyID = token.p11.C_CreateObject(session.id(), attributes);
+            return P11Key.publicKey
+                (session, keyID, "DSA", p.bitLength(), attributes);
+        } finally {
+            token.releaseSession(session);
+        }
+    }
+
+    private PrivateKey generatePrivate(BigInteger x, BigInteger p,
+            BigInteger q, BigInteger g) throws PKCS11Exception {
+        CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
+            new CK_ATTRIBUTE(CKA_CLASS, CKO_PRIVATE_KEY),
+            new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_DSA),
+            new CK_ATTRIBUTE(CKA_VALUE, x),
+            new CK_ATTRIBUTE(CKA_PRIME, p),
+            new CK_ATTRIBUTE(CKA_SUBPRIME, q),
+            new CK_ATTRIBUTE(CKA_BASE, g),
+        };
+        attributes = token.getAttributes
+                (O_IMPORT, CKO_PRIVATE_KEY, CKK_DSA, attributes);
+        Session session = null;
+        try {
+            session = token.getObjSession();
+            long keyID = token.p11.C_CreateObject(session.id(), attributes);
+            return P11Key.privateKey
+                (session, keyID, "DSA", p.bitLength(), attributes);
+        } finally {
+            token.releaseSession(session);
+        }
+    }
+
+    <T extends KeySpec> T implGetPublicKeySpec(P11Key key, Class<T> keySpec,
+            Session[] session) throws PKCS11Exception, InvalidKeySpecException {
+        if (DSAPublicKeySpec.class.isAssignableFrom(keySpec)) {
+            session[0] = token.getObjSession();
+            CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
+                new CK_ATTRIBUTE(CKA_VALUE),
+                new CK_ATTRIBUTE(CKA_PRIME),
+                new CK_ATTRIBUTE(CKA_SUBPRIME),
+                new CK_ATTRIBUTE(CKA_BASE),
+            };
+            token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
+            KeySpec spec = new DSAPublicKeySpec(
+                attributes[0].getBigInteger(),
+                attributes[1].getBigInteger(),
+                attributes[2].getBigInteger(),
+                attributes[3].getBigInteger()
+            );
+            return keySpec.cast(spec);
+        } else { // X.509 handled in superclass
+            throw new InvalidKeySpecException("Only DSAPublicKeySpec and "
+                + "X509EncodedKeySpec supported for DSA public keys");
+        }
+    }
+
+    <T extends KeySpec> T implGetPrivateKeySpec(P11Key key, Class<T> keySpec,
+            Session[] session) throws PKCS11Exception, InvalidKeySpecException {
+        if (DSAPrivateKeySpec.class.isAssignableFrom(keySpec)) {
+            session[0] = token.getObjSession();
+            CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
+                new CK_ATTRIBUTE(CKA_VALUE),
+                new CK_ATTRIBUTE(CKA_PRIME),
+                new CK_ATTRIBUTE(CKA_SUBPRIME),
+                new CK_ATTRIBUTE(CKA_BASE),
+            };
+            token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
+            KeySpec spec = new DSAPrivateKeySpec(
+                attributes[0].getBigInteger(),
+                attributes[1].getBigInteger(),
+                attributes[2].getBigInteger(),
+                attributes[3].getBigInteger()
+            );
+            return keySpec.cast(spec);
+        } else { // PKCS#8 handled in superclass
+            throw new InvalidKeySpecException("Only DSAPrivateKeySpec "
+                + "and PKCS8EncodedKeySpec supported for DSA private keys");
+        }
+    }
+
+    KeyFactory implGetSoftwareFactory() throws GeneralSecurityException {
+        return KeyFactory.getInstance("DSA", P11Util.getSunProvider());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Digest.java	Thu Jan 26 09:19:33 2017 -0800
@@ -0,0 +1,325 @@
+/*
+ * Copyright (c) 2003, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package sun.security.pkcs11;
+
+import java.util.*;
+import java.nio.ByteBuffer;
+
+import java.security.*;
+
+import javax.crypto.SecretKey;
+
+import sun.nio.ch.DirectBuffer;
+
+import sun.security.util.MessageDigestSpi2;
+
+import sun.security.pkcs11.wrapper.*;
+import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
+
+/**
+ * MessageDigest implementation class. This class currently supports
+ * MD2, MD5, SHA-1, SHA-224, SHA-256, SHA-384, and SHA-512.
+ *
+ * Note that many digest operations are on fairly small amounts of data
+ * (less than 100 bytes total). For example, the 2nd hashing in HMAC or
+ * the PRF in TLS. In order to speed those up, we use some buffering to
+ * minimize number of the Java->native transitions.
+ *
+ * @author  Andreas Sterbenz
+ * @since   1.5
+ */
+final class P11Digest extends MessageDigestSpi implements Cloneable,
+    MessageDigestSpi2 {
+
+    /* fields initialized, no session acquired */
+    private final static int S_BLANK    = 1;
+
+    /* data in buffer, session acquired, but digest not initialized */
+    private final static int S_BUFFERED = 2;
+
+    /* session initialized for digesting */
+    private final static int S_INIT     = 3;
+
+    private final static int BUFFER_SIZE = 96;
+
+    // token instance
+    private final Token token;
+
+    // algorithm name
+    private final String algorithm;
+
+    // mechanism id object
+    private final CK_MECHANISM mechanism;
+
+    // length of the digest in bytes
+    private final int digestLength;
+
+    // associated session, if any
+    private Session session;
+
+    // current state, one of S_* above
+    private int state;
+
+    // buffer to reduce number of JNI calls
+    private byte[] buffer;
+
+    // offset into the buffer
+    private int bufOfs;
+
+    P11Digest(Token token, String algorithm, long mechanism) {
+        super();
+        this.token = token;
+        this.algorithm = algorithm;
+        this.mechanism = new CK_MECHANISM(mechanism);
+        switch ((int)mechanism) {
+        case (int)CKM_MD2:
+        case (int)CKM_MD5:
+            digestLength = 16;
+            break;
+        case (int)CKM_SHA_1:
+            digestLength = 20;
+            break;
+        case (int)CKM_SHA224:
+            digestLength = 28;
+            break;
+        case (int)CKM_SHA256:
+            digestLength = 32;
+            break;
+        case (int)CKM_SHA384:
+            digestLength = 48;
+            break;
+        case (int)CKM_SHA512:
+            digestLength = 64;
+            break;
+        default:
+            throw new ProviderException("Unknown mechanism: " + mechanism);
+        }
+        buffer = new byte[BUFFER_SIZE];
+        state = S_BLANK;
+    }
+
+    // see JCA spec
+    protected int engineGetDigestLength() {
+        return digestLength;
+    }
+
+    private void fetchSession() {
+        token.ensureValid();
+        if (state == S_BLANK) {
+            try {
+                session = token.getOpSession();
+                state = S_BUFFERED;
+            } catch (PKCS11Exception e) {
+                throw new ProviderException("No more session available", e);
+            }
+        }
+    }
+
+    // see JCA spec
+    protected void engineReset() {
+        token.ensureValid();
+
+        if (session != null) {
+            if (state == S_INIT && token.explicitCancel == true) {
+                session = token.killSession(session);
+            } else {
+                session = token.releaseSession(session);
+            }
+        }
+        state = S_BLANK;
+        bufOfs = 0;
+    }
+
+    // see JCA spec
+    protected byte[] engineDigest() {
+        try {
+            byte[] digest = new byte[digestLength];
+            int n = engineDigest(digest, 0, digestLength);
+            return digest;
+        } catch (DigestException e) {
+            throw new ProviderException("internal error", e);
+        }
+    }
+
+    // see JCA spec
+    protected int engineDigest(byte[] digest, int ofs, int len)
+            throws DigestException {
+        if (len < digestLength) {
+            throw new DigestException("Length must be at least " +
+                    digestLength);
+        }
+
+        fetchSession();
+        try {
+            int n;
+            if (state == S_BUFFERED) {
+                n = token.p11.C_DigestSingle(session.id(), mechanism, buffer, 0,
+                        bufOfs, digest, ofs, len);
+                bufOfs = 0;
+            } else {
+                if (bufOfs != 0) {
+                    token.p11.C_DigestUpdate(session.id(), 0, buffer, 0,
+                            bufOfs);
+                    bufOfs = 0;
+                }
+                n = token.p11.C_DigestFinal(session.id(), digest, ofs, len);
+            }
+            if (n != digestLength) {
+                throw new ProviderException("internal digest length error");
+            }
+            return n;
+        } catch (PKCS11Exception e) {
+            throw new ProviderException("digest() failed", e);
+        } finally {
+            engineReset();
+        }
+    }
+
+    // see JCA spec
+    protected void engineUpdate(byte in) {
+        byte[] temp = { in };
+        engineUpdate(temp, 0, 1);
+    }
+
+    // see JCA spec
+    protected void engineUpdate(byte[] in, int ofs, int len) {
+        if (len <= 0) {
+            return;
+        }
+
+        fetchSession();
+        try {
+            if (state == S_BUFFERED) {
+                token.p11.C_DigestInit(session.id(), mechanism);
+                state = S_INIT;
+            }
+            if ((bufOfs != 0) && (bufOfs + len > buffer.length)) {
+                // process the buffered data
+                token.p11.C_DigestUpdate(session.id(), 0, buffer, 0, bufOfs);
+                bufOfs = 0;
+            }
+            if (bufOfs + len > buffer.length) {
+                // process the new data
+                token.p11.C_DigestUpdate(session.id(), 0, in, ofs, len);
+             } else {
+                // buffer the new data
+                System.arraycopy(in, ofs, buffer, bufOfs, len);
+                bufOfs += len;
+            }
+        } catch (PKCS11Exception e) {
+            engineReset();
+            throw new ProviderException("update() failed", e);
+        }
+    }
+
+    // Called by SunJSSE via reflection during the SSL 3.0 handshake if
+    // the master secret is sensitive.
+    // Note: Change to protected after this method is moved from
+    // sun.security.util.MessageSpi2 interface to
+    // java.security.MessageDigestSpi class
+    public void engineUpdate(SecretKey key) throws InvalidKeyException {
+        // SunJSSE calls this method only if the key does not have a RAW
+        // encoding, i.e. if it is sensitive. Therefore, no point in calling
+        // SecretKeyFactory to try to convert it. Just verify it ourselves.
+        if (key instanceof P11Key == false) {
+            throw new InvalidKeyException("Not a P11Key: " + key);
+        }
+        P11Key p11Key = (P11Key)key;
+        if (p11Key.token != token) {
+            throw new InvalidKeyException("Not a P11Key of this provider: " +
+                    key);
+        }
+
+        fetchSession();
+        try {
+            if (state == S_BUFFERED) {
+                token.p11.C_DigestInit(session.id(), mechanism);
+                state = S_INIT;
+            }
+
+            if (bufOfs != 0) {
+                token.p11.C_DigestUpdate(session.id(), 0, buffer, 0, bufOfs);
+                bufOfs = 0;
+            }
+            token.p11.C_DigestKey(session.id(), p11Key.keyID);
+        } catch (PKCS11Exception e) {
+            engineReset();
+            throw new ProviderException("update(SecretKey) failed", e);
+        }
+    }
+
+    // see JCA spec
+    protected void engineUpdate(ByteBuffer byteBuffer) {
+        int len = byteBuffer.remaining();
+        if (len <= 0) {
+            return;
+        }
+
+        if (byteBuffer instanceof DirectBuffer == false) {
+            super.engineUpdate(byteBuffer);
+            return;
+        }
+
+        fetchSession();
+        long addr = ((DirectBuffer)byteBuffer).address();
+        int ofs = byteBuffer.position();
+        try {
+            if (state == S_BUFFERED) {
+                token.p11.C_DigestInit(session.id(), mechanism);
+                state = S_INIT;
+            }
+            if (bufOfs != 0) {
+                token.p11.C_DigestUpdate(session.id(), 0, buffer, 0, bufOfs);
+                bufOfs = 0;
+            }
+            token.p11.C_DigestUpdate(session.id(), addr + ofs, null, 0, len);
+            byteBuffer.position(ofs + len);
+        } catch (PKCS11Exception e) {
+            engineReset();
+            throw new ProviderException("update() failed", e);
+        }
+    }
+
+    public Object clone() throws CloneNotSupportedException {
+        P11Digest copy = (P11Digest) super.clone();
+        copy.buffer = buffer.clone();
+        try {
+            if (session != null) {
+                copy.session = copy.token.getOpSession();
+            }
+            if (state == S_INIT) {
+                byte[] stateValues =
+                    token.p11.C_GetOperationState(session.id());
+                token.p11.C_SetOperationState(copy.session.id(),
+                                              stateValues, 0, 0);
+            }
+        } catch (PKCS11Exception e) {
+            throw (CloneNotSupportedException)
+                (new CloneNotSupportedException(algorithm).initCause(e));
+        }
+        return copy;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11ECDHKeyAgreement.java	Thu Jan 26 09:19:33 2017 -0800
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2006, 2007, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package sun.security.pkcs11;
+
+import java.security.*;
+import java.security.interfaces.ECPublicKey;
+import java.security.spec.AlgorithmParameterSpec;
+
+import javax.crypto.*;
+
+import static sun.security.pkcs11.TemplateManager.*;
+import sun.security.pkcs11.wrapper.*;
+import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
+
+/**
+ * KeyAgreement implementation for ECDH.
+ *
+ * @author  Andreas Sterbenz
+ * @since   1.6
+ */
+final class P11ECDHKeyAgreement extends KeyAgreementSpi {
+
+    // token instance
+    private final Token token;
+
+    // algorithm name
+    private final String algorithm;
+
+    // mechanism id
+    private final long mechanism;
+
+    // private key, if initialized
+    private P11Key privateKey;
+
+    // encoded public point, non-null between doPhase() and generateSecret() only
+    private byte[] publicValue;
+
+    // length of the secret to be derived
+    private int secretLen;
+
+    P11ECDHKeyAgreement(Token token, String algorithm, long mechanism) {
+        super();
+        this.token = token;
+        this.algorithm = algorithm;
+        this.mechanism = mechanism;
+    }
+
+    // see JCE spec
+    protected void engineInit(Key key, SecureRandom random)
+            throws InvalidKeyException {
+        if (key instanceof PrivateKey == false) {
+            throw new InvalidKeyException
+                        ("Key must be instance of PrivateKey");
+        }
+        privateKey = P11KeyFactory.convertKey(token, key, "EC");
+        publicValue = null;
+    }
+
+    // see JCE spec
+    protected void engineInit(Key key, AlgorithmParameterSpec params,
+            SecureRandom random) throws InvalidKeyException,
+            InvalidAlgorithmParameterException {
+        if (params != null) {
+            throw new InvalidAlgorithmParameterException
+                        ("Parameters not supported");
+        }
+        engineInit(key, random);
+    }
+
+    // see JCE spec
+    protected Key engineDoPhase(Key key, boolean lastPhase)
+            throws InvalidKeyException, IllegalStateException {
+        if (privateKey == null) {
+            throw new IllegalStateException("Not initialized");
+        }
+        if (publicValue != null) {
+            throw new IllegalStateException("Phase already executed");
+        }
+        if (lastPhase == false) {
+            throw new IllegalStateException
+                ("Only two party agreement supported, lastPhase must be true");
+        }
+        if (key instanceof ECPublicKey == false) {
+            throw new InvalidKeyException
+                ("Key must be a PublicKey with algorithm EC");
+        }
+        ECPublicKey ecKey = (ECPublicKey)key;
+        int keyLenBits = ecKey.getParams().getCurve().getField().getFieldSize();
+        secretLen = (keyLenBits + 7) >> 3;
+        publicValue = P11ECKeyFactory.getEncodedPublicValue(ecKey);
+        return null;
+    }
+
+    // see JCE spec
+    protected byte[] engineGenerateSecret() throws IllegalStateException {
+        if ((privateKey == null) || (publicValue == null)) {
+            throw new IllegalStateException("Not initialized correctly");
+        }
+        Session session = null;
+        try {
+            session = token.getOpSession();
+            CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
+                new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
+                new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_GENERIC_SECRET),
+            };
+            CK_ECDH1_DERIVE_PARAMS ckParams =
+                    new CK_ECDH1_DERIVE_PARAMS(CKD_NULL, null, publicValue);
+            attributes = token.getAttributes
+                (O_GENERATE, CKO_SECRET_KEY, CKK_GENERIC_SECRET, attributes);
+            long keyID = token.p11.C_DeriveKey(session.id(),
+                new CK_MECHANISM(mechanism, ckParams), privateKey.keyID,
+                attributes);
+            attributes = new CK_ATTRIBUTE[] {
+                new CK_ATTRIBUTE(CKA_VALUE)
+            };
+            token.p11.C_GetAttributeValue(session.id(), keyID, attributes);
+            byte[] secret = attributes[0].getByteArray();
+            token.p11.C_DestroyObject(session.id(), keyID);
+            return secret;
+        } catch (PKCS11Exception e) {
+            throw new ProviderException("Could not derive key", e);
+        } finally {
+            publicValue = null;
+            token.releaseSession(session);
+        }
+    }
+
+    // see JCE spec
+    protected int engineGenerateSecret(byte[] sharedSecret, int
+            offset) throws IllegalStateException, ShortBufferException {
+        if (offset + secretLen > sharedSecret.length) {
+            throw new ShortBufferException("Need " + secretLen
+                + " bytes, only " + (sharedSecret.length - offset) + " available");
+        }
+        byte[] secret = engineGenerateSecret();
+        System.arraycopy(secret, 0, sharedSecret, offset, secret.length);
+        return secret.length;
+    }
+
+    // see JCE spec
+    protected SecretKey engineGenerateSecret(String algorithm)
+            throws IllegalStateException, NoSuchAlgorithmException,
+            InvalidKeyException {
+        if (algorithm == null) {
+            throw new NoSuchAlgorithmException("Algorithm must not be null");
+        }
+        if (algorithm.equals("TlsPremasterSecret") == false) {
+            throw new NoSuchAlgorithmException
+                ("Only supported for algorithm TlsPremasterSecret");
+        }
+        return nativeGenerateSecret(algorithm);
+    }
+
+    private SecretKey nativeGenerateSecret(String algorithm)
+            throws IllegalStateException, NoSuchAlgorithmException,
+            InvalidKeyException {
+        if ((privateKey == null) || (publicValue == null)) {
+            throw new IllegalStateException("Not initialized correctly");
+        }
+        long keyType = CKK_GENERIC_SECRET;
+        Session session = null;
+        try {
+            session = token.getObjSession();
+            CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
+                new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
+                new CK_ATTRIBUTE(CKA_KEY_TYPE, keyType),
+            };
+            CK_ECDH1_DERIVE_PARAMS ckParams =
+                    new CK_ECDH1_DERIVE_PARAMS(CKD_NULL, null, publicValue);
+            attributes = token.getAttributes
+                (O_GENERATE, CKO_SECRET_KEY, keyType, attributes);
+            long keyID = token.p11.C_DeriveKey(session.id(),
+                new CK_MECHANISM(mechanism, ckParams), privateKey.keyID,
+                attributes);
+            CK_ATTRIBUTE[] lenAttributes = new CK_ATTRIBUTE[] {
+                new CK_ATTRIBUTE(CKA_VALUE_LEN),
+            };
+            token.p11.C_GetAttributeValue(session.id(), keyID, lenAttributes);
+            int keyLen = (int)lenAttributes[0].getLong();
+            SecretKey key = P11Key.secretKey
+                        (session, keyID, algorithm, keyLen << 3, attributes);
+            return key;
+        } catch (PKCS11Exception e) {
+            throw new InvalidKeyException("Could not derive key", e);
+        } finally {
+            publicValue = null;
+            token.releaseSession(session);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11ECKeyFactory.java	Thu Jan 26 09:19:33 2017 -0800
@@ -0,0 +1,333 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package sun.security.pkcs11;
+
+import java.io.IOException;
+import java.math.BigInteger;
+
+import java.security.*;
+import java.security.interfaces.*;
+import java.security.spec.*;
+
+import static sun.security.pkcs11.TemplateManager.*;
+import sun.security.pkcs11.wrapper.*;
+import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
+
+import sun.security.util.DerValue;
+import sun.security.util.ECUtil;
+
+/**
+ * EC KeyFactory implementation.
+ *
+ * @author  Andreas Sterbenz
+ * @since   1.6
+ */
+final class P11ECKeyFactory extends P11KeyFactory {
+    private static Provider sunECprovider;
+
+    private static Provider getSunECProvider() {
+        if (sunECprovider == null) {
+            sunECprovider = Security.getProvider("SunEC");
+            if (sunECprovider == null) {
+                throw new RuntimeException("Cannot load SunEC provider");
+            }
+        }
+
+        return sunECprovider;
+    }
+
+    P11ECKeyFactory(Token token, String algorithm) {
+        super(token, algorithm);
+    }
+
+    static ECParameterSpec getECParameterSpec(String name) {
+        return ECUtil.getECParameterSpec(getSunECProvider(), name);
+    }
+
+    static ECParameterSpec getECParameterSpec(int keySize) {
+        return ECUtil.getECParameterSpec(getSunECProvider(), keySize);
+    }
+
+    // Check that spec is a known supported curve and convert it to our
+    // ECParameterSpec subclass. If not possible, return null.
+    static ECParameterSpec getECParameterSpec(ECParameterSpec spec) {
+        return ECUtil.getECParameterSpec(getSunECProvider(), spec);
+    }
+
+    static ECParameterSpec decodeParameters(byte[] params) throws IOException {
+        return ECUtil.getECParameterSpec(getSunECProvider(), params);
+    }
+
+    static byte[] encodeParameters(ECParameterSpec params) {
+        return ECUtil.encodeECParameterSpec(getSunECProvider(), params);
+    }
+
+    static ECPoint decodePoint(byte[] encoded, EllipticCurve curve) throws IOException {
+        return ECUtil.decodePoint(encoded, curve);
+    }
+
+    // Used by ECDH KeyAgreement
+    static byte[] getEncodedPublicValue(PublicKey key) throws InvalidKeyException {
+        if (key instanceof ECPublicKey) {
+            ECPublicKey ecKey = (ECPublicKey)key;
+            ECPoint w = ecKey.getW();
+            ECParameterSpec params = ecKey.getParams();
+            return ECUtil.encodePoint(w, params.getCurve());
+        } else {
+            // should never occur
+            throw new InvalidKeyException
+                ("Key class not yet supported: " + key.getClass().getName());
+        }
+    }
+
+    PublicKey implTranslatePublicKey(PublicKey key) throws InvalidKeyException {
+        try {
+            if (key instanceof ECPublicKey) {
+                ECPublicKey ecKey = (ECPublicKey)key;
+                return generatePublic(
+                    ecKey.getW(),
+                    ecKey.getParams()
+                );
+            } else if ("X.509".equals(key.getFormat())) {
+                // let Sun provider parse for us, then recurse
+                byte[] encoded = key.getEncoded();
+
+                try {
+                    key = ECUtil.decodeX509ECPublicKey(encoded);
+                } catch (InvalidKeySpecException ikse) {
+                    throw new InvalidKeyException(ikse);
+                }
+
+                return implTranslatePublicKey(key);
+            } else {
+                throw new InvalidKeyException("PublicKey must be instance "
+                        + "of ECPublicKey or have X.509 encoding");
+            }
+        } catch (PKCS11Exception e) {
+            throw new InvalidKeyException("Could not create EC public key", e);
+        }
+    }
+
+    PrivateKey implTranslatePrivateKey(PrivateKey key)
+            throws InvalidKeyException {
+        try {
+            if (key instanceof ECPrivateKey) {
+                ECPrivateKey ecKey = (ECPrivateKey)key;
+                return generatePrivate(
+                    ecKey.getS(),
+                    ecKey.getParams()
+                );
+            } else if ("PKCS#8".equals(key.getFormat())) {
+                // let Sun provider parse for us, then recurse
+                byte[] encoded = key.getEncoded();
+
+                try {
+                    key = ECUtil.decodePKCS8ECPrivateKey(encoded);
+                } catch (InvalidKeySpecException ikse) {
+                    throw new InvalidKeyException(ikse);
+                }
+
+                return implTranslatePrivateKey(key);
+            } else {
+                throw new InvalidKeyException("PrivateKey must be instance "
+                        + "of ECPrivateKey or have PKCS#8 encoding");
+            }
+        } catch (PKCS11Exception e) {
+            throw new InvalidKeyException("Could not create EC private key", e);
+        }
+    }
+
+    // see JCA spec
+    protected PublicKey engineGeneratePublic(KeySpec keySpec)
+            throws InvalidKeySpecException {
+        token.ensureValid();
+        if (keySpec instanceof X509EncodedKeySpec) {
+            try {
+                byte[] encoded = ((X509EncodedKeySpec)keySpec).getEncoded();
+                PublicKey key = ECUtil.decodeX509ECPublicKey(encoded);
+                return implTranslatePublicKey(key);
+            } catch (InvalidKeyException e) {
+                throw new InvalidKeySpecException
+                        ("Could not create EC public key", e);
+            }
+        }
+        if (keySpec instanceof ECPublicKeySpec == false) {
+            throw new InvalidKeySpecException("Only ECPublicKeySpec and "
+                + "X509EncodedKeySpec supported for EC public keys");
+        }
+        try {
+            ECPublicKeySpec ec = (ECPublicKeySpec)keySpec;
+            return generatePublic(
+                ec.getW(),
+                ec.getParams()
+            );
+        } catch (PKCS11Exception e) {
+            throw new InvalidKeySpecException
+                ("Could not create EC public key", e);
+        }
+    }
+
+    // see JCA spec
+    protected PrivateKey engineGeneratePrivate(KeySpec keySpec)
+            throws InvalidKeySpecException {
+        token.ensureValid();
+        if (keySpec instanceof PKCS8EncodedKeySpec) {
+            try {
+                byte[] encoded = ((PKCS8EncodedKeySpec)keySpec).getEncoded();
+                PrivateKey key = ECUtil.decodePKCS8ECPrivateKey(encoded);
+                return implTranslatePrivateKey(key);
+            } catch (GeneralSecurityException e) {
+                throw new InvalidKeySpecException
+                        ("Could not create EC private key", e);
+            }
+        }
+        if (keySpec instanceof ECPrivateKeySpec == false) {
+            throw new InvalidKeySpecException("Only ECPrivateKeySpec and "
+                + "PKCS8EncodedKeySpec supported for EC private keys");
+        }
+        try {
+            ECPrivateKeySpec ec = (ECPrivateKeySpec)keySpec;
+            return generatePrivate(
+                ec.getS(),
+                ec.getParams()
+            );
+        } catch (PKCS11Exception e) {
+            throw new InvalidKeySpecException
+                ("Could not create EC private key", e);
+        }
+    }
+
+    private PublicKey generatePublic(ECPoint point, ECParameterSpec params)
+            throws PKCS11Exception {
+        byte[] encodedParams =
+            ECUtil.encodeECParameterSpec(getSunECProvider(), params);
+        byte[] encodedPoint =
+            ECUtil.encodePoint(point, params.getCurve());
+
+        // Check whether the X9.63 encoding of an EC point shall be wrapped
+        // in an ASN.1 OCTET STRING
+        if (!token.config.getUseEcX963Encoding()) {
+            try {
+                encodedPoint =
+                    new DerValue(DerValue.tag_OctetString, encodedPoint)
+                        .toByteArray();
+            } catch (IOException e) {
+                throw new
+                    IllegalArgumentException("Could not DER encode point", e);
+            }
+        }
+
+        CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
+            new CK_ATTRIBUTE(CKA_CLASS, CKO_PUBLIC_KEY),
+            new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_EC),
+            new CK_ATTRIBUTE(CKA_EC_POINT, encodedPoint),
+            new CK_ATTRIBUTE(CKA_EC_PARAMS, encodedParams),
+        };
+        attributes = token.getAttributes
+                (O_IMPORT, CKO_PUBLIC_KEY, CKK_EC, attributes);
+        Session session = null;
+        try {
+            session = token.getObjSession();
+            long keyID = token.p11.C_CreateObject(session.id(), attributes);
+            return P11Key.publicKey
+                (session, keyID, "EC", params.getCurve().getField().getFieldSize(), attributes);
+        } finally {
+            token.releaseSession(session);
+        }
+    }
+
+    private PrivateKey generatePrivate(BigInteger s, ECParameterSpec params)
+            throws PKCS11Exception {
+        byte[] encodedParams =
+            ECUtil.encodeECParameterSpec(getSunECProvider(), params);
+        CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
+            new CK_ATTRIBUTE(CKA_CLASS, CKO_PRIVATE_KEY),
+            new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_EC),
+            new CK_ATTRIBUTE(CKA_VALUE, s),
+            new CK_ATTRIBUTE(CKA_EC_PARAMS, encodedParams),
+        };
+        attributes = token.getAttributes
+                (O_IMPORT, CKO_PRIVATE_KEY, CKK_EC, attributes);
+        Session session = null;
+        try {
+            session = token.getObjSession();
+            long keyID = token.p11.C_CreateObject(session.id(), attributes);
+            return P11Key.privateKey
+                (session, keyID, "EC", params.getCurve().getField().getFieldSize(), attributes);
+        } finally {
+            token.releaseSession(session);
+        }
+    }
+
+    <T extends KeySpec> T implGetPublicKeySpec(P11Key key, Class<T> keySpec,
+            Session[] session) throws PKCS11Exception, InvalidKeySpecException {
+        if (ECPublicKeySpec.class.isAssignableFrom(keySpec)) {
+            session[0] = token.getObjSession();
+            CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
+                new CK_ATTRIBUTE(CKA_EC_POINT),
+                new CK_ATTRIBUTE(CKA_EC_PARAMS),
+            };
+            token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
+            try {
+                ECParameterSpec params = decodeParameters(attributes[1].getByteArray());
+                ECPoint point = decodePoint(attributes[0].getByteArray(), params.getCurve());
+                return keySpec.cast(new ECPublicKeySpec(point, params));
+            } catch (IOException e) {
+                throw new InvalidKeySpecException("Could not parse key", e);
+            }
+        } else { // X.509 handled in superclass
+            throw new InvalidKeySpecException("Only ECPublicKeySpec and "
+                + "X509EncodedKeySpec supported for EC public keys");
+        }
+    }
+
+    <T extends KeySpec> T implGetPrivateKeySpec(P11Key key, Class<T> keySpec,
+            Session[] session) throws PKCS11Exception, InvalidKeySpecException {
+        if (ECPrivateKeySpec.class.isAssignableFrom(keySpec)) {
+            session[0] = token.getObjSession();
+            CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
+                new CK_ATTRIBUTE(CKA_VALUE),
+                new CK_ATTRIBUTE(CKA_EC_PARAMS),
+            };
+            token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
+            try {
+                ECParameterSpec params = decodeParameters(attributes[1].getByteArray());
+                return keySpec.cast(
+                    new ECPrivateKeySpec(attributes[0].getBigInteger(), params));
+            } catch (IOException e) {
+                throw new InvalidKeySpecException("Could not parse key", e);
+            }
+        } else { // PKCS#8 handled in superclass
+            throw new InvalidKeySpecException("Only ECPrivateKeySpec "
+                + "and PKCS8EncodedKeySpec supported for EC private keys");
+        }
+    }
+
+    KeyFactory implGetSoftwareFactory() throws GeneralSecurityException {
+        return KeyFactory.getInstance("EC", getSunECProvider());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java	Thu Jan 26 09:19:33 2017 -0800
@@ -0,0 +1,1188 @@
+/*
+ * Copyright (c) 2003, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package sun.security.pkcs11;
+
+import java.io.*;
+import java.lang.ref.*;
+import java.math.BigInteger;
+import java.util.*;
+
+import java.security.*;
+import java.security.interfaces.*;
+import java.security.spec.*;
+
+import javax.crypto.*;
+import javax.crypto.interfaces.*;
+import javax.crypto.spec.*;
+
+import sun.security.rsa.RSAPublicKeyImpl;
+
+import sun.security.internal.interfaces.TlsMasterSecret;
+
+import sun.security.pkcs11.wrapper.*;
+import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
+
+import sun.security.util.Debug;
+import sun.security.util.DerValue;
+import sun.security.util.Length;
+import sun.security.util.ECUtil;
+
+/**
+ * Key implementation classes.
+ *
+ * In PKCS#11, the components of private and secret keys may or may not
+ * be accessible. If they are, we use the algorithm specific key classes
+ * (e.g. DSAPrivateKey) for compatibility with existing applications.
+ * If the components are not accessible, we use a generic class that
+ * only implements PrivateKey (or SecretKey). Whether the components of a
+ * key are extractable is automatically determined when the key object is
+ * created.
+ *
+ * @author  Andreas Sterbenz
+ * @since   1.5
+ */
+abstract class P11Key implements Key, Length {
+
+    private static final long serialVersionUID = -2575874101938349339L;
+
+    private final static String PUBLIC = "public";
+    private final static String PRIVATE = "private";
+    private final static String SECRET = "secret";
+
+    // type of key, one of (PUBLIC, PRIVATE, SECRET)
+    final String type;
+
+    // token instance
+    final Token token;
+
+    // algorithm name, returned by getAlgorithm(), etc.
+    final String algorithm;
+
+    // key id
+    final long keyID;
+
+    // effective key length of the key, e.g. 56 for a DES key
+    final int keyLength;
+
+    // flags indicating whether the key is a token object, sensitive, extractable
+    final boolean tokenObject, sensitive, extractable;
+
+    // phantom reference notification clean up for session keys
+    private final SessionKeyRef sessionKeyRef;
+
+    P11Key(String type, Session session, long keyID, String algorithm,
+            int keyLength, CK_ATTRIBUTE[] attributes) {
+        this.type = type;
+        this.token = session.token;
+        this.keyID = keyID;
+        this.algorithm = algorithm;
+        this.keyLength = keyLength;
+        boolean tokenObject = false;
+        boolean sensitive = false;
+        boolean extractable = true;
+        int n = (attributes == null) ? 0 : attributes.length;
+        for (int i = 0; i < n; i++) {
+            CK_ATTRIBUTE attr = attributes[i];
+            if (attr.type == CKA_TOKEN) {
+                tokenObject = attr.getBoolean();
+            } else if (attr.type == CKA_SENSITIVE) {
+                sensitive = attr.getBoolean();
+            } else if (attr.type == CKA_EXTRACTABLE) {
+                extractable = attr.getBoolean();
+            }
+        }
+        this.tokenObject = tokenObject;
+        this.sensitive = sensitive;
+        this.extractable = extractable;
+        if (tokenObject == false) {
+            sessionKeyRef = new SessionKeyRef(this, keyID, session);
+        } else {
+            sessionKeyRef = null;
+        }
+    }
+
+    // see JCA spec
+    public final String getAlgorithm() {
+        token.ensureValid();
+        return algorithm;
+    }
+
+    // see JCA spec
+    public final byte[] getEncoded() {
+        byte[] b = getEncodedInternal();
+        return (b == null) ? null : b.clone();
+    }
+
+    abstract byte[] getEncodedInternal();
+
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        // equals() should never throw exceptions
+        if (token.isValid() == false) {
+            return false;
+        }
+        if (obj instanceof Key == false) {
+            return false;
+        }
+        String thisFormat = getFormat();
+        if (thisFormat == null) {
+            // no encoding, key only equal to itself
+            // XXX getEncoded() for unextractable keys will change that
+            return false;
+        }
+        Key other = (Key)obj;
+        if (thisFormat.equals(other.getFormat()) == false) {
+            return false;
+        }
+        byte[] thisEnc = this.getEncodedInternal();
+        byte[] otherEnc;
+        if (obj instanceof P11Key) {
+            otherEnc = ((P11Key)other).getEncodedInternal();
+        } else {
+            otherEnc = other.getEncoded();
+        }
+        return MessageDigest.isEqual(thisEnc, otherEnc);
+    }
+
+    public int hashCode() {
+        // hashCode() should never throw exceptions
+        if (token.isValid() == false) {
+            return 0;
+        }
+        byte[] b1 = getEncodedInternal();
+        if (b1 == null) {
+            return 0;
+        }
+        int r = b1.length;
+        for (int i = 0; i < b1.length; i++) {
+            r += (b1[i] & 0xff) * 37;
+        }
+        return r;
+    }
+
+    protected Object writeReplace() throws ObjectStreamException {
+        KeyRep.Type type;
+        String format = getFormat();
+        if (isPrivate() && "PKCS#8".equals(format)) {
+            type = KeyRep.Type.PRIVATE;
+        } else if (isPublic() && "X.509".equals(format)) {
+            type = KeyRep.Type.PUBLIC;
+        } else if (isSecret() && "RAW".equals(format)) {
+            type = KeyRep.Type.SECRET;
+        } else {
+            // XXX short term serialization for unextractable keys
+            throw new NotSerializableException
+                ("Cannot serialize sensitive and unextractable keys");
+        }
+        return new KeyRep(type, getAlgorithm(), format, getEncoded());
+    }
+
+    public String toString() {
+        token.ensureValid();
+        String s1 = token.provider.getName() + " " + algorithm + " " + type
+                + " key, " + keyLength + " bits";
+        s1 += " (id " + keyID + ", "
+                + (tokenObject ? "token" : "session") + " object";
+        if (isPublic()) {
+            s1 += ")";
+        } else {
+            s1 += ", " + (sensitive ? "" : "not ") + "sensitive";
+            s1 += ", " + (extractable ? "" : "un") + "extractable)";
+        }
+        return s1;
+    }
+
+    /**
+     * Return bit length of the key.
+     */
+    @Override
+    public int length() {
+        return keyLength;
+    }
+
+    boolean isPublic() {
+        return type == PUBLIC;
+    }
+
+    boolean isPrivate() {
+        return type == PRIVATE;
+    }
+
+    boolean isSecret() {
+        return type == SECRET;
+    }
+
+    void fetchAttributes(CK_ATTRIBUTE[] attributes) {
+        Session tempSession = null;
+        try {
+            tempSession = token.getOpSession();
+            token.p11.C_GetAttributeValue(tempSession.id(), keyID, attributes);
+        } catch (PKCS11Exception e) {
+            throw new ProviderException(e);
+        } finally {
+            token.releaseSession(tempSession);
+        }
+    }
+
+    private final static CK_ATTRIBUTE[] A0 = new CK_ATTRIBUTE[0];
+
+    private static CK_ATTRIBUTE[] getAttributes(Session session, long keyID,
+            CK_ATTRIBUTE[] knownAttributes, CK_ATTRIBUTE[] desiredAttributes) {
+        if (knownAttributes == null) {
+            knownAttributes = A0;
+        }
+        for (int i = 0; i < desiredAttributes.length; i++) {
+            // For each desired attribute, check to see if we have the value
+            // available already. If everything is here, we save a native call.
+            CK_ATTRIBUTE attr = desiredAttributes[i];
+            for (CK_ATTRIBUTE known : knownAttributes) {
+                if ((attr.type == known.type) && (known.pValue != null)) {
+                    attr.pValue = known.pValue;
+                    break; // break inner for loop
+                }
+            }
+            if (attr.pValue == null) {
+                // nothing found, need to call C_GetAttributeValue()
+                for (int j = 0; j < i; j++) {
+                    // clear values copied from knownAttributes
+                    desiredAttributes[j].pValue = null;
+                }
+                try {
+                    session.token.p11.C_GetAttributeValue
+                            (session.id(), keyID, desiredAttributes);
+                } catch (PKCS11Exception e) {
+                    throw new ProviderException(e);
+                }
+                break; // break loop, goto return
+            }
+        }
+        return desiredAttributes;
+    }
+
+    static SecretKey secretKey(Session session, long keyID, String algorithm,
+            int keyLength, CK_ATTRIBUTE[] attributes) {
+        attributes = getAttributes(session, keyID, attributes, new CK_ATTRIBUTE[] {
+            new CK_ATTRIBUTE(CKA_TOKEN),
+            new CK_ATTRIBUTE(CKA_SENSITIVE),
+            new CK_ATTRIBUTE(CKA_EXTRACTABLE),
+        });
+        return new P11SecretKey(session, keyID, algorithm, keyLength, attributes);
+    }
+
+    static SecretKey masterSecretKey(Session session, long keyID, String algorithm,
+            int keyLength, CK_ATTRIBUTE[] attributes, int major, int minor) {
+        attributes = getAttributes(session, keyID, attributes, new CK_ATTRIBUTE[] {
+            new CK_ATTRIBUTE(CKA_TOKEN),
+            new CK_ATTRIBUTE(CKA_SENSITIVE),
+            new CK_ATTRIBUTE(CKA_EXTRACTABLE),
+        });
+        return new P11TlsMasterSecretKey
+                (session, keyID, algorithm, keyLength, attributes, major, minor);
+    }
+
+    // we assume that all components of public keys are always accessible
+    static PublicKey publicKey(Session session, long keyID, String algorithm,
+            int keyLength, CK_ATTRIBUTE[] attributes) {
+        switch (algorithm) {
+            case "RSA":
+                return new P11RSAPublicKey
+                    (session, keyID, algorithm, keyLength, attributes);
+            case "DSA":
+                return new P11DSAPublicKey
+                    (session, keyID, algorithm, keyLength, attributes);
+            case "DH":
+                return new P11DHPublicKey
+                    (session, keyID, algorithm, keyLength, attributes);
+            case "EC":
+                return new P11ECPublicKey
+                    (session, keyID, algorithm, keyLength, attributes);
+            default:
+                throw new ProviderException
+                    ("Unknown public key algorithm " + algorithm);
+        }
+    }
+
+    static PrivateKey privateKey(Session session, long keyID, String algorithm,
+            int keyLength, CK_ATTRIBUTE[] attributes) {
+        attributes = getAttributes(session, keyID, attributes, new CK_ATTRIBUTE[] {
+            new CK_ATTRIBUTE(CKA_TOKEN),
+            new CK_ATTRIBUTE(CKA_SENSITIVE),
+            new CK_ATTRIBUTE(CKA_EXTRACTABLE),
+        });
+        if (attributes[1].getBoolean() || (attributes[2].getBoolean() == false)) {
+            return new P11PrivateKey
+                (session, keyID, algorithm, keyLength, attributes);
+        } else {
+            switch (algorithm) {
+                case "RSA":
+                    // In order to decide if this is RSA CRT key, we first query
+                    // and see if all extra CRT attributes are available.
+                    CK_ATTRIBUTE[] attrs2 = new CK_ATTRIBUTE[] {
+                        new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT),
+                        new CK_ATTRIBUTE(CKA_PRIME_1),
+                        new CK_ATTRIBUTE(CKA_PRIME_2),
+                        new CK_ATTRIBUTE(CKA_EXPONENT_1),
+                        new CK_ATTRIBUTE(CKA_EXPONENT_2),
+                        new CK_ATTRIBUTE(CKA_COEFFICIENT),
+                    };
+                    boolean crtKey;
+                    try {
+                        session.token.p11.C_GetAttributeValue
+                            (session.id(), keyID, attrs2);
+                        crtKey = ((attrs2[0].pValue instanceof byte[]) &&
+                                  (attrs2[1].pValue instanceof byte[]) &&
+                                  (attrs2[2].pValue instanceof byte[]) &&
+                                  (attrs2[3].pValue instanceof byte[]) &&
+                                  (attrs2[4].pValue instanceof byte[]) &&
+                                  (attrs2[5].pValue instanceof byte[])) ;
+                    } catch (PKCS11Exception e) {
+                        // ignore, assume not available
+                        crtKey = false;
+                    }
+                    if (crtKey) {
+                        return new P11RSAPrivateKey
+                                (session, keyID, algorithm, keyLength, attributes, attrs2);
+                    } else {
+                        return new P11RSAPrivateNonCRTKey
+                                (session, keyID, algorithm, keyLength, attributes);
+                    }
+                case "DSA":
+                    return new P11DSAPrivateKey
+                            (session, keyID, algorithm, keyLength, attributes);
+                case "DH":
+                    return new P11DHPrivateKey
+                            (session, keyID, algorithm, keyLength, attributes);
+                case "EC":
+                    return new P11ECPrivateKey
+                            (session, keyID, algorithm, keyLength, attributes);
+                default:
+                    throw new ProviderException
+                            ("Unknown private key algorithm " + algorithm);
+            }
+        }
+    }
+
+    // class for sensitive and unextractable private keys
+    private static final class P11PrivateKey extends P11Key
+                                                implements PrivateKey {
+        private static final long serialVersionUID = -2138581185214187615L;
+
+        P11PrivateKey(Session session, long keyID, String algorithm,
+                int keyLength, CK_ATTRIBUTE[] attributes) {
+            super(PRIVATE, session, keyID, algorithm, keyLength, attributes);
+        }
+        // XXX temporary encoding for serialization purposes
+        public String getFormat() {
+            token.ensureValid();
+            return null;
+        }
+        byte[] getEncodedInternal() {
+            token.ensureValid();
+            return null;
+        }
+    }
+
+    private static class P11SecretKey extends P11Key implements SecretKey {
+        private static final long serialVersionUID = -7828241727014329084L;
+        private volatile byte[] encoded;
+        P11SecretKey(Session session, long keyID, String algorithm,
+                int keyLength, CK_ATTRIBUTE[] attributes) {
+            super(SECRET, session, keyID, algorithm, keyLength, attributes);
+        }
+        public String getFormat() {
+            token.ensureValid();
+            if (sensitive || (extractable == false)) {
+                return null;
+            } else {
+                return "RAW";
+            }
+        }
+        byte[] getEncodedInternal() {
+            token.ensureValid();
+            if (getFormat() == null) {
+                return null;
+            }
+            byte[] b = encoded;
+            if (b == null) {
+                synchronized (this) {
+                    b = encoded;
+                    if (b == null) {
+                        Session tempSession = null;
+                        try {
+                            tempSession = token.getOpSession();
+                            CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
+                                new CK_ATTRIBUTE(CKA_VALUE),
+                            };
+                            token.p11.C_GetAttributeValue
+                                (tempSession.id(), keyID, attributes);
+                            b = attributes[0].getByteArray();
+                        } catch (PKCS11Exception e) {
+                            throw new ProviderException(e);
+                        } finally {
+                            token.releaseSession(tempSession);
+                        }
+                        encoded = b;
+                    }
+                }
+            }
+            return b;
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+    private static class P11TlsMasterSecretKey extends P11SecretKey
+            implements TlsMasterSecret {
+        private static final long serialVersionUID = -1318560923770573441L;
+
+        private final int majorVersion, minorVersion;
+        P11TlsMasterSecretKey(Session session, long keyID, String algorithm,
+                int keyLength, CK_ATTRIBUTE[] attributes, int major, int minor) {
+            super(session, keyID, algorithm, keyLength, attributes);
+            this.majorVersion = major;
+            this.minorVersion = minor;
+        }
+        public int getMajorVersion() {
+            return majorVersion;
+        }
+
+        public int getMinorVersion() {
+            return minorVersion;
+        }
+    }
+
+    // RSA CRT private key
+    private static final class P11RSAPrivateKey extends P11Key
+                implements RSAPrivateCrtKey {
+        private static final long serialVersionUID = 9215872438913515220L;
+
+        private BigInteger n, e, d, p, q, pe, qe, coeff;
+        private byte[] encoded;
+        P11RSAPrivateKey(Session session, long keyID, String algorithm,
+                int keyLength, CK_ATTRIBUTE[] attrs, CK_ATTRIBUTE[] crtAttrs) {
+            super(PRIVATE, session, keyID, algorithm, keyLength, attrs);
+
+            for (CK_ATTRIBUTE a : crtAttrs) {
+                if (a.type == CKA_PUBLIC_EXPONENT) {
+                    e = a.getBigInteger();
+                } else if (a.type == CKA_PRIME_1) {
+                    p = a.getBigInteger();
+                } else if (a.type == CKA_PRIME_2) {
+                    q = a.getBigInteger();
+                } else if (a.type == CKA_EXPONENT_1) {
+                    pe = a.getBigInteger();
+                } else if (a.type == CKA_EXPONENT_2) {
+                    qe = a.getBigInteger();
+                } else if (a.type == CKA_COEFFICIENT) {
+                    coeff = a.getBigInteger();
+                }
+            }
+        }
+        private synchronized void fetchValues() {
+            token.ensureValid();
+            if (n != null) {
+                return;
+            }
+            CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
+                new CK_ATTRIBUTE(CKA_MODULUS),
+                new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT),
+            };
+            fetchAttributes(attributes);
+            n = attributes[0].getBigInteger();
+            d = attributes[1].getBigInteger();
+        }
+
+        public String getFormat() {
+            token.ensureValid();
+            return "PKCS#8";
+        }
+        synchronized byte[] getEncodedInternal() {
+            token.ensureValid();
+            if (encoded == null) {
+                fetchValues();
+                try {
+                    // XXX make constructor in SunRsaSign provider public
+                    // and call it directly
+                    KeyFactory factory = KeyFactory.getInstance
+                        ("RSA", P11Util.getSunRsaSignProvider());
+                    Key newKey = factory.translateKey(this);
+                    encoded = newKey.getEncoded();
+                } catch (GeneralSecurityException e) {
+                    throw new ProviderException(e);
+                }
+            }
+            return encoded;
+        }
+        public BigInteger getModulus() {
+            fetchValues();
+            return n;
+        }
+        public BigInteger getPublicExponent() {
+            return e;
+        }
+        public BigInteger getPrivateExponent() {
+            fetchValues();
+            return d;
+        }
+        public BigInteger getPrimeP() {
+            return p;
+        }
+        public BigInteger getPrimeQ() {
+            return q;
+        }
+        public BigInteger getPrimeExponentP() {
+            return pe;
+        }
+        public BigInteger getPrimeExponentQ() {
+            return qe;
+        }
+        public BigInteger getCrtCoefficient() {
+            return coeff;
+        }
+    }
+
+    // RSA non-CRT private key
+    private static final class P11RSAPrivateNonCRTKey extends P11Key
+                implements RSAPrivateKey {
+        private static final long serialVersionUID = 1137764983777411481L;
+
+        private BigInteger n, d;
+        private byte[] encoded;
+        P11RSAPrivateNonCRTKey(Session session, long keyID, String algorithm,
+                int keyLength, CK_ATTRIBUTE[] attributes) {
+            super(PRIVATE, session, keyID, algorithm, keyLength, attributes);
+        }
+        private synchronized void fetchValues() {
+            token.ensureValid();
+            if (n != null) {
+                return;
+            }
+            CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
+                new CK_ATTRIBUTE(CKA_MODULUS),
+                new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT),
+            };
+            fetchAttributes(attributes);
+            n = attributes[0].getBigInteger();
+            d = attributes[1].getBigInteger();
+        }
+        public String getFormat() {
+            token.ensureValid();
+            return "PKCS#8";
+        }
+        synchronized byte[] getEncodedInternal() {
+            token.ensureValid();
+            if (encoded == null) {
+                fetchValues();
+                try {
+                    // XXX make constructor in SunRsaSign provider public
+                    // and call it directly
+                    KeyFactory factory = KeyFactory.getInstance
+                        ("RSA", P11Util.getSunRsaSignProvider());
+                    Key newKey = factory.translateKey(this);
+                    encoded = newKey.getEncoded();
+                } catch (GeneralSecurityException e) {
+                    throw new ProviderException(e);
+                }
+            }
+            return encoded;
+        }
+        public BigInteger getModulus() {
+            fetchValues();
+            return n;
+        }
+        public BigInteger getPrivateExponent() {
+            fetchValues();
+            return d;
+        }
+    }
+
+    private static final class P11RSAPublicKey extends P11Key
+                                                implements RSAPublicKey {
+        private static final long serialVersionUID = -826726289023854455L;
+
+        private BigInteger n, e;
+        private byte[] encoded;
+        P11RSAPublicKey(Session session, long keyID, String algorithm,
+                int keyLength, CK_ATTRIBUTE[] attributes) {
+            super(PUBLIC, session, keyID, algorithm, keyLength, attributes);
+        }
+        private synchronized void fetchValues() {
+            token.ensureValid();
+            if (n != null) {
+                return;
+            }
+            CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
+                new CK_ATTRIBUTE(CKA_MODULUS),
+                new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT),
+            };
+            fetchAttributes(attributes);
+            n = attributes[0].getBigInteger();
+            e = attributes[1].getBigInteger();
+        }
+        public String getFormat() {
+            token.ensureValid();
+            return "X.509";
+        }
+        synchronized byte[] getEncodedInternal() {
+            token.ensureValid();
+            if (encoded == null) {
+                fetchValues();
+                try {
+                    encoded = new RSAPublicKeyImpl(n, e).getEncoded();
+                } catch (InvalidKeyException e) {
+                    throw new ProviderException(e);
+                }
+            }
+            return encoded;
+        }
+        public BigInteger getModulus() {
+            fetchValues();
+            return n;
+        }
+        public BigInteger getPublicExponent() {
+            fetchValues();
+            return e;
+        }
+        public String toString() {
+            fetchValues();
+            return super.toString() +  "\n  modulus: " + n
+                + "\n  public exponent: " + e;
+        }
+    }
+
+    private static final class P11DSAPublicKey extends P11Key
+                                                implements DSAPublicKey {
+        private static final long serialVersionUID = 5989753793316396637L;
+
+        private BigInteger y;
+        private DSAParams params;
+        private byte[] encoded;
+        P11DSAPublicKey(Session session, long keyID, String algorithm,
+                int keyLength, CK_ATTRIBUTE[] attributes) {
+            super(PUBLIC, session, keyID, algorithm, keyLength, attributes);
+        }
+        private synchronized void fetchValues() {
+            token.ensureValid();
+            if (y != null) {
+                return;
+            }
+            CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
+                new CK_ATTRIBUTE(CKA_VALUE),
+                new CK_ATTRIBUTE(CKA_PRIME),
+                new CK_ATTRIBUTE(CKA_SUBPRIME),
+                new CK_ATTRIBUTE(CKA_BASE),
+            };
+            fetchAttributes(attributes);
+            y = attributes[0].getBigInteger();
+            params = new DSAParameterSpec(
+                attributes[1].getBigInteger(),
+                attributes[2].getBigInteger(),
+                attributes[3].getBigInteger()
+            );
+        }
+        public String getFormat() {
+            token.ensureValid();
+            return "X.509";
+        }
+        synchronized byte[] getEncodedInternal() {
+            token.ensureValid();
+            if (encoded == null) {
+                fetchValues();
+                try {
+                    Key key = new sun.security.provider.DSAPublicKey
+                            (y, params.getP(), params.getQ(), params.getG());
+                    encoded = key.getEncoded();
+                } catch (InvalidKeyException e) {
+                    throw new ProviderException(e);
+                }
+            }
+            return encoded;
+        }
+        public BigInteger getY() {
+            fetchValues();
+            return y;
+        }
+        public DSAParams getParams() {
+            fetchValues();
+            return params;
+        }
+        public String toString() {
+            fetchValues();
+            return super.toString() +  "\n  y: " + y + "\n  p: " + params.getP()
+                + "\n  q: " + params.getQ() + "\n  g: " + params.getG();
+        }
+    }
+
+    private static final class P11DSAPrivateKey extends P11Key
+                                                implements DSAPrivateKey {
+        private static final long serialVersionUID = 3119629997181999389L;
+
+        private BigInteger x;
+        private DSAParams params;
+        private byte[] encoded;
+        P11DSAPrivateKey(Session session, long keyID, String algorithm,
+                int keyLength, CK_ATTRIBUTE[] attributes) {
+            super(PRIVATE, session, keyID, algorithm, keyLength, attributes);
+        }
+        private synchronized void fetchValues() {
+            token.ensureValid();
+            if (x != null) {
+                return;
+            }
+            CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
+                new CK_ATTRIBUTE(CKA_VALUE),
+                new CK_ATTRIBUTE(CKA_PRIME),
+                new CK_ATTRIBUTE(CKA_SUBPRIME),
+                new CK_ATTRIBUTE(CKA_BASE),
+            };
+            fetchAttributes(attributes);
+            x = attributes[0].getBigInteger();
+            params = new DSAParameterSpec(
+                attributes[1].getBigInteger(),
+                attributes[2].getBigInteger(),
+                attributes[3].getBigInteger()
+            );
+        }
+        public String getFormat() {
+            token.ensureValid();
+            return "PKCS#8";
+        }
+        synchronized byte[] getEncodedInternal() {
+            token.ensureValid();
+            if (encoded == null) {
+                fetchValues();
+                try {
+                    Key key = new sun.security.provider.DSAPrivateKey
+                            (x, params.getP(), params.getQ(), params.getG());
+                    encoded = key.getEncoded();
+                } catch (InvalidKeyException e) {
+                    throw new ProviderException(e);
+                }
+            }
+            return encoded;
+        }
+        public BigInteger getX() {
+            fetchValues();
+            return x;
+        }
+        public DSAParams getParams() {
+            fetchValues();
+            return params;
+        }
+    }
+
+    private static final class P11DHPrivateKey extends P11Key
+                                                implements DHPrivateKey {
+        private static final long serialVersionUID = -1698576167364928838L;
+
+        private BigInteger x;
+        private DHParameterSpec params;
+        private byte[] encoded;
+        P11DHPrivateKey(Session session, long keyID, String algorithm,
+                int keyLength, CK_ATTRIBUTE[] attributes) {
+            super(PRIVATE, session, keyID, algorithm, keyLength, attributes);
+        }
+        private synchronized void fetchValues() {
+            token.ensureValid();
+            if (x != null) {
+                return;
+            }
+            CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
+                new CK_ATTRIBUTE(CKA_VALUE),
+                new CK_ATTRIBUTE(CKA_PRIME),
+                new CK_ATTRIBUTE(CKA_BASE),
+            };
+            fetchAttributes(attributes);
+            x = attributes[0].getBigInteger();
+            params = new DHParameterSpec(
+                attributes[1].getBigInteger(),
+                attributes[2].getBigInteger()
+            );
+        }
+        public String getFormat() {
+            token.ensureValid();
+            return "PKCS#8";
+        }
+        synchronized byte[] getEncodedInternal() {
+            token.ensureValid();
+            if (encoded == null) {
+                fetchValues();
+                try {
+                    DHPrivateKeySpec spec = new DHPrivateKeySpec
+                        (x, params.getP(), params.getG());
+                    KeyFactory kf = KeyFactory.getInstance
+                        ("DH", P11Util.getSunJceProvider());
+                    Key key = kf.generatePrivate(spec);
+                    encoded = key.getEncoded();
+                } catch (GeneralSecurityException e) {
+                    throw new ProviderException(e);
+                }
+            }
+            return encoded;
+        }
+        public BigInteger getX() {
+            fetchValues();
+            return x;
+        }
+        public DHParameterSpec getParams() {
+            fetchValues();
+            return params;
+        }
+        public int hashCode() {
+            if (token.isValid() == false) {
+                return 0;
+            }
+            fetchValues();
+            return Objects.hash(x, params.getP(), params.getG());
+        }
+        public boolean equals(Object obj) {
+            if (this == obj) return true;
+            // equals() should never throw exceptions
+            if (token.isValid() == false) {
+                return false;
+            }
+            if (!(obj instanceof DHPrivateKey)) {
+                return false;
+            }
+            fetchValues();
+            DHPrivateKey other = (DHPrivateKey) obj;
+            DHParameterSpec otherParams = other.getParams();
+            return ((this.x.compareTo(other.getX()) == 0) &&
+                    (this.params.getP().compareTo(otherParams.getP()) == 0) &&
+                    (this.params.getG().compareTo(otherParams.getG()) == 0));
+        }
+    }
+
+    private static final class P11DHPublicKey extends P11Key
+                                                implements DHPublicKey {
+        static final long serialVersionUID = -598383872153843657L;
+
+        private BigInteger y;
+        private DHParameterSpec params;
+        private byte[] encoded;
+        P11DHPublicKey(Session session, long keyID, String algorithm,
+                int keyLength, CK_ATTRIBUTE[] attributes) {
+            super(PUBLIC, session, keyID, algorithm, keyLength, attributes);
+        }
+        private synchronized void fetchValues() {
+            token.ensureValid();
+            if (y != null) {
+                return;
+            }
+            CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
+                new CK_ATTRIBUTE(CKA_VALUE),
+                new CK_ATTRIBUTE(CKA_PRIME),
+                new CK_ATTRIBUTE(CKA_BASE),
+            };
+            fetchAttributes(attributes);
+            y = attributes[0].getBigInteger();
+            params = new DHParameterSpec(
+                attributes[1].getBigInteger(),
+                attributes[2].getBigInteger()
+            );
+        }
+        public String getFormat() {
+            token.ensureValid();
+            return "X.509";
+        }
+        synchronized byte[] getEncodedInternal() {
+            token.ensureValid();
+            if (encoded == null) {
+                fetchValues();
+                try {
+                    DHPublicKeySpec spec = new DHPublicKeySpec
+                        (y, params.getP(), params.getG());
+                    KeyFactory kf = KeyFactory.getInstance
+                        ("DH", P11Util.getSunJceProvider());
+                    Key key = kf.generatePublic(spec);
+                    encoded = key.getEncoded();
+                } catch (GeneralSecurityException e) {
+                    throw new ProviderException(e);
+                }
+            }
+            return encoded;
+        }
+        public BigInteger getY() {
+            fetchValues();
+            return y;
+        }
+        public DHParameterSpec getParams() {
+            fetchValues();
+            return params;
+        }
+        public String toString() {
+            fetchValues();
+            return super.toString() +  "\n  y: " + y + "\n  p: " + params.getP()
+                + "\n  g: " + params.getG();
+        }
+        public int hashCode() {
+            if (token.isValid() == false) {
+                return 0;
+            }
+            fetchValues();
+            return Objects.hash(y, params.getP(), params.getG());
+        }
+        public boolean equals(Object obj) {
+            if (this == obj) return true;
+            // equals() should never throw exceptions
+            if (token.isValid() == false) {
+                return false;
+            }
+            if (!(obj instanceof DHPublicKey)) {
+                return false;
+            }
+            fetchValues();
+            DHPublicKey other = (DHPublicKey) obj;
+            DHParameterSpec otherParams = other.getParams();
+            return ((this.y.compareTo(other.getY()) == 0) &&
+                    (this.params.getP().compareTo(otherParams.getP()) == 0) &&
+                    (this.params.getG().compareTo(otherParams.getG()) == 0));
+        }
+    }
+
+    private static final class P11ECPrivateKey extends P11Key
+                                                implements ECPrivateKey {
+        private static final long serialVersionUID = -7786054399510515515L;
+
+        private BigInteger s;
+        private ECParameterSpec params;
+        private byte[] encoded;
+        P11ECPrivateKey(Session session, long keyID, String algorithm,
+                int keyLength, CK_ATTRIBUTE[] attributes) {
+            super(PRIVATE, session, keyID, algorithm, keyLength, attributes);
+        }
+        private synchronized void fetchValues() {
+            token.ensureValid();
+            if (s != null) {
+                return;
+            }
+            CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
+                new CK_ATTRIBUTE(CKA_VALUE),
+                new CK_ATTRIBUTE(CKA_EC_PARAMS, params),
+            };
+            fetchAttributes(attributes);
+            s = attributes[0].getBigInteger();
+            try {
+                params = P11ECKeyFactory.decodeParameters
+                            (attributes[1].getByteArray());
+            } catch (Exception e) {
+                throw new RuntimeException("Could not parse key values", e);
+            }
+        }
+        public String getFormat() {
+            token.ensureValid();
+            return "PKCS#8";
+        }
+        synchronized byte[] getEncodedInternal() {
+            token.ensureValid();
+            if (encoded == null) {
+                fetchValues();
+                try {
+                    Key key = ECUtil.generateECPrivateKey(s, params);
+                    encoded = key.getEncoded();
+                } catch (InvalidKeySpecException e) {
+                    throw new ProviderException(e);
+                }
+            }
+            return encoded;
+        }
+        public BigInteger getS() {
+            fetchValues();
+            return s;
+        }
+        public ECParameterSpec getParams() {
+            fetchValues();
+            return params;
+        }
+    }
+
+    private static final class P11ECPublicKey extends P11Key
+                                                implements ECPublicKey {
+        private static final long serialVersionUID = -6371481375154806089L;
+
+        private ECPoint w;
+        private ECParameterSpec params;
+        private byte[] encoded;
+        P11ECPublicKey(Session session, long keyID, String algorithm,
+                int keyLength, CK_ATTRIBUTE[] attributes) {
+            super(PUBLIC, session, keyID, algorithm, keyLength, attributes);
+        }
+        private synchronized void fetchValues() {
+            token.ensureValid();
+            if (w != null) {
+                return;
+            }
+            CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
+                new CK_ATTRIBUTE(CKA_EC_POINT),
+                new CK_ATTRIBUTE(CKA_EC_PARAMS),
+            };
+            fetchAttributes(attributes);
+
+            try {
+                params = P11ECKeyFactory.decodeParameters
+                            (attributes[1].getByteArray());
+                byte[] ecKey = attributes[0].getByteArray();
+
+                // Check whether the X9.63 encoding of an EC point is wrapped
+                // in an ASN.1 OCTET STRING
+                if (!token.config.getUseEcX963Encoding()) {
+                    DerValue wECPoint = new DerValue(ecKey);
+
+                    if (wECPoint.getTag() != DerValue.tag_OctetString) {
+                        throw new IOException("Could not DER decode EC point." +
+                            " Unexpected tag: " + wECPoint.getTag());
+                    }
+                    w = P11ECKeyFactory.decodePoint
+                        (wECPoint.getDataBytes(), params.getCurve());
+
+                } else {
+                    w = P11ECKeyFactory.decodePoint(ecKey, params.getCurve());
+                }
+
+            } catch (Exception e) {
+                throw new RuntimeException("Could not parse key values", e);
+            }
+        }
+        public String getFormat() {
+            token.ensureValid();
+            return "X.509";
+        }
+        synchronized byte[] getEncodedInternal() {
+            token.ensureValid();
+            if (encoded == null) {
+                fetchValues();
+                try {
+                    return ECUtil.x509EncodeECPublicKey(w, params);
+                } catch (InvalidKeySpecException e) {
+                    throw new ProviderException(e);
+                }
+            }
+            return encoded;
+        }
+        public ECPoint getW() {
+            fetchValues();
+            return w;
+        }
+        public ECParameterSpec getParams() {
+            fetchValues();
+            return params;
+        }
+        public String toString() {
+            fetchValues();
+            return super.toString()
+                + "\n  public x coord: " + w.getAffineX()
+                + "\n  public y coord: " + w.getAffineY()
+                + "\n  parameters: " + params;
+        }
+    }
+}
+
+/*
+ * NOTE: Must use PhantomReference here and not WeakReference
+ * otherwise the key maybe cleared before other objects which
+ * still use these keys during finalization such as SSLSocket.
+ */
+final class SessionKeyRef extends PhantomReference<P11Key>
+    implements Comparable<SessionKeyRef> {
+    private static ReferenceQueue<P11Key> refQueue =
+        new ReferenceQueue<P11Key>();
+    private static Set<SessionKeyRef> refList =
+        Collections.synchronizedSortedSet(new TreeSet<SessionKeyRef>());
+
+    static ReferenceQueue<P11Key> referenceQueue() {
+        return refQueue;
+    }
+
+    private static void drainRefQueueBounded() {
+        Session sess = null;
+        Token tkn = null;
+        while (true) {
+            SessionKeyRef next = (SessionKeyRef) refQueue.poll();
+            if (next == null) {
+                break;
+            }
+
+            // If the token is still valid, try to remove the object
+            if (next.session.token.isValid()) {
+                // If this key's token is the same as the previous key, the
+                // same session can be used for C_DestroyObject.
+                try {
+                    if (next.session.token != tkn || sess == null) {
+                        // Release session if not using previous token
+                        if (tkn != null && sess != null) {
+                            tkn.releaseSession(sess);
+                            sess = null;
+                        }
+
+                        tkn = next.session.token;
+                        sess = tkn.getOpSession();
+                    }
+                    next.disposeNative(sess);
+                } catch (PKCS11Exception e) {
+                    // ignore
+                }
+            }
+            // Regardless of native results, dispose of java references
+            next.dispose();
+        }
+
+        if (tkn != null && sess != null) {
+            tkn.releaseSession(sess);
+        }
+    }
+
+    // handle to the native key
+    private long keyID;
+    private Session session;
+
+    SessionKeyRef(P11Key key , long keyID, Session session) {
+        super(key, refQueue);
+        this.keyID = keyID;
+        this.session = session;
+        this.session.addObject();
+        refList.add(this);
+        drainRefQueueBounded();
+    }
+
+    private void disposeNative(Session s) throws PKCS11Exception {
+        session.token.p11.C_DestroyObject(s.id(), keyID);
+    }
+
+    private void dispose() {
+        refList.remove(this);
+        this.clear();
+        session.removeObject();
+    }
+
+    public int compareTo(SessionKeyRef other) {
+        if (this.keyID == other.keyID) {
+            return 0;
+        } else {
+            return (this.keyID < other.keyID) ? -1 : 1;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyAgreement.java	Thu Jan 26 09:19:33 2017 -0800
@@ -0,0 +1,347 @@
+/*
+ * Copyright (c) 2003, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package sun.security.pkcs11;
+
+import java.math.BigInteger;
+
+import java.security.*;
+import java.security.spec.*;
+
+import javax.crypto.*;
+import javax.crypto.interfaces.*;
+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.util.KeyUtil;
+
+/**
+ * KeyAgreement implementation class. This class currently supports
+ * DH.
+ *
+ * @author  Andreas Sterbenz
+ * @since   1.5
+ */
+final class P11KeyAgreement extends KeyAgreementSpi {
+
+    // token instance
+    private final Token token;
+
+    // algorithm name
+    private final String algorithm;
+
+    // mechanism id
+    private final long mechanism;
+
+    // private key, if initialized
+    private P11Key privateKey;
+
+    // other sides public value ("y"), if doPhase() already called
+    private BigInteger publicValue;
+
+    // length of the secret to be derived
+    private int secretLen;
+
+    // KeyAgreement from SunJCE as fallback for > 2 party agreement
+    private KeyAgreement multiPartyAgreement;
+
+    P11KeyAgreement(Token token, String algorithm, long mechanism) {
+        super();
+        this.token = token;
+        this.algorithm = algorithm;
+        this.mechanism = mechanism;
+    }
+
+    // see JCE spec
+    protected void engineInit(Key key, SecureRandom random)
+            throws InvalidKeyException {
+        if (key instanceof PrivateKey == false) {
+            throw new InvalidKeyException
+                        ("Key must be instance of PrivateKey");
+        }
+        privateKey = P11KeyFactory.convertKey(token, key, algorithm);
+        publicValue = null;
+        multiPartyAgreement = null;
+    }
+
+    // see JCE spec
+    protected void engineInit(Key key, AlgorithmParameterSpec params,
+            SecureRandom random) throws InvalidKeyException,
+            InvalidAlgorithmParameterException {
+        if (params != null) {
+            throw new InvalidAlgorithmParameterException
+                        ("Parameters not supported");
+        }
+        engineInit(key, random);
+    }
+
+    // see JCE spec
+    protected Key engineDoPhase(Key key, boolean lastPhase)
+            throws InvalidKeyException, IllegalStateException {
+        if (privateKey == null) {
+            throw new IllegalStateException("Not initialized");
+        }
+        if (publicValue != null) {
+            throw new IllegalStateException("Phase already executed");
+        }
+        // PKCS#11 only allows key agreement between 2 parties
+        // JCE allows >= 2 parties. To support that case (for compatibility
+        // and to pass JCK), fall back to SunJCE in this case.
+        // NOTE that we initialize using the P11Key, which will fail if it
+        // is sensitive/unextractable. However, this is not an issue in the
+        // compatibility configuration, which is all we are targeting here.
+        if ((multiPartyAgreement != null) || (lastPhase == false)) {
+            if (multiPartyAgreement == null) {
+                try {
+                    multiPartyAgreement = KeyAgreement.getInstance
+                        ("DH", P11Util.getSunJceProvider());
+                    multiPartyAgreement.init(privateKey);
+                } catch (NoSuchAlgorithmException e) {
+                    throw new InvalidKeyException
+                        ("Could not initialize multi party agreement", e);
+                }
+            }
+            return multiPartyAgreement.doPhase(key, lastPhase);
+        }
+        if ((key instanceof PublicKey == false)
+                || (key.getAlgorithm().equals(algorithm) == false)) {
+            throw new InvalidKeyException
+                ("Key must be a PublicKey with algorithm DH");
+        }
+        BigInteger p, g, y;
+        if (key instanceof DHPublicKey) {
+            DHPublicKey dhKey = (DHPublicKey)key;
+
+            // validate the Diffie-Hellman public key
+            KeyUtil.validate(dhKey);
+
+            y = dhKey.getY();
+            DHParameterSpec params = dhKey.getParams();
+            p = params.getP();
+            g = params.getG();
+        } else {
+            // normally, DH PublicKeys will always implement DHPublicKey
+            // just in case not, attempt conversion
+            P11DHKeyFactory kf = new P11DHKeyFactory(token, "DH");
+            try {
+                DHPublicKeySpec spec = kf.engineGetKeySpec(
+                        key, DHPublicKeySpec.class);
+
+                // validate the Diffie-Hellman public key
+                KeyUtil.validate(spec);
+
+                y = spec.getY();
+                p = spec.getP();
+                g = spec.getG();
+            } catch (InvalidKeySpecException e) {
+                throw new InvalidKeyException("Could not obtain key values", e);
+            }
+        }
+        // if parameters of private key are accessible, verify that
+        // they match parameters of public key
+        // XXX p and g should always be readable, even if the key is sensitive
+        if (privateKey instanceof DHPrivateKey) {
+            DHPrivateKey dhKey = (DHPrivateKey)privateKey;
+            DHParameterSpec params = dhKey.getParams();
+            if ((p.equals(params.getP()) == false)
+                                || (g.equals(params.getG()) == false)) {
+                throw new InvalidKeyException
+                ("PublicKey DH parameters must match PrivateKey DH parameters");
+            }
+        }
+        publicValue = y;
+        // length of the secret is length of key
+        secretLen = (p.bitLength() + 7) >> 3;
+        return null;
+    }
+
+    // see JCE spec
+    protected byte[] engineGenerateSecret() throws IllegalStateException {
+        if (multiPartyAgreement != null) {
+            byte[] val = multiPartyAgreement.generateSecret();
+            multiPartyAgreement = null;
+            return val;
+        }
+        if ((privateKey == null) || (publicValue == null)) {
+            throw new IllegalStateException("Not initialized correctly");
+        }
+        Session session = null;
+        try {
+            session = token.getOpSession();
+            CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
+                new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
+                new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_GENERIC_SECRET),
+            };
+            attributes = token.getAttributes
+                (O_GENERATE, CKO_SECRET_KEY, CKK_GENERIC_SECRET, attributes);
+            long keyID = token.p11.C_DeriveKey(session.id(),
+                new CK_MECHANISM(mechanism, publicValue), privateKey.keyID,
+                attributes);
+            attributes = new CK_ATTRIBUTE[] {
+                new CK_ATTRIBUTE(CKA_VALUE)
+            };
+            token.p11.C_GetAttributeValue(session.id(), keyID, attributes);
+            byte[] secret = attributes[0].getByteArray();
+            token.p11.C_DestroyObject(session.id(), keyID);
+            // Some vendors, e.g. NSS, trim off the leading 0x00 byte(s) from
+            // the generated secret. Thus, we need to check the secret length
+            // and trim/pad it so the returned value has the same length as
+            // the modulus size
+            if (secret.length == secretLen) {
+                return secret;
+            } else {
+                if (secret.length > secretLen) {
+                    // Shouldn't happen; but check just in case
+                    throw new ProviderException("generated secret is out-of-range");
+                }
+                byte[] newSecret = new byte[secretLen];
+                System.arraycopy(secret, 0, newSecret, secretLen - secret.length,
+                    secret.length);
+                return newSecret;
+            }
+        } catch (PKCS11Exception e) {
+            throw new ProviderException("Could not derive key", e);
+        } finally {
+            publicValue = null;
+            token.releaseSession(session);
+        }
+    }
+
+    // see JCE spec
+    protected int engineGenerateSecret(byte[] sharedSecret, int
+            offset) throws IllegalStateException, ShortBufferException {
+        if (multiPartyAgreement != null) {
+            int n = multiPartyAgreement.generateSecret(sharedSecret, offset);
+            multiPartyAgreement = null;
+            return n;
+        }
+        if (offset + secretLen > sharedSecret.length) {
+            throw new ShortBufferException("Need " + secretLen
+                + " bytes, only " + (sharedSecret.length - offset) + " available");
+        }
+        byte[] secret = engineGenerateSecret();
+        System.arraycopy(secret, 0, sharedSecret, offset, secret.length);
+        return secret.length;
+    }
+
+    // see JCE spec
+    protected SecretKey engineGenerateSecret(String algorithm)
+            throws IllegalStateException, NoSuchAlgorithmException,
+            InvalidKeyException {
+        if (multiPartyAgreement != null) {
+            SecretKey key = multiPartyAgreement.generateSecret(algorithm);
+            multiPartyAgreement = null;
+            return key;
+        }
+        if (algorithm == null) {
+            throw new NoSuchAlgorithmException("Algorithm must not be null");
+        }
+        if (algorithm.equals("TlsPremasterSecret")) {
+            // For now, only perform native derivation for TlsPremasterSecret
+            // as that is required for FIPS compliance.
+            // For other algorithms, there are unresolved issues regarding
+            // how this should work in JCE plus a Solaris truncation bug.
+            // (bug not yet filed).
+            return nativeGenerateSecret(algorithm);
+        }
+        byte[] secret = engineGenerateSecret();
+        // Maintain compatibility for SunJCE:
+        // verify secret length is sensible for algorithm / truncate
+        // return generated key itself if possible
+        int keyLen;
+        if (algorithm.equalsIgnoreCase("DES")) {
+            keyLen = 8;
+        } else if (algorithm.equalsIgnoreCase("DESede")) {
+            keyLen = 24;
+        } else if (algorithm.equalsIgnoreCase("Blowfish")) {
+            keyLen = Math.min(56, secret.length);
+        } else if (algorithm.equalsIgnoreCase("TlsPremasterSecret")) {
+            keyLen = secret.length;
+        } else {
+            throw new NoSuchAlgorithmException
+                ("Unknown algorithm " + algorithm);
+        }
+        if (secret.length < keyLen) {
+            throw new InvalidKeyException("Secret too short");
+        }
+        if (algorithm.equalsIgnoreCase("DES") ||
+            algorithm.equalsIgnoreCase("DESede")) {
+                for (int i = 0; i < keyLen; i+=8) {
+                    P11SecretKeyFactory.fixDESParity(secret, i);
+                }
+        }
+        return new SecretKeySpec(secret, 0, keyLen, algorithm);
+    }
+
+    private SecretKey nativeGenerateSecret(String algorithm)
+            throws IllegalStateException, NoSuchAlgorithmException,
+            InvalidKeyException {
+        if ((privateKey == null) || (publicValue == null)) {
+            throw new IllegalStateException("Not initialized correctly");
+        }
+        long keyType = CKK_GENERIC_SECRET;
+        Session session = null;
+        try {
+            session = token.getObjSession();
+            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_GENERATE, CKO_SECRET_KEY, keyType, attributes);
+            long keyID = token.p11.C_DeriveKey(session.id(),
+                new CK_MECHANISM(mechanism, publicValue), privateKey.keyID,
+                attributes);
+            CK_ATTRIBUTE[] lenAttributes = new CK_ATTRIBUTE[] {
+                new CK_ATTRIBUTE(CKA_VALUE_LEN),
+            };
+            token.p11.C_GetAttributeValue(session.id(), keyID, lenAttributes);
+            int keyLen = (int)lenAttributes[0].getLong();
+            SecretKey key = P11Key.secretKey
+                        (session, keyID, algorithm, keyLen << 3, attributes);
+            if ("RAW".equals(key.getFormat())) {
+                // Workaround for Solaris bug 6318543.
+                // Strip leading zeroes ourselves if possible (key not sensitive).
+                // This should be removed once the Solaris fix is available
+                // as here we always retrieve the CKA_VALUE even for tokens
+                // that do not have that bug.
+                byte[] keyBytes = key.getEncoded();
+                byte[] newBytes = KeyUtil.trimZeroes(keyBytes);
+                if (keyBytes != newBytes) {
+                    key = new SecretKeySpec(newBytes, algorithm);
+                }
+            }
+            return key;
+        } catch (PKCS11Exception e) {
+            throw new InvalidKeyException("Could not derive key", e);
+        } finally {
+            publicValue = null;
+            token.releaseSession(session);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyFactory.java	Thu Jan 26 09:19:33 2017 -0800
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2003, 2011, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package sun.security.pkcs11;
+
+import java.security.*;
+import java.security.spec.*;
+
+import sun.security.pkcs11.wrapper.PKCS11Exception;
+
+/**
+ * KeyFactory base class. Provides common infrastructure for the RSA, DSA,
+ * and DH implementations.
+ *
+ * The subclasses support conversion between keys and keyspecs
+ * using X.509, PKCS#8, and their individual algorithm specific formats,
+ * assuming keys are extractable.
+ *
+ * @author  Andreas Sterbenz
+ * @since   1.5
+ */
+abstract class P11KeyFactory extends KeyFactorySpi {
+
+    // token instance
+    final Token token;
+
+    // algorithm name, currently one of RSA, DSA, DH
+    final String algorithm;
+
+    P11KeyFactory(Token token, String algorithm) {
+        super();
+        this.token = token;
+        this.algorithm = algorithm;
+    }
+
+    /**
+     * Convert an arbitrary key of algorithm into a P11Key of token.
+     * Used by P11Signature.init() and RSACipher.init().
+     */
+    static P11Key convertKey(Token token, Key key, String algorithm)
+            throws InvalidKeyException {
+        return (P11Key)token.getKeyFactory(algorithm).engineTranslateKey(key);
+    }
+
+    // see JCA spec
+    protected final <T extends KeySpec> T engineGetKeySpec(Key key, Class<T> keySpec)
+            throws InvalidKeySpecException {
+        token.ensureValid();
+        if ((key == null) || (keySpec == null)) {
+            throw new InvalidKeySpecException
+                ("key and keySpec must not be null");
+        }
+        // delegate to our Java based providers for PKCS#8 and X.509
+        if (PKCS8EncodedKeySpec.class.isAssignableFrom(keySpec)
+                || X509EncodedKeySpec.class.isAssignableFrom(keySpec)) {
+            try {
+                return implGetSoftwareFactory().getKeySpec(key, keySpec);
+            } catch (GeneralSecurityException e) {
+                throw new InvalidKeySpecException("Could not encode key", e);
+            }
+        }
+        // first translate into a key of this token, if it is not already
+        P11Key p11Key;
+        try {
+            p11Key = (P11Key)engineTranslateKey(key);
+        } catch (InvalidKeyException e) {
+            throw new InvalidKeySpecException("Could not convert key", e);
+        }
+        Session[] session = new Session[1];
+        try {
+            if (p11Key.isPublic()) {
+                return implGetPublicKeySpec(p11Key, keySpec, session);
+            } else {
+                return implGetPrivateKeySpec(p11Key, keySpec, session);
+            }
+        } catch (PKCS11Exception e) {
+            throw new InvalidKeySpecException("Could not generate KeySpec", e);
+        } finally {
+            session[0] = token.releaseSession(session[0]);
+        }
+    }
+
+    // see JCA spec
+    protected final Key engineTranslateKey(Key key) throws InvalidKeyException {
+        token.ensureValid();
+        if (key == null) {
+            throw new InvalidKeyException("Key must not be null");
+        }
+        if (key.getAlgorithm().equals(this.algorithm) == false) {
+            throw new InvalidKeyException
+                ("Key algorithm must be " + algorithm);
+        }
+        if (key instanceof P11Key) {
+            P11Key p11Key = (P11Key)key;
+            if (p11Key.token == token) {
+                // already a key of this token, no need to translate
+                return key;
+            }
+        }
+        P11Key p11Key = token.privateCache.get(key);
+        if (p11Key != null) {
+            return p11Key;
+        }
+        if (key instanceof PublicKey) {
+            PublicKey publicKey = implTranslatePublicKey((PublicKey)key);
+            token.privateCache.put(key, (P11Key)publicKey);
+            return publicKey;
+        } else if (key instanceof PrivateKey) {
+            PrivateKey privateKey = implTranslatePrivateKey((PrivateKey)key);
+            token.privateCache.put(key, (P11Key)privateKey);
+            return privateKey;
+        } else {
+            throw new InvalidKeyException
+                ("Key must be instance of PublicKey or PrivateKey");
+        }
+    }
+
+    abstract <T extends KeySpec> T  implGetPublicKeySpec(P11Key key, Class<T> keySpec,
+            Session[] session) throws PKCS11Exception, InvalidKeySpecException;
+
+    abstract <T extends KeySpec> T  implGetPrivateKeySpec(P11Key key, Class<T> keySpec,
+            Session[] session) throws PKCS11Exception, InvalidKeySpecException;
+
+    abstract PublicKey implTranslatePublicKey(PublicKey key)
+            throws InvalidKeyException;
+
+    abstract PrivateKey implTranslatePrivateKey(PrivateKey key)
+            throws InvalidKeyException;
+
+    abstract KeyFactory implGetSoftwareFactory() throws GeneralSecurityException;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyGenerator.java	Thu Jan 26 09:19:33 2017 -0800
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2003, 2008, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package sun.security.pkcs11;
+
+import java.security.*;
+import java.security.spec.AlgorithmParameterSpec;
+
+import javax.crypto.*;
+
+import static sun.security.pkcs11.TemplateManager.*;
+import sun.security.pkcs11.wrapper.*;
+import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
+
+/**
+ * KeyGenerator implementation class. This class currently supports
+ * DES, DESede, AES, ARCFOUR, and Blowfish.
+ *
+ * @author  Andreas Sterbenz
+ * @since   1.5
+ */
+final class P11KeyGenerator extends KeyGeneratorSpi {
+
+    // token instance
+    private final Token token;
+
+    // algorithm name
+    private final String algorithm;
+
+    // mechanism id
+    private long mechanism;
+
+    // raw key size in bits, e.g. 64 for DES. Always valid.
+    private int keySize;
+
+    // bits of entropy in the key, e.g. 56 for DES. Always valid.
+    private int significantKeySize;
+
+    // keyType (CKK_*), needed for TemplateManager call only.
+    private long keyType;
+
+    // for determining if both 112 and 168 bits of DESede key lengths
+    // are supported.
+    private boolean supportBothKeySizes;
+
+    /**
+     * Utility method for checking if the specified key size is valid
+     * and within the supported range. Return the significant key size
+     * upon successful validation.
+     * @param keyGenMech the PKCS#11 key generation mechanism.
+     * @param keySize the to-be-checked key size for this mechanism.
+     * @param token token which provides this mechanism.
+     * @return the significant key size (in bits) corresponding to the
+     * specified key size.
+     * @throws InvalidParameterException if the specified key size is invalid.
+     * @throws ProviderException if this mechanism isn't supported by SunPKCS11
+     * or underlying native impl.
+     */
+    static int checkKeySize(long keyGenMech, int keySize, Token token)
+        throws InvalidAlgorithmParameterException, ProviderException {
+        int sigKeySize;
+        switch ((int)keyGenMech) {
+            case (int)CKM_DES_KEY_GEN:
+                if ((keySize != 64) && (keySize != 56)) {
+                    throw new InvalidAlgorithmParameterException
+                            ("DES key length must be 56 bits");
+                }
+                sigKeySize = 56;
+                break;
+            case (int)CKM_DES2_KEY_GEN:
+            case (int)CKM_DES3_KEY_GEN:
+                if ((keySize == 112) || (keySize == 128)) {
+                    sigKeySize = 112;
+                } else if ((keySize == 168) || (keySize == 192)) {
+                    sigKeySize = 168;
+                } else {
+                    throw new InvalidAlgorithmParameterException
+                            ("DESede key length must be 112, or 168 bits");
+                }
+                break;
+            default:
+                // Handle all variable-key-length algorithms here
+                CK_MECHANISM_INFO info = null;
+                try {
+                    info = token.getMechanismInfo(keyGenMech);
+                } catch (PKCS11Exception p11e) {
+                    // Should never happen
+                    throw new ProviderException
+                            ("Cannot retrieve mechanism info", p11e);
+                }
+                if (info == null) {
+                    // XXX Unable to retrieve the supported key length from
+                    // the underlying native impl. Skip the checking for now.
+                    return keySize;
+                }
+                // PKCS#11 defines these to be in number of bytes except for
+                // RC4 which is in bits. However, some PKCS#11 impls still use
+                // bytes for all mechs, e.g. NSS. We try to detect this
+                // inconsistency if the minKeySize seems unreasonably small.
+                int minKeySize = (int)info.ulMinKeySize;
+                int maxKeySize = (int)info.ulMaxKeySize;
+                if (keyGenMech != CKM_RC4_KEY_GEN || minKeySize < 8) {
+                    minKeySize = (int)info.ulMinKeySize << 3;
+                    maxKeySize = (int)info.ulMaxKeySize << 3;
+                }
+                // Explicitly disallow keys shorter than 40-bits for security
+                if (minKeySize < 40) minKeySize = 40;
+                if (keySize < minKeySize || keySize > maxKeySize) {
+                    throw new InvalidAlgorithmParameterException
+                            ("Key length must be between " + minKeySize +
+                            " and " + maxKeySize + " bits");
+                }
+                if (keyGenMech == CKM_AES_KEY_GEN) {
+                    if ((keySize != 128) && (keySize != 192) &&
+                        (keySize != 256)) {
+                        throw new InvalidAlgorithmParameterException
+                                ("AES key length must be " + minKeySize +
+                                (maxKeySize >= 192? ", 192":"") +
+                                (maxKeySize >= 256? ", or 256":"") + " bits");
+                    }
+                }
+                sigKeySize = keySize;
+        }
+        return sigKeySize;
+    }
+
+    P11KeyGenerator(Token token, String algorithm, long mechanism)
+            throws PKCS11Exception {
+        super();
+        this.token = token;
+        this.algorithm = algorithm;
+        this.mechanism = mechanism;
+
+        if (this.mechanism == CKM_DES3_KEY_GEN) {
+            /* Given the current lookup order specified in SunPKCS11.java,
+               if CKM_DES2_KEY_GEN is used to construct this object, it
+               means that CKM_DES3_KEY_GEN is disabled or unsupported.
+            */
+            supportBothKeySizes =
+                (token.provider.config.isEnabled(CKM_DES2_KEY_GEN) &&
+                 (token.getMechanismInfo(CKM_DES2_KEY_GEN) != null));
+        }
+        setDefaultKeySize();
+    }
+
+    // set default keysize and also initialize keyType
+    private void setDefaultKeySize() {
+        switch ((int)mechanism) {
+        case (int)CKM_DES_KEY_GEN:
+            keySize = 64;
+            keyType = CKK_DES;
+            break;
+        case (int)CKM_DES2_KEY_GEN:
+            keySize = 128;
+            keyType = CKK_DES2;
+            break;
+        case (int)CKM_DES3_KEY_GEN:
+            keySize = 192;
+            keyType = CKK_DES3;
+            break;
+        case (int)CKM_AES_KEY_GEN:
+            keySize = 128;
+            keyType = CKK_AES;
+            break;
+        case (int)CKM_RC4_KEY_GEN:
+            keySize = 128;
+            keyType = CKK_RC4;
+            break;
+        case (int)CKM_BLOWFISH_KEY_GEN:
+            keySize = 128;
+            keyType = CKK_BLOWFISH;
+            break;
+        default:
+            throw new ProviderException("Unknown mechanism " + mechanism);
+        }
+        try {
+            significantKeySize = checkKeySize(mechanism, keySize, token);
+        } catch (InvalidAlgorithmParameterException iape) {
+            throw new ProviderException("Unsupported default key size", iape);
+        }
+    }
+
+    // see JCE spec
+    protected void engineInit(SecureRandom random) {
+        token.ensureValid();
+        setDefaultKeySize();
+    }
+
+    // see JCE spec
+    protected void engineInit(AlgorithmParameterSpec params,
+            SecureRandom random) throws InvalidAlgorithmParameterException {
+        throw new InvalidAlgorithmParameterException
+                ("AlgorithmParameterSpec not supported");
+    }
+
+    // see JCE spec
+    protected void engineInit(int keySize, SecureRandom random) {
+        token.ensureValid();
+        int newSignificantKeySize;
+        try {
+            newSignificantKeySize = checkKeySize(mechanism, keySize, token);
+        } catch (InvalidAlgorithmParameterException iape) {
+            throw (InvalidParameterException)
+                    (new InvalidParameterException().initCause(iape));
+        }
+        if ((mechanism == CKM_DES2_KEY_GEN) ||
+            (mechanism == CKM_DES3_KEY_GEN))  {
+            long newMechanism = (newSignificantKeySize == 112 ?
+                CKM_DES2_KEY_GEN : CKM_DES3_KEY_GEN);
+            if (mechanism != newMechanism) {
+                if (supportBothKeySizes) {
+                    mechanism = newMechanism;
+                    // Adjust keyType to reflect the mechanism change
+                    keyType = (mechanism == CKM_DES2_KEY_GEN ?
+                        CKK_DES2 : CKK_DES3);
+                } else {
+                    throw new InvalidParameterException
+                            ("Only " + significantKeySize +
+                             "-bit DESede is supported");
+                }
+            }
+        }
+        this.keySize = keySize;
+        this.significantKeySize = newSignificantKeySize;
+    }
+
+    // see JCE spec
+    protected SecretKey engineGenerateKey() {
+        Session session = null;
+        try {
+            session = token.getObjSession();
+            CK_ATTRIBUTE[] attributes;
+            switch ((int)keyType) {
+            case (int)CKK_DES:
+            case (int)CKK_DES2:
+            case (int)CKK_DES3:
+                // fixed length, do not specify CKA_VALUE_LEN
+                attributes = new CK_ATTRIBUTE[] {
+                    new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
+                };
+                break;
+            default:
+                attributes = new CK_ATTRIBUTE[] {
+                    new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
+                    new CK_ATTRIBUTE(CKA_VALUE_LEN, keySize >> 3),
+                };
+                break;
+            }
+            attributes = token.getAttributes
+                (O_GENERATE, CKO_SECRET_KEY, keyType, attributes);
+            long keyID = token.p11.C_GenerateKey
+                (session.id(), new CK_MECHANISM(mechanism), attributes);
+            return P11Key.secretKey
+                (session, keyID, algorithm, significantKeySize, attributes);
+        } catch (PKCS11Exception e) {
+            throw new ProviderException("Could not generate key", e);
+        } finally {
+            token.releaseSession(session);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyPairGenerator.java	Thu Jan 26 09:19:33 2017 -0800
@@ -0,0 +1,429 @@
+/*
+ * Copyright (c) 2003, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package sun.security.pkcs11;
+
+import java.math.BigInteger;
+
+import java.security.*;
+import java.security.spec.*;
+
+import javax.crypto.spec.DHParameterSpec;
+
+import sun.security.provider.ParameterCache;
+
+import static sun.security.pkcs11.TemplateManager.*;
+import sun.security.pkcs11.wrapper.*;
+import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
+
+import sun.security.rsa.RSAKeyFactory;
+
+/**
+ * KeyPairGenerator implementation class. This class currently supports
+ * RSA, DSA, DH, and EC.
+ *
+ * Note that for DSA and DH we rely on the Sun and SunJCE providers to
+ * obtain the parameters from.
+ *
+ * @author  Andreas Sterbenz
+ * @since   1.5
+ */
+final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
+
+    // token instance
+    private final Token token;
+
+    // algorithm name
+    private final String algorithm;
+
+    // mechanism id
+    private final long mechanism;
+
+    // selected or default key size, always valid
+    private int keySize;
+
+    // parameters specified via init, if any
+    private AlgorithmParameterSpec params;
+
+    // for RSA, selected or default value of public exponent, always valid
+    private BigInteger rsaPublicExponent = RSAKeyGenParameterSpec.F4;
+
+    // the supported keysize range of the native PKCS11 library
+    // if the value cannot be retrieved or unspecified, -1 is used.
+    private final int minKeySize;
+    private final int maxKeySize;
+
+    // SecureRandom instance, if specified in init
+    private SecureRandom random;
+
+    P11KeyPairGenerator(Token token, String algorithm, long mechanism)
+            throws PKCS11Exception {
+        super();
+        int minKeyLen = -1;
+        int maxKeyLen = -1;
+        try {
+            CK_MECHANISM_INFO mechInfo = token.getMechanismInfo(mechanism);
+            if (mechInfo != null) {
+                minKeyLen = (int) mechInfo.ulMinKeySize;
+                maxKeyLen = (int) mechInfo.ulMaxKeySize;
+            }
+        } catch (PKCS11Exception p11e) {
+            // Should never happen
+            throw new ProviderException
+                        ("Unexpected error while getting mechanism info", p11e);
+        }
+        // set default key sizes and apply our own algorithm-specific limits
+        // override lower limit to disallow unsecure keys being generated
+        // override upper limit to deter DOS attack
+        if (algorithm.equals("EC")) {
+            keySize = 256;
+            if ((minKeyLen == -1) || (minKeyLen < 112)) {
+                minKeyLen = 112;
+            }
+            if ((maxKeyLen == -1) || (maxKeyLen > 2048)) {
+                maxKeyLen = 2048;
+            }
+        } else {
+            if (algorithm.equals("DSA")) {
+                // keep default keysize at 1024 since larger keysizes may be
+                // incompatible with SHA1withDSA and SHA-2 Signature algs
+                // may not be supported by native pkcs11 implementations
+                keySize = 1024;
+            } else {
+                // RSA and DH
+                keySize = 2048;
+            }
+            if ((minKeyLen == -1) || (minKeyLen < 512)) {
+                minKeyLen = 512;
+            }
+            if (algorithm.equals("RSA")) {
+                if ((maxKeyLen == -1) || (maxKeyLen > 64 * 1024)) {
+                    maxKeyLen = 64 * 1024;
+                }
+            }
+        }
+
+        // auto-adjust default keysize in case it's out-of-range
+        if ((minKeyLen != -1) && (keySize < minKeyLen)) {
+            keySize = minKeyLen;
+        }
+        if ((maxKeyLen != -1) && (keySize > maxKeyLen)) {
+            keySize = maxKeyLen;
+        }
+        this.token = token;
+        this.algorithm = algorithm;
+        this.mechanism = mechanism;
+        this.minKeySize = minKeyLen;
+        this.maxKeySize = maxKeyLen;
+        initialize(keySize, null);
+    }
+
+    // see JCA spec
+    @Override
+    public void initialize(int keySize, SecureRandom random) {
+        token.ensureValid();
+        try {
+            checkKeySize(keySize, null);
+        } catch (InvalidAlgorithmParameterException e) {
+            throw new InvalidParameterException(e.getMessage());
+        }
+        this.params = null;
+        if (algorithm.equals("EC")) {
+            params = P11ECKeyFactory.getECParameterSpec(keySize);
+            if (params == null) {
+                throw new InvalidParameterException(
+                    "No EC parameters available for key size "
+                    + keySize + " bits");
+            }
+        }
+        this.keySize = keySize;
+        this.random = random;
+    }
+
+    // see JCA spec
+    @Override
+    public void initialize(AlgorithmParameterSpec params, SecureRandom random)
+            throws InvalidAlgorithmParameterException {
+        token.ensureValid();
+        int tmpKeySize;
+        if (algorithm.equals("DH")) {
+            if (params instanceof DHParameterSpec == false) {
+                throw new InvalidAlgorithmParameterException
+                        ("DHParameterSpec required for Diffie-Hellman");
+            }
+            DHParameterSpec dhParams = (DHParameterSpec) params;
+            tmpKeySize = dhParams.getP().bitLength();
+            checkKeySize(tmpKeySize, dhParams);
+            // XXX sanity check params
+        } else if (algorithm.equals("RSA")) {
+            if (params instanceof RSAKeyGenParameterSpec == false) {
+                throw new InvalidAlgorithmParameterException
+                        ("RSAKeyGenParameterSpec required for RSA");
+            }
+            RSAKeyGenParameterSpec rsaParams =
+                (RSAKeyGenParameterSpec) params;
+            tmpKeySize = rsaParams.getKeysize();
+            checkKeySize(tmpKeySize, rsaParams);
+            // override the supplied params to null
+            params = null;
+            this.rsaPublicExponent = rsaParams.getPublicExponent();
+            // XXX sanity check params
+        } else if (algorithm.equals("DSA")) {
+            if (params instanceof DSAParameterSpec == false) {
+                throw new InvalidAlgorithmParameterException
+                        ("DSAParameterSpec required for DSA");
+            }
+            DSAParameterSpec dsaParams = (DSAParameterSpec) params;
+            tmpKeySize = dsaParams.getP().bitLength();
+            checkKeySize(tmpKeySize, dsaParams);
+            // XXX sanity check params
+        } else if (algorithm.equals("EC")) {
+            ECParameterSpec ecParams;
+            if (params instanceof ECParameterSpec) {
+                ecParams = P11ECKeyFactory.getECParameterSpec(
+                    (ECParameterSpec)params);
+                if (ecParams == null) {
+                    throw new InvalidAlgorithmParameterException
+                        ("Unsupported curve: " + params);
+                }
+            } else if (params instanceof ECGenParameterSpec) {
+                String name = ((ECGenParameterSpec) params).getName();
+                ecParams = P11ECKeyFactory.getECParameterSpec(name);
+                if (ecParams == null) {
+                    throw new InvalidAlgorithmParameterException
+                        ("Unknown curve name: " + name);
+                }
+                // override the supplied params with the derived one
+                params = ecParams;
+            } else {
+                throw new InvalidAlgorithmParameterException
+                    ("ECParameterSpec or ECGenParameterSpec required for EC");
+            }
+            tmpKeySize = ecParams.getCurve().getField().getFieldSize();
+            checkKeySize(tmpKeySize, ecParams);
+        } else {
+            throw new ProviderException("Unknown algorithm: " + algorithm);
+        }
+        this.keySize = tmpKeySize;
+        this.params = params;
+        this.random = random;
+    }
+
+    private void checkKeySize(int keySize, AlgorithmParameterSpec params)
+        throws InvalidAlgorithmParameterException {
+        // check native range first
+        if ((minKeySize != -1) && (keySize < minKeySize)) {
+            throw new InvalidAlgorithmParameterException(algorithm +
+                " key must be at least " + minKeySize + " bits. " +
+                "The specific key size " + keySize + " is not supported");
+        }
+        if ((maxKeySize != -1) && (keySize > maxKeySize)) {
+            throw new InvalidAlgorithmParameterException(algorithm +
+                " key must be at most " + maxKeySize + " bits. " +
+                "The specific key size " + keySize + " is not supported");
+        }
+
+        // check our own algorithm-specific limits also
+        if (algorithm.equals("EC")) {
+            if (keySize < 112) {
+                throw new InvalidAlgorithmParameterException(
+                    "EC key size must be at least 112 bit. " +
+                    "The specific key size " + keySize + " is not supported");
+            }
+            if (keySize > 2048) {
+                // sanity check, nobody really wants keys this large
+                throw new InvalidAlgorithmParameterException(
+                    "EC key size must be at most 2048 bit. " +
+                    "The specific key size " + keySize + " is not supported");
+            }
+        } else {
+            // RSA, DH, DSA
+            if (keySize < 512) {
+                throw new InvalidAlgorithmParameterException(algorithm +
+                    " key size must be at least 512 bit. " +
+                    "The specific key size " + keySize + " is not supported");
+            }
+            if (algorithm.equals("RSA")) {
+                BigInteger tmpExponent = rsaPublicExponent;
+                if (params != null) {
+                    tmpExponent =
+                        ((RSAKeyGenParameterSpec)params).getPublicExponent();
+                }
+                try {
+                    // Reuse the checking in SunRsaSign provider.