From 887d70ce1b8c4a00f62c2b4eec24326e487da5bd Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal@redhat.com>
Date: Thu, 15 Jun 2017 12:38:26 +1000
Subject: [PATCH 3/4] Fix regression in pkcs12 key bag creation
Commit 633c7c6519c925af7e3700adff29961d72435c7f changed the PKCS #12
file handing to never deal with raw private key material.
PKCS12Util.addKeyBag() was changed to export the PrivateKey handle,
or fail. This change missed this case where a PKCS #12 file is
loaded from file, possibly modified, then written back to a file,
without involving an NSSDB. One example is pkcs12-cert-del which
deletes a certificate and associated key from a PKCS #12 file.
Fix the PKCS12Util.addKeyBag() method to use the stored
EncryptedPricateKeyInfo if available, otherwise export the
PrivateKey handle.
Fixes: https://pagure.io/dogtagpki/issue/2741
Change-Id: Ib8098126bc5a79b5dae19103e25b270e2f10ab5a
(cherry picked from commit a411492fe5ad2030bb9f18db9a8ed8d1c45ee7de)
---
.../src/netscape/security/pkcs/PKCS12Util.java | 58 ++++++++++++++--------
1 file changed, 37 insertions(+), 21 deletions(-)
diff --git a/base/util/src/netscape/security/pkcs/PKCS12Util.java b/base/util/src/netscape/security/pkcs/PKCS12Util.java
index 31c7126..1bc1bae 100644
--- a/base/util/src/netscape/security/pkcs/PKCS12Util.java
+++ b/base/util/src/netscape/security/pkcs/PKCS12Util.java
@@ -102,33 +102,49 @@ public class PKCS12Util {
icert.setObjectSigningTrust(PKCS12.decodeFlags(flags[2]));
}
- /**
- * Used during EXPORT to add a private key to the PKCS12.
+ /** Add a private key to the PKCS #12 object.
+ *
+ * The PKCS12KeyInfo object received comes about in two
+ * different scenarios:
+ *
+ * - The private key could be in encrypted byte[] form (e.g.
+ * when we have merely loaded a PKCS #12 file for inspection
+ * or e.g. to delete a certificate and its associated key).
+ * In this case we simply re-use this encrypted private key
+ * info byte[].
*
- * The private key is exported directly from the token, into
- * an EncryptedPrivateKeyInfo value, then added as a
- * "Shrouded Key Bag" to the PKCS #12 object. Unencrypted
- * key material is never seen.
+ * - The private key could be a be an NSS PrivateKey handle. In
+ * this case we must export the PrivateKey from the token to
+ * obtain the EncryptedPrivateKeyInfo.
+ *
+ * The common final step is to add the encrypted private key
+ * data to a "Shrouded Key Bag" to the PKCS #12 object.
+ * Unencrypted key material is never seen.
*/
public void addKeyBag(PKCS12KeyInfo keyInfo, Password password,
SEQUENCE encSafeContents) throws Exception {
- PrivateKey k = keyInfo.getPrivateKey();
- if (k == null) {
- logger.debug("NO PRIVATE KEY for " + keyInfo.subjectDN);
- return;
- }
-
logger.debug("Creating key bag for " + keyInfo.subjectDN);
- PasswordConverter passConverter = new PasswordConverter();
- byte[] epkiBytes = CryptoManager.getInstance()
- .getInternalKeyStorageToken()
- .getCryptoStore()
- .getEncryptedPrivateKeyInfo(
- /* NSS has a bug that causes any AES CBC encryption
- * to use AES-256, but AlgorithmID contains chosen
- * alg. To avoid mismatch, use AES_256_CBC. */
- passConverter, password, EncryptionAlgorithm.AES_256_CBC, 0, k);
+ byte[] epkiBytes = keyInfo.getEncryptedPrivateKeyInfoBytes();
+ if (epkiBytes == null) {
+ PrivateKey k = keyInfo.getPrivateKey();
+ if (k == null) {
+ logger.debug("NO PRIVATE KEY for " + keyInfo.subjectDN);
+ return;
+ }
+ logger.debug("Encrypting private key for " + keyInfo.subjectDN);
+
+ PasswordConverter passConverter = new PasswordConverter();
+ epkiBytes = CryptoManager.getInstance()
+ .getInternalKeyStorageToken()
+ .getCryptoStore()
+ .getEncryptedPrivateKeyInfo(
+ /* NSS has a bug that causes any AES CBC encryption
+ * to use AES-256, but AlgorithmID contains chosen
+ * alg. To avoid mismatch, use AES_256_CBC. */
+ passConverter, password,
+ EncryptionAlgorithm.AES_256_CBC, 0, k);
+ }
SET keyAttrs = createKeyBagAttrs(keyInfo);
--
1.8.3.1