From ef5d954d1160002f6ed0ff05894f5968d7982d24 Mon Sep 17 00:00:00 2001
From: Jack Magne <jmagne@dhcp-16-206.sjc.redhat.com>
Date: Mon, 13 Jun 2016 11:27:59 -0700
Subject: [PATCH] Separated TPS does not automatically receive shared secret
 from remote TKS.

Support to allow the TPS to do the following:

1. Request that the TKS creates a shared secret with the proper ID, pointing to the TPS.
2. Have the TKS securely return the shared secret back to the TPS during the end of configuration.
3. The TPS then imports the wrapped shared secret into it's own internal NSS db permanenty and.
4. Given a name that is mapped to the TPS's id string.

Additional fixes:

1. The TKS was modified to actually be able to use multiple shared secrets registered by
multiple TPS instances.

Caveat:

At this point if the same remote TPS instance is created over and over again, the TPS's user
in the TKS will accumulate "userCert" attributes, making the exportation of teh shared secret
not functional. At this point we need to assume that the TPS user has ONE "userCert" registered
at this time.
---
 .../src/com/netscape/certsrv/key/KeyData.java      |  17 +-
 .../cms/servlet/csadmin/ConfigurationUtils.java    | 252 ++++++++++++---------
 .../cms/servlet/tks/SecureChannelProtocol.java     |   3 +-
 .../com/netscape/cms/servlet/tks/TokenServlet.java |  26 ++-
 .../server/tks/rest/TPSConnectorService.java       | 147 +++++++++---
 .../server/tps/processor/TPSProcessor.java         |   8 +-
 .../server/tps/rest/TPSInstallerService.java       |  12 +-
 .../com/netscape/cmsutil/crypto/CryptoUtil.java    | 157 +++++++++----
 8 files changed, 426 insertions(+), 196 deletions(-)

