From c1bc2379334d89a8a059e5808faabe29d97ff230 Mon Sep 17 00:00:00 2001
From: Ade Lee <alee@redhat.com>
Date: Thu, 3 Mar 2016 14:36:52 -0500
Subject: [PATCH] Fix pkcs12 export

The utility for exporting certs and keys to a PKCS12 file
did not handle the signing certificate correctly.  This is
because the signing certificate was imported multiple times
during the export process - either with its key (and key id set)
or as part of the cert chain for the other system certs (with
no key set).

Each import would override the previous import - so whether
or not the key_id was set would depend on the order in which
the certificates were imported.

This becomes an issue for import into a clone certdb, because in
the new mechanism, we rely on the cert attributes (ie. key_id) to
determine if a key is to be imported or not.

We fix this by specifying whether the entry in the export should
be overwritten or not.
---
 base/util/src/netscape/security/pkcs/PKCS12.java     |  8 ++++++--
 base/util/src/netscape/security/pkcs/PKCS12Util.java | 10 +++++-----
 2 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/base/util/src/netscape/security/pkcs/PKCS12.java b/base/util/src/netscape/security/pkcs/PKCS12.java
index 19e9fd039abfb003cdf3b8d95ea4782c1ba38d9b..4f2f1600b36fbae6c8b3dd18597e3a1ba050b2dc 100644
--- a/base/util/src/netscape/security/pkcs/PKCS12.java
+++ b/base/util/src/netscape/security/pkcs/PKCS12.java
@@ -166,8 +166,12 @@ public class PKCS12 {
         return certInfosByNickname.values();
     }
 
-    public void addCertInfo(PKCS12CertInfo certInfo) {
-        certInfosByNickname.put(certInfo.nickname, certInfo);
+    public void addCertInfo(PKCS12CertInfo certInfo, boolean replace) {
+        String nickname = certInfo.nickname;
+        if (!replace && certInfosByNickname.containsKey(nickname))
+            return;
+
+        certInfosByNickname.put(nickname, certInfo);
     }
 
     public PKCS12CertInfo getCertInfoByNickname(String nickname) {
diff --git a/base/util/src/netscape/security/pkcs/PKCS12Util.java b/base/util/src/netscape/security/pkcs/PKCS12Util.java
index b2c8f8667a4dddc4f2a565bb8fe7488cf8c3d6ce..35b9ed598b98c782c963c3838f1dc9952fd803a1 100644
--- a/base/util/src/netscape/security/pkcs/PKCS12Util.java
+++ b/base/util/src/netscape/security/pkcs/PKCS12Util.java
@@ -254,7 +254,7 @@ public class PKCS12Util {
         loadCertChainFromNSS(pkcs12, cert);
     }
 
-    public void loadCertFromNSS(PKCS12 pkcs12, X509Certificate cert, BigInteger keyID) throws Exception {
+    public void loadCertFromNSS(PKCS12 pkcs12, X509Certificate cert, BigInteger keyID, boolean replace) throws Exception {
 
         String nickname = cert.getNickname();
         logger.info("Loading certificate \"" + nickname + "\" from NSS database");
@@ -264,7 +264,7 @@ public class PKCS12Util {
         certInfo.nickname = nickname;
         certInfo.cert = new X509CertImpl(cert.getEncoded());
         certInfo.trustFlags = getTrustFlags(cert);
-        pkcs12.addCertInfo(certInfo);
+        pkcs12.addCertInfo(certInfo, replace);
     }
 
     public void loadCertKeyFromNSS(PKCS12 pkcs12, X509Certificate cert, BigInteger keyID) throws Exception {
@@ -300,14 +300,14 @@ public class PKCS12Util {
         BigInteger keyID = createLocalKeyID(cert);
 
         // load cert with key
-        loadCertFromNSS(pkcs12, cert, keyID);
+        loadCertFromNSS(pkcs12, cert, keyID, true);
         loadCertKeyFromNSS(pkcs12, cert, keyID);
 
         // load parent certs without key
         X509Certificate[] certChain = cm.buildCertificateChain(cert);
         for (int i = 1; i < certChain.length; i++) {
             X509Certificate c = certChain[i];
-            loadCertFromNSS(pkcs12, c, null);
+            loadCertFromNSS(pkcs12, c, null, false);
         }
     }
 
@@ -488,7 +488,7 @@ public class PKCS12Util {
                 if (!oid.equals(SafeBag.CERT_BAG)) continue;
 
                 PKCS12CertInfo certInfo = getCertInfo(bag);
-                pkcs12.addCertInfo(certInfo);
+                pkcs12.addCertInfo(certInfo, true);
             }
         }
     }
-- 
2.4.3

