diff --git a/.gitignore b/.gitignore
index 52b077b..fe33249 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1 @@
-SOURCES/jss-4.6.0.tar.gz
+SOURCES/jss-4.6.2.tar.gz
diff --git a/.jss.metadata b/.jss.metadata
index cb4e805..d14bd57 100644
--- a/.jss.metadata
+++ b/.jss.metadata
@@ -1 +1 @@
-3d6d2d885129e0d7d8ebac5dfe9055c693a7a9b1 SOURCES/jss-4.6.0.tar.gz
+4fea1d770e0882aa9c1c6c493bce9eb579b5c085 SOURCES/jss-4.6.2.tar.gz
diff --git a/SOURCES/0001-Disable-buffer-based-tests.patch b/SOURCES/0001-Disable-buffer-based-tests.patch
deleted file mode 100644
index f39763a..0000000
--- a/SOURCES/0001-Disable-buffer-based-tests.patch
+++ /dev/null
@@ -1,71 +0,0 @@
-From d7d6d769b510118e40d9c0919317665c4c9feb8d Mon Sep 17 00:00:00 2001
-From: Alexander Scheel <alexander.m.scheel@gmail.com>
-Date: Wed, 12 Jun 2019 17:17:45 -0400
-Subject: [PATCH] Disable buffer-based tests
-
-Signed-off-by: Alexander Scheel <alexander.m.scheel@gmail.com>
----
- cmake/JSSTests.cmake | 33 ---------------------------------
- 1 file changed, 33 deletions(-)
-
-diff --git a/cmake/JSSTests.cmake b/cmake/JSSTests.cmake
-index b389be5c..473d7d4d 100644
---- a/cmake/JSSTests.cmake
-+++ b/cmake/JSSTests.cmake
-@@ -78,24 +78,6 @@ macro(jss_tests)
-         NAME "BigObjectIdentifier"
-         COMMAND "org.mozilla.jss.tests.BigObjectIdentifier"
-     )
--    jss_test_java(
--        NAME "JSS_Test_PR_FileDesc"
--        COMMAND "org.mozilla.jss.tests.TestPRFD"
--    )
--    jss_test_java(
--        NAME "JSS_Test_Raw_SSL"
--        COMMAND "org.mozilla.jss.tests.TestRawSSL" "${RESULTS_NSSDB_OUTPUT_DIR}"
--        DEPENDS "Setup_DBs"
--    )
--    jss_test_java(
--        NAME "JSS_Test_Buffer"
--        COMMAND "org.mozilla.jss.tests.TestBuffer"
--    )
--    jss_test_java(
--        NAME "JSS_Test_BufferPRFD"
--        COMMAND "org.mozilla.jss.tests.TestBufferPRFD" "${RESULTS_NSSDB_OUTPUT_DIR}" "${DB_PWD}"
--        DEPENDS "List_CA_certs"
--    )
-     if ((${Java_VERSION_MAJOR} EQUAL 1) AND (${Java_VERSION_MINOR} LESS 9))
-         jss_test_java(
-             NAME "Test_PKCS11Constants.java_for_Sun_compatibility"
-@@ -126,16 +108,6 @@ macro(jss_tests)
-         NAME "JUnit_UTF8StringTest"
-         COMMAND "org.junit.runner.JUnitCore" "org.mozilla.jss.tests.UTF8StringTest"
-     )
--    jss_test_exec(
--        NAME "buffer_size_1"
--        COMMAND "${BIN_OUTPUT_DIR}/buffer_size_1"
--        DEPENDS "generate_c_buffer_size_1"
--    )
--    jss_test_exec(
--        NAME "buffer_size_4"
--        COMMAND "${BIN_OUTPUT_DIR}/buffer_size_4"
--        DEPENDS "generate_c_buffer_size_4"
--    )
-     jss_test_java(
-         NAME "JUnit_ChainSortingTest"
-         COMMAND "org.junit.runner.JUnitCore" "org.mozilla.jss.tests.ChainSortingTest"
-@@ -180,11 +152,6 @@ macro(jss_tests)
-         COMMAND "org.mozilla.jss.tests.SSLClientAuth" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}" "${JSS_TEST_PORT_CLIENTAUTH}" "50"
-         DEPENDS "List_CA_certs"
-     )
--    jss_test_exec(
--        NAME "TestBufferPRFD"
--        COMMAND "${BIN_OUTPUT_DIR}/TestBufferPRFD" "${RESULTS_NSSDB_OUTPUT_DIR}" "${DB_PWD}"
--        DEPENDS "List_CA_certs" "generate_c_TestBufferPRFD"
--    )
-     jss_test_java(
-         NAME "Key_Generation"
-         COMMAND "org.mozilla.jss.tests.TestKeyGen" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}"
--- 
-2.21.0
-
diff --git a/SOURCES/0001-Fix-NativeProxy-reference-tracker.patch b/SOURCES/0001-Fix-NativeProxy-reference-tracker.patch
new file mode 100644
index 0000000..529b576
--- /dev/null
+++ b/SOURCES/0001-Fix-NativeProxy-reference-tracker.patch
@@ -0,0 +1,53 @@
+From 91514ca0a2979ba778d27220ced0cd312e2cd2d2 Mon Sep 17 00:00:00 2001
+From: Alexander Scheel <ascheel@redhat.com>
+Date: Tue, 29 Oct 2019 10:43:56 -0400
+Subject: [PATCH] Fix NativeProxy reference tracker
+
+In eb5df01003d74b57473eacb84e538d31f5bb06ca, I introduced a bug by
+setting mPointer after trying to add NativeProxy to the registry. In
+most instances this won't matter, however, if another instance exists in
+the HashSet with the same hash value, the equals comparator will be
+used, triggering a NPE.
+
+Signed-off-by: Alexander Scheel <ascheel@redhat.com>
+---
+ org/mozilla/jss/util/NativeProxy.java | 13 +++++--------
+ 1 file changed, 5 insertions(+), 8 deletions(-)
+
+diff --git a/org/mozilla/jss/util/NativeProxy.java b/org/mozilla/jss/util/NativeProxy.java
+index 1c6d1aa5..a0811f76 100644
+--- a/org/mozilla/jss/util/NativeProxy.java
++++ b/org/mozilla/jss/util/NativeProxy.java
+@@ -40,8 +40,8 @@ public abstract class NativeProxy implements AutoCloseable
+      */
+     public NativeProxy(byte[] pointer) {
+ 		assert(pointer!=null);
+-        registry.add(this);
+         mPointer = pointer;
++        registry.add(this);
+ 
+         if (saveStacktraces) {
+             mTrace = Arrays.toString(Thread.currentThread().getStackTrace());
+@@ -61,15 +61,12 @@ public abstract class NativeProxy implements AutoCloseable
+         if( ! (obj instanceof NativeProxy) ) {
+             return false;
+         }
+-        if( ((NativeProxy)obj).mPointer.length != mPointer.length) {
++        if (((NativeProxy)obj).mPointer == null) {
++            /* If mPointer is null, we have no way to compare the values
++             * of the pointers, so assume they're unequal. */
+             return false;
+         }
+-        for(int i=0; i < mPointer.length; i++) {
+-            if(mPointer[i] != ((NativeProxy)obj).mPointer[i]) {
+-                return false;
+-            }
+-        }
+-        return true;
++        return Arrays.equals(((NativeProxy)obj).mPointer, mPointer);
+     }
+ 
+     /**
+-- 
+2.21.0
+
diff --git a/SOURCES/0002-Fix-swapped-parameter-names-with-PBE.patch b/SOURCES/0002-Fix-swapped-parameter-names-with-PBE.patch
new file mode 100644
index 0000000..04830df
--- /dev/null
+++ b/SOURCES/0002-Fix-swapped-parameter-names-with-PBE.patch
@@ -0,0 +1,80 @@
+From 9f29430656342829822568f4ef49f5237b41164b Mon Sep 17 00:00:00 2001
+From: Alexander Scheel <ascheel@redhat.com>
+Date: Fri, 28 Feb 2020 14:10:32 -0500
+Subject: [PATCH 1/2] Fix swapped parameter names with PBE
+
+Commit 13998a9e77e60d6509ac814ed711dd21e1248ecd introduced a regression
+related to extracting the parameter classes during PBE operations:
+previously, the classes of the underlying encryption algorithm were
+iterated over, instead of the classes of the PBE class itself. However,
+this commit iterated over the PBE parameter classes; no PBE algorithm
+accepts a IvParameterSpec, resulting in a null parameter passed to the
+later encryption or key wrap operation. This resulted in stack traces
+like the following:
+
+Caused by: java.security.InvalidAlgorithmParameterException: DES3/CBC/Pad cannot use a null parameter
+	at org.mozilla.jss.pkcs11.PK11KeyWrapper.checkParams(PK11KeyWrapper.java:225)
+	at org.mozilla.jss.pkcs11.PK11KeyWrapper.initWrap(PK11KeyWrapper.java:89)
+	at org.mozilla.jss.pkcs11.PK11KeyWrapper.initWrap(PK11KeyWrapper.java:57)
+	at org.mozilla.jss.pkix.primitive.EncryptedPrivateKeyInfo.createPBE(EncryptedPrivateKeyInfo.java:342)
+
+Resolves: rh-bz#1807371
+
+Signed-off-by: Alexander Scheel <ascheel@redhat.com>
+---
+ org/mozilla/jss/pkcs7/EncryptedContentInfo.java             | 2 +-
+ org/mozilla/jss/pkix/cms/EncryptedContentInfo.java          | 2 +-
+ org/mozilla/jss/pkix/primitive/EncryptedPrivateKeyInfo.java | 4 ++--
+ 3 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/org/mozilla/jss/pkcs7/EncryptedContentInfo.java b/org/mozilla/jss/pkcs7/EncryptedContentInfo.java
+index 084752c3..0344b14d 100644
+--- a/org/mozilla/jss/pkcs7/EncryptedContentInfo.java
++++ b/org/mozilla/jss/pkcs7/EncryptedContentInfo.java
+@@ -182,7 +182,7 @@ public class EncryptedContentInfo implements ASN1Value {
+         // generate IV
+         EncryptionAlgorithm encAlg = pbeAlg.getEncryptionAlg();
+         AlgorithmParameterSpec params=null;
+-        Class<?> [] paramClasses = pbeAlg.getParameterClasses();
++        Class<?> [] paramClasses = encAlg.getParameterClasses();
+         for (int i = 0; i < paramClasses.length; i ++) {
+             if ( paramClasses[i].equals(
+                       javax.crypto.spec.IvParameterSpec.class ) ) {
+diff --git a/org/mozilla/jss/pkix/cms/EncryptedContentInfo.java b/org/mozilla/jss/pkix/cms/EncryptedContentInfo.java
+index a4709070..d85eb0d3 100644
+--- a/org/mozilla/jss/pkix/cms/EncryptedContentInfo.java
++++ b/org/mozilla/jss/pkix/cms/EncryptedContentInfo.java
+@@ -180,7 +180,7 @@ public class EncryptedContentInfo implements ASN1Value {
+         // generate IV
+         EncryptionAlgorithm encAlg = pbeAlg.getEncryptionAlg();
+         AlgorithmParameterSpec params=null;
+-        Class<?> [] paramClasses = pbeAlg.getParameterClasses();
++        Class<?> [] paramClasses = encAlg.getParameterClasses();
+         for (int i = 0; i < paramClasses.length; i ++) {
+             if ( paramClasses[i].equals( IVParameterSpec.class ) ) {
+                 params = new IVParameterSpec( kg.generatePBE_IV() );
+diff --git a/org/mozilla/jss/pkix/primitive/EncryptedPrivateKeyInfo.java b/org/mozilla/jss/pkix/primitive/EncryptedPrivateKeyInfo.java
+index b35714e3..ebd269f3 100644
+--- a/org/mozilla/jss/pkix/primitive/EncryptedPrivateKeyInfo.java
++++ b/org/mozilla/jss/pkix/primitive/EncryptedPrivateKeyInfo.java
+@@ -147,7 +147,7 @@ public class EncryptedPrivateKeyInfo implements ASN1Value {
+         // generate IV
+         EncryptionAlgorithm encAlg = pbeAlg.getEncryptionAlg();
+         AlgorithmParameterSpec params=null;
+-        Class<?> [] paramClasses = pbeAlg.getParameterClasses();
++        Class<?> [] paramClasses = encAlg.getParameterClasses();
+         for (int i = 0; i < paramClasses.length; i ++) {
+             if ( paramClasses[i].equals( javax.crypto.spec.IvParameterSpec.class ) ) {
+                 params = new IVParameterSpec( kg.generatePBE_IV() );
+@@ -328,7 +328,7 @@ public class EncryptedPrivateKeyInfo implements ASN1Value {
+         // generate IV
+         EncryptionAlgorithm encAlg = pbeAlg.getEncryptionAlg();
+         AlgorithmParameterSpec params=null;
+-        Class<?> [] paramClasses = pbeAlg.getParameterClasses();
++        Class<?> [] paramClasses = encAlg.getParameterClasses();
+         for (int i = 0; i < paramClasses.length; i ++) {
+             if ( paramClasses[i].equals(
+                       javax.crypto.spec.IvParameterSpec.class ) ) {
+-- 
+2.24.1
+
diff --git a/SOURCES/0002-Support-LD_FLAGS-from-environment.patch b/SOURCES/0002-Support-LD_FLAGS-from-environment.patch
deleted file mode 100644
index eaa0e60..0000000
--- a/SOURCES/0002-Support-LD_FLAGS-from-environment.patch
+++ /dev/null
@@ -1,39 +0,0 @@
-From 731b62d4c456a3e1a70519c24eb0df2c59d943b4 Mon Sep 17 00:00:00 2001
-From: Alexander Scheel <ascheel@redhat.com>
-Date: Mon, 17 Jun 2019 08:48:01 -0400
-Subject: [PATCH] Support LD_FLAGS from environment
-
-Signed-off-by: Alexander Scheel <ascheel@redhat.com>
----
- cmake/JSSConfig.cmake | 8 ++++++++
- 1 file changed, 8 insertions(+)
-
-diff --git a/cmake/JSSConfig.cmake b/cmake/JSSConfig.cmake
-index f045850a..e63dd5fa 100644
---- a/cmake/JSSConfig.cmake
-+++ b/cmake/JSSConfig.cmake
-@@ -174,6 +174,11 @@ macro(jss_config_ldflags)
-     list(APPEND JSS_LD_FLAGS "-lpthread")
-     list(APPEND JSS_LD_FLAGS "-ldl")
- 
-+    separate_arguments(PASSED_LD_FLAGS UNIX_COMMAND "${CMAKE_SHARED_LINKER_FLAGS}")
-+    foreach(PASSED_LD_FLAG ${PASSED_LD_FLAGS})
-+        list(INSERT JSS_LD_FLAGS 0 "${PASSED_LD_FLAG}")
-+    endforeach()
-+
-     # This set of flags is specific to building the libjss library.
-     list(APPEND JSS_LIBRARY_FLAGS "-shared")
-     list(APPEND JSS_LIBRARY_FLAGS "-Wl,-z,defs")
-@@ -181,6 +186,9 @@ macro(jss_config_ldflags)
-     list(APPEND JSS_LIBRARY_FLAGS "-Wl,${JSS_SO}")
- 
-     set(JSS_VERSION_SCRIPT "-Wl,--version-script,${PROJECT_SOURCE_DIR}/lib/jss.map")
-+
-+    message(STATUS "JSS LD FLAGS: ${JSS_LD_FLAGS}")
-+    message(STATUS "JSS LIBRARY FLAGS: ${JSS_LIBRARY_FLAGS}")
- endmacro()
- 
- macro(jss_config_java)
--- 
-2.20.1
-
diff --git a/SOURCES/0003-Remove-legacy-DSA-implementation.patch b/SOURCES/0003-Remove-legacy-DSA-implementation.patch
deleted file mode 100644
index 9915a51..0000000
--- a/SOURCES/0003-Remove-legacy-DSA-implementation.patch
+++ /dev/null
@@ -1,2197 +0,0 @@
-From 34e52cf538fab7786be6298de05d7a1ad0b652b7 Mon Sep 17 00:00:00 2001
-From: Alexander Scheel <ascheel@redhat.com>
-Date: Wed, 14 Aug 2019 14:38:39 -0400
-Subject: [PATCH] Remove legacy DSA implementation
-
-This is better suited for NSS via the Mozilla-JSS provider. This entire
-provider could eventually be removed if we wished, but certain
-functionality required by PKI transitively depends on it. It is never
-explicitly added though, so I'm not convinced those places truly use it
-via the intended APIs. However, various classes inside the provider are
-used directly (such as RSAPublicKey and DSAPublicKey).
-
-Signed-off-by: Alexander Scheel <ascheel@redhat.com>
----
- .../jss/netscape/security/provider/DSA.java   | 664 ------------------
- .../provider/DSAKeyPairGenerator.java         | 389 ----------
- .../provider/DSAParameterGenerator.java       | 298 --------
- .../jss/netscape/security/provider/MD5.java   | 378 ----------
- .../jss/netscape/security/provider/SHA.java   | 349 ---------
- .../jss/netscape/security/provider/Sun.java   |  43 --
- 6 files changed, 2121 deletions(-)
- delete mode 100644 org/mozilla/jss/netscape/security/provider/DSA.java
- delete mode 100644 org/mozilla/jss/netscape/security/provider/DSAKeyPairGenerator.java
- delete mode 100644 org/mozilla/jss/netscape/security/provider/DSAParameterGenerator.java
- delete mode 100644 org/mozilla/jss/netscape/security/provider/MD5.java
- delete mode 100644 org/mozilla/jss/netscape/security/provider/SHA.java
-
-diff --git a/org/mozilla/jss/netscape/security/provider/DSA.java b/org/mozilla/jss/netscape/security/provider/DSA.java
-deleted file mode 100644
-index abc320f4..00000000
---- a/org/mozilla/jss/netscape/security/provider/DSA.java
-+++ /dev/null
-@@ -1,664 +0,0 @@
--// --- BEGIN COPYRIGHT BLOCK ---
--// This program is free software; you can redistribute it and/or modify
--// it under the terms of the GNU General Public License as published by
--// the Free Software Foundation; version 2 of the License.
--//
--// This program 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 for more details.
--//
--// You should have received a copy of the GNU General Public License along
--// with this program; if not, write to the Free Software Foundation, Inc.,
--// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
--//
--// (C) 2007 Red Hat, Inc.
--// All rights reserved.
--// --- END COPYRIGHT BLOCK ---
--package org.mozilla.jss.netscape.security.provider;
--
--import java.io.IOException;
--import java.io.PrintStream;
--import java.math.BigInteger;
--import java.security.InvalidKeyException;
--import java.security.InvalidParameterException;
--import java.security.MessageDigest;
--import java.security.NoSuchAlgorithmException;
--import java.security.PrivateKey;
--import java.security.PublicKey;
--import java.security.SecureRandom;
--import java.security.Signature;
--import java.security.SignatureException;
--import java.security.interfaces.DSAParams;
--
--import org.mozilla.jss.netscape.security.util.BigInt;
--import org.mozilla.jss.netscape.security.util.DerInputStream;
--import org.mozilla.jss.netscape.security.util.DerOutputStream;
--import org.mozilla.jss.netscape.security.util.DerValue;
--
--/**
-- * The Digital Signature Standard (using the Digital Signature
-- * Algorithm), as described in fips186 of the National Instute of
-- * Standards and Technology (NIST), using fips180-1 (SHA-1).
-- *
-- * @author Benjamin Renaud
-- *
-- * @version 1.86, 97/09/17
-- *
-- * @see DSAPublicKey
-- * @see DSAPrivateKey
-- */
--
--public final class DSA extends Signature {
--
--    /* Are we debugging? */
--    private static boolean debug = false;
--
--    /* The parameter object */
--    @SuppressWarnings("unused")
--    private DSAParams params;
--
--    /* algorithm parameters */
--    private BigInteger presetP, presetQ, presetG;
--
--    /* The public key, if any */
--    private BigInteger presetY;
--
--    /* The private key, if any */
--    private BigInteger presetX;
--
--    /* The SHA hash for the data */
--    private MessageDigest dataSHA;
--
--    /* The random seed used to generate k */
--    private int[] Kseed;
--
--    /* The random seed used to generate k (specified by application) */
--    private byte[] KseedAsByteArray;
--
--    /*
--     * The random seed used to generate k
--     * (prevent the same Kseed from being used twice in a row
--     */
--    private int[] previousKseed;
--
--    /* The RNG used to output a seed for generating k */
--    private SecureRandom signingRandom;
--
--    /**
--     * Construct a blank DSA object. It can generate keys, but must be
--     * initialized before being usable for signing or verifying.
--     */
--    public DSA() throws NoSuchAlgorithmException {
--        super("SHA/DSA");
--        dataSHA = MessageDigest.getInstance("SHA");
--    }
--
--    /**
--     * Initialize the DSA object with a DSA private key.
--     *
--     * @param privateKey the DSA private key
--     *
--     * @exception InvalidKeyException if the key is not a valid DSA private
--     *                key.
--     */
--    protected void engineInitSign(PrivateKey privateKey)
--            throws InvalidKeyException {
--        if (!(privateKey instanceof java.security.interfaces.DSAPrivateKey)) {
--            throw new InvalidKeyException("not a DSA private key: " +
--                      privateKey);
--        }
--        java.security.interfaces.DSAPrivateKey priv =
--                (java.security.interfaces.DSAPrivateKey) privateKey;
--
--        this.presetX = priv.getX();
--        initialize(priv.getParams());
--    }
--
--    /**
--     * Initialize the DSA object with a DSA public key.
--     *
--     * @param publicKey the DSA public key.
--     *
--     * @exception InvalidKeyException if the key is not a valid DSA public
--     *                key.
--     */
--    protected void engineInitVerify(PublicKey publicKey)
--            throws InvalidKeyException {
--        if (!(publicKey instanceof java.security.interfaces.DSAPublicKey)) {
--            throw new InvalidKeyException("not a DSA public key: " +
--                      publicKey);
--        }
--        java.security.interfaces.DSAPublicKey pub =
--                (java.security.interfaces.DSAPublicKey) publicKey;
--        this.presetY = pub.getY();
--        initialize(pub.getParams());
--    }
--
--    private void initialize(DSAParams params) {
--        dataSHA.reset();
--        setParams(params);
--    }
--
--    /**
--     * Sign all the data thus far updated. The signature is formatted
--     * according to the Canonical Encoding Rules, returned as a DER
--     * sequence of Integer, r and s.
--     *
--     * @return a signature block formatted according to the Canonical
--     *         Encoding Rules.
--     *
--     * @exception SignatureException if the signature object was not
--     *                properly initialized, or if another exception occurs.
--     *
--     * @see org.mozilla.jss.netscape.security.provider.DSA#engineUpdate
--     * @see org.mozilla.jss.netscape.security.provider.DSA#engineVerify
--     */
--    protected byte[] engineSign() throws SignatureException {
--        BigInteger k = generateK(presetQ);
--        BigInteger r = generateR(presetP, presetQ, presetG, k);
--        BigInteger s = generateS(presetX, presetQ, r, k);
--
--        // got to convert to BigInt...
--        BigInt rAsBigInt = new BigInt(r.toByteArray());
--        BigInt sAsBigInt = new BigInt(s.toByteArray());
--
--        try (DerOutputStream outseq = new DerOutputStream(100)) {
--            outseq.putInteger(rAsBigInt);
--            outseq.putInteger(sAsBigInt);
--            DerValue result = new DerValue(DerValue.tag_Sequence,
--                       outseq.toByteArray());
--
--            return result.toByteArray();
--
--        } catch (IOException e) {
--            throw new SignatureException("error encoding signature");
--        }
--    }
--
--    /**
--     * Verify all the data thus far updated.
--     *
--     * @param signature the alledged signature, encoded using the
--     *            Canonical Encoding Rules, as a sequence of integers, r and s.
--     *
--     * @exception SignatureException if the signature object was not
--     *                properly initialized, or if another exception occurs.
--     *
--     * @see org.mozilla.jss.netscape.security.provider.DSA#engineUpdate
--     * @see org.mozilla.jss.netscape.security.provider.DSA#engineSign
--     */
--    protected boolean engineVerify(byte[] signature)
--            throws SignatureException {
--
--        BigInteger r = null;
--        BigInteger s = null;
--        // first decode the signature.
--        try {
--            DerInputStream in = new DerInputStream(signature);
--            DerValue[] values = in.getSequence(2);
--
--            r = values[0].getInteger().toBigInteger();
--            s = values[1].getInteger().toBigInteger();
--
--        } catch (IOException e) {
--            throw new SignatureException("invalid encoding for signature");
--        }
--        BigInteger w = generateW(presetP, presetQ, presetG, s);
--        BigInteger v = generateV(presetY, presetP, presetQ, presetG, w, r);
--
--        return v.equals(r);
--    }
--
--    BigInteger generateR(BigInteger p, BigInteger q, BigInteger g,
--             BigInteger k) {
--        BigInteger temp = g.modPow(k, p);
--        return temp.remainder(q);
--
--    }
--
--    BigInteger generateS(BigInteger x, BigInteger q,
--                 BigInteger r, BigInteger k) {
--
--        byte[] s2 = dataSHA.digest();
--        BigInteger temp = new BigInteger(1, s2);
--        BigInteger k1 = k.modInverse(q);
--
--        BigInteger s = x.multiply(r);
--        s = temp.add(s);
--        s = k1.multiply(s);
--        return s.remainder(q);
--    }
--
--    BigInteger generateW(BigInteger p, BigInteger q,
--             BigInteger g, BigInteger s) {
--        return s.modInverse(q);
--    }
--
--    BigInteger generateV(BigInteger y, BigInteger p,
--             BigInteger q, BigInteger g,
--             BigInteger w, BigInteger r) {
--
--        byte[] s2 = dataSHA.digest();
--        BigInteger temp = new BigInteger(1, s2);
--
--        temp = temp.multiply(w);
--        BigInteger u1 = temp.remainder(q);
--
--        BigInteger u2 = (r.multiply(w)).remainder(q);
--
--        BigInteger t1 = g.modPow(u1, p);
--        BigInteger t2 = y.modPow(u2, p);
--        BigInteger t3 = t1.multiply(t2);
--        BigInteger t5 = t3.remainder(p);
--        return t5.remainder(q);
--    }
--
--    /*
--     * Please read bug report 4044247 for an alternative, faster,
--     * NON-FIPS approved method to generate K
--     */
--    BigInteger generateK(BigInteger q) {
--
--        BigInteger k = null;
--
--        // The application specified a Kseed for us to use.
--        // Note that we do not allow usage of the same Kseed twice in a row
--        if (Kseed != null && compareSeeds(Kseed, previousKseed) != 0) {
--            k = generateK(Kseed, q);
--            if (k.signum() > 0 && k.compareTo(q) < 0) {
--                previousKseed = new int[Kseed.length];
--                System.arraycopy(Kseed, 0, previousKseed, 0, Kseed.length);
--                return k;
--            }
--        }
--
--        // The application did not specify a Kseed for us to use.
--        // We'll generate a new Kseed by getting random bytes from
--        // a SecureRandom object.
--        SecureRandom random = getSigningRandom();
--
--        while (true) {
--            int[] seed = new int[5];
--
--            for (int i = 0; i < 5; i++)
--                seed[i] = random.nextInt();
--            k = generateK(seed, q);
--            if (k.signum() > 0 && k.compareTo(q) < 0) {
--                previousKseed = new int[seed.length];
--                System.arraycopy(seed, 0, previousKseed, 0, seed.length);
--                return k;
--            }
--        }
--    }
--
--    // Use the application-specified SecureRandom Object if provided.
--    // Otherwise, use our default SecureRandom Object.
--    private SecureRandom getSigningRandom() {
--        if (signingRandom == null) {
--            if (appRandom != null)
--                signingRandom = appRandom;
--            else
--                signingRandom = new SecureRandom();
--        }
--        return signingRandom;
--    }
--
--    /*
--     * return 0 if equal
--     * return 1 if not equal
--     */
--    private int compareSeeds(int[] seed1, int[] seed2) {
--
--        if (seed1 == null || seed2 == null) {
--            return 1;
--        }
--        if (seed1.length != seed2.length) {
--            return 1;
--        }
--
--        for (int i = 0; i < seed1.length; i++) {
--            if (seed1[i] != seed2[i])
--                return 1;
--        }
--
--        return 0;
--
--    }
--
--    /**
--     * Compute k for a DSA signature.
--     *
--     * @param seed the seed for generating k. This seed should be
--     *            secure. This is what is refered to as the KSEED in the DSA
--     *            specification.
--     *
--     * @param g the g parameter from the DSA key pair.
--     */
--    BigInteger generateK(int[] seed, BigInteger q) {
--
--        // check out t in the spec.
--        int[] t = { 0xEFCDAB89, 0x98BADCFE, 0x10325476,
--                0xC3D2E1F0, 0x67452301 };
--        //
--        int[] tmp = DSA.SHA_7(seed, t);
--        byte[] tmpBytes = new byte[tmp.length * 4];
--        for (int i = 0; i < tmp.length; i++) {
--            int k = tmp[i];
--            for (int j = 0; j < 4; j++) {
--                tmpBytes[(i * 4) + j] = (byte) (k >>> (24 - (j * 8)));
--            }
--        }
--        BigInteger k = new BigInteger(1, tmpBytes).mod(q);
--        return k;
--    }
--
--    // Constants for each round
--    private static final int round1_kt = 0x5a827999;
--    private static final int round2_kt = 0x6ed9eba1;
--    private static final int round3_kt = 0x8f1bbcdc;
--    private static final int round4_kt = 0xca62c1d6;
--
--    /**
--     * Computes set 1 thru 7 of SHA-1 on m1.
--     */
--    static int[] SHA_7(int[] m1, int[] h) {
--
--        int[] W = new int[80];
--        System.arraycopy(m1, 0, W, 0, m1.length);
--        int temp = 0;
--
--        for (int t = 16; t <= 79; t++) {
--            temp = W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16];
--            W[t] = ((temp << 1) | (temp >>> (32 - 1)));
--        }
--
--        int a = h[0], b = h[1], c = h[2], d = h[3], e = h[4];
--        for (int i = 0; i < 20; i++) {
--            temp = ((a << 5) | (a >>> (32 - 5))) +
--                    ((b & c) | ((~b) & d)) + e + W[i] + round1_kt;
--            e = d;
--            d = c;
--            c = ((b << 30) | (b >>> (32 - 30)));
--            b = a;
--            a = temp;
--        }
--
--        // Round 2
--        for (int i = 20; i < 40; i++) {
--            temp = ((a << 5) | (a >>> (32 - 5))) +
--                    (b ^ c ^ d) + e + W[i] + round2_kt;
--            e = d;
--            d = c;
--            c = ((b << 30) | (b >>> (32 - 30)));
--            b = a;
--            a = temp;
--        }
--
--        // Round 3
--        for (int i = 40; i < 60; i++) {
--            temp = ((a << 5) | (a >>> (32 - 5))) +
--                    ((b & c) | (b & d) | (c & d)) + e + W[i] + round3_kt;
--            e = d;
--            d = c;
--            c = ((b << 30) | (b >>> (32 - 30)));
--            b = a;
--            a = temp;
--        }
--
--        // Round 4
--        for (int i = 60; i < 80; i++) {
--            temp = ((a << 5) | (a >>> (32 - 5))) +
--                    (b ^ c ^ d) + e + W[i] + round4_kt;
--            e = d;
--            d = c;
--            c = ((b << 30) | (b >>> (32 - 30)));
--            b = a;
--            a = temp;
--        }
--        int[] md = new int[5];
--        md[0] = h[0] + a;
--        md[1] = h[1] + b;
--        md[2] = h[2] + c;
--        md[3] = h[3] + d;
--        md[4] = h[4] + e;
--        return md;
--    }
--
--    /**
--     * This implementation recognizes the following parameter:
--     * <dl>
--     *
--     * <dt><code>Kseed</code>
--     *
--     * <dd>a byte array.
--     *
--     * </dl>
--     *
--     * @deprecated Replaced by engineSetParameter(AlgorithmParameterSpec params)
--     */
--    @Deprecated
--    protected void engineSetParameter(String key, Object param) {
--
--        if (key.equals("KSEED")) {
--
--            if (param instanceof byte[]) {
--
--                Kseed = byteArray2IntArray((byte[]) param);
--                KseedAsByteArray = (byte[]) param;
--
--            } else {
--                debug("unrecognized param: " + key);
--                throw new InvalidParameterException("Kseed not a byte array");
--            }
--
--        } else {
--            throw new InvalidParameterException("invalid parameter");
--        }
--    }
--
--    /**
--     * Return the value of the requested parameter. Recognized
--     * parameters are:
--     *
--     * <dl>
--     *
--     * <dt><code>Kseed</code>
--     *
--     * <dd>a byte array.
--     *
--     * </dl>
--     *
--     * @return the value of the requested parameter.
--     *
--     * @deprecated no replacent given
--     * @see https://docs.oracle.com/javase/10/docs/api/java/security/SignatureSpi.html#engineGetParameter(java.lang.String)
--     */
--    @Deprecated
--    protected Object engineGetParameter(String key) {
--        if (key.equals("KSEED")) {
--            return KseedAsByteArray;
--        } else {
--            return null;
--        }
--    }
--
--    /**
--     * Set the algorithm object.
--     */
--    private void setParams(DSAParams params) {
--        this.params = params;
--        this.presetP = params.getP();
--        this.presetQ = params.getQ();
--        this.presetG = params.getG();
--    }
--
--    /**
--     * Update a byte to be signed or verified.
--     *
--     * @param b the byte to updated.
--     */
--    protected void engineUpdate(byte b) {
--        dataSHA.update(b);
--    }
--
--    /**
--     * Update an array of bytes to be signed or verified.
--     *
--     * @param data the bytes to be updated.
--     */
--    protected void engineUpdate(byte[] data, int off, int len) {
--        dataSHA.update(data, off, len);
--    }
--
--    /**
--     * Return a human readable rendition of the engine.
--     */
--    public String toString() {
--        String printable = "DSA Signature";
--        if (presetP != null && presetQ != null && presetG != null) {
--            printable += "\n\tp: " + presetP.toString(16);
--            printable += "\n\tq: " + presetQ.toString(16);
--            printable += "\n\tg: " + presetG.toString(16);
--        } else {
--            printable += "\n\t P, Q or G not initialized.";
--        }
--        if (presetY != null) {
--            printable += "\n\ty: " + presetY.toString(16);
--        }
--        if (presetY == null && presetX == null) {
--            printable += "\n\tUNINIIALIZED";
--        }
--        return printable;
--    }
--
--    /*
--     * Utility routine for converting a byte array into an int array
--     */
--    private int[] byteArray2IntArray(byte[] byteArray) {
--
--        int j = 0;
--        byte[] newBA;
--        int mod = byteArray.length % 4;
--
--        // guarantee that the incoming byteArray is a multiple of 4
--        // (pad with 0's)
--        switch (mod) {
--        case 3:
--            newBA = new byte[byteArray.length + 1];
--            break;
--        case 2:
--            newBA = new byte[byteArray.length + 2];
--            break;
--        case 1:
--            newBA = new byte[byteArray.length + 3];
--            break;
--        default:
--            newBA = new byte[byteArray.length + 0];
--            break;
--        }
--        System.arraycopy(byteArray, 0, newBA, 0, byteArray.length);
--
--        // copy each set of 4 bytes in the byte array into an integer
--        int[] newSeed = new int[newBA.length / 4];
--        for (int i = 0; i < newBA.length; i += 4) {
--            newSeed[j] = newBA[i + 3] & 0xFF;
--            newSeed[j] |= (newBA[i + 2] << 8) & 0xFF00;
--            newSeed[j] |= (newBA[i + 1] << 16) & 0xFF0000;
--            newSeed[j] |= (newBA[i + 0] << 24) & 0xFF000000;
--            j++;
--        }
--
--        return newSeed;
--    }
--
--    /* We include the test vectors from the DSA specification, FIPS
--       186, and the FIPS 186 Change No 1, which updates the test
--       vector using SHA-1 instead of SHA (for both the G function and
--       the message hash.  */
--
--    static void testDSA() throws Exception {
--        PrintStream p = System.out;
--
--        DSA dsa = new DSA();
--        int[] Kseed = { 0x687a66d9, 0x0648f993, 0x867e121f,
--                0x4ddf9ddb, 0x1205584 };
--        BigInteger k = dsa.generateK(Kseed, q512);
--        p.println("k: " + k.toString(16));
--        BigInteger r = dsa.generateR(p512, q512, g512, k);
--        p.println("r: " + r.toString(16));
--        byte[] abc = { 0x61, 0x62, 0x63 };
--        dsa.dataSHA.update(abc);
--        BigInteger s = dsa.generateS(x512, q512, r, k);
--        p.println("s: " + s.toString(16));
--
--        dsa.dataSHA.update(abc);
--        BigInteger w = dsa.generateW(p512, q512, g512, s);
--        p.println("w: " + w.toString(16));
--        BigInteger v = dsa.generateV(y512, p512, q512, g512, w, r);
--        p.println("v: " + v.toString(16));
--        if (v.equals(r)) {
--            p.println("signature verifies.");
--        } else {
--            p.println("signature does not verify.");
--        }
--    }
--
--    /* Test vector: 512-bit keys generated by our key generator. */
--
--    static BigInteger p512 =
--            new BigInteger("fca682ce8e12caba26efccf7110e526db078b05edecb" +
--                    "cd1eb4a208f3ae1617ae01f35b91a47e6df63413c5e1" +
--                    "2ed0899bcd132acd50d99151bdc43ee737592e17", 16);
--
--    static BigInteger q512 =
--            new BigInteger("962eddcc369cba8ebb260ee6b6a126d9346e38c5", 16);
--
--    static BigInteger g512 =
--            new BigInteger("678471b27a9cf44ee91a49c5147db1a9aaf244f05a43" +
--                    "4d6486931d2d14271b9e35030b71fd73da179069b32e" +
--                    "2935630e1c2062354d0da20a6c416e50be794ca4", 16);
--
--    static BigInteger x512 =
--            new BigInteger("3406c2d71b04b5fc0db62afcad58a6607d3de688", 16);
--
--    static BigInteger y512 =
--            new BigInteger("2d335d76b8ec9d610aa8f2cbb4b149fd96fdd" +
--                    "3a9a6e62bd6c2e01d406be4d1d72718a2fe08bea6d12f5e452474461f70f4" +
--                    "dea60508e9fe2eaec23d2ec5d1a866", 16);
--
--    /* Official NIST 512-bit test keys */
--
--    static String pString = "8df2a494492276aa3d25759bb06869cbeac0d83afb8d0" +
--            "cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec" +
--            "0736ee31c80291";
--
--    static BigInteger testP = new BigInteger(pString, 16);
--
--    static String gString = "626d027839ea0a13413163a55b4cb500299d5522956ce" +
--            "fcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc5" +
--            "72af53e6d78802";
--
--    static BigInteger testG = new BigInteger(gString, 16);
--
--    static BigInteger testQ = new BigInteger("c773218c737ec8ee993b4f2ded30" +
--                         "f48edace915f", 16);
--
--    static BigInteger testX = new BigInteger("2070b3223dba372fde1c0ffc7b2e" +
--                         "3b498b260614", 16);
--
--    static String yString = "19131871d75b1612a819f29d78d1b0d7346f7aa77" +
--            "bb62a859bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74858fba33f44c06" +
--            "699630a76b030ee333";
--
--    static BigInteger testY = new BigInteger(yString, 16);
--
--    /* End test vector values */
--
--    private static void debug(String s) {
--        if (debug) {
--            System.err.println(s);
--        }
--    }
--
--}
-diff --git a/org/mozilla/jss/netscape/security/provider/DSAKeyPairGenerator.java b/org/mozilla/jss/netscape/security/provider/DSAKeyPairGenerator.java
-deleted file mode 100644
-index c4942dea..00000000
---- a/org/mozilla/jss/netscape/security/provider/DSAKeyPairGenerator.java
-+++ /dev/null
-@@ -1,389 +0,0 @@
--// --- BEGIN COPYRIGHT BLOCK ---
--// This program is free software; you can redistribute it and/or modify
--// it under the terms of the GNU General Public License as published by
--// the Free Software Foundation; version 2 of the License.
--//
--// This program 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 for more details.
--//
--// You should have received a copy of the GNU General Public License along
--// with this program; if not, write to the Free Software Foundation, Inc.,
--// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
--//
--// (C) 2007 Red Hat, Inc.
--// All rights reserved.
--// --- END COPYRIGHT BLOCK ---
--package org.mozilla.jss.netscape.security.provider;
--
--import java.math.BigInteger;
--import java.security.AlgorithmParameterGenerator;
--import java.security.InvalidAlgorithmParameterException;
--import java.security.InvalidKeyException;
--import java.security.InvalidParameterException;
--import java.security.KeyPair;
--import java.security.KeyPairGenerator;
--import java.security.NoSuchAlgorithmException;
--import java.security.NoSuchProviderException;
--import java.security.ProviderException;
--import java.security.SecureRandom;
--import java.security.interfaces.DSAParams;
--import java.security.spec.AlgorithmParameterSpec;
--import java.security.spec.DSAParameterSpec;
--import java.security.spec.InvalidParameterSpecException;
--import java.util.Hashtable;
--
--import org.mozilla.jss.netscape.security.x509.AlgIdDSA;
--
--/**
-- * This class generates DSA key parameters and public/private key
-- * pairs according to the DSS standard NIST FIPS 186. It uses the
-- * updated version of SHA, SHA-1 as described in FIPS 180-1.
-- *
-- * @author Benjamin Renaud
-- *
-- * @version 1.23, 97/12/10
-- */
--
--public class DSAKeyPairGenerator extends KeyPairGenerator
--        implements java.security.interfaces.DSAKeyPairGenerator {
--
--    private static Hashtable<Integer, AlgIdDSA> precomputedParams;
--
--    static {
--
--        /* We support precomputed parameter for 512, 768 and 1024 bit
--           moduli. In this file we provide both the seed and counter
--           value of the generation process for each of these seeds,
--           for validation purposes. We also include the test vectors
--           from the DSA specification, FIPS 186, and the FIPS 186
--           Change No 1, which updates the test vector using SHA-1
--           instead of SHA (for both the G function and the message
--           hash.
--           */
--
--        precomputedParams = new Hashtable<Integer, AlgIdDSA>();
--
--        /*
--         * L = 512
--         * SEED = b869c82b35d70e1b1ff91b28e37a62ecdc34409b
--         * counter = 123
--         */
--        BigInteger p512 =
--                new BigInteger("fca682ce8e12caba26efccf7110e526db078b05edecb" +
--                        "cd1eb4a208f3ae1617ae01f35b91a47e6df63413c5e1" +
--                        "2ed0899bcd132acd50d99151bdc43ee737592e17", 16);
--
--        BigInteger q512 =
--                new BigInteger("962eddcc369cba8ebb260ee6b6a126d9346e38c5", 16);
--
--        BigInteger g512 =
--                new BigInteger("678471b27a9cf44ee91a49c5147db1a9aaf244f05a43" +
--                        "4d6486931d2d14271b9e35030b71fd73da179069b32e" +
--                        "2935630e1c2062354d0da20a6c416e50be794ca4", 16);
--
--        /*
--         * L = 768
--         * SEED = 77d0f8c4dad15eb8c4f2f8d6726cefd96d5bb399
--         * counter = 263
--         */
--        BigInteger p768 =
--                new BigInteger("e9e642599d355f37c97ffd3567120b8e25c9cd43e" +
--                        "927b3a9670fbec5d890141922d2c3b3ad24800937" +
--                        "99869d1e846aab49fab0ad26d2ce6a22219d470bc" +
--                        "e7d777d4a21fbe9c270b57f607002f3cef8393694" +
--                        "cf45ee3688c11a8c56ab127a3daf", 16);
--
--        BigInteger q768 =
--                new BigInteger("9cdbd84c9f1ac2f38d0f80f42ab952e7338bf511",
--                        16);
--
--        BigInteger g768 =
--                new BigInteger("30470ad5a005fb14ce2d9dcd87e38bc7d1b1c5fac" +
--                        "baecbe95f190aa7a31d23c4dbbcbe06174544401a" +
--                        "5b2c020965d8c2bd2171d3668445771f74ba084d2" +
--                        "029d83c1c158547f3a9f1a2715be23d51ae4d3e5a" +
--                        "1f6a7064f316933a346d3f529252", 16);
--
--        /*
--         * L = 1024
--         * SEED = 8d5155894229d5e689ee01e6018a237e2cae64cd
--         * counter = 92
--         */
--        BigInteger p1024 =
--                new BigInteger("fd7f53811d75122952df4a9c2eece4e7f611b7523c" +
--                        "ef4400c31e3f80b6512669455d402251fb593d8d58" +
--                        "fabfc5f5ba30f6cb9b556cd7813b801d346ff26660" +
--                        "b76b9950a5a49f9fe8047b1022c24fbba9d7feb7c6" +
--                        "1bf83b57e7c6a8a6150f04fb83f6d3c51ec3023554" +
--                        "135a169132f675f3ae2b61d72aeff22203199dd148" +
--                        "01c7", 16);
--
--        BigInteger q1024 =
--                new BigInteger("9760508f15230bccb292b982a2eb840bf0581cf5",
--                        16);
--
--        BigInteger g1024 =
--                new BigInteger("f7e1a085d69b3ddecbbcab5c36b857b97994afbbfa" +
--                        "3aea82f9574c0b3d0782675159578ebad4594fe671" +
--                        "07108180b449167123e84c281613b7cf09328cc8a6" +
--                        "e13c167a8b547c8d28e0a3ae1e2bb3a675916ea37f" +
--                        "0bfa213562f1fb627a01243bcca4f1bea8519089a8" +
--                        "83dfe15ae59f06928b665e807b552564014c3bfecf" +
--                        "492a", 16);
--
--        try {
--            AlgIdDSA alg512 = new AlgIdDSA(p512, q512, g512);
--            AlgIdDSA alg768 = new AlgIdDSA(p768, q768, g768);
--            AlgIdDSA alg1024 = new AlgIdDSA(p1024, q1024, g1024);
--
--            precomputedParams.put(Integer.valueOf(512), alg512);
--            precomputedParams.put(Integer.valueOf(768), alg768);
--            precomputedParams.put(Integer.valueOf(1024), alg1024);
--
--        } catch (Exception e) {
--            throw new InternalError("initializing precomputed " +
--                     "algorithm parameters for Sun DSA");
--        }
--    }
--
--    /* The modulus length */
--    private int modlen = 1024;
--
--    /* Generate new parameters, even if we have precomputed ones. */
--    boolean generateNewParameters = false;
--
--    /* preset algorithm parameters. */
--    private BigInteger presetP, presetQ, presetG;
--
--    /* The source of random bits to use */
--    SecureRandom random;
--
--    public DSAKeyPairGenerator() {
--        super("DSA");
--    }
--
--    public void initialize(int strength, SecureRandom random) {
--        if ((strength < 512) || (strength > 1024) || (strength % 64 != 0)) {
--            throw new InvalidParameterException("Modulus size must range from 512 to 1024 "
--                    + "and be a multiple of 64");
--        }
--
--        /* Set the random */
--        this.random = random;
--        if (this.random == null) {
--            this.random = new SecureRandom();
--        }
--
--        this.modlen = strength;
--        DSAParams params = null;
--
--        /* Find the precomputed parameters, if any */
--        if (!generateNewParameters) {
--            Integer mod = Integer.valueOf(this.modlen);
--            params = precomputedParams.get(mod);
--        }
--        if (params != null) {
--            setParams(params);
--        }
--    }
--
--    /**
--     * Initializes the DSA key pair generator. If <code>genParams</code> is false, a set of pre-computed parameters is
--     * used. In this case, <code>modelen</code> must be 512, 768, or 1024.
--     */
--    public void initialize(int modlen, boolean genParams, SecureRandom random)
--            throws InvalidParameterException {
--        if (genParams == false && modlen != 512 && modlen != 768
--                && modlen != 1024) {
--            throw new InvalidParameterException("No precomputed parameters for requested modulus size "
--                    + "available");
--        }
--        this.generateNewParameters = genParams;
--        initialize(modlen, random);
--    }
--
--    /**
--     * Initializes the DSA object using a DSA parameter object.
--     *
--     * @param params a fully initialized DSA parameter object.
--     */
--    public void initialize(DSAParams params, SecureRandom random)
--            throws InvalidParameterException {
--        initialize(params.getP().bitLength(), random);
--        setParams(params);
--    }
--
--    /**
--     * Initializes the DSA object using a parameter object.
--     *
--     * @param params the parameter set to be used to generate
--     *            the keys.
--     * @param random the source of randomness for this generator.
--     *
--     * @exception InvalidAlgorithmParameterException if the given parameters
--     *                are inappropriate for this key pair generator
--     */
--    public void initialize(AlgorithmParameterSpec params, SecureRandom random)
--            throws InvalidAlgorithmParameterException {
--        if (!(params instanceof DSAParameterSpec)) {
--            throw new InvalidAlgorithmParameterException("Inappropriate parameter");
--        }
--        initialize(((DSAParameterSpec) params).getP().bitLength(),
--                random);
--        setParams((DSAParameterSpec) params);
--    }
--
--    /**
--     * Generates a pair of keys usable by any JavaSecurity compliant
--     * DSA implementation.
--     *
--     * @param rnd the source of random bits from which the random key
--     *            generation parameters are drawn. In particular, this includes
--     *            the XSEED parameter.
--     *
--     * @exception InvalidParameterException if the modulus is not
--     *                between 512 and 1024.
--     */
--    public KeyPair generateKeyPair() {
--
--        // set random if initialize() method has been skipped
--        if (this.random == null) {
--            this.random = new SecureRandom();
--        }
--
--        if (presetP == null || presetQ == null || presetG == null ||
--                generateNewParameters) {
--
--            AlgorithmParameterGenerator dsaParamGen;
--
--            try {
--                dsaParamGen = AlgorithmParameterGenerator.getInstance("DSA",
--                                      "SUN");
--            } catch (NoSuchAlgorithmException e) {
--                // this should never happen, because we provide it
--                throw new RuntimeException(e.getMessage());
--            } catch (NoSuchProviderException e) {
--                // this should never happen, because we provide it
--                throw new RuntimeException(e.getMessage());
--            }
--
--            dsaParamGen.init(modlen, random);
--
--            DSAParameterSpec dsaParamSpec;
--            try {
--                dsaParamSpec = dsaParamGen.generateParameters().getParameterSpec
--                        (DSAParameterSpec.class);
--            } catch (InvalidParameterSpecException e) {
--                // this should never happen
--                throw new RuntimeException(e.getMessage());
--            }
--            presetP = dsaParamSpec.getP();
--            presetQ = dsaParamSpec.getQ();
--            presetG = dsaParamSpec.getG();
--        }
--
--        return generateKeyPair(presetP, presetQ, presetG, random);
--    }
--
--    public KeyPair generateKeyPair(BigInteger p, BigInteger q, BigInteger g,
--                   SecureRandom random) {
--
--        BigInteger x = generateX(random, q);
--        BigInteger y = generateY(x, p, g);
--
--        try {
--            DSAPublicKey pub = new DSAPublicKey(y, p, q, g);
--            DSAPrivateKey priv = new DSAPrivateKey(x, p, q, g);
--
--            KeyPair pair = new KeyPair(pub, priv);
--            return pair;
--
--        } catch (InvalidKeyException e) {
--            throw new ProviderException(e.getMessage());
--        }
--    }
--
--    /**
--     * Generate the private key component of the key pair using the
--     * provided source of random bits. This method uses the random but
--     * source passed to generate a seed and then calls the seed-based
--     * generateX method.
--     */
--    private BigInteger generateX(SecureRandom random, BigInteger q) {
--        BigInteger x = null;
--        while (true) {
--            int[] seed = new int[5];
--            for (int i = 0; i < 5; i++) {
--                seed[i] = random.nextInt();
--            }
--            x = generateX(seed, q);
--            if (x.signum() > 0 && (x.compareTo(q) < 0)) {
--                break;
--            }
--        }
--        return x;
--    }
--
--    /**
--     * Given a seed, generate the private key component of the key
--     * pair. In the terminology used in the DSA specification
--     * (FIPS-186) seed is the XSEED quantity.
--     *
--     * @param seed the seed to use to generate the private key.
--     */
--    BigInteger generateX(int[] seed, BigInteger q) {
--
--        /* Test vector
--        int[] tseed = { 0xbd029bbe, 0x7f51960b, 0xcf9edb2b,
--        		 0x61f06f0f, 0xeb5a38b6 };
--        seed = tseed;
--        */
--        // check out t in the spec.
--        int[] t = { 0x67452301, 0xEFCDAB89, 0x98BADCFE,
--                0x10325476, 0xC3D2E1F0 };
--        //
--
--        int[] tmp = DSA.SHA_7(seed, t);
--        byte[] tmpBytes = new byte[tmp.length * 4];
--        for (int i = 0; i < tmp.length; i++) {
--            int k = tmp[i];
--            for (int j = 0; j < 4; j++) {
--                tmpBytes[(i * 4) + j] = (byte) (k >>> (24 - (j * 8)));
--            }
--        }
--        BigInteger x = new BigInteger(1, tmpBytes).mod(q);
--        return x;
--    }
--
--    /**
--     * Generate the public key component y of the key pair.
--     *
--     * @param x the private key component.
--     *
--     * @param p the base parameter.
--     */
--    BigInteger generateY(BigInteger x, BigInteger p, BigInteger g) {
--        BigInteger y = g.modPow(x, p);
--        return y;
--    }
--
--    /**
--     * Set the parameters.
--     */
--    private void setParams(DSAParams params) {
--        presetP = params.getP();
--        presetQ = params.getQ();
--        presetG = params.getG();
--    }
--
--    /**
--     * Set the parameters.
--     */
--    private void setParams(DSAParameterSpec params) {
--        presetP = params.getP();
--        presetQ = params.getQ();
--        presetG = params.getG();
--    }
--}
-diff --git a/org/mozilla/jss/netscape/security/provider/DSAParameterGenerator.java b/org/mozilla/jss/netscape/security/provider/DSAParameterGenerator.java
-deleted file mode 100644
-index 5cd86c79..00000000
---- a/org/mozilla/jss/netscape/security/provider/DSAParameterGenerator.java
-+++ /dev/null
-@@ -1,298 +0,0 @@
--// --- BEGIN COPYRIGHT BLOCK ---
--// This program is free software; you can redistribute it and/or modify
--// it under the terms of the GNU General Public License as published by
--// the Free Software Foundation; version 2 of the License.
--//
--// This program 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 for more details.
--//
--// You should have received a copy of the GNU General Public License along
--// with this program; if not, write to the Free Software Foundation, Inc.,
--// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
--//
--// (C) 2007 Red Hat, Inc.
--// All rights reserved.
--// --- END COPYRIGHT BLOCK ---
--package org.mozilla.jss.netscape.security.provider;
--
--import java.math.BigInteger;
--import java.security.AlgorithmParameterGeneratorSpi;
--import java.security.AlgorithmParameters;
--import java.security.InvalidAlgorithmParameterException;
--import java.security.InvalidParameterException;
--import java.security.NoSuchAlgorithmException;
--import java.security.NoSuchProviderException;
--import java.security.SecureRandom;
--import java.security.spec.AlgorithmParameterSpec;
--import java.security.spec.DSAParameterSpec;
--import java.security.spec.InvalidParameterSpecException;
--
--/*
-- * This class generates parameters for the DSA algorithm. It uses a default
-- * prime modulus size of 1024 bits, which can be overwritten during
-- * initialization.
-- *
-- * @author Jan Luehe
-- *
-- * @version 1.4, 97/12/10
-- *
-- * @see java.security.AlgorithmParameters
-- * @see java.security.spec.AlgorithmParameterSpec
-- * @see DSAParameters
-- *
-- * @since JDK1.2
-- */
--
--public class DSAParameterGenerator extends AlgorithmParameterGeneratorSpi {
--
--    // the modulus length
--    private int modLen = 1024; // default
--
--    // the source of randomness
--    private SecureRandom random;
--
--    // useful constants
--    private static final BigInteger ONE = BigInteger.valueOf(1);
--    private static final BigInteger TWO = BigInteger.valueOf(2);
--
--    // Make a SHA-1 hash function
--    private SHA sha;
--
--    public DSAParameterGenerator() {
--        this.sha = new SHA();
--    }
--
--    /**
--     * Initializes this parameter generator for a certain strength
--     * and source of randomness.
--     *
--     * @param strength the strength (size of prime) in bits
--     * @param random the source of randomness
--     */
--    protected void engineInit(int strength, SecureRandom random) {
--        /*
--         * Bruce Schneier, "Applied Cryptography", 2nd Edition,
--         * Description of DSA:
--         * [...] The algorithm uses the following parameter:
--         * p=a prime number L bits long, when L ranges from 512 to 1024 and is
--         * a multiple of 64. [...]
--         */
--        if ((strength < 512) || (strength > 1024) || (strength % 64 != 0)) {
--            throw new InvalidParameterException("Prime size must range from 512 to 1024 "
--                    + "and be a multiple of 64");
--        }
--        this.modLen = strength;
--        this.random = random;
--    }
--
--    /**
--     * Initializes this parameter generator with a set of
--     * algorithm-specific parameter generation values.
--     *
--     * @param params the set of algorithm-specific parameter generation values
--     * @param random the source of randomness
--     *
--     * @exception InvalidAlgorithmParameterException if the given parameter
--     *                generation values are inappropriate for this parameter generator
--     */
--    protected void engineInit(AlgorithmParameterSpec genParamSpec,
--                  SecureRandom random)
--            throws InvalidAlgorithmParameterException {
--        throw new InvalidAlgorithmParameterException("Invalid parameter");
--    }
--
--    /**
--     * Generates the parameters.
--     *
--     * @return the new AlgorithmParameters object
--     */
--    protected AlgorithmParameters engineGenerateParameters() {
--        AlgorithmParameters algParams = null;
--        try {
--            if (this.random == null) {
--                this.random = new SecureRandom();
--            }
--
--            BigInteger[] pAndQ = generatePandQ(this.random, this.modLen);
--            BigInteger paramP = pAndQ[0];
--            BigInteger paramQ = pAndQ[1];
--            BigInteger paramG = generateG(paramP, paramQ);
--
--            DSAParameterSpec dsaParamSpec = new DSAParameterSpec(paramP,
--                                 paramQ,
--                                 paramG);
--            algParams = AlgorithmParameters.getInstance("DSA", "SUN");
--            algParams.init(dsaParamSpec);
--        } catch (InvalidParameterSpecException e) {
--            // this should never happen
--            throw new RuntimeException(e.getMessage());
--        } catch (NoSuchAlgorithmException e) {
--            // this should never happen, because we provide it
--            throw new RuntimeException(e.getMessage());
--        } catch (NoSuchProviderException e) {
--            // this should never happen, because we provide it
--            throw new RuntimeException(e.getMessage());
--        }
--
--        return algParams;
--    }
--
--    /*
--     * Generates the prime and subprime parameters for DSA,
--     * using the provided source of randomness.
--     * This method will generate new seeds until a suitable
--     * seed has been found.
--     *
--     * @param random the source of randomness to generate the
--     * seed
--     * @param L the size of <code>p</code>, in bits.
--     *
--     * @return an array of BigInteger, with <code>p</code> at index 0 and
--     * <code>q</code> at index 1.
--     */
--    BigInteger[] generatePandQ(SecureRandom random, int L) {
--        BigInteger[] result = null;
--        byte[] seed = new byte[20];
--
--        while (result == null) {
--            for (int i = 0; i < 20; i++) {
--                seed[i] = (byte) random.nextInt();
--            }
--            result = generatePandQ(seed, L);
--        }
--        return result;
--    }
--
--    /*
--     * Generates the prime and subprime parameters for DSA.
--     *
--     * <p>The seed parameter corresponds to the <code>SEED</code> parameter
--     * referenced in the FIPS specification of the DSA algorithm,
--     * and L is the size of <code>p</code>, in bits.
--     *
--     * @param seed the seed to generate the parameters
--     * @param L the size of <code>p</code>, in bits.
--     *
--     * @return an array of BigInteger, with <code>p</code> at index 0,
--     * <code>q</code> at index 1, the seed at index 2, and the counter value
--     * at index 3, or null if the seed does not yield suitable numbers.
--     */
--    BigInteger[] generatePandQ(byte[] seed, int L) {
--
--        /* Useful variables */
--        int g = seed.length * 8;
--        int n = (L - 1) / 160;
--        int b = (L - 1) % 160;
--
--        BigInteger SEED = new BigInteger(1, seed);
--        BigInteger TWOG = TWO.pow(2 * g);
--
--        /* Step 2 (Step 1 is getting seed). */
--        byte[] U1 = SHA(seed);
--        byte[] U2 = SHA(toByteArray((SEED.add(ONE)).mod(TWOG)));
--
--        xor(U1, U2);
--        byte[] U = U1;
--
--        /* Step 3: For q by setting the msb and lsb to 1 */
--        U[0] |= 0x80;
--        U[19] |= 1;
--        BigInteger q = new BigInteger(1, U);
--
--        /* Step 5 */
--        if (!q.isProbablePrime(40)) {
--            return null;
--
--        } else {
--            BigInteger V[] = new BigInteger[n + 1];
--            BigInteger offset = TWO;
--
--            /* Step 6 */
--            for (int counter = 0; counter < 4096; counter++) {
--
--                /* Step 7 */
--                for (int k = 0; k <= n; k++) {
--                    BigInteger K = BigInteger.valueOf(k);
--                    BigInteger tmp = (SEED.add(offset).add(K)).mod(TWOG);
--                    V[k] = new BigInteger(1, SHA(toByteArray(tmp)));
--                }
--
--                /* Step 8 */
--                BigInteger W = V[0];
--                for (int i = 1; i < n; i++) {
--                    W = W.add(V[i].multiply(TWO.pow(i * 160)));
--                }
--                W = W.add((V[n].mod(TWO.pow(b))).multiply(TWO.pow(n * 160)));
--
--                BigInteger TWOLm1 = TWO.pow(L - 1);
--                BigInteger X = W.add(TWOLm1);
--
--                /* Step 9 */
--                BigInteger c = X.mod(q.multiply(TWO));
--                BigInteger p = X.subtract(c.subtract(ONE));
--
--                /* Step 10 - 13 */
--                if (p.compareTo(TWOLm1) > -1 && p.isProbablePrime(15)) {
--                    BigInteger[] result = { p, q, SEED,
--                            BigInteger.valueOf(counter) };
--                    return result;
--                }
--                offset = offset.add(BigInteger.valueOf(n)).add(ONE);
--            }
--            return null;
--        }
--    }
--
--    /*
--     * Generates the <code>g</code> parameter for DSA.
--     *
--     * @param p the prime, <code>p</code>.
--     * @param q the subprime, <code>q</code>.
--     *
--     * @param the <code>g</code>
--     */
--    BigInteger generateG(BigInteger p, BigInteger q) {
--        BigInteger h = ONE;
--        BigInteger pMinusOneOverQ = (p.subtract(ONE)).divide(q);
--        BigInteger g = ONE;
--        while (g.compareTo(TWO) < 0) {
--            g = h.modPow(pMinusOneOverQ, p);
--            h = h.add(ONE);
--        }
--        return g;
--    }
--
--    /*
--     * Returns the SHA-1 digest of some data
--     */
--    private byte[] SHA(byte[] array) {
--        sha.engineReset();
--        sha.engineUpdate(array, 0, array.length);
--        return sha.engineDigest();
--    }
--
--    /*
--     * Converts the result of a BigInteger.toByteArray call to an exact
--     * signed magnitude representation for any positive number.
--     */
--    private byte[] toByteArray(BigInteger bigInt) {
--        byte[] result = bigInt.toByteArray();
--        if (result[0] == 0) {
--            byte[] tmp = new byte[result.length - 1];
--            System.arraycopy(result, 1, tmp, 0, tmp.length);
--            result = tmp;
--        }
--        return result;
--    }
--
--    /*
--     * XORs U2 into U1
--     */
--    private void xor(byte[] U1, byte[] U2) {
--        for (int i = 0; i < U1.length; i++) {
--            U1[i] ^= U2[i];
--        }
--    }
--}
-diff --git a/org/mozilla/jss/netscape/security/provider/MD5.java b/org/mozilla/jss/netscape/security/provider/MD5.java
-deleted file mode 100644
-index d46da4fc..00000000
---- a/org/mozilla/jss/netscape/security/provider/MD5.java
-+++ /dev/null
-@@ -1,378 +0,0 @@
--// --- BEGIN COPYRIGHT BLOCK ---
--// This program is free software; you can redistribute it and/or modify
--// it under the terms of the GNU General Public License as published by
--// the Free Software Foundation; version 2 of the License.
--//
--// This program 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 for more details.
--//
--// You should have received a copy of the GNU General Public License along
--// with this program; if not, write to the Free Software Foundation, Inc.,
--// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
--//
--// (C) 2007 Red Hat, Inc.
--// All rights reserved.
--// --- END COPYRIGHT BLOCK ---
--package org.mozilla.jss.netscape.security.provider;
--
--import java.security.DigestException;
--import java.security.MessageDigestSpi;
--
--/**
-- * The MD5 class is used to compute an MD5 message digest over a given
-- * buffer of bytes. It is an implementation of the RSA Data Security Inc
-- * MD5 algorithim as described in internet RFC 1321.
-- *
-- * @version 1.24 97/12/10
-- * @author Chuck McManis
-- * @author Benjamin Renaud
-- */
--
--public final class MD5 extends MessageDigestSpi implements Cloneable {
--
--    /** contains the computed message digest */
--    private byte[] digestBits;
--
--    private int state[];
--    private long count; // bit count AND buffer[] index aid
--    private byte buffer[];
--    private int transformBuffer[];
--
--    private static final int S11 = 7;
--    private static final int S12 = 12;
--    private static final int S13 = 17;
--    private static final int S14 = 22;
--    private static final int S21 = 5;
--    private static final int S22 = 9;
--    private static final int S23 = 14;
--    private static final int S24 = 20;
--    private static final int S31 = 4;
--    private static final int S32 = 11;
--    private static final int S33 = 16;
--    private static final int S34 = 23;
--    private static final int S41 = 6;
--    private static final int S42 = 10;
--    private static final int S43 = 15;
--    private static final int S44 = 21;
--
--    private static final int MD5_LENGTH = 16;
--
--    /**
--     * Standard constructor, creates a new MD5 instance, allocates its
--     * buffers from the heap.
--     */
--    public MD5() {
--        init();
--    }
--
--    /* **********************************************************
--     * The MD5 Functions. These are copied verbatim from
--     * the RFC to insure accuracy. The results of this
--     * implementation were checked against the RSADSI version.
--     * **********************************************************
--     */
--
--    private int F(int x, int y, int z) {
--        return ((x & y) | ((~x) & z));
--    }
--
--    private int G(int x, int y, int z) {
--        return ((x & z) | (y & (~z)));
--    }
--
--    private int H(int x, int y, int z) {
--        return ((x ^ y) ^ z);
--    }
--
--    private int I(int x, int y, int z) {
--        return (y ^ (x | (~z)));
--    }
--
--    private int rotateLeft(int a, int n) {
--        return ((a << n) | (a >>> (32 - n)));
--    }
--
--    private int FF(int a, int b, int c, int d, int x, int s, int ac) {
--        a += F(b, c, d) + x + ac;
--        a = rotateLeft(a, s);
--        a += b;
--        return a;
--    }
--
--    private int GG(int a, int b, int c, int d, int x, int s, int ac) {
--        a += G(b, c, d) + x + ac;
--        a = rotateLeft(a, s);
--        a += b;
--        return a;
--    }
--
--    private int HH(int a, int b, int c, int d, int x, int s, int ac) {
--        a += H(b, c, d) + x + ac;
--        a = rotateLeft(a, s);
--        a += b;
--        return a;
--    }
--
--    private int II(int a, int b, int c, int d, int x, int s, int ac) {
--        a += I(b, c, d) + x + ac;
--        a = rotateLeft(a, s);
--        a += b;
--        return a;
--    }
--
--    /**
--     * This is where the functions come together as the generic MD5
--     * transformation operation, it is called by update() which is
--     * synchronized (to protect transformBuffer). It consumes sixteen
--     * bytes from the buffer, beginning at the specified offset.
--     */
--    void transform(byte buf[], int offset) {
--        int a, b, c, d;
--        int x[] = transformBuffer;
--
--        a = state[0];
--        b = state[1];
--        c = state[2];
--        d = state[3];
--
--        for (int i = 0; i < 16; i++) {
--            x[i] = buf[i * 4 + offset] & 0xff;
--            for (int j = 1; j < 4; j++) {
--                x[i] += (buf[i * 4 + j + offset] & 0xff) << (j * 8);
--            }
--        }
--
--        /* Round 1 */
--        a = FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */
--        d = FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */
--        c = FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */
--        b = FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */
--        a = FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */
--        d = FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */
--        c = FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */
--        b = FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */
--        a = FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */
--        d = FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */
--        c = FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
--        b = FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
--        a = FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
--        d = FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
--        c = FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
--        b = FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
--
--        /* Round 2 */
--        a = GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */
--        d = GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */
--        c = GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
--        b = GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */
--        a = GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */
--        d = GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
--        c = GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
--        b = GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */
--        a = GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */
--        d = GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
--        c = GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */
--        b = GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */
--        a = GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
--        d = GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */
--        c = GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */
--        b = GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
--
--        /* Round 3 */
--        a = HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */
--        d = HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */
--        c = HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
--        b = HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
--        a = HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */
--        d = HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */
--        c = HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */
--        b = HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
--        a = HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
--        d = HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */
--        c = HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */
--        b = HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */
--        a = HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */
--        d = HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
--        c = HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
--        b = HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */
--
--        /* Round 4 */
--        a = II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */
--        d = II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */
--        c = II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
--        b = II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */
--        a = II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
--        d = II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */
--        c = II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
--        b = II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */
--        a = II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */
--        d = II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
--        c = II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */
--        b = II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
--        a = II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */
--        d = II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
--        c = II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */
--        b = II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */
--
--        state[0] += a;
--        state[1] += b;
--        state[2] += c;
--        state[3] += d;
--    }
--
--    /**
--     * Initialize the MD5 state information and reset the bit count
--     * to 0. Given this implementation you are constrained to counting
--     * 2^64 bits.
--     */
--    public void init() {
--        state = new int[4];
--        transformBuffer = new int[16];
--        synchronized (this) {
--            buffer = new byte[64];
--        }
--        digestBits = new byte[16];
--        count = 0;
--        // Load magic initialization constants.
--        state[0] = 0x67452301;
--        state[1] = 0xefcdab89;
--        state[2] = 0x98badcfe;
--        state[3] = 0x10325476;
--        for (int i = 0; i < digestBits.length; i++)
--            digestBits[i] = 0;
--    }
--
--    protected void engineReset() {
--        init();
--    }
--
--    /**
--     * Return the digest length in bytes
--     */
--    protected int engineGetDigestLength() {
--        return (MD5_LENGTH);
--    }
--
--    /**
--     * Update adds the passed byte to the digested data.
--     */
--    protected synchronized void engineUpdate(byte b) {
--        int index;
--
--        index = (int) ((count >>> 3) & 0x3f);
--        count += 8;
--        buffer[index] = b;
--        if (index >= 63) {
--            transform(buffer, 0);
--        }
--    }
--
--    /**
--     * Update adds the selected part of an array of bytes to the digest.
--     * This version is more efficient than the byte-at-a-time version;
--     * it avoids data copies and reduces per-byte call overhead.
--     */
--    protected synchronized void engineUpdate(byte input[], int offset,
--                         int len) {
--        int i;
--
--        for (i = offset; len > 0;) {
--            int index = (int) ((count >>> 3) & 0x3f);
--
--            if (index == 0 && len > 64) {
--                count += (64 * 8);
--                transform(input, i);
--                len -= 64;
--                i += 64;
--            } else {
--                count += 8;
--                buffer[index] = input[i];
--                if (index >= 63)
--                    transform(buffer, 0);
--                i++;
--                len--;
--            }
--        }
--    }
--
--    /**
--     * Perform the final computations, any buffered bytes are added
--     * to the digest, the count is added to the digest, and the resulting
--     * digest is stored. After calling final you will need to call
--     * init() again to do another digest.
--     */
--    private void finish() {
--        byte bits[] = new byte[8];
--        byte padding[];
--        int i, index, padLen;
--
--        for (i = 0; i < 8; i++) {
--            bits[i] = (byte) ((count >>> (i * 8)) & 0xff);
--        }
--
--        index = (int) (count >> 3) & 0x3f;
--        padLen = (index < 56) ? (56 - index) : (120 - index);
--        padding = new byte[padLen];
--        padding[0] = (byte) 0x80;
--        engineUpdate(padding, 0, padding.length);
--        engineUpdate(bits, 0, bits.length);
--
--        for (i = 0; i < 4; i++) {
--            for (int j = 0; j < 4; j++) {
--                digestBits[i * 4 + j] = (byte) ((state[i] >>> (j * 8)) & 0xff);
--            }
--        }
--    }
--
--    /**
--     */
--    protected byte[] engineDigest() {
--        finish();
--
--        byte[] result = new byte[MD5_LENGTH];
--        System.arraycopy(digestBits, 0, result, 0, MD5_LENGTH);
--
--        init();
--
--        return result;
--    }
--
--    /**
--     */
--    protected int engineDigest(byte[] buf, int offset, int len)
--                        throws DigestException {
--        finish();
--
--        if (len < MD5_LENGTH)
--            throw new DigestException("partial digests not returned");
--        if (buf.length - offset < MD5_LENGTH)
--            throw new DigestException("insufficient space in the output " +
--                    "buffer to store the digest");
--
--        System.arraycopy(digestBits, 0, buf, offset, MD5_LENGTH);
--
--        init();
--
--        return MD5_LENGTH;
--    }
--
--    /*
--     * Clones this object.
--     */
--    public Object clone() {
--        MD5 that = null;
--        try {
--            that = (MD5) super.clone();
--            that.state = this.state.clone();
--            that.transformBuffer = this.transformBuffer.clone();
--            that.buffer = this.buffer.clone();
--            that.digestBits = this.digestBits.clone();
--            that.count = this.count;
--            return that;
--        } catch (CloneNotSupportedException e) {
--        }
--        return that;
--    }
--}
-diff --git a/org/mozilla/jss/netscape/security/provider/SHA.java b/org/mozilla/jss/netscape/security/provider/SHA.java
-deleted file mode 100644
-index a911e386..00000000
---- a/org/mozilla/jss/netscape/security/provider/SHA.java
-+++ /dev/null
-@@ -1,349 +0,0 @@
--// --- BEGIN COPYRIGHT BLOCK ---
--// This program is free software; you can redistribute it and/or modify
--// it under the terms of the GNU General Public License as published by
--// the Free Software Foundation; version 2 of the License.
--//
--// This program 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 for more details.
--//
--// You should have received a copy of the GNU General Public License along
--// with this program; if not, write to the Free Software Foundation, Inc.,
--// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
--//
--// (C) 2007 Red Hat, Inc.
--// All rights reserved.
--// --- END COPYRIGHT BLOCK ---
--package org.mozilla.jss.netscape.security.provider;
--
--import java.security.DigestException;
--import java.security.MessageDigestSpi;
--
--/**
-- * This class implements the Secure Hash Algorithm (SHA) developed by
-- * the National Institute of Standards and Technology along with the
-- * National Security Agency. This is the updated version of SHA
-- * fip-180 as superseded by fip-180-1.
-- *
-- * <p>
-- * It implement JavaSecurity MessageDigest, and can be used by in the Java Security framework, as a pluggable
-- * implementation, as a filter for the digest stream classes.
-- *
-- * @version 1.30 97/12/10
-- * @author Roger Riggs
-- * @author Benjamin Renaud
-- */
--
--public class SHA extends MessageDigestSpi implements Cloneable {
--
--    /* This private hookm controlled by the appropriate constructor,
--       causes this class to implement the first version of SHA,
--       as defined in FIPS 180, as opposed to FIPS 180-1. This was
--       useful for DSA testing. */
--    private int version = 1;
--
--    private static final int SHA_LENGTH = 20;
--
--    // Buffer of int's and count of characters accumulated
--    // 64 bytes are included in each hash block so the low order
--    // bits of count are used to know how to pack the bytes into ints
--    // and to know when to compute the block and start the next one.
--    private int W[] = new int[80];
--    private long count = 0;
--    private final int countmax = 64;
--    private final int countmask = (countmax - 1);
--
--    private int AA, BB, CC, DD, EE;
--
--    SHA(int version) {
--        this();
--        this.version = version;
--    }
--
--    /**
--     * Creates a new SHA object.
--     */
--    public SHA() {
--        init();
--    }
--
--    /**
--     * Return the length of the digest in bytes
--     */
--    protected int engineGetDigestLength() {
--        return (SHA_LENGTH);
--    }
--
--    public void engineUpdate(byte b) {
--        engineUpdate((int) b);
--    }
--
--    /**
--     * Update a byte.
--     *
--     * @param b the byte
--     */
--    private void engineUpdate(int b) {
--        int word;
--        int offset;
--
--        /* compute word offset and bit offset within word the low bits
--           of count are inverted to make put the bytes in the write
--           order */
--        word = ((int) count & countmask) >>> 2;
--        offset = (~(int) count & 3) << 3;
--
--        W[word] = (W[word] & ~(0xff << offset)) | ((b & 0xff) << offset);
--
--        /* If this is the last byte of a block, compute the partial hash */
--        if (((int) count & countmask) == countmask) {
--            computeBlock();
--        }
--        count++;
--    }
--
--    /**
--     * Update a buffer.
--     *
--     * @param b the data to be updated.
--     * @param off the start offset in the data
--     * @param len the number of bytes to be updated.
--     */
--    public void engineUpdate(byte b[], int off, int len) {
--        int word;
--
--        if ((off < 0) || (len < 0) || (off + len > b.length))
--            throw new ArrayIndexOutOfBoundsException();
--
--        // Use single writes until integer aligned
--        while ((len > 0) &&
--                ((int) count & 3) != 0) {
--            engineUpdate(b[off]);
--            off++;
--            len--;
--        }
--
--        /* Assemble groups of 4 bytes to be inserted in integer array */
--        for (; len >= 4; len -= 4, off += 4) {
--
--            word = ((int) count & countmask) >> 2;
--
--            W[word] = ((b[off] & 0xff) << 24) |
--                    ((b[off + 1] & 0xff) << 16) |
--                    ((b[off + 2] & 0xff) << 8) |
--                    ((b[off + 3] & 0xff));
--
--            count += 4;
--            if (((int) count & countmask) == 0) {
--                computeBlock();
--            }
--        }
--
--        /* Use single writes for last few bytes */
--        for (; len > 0; len--, off++) {
--            engineUpdate(b[off]);
--        }
--    }
--
--    /**
--     * Resets the buffers and hash value to start a new hash.
--     */
--    public void init() {
--        AA = 0x67452301;
--        BB = 0xefcdab89;
--        CC = 0x98badcfe;
--        DD = 0x10325476;
--        EE = 0xc3d2e1f0;
--
--        for (int i = 0; i < 80; i++)
--            W[i] = 0;
--        count = 0;
--    }
--
--    /**
--     * Resets the buffers and hash value to start a new hash.
--     */
--    public void engineReset() {
--        init();
--    }
--
--    /**
--     * Computes the final hash and returns the final value as a
--     * byte[20] array. The object is reset to be ready for further
--     * use, as specified in the JavaSecurity MessageDigest
--     * specification.
--     */
--    public byte[] engineDigest() {
--        byte hashvalue[] = new byte[SHA_LENGTH];
--
--        try {
--            engineDigest(hashvalue, 0, hashvalue.length);
--        } catch (DigestException e) {
--            throw new InternalError("");
--        }
--        return hashvalue;
--    }
--
--    /**
--     * Computes the final hash and returns the final value as a
--     * byte[20] array. The object is reset to be ready for further
--     * use, as specified in the JavaSecurity MessageDigest
--     * specification.
--     */
--    public int engineDigest(byte[] hashvalue, int offset, int len)
--                    throws DigestException {
--
--        if (len < SHA_LENGTH)
--            throw new DigestException("partial digests not returned");
--        if (hashvalue.length - offset < SHA_LENGTH)
--            throw new DigestException("insufficient space in the output " +
--                    "buffer to store the digest");
--
--        /* The number of bits before padding occurs */
--        long bits = count << 3;
--
--        engineUpdate(0x80);
--
--        /* Pad with zeros until length is a multiple of 448 (the last two
--           32 ints are used a holder for bits (see above). */
--        while ((int) (count & countmask) != 56) {
--            engineUpdate(0);
--        }
--
--        W[14] = (int) (bits >>> 32);
--        W[15] = (int) (bits & 0xffffffff);
--
--        count += 8;
--        computeBlock();
--
--        // Copy out the result
--        hashvalue[offset + 0] = (byte) (AA >>> 24);
--        hashvalue[offset + 1] = (byte) (AA >>> 16);
--        hashvalue[offset + 2] = (byte) (AA >>> 8);
--        hashvalue[offset + 3] = (byte) (AA >>> 0);
--
--        hashvalue[offset + 4] = (byte) (BB >>> 24);
--        hashvalue[offset + 5] = (byte) (BB >>> 16);
--        hashvalue[offset + 6] = (byte) (BB >>> 8);
--        hashvalue[offset + 7] = (byte) (BB >>> 0);
--
--        hashvalue[offset + 8] = (byte) (CC >>> 24);
--        hashvalue[offset + 9] = (byte) (CC >>> 16);
--        hashvalue[offset + 10] = (byte) (CC >>> 8);
--        hashvalue[offset + 11] = (byte) (CC >>> 0);
--
--        hashvalue[offset + 12] = (byte) (DD >>> 24);
--        hashvalue[offset + 13] = (byte) (DD >>> 16);
--        hashvalue[offset + 14] = (byte) (DD >>> 8);
--        hashvalue[offset + 15] = (byte) (DD >>> 0);
--
--        hashvalue[offset + 16] = (byte) (EE >>> 24);
--        hashvalue[offset + 17] = (byte) (EE >>> 16);
--        hashvalue[offset + 18] = (byte) (EE >>> 8);
--        hashvalue[offset + 19] = (byte) (EE >>> 0);
--
--        engineReset(); // remove the evidence
--
--        return SHA_LENGTH;
--    }
--
--    // Constants for each round
--    private final int round1_kt = 0x5a827999;
--    private final int round2_kt = 0x6ed9eba1;
--    private final int round3_kt = 0x8f1bbcdc;
--    private final int round4_kt = 0xca62c1d6;
--
--    /**
--     * Compute a the hash for the current block.
--     *
--     * This is in the same vein as Peter Gutmann's algorithm listed in
--     * the back of Applied Cryptography, Compact implementation of
--     * "old" NIST Secure Hash Algorithm.
--     *
--     */
--    private void computeBlock() {
--        int temp, a, b, c, d, e;
--
--        // The first 16 ints have the byte stream, compute the rest of
--        // the buffer
--        for (int t = 16; t <= 79; t++) {
--            if (version == 0) {
--                W[t] = W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16];
--            } else {
--                temp = W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16];
--                W[t] = ((temp << 1) | (temp >>> (32 - 1)));
--            }
--        }
--
--        a = AA;
--        b = BB;
--        c = CC;
--        d = DD;
--        e = EE;
--
--        // Round 1
--        for (int i = 0; i < 20; i++) {
--            temp = ((a << 5) | (a >>> (32 - 5))) +
--                    ((b & c) | ((~b) & d)) + e + W[i] + round1_kt;
--            e = d;
--            d = c;
--            c = ((b << 30) | (b >>> (32 - 30)));
--            b = a;
--            a = temp;
--        }
--
--        // Round 2
--        for (int i = 20; i < 40; i++) {
--            temp = ((a << 5) | (a >>> (32 - 5))) +
--                    (b ^ c ^ d) + e + W[i] + round2_kt;
--            e = d;
--            d = c;
--            c = ((b << 30) | (b >>> (32 - 30)));
--            b = a;
--            a = temp;
--        }
--
--        // Round 3
--        for (int i = 40; i < 60; i++) {
--            temp = ((a << 5) | (a >>> (32 - 5))) +
--                    ((b & c) | (b & d) | (c & d)) + e + W[i] + round3_kt;
--            e = d;
--            d = c;
--            c = ((b << 30) | (b >>> (32 - 30)));
--            b = a;
--            a = temp;
--        }
--
--        // Round 4
--        for (int i = 60; i < 80; i++) {
--            temp = ((a << 5) | (a >>> (32 - 5))) +
--                    (b ^ c ^ d) + e + W[i] + round4_kt;
--            e = d;
--            d = c;
--            c = ((b << 30) | (b >>> (32 - 30)));
--            b = a;
--            a = temp;
--        }
--        AA += a;
--        BB += b;
--        CC += c;
--        DD += d;
--        EE += e;
--    }
--
--    /*
--     * Clones this object.
--     */
--    public Object clone() {
--        SHA that = null;
--        try {
--            that = (SHA) super.clone();
--            that.W = new int[80];
--            System.arraycopy(this.W, 0, that.W, 0, W.length);
--            return that;
--        } catch (CloneNotSupportedException e) {
--        }
--        return that;
--    }
--}
-diff --git a/org/mozilla/jss/netscape/security/provider/Sun.java b/org/mozilla/jss/netscape/security/provider/Sun.java
-index 94e72ef4..dd12d26d 100644
---- a/org/mozilla/jss/netscape/security/provider/Sun.java
-+++ b/org/mozilla/jss/netscape/security/provider/Sun.java
-@@ -68,54 +68,11 @@ public final class Sun extends Provider {
- 
-             //	    AccessController.beginPrivileged();
- 
--            /*
--             * Signature engines
--             */
--            put("Signature.DSA", "org.mozilla.jss.netscape.security.provider.DSA");
--
--            put("Alg.Alias.Signature.SHA/DSA", "DSA");
--            put("Alg.Alias.Signature.SHA1/DSA", "DSA");
--            put("Alg.Alias.Signature.SHA-1/DSA", "DSA");
--            put("Alg.Alias.Signature.DSS", "DSA");
--            put("Alg.Alias.Signature.OID.1.3.14.3.2.13", "DSA");
--            put("Alg.Alias.Signature.OID.1.3.14.3.2.27", "DSA");
--            put("Alg.Alias.Signature.OID.1.2.840.10040.4.3", "DSA");
--            // the following are not according to our formal spec but
--            // are still supported
--            put("Alg.Alias.Signature.1.3.14.3.2.13", "DSA");
--            put("Alg.Alias.Signature.1.3.14.3.2.27", "DSA");
--            put("Alg.Alias.Signature.1.2.840.10040.4.3", "DSA");
--            put("Alg.Alias.Signature.SHAwithDSA", "DSA");
--            put("Alg.Alias.Signature.SHA1withDSA", "DSA");
--
--            /*
--             *  Key Pair Generator engines
--             */
--            put("KeyPairGenerator.DSA",
--                    "org.mozilla.jss.netscape.security.provider.DSAKeyPairGenerator");
--
--            put("Alg.Alias.KeyPairGenerator.OID.1.3.14.3.2.12", "DSA");
--            put("Alg.Alias.KeyPairGenerator.OID.1.2.840.10040.4.1", "DSA");
-             // the following are not according to our formal spec but
-             // are still supported
-             put("Alg.Alias.KeyPairGenerator.1.3.14.3.2.12", "DSA");
-             put("Alg.Alias.KeyPairGenerator.1.2.840.10040.4.1", "DSA");
- 
--            /*
--             * Digest engines
--             */
--            put("MessageDigest.MD5", "org.mozilla.jss.netscape.security.provider.MD5");
--            put("MessageDigest.SHA-1", "org.mozilla.jss.netscape.security.provider.SHA");
--
--            put("Alg.Alias.MessageDigest.SHA", "SHA-1");
--            put("Alg.Alias.MessageDigest.SHA1", "SHA-1");
--
--            /*
--             * Algorithm Parameter Generator engines
--             */
--            put("AlgorithmParameterGenerator.DSA",
--                    "org.mozilla.jss.netscape.security.provider.DSAParameterGenerator");
--
-             /*
-              * Algorithm Parameter engines
-              */
--- 
-2.21.0
-
diff --git a/SOURCES/0003-Use-specified-algorithm-for-KeyWrap.patch b/SOURCES/0003-Use-specified-algorithm-for-KeyWrap.patch
new file mode 100644
index 0000000..3f598a9
--- /dev/null
+++ b/SOURCES/0003-Use-specified-algorithm-for-KeyWrap.patch
@@ -0,0 +1,60 @@
+From 55482c8bfa0addeb9db7b590703ba3704c5db167 Mon Sep 17 00:00:00 2001
+From: Alexander Scheel <ascheel@redhat.com>
+Date: Fri, 28 Feb 2020 14:39:29 -0500
+Subject: [PATCH 2/2] Use specified algorithm for KeyWrap
+
+When the token-specified from of EncryptedPrivateKeyInfo.createPBE is
+called, it would always request DES3_CBC_PAD as the key wrapping
+algorithm, regardless of the input PBE key type. However, the other form
+(with an implicit token) was correctly handling this case.
+
+Introduces a new KeyWrapAlgorithm method to take an OBJECT_IDENTIFIER
+instead of having to convert to/from a String form.
+
+Signed-off-by: Alexander Scheel <ascheel@redhat.com>
+---
+ org/mozilla/jss/crypto/KeyWrapAlgorithm.java                | 5 ++++-
+ org/mozilla/jss/pkix/primitive/EncryptedPrivateKeyInfo.java | 4 ++--
+ 2 files changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/org/mozilla/jss/crypto/KeyWrapAlgorithm.java b/org/mozilla/jss/crypto/KeyWrapAlgorithm.java
+index 3113f614..3a106977 100644
+--- a/org/mozilla/jss/crypto/KeyWrapAlgorithm.java
++++ b/org/mozilla/jss/crypto/KeyWrapAlgorithm.java
+@@ -138,7 +138,10 @@ public class KeyWrapAlgorithm extends Algorithm {
+ 
+     public static KeyWrapAlgorithm fromOID(String wrapOID) throws NoSuchAlgorithmException {
+         OBJECT_IDENTIFIER oid = new OBJECT_IDENTIFIER(wrapOID);
++        return fromOID(oid);
++    }
+ 
++    public static KeyWrapAlgorithm fromOID(OBJECT_IDENTIFIER oid) throws NoSuchAlgorithmException {
+         if (oid.equals(AES_KEY_WRAP_PAD_OID))
+             return AES_KEY_WRAP_PAD;
+ 
+@@ -154,6 +157,6 @@ public class KeyWrapAlgorithm extends Algorithm {
+         if (oid.equals(DES_CBC_PAD_OID))
+             return DES_CBC_PAD;
+ 
+-        throw new NoSuchAlgorithmException("Unknown Algorithm for OID: " + wrapOID);
++        throw new NoSuchAlgorithmException("Unknown Algorithm for OID: " + oid);
+     }
+ }
+diff --git a/org/mozilla/jss/pkix/primitive/EncryptedPrivateKeyInfo.java b/org/mozilla/jss/pkix/primitive/EncryptedPrivateKeyInfo.java
+index ebd269f3..abfc39a7 100644
+--- a/org/mozilla/jss/pkix/primitive/EncryptedPrivateKeyInfo.java
++++ b/org/mozilla/jss/pkix/primitive/EncryptedPrivateKeyInfo.java
+@@ -337,8 +337,8 @@ public class EncryptedPrivateKeyInfo implements ASN1Value {
+             }
+         }
+ 
+-        KeyWrapper wrapper = token.getKeyWrapper(
+-                KeyWrapAlgorithm.DES3_CBC_PAD);
++        // wrap the key
++        KeyWrapper wrapper = token.getKeyWrapper(KeyWrapAlgorithm.fromOID(encAlg.toOID()));
+         wrapper.initWrap(key, params);
+         byte encrypted[] = wrapper.wrap(pri);
+ 
+-- 
+2.24.1
+
diff --git a/SOURCES/0004-JSS-CVE-2019-14823-fix.patch b/SOURCES/0004-JSS-CVE-2019-14823-fix.patch
deleted file mode 100644
index 10218a0..0000000
--- a/SOURCES/0004-JSS-CVE-2019-14823-fix.patch
+++ /dev/null
@@ -1,346 +0,0 @@
-From 233795b098a17269f8495fee312fe6df404a236d Mon Sep 17 00:00:00 2001
-From: Alexander Scheel <ascheel@redhat.com>
-Date: Wed, 4 Sep 2019 08:33:14 -0400
-Subject: [PATCH] Fix root certificate validation
-
-When the Leaf and Chain OCSP checking policy is enabled in
-CryptoManager, JSS will switch to alternative certificate verification
-logic in JSSL_DefaultCertAuthCallback. In this method, the root
-certificate was incorrectly trusted without being verified to exist in
-the trust store.
-
-This patch cleans up the logic in JSSL_verifyCertPKIX and makes it
-more explicit in addition to fixing the error.
-
-Fixes CVE-2019-14823
-
-Signed-off-by: Alexander Scheel <ascheel@redhat.com>
----
- org/mozilla/jss/ssl/common.c | 239 ++++++++++++++++++++---------------
- 1 file changed, 136 insertions(+), 103 deletions(-)
-
-diff --git a/org/mozilla/jss/ssl/common.c b/org/mozilla/jss/ssl/common.c
-index 1bbfed45..2db9fda1 100644
---- a/org/mozilla/jss/ssl/common.c
-+++ b/org/mozilla/jss/ssl/common.c
-@@ -904,7 +904,6 @@ finish:
- }
- 
- /* Get the trusted anchor for pkix */
--
- CERTCertificate *getRoot(CERTCertificate *cert,
-     SECCertUsage certUsage) 
- {
-@@ -938,79 +937,84 @@ finish:
-     return root; 
- }
- 
--/* Verify a cert using explicit PKIX call.
-- * For now only used in OCSP AIA context.
-- * The result of this call will be a full chain
-- * and leaf network AIA ocsp validation.
-- * The policy param will be used in the future to
-- * handle more scenarios.
-- */
--
--SECStatus JSSL_verifyCertPKIX(CERTCertificate *cert,
--      SECCertificateUsage certificateUsage,secuPWData *pwdata, int ocspPolicy,
--      CERTVerifyLog *log, SECCertificateUsage *usage) 
-+/* Internal helper for the below call. */
-+static SECStatus
-+JSSL_verifyCertPKIXInternal(CERTCertificate *cert,
-+    SECCertificateUsage certificateUsage, secuPWData *pwdata, int ocspPolicy,
-+    CERTVerifyLog *log, SECCertificateUsage *usage,
-+    CERTCertList *trustedCertList)
- {
--
--    /* put the first set of possible flags internally here first */
--    /* later there could be a more complete list to choose from */
--    /* support our hard core fetch aia ocsp policy for now */
--
--    static PRUint64 ocsp_Enabled_Hard_Policy_LeafFlags[2] = {
-+    /* Put the first set of possible flags internally here first. Later
-+     * there could be a more complete list to choose from; for now we only
-+     * support our hard core fetch AIA OCSP policy. Note that we disable
-+     * CRL fetching as Dogtag doesn't support it. Additionally, enable OCSP
-+     * checking on the chained CA certificates. Since NSS/PKIX's
-+     * CERT_GetClassicOCSPEnabledHardFailurePolicy doesn't do what we want,
-+     * we construct the policy ourselves. */
-+    PRUint64 ocsp_Enabled_Hard_Policy_LeafFlags[2] = {
-         /* crl */
--        0,
-+        CERT_REV_M_DO_NOT_TEST_USING_THIS_METHOD,
-         /* ocsp */
-         CERT_REV_M_TEST_USING_THIS_METHOD |
--        CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO
-+            CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO
-     };
- 
--    static PRUint64 ocsp_Enabled_Hard_Policy_ChainFlags[2] = {
-+    PRUint64 ocsp_Enabled_Hard_Policy_ChainFlags[2] = {
-         /* crl */
--        0,
-+        CERT_REV_M_DO_NOT_TEST_USING_THIS_METHOD,
-         /* ocsp */
-         CERT_REV_M_TEST_USING_THIS_METHOD |
--        CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO
-+            CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO
-     };
- 
--    static CERTRevocationMethodIndex
--        ocsp_Enabled_Hard_Policy_Method_Preference = {
--            cert_revocation_method_ocsp
--        };
--
--    static CERTRevocationFlags ocsp_Enabled_Hard_Policy = {
--    { /* leafTests */
--      2,
--      ocsp_Enabled_Hard_Policy_LeafFlags,
--      1,
--      &ocsp_Enabled_Hard_Policy_Method_Preference,
--      0 },
--    { /* chainTests */
--      2,
--      ocsp_Enabled_Hard_Policy_ChainFlags,
--      1,
--      &ocsp_Enabled_Hard_Policy_Method_Preference,
--      0 }
-+    CERTRevocationMethodIndex ocsp_Enabled_Hard_Policy_Method_Preference[1] = {
-+        cert_revocation_method_ocsp
-     };
- 
--    /* for future expansion */
-+    CERTRevocationFlags ocsp_Enabled_Hard_Policy = {
-+        /* CERTRevocationTests - leafTests */
-+        {
-+            /* number_of_defined_methods */
-+            2,
-+            /* cert_rev_flags_per_method */
-+            ocsp_Enabled_Hard_Policy_LeafFlags,
-+            /* number_of_preferred_methods */
-+            1,
-+            /* preferred_methods */
-+            ocsp_Enabled_Hard_Policy_Method_Preference,
-+            /* cert_rev_method_independent_flags */
-+            0
-+        },
-+        /* CERTRevocationTests - chainTests */
-+        {
-+            /* number_of_defined_methods */
-+            2,
-+            /* cert_rev_flags_per_method */
-+            ocsp_Enabled_Hard_Policy_ChainFlags,
-+            /* number_of_preferred_methods */
-+            1,
-+            /* preferred_methods */
-+            ocsp_Enabled_Hard_Policy_Method_Preference,
-+            /* cert_rev_method_independent_flags */
-+            0
-+        }
-+    };
- 
--    CERTValOutParam cvout[20] = {{0}};
--    CERTValInParam cvin[20] = {{0}};
-+    /* The size of these objects are defined here based upon maximum possible
-+     * inputs. A dynamic allocation could reallocate based upon actual usage,
-+     * however this would affect the size by at most one or two. Note that,
-+     * due to the required usage of cert_pi_end/cert_po_end, these sizes are
-+     * inflated by one. */
-+    CERTValOutParam cvout[3] = {{0}};
-+    CERTValInParam cvin[6] = {{0}};
- 
-+    int usageIndex = -1;
-     int inParamIndex = 0;
-     int outParamIndex = 0;
--    CERTRevocationFlags *rev = NULL;
--
--    CERTCertList *trustedCertList = NULL;
--
--    PRBool fetchCerts = PR_FALSE;
- 
--    SECCertUsage certUsage = certUsageSSLClient /* 0 */;
--    
-     SECStatus res =  SECFailure;
- 
--    CERTCertificate *root = NULL;
--
--    if(cert == NULL) {
-+    if (cert == NULL) {
-         goto finish;
-     }
- 
-@@ -1018,93 +1022,122 @@ SECStatus JSSL_verifyCertPKIX(CERTCertificate *cert,
-         goto finish;
-     }
- 
--    /* Force the strict ocsp network check on chain
--       and leaf.
--    */
--
--    fetchCerts = PR_TRUE;   
--    rev = &ocsp_Enabled_Hard_Policy;
--
--    /* fetch aia over net */
-- 
-+    /* Enable live AIA fetching over the network. */
-     cvin[inParamIndex].type = cert_pi_useAIACertFetch;
--    cvin[inParamIndex].value.scalar.b = fetchCerts;
--    inParamIndex++; 
--
--    /* time */
-+    cvin[inParamIndex].value.scalar.b = PR_TRUE;
-+    inParamIndex++;
- 
-+    /* By setting the time to zero, we choose the current time when the
-+     * check is performed. */
-     cvin[inParamIndex].type = cert_pi_date;
--    cvin[inParamIndex].value.scalar.time = PR_Now();
-+    cvin[inParamIndex].value.scalar.time = 0;
-     inParamIndex++;
- 
--    /* flags */
--
-+    /* Force the strict OCSP check on both the leaf and its chain. */
-     cvin[inParamIndex].type = cert_pi_revocationFlags;
--    cvin[inParamIndex].value.pointer.revocation = rev;
-+    cvin[inParamIndex].value.pointer.revocation = &ocsp_Enabled_Hard_Policy;
-     inParamIndex++;
- 
--    /* establish trust anchor */
--
--    /* We need to convert the SECCertificateUsage to a SECCertUsage to obtain
--     * the root.
--    */
--
--    SECCertificateUsage testUsage = certificateUsage;
--    while (0 != (testUsage = testUsage >> 1)) { certUsage++; }
--
--    root = getRoot(cert,certUsage);
--
--    /* Try to add the root as the trust anchor so all the
--       other memebers of the ca chain will get validated.
--    */
--
--    if( root != NULL ) {
--        trustedCertList = CERT_NewCertList();
--        CERT_AddCertToListTail(trustedCertList, root);        
--
-+    /* Establish a trust anchor if it is passed to us. NOTE: this trust anchor
-+     * must previously be validated before it is passed to us here. */
-+    if (trustedCertList != NULL) {
-         cvin[inParamIndex].type = cert_pi_trustAnchors;
-         cvin[inParamIndex].value.pointer.chain = trustedCertList;
--
-         inParamIndex++;
-     }
- 
-+    /* Done establishing input parameters. */
-     cvin[inParamIndex].type = cert_pi_end;
- 
--    if(log != NULL) {
-+    /* When we need to log rationale for failure, pass it as an output
-+     * parameter. */
-+    if (log != NULL) {
-         cvout[outParamIndex].type = cert_po_errorLog;
-         cvout[outParamIndex].value.pointer.log = log;
-         outParamIndex ++;
-     }
- 
--    int usageIndex = 0;
--    if(usage != NULL) {
-+    /* When we need to inquire about the resulting certificate usage, pass it
-+     * here. */
-+    if (usage != NULL) {
-         usageIndex = outParamIndex;
-         cvout[outParamIndex].type = cert_po_usages;
-         cvout[outParamIndex].value.scalar.usages = 0;
-         outParamIndex ++;
-     }
- 
-+    /* Done establishing output parameters. */
-     cvout[outParamIndex].type = cert_po_end;
- 
-+    /* Call into NSS's PKIX library to validate our certificate. */
-     res = CERT_PKIXVerifyCert(cert, certificateUsage, cvin, cvout, &pwdata);
- 
- finish:
--    /* clean up any trusted cert list */
--
-+    /* Clean up any certificates in the trusted certificate list. This was
-+     * a passed input parameter, but by taking ownership of it and clearing it,
-+     * we enable tail calls to this function. */
-     if (trustedCertList) {
-+        /* CERT_DestroyCertList destroys interior certs for us. */
-         CERT_DestroyCertList(trustedCertList);
-         trustedCertList = NULL;
-     }
- 
--    /* CERT_DestroyCertList destroys interior certs for us. */
--
--    if(root) {
--       root = NULL;
--    }
--
--    if(res == SECSuccess && usage) {
-+    if (res == SECSuccess && usage && usageIndex != -1) {
-         *usage = cvout[usageIndex].value.scalar.usages;
-     }
- 
-     return res;
- }
-+
-+/* Verify a cert using an explicit PKIX call. For now only perform this call
-+ * when the OCSP policy is set to leaf and chain. Performs a blocking, online
-+ * OCSP status refresh. The result of this call will be a full-chain OCSP
-+ * validation.
-+ *
-+ * In the future, we'll use ocspPolicy to condition around additional policies
-+ * and handle them all with this method (and a call to PKIX).
-+ *
-+ * Note that this currently requires the certificate to be added directly
-+ * to the NSS DB. We can't otherwise validate against root certificates in
-+ * the default NSS DB.
-+ */
-+SECStatus JSSL_verifyCertPKIX(CERTCertificate *cert,
-+      SECCertificateUsage certificateUsage, secuPWData *pwdata, int ocspPolicy,
-+      CERTVerifyLog *log, SECCertificateUsage *usage)
-+{
-+    SECCertUsage certUsage = certUsageSSLClient /* 0 */;
-+
-+    /* We need to convert the SECCertificateUsage to a SECCertUsage to obtain
-+     * the root.
-+     */
-+
-+    SECCertificateUsage testUsage = certificateUsage;
-+    while (0 != (testUsage = testUsage >> 1)) { certUsage++; }
-+
-+    CERTCertificate *root = getRoot(cert, certUsage);
-+
-+    // Two cases: either the root is present, or it isn't.
-+    if (root == NULL) {
-+        /* In this case, we've had a hard time finding the root. In all
-+         * likelihood, the following call will fail to validate the end cert
-+         * as well and thus fail to validate. I don't believe there's a risk
-+         * in trying it however. */
-+        return JSSL_verifyCertPKIXInternal(cert, certificateUsage, pwdata,
-+                                           ocspPolicy, log, usage, NULL);
-+    } else {
-+        /* In this case, we've found the root certificate. Before passing it
-+         * to the leaf, explicitly validate it with strict OCSP checking. Then
-+         * validate the leaf certificate with a known and trusted root
-+         * certificate. */
-+        SECStatus ret = JSSL_verifyCertPKIXInternal(root, certificateUsageSSLCA,
-+            pwdata, ocspPolicy, log, usage, NULL);
-+        if (ret != SECSuccess) {
-+            return ret;
-+        }
-+
-+        CERTCertList *rootList = CERT_NewCertList();
-+        CERT_AddCertToListTail(rootList, root);
-+        return JSSL_verifyCertPKIXInternal(cert, certificateUsage, pwdata,
-+                                           ocspPolicy, log, usage, rootList);
-+    }
-+}
--- 
-2.21.0
-
diff --git a/SOURCES/0004-Remove-token-key-checks.patch b/SOURCES/0004-Remove-token-key-checks.patch
new file mode 100644
index 0000000..7353cce
--- /dev/null
+++ b/SOURCES/0004-Remove-token-key-checks.patch
@@ -0,0 +1,112 @@
+From a3a91a8e85d7f05de3c85b0ae6ad1c80cf7c5b55 Mon Sep 17 00:00:00 2001
+From: Alexander Scheel <ascheel@redhat.com>
+Date: Tue, 17 Mar 2020 12:54:49 -0400
+Subject: [PATCH 1/2] Remove token key checks
+
+Previously we enforced strict token key matching: the primary key used
+for the operation must strictly reside on the current PKCS#11 token,
+otherwise JSS would bail. However, NSS has the ability to move the key
+to whichever token best supports the given operation. This means that
+we'd prematurely bail when the operation would succeed if it were
+actually executed. By removing these checks, we still leave the ability
+to generate keys on a specific token, we just allow them to be used on
+whatever token supports the given operation (and the key is allowed to
+be moved to).
+
+Signed-off-by: Alexander Scheel <ascheel@redhat.com>
+---
+ org/mozilla/jss/pkcs11/PK11Cipher.java        |  4 ----
+ org/mozilla/jss/pkcs11/PK11KeyWrapper.java    | 22 -------------------
+ org/mozilla/jss/pkcs11/PK11MessageDigest.java |  7 ------
+ 3 files changed, 33 deletions(-)
+
+diff --git a/org/mozilla/jss/pkcs11/PK11Cipher.java b/org/mozilla/jss/pkcs11/PK11Cipher.java
+index 81b600a4..aac411a4 100644
+--- a/org/mozilla/jss/pkcs11/PK11Cipher.java
++++ b/org/mozilla/jss/pkcs11/PK11Cipher.java
+@@ -262,10 +262,6 @@ public final class PK11Cipher extends org.mozilla.jss.crypto.Cipher {
+         if( key==null ) {
+             throw new InvalidKeyException("Key is null");
+         }
+-        if( ! key.getOwningToken().equals(token) ) {
+-            throw new InvalidKeyException("Key does not reside on the "+
+-                "current token");
+-        }
+         if( ! (key instanceof PK11SymKey) ) {
+             throw new InvalidKeyException("Key is not a PKCS #11 key");
+         }
+diff --git a/org/mozilla/jss/pkcs11/PK11KeyWrapper.java b/org/mozilla/jss/pkcs11/PK11KeyWrapper.java
+index 28840a87..eee2984d 100644
+--- a/org/mozilla/jss/pkcs11/PK11KeyWrapper.java
++++ b/org/mozilla/jss/pkcs11/PK11KeyWrapper.java
+@@ -168,10 +168,6 @@ public final class PK11KeyWrapper implements KeyWrapper {
+             throw new InvalidKeyException("Key is null");
+         }
+         try {
+-            if( ! key.getOwningToken().equals(token) ) {
+-                throw new InvalidKeyException("Key does not reside on the current token: key owning token="+
+-                    key.getOwningToken().getName());
+-            }
+             if( ! (key instanceof PK11SymKey) ) {
+                 throw new InvalidKeyException("Key is not a PKCS #11 key");
+             }
+@@ -196,10 +192,6 @@ public final class PK11KeyWrapper implements KeyWrapper {
+         if( key==null ) {
+             throw new InvalidKeyException("Key is null");
+         }
+-        if( ! key.getOwningToken().equals(token) ) {
+-            throw new InvalidKeyException("Key does not reside on the "+
+-                "current token");
+-        }
+         if( ! (key instanceof PK11PrivKey) ) {
+             throw new InvalidKeyException("Key is not a PKCS #11 key");
+         }
+@@ -299,13 +291,6 @@ public final class PK11KeyWrapper implements KeyWrapper {
+             throw new InvalidKeyException("key to be wrapped is not a "+
+                 "PKCS #11 key");
+         }
+-/* NSS is capable of moving keys appropriately,
+-   so this call is prematurely bailing
+-        if( ! symKey.getOwningToken().equals(token) ) {
+-            throw new InvalidKeyException("key to be wrapped does not live"+
+-                " on the same token as the wrapping key");
+-        }
+-*/
+     }
+ 
+     /**
+@@ -320,13 +305,6 @@ public final class PK11KeyWrapper implements KeyWrapper {
+             throw new InvalidKeyException("key to be wrapped is not a "+
+                 "PKCS #11 key");
+         }
+-/* NSS is capable of moving keys appropriately,
+-   so this call is prematurely bailing
+-        if( ! privKey.getOwningToken().equals(token) ) {
+-            throw new InvalidKeyException("key to be wrapped does not live"+
+-                " on the same token as the wrapping key");
+-        }
+-*/
+     }
+ 
+     /**
+diff --git a/org/mozilla/jss/pkcs11/PK11MessageDigest.java b/org/mozilla/jss/pkcs11/PK11MessageDigest.java
+index cd732788..7a1a6dad 100644
+--- a/org/mozilla/jss/pkcs11/PK11MessageDigest.java
++++ b/org/mozilla/jss/pkcs11/PK11MessageDigest.java
+@@ -47,13 +47,6 @@ public final class PK11MessageDigest extends JSSMessageDigest {
+         }
+ 
+         hmacKey = (PK11SymKey) key;
+-
+-        if( ! key.getOwningToken().equals(token) ) {
+-            hmacKey = null;
+-            throw new InvalidKeyException(
+-                "HMAC key does not live on the same token as this digest");
+-        }
+-
+         this.digestProxy = initHMAC(token, alg, hmacKey);
+     }
+ 
+-- 
+2.25.1
+
diff --git a/SOURCES/0005-Add-helper-to-run-a-single-test-case.patch b/SOURCES/0005-Add-helper-to-run-a-single-test-case.patch
deleted file mode 100644
index 586a687..0000000
--- a/SOURCES/0005-Add-helper-to-run-a-single-test-case.patch
+++ /dev/null
@@ -1,91 +0,0 @@
-From 7d1c481e947edf0786223ef43a359c8d5771a214 Mon Sep 17 00:00:00 2001
-From: Alexander Scheel <ascheel@redhat.com>
-Date: Wed, 28 Aug 2019 09:23:41 -0400
-Subject: [PATCH 1/3] Add helper to run a single test case
-
-run_test.sh.in is templated by CMake to build/run_test.sh, fully
-configured to your test execution environment. In particular, it writes
-the classpath and loads the JSS native library.
-
-Signed-off-by: Alexander Scheel <ascheel@redhat.com>
----
- cmake/JSSConfig.cmake | 29 +++++++++++++++++++----------
- tools/run_test.sh.in  | 15 +++++++++++++++
- 2 files changed, 34 insertions(+), 10 deletions(-)
- create mode 100755 tools/run_test.sh.in
-
-diff --git a/cmake/JSSConfig.cmake b/cmake/JSSConfig.cmake
-index 27b2a9bf..6295a6e3 100644
---- a/cmake/JSSConfig.cmake
-+++ b/cmake/JSSConfig.cmake
-@@ -13,6 +13,9 @@ macro(jss_config)
- 
-     # Configure java-related flags
-     jss_config_java()
-+
-+    # Template auto-generated files
-+    jss_config_template()
- endmacro()
- 
- macro(jss_config_version MAJOR MINOR PATCH BETA)
-@@ -45,16 +48,6 @@ macro(jss_config_version MAJOR MINOR PATCH BETA)
-         set(JSS_VERSION "${JSS_VERSION} beta ${JSS_VERSION_BETA}")
-         set(JSS_VERSION_STR "${JSS_VERSION_STR}_b${JSS_VERSION_BETA}")
-     endif()
--
--    # Template files
--    configure_file(
--        "${PROJECT_SOURCE_DIR}/org/mozilla/jss/util/jssver.h.in"
--        "${PROJECT_SOURCE_DIR}/org/mozilla/jss/util/jssver.h"
--    )
--    configure_file(
--        "${PROJECT_SOURCE_DIR}/lib/MANIFEST.MF.in"
--        "${CMAKE_BINARY_DIR}/MANIFEST.MF"
--    )
- endmacro()
- 
- macro(jss_config_outputs)
-@@ -326,3 +319,19 @@ macro(jss_config_java)
-     math(EXPR JSS_TEST_PORT_CLIENTAUTH ${JSS_BASE_PORT}+0)
-     math(EXPR JSS_TEST_PORT_CLIENTAUTH_FIPS ${JSS_BASE_PORT}+1)
- endmacro()
-+
-+macro(jss_config_template)
-+    # Template files
-+    configure_file(
-+        "${PROJECT_SOURCE_DIR}/org/mozilla/jss/util/jssver.h.in"
-+        "${PROJECT_SOURCE_DIR}/org/mozilla/jss/util/jssver.h"
-+    )
-+    configure_file(
-+        "${PROJECT_SOURCE_DIR}/lib/MANIFEST.MF.in"
-+        "${CMAKE_BINARY_DIR}/MANIFEST.MF"
-+    )
-+    configure_file(
-+        "${PROJECT_SOURCE_DIR}/tools/run_test.sh.in"
-+        "${CMAKE_BINARY_DIR}/run_test.sh"
-+    )
-+endmacro()
-diff --git a/tools/run_test.sh.in b/tools/run_test.sh.in
-new file mode 100755
-index 00000000..60233c05
---- /dev/null
-+++ b/tools/run_test.sh.in
-@@ -0,0 +1,15 @@
-+#!/bin/bash
-+
-+# This utility gets templated to build/run_test.sh to help with running a
-+# single test after building JSS. This gives the caller more flexibility
-+# with command line arguments and ensures that the correct build artifacts
-+# get used.
-+
-+export LD_LIBRARY_PATH="${CMAKE_BINARY_DIR}"
-+
-+if [ "$1" == "--gdb" ]; then
-+    shift
-+    gdb --args "${Java_JAVA_EXECUTABLE}" -classpath "${TEST_CLASSPATH}" -ea -Djava.library.path="${CMAKE_BINARY_DIR}" "$@"
-+else
-+    "${Java_JAVA_EXECUTABLE}" -classpath "${TEST_CLASSPATH}" -ea -Djava.library.path="${CMAKE_BINARY_DIR}" "$@"
-+fi
--- 
-2.21.0
-
diff --git a/SOURCES/0006-Add-script-to-add-common-root-CAs.patch b/SOURCES/0006-Add-script-to-add-common-root-CAs.patch
deleted file mode 100644
index cde61fe..0000000
--- a/SOURCES/0006-Add-script-to-add-common-root-CAs.patch
+++ /dev/null
@@ -1,59 +0,0 @@
-From 61985f642b0b5cc75fc3f254ef6c99aeb56acbe2 Mon Sep 17 00:00:00 2001
-From: Alexander Scheel <ascheel@redhat.com>
-Date: Thu, 29 Aug 2019 16:14:08 -0400
-Subject: [PATCH 2/3] Add script to add common root CAs
-
-When given an NSS DB, common_roots.sh uses the trust command to extract
-the root CAs trusted by the local system and add them to said NSS DB.
-
-Signed-off-by: Alexander Scheel <ascheel@redhat.com>
----
- tools/common_roots.sh | 36 ++++++++++++++++++++++++++++++++++++
- 1 file changed, 36 insertions(+)
- create mode 100755 tools/common_roots.sh
-
-diff --git a/tools/common_roots.sh b/tools/common_roots.sh
-new file mode 100755
-index 00000000..97341c4c
---- /dev/null
-+++ b/tools/common_roots.sh
-@@ -0,0 +1,36 @@
-+#!/bin/bash
-+
-+# This script reads the contents of the OS CA bundle store,
-+#   /usr/share/pki/ca-trust-source/ca-bundle.trust.p11-kit
-+# and places the contained CAs into the specified NSS DB.
-+#
-+# This NSS DB is used by various JSS tests that aren't enabled
-+# by default because they require an active internet connection.
-+
-+nssdb="$1"
-+
-+if [ -z "$nssdb" ] && [ -e "build" ]; then
-+    nssdb="build/results/cadb"
-+elif [ -z "$nssdb" ] && [ -e "../build" ]; then
-+    nssdb="../build/results/cadb"
-+else
-+    echo "Must provide path to NSS DB!" 1>&2
-+    exit 1
-+fi
-+
-+if [ -e "$nssdb" ]; then
-+    rm -rf "$nssdb"
-+fi
-+
-+mkdir -p "$nssdb"
-+echo "" > "$nssdb/password.txt"
-+certutil -N -d "$nssdb" -f "$nssdb/password.txt"
-+
-+trust extract --format=pem-bundle  --filter=ca-anchors "$nssdb/complete.pem"
-+
-+# From: https://serverfault.com/questions/391396/how-to-split-a-pem-file
-+csplit -f "$nssdb/individual-" "$nssdb/complete.pem" '/-----BEGIN CERTIFICATE-----/' '{*}'
-+
-+for cert in "$nssdb"/individual*; do
-+    certutil -A -a -i "$cert" -n "$cert" -t CT,C,C -d "$nssdb" -f "$nssdb/password.txt"
-+done
--- 
-2.21.0
-
diff --git a/SOURCES/0007-Add-optional-test-case-against-badssl.com.patch b/SOURCES/0007-Add-optional-test-case-against-badssl.com.patch
deleted file mode 100644
index ba155f1..0000000
--- a/SOURCES/0007-Add-optional-test-case-against-badssl.com.patch
+++ /dev/null
@@ -1,233 +0,0 @@
-From 7b4c0fa04f5e4469fc8bc442c9f12f975c5e1610 Mon Sep 17 00:00:00 2001
-From: Alexander Scheel <ascheel@redhat.com>
-Date: Wed, 28 Aug 2019 09:23:41 -0400
-Subject: [PATCH 3/3] Add optional test case against badssl.com
-
-badssl.com maintains a number of subdomains with valid and invalid TLS
-configurations. A number of these test certificates which fail in
-certain scenarios (revoked, expired, etc). Add a test runner which
-validates SSLSocket's implementation against badssl.com.
-
-Signed-off-by: Alexander Scheel <ascheel@redhat.com>
----
- org/mozilla/jss/tests/BadSSL.java | 208 ++++++++++++++++++++++++++++++
- 1 file changed, 208 insertions(+)
- create mode 100644 org/mozilla/jss/tests/BadSSL.java
-
-diff --git a/org/mozilla/jss/tests/BadSSL.java b/org/mozilla/jss/tests/BadSSL.java
-new file mode 100644
-index 00000000..60bfe820
---- /dev/null
-+++ b/org/mozilla/jss/tests/BadSSL.java
-@@ -0,0 +1,208 @@
-+package org.mozilla.jss.tests;
-+
-+import org.mozilla.jss.CryptoManager;
-+
-+import org.mozilla.jss.ssl.SSLSocket;
-+import org.mozilla.jss.ssl.SSLSocketException;
-+
-+import org.mozilla.jss.util.NativeErrcodes;
-+
-+/**
-+ * The BadSSL test case maintains an internal mapping from badssl.com
-+ * subdomains to expected exceptions and validates they occur.
-+ *
-+ * Since badssl.com offers no guaranteed SLA or availability, we likely
-+ * shouldn't add this site to automated tests.
-+ */
-+
-+public class BadSSL {
-+    public static void main(String[] args) throws Exception {
-+        boolean ocsp = false;
-+
-+        if (args.length < 1) {
-+            System.out.println("Usage: BadSSL nssdb [LEAF_AND_CHAIN]");
-+            return;
-+        }
-+
-+        if (args.length >= 2 && args[1].equals("LEAF_AND_CHAIN")) {
-+            System.out.println("Enabling leaf and chain policy...");
-+            ocsp = true;
-+        }
-+
-+        CryptoManager.initialize(args[0]);
-+        CryptoManager cm = CryptoManager.getInstance();
-+
-+        if (ocsp) {
-+            cm.setOCSPPolicy(CryptoManager.OCSPPolicy.LEAF_AND_CHAIN);
-+        }
-+
-+
-+        // Test cases which should fail due to various certificate errors.
-+        testExpired();
-+        testWrongHost();
-+        testSelfSigned();
-+        testUntrustedRoot();
-+
-+        // The following test cases depend on crypto-policies or local NSS
-+        // configuration.
-+        testSHA1();
-+        testRC4MD5();
-+        testRC4();
-+        test3DES();
-+        testNULL();
-+
-+        // The following test cases depend on OCSP being enabled.
-+        if (ocsp) {
-+            testRevoked();
-+        }
-+
-+        // Test cases which should pass given the correct root certs.
-+        testSHA256();
-+        testSHA384();
-+        testSHA512();
-+
-+        testECC256();
-+        testECC384();
-+
-+        testRSA2048();
-+        testRSA4096();
-+        testRSA8192();
-+
-+        testExtendedValidation();
-+    }
-+
-+    /* Test cases whose handshakes should fail below. */
-+
-+    public static void testExpired() throws Exception {
-+        testHelper("expired.badssl.com", 443, new String[]{ "(-8181)", "has expired" });
-+    }
-+
-+    public static void testWrongHost() throws Exception {
-+        testHelper("wrong.host.badssl.com", 443, new String[]{ "(-12276)", "domain name does not match" });
-+    }
-+
-+    public static void testSelfSigned() throws Exception {
-+        testHelper("self-signed.badssl.com", 443, new String[]{ "(-8101)", "(-8156)", "type not approved", "issuer certificate is invalid" });
-+    }
-+
-+    public static void testUntrustedRoot() throws Exception {
-+        testHelper("untrusted-root.badssl.com", 443, new String[]{ "(-8172)", "certificate issuer has been marked as not trusted" });
-+    }
-+
-+    public static void testRevoked() throws Exception {
-+        testHelper("revoked.badssl.com", 443, new String[]{ "(-8180)", "has been revoked" });
-+    }
-+
-+    public static void testSHA1() throws Exception {
-+        testHelper("sha1-intermediate.badssl.com", 443, new String[] { "(-12286)", "Cannot communicate securely" });
-+    }
-+
-+    public static void testRC4MD5() throws Exception {
-+        testHelper("rc4-md5.badssl.com", 443, new String[] { "(-12286)", "Cannot communicate securely" });
-+    }
-+
-+    public static void testRC4() throws Exception {
-+        testHelper("rc4.badssl.com", 443, new String[] { "(-12286)", "Cannot communicate securely" });
-+    }
-+
-+    public static void test3DES() throws Exception {
-+        testHelper("3des.badssl.com", 443, new String[] { "(-12286)", "Cannot communicate securely" });
-+    }
-+
-+    public static void testNULL() throws Exception {
-+        testHelper("null.badssl.com", 443, new String[] { "(-12286)", "Cannot communicate securely" });
-+    }
-+
-+    /* Test cases which should handshake successfully below. */
-+
-+    public static void testSHA256() throws Exception {
-+        testHelper("sha256.badssl.com", 443);
-+    }
-+
-+    public static void testSHA384() throws Exception {
-+        testHelper("sha384.badssl.com", 443);
-+    }
-+
-+    public static void testSHA512() throws Exception {
-+        testHelper("sha512.badssl.com", 443);
-+    }
-+
-+    public static void testECC256() throws Exception {
-+        testHelper("ecc256.badssl.com", 443);
-+    }
-+
-+    public static void testECC384() throws Exception {
-+        testHelper("ecc384.badssl.com", 443);
-+    }
-+
-+    public static void testRSA2048() throws Exception {
-+        testHelper("rsa2048.badssl.com", 443);
-+    }
-+
-+    public static void testRSA4096() throws Exception {
-+        testHelper("rsa4096.badssl.com", 443);
-+    }
-+
-+    public static void testRSA8192() throws Exception {
-+        testHelper("rsa8192.badssl.com", 443);
-+    }
-+
-+    public static void testExtendedValidation() throws Exception {
-+        testHelper("extended-validation.badssl.com", 443);
-+    }
-+
-+    /* Test case helpers. */
-+
-+    public static void testHelper(String host, int port) throws Exception {
-+        testSite(host, port);
-+        System.out.println("\t...ok");
-+    }
-+
-+    public static void testHelper(String host, int port, String[] substrs) throws Exception {
-+        try {
-+            testSite(host, port);
-+        } catch (SSLSocketException sse) {
-+            String actual = sse.getMessage().toLowerCase();
-+
-+            for (String expected : substrs) {
-+                if (actual.contains(expected.toLowerCase())) {
-+                    System.out.println("\t...got expected error message.");
-+                    return;
-+                }
-+            }
-+
-+            System.err.println("\tUnexpected error message: " + actual);
-+            throw sse;
-+        }
-+
-+        throw new RuntimeException("Expected to get an exception, but didn't!");
-+    }
-+
-+    public static void testHelper(String host, int port, int[] codes) throws Exception {
-+        try {
-+            testSite(host, port);
-+        } catch (SSLSocketException sse) {
-+            int actual = sse.getErrcode();
-+            for (int expected : codes) {
-+                if (actual == expected) {
-+                    System.out.println("\t...got expected error code.");
-+                    return;
-+                }
-+            }
-+
-+            System.err.println("\tUnexpected error code: " + actual);
-+            throw sse;
-+        }
-+
-+        throw new RuntimeException("Expected to get an exception, but didn't!");
-+    }
-+
-+    public static void testSite(String host, int port) throws Exception {
-+        System.out.println("Testing connection to " + host + ":" + port);
-+        SSLSocket sock = new SSLSocket(host, 443);
-+        sock.forceHandshake();
-+        sock.shutdownOutput();
-+        sock.shutdownInput();
-+        sock.close();
-+    }
-+}
--- 
-2.21.0
-
diff --git a/SPECS/jss.spec b/SPECS/jss.spec
index 330bc8d..87baafc 100644
--- a/SPECS/jss.spec
+++ b/SPECS/jss.spec
@@ -6,8 +6,8 @@ Summary:        Java Security Services (JSS)
 URL:            http://www.dogtagpki.org/wiki/JSS
 License:        MPLv1.1 or GPLv2+ or LGPLv2+
 
-Version:        4.6.0
-Release:        5%{?_timestamp}%{?_commit_id}%{?dist}
+Version:        4.6.2
+Release:        4%{?_timestamp}%{?_commit_id}%{?dist}
 # global         _phase -a1
 
 # To generate the source tarball:
@@ -25,13 +25,10 @@ Source:         https://github.com/dogtagpki/%{name}/archive/v%{version}%{?_phas
 #     <version tag> \
 #     > jss-VERSION-RELEASE.patch
 # Patch: jss-VERSION-RELEASE.patch
-Patch1:         0001-Disable-buffer-based-tests.patch
-Patch2:         0002-Support-LD_FLAGS-from-environment.patch
-Patch3:         0003-Remove-legacy-DSA-implementation.patch
-Patch4:         0004-JSS-CVE-2019-14823-fix.patch
-Patch5:         0005-Add-helper-to-run-a-single-test-case.patch
-Patch6:         0006-Add-script-to-add-common-root-CAs.patch
-Patch7:         0007-Add-optional-test-case-against-badssl.com.patch
+Patch0: 0001-Fix-NativeProxy-reference-tracker.patch
+Patch1: 0002-Fix-swapped-parameter-names-with-PBE.patch
+Patch3: 0003-Use-specified-algorithm-for-KeyWrap.patch
+Patch4: 0004-Remove-token-key-checks.patch
 
 ################################################################################
 # Build Dependencies
@@ -88,7 +85,6 @@ This only works with gcj. Other JREs require that JCE providers be signed.
 ################################################################################
 
 Summary:        Java Security Services (JSS) Javadocs
-Group:          Documentation
 Requires:       jss = %{version}-%{release}
 
 %description javadoc
@@ -113,6 +109,9 @@ export BUILD_OPT=1
 CFLAGS="-g $RPM_OPT_FLAGS"
 export CFLAGS
 
+# Check if we're in FIPS mode
+modutil -dbdir /etc/pki/nssdb -chkfips true | grep -q enabled && export FIPS_ENABLED=1
+
 # The Makefile is not thread-safe
 rm -rf build && mkdir -p build && cd build
 %cmake \
@@ -164,14 +163,24 @@ cp -p *.txt $RPM_BUILD_ROOT%{_javadocdir}/%{name}-%{version}
 
 ################################################################################
 %changelog
+* Mon Mar 23 2020 Red Hat PKI Team <rhcs-maint@redhat.com> 4.6.2-4
+- Red Hat Bugzilla #1807371 - KRA-HSM: Async and sync key recovery using kra agent web is failing
+
+* Mon Mar 02 2020 Red Hat PKI Team <rhcs-maint@redhat.com> 4.6.2-3
+- Red Hat Bugzilla #1807371 - KRA-HSM: Async and sync key recovery using kra agent web is failing
+
+* Tue Oct 29 2019 Red Hat PKI Team <rhcs-maint@redhat.com> 4.6.2-2
+- Red Hat Bugzilla #1730767 - JSS: Wrap NSS CMAC + KDF implementations
+- Rebased to JSS 4.6.2
+
 * Wed Sep 11 2019 Red Hat PKI Team <rhcs-maint@redhat.com> 4.6.0-5
-- Bugzilla #1747987 - CVE 2019-14823 jss: OCSP policy "Leaf and Chain" implicitly trusts the root certificate
+- Red Hat Bugzilla #1747987 - CVE 2019-14823 jss: OCSP policy "Leaf and Chain" implicitly trusts the root certificate
 
 * Wed Aug 14 2019 Red Hat PKI Team <rhcs-maint@redhat.com> 4.6.0-4
 - Red Hat Bugzilla #1698059 - pki-core implements crypto
 
 * Tue Jul 16 2019 Red Hat PKI Team <rhcs-maint@redhat.com> 4.6.0-3
-- Red Hat Bugilla #1721135 - JSS - LD_FLAGS support
+- Red Hat Bugzilla #1721135 - JSS - LD_FLAGS support
 
 * Wed Jun 12 2019 Red Hat PKI Team <rhcs-maint@redhat.com> 4.6.0-2
 - Minor updates to release