|
|
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 |
|