Blame SOURCES/pki-core-Make-PKCS12-files-compatible-with-PBES2.patch

3fd438
From 137832b2892dfc596ed067a86242d341f2c325e7 Mon Sep 17 00:00:00 2001
3fd438
From: Fraser Tweedale <ftweedal@redhat.com>
3fd438
Date: Thu, 14 Sep 2017 12:22:47 +1000
3fd438
Subject: [PATCH] Make PKCS #12 files compatible with OpenSSL, NSS >= 3.31
3fd438
3fd438
For compatibility with OpenSSL and NSS >= 3.31, the passphrase must
3fd438
not be BMPString-encoded when non-PKCS #12 PBE schemes such as
3fd438
PBES2.
3fd438
3fd438
Fixes: https://pagure.io/dogtagpki/issue/2809
3fd438
3fd438
Change-Id: Ic78ad337ac0b9b2f5d2e75581cc0ee55e6d82782
3fd438
(cherry picked from commit ed5cccefebf98e588a5385191e43f727349b54a9)
3fd438
---
3fd438
 base/kra/src/com/netscape/kra/RecoveryService.java | 26 +++++++++++++++----
3fd438
 .../cms/servlet/csadmin/ConfigurationUtils.java    | 15 ++++++++---
3fd438
 .../src/netscape/security/pkcs/PKCS12Util.java     | 29 ++++++++++++++++++----
3fd438
 3 files changed, 57 insertions(+), 13 deletions(-)
3fd438
3fd438
diff --git a/base/kra/src/com/netscape/kra/RecoveryService.java b/base/kra/src/com/netscape/kra/RecoveryService.java
3fd438
index a7d639208..0d293e411 100644
3fd438
--- a/base/kra/src/com/netscape/kra/RecoveryService.java
3fd438
+++ b/base/kra/src/com/netscape/kra/RecoveryService.java
3fd438
@@ -508,10 +508,21 @@ public class RecoveryService implements IService {
3fd438
                 }
3fd438
             } else {
3fd438
                 byte[] epkiBytes = ct.getCryptoStore().getEncryptedPrivateKeyInfo(
3fd438
+                    /* For compatibility with OpenSSL and NSS >= 3.31,
3fd438
+                     * do not BMPString-encode the passphrase when using
3fd438
+                     * non-PKCS #12 PBE scheme such as PKCS #5 PBES2.
3fd438
+                     *
3fd438
+                     * The resulting PKCS #12 is not compatible with
3fd438
+                     * NSS < 3.31.
3fd438
+                     */
3fd438
+                    null /* passConverter */,
3fd438
+                    pass,
3fd438
                     /* NSS has a bug that causes any AES CBC encryption
3fd438
                      * to use AES-256, but AlgorithmID contains chosen
3fd438
                      * alg.  To avoid mismatch, use AES_256_CBC. */
3fd438
-                    passConverter, pass, EncryptionAlgorithm.AES_256_CBC, 0, priKey);
3fd438
+                    EncryptionAlgorithm.AES_256_CBC,
3fd438
+                    0 /* iterations (use default) */,
3fd438
+                    priKey);
3fd438
                 CMS.debug("RecoverService: createPFX() getEncryptedPrivateKeyInfo() returned");
3fd438
                 if (epkiBytes == null) {
3fd438
                     CMS.debug("RecoverService: createPFX() epkiBytes null");
3fd438
@@ -646,8 +657,6 @@ public class RecoveryService implements IService {
3fd438
                             pwd.toCharArray());
3fd438
 
3fd438
             SEQUENCE safeContents = new SEQUENCE();
3fd438
-            PasswordConverter passConverter = new
3fd438
-                    PasswordConverter();
3fd438
             PrivateKeyInfo pki = (PrivateKeyInfo)
3fd438
                     ASN1Util.decode(PrivateKeyInfo.getTemplate(),
3fd438
                             priData);
3fd438
@@ -662,14 +671,21 @@ public class RecoveryService implements IService {
3fd438
                 byte salt[] = { 0x01, 0x01, 0x01, 0x01 };
3fd438
                 epki = EncryptedPrivateKeyInfo.createPBE(
3fd438
                     PBEAlgorithm.PBE_SHA1_DES3_CBC,
3fd438
-                    pass, salt, 1, passConverter, pki);
3fd438
+                    pass, salt, 1, new PasswordConverter(), pki);
3fd438
             } else {
3fd438
                 epki = EncryptedPrivateKeyInfo.createPBES2(
3fd438
                     16, // saltLen
3fd438
                     2000, // kdfIterations
3fd438
                     EncryptionAlgorithm.AES_128_CBC_PAD,
3fd438
                     pass,
3fd438
-                    passConverter,
3fd438
+                    /* For compatibility with OpenSSL and NSS >= 3.31,
3fd438
+                     * do not BMPString-encode the passphrase when using
3fd438
+                     * non-PKCS #12 PBE scheme such as PKCS #5 PBES2.
3fd438
+                     *
3fd438
+                     * The resulting PKCS #12 is not compatible with
3fd438
+                     * NSS < 3.31.
3fd438
+                     */
3fd438
+                    null /* passConverter */,
3fd438
                     pki);
3fd438
             }