diff --git a/base/common/src/com/netscape/certsrv/key/KeyData.java b/base/common/src/com/netscape/certsrv/key/KeyData.java
index 6da4d38..d50c9ec 100644
--- a/base/common/src/com/netscape/certsrv/key/KeyData.java
+++ b/base/common/src/com/netscape/certsrv/key/KeyData.java
@@ -48,7 +48,8 @@ public class KeyData {
     @XmlElement
     Integer size;
 
-    String privateData;
+    @XmlElement
+    String additionalWrappedPrivateData;
 
     public KeyData() {
         // required for JAXB (defaults)
@@ -68,6 +69,14 @@ public class KeyData {
         this.wrappedPrivateData = wrappedPrivateData;
     }
 
+    public String getAdditionalWrappedPrivateData() {
+        return additionalWrappedPrivateData;
+    }
+
+    public void setAdditionalWrappedPrivateData(String additionalWrappedPrivateData) {
+        this.additionalWrappedPrivateData = additionalWrappedPrivateData;
+    }
+
     /**
      * @return the nonceData
      */
@@ -126,11 +135,5 @@ public class KeyData {
         this.size = size;
     }
 
-    public String getPrivateData() {
-        return privateData;
-    }
 
-    public void setPrivateData(String privateData) {
-        this.privateData = privateData;
-    }
 }
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
index 2da4e48..56ee9fa 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java
@@ -15,7 +15,7 @@
 // (C) 2012 Red Hat, Inc.
 // All rights reserved.
 // --- END COPYRIGHT BLOCK ---
- package com.netscape.cms.servlet.csadmin;
+package com.netscape.cms.servlet.csadmin;
 
 import java.io.BufferedReader;
 import java.io.ByteArrayInputStream;
@@ -58,6 +58,34 @@ import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
 import javax.xml.parsers.ParserConfigurationException;
 
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSet;
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPDN;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPModification;
+import netscape.ldap.LDAPSearchConstraints;
+import netscape.ldap.LDAPSearchResults;
+import netscape.ldap.LDAPv3;
+import netscape.security.pkcs.ContentInfo;
+import netscape.security.pkcs.PKCS10;
+import netscape.security.pkcs.PKCS12;
+import netscape.security.pkcs.PKCS12Util;
+import netscape.security.pkcs.PKCS7;
+import netscape.security.pkcs.SignerInfo;
+import netscape.security.util.DerOutputStream;
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.AlgorithmId;
+import netscape.security.x509.BasicConstraintsExtension;
+import netscape.security.x509.CertificateChain;
+import netscape.security.x509.Extension;
+import netscape.security.x509.Extensions;
+import netscape.security.x509.KeyUsageExtension;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509Key;
+
 import org.apache.commons.lang.StringUtils;
 import org.apache.velocity.context.Context;
 import org.mozilla.jss.CryptoManager;
@@ -149,36 +177,9 @@ import com.netscape.certsrv.usrgrp.IUGSubsystem;
 import com.netscape.certsrv.usrgrp.IUser;
 import com.netscape.cmsutil.crypto.CryptoUtil;
 import com.netscape.cmsutil.ldap.LDAPUtil;
+import com.netscape.cmsutil.util.Utils;
 import com.netscape.cmsutil.xml.XMLObject;
 
-import netscape.ldap.LDAPAttribute;
-import netscape.ldap.LDAPAttributeSet;
-import netscape.ldap.LDAPConnection;
-import netscape.ldap.LDAPDN;
-import netscape.ldap.LDAPEntry;
-import netscape.ldap.LDAPException;
-import netscape.ldap.LDAPModification;
-import netscape.ldap.LDAPSearchConstraints;
-import netscape.ldap.LDAPSearchResults;
-import netscape.ldap.LDAPv3;
-import netscape.security.pkcs.ContentInfo;
-import netscape.security.pkcs.PKCS10;
-import netscape.security.pkcs.PKCS12;
-import netscape.security.pkcs.PKCS12Util;
-import netscape.security.pkcs.PKCS7;
-import netscape.security.pkcs.SignerInfo;
-import netscape.security.util.DerOutputStream;
-import netscape.security.util.ObjectIdentifier;
-import netscape.security.x509.AlgorithmId;
-import netscape.security.x509.BasicConstraintsExtension;
-import netscape.security.x509.CertificateChain;
-import netscape.security.x509.Extension;
-import netscape.security.x509.Extensions;
-import netscape.security.x509.KeyUsageExtension;
-import netscape.security.x509.X500Name;
-import netscape.security.x509.X509CertImpl;
-import netscape.security.x509.X509Key;
-
 /**
  * Utility class for functions to be used by the RESTful installer.
  *
@@ -377,7 +378,7 @@ public class ConfigurationUtils {
             if (eqPos != -1) {
                 String name = line.substring(0, eqPos).trim();
                 String tempval = line.substring(eqPos + 1).trim();
-                String value = tempval.replaceAll("(^\")|(\";$)","");
+                String value = tempval.replaceAll("(^\")|(\";$)", "");
 
                 if (name.equals(header)) {
                     return value;
@@ -634,7 +635,7 @@ public class ConfigurationUtils {
                 throw new IOException("The server you want to contact is not available");
             }
 
-            CMS.debug("content from admin interface ="+ c);
+            CMS.debug("content from admin interface =" + c);
             // when the admin servlet is unavailable, we return a badly formatted error page
             // in that case, this will throw an exception and be passed into the catch block.
             parser = new XMLObject(new ByteArrayInputStream(c.getBytes()));
@@ -685,7 +686,7 @@ public class ConfigurationUtils {
 
     public static boolean updateConfigEntries(String hostname, int port, boolean https,
             String servlet, MultivaluedMap<String, String> content, IConfigStore config)
-                    throws Exception {
+            throws Exception {
         CMS.debug("updateConfigEntries start");
         String c = post(hostname, port, https, servlet, content, null, null);
 
@@ -874,7 +875,8 @@ public class ConfigurationUtils {
                     // pkeyinfo_v stores private key (PrivateKeyInfo) and subject DN (String)
                     Vector<Object> pkeyinfo_v = new Vector<Object>();
                     pkeyinfo_v.addElement(pkeyinfo);
-                    if (subjectDN != null) pkeyinfo_v.addElement(subjectDN);
+                    if (subjectDN != null)
+                        pkeyinfo_v.addElement(subjectDN);
 
                     pkeyinfo_collection.addElement(pkeyinfo_v);
 
@@ -923,7 +925,8 @@ public class ConfigurationUtils {
                     // cert_v stores certificate (byte[]) and nickname (String)
                     Vector<Object> cert_v = new Vector<Object>();
                     cert_v.addElement(x509cert);
-                    if (nickname != null) cert_v.addElement(nickname);
+                    if (nickname != null)
+                        cert_v.addElement(nickname);
 
                     cert_collection.addElement(cert_v);
                 }
@@ -974,10 +977,11 @@ public class ConfigurationUtils {
     public static void importKeyCert(
             Vector<Vector<Object>> pkeyinfo_collection,
             Vector<Vector<Object>> cert_collection
-        ) throws IOException, CertificateException, TokenException,
-            NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalStateException,
-            IllegalBlockSizeException, BadPaddingException, NotInitializedException, NicknameConflictException,
-            UserCertConflictException, NoSuchItemOnTokenException, EPropertyNotFound, EBaseException {
+            ) throws IOException, CertificateException, TokenException,
+                    NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException,
+                    IllegalStateException,
+                    IllegalBlockSizeException, BadPaddingException, NotInitializedException, NicknameConflictException,
+                    UserCertConflictException, NoSuchItemOnTokenException, EPropertyNotFound, EBaseException {
 
         CMS.debug("ConfigurationUtils.importKeyCert()");
         CryptoManager cm = CryptoManager.getInstance();
@@ -1051,7 +1055,7 @@ public class ConfigurationUtils {
                 String name = (String) cert_v.elementAt(1);
                 CMS.debug("- Certificate: " + name);
 
-                if (! masterList.contains(name)) {
+                if (!masterList.contains(name)) {
                     CMS.debug("  Certificate not in master list, ignore certificate");
                     continue;
                 }
@@ -1142,10 +1146,11 @@ public class ConfigurationUtils {
             return true;
         try {
             X500Name xname = new X500Name(nickname);
-            for (String key: masterList) {
+            for (String key : masterList) {
                 try {
                     X500Name xkey = new X500Name(key);
-                    if (xkey.equals(xname)) return true;
+                    if (xkey.equals(xname))
+                        return true;
                 } catch (IOException e) {
                     // xkey not an X500Name
                 }
@@ -1187,10 +1192,12 @@ public class ConfigurationUtils {
         IConfigStore cs = CMS.getConfigStore();
         try {
             String nickname = cs.getString("preop.master.signing.nickname");
-            if (nickname.equals(name)) return true;
-        } catch(Exception e) {
+            if (nickname.equals(name))
+                return true;
+        } catch (Exception e) {
             // nickname may not exist if this is not cloning a CA
-        };
+        }
+        ;
 
         return false;
     }
@@ -1198,7 +1205,8 @@ public class ConfigurationUtils {
     public static boolean isAuditSigningCert(String name) throws EPropertyNotFound, EBaseException {
         IConfigStore cs = CMS.getConfigStore();
         String nickname = cs.getString("preop.master.audit_signing.nickname");
-        if (nickname.equals(name)) return true;
+        if (nickname.equals(name))
+            return true;
         return false;
     }
 
@@ -1248,7 +1256,7 @@ public class ConfigurationUtils {
         while (st.hasMoreTokens()) {
             String s = st.nextToken();
             if (s.equals("sslserver"))
-                    continue;
+                continue;
             String name = "preop.master." + s + ".nickname";
             String nickname = cs.getString(name);
             list.add(nickname);
@@ -1268,14 +1276,16 @@ public class ConfigurationUtils {
             X509CertImpl impl = null;
             impl = new X509CertImpl(b);
             Principal subjectdn = impl.getSubjectDN();
-            if (LDAPDN.equals(subjectdn.toString(), nickname)) return b;
+            if (LDAPDN.equals(subjectdn.toString(), nickname))
+                return b;
         }
         return null;
     }
 
     public static void releaseConnection(LDAPConnection conn) {
         try {
-            if (conn != null) conn.disconnect();
+            if (conn != null)
+                conn.disconnect();
         } catch (LDAPException e) {
             CMS.debug(e);
             CMS.debug("releaseConnection: " + e);
@@ -1526,14 +1536,15 @@ public class ConfigurationUtils {
             LDAPSearchResults res = conn.search(
                     "cn=mapping tree, cn=config", LDAPConnection.SCOPE_ONE,
                     "nsslapd-backend=" + LDAPUtil.escapeFilter(database),
-                    null, false, (LDAPSearchConstraints)null);
+                    null, false, (LDAPSearchConstraints) null);
 
             while (res.hasMoreElements()) {
                 LDAPEntry entry = res.next();
 
                 LDAPAttribute cn = entry.getAttribute("cn");
                 String dn = cn.getStringValueArray()[0];
-                if (LDAPDN.equals(baseDN, dn)) continue;
+                if (LDAPDN.equals(baseDN, dn))
+                    continue;
 
                 CMS.debug("confirmMappings: Database " + database + " is used by " + dn + ".");
                 throw new EBaseException("The database (" + database + ") is used by another base DN. " +
@@ -1621,12 +1632,12 @@ public class ConfigurationUtils {
 
     private static void checkParentExists(String baseDN, LDAPConnection conn) throws EBaseException {
         String[] dns = LDAPDN.explodeDN(baseDN, false);
-        if (dns.length == 1 ) {
+        if (dns.length == 1) {
             CMS.debug("checkParentExists: no parent in baseDN: " + baseDN);
             throw new EBaseException("Invalid BaseDN. No parent DN in " + baseDN);
         }
         String parentDN = Arrays.toString(Arrays.copyOfRange(dns, 1, dns.length));
-        parentDN = parentDN.substring(1,parentDN.length() -1);
+        parentDN = parentDN.substring(1, parentDN.length() - 1);
         try {
             CMS.debug("checkParentExists: Checking parent " + parentDN + ".");
             conn.read(parentDN);
@@ -1641,11 +1652,13 @@ public class ConfigurationUtils {
         }
     }
 
-    public static void importLDIFS(String param, LDAPConnection conn) throws EPropertyNotFound, IOException, EBaseException {
+    public static void importLDIFS(String param, LDAPConnection conn) throws EPropertyNotFound, IOException,
+            EBaseException {
         importLDIFS(param, conn, true);
     }
 
-    public static void importLDIFS(String param, LDAPConnection conn, boolean suppressErrors) throws IOException, EPropertyNotFound,
+    public static void importLDIFS(String param, LDAPConnection conn, boolean suppressErrors) throws IOException,
+            EPropertyNotFound,
             EBaseException {
         IConfigStore cs = CMS.getConfigStore();
 
@@ -1739,7 +1752,7 @@ public class ConfigurationUtils {
         try {
             LDAPSearchResults res = conn.search(
                     dn, LDAPConnection.SCOPE_BASE, "objectclass=*",
-                    null, true, (LDAPSearchConstraints)null);
+                    null, true, (LDAPSearchConstraints) null);
             deleteEntries(res, conn, excludedDNs);
 
         } catch (LDAPException e) {
@@ -1752,14 +1765,15 @@ public class ConfigurationUtils {
         }
     }
 
-    public static void deleteEntries(LDAPSearchResults res, LDAPConnection conn, String[] excludedDNs) throws LDAPException {
+    public static void deleteEntries(LDAPSearchResults res, LDAPConnection conn, String[] excludedDNs)
+            throws LDAPException {
         while (res.hasMoreElements()) {
             LDAPEntry entry = res.next();
             String dn = entry.getDN();
 
             LDAPSearchResults res1 = conn.search(
                     dn, 1, "objectclass=*",
-                    null, true, (LDAPSearchConstraints)null);
+                    null, true, (LDAPSearchConstraints) null);
             deleteEntries(res1, conn, excludedDNs);
             deleteEntry(conn, dn, excludedDNs);
         }
@@ -1767,7 +1781,8 @@ public class ConfigurationUtils {
 
     public static void deleteEntry(LDAPConnection conn, String dn, String[] excludedDNs) throws LDAPException {
         for (String excludedDN : excludedDNs) {
-            if (!LDAPDN.equals(dn, excludedDN)) continue;
+            if (!LDAPDN.equals(dn, excludedDN))
+                continue;
 
             CMS.debug("deleteEntry: entry with this dn " + dn + " is not deleted.");
             return;
@@ -1972,7 +1987,7 @@ public class ConfigurationUtils {
 
             String status = replicationStatus(replicadn, masterConn, masterAgreementName);
             if (!status.startsWith("0 ")) {
-                CMS.debug("setupReplication: consumer initialization failed. " +status);
+                CMS.debug("setupReplication: consumer initialization failed. " + status);
                 throw new IOException("consumer initialization failed. " + status);
             }
 
@@ -1990,7 +2005,7 @@ public class ConfigurationUtils {
             releaseConnection(masterConn);
             releaseConnection(replicaConn);
         }
-}
+    }
 
     public static void createReplicationManager(LDAPConnection conn, String bindUser, String pwd)
             throws LDAPException {
@@ -2252,7 +2267,8 @@ public class ConfigurationUtils {
         CMS.reinit(IUGSubsystem.ID);
     }
 
-    public static void setExternalCACert(String certStr, String subsystem, IConfigStore config, Cert certObj) throws Exception {
+    public static void setExternalCACert(String certStr, String subsystem, IConfigStore config, Cert certObj)
+            throws Exception {
         certStr = CryptoUtil.stripCertBrackets(certStr.trim());
         certStr = CryptoUtil.normalizeCertStr(certStr);
         config.putString(subsystem + ".external_ca.cert", certStr);
@@ -2340,7 +2356,8 @@ public class ConfigurationUtils {
         String sslType = "ECDHE";
         try {
             sslType = config.getString(PCERT_PREFIX + ct + "ec.type", "ECDHE");
-        } catch (Exception e) {}
+        } catch (Exception e) {
+        }
 
         // ECDHE needs "SIGN" but no "DERIVE"
         org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage usages_mask[] = {
@@ -2355,13 +2372,15 @@ public class ConfigurationUtils {
 
         do {
             if (ct.equals("sslserver") && sslType.equalsIgnoreCase("ECDH")) {
-                CMS.debug("ConfigurationUtils: createECCKeypair: sslserver cert for ECDH. Make sure server.xml is set " +
-                          "properly with -TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,+TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA");
+                CMS.debug("ConfigurationUtils: createECCKeypair: sslserver cert for ECDH. Make sure server.xml is set "
+                        +
+                        "properly with -TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,+TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA");
                 pair = CryptoUtil.generateECCKeyPair(token, curveName, null, ECDH_usages_mask);
             } else {
                 if (ct.equals("sslserver")) {
-                    CMS.debug("ConfigurationUtils: createECCKeypair: sslserver cert for ECDHE. Make sure server.xml is set " +
-                              "properly with +TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,-TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA");
+                    CMS.debug("ConfigurationUtils: createECCKeypair: sslserver cert for ECDHE. Make sure server.xml is set "
+                            +
+                            "properly with +TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,-TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA");
                 }
                 pair = CryptoUtil.generateECCKeyPair(token, curveName, null, usages_mask);
             }
@@ -2418,7 +2437,8 @@ public class ConfigurationUtils {
         setSigningAlgorithm(ct, keyAlgo, config);
     }
 
-    public static void setSigningAlgorithm(String ct, String keyAlgo, IConfigStore config) throws EPropertyNotFound, EBaseException {
+    public static void setSigningAlgorithm(String ct, String keyAlgo, IConfigStore config) throws EPropertyNotFound,
+            EBaseException {
         String systemType = config.getString("cs.type");
         if (systemType.equalsIgnoreCase("CA")) {
             if (ct.equals("signing")) {
@@ -2498,16 +2518,16 @@ public class ConfigurationUtils {
                 // retrieve and store original 'CS.cfg' entries
                 preop_ca_type = config.getString("preop.ca.type", "");
                 preop_cert_signing_type = config.getString("preop.cert.signing.type", "");
-                preop_cert_signing_profile = config.getString("preop.cert.signing.profile","");
+                preop_cert_signing_profile = config.getString("preop.cert.signing.profile", "");
                 preop_cert_sslserver_type = config.getString("preop.cert.sslserver.type", "");
-                preop_cert_sslserver_profile = config.getString("preop.cert.sslserver.profile","");
+                preop_cert_sslserver_profile = config.getString("preop.cert.sslserver.profile", "");
 
                 // add/modify 'CS.cfg' entries
                 config.putString("preop.ca.type", "sdca");
                 config.putString("preop.cert.signing.type", "remote");
-                config.putString("preop.cert.signing.profile","caInstallCACert");
+                config.putString("preop.cert.signing.profile", "caInstallCACert");
                 config.putString("preop.cert.sslserver.type", "remote");
-                config.putString("preop.cert.sslserver.profile","caInternalAuthServerCert");
+                config.putString("preop.cert.sslserver.profile", "caInternalAuthServerCert");
 
                 // store original caType
                 original_caType = caType;
@@ -2543,7 +2563,7 @@ public class ConfigurationUtils {
                     if (standalone) {
                         // Treat standalone subsystem the same as "otherca"
                         config.putString(subsystem + "." + certTag + ".cert",
-                                         "...paste certificate here...");
+                                "...paste certificate here...");
 
                     } else {
                         String sd_hostname = config.getString("securitydomain.host", "");
@@ -2569,8 +2589,8 @@ public class ConfigurationUtils {
                     try {
                         if (sign_clone_sslserver_cert_using_master) {
                             CMS.debug("ConfigurationUtils: For this Cloned CA, always use its Master CA to generate " +
-                                      "the 'sslserver' certificate to avoid any changes which may have been " +
-                                      "made to the X500Name directory string encoding order.");
+                                    "the 'sslserver' certificate to avoid any changes which may have been " +
+                                    "made to the X500Name directory string encoding order.");
                             ca_hostname = config.getString("preop.master.hostname", "");
                             ca_port = config.getInteger("preop.master.httpsport", -1);
                         } else {
@@ -2582,12 +2602,12 @@ public class ConfigurationUtils {
 
                     String sslserver_extension = "";
                     Boolean injectSAN = config.getBoolean(
-                                      "service.injectSAN", false);
-                    CMS.debug("ConfigurationUtils: injectSAN="+injectSAN);
+                            "service.injectSAN", false);
+                    CMS.debug("ConfigurationUtils: injectSAN=" + injectSAN);
                     if (certTag.equals("sslserver") &&
-                        injectSAN == true) {
+                            injectSAN == true) {
                         sslserver_extension =
-                            CertUtil.buildSANSSLserverURLExtension(config);
+                                CertUtil.buildSANSSLserverURLExtension(config);
                     }
 
                     MultivaluedMap<String, String> content = new MultivaluedHashMap<String, String>();
@@ -3090,7 +3110,8 @@ public class ConfigurationUtils {
         IConfigStore config = CMS.getConfigStore();
 
         boolean enable = config.getBoolean(PCERT_PREFIX + certTag + ".enable", true);
-        if (!enable) return 0;
+        if (!enable)
+            return 0;
 
         CMS.debug("handleCerts(): for cert tag '" + cert.getCertTag() + "' using cert type '" + cert.getType() + "'");
         String b64 = cert.getCert();
@@ -3106,7 +3127,8 @@ public class ConfigurationUtils {
             }
 
             if (findCertificate(tokenname, nickname)) {
-                if (!certTag.equals("sslserver")) return 0;
+                if (!certTag.equals("sslserver"))
+                    return 0;
             }
             X509CertImpl impl = CertUtil.createLocalCert(config, x509key,
                     PCERT_PREFIX, certTag, cert.getType(), null);
@@ -3131,7 +3153,8 @@ public class ConfigurationUtils {
                     CMS.debug("handleCerts(): cert imported for certTag '" + certTag + "'");
                 } catch (Exception ee) {
                     CMS.debug(ee);
-                    CMS.debug("handleCerts(): import certificate for certTag=" + certTag + " Exception: " + ee.toString());
+                    CMS.debug("handleCerts(): import certificate for certTag=" + certTag + " Exception: "
+                            + ee.toString());
                 }
             }
         } else if (cert.getType().equals("remote")) {
@@ -3191,7 +3214,7 @@ public class ConfigurationUtils {
                     CMS.debug("handleCerts(): import certificate successfully, certTag=" + certTag);
                 } catch (Exception ee) {
                     ee.printStackTrace();
-                    CMS.debug("handleCerts: import certificate for certTag=" + certTag + " Exception: "+ ee.toString());
+                    CMS.debug("handleCerts: import certificate for certTag=" + certTag + " Exception: " + ee.toString());
                 }
 
             } else {
@@ -3243,7 +3266,8 @@ public class ConfigurationUtils {
 
     public static void setCertPermissions(String tag) throws EBaseException, NotInitializedException,
             ObjectNotFoundException, TokenException {
-        if (tag.equals("signing") || tag.equals("external_signing")) return;
+        if (tag.equals("signing") || tag.equals("external_signing"))
+            return;
 
         IConfigStore cs = CMS.getConfigStore();
         String nickname = cs.getString("preop.cert." + tag + ".nickname", "");
@@ -3302,7 +3326,6 @@ public class ConfigurationUtils {
         return true;
     }
 
-
     public static boolean findBootstrapServerCert() throws EBaseException, NotInitializedException, TokenException {
         IConfigStore cs = CMS.getConfigStore();
 
@@ -3317,7 +3340,8 @@ public class ConfigurationUtils {
         }
         Principal issuerDN = cert.getIssuerDN();
         Principal subjectDN = cert.getSubjectDN();
-        if (issuerDN.equals(subjectDN)) return true;
+        if (issuerDN.equals(subjectDN))
+            return true;
 
         return false;
     }
@@ -3448,7 +3472,8 @@ public class ConfigurationUtils {
     }
 
     public static byte[] addCertBag(X509Certificate x509cert, String nickname,
-            SEQUENCE safeContents) throws CertificateEncodingException, NoSuchAlgorithmException, CharConversionException {
+            SEQUENCE safeContents) throws CertificateEncodingException, NoSuchAlgorithmException,
+            CharConversionException {
         byte[] localKeyId = null;
 
         ASN1Value cert = new OCTET_STRING(x509cert.getEncoded());
@@ -3611,49 +3636,56 @@ public class ConfigurationUtils {
         if (select.equals("new")) {
             group = system.getGroupFromName("Security Domain Administrators");
             if (group != null && !group.isMember(uid)) {
-                CMS.debug("ConfigurationUtils: createAdmin:  add user '" + uid + "' to group 'Security Domain Administrators'");
+                CMS.debug("ConfigurationUtils: createAdmin:  add user '" + uid
+                        + "' to group 'Security Domain Administrators'");
                 group.addMemberName(uid);
                 system.modifyGroup(group);
             }
 
             group = system.getGroupFromName("Enterprise CA Administrators");
             if (group != null && !group.isMember(uid)) {
-                CMS.debug("ConfigurationUtils: createAdmin:  add user '" + uid + "' to group 'Enterprise CA Administrators'");
+                CMS.debug("ConfigurationUtils: createAdmin:  add user '" + uid
+                        + "' to group 'Enterprise CA Administrators'");
                 group.addMemberName(uid);
                 system.modifyGroup(group);
             }
 
             group = system.getGroupFromName("Enterprise KRA Administrators");
             if (group != null && !group.isMember(uid)) {
-                CMS.debug("ConfigurationUtils: createAdmin:  add user '" + uid + "' to group 'Enterprise KRA Administrators'");
+                CMS.debug("ConfigurationUtils: createAdmin:  add user '" + uid
+                        + "' to group 'Enterprise KRA Administrators'");
                 group.addMemberName(uid);
                 system.modifyGroup(group);
             }
 
             group = system.getGroupFromName("Enterprise RA Administrators");
             if (group != null && !group.isMember(uid)) {
-                CMS.debug("ConfigurationUtils: createAdmin:  add user '" + uid + "' to group 'Enterprise RA Administrators'");
+                CMS.debug("ConfigurationUtils: createAdmin:  add user '" + uid
+                        + "' to group 'Enterprise RA Administrators'");
                 group.addMemberName(uid);
                 system.modifyGroup(group);
             }
 
             group = system.getGroupFromName("Enterprise TKS Administrators");
             if (group != null && !group.isMember(uid)) {
-                CMS.debug("ConfigurationUtils: createAdmin:  add user '" + uid + "' to group 'Enterprise TKS Administrators'");
+                CMS.debug("ConfigurationUtils: createAdmin:  add user '" + uid
+                        + "' to group 'Enterprise TKS Administrators'");
                 group.addMemberName(uid);
                 system.modifyGroup(group);
             }
 
             group = system.getGroupFromName("Enterprise OCSP Administrators");
             if (group != null && !group.isMember(uid)) {
-                CMS.debug("ConfigurationUtils: createAdmin:  add user '" + uid + "' to group 'Enterprise OCSP Administrators'");
+                CMS.debug("ConfigurationUtils: createAdmin:  add user '" + uid
+                        + "' to group 'Enterprise OCSP Administrators'");
                 group.addMemberName(uid);
                 system.modifyGroup(group);
             }
 
             group = system.getGroupFromName("Enterprise TPS Administrators");
             if (group != null && !group.isMember(uid)) {
-                CMS.debug("ConfigurationUtils: createAdmin:  add user '" + uid + "' to group 'Enterprise TPS Administrators'");
+                CMS.debug("ConfigurationUtils: createAdmin:  add user '" + uid
+                        + "' to group 'Enterprise TPS Administrators'");
                 group.addMemberName(uid);
                 system.modifyGroup(group);
             }
@@ -3808,7 +3840,7 @@ public class ConfigurationUtils {
             CMS.debug("Cloning a domain master");
         }
 
-        String url =  "/ca/admin/ca/updateDomainXML";
+        String url = "/ca/admin/ca/updateDomainXML";
 
         MultivaluedMap<String, String> content = new MultivaluedHashMap<String, String>();
         content.putSingle("list", type + "List");
@@ -3837,7 +3869,7 @@ public class ConfigurationUtils {
             CMS.debug("Unable to access admin interface: " + e);
 
             CMS.debug("Update security domain using agent interface");
-            url =  "/ca/agent/ca/updateDomainXML";
+            url = "/ca/agent/ca/updateDomainXML";
             updateDomainXML(sd_host, sd_agent_port, true, url, content, true);
         }
 
@@ -3878,7 +3910,7 @@ public class ConfigurationUtils {
 
     public static void updateDomainXML(String hostname, int port, boolean https,
             String servlet, MultivaluedMap<String, String> content, boolean useClientAuth)
-                    throws Exception {
+            throws Exception {
 
         CMS.debug("ConfigurationUtils: updateDomainXML start hostname=" + hostname + " port=" + port);
 
@@ -4022,7 +4054,7 @@ public class ConfigurationUtils {
             try {
                 CMS.debug("setupClientAuthUser: Adding cert to user: " + id);
                 system.addUserCert(user);
-            } catch(ConflictingOperationException e) {
+            } catch (ConflictingOperationException e) {
                 // ignore exception
                 CMS.debug("setupClientAuthUser: Cert already added: " + e);
             }
@@ -4096,7 +4128,9 @@ public class ConfigurationUtils {
     }
 
     public static void getSharedSecret(String tksHost, int tksPort, boolean importKey) throws EPropertyNotFound,
-            EBaseException, URISyntaxException {
+            EBaseException, URISyntaxException, InvalidKeyException, NoSuchAlgorithmException,
+            InvalidAlgorithmParameterException, NotInitializedException, TokenException, ObjectNotFoundException,
+            IOException {
         IConfigStore cs = CMS.getConfigStore();
         String host = cs.getString("service.machineName");
         String port = cs.getString("service.securePort");
@@ -4115,6 +4149,8 @@ public class ConfigurationUtils {
 
         PKIClient client = new PKIClient(config, null);
 
+        CMS.debug("In ConfigurationUtils.getSharedSecret! importKey: " + importKey);
+
         // Ignore the "UNTRUSTED_ISSUER" and "CA_CERT_INVALID" validity status
         // during PKI instance creation since we are using an untrusted temporary CA cert.
         client.addIgnoredCertStatus(SSLCertificateApprovalCallback.ValidityStatus.UNTRUSTED_ISSUER);
@@ -4131,6 +4167,8 @@ public class ConfigurationUtils {
             // no connector exists
             data = null;
         }
+
+
         KeyData keyData = null;
         if (data == null) {
             data = tpsConnectorClient.createConnector(host, port);
@@ -4146,14 +4184,24 @@ public class ConfigurationUtils {
         }
         accountClient.logout();
 
+        String nick = "TPS-" + host + "-" + port + " sharedSecret";
+
         if (importKey) {
-            // TODO - we need code here to import the key into the tps certdb
+            CMS.debug("getSharedSecret: About to attempt to import shared secret key.");
+            byte[] sessionKeyData = Utils.base64decode(keyData.getWrappedPrivateData());
+            byte[] sharedSecretData = Utils.base64decode(keyData.getAdditionalWrappedPrivateData());
+
+            try {
+                CryptoUtil.importSharedSecret(sessionKeyData, sharedSecretData, dbNick, nick);
+            } catch (Exception e) {
+                CMS.debug("getSharedSecret()): WARNING, Failed to automatically import shared secret. Please follow the manual procedure." + e.toString());
+            }
             // this is not needed if we are using a shared database with
             // the tks.
         }
 
         // store the new nick in CS.cfg
-        String nick = "TPS-" + host + "-" + port + " sharedSecret";
+
         cs.putString("conn.tks1.tksSharedSymKeyName", nick);
         cs.commit(false);
     }
@@ -4363,7 +4411,7 @@ public class ConfigurationUtils {
 
             if (status.equals(SUCCESS)) {
                 CMS.debug("registerUser: Successfully added user " + uid + " to " + targetURI +
-                          " using " + targetURL);
+                        " using " + targetURL);
 
             } else if (status.equals(AUTH_FAILURE)) {
                 throw new EAuthException(AUTH_FAILURE);
@@ -4475,7 +4523,6 @@ public class ConfigurationUtils {
         cs.putString("auths.instance.ldap1.ldap.ldapconn.secureConn", secureConn);
     }
 
-
     public static void updateNextRanges() throws EBaseException, LDAPException {
         IConfigStore cs = CMS.getConfigStore();
 
@@ -4516,6 +4563,7 @@ public class ConfigurationUtils {
 
     /**
      * save variables needed for cloning and remove preops
+     *
      * @throws EBaseException
      */
     public static void removePreopConfigEntries() throws EBaseException {
diff --git a/base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java b/base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java
index 7dab140..9593816 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java
@@ -418,7 +418,8 @@ public class SecureChannelProtocol {
         String method = "SecureChannelProtocol.getSharedSecretKeyName:";
         CMS.debug(method + " Entering...");
 
-        if (name != null && SecureChannelProtocol.sharedSecretKeyName == null) {
+        // No longer cache the secret name, there could be a different one for each incoming TPS connection.
+        if (name != null) {
             SecureChannelProtocol.sharedSecretKeyName = name;
         }
 
diff --git a/base/server/cms/src/com/netscape/cms/servlet/tks/TokenServlet.java b/base/server/cms/src/com/netscape/cms/servlet/tks/TokenServlet.java
index ab2ade9..9c143fd 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/tks/TokenServlet.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/tks/TokenServlet.java
@@ -70,6 +70,7 @@ public class TokenServlet extends CMSServlet {
     public static int ERROR = 1;
     String mKeyNickName = null;
     String mNewKeyNickName = null;
+    String mCurrentUID = null;
     IPrettyPrintFormat pp = CMS.getPrettyPrintFormat(":");
 
     private final static String LOGGING_SIGNED_AUDIT_COMPUTE_SESSION_KEY_REQUEST =
@@ -951,8 +952,6 @@ public class TokenServlet extends CMSServlet {
 
         transportKeyName = getSharedSecretName(sconfig);
 
-        CMS.debug("TokenServlet: ComputeSessionKey(): tksSharedSymKeyName: " + transportKeyName);
-
         String rcard_challenge = req.getParameter(IRemoteRequest.TOKEN_CARD_CHALLENGE);
         String rhost_challenge = req.getParameter(IRemoteRequest.TOKEN_HOST_CHALLENGE);
         String rKeyInfo = req.getParameter(IRemoteRequest.TOKEN_KEYINFO);
@@ -1537,13 +1536,32 @@ public class TokenServlet extends CMSServlet {
 
         if (useNewNames) {
             String tpsList = cs.getString("tps.list", "");
+            String firstSharedSecretName = null;
             if (!tpsList.isEmpty()) {
                 for (String tpsID : tpsList.split(",")) {
                     String sharedSecretName = cs.getString("tps." + tpsID + ".nickname", "");
+
+                    // This one will be a fall back in case we can't get a specific one
+                    if (firstSharedSecretName == null) {
+                        firstSharedSecretName = sharedSecretName;
+                    }
+
                     if (!sharedSecretName.isEmpty()) {
-                        return sharedSecretName;
+                        if (mCurrentUID != null) {
+                            String csUid = cs.getString("tps." + tpsID + ".userid", "");
+
+                            if (mCurrentUID.equalsIgnoreCase(csUid)) {
+                                CMS.debug("TokenServlet.getSharedSecretName: found a match of the user id! " + csUid);
+                                return sharedSecretName;
+                            }
+                        }
                     }
                 }
+
+                if (firstSharedSecretName != null) {
+                    //Return the first in the list if we couldn't isolate one
+                    return firstSharedSecretName;
+                }
             }
             CMS.debug("getSharedSecretName: no shared secret has been configured");
             throw new EBaseException("No shared secret has been configured");
@@ -2351,6 +2369,8 @@ public class TokenServlet extends CMSServlet {
         IAuthToken authToken = authenticate(cmsReq);
         AuthzToken authzToken = null;
 
+        mCurrentUID = (String) authToken.get(IAuthToken.UID) ;
+
         try {
             authzToken = authorize(mAclMethod, authToken,
                     mAuthzResourceName, "execute");
diff --git a/base/tks/src/org/dogtagpki/server/tks/rest/TPSConnectorService.java b/base/tks/src/org/dogtagpki/server/tks/rest/TPSConnectorService.java
index bc655d6..a2d18f1 100644
--- a/base/tks/src/org/dogtagpki/server/tks/rest/TPSConnectorService.java
+++ b/base/tks/src/org/dogtagpki/server/tks/rest/TPSConnectorService.java
@@ -1,5 +1,6 @@
 package org.dogtagpki.server.tks.rest;
 
+import java.io.CharConversionException;
 import java.io.IOException;
 import java.net.URI;
 import java.security.InvalidAlgorithmParameterException;
@@ -10,6 +11,7 @@ import java.security.cert.X509Certificate;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Iterator;
+import java.util.List;
 import java.util.TreeSet;
 
 import javax.servlet.http.HttpServletRequest;
@@ -20,8 +22,13 @@ import javax.ws.rs.core.UriInfo;
 import org.apache.commons.lang.ArrayUtils;
 import org.apache.commons.lang.StringUtils;
 import org.jboss.resteasy.plugins.providers.atom.Link;
+import org.mozilla.jss.CryptoManager;
 import org.mozilla.jss.CryptoManager.NotInitializedException;
+import org.mozilla.jss.crypto.CryptoToken;
 import org.mozilla.jss.crypto.InvalidKeyFormatException;
+import org.mozilla.jss.crypto.KeyGenAlgorithm;
+import org.mozilla.jss.crypto.KeyGenerator;
+import org.mozilla.jss.crypto.SymmetricKey;
 import org.mozilla.jss.crypto.TokenException;
 
 import com.netscape.certsrv.apps.CMS;
@@ -60,30 +67,32 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou
     public Response findConnectors(Integer start, Integer size) {
         try {
             String tpsList = cs.getString(TPS_LIST, "");
-            Iterator<String> entries = Arrays.asList(StringUtils.split(tpsList,",")).iterator();
+            Iterator<String> entries = Arrays.asList(StringUtils.split(tpsList, ",")).iterator();
 
             TPSConnectorCollection response = new TPSConnectorCollection();
             int i = 0;
 
             // skip to the start of the page
-            for ( ; i<start && entries.hasNext(); i++) entries.next();
+            for (; i < start && entries.hasNext(); i++)
+                entries.next();
 
             // return entries up to the page size
-            for ( ; i<start+size && entries.hasNext(); i++) {
+            for (; i < start + size && entries.hasNext(); i++) {
                 response.addEntry(createTPSConnectorData(entries.next()));
             }
 
             // count the total entries
-            for ( ; entries.hasNext(); i++) entries.next();
+            for (; entries.hasNext(); i++)
+                entries.next();
             response.setTotal(i);
 
             if (start > 0) {
-                URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start-size, 0)).build();
+                URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start - size, 0)).build();
                 response.addLink(new Link("prev", uri));
             }
 
-            if (start+size < i) {
-                URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", start+size).build();
+            if (start + size < i) {
+                URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", start + size).build();
                 response.addLink(new Link("next", uri));
             }
 
@@ -114,7 +123,8 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou
 
     public TPSConnectorData getConnectorData(String id) {
 
-        if (id == null) throw new BadRequestException("TPS connector ID is null.");
+        if (id == null)
+            throw new BadRequestException("TPS connector ID is null.");
 
         try {
             if (!connectorExists(id))
@@ -131,8 +141,10 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou
     @Override
     public Response getConnector(String host, String port) {
 
-        if (host == null) throw new BadRequestException("TPS connector host is null.");
-        if (port == null) throw new BadRequestException("TPS connector port is null.");
+        if (host == null)
+            throw new BadRequestException("TPS connector host is null.");
+        if (port == null)
+            throw new BadRequestException("TPS connector port is null.");
 
         try {
             String id = getConnectorID(host, port);
@@ -151,8 +163,10 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou
     @Override
     public Response createConnector(String tpsHost, String tpsPort) {
 
-        if (tpsHost == null) throw new BadRequestException("TPS connector host is null.");
-        if (tpsPort == null) throw new BadRequestException("TPS connector port is null.");
+        if (tpsHost == null)
+            throw new BadRequestException("TPS connector host is null.");
+        if (tpsPort == null)
+            throw new BadRequestException("TPS connector port is null.");
 
         try {
             String id = getConnectorID(tpsHost, tpsPort);
@@ -245,7 +259,8 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou
             if (StringUtils.isEmpty(id))
                 throw new BadRequestException("Attempt to delete TPS connection with null or empty id");
 
-            if (!connectorExists(id)) return createNoContentResponse();
+            if (!connectorExists(id))
+                return createNoContentResponse();
 
             deleteSharedSecret(id);
             cs.removeSubStore("tps." + id);
@@ -263,8 +278,10 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou
     @Override
     public Response deleteConnector(String host, String port) {
 
-        if (host == null) throw new BadRequestException("TPS connector host is null.");
-        if (port == null) throw new BadRequestException("TPS connector port is null.");
+        if (host == null)
+            throw new BadRequestException("TPS connector host is null.");
+        if (port == null)
+            throw new BadRequestException("TPS connector port is null.");
 
         String id;
         try {
@@ -281,7 +298,10 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou
     @Override
     public Response createSharedSecret(String id) {
 
-        if (id == null) throw new BadRequestException("TPS connector ID is null.");
+        CMS.debug("TPSConnectorService.createSharedSecret.id: " + id);
+
+        if (id == null)
+            throw new BadRequestException("TPS connector ID is null.");
 
         try {
             if (!connectorExists(id)) {
@@ -293,9 +313,13 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou
 
             // get user cert
             IUser user = userGroupManager.getUser(userid);
+
+            CMS.debug("TPSConnectorService.createSharedSecret.userid: " + userid);
             X509Certificate[] certs = user.getX509Certificates();
 
             String nickname = userid + " sharedSecret";
+
+            CMS.debug("TPSConnectorService.createSharedSecret. nickname: " + nickname);
             if (CryptoUtil.sharedSecretExists(nickname)) {
                 throw new BadRequestException("Shared secret already exists");
             }
@@ -305,9 +329,21 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou
             cs.putString("tps." + id + ".nickname", nickname);
             cs.commit(true);
 
-            byte[] wrappedKey = CryptoUtil.exportSharedSecret(nickname, certs[0]);
+            //Create des3 session sym key to wrap the shared secret.
+            SymmetricKey tempKey = createDes3SessionKeyOnInternal();
+
+            if (tempKey == null) {
+                return createNoContentResponse();
+            }
+
+            List<byte[]> listWrappedKeys = CryptoUtil.exportSharedSecret(nickname, certs[0], tempKey);
+
+            byte[] wrappedSessionKey = listWrappedKeys.get(0);
+            byte[] wrappedSharedSecret = listWrappedKeys.get(1);
+
             KeyData keyData = new KeyData();
-            keyData.setWrappedPrivateData(Utils.base64encode(wrappedKey));
+            keyData.setWrappedPrivateData(Utils.base64encode(wrappedSessionKey));
+            keyData.setAdditionalWrappedPrivateData(Utils.base64encode(wrappedSharedSecret));
 
             return createOKResponse(keyData);
 
@@ -341,7 +377,8 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou
     @Override
     public Response replaceSharedSecret(String id) {
 
-        if (id == null) throw new BadRequestException("TPS connector ID is null.");
+        if (id == null)
+            throw new BadRequestException("TPS connector ID is null.");
 
         try {
             if (!connectorExists(id)) {
@@ -362,9 +399,22 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou
 
             CryptoUtil.deleteSharedSecret(nickname);
             CryptoUtil.createSharedSecret(nickname);
-            byte[] wrappedKey = CryptoUtil.exportSharedSecret(nickname, certs[0]);
+
+            //Create des3 session sym key to wrap the shared secret.
+            SymmetricKey tempKey = createDes3SessionKeyOnInternal();
+
+            if (tempKey == null) {
+                return createNoContentResponse();
+            }
+
+            List<byte[]> listWrappedKeys = CryptoUtil.exportSharedSecret(nickname,certs[0], tempKey);
+
+            byte[] wrappedSessionKey = listWrappedKeys.get(0);
+            byte[] wrappedSharedSecret = listWrappedKeys.get(1);
+
             KeyData keyData = new KeyData();
-            keyData.setWrappedPrivateData(Utils.base64encode(wrappedKey));
+            keyData.setWrappedPrivateData(Utils.base64encode(wrappedSessionKey));
+            keyData.setAdditionalWrappedPrivateData(Utils.base64encode(wrappedSharedSecret));
 
             return createOKResponse(keyData);
 
@@ -380,7 +430,8 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou
     @Override
     public Response deleteSharedSecret(String id) {
 
-        if (id == null) throw new BadRequestException("TPS connector ID is null.");
+        if (id == null)
+            throw new BadRequestException("TPS connector ID is null.");
 
         try {
             if (!connectorExists(id)) {
@@ -415,8 +466,10 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou
     @Override
     public Response getSharedSecret(String id) {
 
-        if (id == null) throw new BadRequestException("TPS connector ID is null.");
+        if (id == null)
+            throw new BadRequestException("TPS connector ID is null.");
 
+        CMS.debug("TPSConnectorServlet.getSharedSecret: id : " + id);
         try {
             if (!connectorExists(id)) {
                 throw new ResourceNotFoundException("TPS connection does not exist");
@@ -434,9 +487,20 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou
             IUser user = userGroupManager.getUser(userid);
             X509Certificate[] certs = user.getX509Certificates();
 
-            byte[] wrappedKey = CryptoUtil.exportSharedSecret(nickname, certs[0]);
+            //Create des3 session sym key to wrap the shared secrt.
+            SymmetricKey tempKey = createDes3SessionKeyOnInternal();
+
+            if (tempKey == null) {
+                return createNoContentResponse();
+            }
+
+            List<byte[]> listWrappedKeys = CryptoUtil.exportSharedSecret(nickname, certs[0], tempKey);
+            byte[] wrappedSessionKey = listWrappedKeys.get(0);
+            byte[] wrappedSharedSecret = listWrappedKeys.get(1);
+
             KeyData keyData = new KeyData();
-            keyData.setWrappedPrivateData(Utils.base64encode(wrappedKey));
+            keyData.setWrappedPrivateData(Utils.base64encode(wrappedSessionKey));
+            keyData.setAdditionalWrappedPrivateData(Utils.base64encode(wrappedSharedSecret));
 
             return createOKResponse(keyData);
 
@@ -456,7 +520,7 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou
 
     private String getConnectorID(String host, String port) throws EBaseException {
         String tpsList = cs.getString(TPS_LIST, "");
-        for (String tpsID : StringUtils.split(tpsList,",")) {
+        for (String tpsID : StringUtils.split(tpsList, ",")) {
             TPSConnectorData data = createTPSConnectorData(tpsID);
             if (data.getHost().equals(host) && data.getPort().equals(port))
                 return tpsID;
@@ -486,7 +550,36 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou
         sorted.addAll(Arrays.asList(StringUtils.split(tpsList, ",")));
 
         int index = 0;
-        while (sorted.contains(Integer.toString(index))) index++;
+        while (sorted.contains(Integer.toString(index)))
+            index++;
         return Integer.toString(index);
     }
+
+    private SymmetricKey createDes3SessionKeyOnInternal() throws EBaseException {
+
+        SymmetricKey tempKey = null;
+        try {
+            CryptoManager cm = CryptoManager.getInstance();
+            CryptoToken token = cm.getInternalKeyStorageToken();
+            KeyGenerator kg = token.getKeyGenerator(KeyGenAlgorithm.DES3);
+
+            SymmetricKey.Usage usages[] = new SymmetricKey.Usage[4];
+            usages[0] = SymmetricKey.Usage.WRAP;
+            usages[1] = SymmetricKey.Usage.UNWRAP;
+            usages[2] = SymmetricKey.Usage.ENCRYPT;
+            usages[3] = SymmetricKey.Usage.DECRYPT;
+
+            kg.setKeyUsages(usages);
+            kg.temporaryKeys(true);
+            tempKey = kg.generate();
+        } catch (NoSuchAlgorithmException | TokenException | IllegalStateException | CharConversionException
+                | NotInitializedException e) {
+            CMS.debug("TPSConnectorService.createDes3SesisonKeyOnInternal: Can't generate temporary session key.");
+
+            throw new EBaseException(e);
+        }
+
+        return tempKey;
+    }
+
 }
diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java b/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
index ff64208..94e6497 100644
--- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
+++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
@@ -33,6 +33,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import netscape.security.x509.RevocationReason;
+
 import org.dogtagpki.server.tps.TPSSession;
 import org.dogtagpki.server.tps.TPSSubsystem;
 import org.dogtagpki.server.tps.authentication.AuthUIParameter;
@@ -96,8 +98,6 @@ import com.netscape.certsrv.tps.token.TokenStatus;
 import com.netscape.cms.servlet.tks.SecureChannelProtocol;
 import com.netscape.symkey.SessionKey;
 
-import netscape.security.x509.RevocationReason;
-
 public class TPSProcessor {
 
     public static final int RESULT_NO_ERROR = 0;
@@ -686,9 +686,6 @@ public class TPSProcessor {
                sessionKey =  (PK11SymKey) protocol.unwrapWrappedSymKeyOnToken(token, sharedSecret, sessionKeyWrapped.toBytesArray(), false);
 
 
-
-
-
                 if (sessionKey == null) {
                     CMS.debug("TPSProcessor.generateSecureChannel: Can't extract session key!");
                     throw new TPSException("TPSProcessor.generateSecureChannel: Can't extract session key!",
@@ -708,7 +705,6 @@ public class TPSProcessor {
                             TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
                 }
 
-                //CMS.debug("TPSProcessor.generateSecureChannel: retrieved enc session key: " + encSessionKey);
                 CMS.debug("TPSProcessor.generateSecureChannel: retrieved enc session key");
 
                 TPSBuffer drmDesKey = null;
diff --git a/base/tps/src/org/dogtagpki/server/tps/rest/TPSInstallerService.java b/base/tps/src/org/dogtagpki/server/tps/rest/TPSInstallerService.java
index dab80e4..068293e 100644
--- a/base/tps/src/org/dogtagpki/server/tps/rest/TPSInstallerService.java
+++ b/base/tps/src/org/dogtagpki/server/tps/rest/TPSInstallerService.java
@@ -142,11 +142,21 @@ public class TPSInstallerService extends SystemConfigService  {
                 ConfigurationUtils.exportTransportCert(secdomainURI, tksURI, transportCert);
             }
 
+            String doImportStr = request.getImportSharedSecret();
+            CMS.debug("finalizeConfiguration: importSharedSecret:" + doImportStr);
             // generate shared secret from the tks
+
+            boolean doImport = false;
+
+            if("true".equalsIgnoreCase(doImportStr)) {
+                CMS.debug("finalizeConfiguration: importSharedSecret: importSharedSecret is true.");
+                doImport = true;
+            }
+
             ConfigurationUtils.getSharedSecret(
                     tksURI.getHost(),
                     tksURI.getPort(),
-                    Boolean.getBoolean(request.getImportSharedSecret()));
+                    doImport);
 
         } catch (URISyntaxException e) {
             throw new BadRequestException("Invalid URI for CA, TKS or KRA");
diff --git a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java
index 979b047..6e67629 100644
--- a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java
+++ b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java
@@ -47,7 +47,32 @@ import java.util.Random;
 import java.util.StringTokenizer;
 import java.util.Vector;
 
-import javax.crypto.SecretKey;
+import netscape.security.pkcs.PKCS10;
+import netscape.security.pkcs.PKCS10Attribute;
+import netscape.security.pkcs.PKCS10Attributes;
+import netscape.security.pkcs.PKCS7;
+import netscape.security.pkcs.PKCS9Attribute;
+import netscape.security.util.BigInt;
+import netscape.security.util.DerInputStream;
+import netscape.security.util.DerOutputStream;
+import netscape.security.util.DerValue;
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.AlgorithmId;
+import netscape.security.x509.CertificateAlgorithmId;
+import netscape.security.x509.CertificateChain;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateIssuerName;
+import netscape.security.x509.CertificateSerialNumber;
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.x509.CertificateValidity;
+import netscape.security.x509.CertificateVersion;
+import netscape.security.x509.CertificateX509Key;
+import netscape.security.x509.Extensions;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X500Signer;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+import netscape.security.x509.X509Key;
 
 import org.mozilla.jss.CryptoManager;
 import org.mozilla.jss.CryptoManager.NotInitializedException;
@@ -82,7 +107,6 @@ import org.mozilla.jss.crypto.NoSuchItemOnTokenException;
 import org.mozilla.jss.crypto.ObjectNotFoundException;
 import org.mozilla.jss.crypto.PBEAlgorithm;
 import org.mozilla.jss.crypto.PrivateKey;
-import org.mozilla.jss.crypto.SecretKeyFacade;
 import org.mozilla.jss.crypto.Signature;
 import org.mozilla.jss.crypto.SignatureAlgorithm;
 import org.mozilla.jss.crypto.SymmetricKey;
@@ -108,33 +132,6 @@ import org.mozilla.jss.util.Password;
 import com.netscape.cmsutil.util.Cert;
 import com.netscape.cmsutil.util.Utils;
 
-import netscape.security.pkcs.PKCS10;
-import netscape.security.pkcs.PKCS10Attribute;
-import netscape.security.pkcs.PKCS10Attributes;
-import netscape.security.pkcs.PKCS7;
-import netscape.security.pkcs.PKCS9Attribute;
-import netscape.security.util.BigInt;
-import netscape.security.util.DerInputStream;
-import netscape.security.util.DerOutputStream;
-import netscape.security.util.DerValue;
-import netscape.security.util.ObjectIdentifier;
-import netscape.security.x509.AlgorithmId;
-import netscape.security.x509.CertificateAlgorithmId;
-import netscape.security.x509.CertificateChain;
-import netscape.security.x509.CertificateExtensions;
-import netscape.security.x509.CertificateIssuerName;
-import netscape.security.x509.CertificateSerialNumber;
-import netscape.security.x509.CertificateSubjectName;
-import netscape.security.x509.CertificateValidity;
-import netscape.security.x509.CertificateVersion;
-import netscape.security.x509.CertificateX509Key;
-import netscape.security.x509.Extensions;
-import netscape.security.x509.X500Name;
-import netscape.security.x509.X500Signer;
-import netscape.security.x509.X509CertImpl;
-import netscape.security.x509.X509CertInfo;
-import netscape.security.x509.X509Key;
-
 @SuppressWarnings("serial")
 public class CryptoUtil {
 
@@ -2076,55 +2073,117 @@ public class CryptoUtil {
         km.deleteUniqueNamedKey(nickname);
     }
 
-    public static byte[] exportSharedSecret(String nickname, java.security.cert.X509Certificate wrappingCert)
+    // Return a list of two wrapped keys: first element: temp DES3 key wrapped by cert , second element: shared secret wrapped by temp DES3 key
+    public static List<byte[]> exportSharedSecret(String nickname, java.security.cert.X509Certificate wrappingCert,SymmetricKey wrappingKey)
             throws NotInitializedException, TokenException, IOException, NoSuchAlgorithmException, InvalidKeyException,
             InvalidAlgorithmParameterException, InvalidKeyFormatException {
         CryptoManager cm = CryptoManager.getInstance();
         CryptoToken token = cm.getInternalKeyStorageToken();
+
+        List<byte[]> listWrappedKeys = new ArrayList<byte[]>();
+
+
         KeyManager km = new KeyManager(token);
         if (!km.uniqueNamedKeyExists(nickname)) {
             throw new IOException("Shared secret " + nickname + " does not exist");
         }
-        SecretKey skey = km.lookupUniqueNamedKey(EncryptionAlgorithm.DES3_ECB, nickname);
+
+        SymmetricKey sharedSecretKey =  null;
+
+        try {
+            sharedSecretKey = getSymKeyByName(token, nickname);
+        } catch (Exception e) {
+            sharedSecretKey = null;
+        }
+
+        if (sharedSecretKey == null) {
+            throw new IOException("Shared secret " + nickname + " does not exist");
+        }
 
         KeyWrapper keyWrap = token.getKeyWrapper(KeyWrapAlgorithm.RSA);
         PublicKey pub = wrappingCert.getPublicKey();
         PK11PubKey pubK = PK11PubKey.fromSPKI(pub.getEncoded());
         keyWrap.initWrap(pubK, null);
-        byte[] wrappedKey = keyWrap.wrap(((SecretKeyFacade) skey).key);
-        return wrappedKey;
+
+        //Wrap the temp DES3 key with the cert
+        byte[] wrappedKey = keyWrap.wrap(wrappingKey);
+
+        listWrappedKeys.add(wrappedKey);
+        //Use the DES3 key to wrap the shared secret
+
+        KeyWrapper keyWrapSharedSecret = token.getKeyWrapper(KeyWrapAlgorithm.DES3_ECB);
+        keyWrapSharedSecret.initWrap(wrappingKey,null);
+
+        byte[] wrappedSharedSecret = keyWrapSharedSecret.wrap(sharedSecretKey);
+
+        listWrappedKeys.add(wrappedSharedSecret);
+
+        if(listWrappedKeys.size() != 2) {
+            throw new IOException("Can't write out shared secret data to export for nickname: " + nickname);
+        }
+
+        return listWrappedKeys;
     }
 
-    /*
-    public static void importSharedSecret(KeyData data) throws EBaseException, NotInitializedException, TokenException,
+
+    public static void importSharedSecret(byte[] wrappedSessionKey,byte[] wrappedSharedSecret,String subsystemCertNickname,String sharedSecretNickname) throws Exception, NotInitializedException, TokenException,
             NoSuchAlgorithmException, ObjectNotFoundException, InvalidKeyException, InvalidAlgorithmParameterException,
             IOException {
-        byte[] wrappedKey = Utils.base64decode(data.getWrappedPrivateData());
-
-        IConfigStore cs = CMS.getConfigStore();
-        String subsystemNick = cs.getString("tps.cert.subsystem.nickname");
-        String keyNick = cs.getString("conn.tks1.tksSharedSymKeyName", "sharedSecret");
 
         CryptoManager cm = CryptoManager.getInstance();
         CryptoToken token = cm.getInternalKeyStorageToken();
+
         KeyManager km = new KeyManager(token);
 
-        if (km.uniqueNamedKeyExists(keyNick)) {
-            throw new IOException("Shared secret " + keyNick + " already exists");
+        if (km.uniqueNamedKeyExists(sharedSecretNickname)) {
+            throw new IOException("Shared secret " + sharedSecretNickname + " already exists");
         }
 
+        //Unwrap session key
+
         KeyWrapper keyWrap = token.getKeyWrapper(KeyWrapAlgorithm.RSA);
-        X509Certificate cert = cm.findCertByNickname(subsystemNick);
+        X509Certificate cert = cm.findCertByNickname(subsystemCertNickname);
         PrivateKey subsystemPrivateKey = cm.findPrivKeyByCert(cert);
         keyWrap.initUnwrap(subsystemPrivateKey, null);
 
-        @SuppressWarnings("unused")
-        SymmetricKey unwrapped = keyWrap.unwrapSymmetric(wrappedKey, SymmetricKey.DES,
-                SymmetricKey.Usage.DECRYPT, 0);
+        SymmetricKey unwrappedSessionKey = keyWrap.unwrapSymmetric(wrappedSessionKey, SymmetricKey.DES3,
+                0);
+
+        SymmetricKey unwrappedSharedSecret = null;
+
+        //Unwrap shared secret permanently with session key
+
+        KeyWrapper sharedSecretWrap = token.getKeyWrapper(KeyWrapAlgorithm.DES3_ECB);
+        sharedSecretWrap.initUnwrap(unwrappedSessionKey,null);
+        unwrappedSharedSecret = sharedSecretWrap.unwrapSymmetricPerm(wrappedSharedSecret,SymmetricKey.DES3,0 );
+        unwrappedSharedSecret.setNickName(sharedSecretNickname);
+    }
 
-        // TODO - I have a key - now what to do with it?
-        // need to somehow import/label the symkey
-    }*/
+    public static SymmetricKey getSymKeyByName(CryptoToken token, String name) throws Exception {
+
+        String method = "CryptoUtil.getSymKeyByName:";
+        if (token == null || name == null) {
+            throw new Exception(method + "Invalid input data!");
+        }
+        SymmetricKey[] keys;
+
+        try {
+            keys = token.getCryptoStore().getSymmetricKeys();
+        } catch (TokenException e) {
+            throw new Exception(method + "Can't get the list of symmetric keys!");
+        }
+        int len = keys.length;
+        for (int i = 0; i < len; i++) {
+            SymmetricKey cur = keys[i];
+            if (cur != null) {
+                if (name.equals(cur.getNickName())) {
+                    return cur;
+                }
+            }
+        }
+
+        return null;
+    }
 
     public static String[] getECcurves() {
         return ecCurves;
-- 
2.5.0

