From 887d70ce1b8c4a00f62c2b4eec24326e487da5bd Mon Sep 17 00:00:00 2001 From: Fraser Tweedale 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