3fd438
 
3fd438
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java
3fd438
index ebade36bc..df3b4672d 100644
3fd438
--- a/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java
3fd438
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java
3fd438
@@ -1058,9 +1058,18 @@ public class ConfigurationUtils {
3fd438
                 // this is OK
3fd438
             }
3fd438
 
3fd438
-            // import private key into database
3fd438
-            store.importEncryptedPrivateKeyInfo(
3fd438
-                new PasswordConverter(), password, nickname, publicKey, epki);
3fd438
+            try {
3fd438
+                // first true without BMPString-encoding the passphrase.
3fd438
+                store.importEncryptedPrivateKeyInfo(
3fd438
+                    null, password, nickname, publicKey, epki);
3fd438
+            } catch (Exception e) {
3fd438
+                // if that failed, try again with BMPString-encoded
3fd438
+                // passphrase.  This is required for PKCS #12 PBE
3fd438
+                // schemes and for PKCS #12 files using PBES2 generated
3fd438
+                // by NSS < 3.31
3fd438
+                store.importEncryptedPrivateKeyInfo(
3fd438
+                    new PasswordConverter(), password, nickname, publicKey, epki);
3fd438
+            }
3fd438
         }
3fd438
 
3fd438
         CMS.debug("Importing new certificates:");
3fd438
diff --git a/base/util/src/netscape/security/pkcs/PKCS12Util.java b/base/util/src/netscape/security/pkcs/PKCS12Util.java
3fd438
index 1bc1baee5..1018b21f6 100644
3fd438
--- a/base/util/src/netscape/security/pkcs/PKCS12Util.java
3fd438
+++ b/base/util/src/netscape/security/pkcs/PKCS12Util.java
3fd438
@@ -134,16 +134,25 @@ public class PKCS12Util {
3fd438
             }
3fd438
             logger.debug("Encrypting private key for " + keyInfo.subjectDN);
3fd438
 
3fd438
-            PasswordConverter passConverter = new PasswordConverter();
3fd438
             epkiBytes = CryptoManager.getInstance()
3fd438
                 .getInternalKeyStorageToken()
3fd438
                 .getCryptoStore()
3fd438
                 .getEncryptedPrivateKeyInfo(
3fd438
+                    /* For compatibility with OpenSSL and NSS >= 3.31,
3fd438
+                     * do not BMPString-encode the passphrase when using
3fd438
+                     * non-PKCS #12 PBE scheme such as PKCS #5 PBES2.
3fd438
+                     *
3fd438
+                     * The resulting PKCS #12 is not compatible with
3fd438
+                     * NSS < 3.31.
3fd438
+                     */
3fd438
+                    null /* passConverter */,
3fd438
+                    password,
3fd438
                     /* NSS has a bug that causes any AES CBC encryption
3fd438
                      * to use AES-256, but AlgorithmID contains chosen
3fd438
                      * alg.  To avoid mismatch, use AES_256_CBC. */
3fd438
-                    passConverter, password,
3fd438
-                    EncryptionAlgorithm.AES_256_CBC, 0, k);
3fd438
+                    EncryptionAlgorithm.AES_256_CBC,
3fd438
+                    0 /* iterations (default) */,
3fd438
+                    k);
3fd438
         }
3fd438
 
3fd438
         SET keyAttrs = createKeyBagAttrs(keyInfo);
3fd438
@@ -616,8 +625,18 @@ public class PKCS12Util {
3fd438
                 "No EncryptedPrivateKeyInfo for key '"
3fd438
                 + keyInfo.subjectDN + "'; skipping key");
3fd438
         }
3fd438
-        store.importEncryptedPrivateKeyInfo(
3fd438
-            new PasswordConverter(), password, nickname, publicKey, epkiBytes);
3fd438
+        try {
3fd438
+            // first true without BMPString-encoding the passphrase.
3fd438
+            store.importEncryptedPrivateKeyInfo(
3fd438
+                null, password, nickname, publicKey, epkiBytes);
3fd438
+        } catch (Exception e) {
3fd438
+            // if that failed, try again with BMPString-encoded
3fd438
+            // passphrase.  This is required for PKCS #12 PBE
3fd438
+            // schemes and for PKCS #12 files using PBES2 generated
3fd438
+            // by NSS < 3.31
3fd438
+            store.importEncryptedPrivateKeyInfo(
3fd438
+                new PasswordConverter(), password, nickname, publicKey, epkiBytes);
3fd438
+        }
3fd438
 
3fd438
         // delete the cert again (it will be imported again later
3fd438
         // with the correct nickname)
3fd438
-- 
3fd438
2.13.5
3fd438