+ * PKCS#11 structure: + *
+ * typedef struct CK_PBE_PARAMS {
+- * CK_CHAR_PTR pInitVector;
+- * CK_CHAR_PTR pPassword;
++ * CK_BYTE_PTR pInitVector;
++ * CK_UTF8CHAR_PTR pPassword;
+ * CK_ULONG ulPasswordLen;
+- * CK_CHAR_PTR pSalt;
++ * CK_BYTE_PTR pSalt;
+ * CK_ULONG ulSaltLen;
+ * CK_ULONG ulIteration;
+ * } CK_PBE_PARAMS;
+@@ -72,15 +72,15 @@ public class CK_PBE_PARAMS {
+ /**
+ * PKCS#11:
+ *
+- * CK_CHAR_PTR pInitVector;
++ * CK_BYTE_PTR pInitVector;
+ *
+ */
+- public char[] pInitVector;
++ public byte[] pInitVector;
+
+ /**
+ * PKCS#11:
+ *
+- * CK_CHAR_PTR pPassword;
++ * CK_UTF8CHAR_PTR pPassword;
+ * CK_ULONG ulPasswordLen;
+ *
+ */
+@@ -89,11 +89,11 @@ public class CK_PBE_PARAMS {
+ /**
+ * PKCS#11:
+ *
+- * CK_CHAR_PTR pSalt
++ * CK_BYTE_PTR pSalt
+ * CK_ULONG ulSaltLen;
+ *
+ */
+- public char[] pSalt;
++ public byte[] pSalt;
+
+ /**
+ * PKCS#11:
+@@ -103,6 +103,12 @@ public class CK_PBE_PARAMS {
+ */
+ public long ulIteration;
+
++ public CK_PBE_PARAMS(char[] pPassword, byte[] pSalt, long ulIteration) {
++ this.pPassword = pPassword;
++ this.pSalt = pSalt;
++ this.ulIteration = ulIteration;
++ }
++
+ /**
+ * Returns the string representation of CK_PBE_PARAMS.
+ *
+diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_PKCS5_PBKD2_PARAMS.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_PKCS5_PBKD2_PARAMS.java
+index fb90bfced27..a01beb0753a 100644
+--- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_PKCS5_PBKD2_PARAMS.java
++++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_PKCS5_PBKD2_PARAMS.java
+@@ -47,7 +47,7 @@
+
+ package sun.security.pkcs11.wrapper;
+
+-
++import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
+
+ /**
+ * class CK_PKCS5_PBKD2_PARAMS provides the parameters to the CKM_PKCS5_PBKD2
+@@ -55,13 +55,15 @@ package sun.security.pkcs11.wrapper;
+ * PKCS#11 structure:
+ *
+ * typedef struct CK_PKCS5_PBKD2_PARAMS {
+- * CK_PKCS5_PBKD2_SALT_SOURCE_TYPE saltSource;
++ * CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource;
+ * CK_VOID_PTR pSaltSourceData;
+ * CK_ULONG ulSaltSourceDataLen;
+ * CK_ULONG iterations;
+ * CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf;
+ * CK_VOID_PTR pPrfData;
+ * CK_ULONG ulPrfDataLen;
++ * CK_UTF8CHAR_PTR pPassword;
++ * CK_ULONG_PTR ulPasswordLen;
+ * } CK_PKCS5_PBKD2_PARAMS;
+ *
+ *
+@@ -112,6 +114,24 @@ public class CK_PKCS5_PBKD2_PARAMS {
+ */
+ public byte[] pPrfData;
+
++ /**
++ * PKCS#11:
++ *
++ * CK_UTF8CHAR_PTR pPassword
++ * CK_ULONG_PTR ulPasswordLen;
++ *
++ */
++ public char[] pPassword;
++
++ public CK_PKCS5_PBKD2_PARAMS(char[] pPassword, byte[] pSalt,
++ long iterations, long prf) {
++ this.pPassword = pPassword;
++ this.pSaltSourceData = pSalt;
++ this.iterations = iterations;
++ this.prf = prf;
++ this.saltSource = CKZ_SALT_SPECIFIED;
++ }
++
+ /**
+ * Returns the string representation of CK_PKCS5_PBKD2_PARAMS.
+ *
+diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_PKCS5_PBKD2_PARAMS2.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_PKCS5_PBKD2_PARAMS2.java
+new file mode 100644
+index 00000000000..935db656639
+--- /dev/null
++++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_PKCS5_PBKD2_PARAMS2.java
+@@ -0,0 +1,156 @@
++/*
++ * Copyright (c) 2022, Red Hat, Inc.
++ * 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.wrapper;
++
++import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
++
++/**
++ * class CK_PKCS5_PBKD2_PARAMS2 provides the parameters to the CKM_PKCS5_PBKD2
++ * mechanism.
++ * PKCS#11 structure:
++ *
++ * typedef struct CK_PKCS5_PBKD2_PARAMS2 {
++ * CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource;
++ * CK_VOID_PTR pSaltSourceData;
++ * CK_ULONG ulSaltSourceDataLen;
++ * CK_ULONG iterations;
++ * CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf;
++ * CK_VOID_PTR pPrfData;
++ * CK_ULONG ulPrfDataLen;
++ * CK_UTF8CHAR_PTR pPassword;
++ * CK_ULONG ulPasswordLen;
++ * } CK_PKCS5_PBKD2_PARAMS2;
++ *
++ *
++ */
++public class CK_PKCS5_PBKD2_PARAMS2 {
++
++ /**
++ * PKCS#11:
++ *
++ * CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource;
++ *
++ */
++ public long saltSource;
++
++ /**
++ * PKCS#11:
++ *
++ * CK_VOID_PTR pSaltSourceData;
++ * CK_ULONG ulSaltSourceDataLen;
++ *
++ */
++ public byte[] pSaltSourceData;
++
++ /**
++ * PKCS#11:
++ *
++ * CK_ULONG iterations;
++ *
++ */
++ public long iterations;
++
++ /**
++ * PKCS#11:
++ *
++ * CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf;
++ *
++ */
++ public long prf;
++
++ /**
++ * PKCS#11:
++ *
++ * CK_VOID_PTR pPrfData;
++ * CK_ULONG ulPrfDataLen;
++ *
++ */
++ public byte[] pPrfData;
++
++ /**
++ * PKCS#11:
++ *
++ * CK_UTF8CHAR_PTR pPassword
++ * CK_ULONG ulPasswordLen;
++ *
++ */
++ public char[] pPassword;
++
++ public CK_PKCS5_PBKD2_PARAMS2(char[] pPassword, byte[] pSalt,
++ long iterations, long prf) {
++ this.pPassword = pPassword;
++ this.pSaltSourceData = pSalt;
++ this.iterations = iterations;
++ this.prf = prf;
++ this.saltSource = CKZ_SALT_SPECIFIED;
++ }
++
++ /**
++ * Returns the string representation of CK_PKCS5_PBKD2_PARAMS2.
++ *
++ * @return the string representation of CK_PKCS5_PBKD2_PARAMS2
++ */
++ public String toString() {
++ StringBuilder sb = new StringBuilder();
++
++ sb.append(Constants.INDENT);
++ sb.append("saltSource: ");
++ sb.append(saltSource);
++ sb.append(Constants.NEWLINE);
++
++ sb.append(Constants.INDENT);
++ sb.append("pSaltSourceData: ");
++ sb.append(Functions.toHexString(pSaltSourceData));
++ sb.append(Constants.NEWLINE);
++
++ sb.append(Constants.INDENT);
++ sb.append("ulSaltSourceDataLen: ");
++ sb.append(pSaltSourceData.length);
++ sb.append(Constants.NEWLINE);
++
++ sb.append(Constants.INDENT);
++ sb.append("iterations: ");
++ sb.append(iterations);
++ sb.append(Constants.NEWLINE);
++
++ sb.append(Constants.INDENT);
++ sb.append("prf: ");
++ sb.append(prf);
++ sb.append(Constants.NEWLINE);
++
++ sb.append(Constants.INDENT);
++ sb.append("pPrfData: ");
++ sb.append(Functions.toHexString(pPrfData));
++ sb.append(Constants.NEWLINE);
++
++ sb.append(Constants.INDENT);
++ sb.append("ulPrfDataLen: ");
++ sb.append(pPrfData.length);
++
++ return sb.toString();
++ }
++
++}
+diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_X9_42_DH1_DERIVE_PARAMS.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_X9_42_DH1_DERIVE_PARAMS.java
+index 1f9c4d39f57..5e3c1b9d29f 100644
+--- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_X9_42_DH1_DERIVE_PARAMS.java
++++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_X9_42_DH1_DERIVE_PARAMS.java
+@@ -94,9 +94,9 @@ public class CK_X9_42_DH1_DERIVE_PARAMS {
+ public byte[] pPublicData;
+
+ /**
+- * Returns the string representation of CK_PKCS5_PBKD2_PARAMS.
++ * Returns the string representation of CK_X9_42_DH1_DERIVE_PARAMS.
+ *
+- * @return the string representation of CK_PKCS5_PBKD2_PARAMS
++ * @return the string representation of CK_X9_42_DH1_DERIVE_PARAMS
+ */
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java
-index 5c0aacd1a67..0e4a1235084 100644
+index 5c0aacd1a67..5fbf8addcba 100644
--- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java
+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java
-@@ -49,6 +49,7 @@ package sun.security.pkcs11.wrapper;
+@@ -49,6 +49,9 @@ package sun.security.pkcs11.wrapper;
import java.io.File;
import java.io.IOException;
+import java.lang.invoke.MethodHandle;
++import java.lang.invoke.MethodHandles;
++import java.lang.invoke.MethodType;
import java.util.*;
import java.security.AccessController;
-@@ -150,18 +151,41 @@ public class PKCS11 {
- this.pkcs11ModulePath = pkcs11ModulePath;
- }
+@@ -113,6 +116,8 @@ public class PKCS11 {
+ private long pNativeData;
+
++ private CK_INFO pInfo;
++
+ /**
+ * This method does the initialization of the native library. It is called
+ * exactly once for this class.
+@@ -145,23 +150,49 @@ public class PKCS11 {
+ * @postconditions
+ */
+ PKCS11(String pkcs11ModulePath, String functionListName)
+- throws IOException {
++ throws IOException, PKCS11Exception {
+ connect(pkcs11ModulePath, functionListName);
+ this.pkcs11ModulePath = pkcs11ModulePath;
++ pInfo = C_GetInfo();
++ }
++
+ /*
+ * Compatibility wrapper to allow this method to work as before
+ * when FIPS mode support is not active.
@@ -2897,25 +4622,27 @@ index 5c0aacd1a67..0e4a1235084 100644
+ String functionList, CK_C_INITIALIZE_ARGS pInitArgs,
+ boolean omitInitialize) throws IOException, PKCS11Exception {
+ return getInstance(pkcs11ModulePath, functionList,
-+ pInitArgs, omitInitialize, null);
-+ }
-+
++ pInitArgs, omitInitialize, null, null);
+ }
+
public static synchronized PKCS11 getInstance(String pkcs11ModulePath,
String functionList, CK_C_INITIALIZE_ARGS pInitArgs,
- boolean omitInitialize) throws IOException, PKCS11Exception {
-+ boolean omitInitialize, MethodHandle fipsKeyImporter)
++ boolean omitInitialize, MethodHandle fipsKeyImporter,
++ MethodHandle fipsKeyExporter)
+ throws IOException, PKCS11Exception {
// we may only call C_Initialize once per native .so/.dll
// so keep a cache using the (non-canonicalized!) path
PKCS11 pkcs11 = moduleMap.get(pkcs11ModulePath);
if (pkcs11 == null) {
-+ boolean nssFipsMode = fipsKeyImporter != null;
++ boolean nssFipsMode = fipsKeyImporter != null &&
++ fipsKeyExporter != null;
if ((pInitArgs != null)
&& ((pInitArgs.flags & CKF_OS_LOCKING_OK) != 0)) {
- pkcs11 = new PKCS11(pkcs11ModulePath, functionList);
+ if (nssFipsMode) {
+ pkcs11 = new FIPSPKCS11(pkcs11ModulePath, functionList,
-+ fipsKeyImporter);
++ fipsKeyImporter, fipsKeyExporter);
+ } else {
+ pkcs11 = new PKCS11(pkcs11ModulePath, functionList);
+ }
@@ -2923,14 +4650,38 @@ index 5c0aacd1a67..0e4a1235084 100644
- pkcs11 = new SynchronizedPKCS11(pkcs11ModulePath, functionList);
+ if (nssFipsMode) {
+ pkcs11 = new SynchronizedFIPSPKCS11(pkcs11ModulePath,
-+ functionList, fipsKeyImporter);
++ functionList, fipsKeyImporter, fipsKeyExporter);
+ } else {
+ pkcs11 = new SynchronizedPKCS11(pkcs11ModulePath, functionList);
+ }
}
if (omitInitialize == false) {
try {
-@@ -1911,4 +1935,69 @@ static class SynchronizedPKCS11 extends PKCS11 {
+@@ -179,6 +210,14 @@ public class PKCS11 {
+ return pkcs11;
+ }
+
++ /**
++ * Returns the CK_INFO structure fetched at initialization with
++ * C_GetInfo. This structure represent Cryptoki library information.
++ */
++ public CK_INFO getInfo() {
++ return pInfo;
++ }
++
+ /**
+ * Connects this object to the specified PKCS#11 library. This method is for
+ * internal use only.
+@@ -1625,7 +1664,7 @@ public class PKCS11 {
+ static class SynchronizedPKCS11 extends PKCS11 {
+
+ SynchronizedPKCS11(String pkcs11ModulePath, String functionListName)
+- throws IOException {
++ throws IOException, PKCS11Exception {
+ super(pkcs11ModulePath, functionListName);
+ }
+
+@@ -1911,4 +1950,194 @@ static class SynchronizedPKCS11 extends PKCS11 {
super.C_GenerateRandom(hSession, randomData);
}
}
@@ -2940,13 +4691,29 @@ index 5c0aacd1a67..0e4a1235084 100644
+// is enabled.
+static class FIPSPKCS11 extends PKCS11 {
+ private MethodHandle fipsKeyImporter;
++ private MethodHandle fipsKeyExporter;
++ private MethodHandle hC_GetAttributeValue;
+ FIPSPKCS11(String pkcs11ModulePath, String functionListName,
-+ MethodHandle fipsKeyImporter) throws IOException {
++ MethodHandle fipsKeyImporter, MethodHandle fipsKeyExporter)
++ throws IOException, PKCS11Exception {
+ super(pkcs11ModulePath, functionListName);
+ this.fipsKeyImporter = fipsKeyImporter;
++ this.fipsKeyExporter = fipsKeyExporter;
++ try {
++ hC_GetAttributeValue = MethodHandles.insertArguments(
++ MethodHandles.lookup().findSpecial(PKCS11.class,
++ "C_GetAttributeValue", MethodType.methodType(
++ void.class, long.class, long.class,
++ CK_ATTRIBUTE[].class),
++ FIPSPKCS11.class), 0, this);
++ } catch (Throwable t) {
++ throw new RuntimeException(
++ "sun.security.pkcs11.wrapper.PKCS11" +
++ "::C_GetAttributeValue method not found.", t);
++ }
+ }
+
-+ public synchronized long C_CreateObject(long hSession,
++ public long C_CreateObject(long hSession,
+ CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception {
+ // Creating sensitive key objects from plain key material in a
+ // FIPS-configured NSS Software Token is not allowed. We apply
@@ -2956,20 +4723,46 @@ index 5c0aacd1a67..0e4a1235084 100644
+ return ((Long)fipsKeyImporter.invoke(hSession, pTemplate))
+ .longValue();
+ } catch (Throwable t) {
-+ throw new PKCS11Exception(CKR_GENERAL_ERROR);
++ if (t instanceof PKCS11Exception) {
++ throw (PKCS11Exception)t;
++ }
++ throw new PKCS11Exception(CKR_GENERAL_ERROR,
++ t.getMessage());
+ }
+ }
+ return super.C_CreateObject(hSession, pTemplate);
+ }
++
++ public void C_GetAttributeValue(long hSession, long hObject,
++ CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception {
++ FIPSPKCS11Helper.C_GetAttributeValue(hC_GetAttributeValue,
++ fipsKeyExporter, hSession, hObject, pTemplate);
++ }
+}
+
+// FIPSPKCS11 synchronized counterpart.
+static class SynchronizedFIPSPKCS11 extends SynchronizedPKCS11 {
+ private MethodHandle fipsKeyImporter;
++ private MethodHandle fipsKeyExporter;
++ private MethodHandle hC_GetAttributeValue;
+ SynchronizedFIPSPKCS11(String pkcs11ModulePath, String functionListName,
-+ MethodHandle fipsKeyImporter) throws IOException {
++ MethodHandle fipsKeyImporter, MethodHandle fipsKeyExporter)
++ throws IOException, PKCS11Exception {
+ super(pkcs11ModulePath, functionListName);
+ this.fipsKeyImporter = fipsKeyImporter;
++ this.fipsKeyExporter = fipsKeyExporter;
++ try {
++ hC_GetAttributeValue = MethodHandles.insertArguments(
++ MethodHandles.lookup().findSpecial(SynchronizedPKCS11.class,
++ "C_GetAttributeValue", MethodType.methodType(
++ void.class, long.class, long.class,
++ CK_ATTRIBUTE[].class),
++ SynchronizedFIPSPKCS11.class), 0, this);
++ } catch (Throwable t) {
++ throw new RuntimeException(
++ "sun.security.pkcs11.wrapper.SynchronizedPKCS11" +
++ "::C_GetAttributeValue method not found.", t);
++ }
+ }
+
+ public synchronized long C_CreateObject(long hSession,
@@ -2980,11 +4773,21 @@ index 5c0aacd1a67..0e4a1235084 100644
+ return ((Long)fipsKeyImporter.invoke(hSession, pTemplate))
+ .longValue();
+ } catch (Throwable t) {
-+ throw new PKCS11Exception(CKR_GENERAL_ERROR);
++ if (t instanceof PKCS11Exception) {
++ throw (PKCS11Exception)t;
++ }
++ throw new PKCS11Exception(CKR_GENERAL_ERROR,
++ t.getMessage());
+ }
+ }
+ return super.C_CreateObject(hSession, pTemplate);
+ }
++
++ public synchronized void C_GetAttributeValue(long hSession, long hObject,
++ CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception {
++ FIPSPKCS11Helper.C_GetAttributeValue(hC_GetAttributeValue,
++ fipsKeyExporter, hSession, hObject, pTemplate);
++ }
+}
+
+private static class FIPSPKCS11Helper {
@@ -2998,27 +4801,517 @@ index 5c0aacd1a67..0e4a1235084 100644
+ }
+ return false;
+ }
++ static void C_GetAttributeValue(MethodHandle hC_GetAttributeValue,
++ MethodHandle fipsKeyExporter, long hSession, long hObject,
++ CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception {
++ Map sensitiveAttrs = new HashMap<>();
++ List nonSensitiveAttrs = new LinkedList<>();
++ FIPSPKCS11Helper.getAttributesBySensitivity(pTemplate,
++ sensitiveAttrs, nonSensitiveAttrs);
++ try {
++ if (sensitiveAttrs.size() > 0) {
++ long keyClass = -1L;
++ long keyType = -1L;
++ try {
++ // Secret and private keys have both class and type
++ // attributes, so we can query them at once.
++ CK_ATTRIBUTE[] queryAttrs = new CK_ATTRIBUTE[]{
++ new CK_ATTRIBUTE(CKA_CLASS),
++ new CK_ATTRIBUTE(CKA_KEY_TYPE),
++ };
++ hC_GetAttributeValue.invoke(hSession, hObject, queryAttrs);
++ keyClass = queryAttrs[0].getLong();
++ keyType = queryAttrs[1].getLong();
++ } catch (PKCS11Exception e) {
++ // If the query fails, the object is neither a secret nor a
++ // private key. As this case won't be handled with the FIPS
++ // Key Exporter, we keep keyClass initialized to -1L.
++ }
++ if (keyClass == CKO_SECRET_KEY || keyClass == CKO_PRIVATE_KEY) {
++ fipsKeyExporter.invoke(hSession, hObject, keyClass, keyType,
++ sensitiveAttrs);
++ if (nonSensitiveAttrs.size() > 0) {
++ CK_ATTRIBUTE[] pNonSensitiveAttrs =
++ new CK_ATTRIBUTE[nonSensitiveAttrs.size()];
++ int i = 0;
++ for (CK_ATTRIBUTE nonSensAttr : nonSensitiveAttrs) {
++ pNonSensitiveAttrs[i++] = nonSensAttr;
++ }
++ hC_GetAttributeValue.invoke(hSession, hObject,
++ pNonSensitiveAttrs);
++ // libj2pkcs11 allocates new CK_ATTRIBUTE objects, so we
++ // update the reference on the previous CK_ATTRIBUTEs
++ i = 0;
++ for (CK_ATTRIBUTE nonSensAttr : nonSensitiveAttrs) {
++ nonSensAttr.pValue = pNonSensitiveAttrs[i++].pValue;
++ }
++ }
++ return;
++ }
++ }
++ hC_GetAttributeValue.invoke(hSession, hObject, pTemplate);
++ } catch (Throwable t) {
++ if (t instanceof PKCS11Exception) {
++ throw (PKCS11Exception)t;
++ }
++ throw new PKCS11Exception(CKR_GENERAL_ERROR,
++ t.getMessage());
++ }
++ }
++ private static void getAttributesBySensitivity(CK_ATTRIBUTE[] pTemplate,
++ Map sensitiveAttrs,
++ List nonSensitiveAttrs) {
++ for (CK_ATTRIBUTE attr : pTemplate) {
++ long type = attr.type;
++ // Aligned with NSS' sftk_isSensitive in lib/softoken/pkcs11u.c
++ if (type == CKA_VALUE || type == CKA_PRIVATE_EXPONENT ||
++ type == CKA_PRIME_1 || type == CKA_PRIME_2 ||
++ type == CKA_EXPONENT_1 || type == CKA_EXPONENT_2 ||
++ type == CKA_COEFFICIENT) {
++ sensitiveAttrs.put(type, attr);
++ } else {
++ nonSensitiveAttrs.add(attr);
++ }
++ }
++ }
+}
}
-diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11Exception.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11Exception.java
-index e2d6d371bec..dc5e7eefdd3 100644
---- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11Exception.java
-+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11Exception.java
-@@ -219,6 +219,14 @@ public class PKCS11Exception extends Exception {
- return "0x" + Functions.toFullHexString((int)errorCode);
+diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11Constants.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11Constants.java
+index d22844cfba8..9e02958b4b0 100644
+--- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11Constants.java
++++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11Constants.java
+@@ -1104,17 +1104,6 @@ public interface PKCS11Constants {
+ public static final long CKD_BLAKE2B_384_KDF = 0x00000019L;
+ public static final long CKD_BLAKE2B_512_KDF = 0x0000001aL;
+
+- public static final long CKP_PKCS5_PBKD2_HMAC_SHA1 = 0x00000001L;
+- public static final long CKP_PKCS5_PBKD2_HMAC_GOSTR3411 = 0x00000002L;
+- public static final long CKP_PKCS5_PBKD2_HMAC_SHA224 = 0x00000003L;
+- public static final long CKP_PKCS5_PBKD2_HMAC_SHA256 = 0x00000004L;
+- public static final long CKP_PKCS5_PBKD2_HMAC_SHA384 = 0x00000005L;
+- public static final long CKP_PKCS5_PBKD2_HMAC_SHA512 = 0x00000006L;
+- public static final long CKP_PKCS5_PBKD2_HMAC_SHA512_224 = 0x00000007L;
+- public static final long CKP_PKCS5_PBKD2_HMAC_SHA512_256 = 0x00000008L;
+-
+- public static final long CKZ_SALT_SPECIFIED = 0x00000001L;
+-
+ public static final long CK_OTP_VALUE = 0x00000000L;
+ public static final long CK_OTP_PIN = 0x00000001L;
+ public static final long CK_OTP_CHALLENGE = 0x00000002L;
+@@ -1150,12 +1139,23 @@ public interface PKCS11Constants {
+ public static final long CKF_HKDF_SALT_KEY = 0x00000004L;
+ */
+
++ // PBKDF2 support, used in P11Util
++ public static final long CKZ_SALT_SPECIFIED = 0x00000001L;
++ public static final long CKP_PKCS5_PBKD2_HMAC_SHA1 = 0x00000001L;
++ public static final long CKP_PKCS5_PBKD2_HMAC_GOSTR3411 = 0x00000002L;
++ public static final long CKP_PKCS5_PBKD2_HMAC_SHA224 = 0x00000003L;
++ public static final long CKP_PKCS5_PBKD2_HMAC_SHA256 = 0x00000004L;
++ public static final long CKP_PKCS5_PBKD2_HMAC_SHA384 = 0x00000005L;
++ public static final long CKP_PKCS5_PBKD2_HMAC_SHA512 = 0x00000006L;
++ public static final long CKP_PKCS5_PBKD2_HMAC_SHA512_224 = 0x00000007L;
++ public static final long CKP_PKCS5_PBKD2_HMAC_SHA512_256 = 0x00000008L;
++
+ // private NSS attribute (for DSA and DH private keys)
+ public static final long CKA_NETSCAPE_DB = 0xD5A0DB00L;
+
+ // base number of NSS private attributes
+ public static final long CKA_NETSCAPE_BASE /*0x80000000L + 0x4E534350L*/
+- = 0xCE534350L;
++ /* now known as CKM_NSS ^ */ = 0xCE534350L;
+
+ // object type for NSS trust
+ public static final long CKO_NETSCAPE_TRUST = 0xCE534353L;
+@@ -1180,4 +1180,14 @@ public interface PKCS11Constants {
+ = 0xCE534355L;
+ public static final long CKT_NETSCAPE_VALID = 0xCE53435AL;
+ public static final long CKT_NETSCAPE_VALID_DELEGATOR = 0xCE53435BL;
++
++ // Additional PKCS #12 PBE key derivation algorithms defined in NSS v3.29
++ public static final long CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN
++ /* (CKM_NSS + 29) */ = 0xCE53436DL;
++ public static final long CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN
++ /* (CKM_NSS + 30) */ = 0xCE53436EL;
++ public static final long CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN
++ /* (CKM_NSS + 31) */ = 0xCE53436FL;
++ public static final long CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN
++ /* (CKM_NSS + 32) */ = 0xCE534370L;
+ }
+diff --git a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_convert.c b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_convert.c
+index 666c5eb9b3b..5523dafcdb4 100644
+--- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_convert.c
++++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_convert.c
+@@ -1515,6 +1515,10 @@ CK_VOID_PTR jMechParamToCKMechParamPtrSlow(JNIEnv *env, jobject jParam,
+ case CKM_PBE_SHA1_DES3_EDE_CBC:
+ case CKM_PBE_SHA1_DES2_EDE_CBC:
+ case CKM_PBA_SHA1_WITH_SHA1_HMAC:
++ case CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN:
++ case CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN:
++ case CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN:
++ case CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN:
+ ckpParamPtr = jPbeParamToCKPbeParamPtr(env, jParam, ckpLength);
+ break;
+ case CKM_PKCS5_PBKD2:
+@@ -1658,13 +1662,13 @@ jPbeParamToCKPbeParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength)
+ // retrieve java values
+ jPbeParamsClass = (*env)->FindClass(env, CLASS_PBE_PARAMS);
+ if (jPbeParamsClass == NULL) { return NULL; }
+- fieldID = (*env)->GetFieldID(env, jPbeParamsClass, "pInitVector", "[C");
++ fieldID = (*env)->GetFieldID(env, jPbeParamsClass, "pInitVector", "[B");
+ if (fieldID == NULL) { return NULL; }
+ jInitVector = (*env)->GetObjectField(env, jParam, fieldID);
+ fieldID = (*env)->GetFieldID(env, jPbeParamsClass, "pPassword", "[C");
+ if (fieldID == NULL) { return NULL; }
+ jPassword = (*env)->GetObjectField(env, jParam, fieldID);
+- fieldID = (*env)->GetFieldID(env, jPbeParamsClass, "pSalt", "[C");
++ fieldID = (*env)->GetFieldID(env, jPbeParamsClass, "pSalt", "[B");
+ if (fieldID == NULL) { return NULL; }
+ jSalt = (*env)->GetObjectField(env, jParam, fieldID);
+ fieldID = (*env)->GetFieldID(env, jPbeParamsClass, "ulIteration", "J");
+@@ -1680,15 +1684,15 @@ jPbeParamToCKPbeParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength)
+
+ // populate using java values
+ ckParamPtr->ulIteration = jLongToCKULong(jIteration);
+- jCharArrayToCKCharArray(env, jInitVector, &(ckParamPtr->pInitVector), &ckTemp);
++ jByteArrayToCKByteArray(env, jInitVector, &(ckParamPtr->pInitVector), &ckTemp);
+ if ((*env)->ExceptionCheck(env)) {
+ goto cleanup;
+ }
+- jCharArrayToCKCharArray(env, jPassword, &(ckParamPtr->pPassword), &(ckParamPtr->ulPasswordLen));
++ jCharArrayToCKUTF8CharArray(env, jPassword, &(ckParamPtr->pPassword), &(ckParamPtr->ulPasswordLen));
+ if ((*env)->ExceptionCheck(env)) {
+ goto cleanup;
}
+- jCharArrayToCKCharArray(env, jSalt, &(ckParamPtr->pSalt), &(ckParamPtr->ulSaltLen));
++ jByteArrayToCKByteArray(env, jSalt, &(ckParamPtr->pSalt), &(ckParamPtr->ulSaltLen));
+ if ((*env)->ExceptionCheck(env)) {
+ goto cleanup;
+ }
+@@ -1767,31 +1771,59 @@ void copyBackPBEInitializationVector(JNIEnv *env, CK_MECHANISM *ckMechanism, job
+ }
+ }
-+ /**
-+ * Constructor taking the error code (the CKR_* constants in PKCS#11) with
-+ * no extra info for the error message.
-+ */
-+ public PKCS11Exception(long errorCode) {
-+ this(errorCode, null);
++#define PBKD2_PARAM_SET(member, value) \
++ do { \
++ if(ckParamPtr->version == PARAMS) { \
++ ckParamPtr->params.v1.member = value; \
++ } else { \
++ ckParamPtr->params.v2.member = value; \
++ } \
++ } while(0)
++
++#define PBKD2_PARAM_ADDR(member) \
++ ( \
++ (ckParamPtr->version == PARAMS) ? \
++ (void*) &ckParamPtr->params.v1.member : \
++ (void*) &ckParamPtr->params.v2.member \
++ )
++
+ /*
+- * converts the Java CK_PKCS5_PBKD2_PARAMS object to a CK_PKCS5_PBKD2_PARAMS
++ * converts a Java CK_PKCS5_PBKD2_PARAMS object to a CK_PKCS5_PBKD2_PARAMS
++ * pointer, or a Java CK_PKCS5_PBKD2_PARAMS2 object to a CK_PKCS5_PBKD2_PARAMS2
+ * pointer
+ *
+- * @param env - used to call JNI funktions to get the Java classes and objects
+- * @param jParam - the Java CK_PKCS5_PBKD2_PARAMS object to convert
++ * @param env - used to call JNI functions to get the Java classes and objects
++ * @param jParam - the Java object to convert
+ * @param pLength - length of the allocated memory of the returned pointer
+- * @return pointer to the new CK_PKCS5_PBKD2_PARAMS structure
++ * @return pointer to the new structure
+ */
+-CK_PKCS5_PBKD2_PARAMS_PTR
++CK_VOID_PTR
+ jPkcs5Pbkd2ParamToCKPkcs5Pbkd2ParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength)
+ {
+- CK_PKCS5_PBKD2_PARAMS_PTR ckParamPtr;
++ VersionedPbkd2ParamsPtr ckParamPtr;
++ ParamVersion paramVersion;
++ CK_ULONG_PTR pUlPasswordLen;
+ jclass jPkcs5Pbkd2ParamsClass;
+ jfieldID fieldID;
+ jlong jSaltSource, jIteration, jPrf;
+- jobject jSaltSourceData, jPrfData;
++ jobject jSaltSourceData, jPrfData, jPassword;
+
+ if (pLength != NULL) {
+ *pLength = 0L;
+ }
+
+ // retrieve java values
+- jPkcs5Pbkd2ParamsClass = (*env)->FindClass(env, CLASS_PKCS5_PBKD2_PARAMS);
+- if (jPkcs5Pbkd2ParamsClass == NULL) { return NULL; }
++ if ((jPkcs5Pbkd2ParamsClass =
++ (*env)->FindClass(env, CLASS_PKCS5_PBKD2_PARAMS)) != NULL
++ && (*env)->IsInstanceOf(env, jParam, jPkcs5Pbkd2ParamsClass)) {
++ paramVersion = PARAMS;
++ } else if ((jPkcs5Pbkd2ParamsClass =
++ (*env)->FindClass(env, CLASS_PKCS5_PBKD2_PARAMS2)) != NULL
++ && (*env)->IsInstanceOf(env, jParam, jPkcs5Pbkd2ParamsClass)) {
++ paramVersion = PARAMS2;
++ } else {
++ return NULL;
++ }
+ fieldID = (*env)->GetFieldID(env, jPkcs5Pbkd2ParamsClass, "saltSource", "J");
+ if (fieldID == NULL) { return NULL; }
+ jSaltSource = (*env)->GetLongField(env, jParam, fieldID);
+@@ -1807,36 +1839,60 @@ jPkcs5Pbkd2ParamToCKPkcs5Pbkd2ParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pL
+ fieldID = (*env)->GetFieldID(env, jPkcs5Pbkd2ParamsClass, "pPrfData", "[B");
+ if (fieldID == NULL) { return NULL; }
+ jPrfData = (*env)->GetObjectField(env, jParam, fieldID);
++ fieldID = (*env)->GetFieldID(env, jPkcs5Pbkd2ParamsClass, "pPassword", "[C");
++ if (fieldID == NULL) { return NULL; }
++ jPassword = (*env)->GetObjectField(env, jParam, fieldID);
+
+- // allocate memory for CK_PKCS5_PBKD2_PARAMS pointer
+- ckParamPtr = calloc(1, sizeof(CK_PKCS5_PBKD2_PARAMS));
++ // allocate memory for VersionedPbkd2Params and store the structure version
++ ckParamPtr = calloc(1, sizeof(VersionedPbkd2Params));
+ if (ckParamPtr == NULL) {
+ throwOutOfMemoryError(env, 0);
+ return NULL;
+ }
++ ckParamPtr->version = paramVersion;
+
+ // populate using java values
+- ckParamPtr->saltSource = jLongToCKULong(jSaltSource);
+- jByteArrayToCKByteArray(env, jSaltSourceData, (CK_BYTE_PTR *)
+- &(ckParamPtr->pSaltSourceData), &(ckParamPtr->ulSaltSourceDataLen));
++ PBKD2_PARAM_SET(saltSource, jLongToCKULong(jSaltSource));
++ jByteArrayToCKByteArray(env, jSaltSourceData,
++ (CK_BYTE_PTR *) PBKD2_PARAM_ADDR(pSaltSourceData),
++ PBKD2_PARAM_ADDR(ulSaltSourceDataLen));
+ if ((*env)->ExceptionCheck(env)) {
+ goto cleanup;
+ }
+- ckParamPtr->iterations = jLongToCKULong(jIteration);
+- ckParamPtr->prf = jLongToCKULong(jPrf);
+- jByteArrayToCKByteArray(env, jPrfData, (CK_BYTE_PTR *)
+- &(ckParamPtr->pPrfData), &(ckParamPtr->ulPrfDataLen));
++ PBKD2_PARAM_SET(iterations, jLongToCKULong(jIteration));
++ PBKD2_PARAM_SET(prf, jLongToCKULong(jPrf));
++ jByteArrayToCKByteArray(env, jPrfData,
++ (CK_BYTE_PTR *) PBKD2_PARAM_ADDR(pPrfData),
++ PBKD2_PARAM_ADDR(ulPrfDataLen));
++ if ((*env)->ExceptionCheck(env)) {
++ goto cleanup;
+ }
++ if (ckParamPtr->version == PARAMS) {
++ pUlPasswordLen = calloc(1, sizeof(CK_ULONG));
++ if (pUlPasswordLen == NULL) {
++ throwOutOfMemoryError(env, 0);
++ goto cleanup;
++ }
++ ckParamPtr->params.v1.ulPasswordLen = pUlPasswordLen;
++ } else {
++ pUlPasswordLen = &ckParamPtr->params.v2.ulPasswordLen;
++ }
++ jCharArrayToCKUTF8CharArray(env, jPassword,
++ (CK_CHAR_PTR *) PBKD2_PARAM_ADDR(pPassword),
++ pUlPasswordLen);
+ if ((*env)->ExceptionCheck(env)) {
+ goto cleanup;
+ }
+
+ if (pLength != NULL) {
+- *pLength = sizeof(CK_PKCS5_PBKD2_PARAMS);
++ *pLength = (ckParamPtr->version == PARAMS ?
++ sizeof(ckParamPtr->params.v1) :
++ sizeof(ckParamPtr->params.v2));
+ }
++ // VersionedPbkd2ParamsPtr is equivalent to CK_PKCS5_PBKD2_PARAMS[2]_PTR
+ return ckParamPtr;
+ cleanup:
+- free(ckParamPtr->pSaltSourceData);
+- free(ckParamPtr->pPrfData);
++ FREE_VERSIONED_PBKD2_MEMBERS(ckParamPtr);
+ free(ckParamPtr);
+ return NULL;
+
+diff --git a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_util.c b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_util.c
+index 520bd52a2cd..aa76945283d 100644
+--- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_util.c
++++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_util.c
+@@ -410,11 +410,27 @@ void freeCKMechanismPtr(CK_MECHANISM_PTR mechPtr) {
+ case CKM_CAMELLIA_CTR:
+ // params do not contain pointers
+ break;
++ case CKM_PKCS5_PBKD2:
++ // get the versioned structure from behind memory
++ TRACE0(((VersionedPbkd2ParamsPtr)tmp)->version == PARAMS ?
++ "[ CK_PKCS5_PBKD2_PARAMS ]\n" :
++ "[ CK_PKCS5_PBKD2_PARAMS2 ]\n");
++ FREE_VERSIONED_PBKD2_MEMBERS((VersionedPbkd2ParamsPtr)tmp);
++ break;
++ case CKM_PBA_SHA1_WITH_SHA1_HMAC:
++ case CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN:
++ case CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN:
++ case CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN:
++ case CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN:
++ free(((CK_PBE_PARAMS_PTR)tmp)->pInitVector);
++ free(((CK_PBE_PARAMS_PTR)tmp)->pPassword);
++ free(((CK_PBE_PARAMS_PTR)tmp)->pSalt);
++ break;
+ default:
+ // currently unsupported mechs by SunPKCS11 provider
+ // CKM_RSA_PKCS_OAEP, CKM_ECMQV_DERIVE,
+ // CKM_X9_42_*, CKM_KEA_DERIVE, CKM_RC2_*, CKM_RC5_*,
+- // CKM_SKIPJACK_*, CKM_KEY_WRAP_SET_OAEP, CKM_PKCS5_PBKD2,
++ // CKM_SKIPJACK_*, CKM_KEY_WRAP_SET_OAEP,
+ // PBE mechs, WTLS mechs, CMS mechs,
+ // CKM_EXTRACT_KEY_FROM_KEY, CKM_OTP, CKM_KIP,
+ // CKM_DSA_PARAMETER_GEN?, CKM_GOSTR3410_*
+@@ -517,12 +533,11 @@ void jBooleanArrayToCKBBoolArray(JNIEnv *env, const jbooleanArray jArray, CK_BBO
+ jboolean* jpTemp;
+ CK_ULONG i;
+
+- if(jArray == NULL) {
++ *ckpLength = jArray == NULL ? 0L : (*env)->GetArrayLength(env, jArray);
++ if(*ckpLength == 0L) {
+ *ckpArray = NULL_PTR;
+- *ckpLength = 0L;
+ return;
+ }
+- *ckpLength = (*env)->GetArrayLength(env, jArray);
+ jpTemp = (jboolean*) calloc(*ckpLength, sizeof(jboolean));
+ if (jpTemp == NULL) {
+ throwOutOfMemoryError(env, 0);
+@@ -559,12 +574,11 @@ void jByteArrayToCKByteArray(JNIEnv *env, const jbyteArray jArray, CK_BYTE_PTR *
+ jbyte* jpTemp;
+ CK_ULONG i;
+
+- if(jArray == NULL) {
++ *ckpLength = jArray == NULL ? 0L : (*env)->GetArrayLength(env, jArray);
++ if(*ckpLength == 0L) {
+ *ckpArray = NULL_PTR;
+- *ckpLength = 0L;
+ return;
+ }
+- *ckpLength = (*env)->GetArrayLength(env, jArray);
+ jpTemp = (jbyte*) calloc(*ckpLength, sizeof(jbyte));
+ if (jpTemp == NULL) {
+ throwOutOfMemoryError(env, 0);
+@@ -606,12 +620,11 @@ void jLongArrayToCKULongArray(JNIEnv *env, const jlongArray jArray, CK_ULONG_PTR
+ jlong* jTemp;
+ CK_ULONG i;
+
+- if(jArray == NULL) {
++ *ckpLength = jArray == NULL ? 0L : (*env)->GetArrayLength(env, jArray);
++ if(*ckpLength == 0L) {
+ *ckpArray = NULL_PTR;
+- *ckpLength = 0L;
+ return;
+ }
+- *ckpLength = (*env)->GetArrayLength(env, jArray);
+ jTemp = (jlong*) calloc(*ckpLength, sizeof(jlong));
+ if (jTemp == NULL) {
+ throwOutOfMemoryError(env, 0);
+@@ -648,12 +661,11 @@ void jCharArrayToCKCharArray(JNIEnv *env, const jcharArray jArray, CK_CHAR_PTR *
+ jchar* jpTemp;
+ CK_ULONG i;
+
+- if(jArray == NULL) {
++ *ckpLength = jArray == NULL ? 0L : (*env)->GetArrayLength(env, jArray);
++ if(*ckpLength == 0L) {
+ *ckpArray = NULL_PTR;
+- *ckpLength = 0L;
+ return;
+ }
+- *ckpLength = (*env)->GetArrayLength(env, jArray);
+ jpTemp = (jchar*) calloc(*ckpLength, sizeof(jchar));
+ if (jpTemp == NULL) {
+ throwOutOfMemoryError(env, 0);
+@@ -690,12 +702,11 @@ void jCharArrayToCKUTF8CharArray(JNIEnv *env, const jcharArray jArray, CK_UTF8CH
+ jchar* jTemp;
+ CK_ULONG i;
+
+- if(jArray == NULL) {
++ *ckpLength = jArray == NULL ? 0L : (*env)->GetArrayLength(env, jArray);
++ if(*ckpLength == 0L) {
+ *ckpArray = NULL_PTR;
+- *ckpLength = 0L;
+ return;
+ }
+- *ckpLength = (*env)->GetArrayLength(env, jArray);
+ jTemp = (jchar*) calloc(*ckpLength, sizeof(jchar));
+ if (jTemp == NULL) {
+ throwOutOfMemoryError(env, 0);
+diff --git a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11wrapper.h b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11wrapper.h
+index eb6d01b9e47..450e4d27d62 100644
+--- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11wrapper.h
++++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11wrapper.h
+@@ -68,6 +68,7 @@
+ /* extra PKCS#11 constants not in the standard include files */
+
+ #define CKA_NETSCAPE_BASE (0x80000000 + 0x4E534350)
++/* ^ now known as CKM_NSS (CKM_VENDOR_DEFINED | NSSCK_VENDOR_NSS) */
+ #define CKA_NETSCAPE_TRUST_BASE (CKA_NETSCAPE_BASE + 0x2000)
+ #define CKA_NETSCAPE_TRUST_SERVER_AUTH (CKA_NETSCAPE_TRUST_BASE + 8)
+ #define CKA_NETSCAPE_TRUST_CLIENT_AUTH (CKA_NETSCAPE_TRUST_BASE + 9)
+@@ -76,6 +77,12 @@
+ #define CKA_NETSCAPE_DB 0xD5A0DB00
+ #define CKM_NSS_TLS_PRF_GENERAL 0x80000373
+
++/* additional PKCS #12 PBE key derivation algorithms defined in NSS v3.29 */
++#define CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN (CKA_NETSCAPE_BASE + 29)
++#define CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN (CKA_NETSCAPE_BASE + 30)
++#define CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN (CKA_NETSCAPE_BASE + 31)
++#define CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN (CKA_NETSCAPE_BASE + 32)
+
- /**
- * Constructor taking the error code (the CKR_* constants in PKCS#11) and
- * extra info for error message.
+ /*
+
+ Define the PKCS#11 functions to include and exclude. Reduces the size
+@@ -265,6 +272,7 @@ void printDebug(const char *format, ...);
+ #define CLASS_PBE_PARAMS "sun/security/pkcs11/wrapper/CK_PBE_PARAMS"
+ #define PBE_INIT_VECTOR_SIZE 8
+ #define CLASS_PKCS5_PBKD2_PARAMS "sun/security/pkcs11/wrapper/CK_PKCS5_PBKD2_PARAMS"
++#define CLASS_PKCS5_PBKD2_PARAMS2 "sun/security/pkcs11/wrapper/CK_PKCS5_PBKD2_PARAMS2"
+ #define CLASS_EXTRACT_PARAMS "sun/security/pkcs11/wrapper/CK_EXTRACT_PARAMS"
+
+ #define CLASS_ECDH1_DERIVE_PARAMS "sun/security/pkcs11/wrapper/CK_ECDH1_DERIVE_PARAMS"
+@@ -378,7 +386,7 @@ CK_VOID_PTR jMechParamToCKMechParamPtr(JNIEnv *env, jobject jParam, CK_MECHANISM
+ CK_RSA_PKCS_OAEP_PARAMS_PTR jRsaPkcsOaepParamToCKRsaPkcsOaepParamPtr(JNIEnv *env,
+ jobject jParam, CK_ULONG* pLength);
+ CK_PBE_PARAMS_PTR jPbeParamToCKPbeParamPtr(JNIEnv *env, jobject jParam, CK_ULONG* pLength);
+-CK_PKCS5_PBKD2_PARAMS_PTR jPkcs5Pbkd2ParamToCKPkcs5Pbkd2ParamPtr(JNIEnv *env, jobject jParam, CK_ULONG* pLength);
++CK_VOID_PTR jPkcs5Pbkd2ParamToCKPkcs5Pbkd2ParamPtr(JNIEnv *env, jobject jParam, CK_ULONG* pLength);
+ CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR jSsl3MasterKeyDeriveParamToCKSsl3MasterKeyDeriveParamPtr(JNIEnv *env, jobject jParam, CK_ULONG* pLength);
+ CK_SSL3_KEY_MAT_PARAMS_PTR jSsl3KeyMatParamToCKSsl3KeyMatParamPtr(JNIEnv *env, jobject jParam, CK_ULONG* pLength);
+ CK_KEY_DERIVATION_STRING_DATA jKeyDerivationStringDataToCKKeyDerivationStringData(JNIEnv *env, jobject jParam);
+@@ -388,6 +396,31 @@ CK_ECDH2_DERIVE_PARAMS_PTR jEcdh2DeriveParamToCKEcdh2DeriveParamPtr(JNIEnv *env,
+ CK_X9_42_DH1_DERIVE_PARAMS_PTR jX942Dh1DeriveParamToCKX942Dh1DeriveParamPtr(JNIEnv *env, jobject jParam, CK_ULONG* pLength);
+ CK_X9_42_DH2_DERIVE_PARAMS_PTR jX942Dh2DeriveParamToCKX942Dh2DeriveParamPtr(JNIEnv *env, jobject jParam, CK_ULONG* pLength);
+
++/* handling of CK_PKCS5_PBKD2_PARAMS and CK_PKCS5_PBKD2_PARAMS2 */
++typedef enum {PARAMS=0, PARAMS2} ParamVersion;
++
++typedef struct {
++ union {
++ CK_PKCS5_PBKD2_PARAMS v1;
++ CK_PKCS5_PBKD2_PARAMS2 v2;
++ } params;
++ ParamVersion version;
++} VersionedPbkd2Params, *VersionedPbkd2ParamsPtr;
++
++#define FREE_VERSIONED_PBKD2_MEMBERS(verParamsPtr) \
++ do { \
++ if ((verParamsPtr)->version == PARAMS) { \
++ free((verParamsPtr)->params.v1.pSaltSourceData); \
++ free((verParamsPtr)->params.v1.pPrfData); \
++ free((verParamsPtr)->params.v1.pPassword); \
++ free((verParamsPtr)->params.v1.ulPasswordLen); \
++ } else { \
++ free((verParamsPtr)->params.v2.pSaltSourceData); \
++ free((verParamsPtr)->params.v2.pPrfData); \
++ free((verParamsPtr)->params.v2.pPassword); \
++ } \
++ } while(0)
++
+ /* functions to copy the returned values inside CK-mechanism back to Java object */
+
+ void copyBackPBEInitializationVector(JNIEnv *env, CK_MECHANISM *ckMechanism, jobject jMechanism);
diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/SunEC.java b/src/jdk.crypto.ec/share/classes/sun/security/ec/SunEC.java
index 8c9e4f9dbe6..883dc04758e 100644
--- a/src/jdk.crypto.ec/share/classes/sun/security/ec/SunEC.java
diff --git a/java-17-openjdk.spec b/java-17-openjdk.spec
index 04b212301c6bc4bfc1d534d78b459ca7dc18b052..fe22d04fc6ec4627425b1b84b0cfa899c32f08b5 100644
--- a/java-17-openjdk.spec
+++ b/java-17-openjdk.spec
@@ -306,7 +306,7 @@
%global featurever 17
%global interimver 0
%global updatever 4
-%global patchver 0
+%global patchver 1
# buildjdkver is usually same as %%{featurever},
# but in time of bootstrap of next jdk, it is featurever-1,
# and this it is better to change it here, on single place
@@ -345,14 +345,14 @@
# Define IcedTea version used for SystemTap tapsets and desktop file
%global icedteaver 6.0.0pre00-c848b93a8598
# Define current Git revision for the FIPS support patches
-%global fipsver 765f970aef1
+%global fipsver 0bd5ca9ccc5
# Standard JPackage naming and versioning defines
%global origin openjdk
%global origin_nice OpenJDK
%global top_level_dir_name %{origin}
%global top_level_dir_name_backup %{top_level_dir_name}-backup
-%global buildver 8
+%global buildver 1
%global rpmrelease 2
# Priority must be 8 digits in total; up to openjdk 1.8, we were using 18..... so when we moved to 11, we had to add another digit
%if %is_system_jdk
@@ -1295,6 +1295,9 @@ Source16: CheckVendor.java
# nss fips configuration file
Source17: nss.fips.cfg.in
+# Ensure translations are available for new timezones
+Source18: TestTranslations.java
+
############################################
#
# RPM/distribution specific patches
@@ -1314,6 +1317,8 @@ Patch2: rh1648644-java_access_bridge_privileged_security.patch
Patch3: rh649512-remove_uses_of_far_in_jpeg_libjpeg_turbo_1_4_compat_for_jdk10_and_up.patch
# Depend on pcsc-lite-libs instead of pcsc-lite-devel as this is only in optional repo
Patch6: rh1684077-openjdk_should_depend_on_pcsc-lite-libs_instead_of_pcsc-lite-devel.patch
+# Add translations for Europe/Kyiv locally until upstream is fully updated for tzdata2022b
+Patch7: jdk8292223-tzdata2022b-kyiv.patch
# Crypto policy and FIPS support patches
# Patch is generated from the fips-17u tree at https://github.com/rh-openjdk/jdk/tree/fips-17u-cpu-2022-07
@@ -1334,9 +1339,15 @@ Patch6: rh1684077-openjdk_should_depend_on_pcsc-lite-libs_instead_of_pcsc-lite-d
# RH2052819: Fix FIPS reliance on crypto policies
# RH2052829: Detect NSS at Runtime for FIPS detection
# RH2052070: Enable AlgorithmParameters and AlgorithmParameterGenerator services in FIPS mode
+# RH2023467: Enable FIPS keys export
# RH2094027: SunEC runtime permission for FIPS
# RH2036462: sun.security.pkcs11.wrapper.PKCS11.getInstance breakage
# RH2090378: Revert to disabling system security properties and FIPS mode support together
+# RH2104724: Avoid import/export of DH private keys
+# RH2092507: P11Key.getEncoded does not work for DH keys in FIPS mode
+# Build the systemconf library on all platforms
+# RH2048582: Support PKCS#12 keystores
+# RH2020290: Support TLS 1.3 in FIPS mode
Patch1001: fips-17u-%{fipsver}.patch
#############################################
@@ -1759,6 +1770,7 @@ pushd %{top_level_dir_name}
%patch2 -p1
%patch3 -p1
%patch6 -p1
+%patch7 -p1
# Add crypto policy and FIPS support
%patch1001 -p1
# nss.cfg PKCS11 support; must come last as it also alters java.security
@@ -2101,6 +2113,14 @@ nm $JAVA_HOME/bin/%{alt_java_name} | grep set_speculation
if ! nm $JAVA_HOME/bin/%{alt_java_name} | grep set_speculation ; then true ; else false; fi
%endif
+# Check translations are available for new timezones
+$JAVA_HOME/bin/javac --add-exports java.base/sun.util.resources=ALL-UNNAMED \
+ --add-exports java.base/sun.util.locale.provider=ALL-UNNAMED \
+ -d . %{SOURCE18}
+$JAVA_HOME/bin/java --add-exports java.base/sun.util.resources=ALL-UNNAMED \
+ --add-exports java.base/sun.util.locale.provider=ALL-UNNAMED \
+ $(echo $(basename %{SOURCE18})|sed "s|\.java||") "Europe/Kiev" "Europe/Kyiv"
+
%if %{include_staticlibs}
# Check debug symbols in static libraries (smoke test)
export STATIC_LIBS_HOME=${top_dir_abs_staticlibs_build_path}/images/%{static_libs_image}
@@ -2556,6 +2576,27 @@ require "copy_jdk_configs.lua"
%endif
%changelog
+* Fri Sep 02 2022 Andrew Hughes - 1:17.0.4.1.1-2
+- Update FIPS support to bring in latest changes
+- * RH2023467: Enable FIPS keys export
+- * RH2104724: Avoid import/export of DH private keys
+- * RH2092507: P11Key.getEncoded does not work for DH keys in FIPS mode
+- * Build the systemconf library on all platforms
+- * RH2048582: Support PKCS#12 keystores
+- * RH2020290: Support TLS 1.3 in FIPS mode
+- Resolves: rhbz#2123561
+- Resolves: rhbz#2123564
+- Resolves: rhbz#2123566
+- Resolves: rhbz#2123568
+- Resolves: rhbz#2123572
+
+* Sun Aug 21 2022 Andrew Hughes - 1:17.0.4.1.1-1
+- Update to jdk-17.0.4.1+1
+- Update release notes to 17.0.4.1+1
+- Add patch to provide translations for Europe/Kyiv added in tzdata2022b
+- Add test to ensure timezones can be translated
+- Resolves: rhbz#2120059
+
* Wed Jul 20 2022 Andrew Hughes - 1:17.0.4.0.8-0.2.ea
- Add rpminspect.yaml to turn off Java bytecode inspections
- java-17-openjdk deliberately produces Java 17 bytecode, not the default Java 11 bytecode
diff --git a/jdk8292223-tzdata2022b-kyiv.patch b/jdk8292223-tzdata2022b-kyiv.patch
new file mode 100644
index 0000000000000000000000000000000000000000..1107b825e35d5783f0418354ad5b74cc77ae0869
--- /dev/null
+++ b/jdk8292223-tzdata2022b-kyiv.patch
@@ -0,0 +1,132 @@
+diff --git a/src/java.base/share/classes/sun/util/resources/TimeZoneNames.java b/src/java.base/share/classes/sun/util/resources/TimeZoneNames.java
+index 8759aab3995..11ccbf73839 100644
+--- a/src/java.base/share/classes/sun/util/resources/TimeZoneNames.java
++++ b/src/java.base/share/classes/sun/util/resources/TimeZoneNames.java
+@@ -847,6 +847,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle {
+ {"Europe/Kirov", new String[] {"Kirov Standard Time", "GMT+03:00",
+ "Kirov Daylight Time", "GMT+03:00",
+ "Kirov Time", "GMT+03:00"}},
++ {"Europe/Kyiv", EET},
+ {"Europe/Lisbon", WET},
+ {"Europe/Ljubljana", CET},
+ {"Europe/London", GMTBST},
+diff --git a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_de.java b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_de.java
+index f007c1a8d3b..617268e4cf3 100644
+--- a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_de.java
++++ b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_de.java
+@@ -825,6 +825,7 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle {
+ {"Europe/Jersey", GMTBST},
+ {"Europe/Kaliningrad", EET},
+ {"Europe/Kiev", EET},
++ {"Europe/Kyiv", EET},
+ {"Europe/Lisbon", WET},
+ {"Europe/Ljubljana", CET},
+ {"Europe/London", GMTBST},
+diff --git a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_es.java b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_es.java
+index 386414e16e6..14c5d89b9c5 100644
+--- a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_es.java
++++ b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_es.java
+@@ -825,6 +825,7 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle {
+ {"Europe/Jersey", GMTBST},
+ {"Europe/Kaliningrad", EET},
+ {"Europe/Kiev", EET},
++ {"Europe/Kyiv", EET},
+ {"Europe/Lisbon", WET},
+ {"Europe/Ljubljana", CET},
+ {"Europe/London", GMTBST},
+diff --git a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_fr.java b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_fr.java
+index d23f5fd49e6..44117125619 100644
+--- a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_fr.java
++++ b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_fr.java
+@@ -825,6 +825,7 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle {
+ {"Europe/Jersey", GMTBST},
+ {"Europe/Kaliningrad", EET},
+ {"Europe/Kiev", EET},
++ {"Europe/Kyiv", EET},
+ {"Europe/Lisbon", WET},
+ {"Europe/Ljubljana", CET},
+ {"Europe/London", GMTBST},
+diff --git a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_it.java b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_it.java
+index b4f57d4568c..efa818f3865 100644
+--- a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_it.java
++++ b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_it.java
+@@ -825,6 +825,7 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle {
+ {"Europe/Jersey", GMTBST},
+ {"Europe/Kaliningrad", EET},
+ {"Europe/Kiev", EET},
++ {"Europe/Kyiv", EET},
+ {"Europe/Lisbon", WET},
+ {"Europe/Ljubljana", CET},
+ {"Europe/London", GMTBST},
+diff --git a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_ja.java b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_ja.java
+index 1a10a9f96dc..7c0565461ad 100644
+--- a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_ja.java
++++ b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_ja.java
+@@ -825,6 +825,7 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle {
+ {"Europe/Jersey", GMTBST},
+ {"Europe/Kaliningrad", EET},
+ {"Europe/Kiev", EET},
++ {"Europe/Kyiv", EET},
+ {"Europe/Lisbon", WET},
+ {"Europe/Ljubljana", CET},
+ {"Europe/London", GMTBST},
+diff --git a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_ko.java b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_ko.java
+index 9a2d9e5c57c..8a2c805997f 100644
+--- a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_ko.java
++++ b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_ko.java
+@@ -825,6 +825,7 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle {
+ {"Europe/Jersey", GMTBST},
+ {"Europe/Kaliningrad", EET},
+ {"Europe/Kiev", EET},
++ {"Europe/Kyiv", EET},
+ {"Europe/Lisbon", WET},
+ {"Europe/Ljubljana", CET},
+ {"Europe/London", GMTBST},
+diff --git a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_pt_BR.java b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_pt_BR.java
+index de5e5c82daa..e3c06417f09 100644
+--- a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_pt_BR.java
++++ b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_pt_BR.java
+@@ -825,6 +825,7 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle {
+ {"Europe/Jersey", GMTBST},
+ {"Europe/Kaliningrad", EET},
+ {"Europe/Kiev", EET},
++ {"Europe/Kyiv", EET},
+ {"Europe/Lisbon", WET},
+ {"Europe/Ljubljana", CET},
+ {"Europe/London", GMTBST},
+diff --git a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_sv.java b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_sv.java
+index b53de4d8c89..3e46b6a063e 100644
+--- a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_sv.java
++++ b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_sv.java
+@@ -825,6 +825,7 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle {
+ {"Europe/Jersey", GMTBST},
+ {"Europe/Kaliningrad", EET},
+ {"Europe/Kiev", EET},
++ {"Europe/Kyiv", EET},
+ {"Europe/Lisbon", WET},
+ {"Europe/Ljubljana", CET},
+ {"Europe/London", GMTBST},
+diff --git a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_zh_CN.java b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_zh_CN.java
+index 7797cda19d5..590908409a8 100644
+--- a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_zh_CN.java
++++ b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_zh_CN.java
+@@ -825,6 +825,7 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle {
+ {"Europe/Jersey", GMTBST},
+ {"Europe/Kaliningrad", EET},
+ {"Europe/Kiev", EET},
++ {"Europe/Kyiv", EET},
+ {"Europe/Lisbon", WET},
+ {"Europe/Ljubljana", CET},
+ {"Europe/London", GMTBST},
+diff --git a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_zh_TW.java b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_zh_TW.java
+index 2cd10554853..23c5f180b6d 100644
+--- a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_zh_TW.java
++++ b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_zh_TW.java
+@@ -827,6 +827,7 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle {
+ {"Europe/Jersey", GMTBST},
+ {"Europe/Kaliningrad", EET},
+ {"Europe/Kiev", EET},
++ {"Europe/Kyiv", EET},
+ {"Europe/Lisbon", WET},
+ {"Europe/Ljubljana", CET},
+ {"Europe/London", GMTBST},