>From bda97cba823f2b20a40b6d475da2784af50ac367 Mon Sep 17 00:00:00 2001
From: Christina Fu <cfu@redhat.com>
Date: Mon, 10 Mar 2014 14:46:14 -0700
Subject: [PATCH] Ticket #888 - (part 1: TKS) TPS rewrite: provide remote
 authority functions

---
 base/common/src/org/dogtagpki/tps/main/Util.java   |  11 +
 .../com/netscape/cms/servlet/tks/TokenServlet.java |  99 ++---
 .../dogtagpki/server/connector/IRemoteRequest.java |  60 +++
 .../server/tps/cms/ConnectionManager.java          |  22 --
 .../server/tps/cms/RemoteRequestHandler.java       |  91 +++++
 .../tps/cms/TKSComputeRandomDataResponse.java      |  40 ++
 .../tps/cms/TKSComputeSessionKeyResponse.java      |  61 +++
 .../tps/cms/TKSCreateKeySetDataResponse.java       |  41 ++
 .../server/tps/cms/TKSEncryptDataResponse.java     |  41 ++
 .../server/tps/cms/TKSRemoteRequestHandler.java    | 427 +++++++++++++++++++++
 .../org/dogtagpki/server/tps/cms/TKSResponse.java  |  40 ++
 11 files changed, 863 insertions(+), 70 deletions(-)
 create mode 100644 base/server/cms/src/org/dogtagpki/server/connector/IRemoteRequest.java
 create mode 100644 base/tps-tomcat/src/org/dogtagpki/server/tps/cms/RemoteRequestHandler.java
 create mode 100644 base/tps-tomcat/src/org/dogtagpki/server/tps/cms/TKSComputeRandomDataResponse.java
 create mode 100644 base/tps-tomcat/src/org/dogtagpki/server/tps/cms/TKSComputeSessionKeyResponse.java
 create mode 100644 base/tps-tomcat/src/org/dogtagpki/server/tps/cms/TKSCreateKeySetDataResponse.java
 create mode 100644 base/tps-tomcat/src/org/dogtagpki/server/tps/cms/TKSEncryptDataResponse.java
 create mode 100644 base/tps-tomcat/src/org/dogtagpki/server/tps/cms/TKSRemoteRequestHandler.java
 create mode 100644 base/tps-tomcat/src/org/dogtagpki/server/tps/cms/TKSResponse.java

diff --git a/base/common/src/org/dogtagpki/tps/main/Util.java b/base/common/src/org/dogtagpki/tps/main/Util.java
index a493dd6..aba6c6e 100644
--- a/base/common/src/org/dogtagpki/tps/main/Util.java
+++ b/base/common/src/org/dogtagpki/tps/main/Util.java
@@ -24,6 +24,8 @@ import java.io.UnsupportedEncodingException;
 import java.net.URLDecoder;
 import java.net.URLEncoder;
 
+import com.netscape.cmsutil.util.Utils;
+
 
 public class Util {
 
@@ -125,4 +127,13 @@ public class Util {
         return result.toString();
     }
 
+    public static String specialEncode(TPSBuffer data) {
+        return Utils.SpecialEncode(data.toBytesArray());
+    }
+
+    public static TPSBuffer specialDecode(String str) {
+        byte[] data = Utils.SpecialDecode(str);
+        TPSBuffer tbuf = new TPSBuffer(data);
+        return tbuf;
+    }
 }
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 7669756..9b0c2bc 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
@@ -48,6 +48,8 @@ import com.netscape.cms.servlet.base.CMSServlet;
 import com.netscape.cms.servlet.common.CMSRequest;
 import com.netscape.symkey.SessionKey;
 
+import org.dogtagpki.server.connector.IRemoteRequest;
+
 /**
  * A class representings an administration servlet for Token Key
  * Service Authority. This servlet is responsible to serve
@@ -165,14 +167,14 @@ public class TokenServlet extends CMSServlet {
     private void setDefaultSlotAndKeyName(HttpServletRequest req) {
         try {
 
-            String keySet = req.getParameter("keySet");
+            String keySet = req.getParameter(IRemoteRequest.TOKEN_KEYSET);
             if (keySet == null || keySet.equals("")) {
                 keySet = "defKeySet";
             }
             CMS.debug("keySet selected: " + keySet);
 
             String masterKeyPrefix = CMS.getConfigStore().getString("tks.master_key_prefix", null);
-            String temp = req.getParameter("KeyInfo"); //#xx#xx
+            String temp = req.getParameter(IRemoteRequest.TOKEN_KEYINFO); //#xx#xx
             String keyInfoMap = "tks." + keySet + ".mk_mappings." + temp;
             String mappingValue = CMS.getConfigStore().getString(keyInfoMap, null);
             if (mappingValue != null) {
@@ -187,9 +189,9 @@ public class TokenServlet extends CMSServlet {
 
                 }
             }
-            if (req.getParameter("newKeyInfo") != null) // for diversification
+            if (req.getParameter(IRemoteRequest.TOKEN_NEW_KEYINFO) != null) // for diversification
             {
-                temp = req.getParameter("newKeyInfo"); //#xx#xx
+                temp = req.getParameter(IRemoteRequest.TOKEN_NEW_KEYINFO); //#xx#xx
                 String newKeyInfoMap = "tks." + keySet + ".mk_mappings." + temp;
                 String newMappingValue = CMS.getConfigStore().getString(newKeyInfoMap, null);
                 if (newMappingValue != null) {
@@ -225,8 +227,8 @@ public class TokenServlet extends CMSServlet {
         String badParams = "";
         String transportKeyName = "";
 
-        String rCUID = req.getParameter("CUID");
-        String keySet = req.getParameter("keySet");
+        String rCUID = req.getParameter(IRemoteRequest.TOKEN_CUID);
+        String keySet = req.getParameter(IRemoteRequest.TOKEN_KEYSET);
         if (keySet == null || keySet.equals("")) {
             keySet = "defKeySet";
         }
@@ -271,7 +273,7 @@ public class TokenServlet extends CMSServlet {
         if (!useSoftToken_s.equalsIgnoreCase("true"))
             useSoftToken_s = "false";
 
-        String rServersideKeygen = req.getParameter("serversideKeygen");
+        String rServersideKeygen = req.getParameter(IRemoteRequest.SERVER_SIDE_KEYGEN);
         if (rServersideKeygen.equals("true")) {
             CMS.debug("TokenServlet: serversideKeygen requested");
             serversideKeygen = true;
@@ -288,10 +290,10 @@ public class TokenServlet extends CMSServlet {
 
         CMS.debug("TokenServlet: ComputeSessionKey(): tksSharedSymKeyName: " + transportKeyName);
 
-        String rcard_challenge = req.getParameter("card_challenge");
-        String rhost_challenge = req.getParameter("host_challenge");
-        String rKeyInfo = req.getParameter("KeyInfo");
-        String rcard_cryptogram = req.getParameter("card_cryptogram");
+        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);
+        String rcard_cryptogram = req.getParameter(IRemoteRequest.TOKEN_CARD_CRYPTOGRAM);
         if ((rCUID == null) || (rCUID.equals(""))) {
             CMS.debug("TokenServlet: ComputeSessionKey(): missing request parameter: CUID");
             badParams += " CUID,";
@@ -659,32 +661,32 @@ public class TokenServlet extends CMSServlet {
                 errorMsg = "Missing input parameters :" + badParams;
             }
 
-            value = "status=" + status;
+            value = IRemoteRequest.RESPONSE_STATUS+"=" + status;
         } else {
             if (serversideKeygen == true) {
                 StringBuffer sb = new StringBuffer();
-                sb.append("status=0&");
-                sb.append("sessionKey=");
+                sb.append(IRemoteRequest.RESPONSE_STATUS+"=0&");
+                sb.append(IRemoteRequest.TKS_RESPONSE_SessionKey+"=");
                 sb.append(outputString);
-                sb.append("&hostCryptogram=");
+                sb.append("&"+IRemoteRequest.TKS_RESPONSE_HostCryptogram+"=");
                 sb.append(cryptogram);
-                sb.append("&encSessionKey=");
+                sb.append("&"+IRemoteRequest.TKS_RESPONSE_EncSessionKey+"=");
                 sb.append(encSessionKeyString);
-                sb.append("&kek_wrapped_desKey=");
+                sb.append("&"+IRemoteRequest.TKS_RESPONSE_KEK_DesKey+"=");
                 sb.append(kek_wrapped_desKeyString);
-                sb.append("&keycheck=");
+                sb.append("&"+IRemoteRequest.TKS_RESPONSE_KeyCheck+"=");
                 sb.append(keycheck_s);
-                sb.append("&drm_trans_wrapped_desKey=");
+                sb.append("&"+IRemoteRequest.TKS_RESPONSE_DRM_Trans_DesKey+"=");
                 sb.append(drm_trans_wrapped_desKeyString);
                 value = sb.toString();
             } else {
                 StringBuffer sb = new StringBuffer();
-                sb.append("status=0&");
-                sb.append("sessionKey=");
+                sb.append(IRemoteRequest.RESPONSE_STATUS+"=0&");
+                sb.append(IRemoteRequest.TKS_RESPONSE_SessionKey+"=");
                 sb.append(outputString);
-                sb.append("&hostCryptogram=");
+                sb.append("&"+IRemoteRequest.TKS_RESPONSE_HostCryptogram+"=");
                 sb.append(cryptogram);
-                sb.append("&encSessionKey=");
+                sb.append("&"+IRemoteRequest.TKS_RESPONSE_EncSessionKey+"=");
                 sb.append(encSessionKeyString);
                 value = sb.toString();
             }
@@ -773,13 +775,13 @@ public class TokenServlet extends CMSServlet {
         String badParams = "";
 
         IConfigStore sconfig = CMS.getConfigStore();
-        String rnewKeyInfo = req.getParameter("newKeyInfo");
-        String newMasterKeyName = req.getParameter("newKeyInfo");
-        String oldMasterKeyName = req.getParameter("KeyInfo");
-        String rCUID = req.getParameter("CUID");
+        String rnewKeyInfo = req.getParameter(IRemoteRequest.TOKEN_NEW_KEYINFO);
+        String newMasterKeyName = req.getParameter(IRemoteRequest.TOKEN_NEW_KEYINFO);
+        String oldMasterKeyName = req.getParameter(IRemoteRequest.TOKEN_KEYINFO);
+        String rCUID = req.getParameter(IRemoteRequest.TOKEN_CUID);
         String auditMessage = "";
 
-        String keySet = req.getParameter("keySet");
+        String keySet = req.getParameter(IRemoteRequest.TOKEN_KEYSET);
         if (keySet == null || keySet.equals("")) {
             keySet = "defKeySet";
         }
@@ -854,13 +856,13 @@ public class TokenServlet extends CMSServlet {
             if (mNewKeyNickName != null)
                 newMasterKeyName = mNewKeyNickName;
 
-            String oldKeyInfoMap = "tks." + keySet + ".mk_mappings." + req.getParameter("KeyInfo"); //#xx#xx
+            String oldKeyInfoMap = "tks." + keySet + ".mk_mappings." + req.getParameter(IRemoteRequest.TOKEN_KEYINFO); //#xx#xx
             String oldMappingValue = CMS.getConfigStore().getString(oldKeyInfoMap, null);
             String oldSelectedToken = null;
             String oldKeyNickName = null;
             if (oldMappingValue == null) {
                 oldSelectedToken = CMS.getConfigStore().getString("tks.defaultSlot", "internal");
-                oldKeyNickName = req.getParameter("KeyInfo");
+                oldKeyNickName = req.getParameter(IRemoteRequest.TOKEN_KEYINFO);
             } else {
                 StringTokenizer st = new StringTokenizer(oldMappingValue, ":");
                 oldSelectedToken = st.nextToken();
@@ -913,7 +915,7 @@ public class TokenServlet extends CMSServlet {
         String status = "0";
 
         if (KeySetData != null && KeySetData.length > 1) {
-            value = "status=0&" + "keySetData=" +
+            value = IRemoteRequest.RESPONSE_STATUS+"=0&" + IRemoteRequest.TKS_RESPONSE_KeySetData+"=" +
                      com.netscape.cmsutil.util.Utils.SpecialEncode(KeySetData);
             CMS.debug("TokenServlet:process DiversifyKey.encode " + value);
         } else if (missingParam) {
@@ -922,11 +924,11 @@ public class TokenServlet extends CMSServlet {
                 badParams = badParams.substring(0, badParams.length() - 1);
             }
             errorMsg = "Missing input parameters: " + badParams;
-            value = "status=" + status;
+            value = IRemoteRequest.RESPONSE_STATUS+"=" + status;
         } else {
             errorMsg = "Problem diversifying key data.";
             status = "1";
-            value = "status=" + status;
+            value = IRemoteRequest.RESPONSE_STATUS+"=" + status;
         }
 
         resp.setContentLength(value.length());
@@ -979,10 +981,10 @@ public class TokenServlet extends CMSServlet {
         String badParams = "";
         IConfigStore sconfig = CMS.getConfigStore();
         encryptedData = null;
-        String rdata = req.getParameter("data");
-        String rKeyInfo = req.getParameter("KeyInfo");
-        String rCUID = req.getParameter("CUID");
-        String keySet = req.getParameter("keySet");
+        String rdata = req.getParameter(IRemoteRequest.TOKEN_DATA);
+        String rKeyInfo = req.getParameter(IRemoteRequest.TOKEN_KEYINFO);
+        String rCUID = req.getParameter(IRemoteRequest.TOKEN_CUID);
+        String keySet = req.getParameter(IRemoteRequest.TOKEN_KEYSET);
         if (keySet == null || keySet.equals("")) {
             keySet = "defKeySet";
         }
@@ -1102,9 +1104,10 @@ public class TokenServlet extends CMSServlet {
         String status = "0";
         if (encryptedData != null && encryptedData.length > 0) {
             // sending both the pre-encrypted and encrypted data back
-            value = "status=0&" + "data=" +
+            value = IRemoteRequest.RESPONSE_STATUS+"=0&"
+                    + IRemoteRequest.TOKEN_DATA+"=" +
                          com.netscape.cmsutil.util.Utils.SpecialEncode(data) +
-                         "&encryptedData=" +
+                    "&"+IRemoteRequest.TKS_RESPONSE_EncryptedData+"=" +
                          com.netscape.cmsutil.util.Utils.SpecialEncode(encryptedData);
         } else if (missingParam) {
             if (badParams.endsWith(",")) {
@@ -1112,11 +1115,11 @@ public class TokenServlet extends CMSServlet {
             }
             errorMsg = "Missing input parameters: " + badParams;
             status = "3";
-            value = "status=" + status;
+            value = IRemoteRequest.RESPONSE_STATUS+"=" + status;
         } else {
             errorMsg = "Problem encrypting data.";
             status = "1";
-            value = "status=" + status;
+            value = IRemoteRequest.RESPONSE_STATUS+"=" + status;
         }
 
         CMS.debug("TokenServlet:process EncryptData.encode " + value);
@@ -1197,7 +1200,7 @@ public class TokenServlet extends CMSServlet {
                     (String) sContext.get(SessionContext.USER_ID);
         }
 
-        String sDataSize = req.getParameter("dataNumBytes");
+        String sDataSize = req.getParameter(IRemoteRequest.TOKEN_DATA_NUM_BYTES);
 
         if (sDataSize == null || sDataSize.equals("")) {
             CMS.debug("TokenServlet::processComputeRandomData missing param dataNumBytes");
@@ -1259,9 +1262,9 @@ public class TokenServlet extends CMSServlet {
         resp.setContentType("text/html");
         String value = "";
 
-        value = "status=" + status;
+        value = IRemoteRequest.RESPONSE_STATUS+"=" + status;
         if (status.equals("0")) {
-            value = value + "&DATA=" + randomDataOut;
+            value = value + "&"+IRemoteRequest.TKS_RESPONSE_RandomData+"=" + randomDataOut;
         }
 
         try {
@@ -1327,15 +1330,15 @@ public class TokenServlet extends CMSServlet {
             return;
         }
 
-        String temp = req.getParameter("card_challenge");
+        String temp = req.getParameter(IRemoteRequest.TOKEN_CARD_CHALLENGE);
         setDefaultSlotAndKeyName(req);
         if (temp != null) {
             processComputeSessionKey(req, resp);
-        } else if (req.getParameter("data") != null) {
+        } else if (req.getParameter(IRemoteRequest.TOKEN_DATA) != null) {
             processEncryptData(req, resp);
-        } else if (req.getParameter("newKeyInfo") != null) {
+        } else if (req.getParameter(IRemoteRequest.TOKEN_NEW_KEYINFO) != null) {
             processDiversifyKey(req, resp);
-        } else if (req.getParameter("dataNumBytes") != null) {
+        } else if (req.getParameter(IRemoteRequest.TOKEN_DATA_NUM_BYTES) != null) {
             processComputeRandomData(req, resp);
         }
     }
diff --git a/base/server/cms/src/org/dogtagpki/server/connector/IRemoteRequest.java b/base/server/cms/src/org/dogtagpki/server/connector/IRemoteRequest.java
new file mode 100644
index 0000000..7697b56
--- /dev/null
+++ b/base/server/cms/src/org/dogtagpki/server/connector/IRemoteRequest.java
@@ -0,0 +1,60 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.connector;
+
+/**
+ * IRemoteRequest is the interface class for the remote
+ *     requests and responses
+ *
+ * @author cfu
+ */
+public interface IRemoteRequest {
+
+    public static final String SERVER_SIDE_KEYGEN = "serversideKeygen";
+    public static final String TOKEN_CUID = "CUID";
+    public static final String TOKEN_CARD_CHALLENGE = "card_challenge";
+    public static final String TOKEN_HOST_CHALLENGE = "host_challenge";
+    public static final String TOKEN_KEYINFO = "KeyInfo";
+    public static final String TOKEN_CARD_CRYPTOGRAM = "card_cryptogram";
+    public static final String TOKEN_KEYSET = "keySet";
+    public static final String TOKEN_DATA_NUM_BYTES = "dataNumBytes";
+    public static final String TOKEN_NEW_KEYINFO = "newKeyInfo";
+    public static final String TOKEN_DATA = "data";
+
+    public static final int RESPONSE_STATUS_NOT_FOUND = -1;
+    public static final String RESPONSE_STATUS = "status";
+
+    /* computeSessionKey responses */
+    public static final String TKS_RESPONSE_SessionKey = "sessionKey";
+    public static final String TKS_RESPONSE_EncSessionKey = "encSessionKey";
+    public static final String TKS_RESPONSE_KEK_DesKey = "kek_wrapped_desKey";
+    public static final String TKS_RESPONSE_DRM_Trans_DesKey = "drm_trans_wrapped_desKey";
+    public static final String TKS_RESPONSE_KeyCheck = "keycheck";
+    public static final String TKS_RESPONSE_HostCryptogram = "hostCryptogram";
+
+    /* createKeySetData response */
+    public static final String TKS_RESPONSE_KeySetData = "keySetData";
+
+    /* encryptData response */
+    public static final String TKS_RESPONSE_EncryptedData = "encryptedData";
+
+    /* computeRandomData response */
+    public static final String TKS_RESPONSE_RandomData = "randomData";
+
+}
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/ConnectionManager.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/ConnectionManager.java
index c9b88f1..e0c585b 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/ConnectionManager.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/ConnectionManager.java
@@ -201,26 +201,4 @@ public class ConnectionManager
         return connectors.get(connID);
     }
 
-    /*
-     * Get the XML parser for XML in text
-     *
-     * @param text XML in text
-     * @return XMLObject the parser
-     */
-    public XMLObject getXMLParser(String text) {
-        if (text == null) {
-            return null;
-        } else {
-            CMS.debug("ConnectionManager: getXMLparser(): parsing: "+ text);
-        }
-        try {
-            ByteArrayInputStream bis =
-                new ByteArrayInputStream(text.getBytes());
-            return new XMLObject(bis);
-        } catch (Exception e) {
-            CMS.debug("ConnectionManager: getXMLparser(): failed: "+ e);
-            throw new RuntimeException(e);
-        }
-    }
-
 }
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/RemoteRequestHandler.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/RemoteRequestHandler.java
new file mode 100644
index 0000000..ceed1c1
--- /dev/null
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/RemoteRequestHandler.java
@@ -0,0 +1,91 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.cms;
+
+import java.io.ByteArrayInputStream;
+import java.util.Hashtable;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.cmsutil.xml.XMLObject;
+
+/**
+ * RemoteRequestHandler is the base class for the remote authorities
+ *
+ * @author cfu
+ */
+public abstract class RemoteRequestHandler
+{
+    private static final String RESPONSE_SEPARATOR = "\\&";
+    private static final String NAME_VALUE_EQUAL = "=";
+
+    protected String connid;
+
+    /**
+     * parseResponse parses remote responses that take the form of '&'-separated
+     * name-value pairs
+     *
+     * @param content The exact string content in the HTTP response
+     * @return name-value pairs in a Hashtable
+     */
+    protected Hashtable<String, Object> parseResponse(String content)
+            throws EBaseException {
+        CMS.debug("RemoteRequestHandler: parseResponse(): begins:");
+        if (content == null) {
+            throw new EBaseException("RemoteRequestHandler: parserResponse(): no response content.");
+        }
+        Hashtable<String, Object> vars = new Hashtable<String, Object>();
+        String[] elements = content.split(RESPONSE_SEPARATOR);
+        CMS.debug("RemoteRequestHandler: parseResponse(): # of elements:" +
+            elements.length);
+        for (String nvs : elements) {
+            String[] nv = nvs.split(NAME_VALUE_EQUAL);
+            if (nv.length == 2) {
+                vars.put(nv[0], nv[1]);
+            } else {
+                // continue to parse through
+                CMS.debug("RemoteRequestHandler: parseResponse(): content contains element not conforming to <name>=<value>.");
+            }
+        }
+        return vars;
+    }
+
+    /**
+     * Get the XML parser for XML in text
+     *
+     * @param text XML in text
+     * @return XMLObject the parser
+     */
+    protected XMLObject getXMLparser(String text) {
+        if (text == null) {
+            return null;
+        } else {
+            CMS.debug("RemoteRequestHandler: getXMLparser(): parsing: " + text);
+        }
+        try {
+            ByteArrayInputStream bis =
+                    new ByteArrayInputStream(text.getBytes());
+            return new XMLObject(bis);
+        } catch (Exception e) {
+            CMS.debug("RemoteRequestHandler: getXMLparser(): failed: " + e);
+            throw new RuntimeException(e);
+        }
+    }
+
+}
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/TKSComputeRandomDataResponse.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/TKSComputeRandomDataResponse.java
new file mode 100644
index 0000000..e601238
--- /dev/null
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/TKSComputeRandomDataResponse.java
@@ -0,0 +1,40 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.cms;
+
+import java.util.Hashtable;
+
+import org.dogtagpki.server.connector.IRemoteRequest;
+import org.dogtagpki.tps.main.TPSBuffer;
+
+/**
+ * TKSComputeRandomDataResponse is the class for the response to
+ * TKS Remote Request: computeRandomData()
+ *
+ */
+public class TKSComputeRandomDataResponse extends TKSResponse
+{
+    public TKSComputeRandomDataResponse(Hashtable<String, Object> ht) {
+        nameValTable = ht;
+    }
+
+    public TPSBuffer getRandomData() {
+        return (TPSBuffer) nameValTable.get(IRemoteRequest.TKS_RESPONSE_RandomData);
+    }
+}
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/TKSComputeSessionKeyResponse.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/TKSComputeSessionKeyResponse.java
new file mode 100644
index 0000000..95d711f
--- /dev/null
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/TKSComputeSessionKeyResponse.java
@@ -0,0 +1,61 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.cms;
+
+import java.util.Hashtable;
+
+import org.dogtagpki.server.connector.IRemoteRequest;
+import org.dogtagpki.tps.main.TPSBuffer;
+
+/**
+ * TKSComputeSessionKeyResponse is the class for the response to
+ * TKS Remote Request: computeSessionKey()
+ *
+ */
+public class TKSComputeSessionKeyResponse extends TKSResponse
+{
+
+    public TKSComputeSessionKeyResponse(Hashtable<String, Object> ht) {
+        nameValTable = ht;
+    }
+
+    public TPSBuffer getKeySetData() {
+        return (TPSBuffer) nameValTable.get(IRemoteRequest.TKS_RESPONSE_KeySetData);
+    }
+
+    public TPSBuffer getSessionKey() {
+        return (TPSBuffer) nameValTable.get(IRemoteRequest.TKS_RESPONSE_SessionKey);
+    }
+
+    public TPSBuffer getEncSessionKey() {
+        return (TPSBuffer) nameValTable.get(IRemoteRequest.TKS_RESPONSE_EncSessionKey);
+    }
+
+    public TPSBuffer getDRM_Trans_DesKey() {
+        return (TPSBuffer) nameValTable.get(IRemoteRequest.TKS_RESPONSE_DRM_Trans_DesKey);
+    }
+
+    public TPSBuffer getKeyCheck() {
+        return (TPSBuffer) nameValTable.get(IRemoteRequest.TKS_RESPONSE_KeyCheck);
+    }
+
+    public TPSBuffer getHostCryptogram() {
+        return (TPSBuffer) nameValTable.get(IRemoteRequest.TKS_RESPONSE_HostCryptogram);
+    }
+}
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/TKSCreateKeySetDataResponse.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/TKSCreateKeySetDataResponse.java
new file mode 100644
index 0000000..5178d62
--- /dev/null
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/TKSCreateKeySetDataResponse.java
@@ -0,0 +1,41 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.cms;
+
+import java.util.Hashtable;
+
+import org.dogtagpki.server.connector.IRemoteRequest;
+import org.dogtagpki.tps.main.TPSBuffer;
+
+/**
+ * TKSCreateKeySetDataResponse is the class for the response to
+ * TKS Remote Request: createKeySetData
+ *
+ */
+public class TKSCreateKeySetDataResponse extends TKSResponse
+{
+
+    public TKSCreateKeySetDataResponse(Hashtable<String, Object> ht) {
+        nameValTable = ht;
+    }
+
+    public TPSBuffer getKeySetData() {
+        return (TPSBuffer) nameValTable.get(IRemoteRequest.TKS_RESPONSE_KeySetData);
+    }
+}
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/TKSEncryptDataResponse.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/TKSEncryptDataResponse.java
new file mode 100644
index 0000000..e11d9e6
--- /dev/null
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/TKSEncryptDataResponse.java
@@ -0,0 +1,41 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.cms;
+
+import java.util.Hashtable;
+
+import org.dogtagpki.server.connector.IRemoteRequest;
+import org.dogtagpki.tps.main.TPSBuffer;
+
+/**
+ * TKSEncryptDataResponse is the class for the response to
+ * TKS Remote Request: encryptData
+ *
+ */
+public class TKSEncryptDataResponse extends TKSResponse
+{
+
+    public TKSEncryptDataResponse(Hashtable<String, Object> ht) {
+        nameValTable = ht;
+    }
+
+    public TPSBuffer getEncryptedData() {
+        return (TPSBuffer) nameValTable.get(IRemoteRequest.TKS_RESPONSE_EncryptedData);
+    }
+}
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/TKSRemoteRequestHandler.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/TKSRemoteRequestHandler.java
new file mode 100644
index 0000000..a94306c
--- /dev/null
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/TKSRemoteRequestHandler.java
@@ -0,0 +1,427 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.cms;
+
+import java.util.Hashtable;
+
+import org.dogtagpki.server.connector.IRemoteRequest;
+import org.dogtagpki.server.tps.TPSSubsystem;
+import org.dogtagpki.tps.main.TPSBuffer;
+import org.dogtagpki.tps.main.Util;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.cmscore.connector.HttpConnector;
+import com.netscape.cmsutil.http.HttpResponse;
+
+/**
+ * TKSRemoteRequestHandler is a class representing remote requests
+ * offered by the Token Key Service Authority (TKS)
+ * On a successful return, name/value pairs are provided in a Hashtable where
+ * all contents are URL decoded if needed
+ *
+ * @author cfu
+ */
+public class TKSRemoteRequestHandler extends RemoteRequestHandler
+{
+    public TKSRemoteRequestHandler(String connID) {
+        connid = connID;
+    }
+
+    /*
+     * computeSessionKey
+     *
+     * Usage Example:
+     *   TKSRemoteRequestHandler tksReq = new TKSRemoteRequestHandler("tks1");
+     *   TKSComputeSessionKeyResponse responseObj =
+     *     tksReq.computeSessionKey(
+     *      cuid,
+     *      keyInfo,
+     *      card_challenge,
+     *      card_cryptogram,
+     *      host_challenge);
+     *   - on success return, one can say
+     *    TPSBuffer value = responseObj.getSessionKey();
+     *      to get response param value session key
+     *
+     * @param cuid token cuid
+     * @param keyInfo keyInfo
+     * @param card_challenge card challenge
+     * @param card_cryptogram card cryptogram
+     * @param host_challenge host challenge
+     * @return response TKSComputeSessionKeyResponse class object
+     */
+    public TKSComputeSessionKeyResponse computeSessionKey(
+            TPSBuffer cuid,
+            TPSBuffer keyInfo,
+            TPSBuffer card_challenge,
+            TPSBuffer card_cryptogram,
+            TPSBuffer host_challenge)
+            throws EBaseException {
+
+        CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): begins.");
+
+        TPSSubsystem subsystem =
+                (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+        IConfigStore conf = subsystem.getConfigStore();
+
+        /*
+         * TODO: obtain the profile name from current session when available.
+         *   Hard-code to "userKey" for now
+         */
+        boolean serverKeygen =
+                conf.getBoolean("op.enroll.userKey.keyGen.encryption.serverKeygen.enable",
+                        false);
+        String keySet =
+                conf.getString("connector." + connid + "keySet", "defKeySet");
+
+        CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): sending request to tks.");
+        HttpConnector conn =
+                (HttpConnector) subsystem.getConnectionManager().getConnector(connid);
+        HttpResponse resp =
+                conn.send("computeSessionKey",
+                        IRemoteRequest.SERVER_SIDE_KEYGEN + "=" + serverKeygen +
+                                "&" + IRemoteRequest.TOKEN_CUID + "=" + Util.specialEncode(cuid) +
+                                "&" + IRemoteRequest.TOKEN_CARD_CHALLENGE + "=" + Util.specialEncode(card_challenge) +
+                                "&" + IRemoteRequest.TOKEN_HOST_CHALLENGE + "=" + Util.specialEncode(host_challenge) +
+                                "&" + IRemoteRequest.TOKEN_KEYINFO + "=" + Util.specialEncode(keyInfo) +
+                                "&" + IRemoteRequest.TOKEN_CARD_CRYPTOGRAM + "=" + Util.specialEncode(card_cryptogram) +
+                                "&" + IRemoteRequest.TOKEN_KEYSET + "=" + keySet);
+
+        String content = resp.getContent();
+
+        if (content != null && !content.equals("")) {
+            Hashtable<String, Object> response =
+                    parseResponse(content);
+
+            /*
+             * When a value is not found in response, keep going so we know
+             * what else is missing
+             * Note: serverKeygen and !serverKeygen returns different set of
+             *     response values so "missing" might not be bad
+             */
+            String value = null;
+            Integer ist = new Integer(IRemoteRequest.RESPONSE_STATUS_NOT_FOUND);
+            value = (String) response.get(IRemoteRequest.RESPONSE_STATUS);
+            if (value == null) {
+                CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): status not found.");
+                throw new EBaseException("TKSRemoteRequestHandler: computeSessionKey(): no status found.");
+            } else {
+                CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): got status = " + value);
+                ist = Integer.parseInt(value);
+                response.put(IRemoteRequest.RESPONSE_STATUS, ist);
+            }
+
+            value = (String) response.get(IRemoteRequest.TKS_RESPONSE_SessionKey);
+            if (value == null) {
+                CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): response missing name-value pair for: " +
+                        IRemoteRequest.TKS_RESPONSE_SessionKey);
+            } else {
+                CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): got IRemoteRequest.TKS_RESPONSE_SessionKey = ");
+                response.put(IRemoteRequest.TKS_RESPONSE_SessionKey, Util.specialDecode(value));
+            }
+
+            value = (String) response.get(IRemoteRequest.TKS_RESPONSE_EncSessionKey);
+            if (value == null) {
+                CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): response missing name-value pair for: " +
+                        IRemoteRequest.TKS_RESPONSE_EncSessionKey);
+            } else {
+                CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): got IRemoteRequest.TKS_RESPONSE_EncSessionKey = ");
+                response.put(IRemoteRequest.TKS_RESPONSE_EncSessionKey, Util.specialDecode(value));
+            }
+
+            value = (String) response.get(IRemoteRequest.TKS_RESPONSE_DRM_Trans_DesKey);
+            if (value == null) {
+                CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): response missing name-value pair for: " +
+                        IRemoteRequest.TKS_RESPONSE_DRM_Trans_DesKey);
+            } else {
+                CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): got IRemoteRequest.TKS_RESPONSE_DRM_Trans_DesKey = ");
+                response.put(IRemoteRequest.TKS_RESPONSE_DRM_Trans_DesKey, Util.specialDecode(value));
+            }
+
+            value = (String) response.get(IRemoteRequest.TKS_RESPONSE_KEK_DesKey);
+            if (value == null) {
+                CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): response missing name-value pair for: " +
+                        IRemoteRequest.TKS_RESPONSE_KEK_DesKey);
+            } else {
+                CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): got IRemoteRequest.TKS_RESPONSE_KEK_DesKey = ");
+                response.put(IRemoteRequest.TKS_RESPONSE_KEK_DesKey, Util.specialDecode(value));
+            }
+
+            value = (String) response.get(IRemoteRequest.TKS_RESPONSE_KeyCheck);
+            if (value == null) {
+                CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): response missing name-value pair for: " +
+                        IRemoteRequest.TKS_RESPONSE_KeyCheck);
+            } else {
+                CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): got IRemoteRequest.TKS_RESPONSE_KeyCheck = ");
+                response.put(IRemoteRequest.TKS_RESPONSE_KeyCheck, Util.specialDecode(value));
+            }
+
+            value = (String) response.get(IRemoteRequest.TKS_RESPONSE_HostCryptogram);
+            if (value == null) {
+                CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): response missing name-value pair for: " +
+                        IRemoteRequest.TKS_RESPONSE_HostCryptogram);
+            } else {
+                CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): got IRemoteRequest.TKS_RESPONSE_HostCryptogram = ");
+                response.put(IRemoteRequest.TKS_RESPONSE_HostCryptogram, Util.specialDecode(value));
+            }
+            CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): ends.");
+
+            return new TKSComputeSessionKeyResponse(response);
+        } else {
+            CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): no response content.");
+            throw new EBaseException("TKSRemoteRequestHandler: computeSessionKey(): no response content.");
+        }
+    }
+
+    /*
+     * createKeySetData
+     *
+     * Usage Example:
+     *   TKSRemoteRequestHandler tksReq = new TKSRemoteRequestHandler("tks1");
+     *   TKSCreateKeySetDataResponse responseObj = 
+     *     tksReq.createKeySetData(
+     *      NewMasterVer,
+     *      version,
+     *      cuid)
+     *   - on success return, one can say
+     *    TPSBuffer value = responseObj.getKeySetData();
+     *      to get response param value keySetData
+     *
+     * @param NewMasterVer newKeyInfo
+     * @param version keyInfo
+     * @param cuid token cuid
+     * @return response TKSCreateKeySetDataResponse class object
+     */
+    public TKSCreateKeySetDataResponse createKeySetData(
+            TPSBuffer NewMasterVer,
+            TPSBuffer version,
+            TPSBuffer cuid)
+            throws EBaseException {
+        CMS.debug("TKSRemoteRequestHandler: createKeySetData(): begins.");
+        TPSSubsystem subsystem =
+                (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+        IConfigStore conf = subsystem.getConfigStore();
+        String keySet =
+                conf.getString("connector." + connid + "keySet", "defKeySet");
+
+        CMS.debug("TKSRemoteRequestHandler: createKeySetData(): sending request to tks.");
+        HttpConnector conn =
+                (HttpConnector) subsystem.getConnectionManager().getConnector(connid);
+        HttpResponse resp =
+                conn.send("createKeySetData",
+                        IRemoteRequest.TOKEN_NEW_KEYINFO + "=" + Util.specialEncode(NewMasterVer) +
+                                "&" + IRemoteRequest.TOKEN_CUID + "=" + Util.specialEncode(cuid) +
+                                "&" + IRemoteRequest.TOKEN_KEYINFO + "=" + Util.specialEncode(version) +
+                                "&" + IRemoteRequest.TOKEN_KEYSET + "=" + keySet);
+
+        String content = resp.getContent();
+
+        if (content != null && !content.equals("")) {
+            Hashtable<String, Object> response =
+                    parseResponse(content);
+            if (response == null) {
+                CMS.debug("TKSRemoteRequestHandler: createKeySetData(): parseResponse returned null.");
+                return null;
+            }
+
+            /*
+             * When a value is not found in response, keep going so we know
+             * what else is missing
+             */
+            String value = null;
+            Integer ist = new Integer(IRemoteRequest.RESPONSE_STATUS_NOT_FOUND);
+            value = (String) response.get(IRemoteRequest.RESPONSE_STATUS);
+            if (value == null) {
+                CMS.debug("TKSRemoteRequestHandler: createKeySetData(): status not found.");
+            } else {
+                CMS.debug("TKSRemoteRequestHandler: createKeySetData(): got status = " + value);
+                ist = Integer.parseInt(value);
+                response.put(IRemoteRequest.RESPONSE_STATUS, ist);
+            }
+            value = (String) response.get(IRemoteRequest.TKS_RESPONSE_KeySetData);
+            if (value == null) {
+                CMS.debug("TKSRemoteRequestHandler: createKeySetData(): response missing name-value pair for: " +
+                        IRemoteRequest.TKS_RESPONSE_KeySetData);
+            } else {
+                CMS.debug("TKSRemoteRequestHandler: createKeySetData(): got IRemoteRequest.TKS_RESPONSE_KeySetData = ");
+                response.put(IRemoteRequest.TKS_RESPONSE_KeySetData, Util.specialDecode(value));
+            }
+            CMS.debug("TKSRemoteRequestHandler: createKeySetData(): ends.");
+
+            return new TKSCreateKeySetDataResponse(response);
+        } else {
+            CMS.debug("TKSRemoteRequestHandler: createKeySetData(): no response content.");
+            throw new EBaseException("TKSRemoteRequestHandler: createKeySetData(): no response content.");
+        }
+    }
+
+    /*
+     * computeRandomData
+     *
+     * Usage Example:
+     *   TKSRemoteRequestHandler tksReq = new TKSRemoteRequestHandler("tks1");
+     *   TKSComputeRandomDataResponse responseObj =
+     *     tksReq.computeRandomData(
+     *      dataSize)
+     *   - on success return, one can say
+     *     TPSBuffer value = responseObj.getRandomData();
+     *      to get response param value random data
+     *
+     * @param dataSize size of random data to be generated in number of bytes
+     * @return response TKSComputeRandomDataResponse class object
+     */
+    public TKSComputeRandomDataResponse computeRandomData(int dataSize)
+            throws EBaseException {
+        CMS.debug("TKSRemoteRequestHandler: computeRandomData(): begins.");
+        /*
+         * check for absurd dataSize values
+         */
+        if (dataSize <= 0 || dataSize > 1024) {
+            CMS.debug("TKSRemoteRequestHandler: computeRandomData(): invalid dataSize requested:" + dataSize);
+            throw new EBaseException("TKSRemoteRequestHandler: computeRandomData(): invalid dataSize requested");
+        }
+        CMS.debug("TKSRemoteRequestHandler: computeRandomData(): sending request to tks.");
+        TPSSubsystem subsystem =
+                (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+        HttpConnector conn =
+                (HttpConnector) subsystem.getConnectionManager().getConnector(connid);
+        HttpResponse resp =
+                conn.send("computeRandomData",
+                        IRemoteRequest.TOKEN_DATA_NUM_BYTES + "=" + dataSize);
+
+        String content = resp.getContent();
+
+        if (content != null && !content.equals("")) {
+            // CMS.debug("TKSRemoteRequestHandler: computeRandomData(): got content = " + content);
+            Hashtable<String, Object> response =
+                    parseResponse(content);
+
+            /*
+             * When a value is not found in response, keep going so we know
+             * what else is missing
+             */
+            String value = null;
+            Integer ist = new Integer(IRemoteRequest.RESPONSE_STATUS_NOT_FOUND);
+            value = (String) response.get(IRemoteRequest.RESPONSE_STATUS);
+            if (value == null) {
+                CMS.debug("TKSRemoteRequestHandler: computeRandomData(): status not found.");
+            } else {
+                CMS.debug("TKSRemoteRequestHandler: computeRandomData(): got status = " + value);
+                ist = Integer.parseInt(value);
+                response.put(IRemoteRequest.RESPONSE_STATUS, ist);
+            }
+            value = (String) response.get(IRemoteRequest.TKS_RESPONSE_RandomData);
+            if (value == null) {
+                CMS.debug("TKSRemoteRequestHandler: computeRandomData(): response missing name-value pair for: " +
+                        IRemoteRequest.TKS_RESPONSE_RandomData);
+            } else {
+                CMS.debug("TKSRemoteRequestHandler: computeRandomData(): got IRemoteRequest.TKS_RESPONSE_RandomData = "
+                        + value);
+                response.put(IRemoteRequest.TKS_RESPONSE_RandomData, Util.specialDecode(value));
+            }
+            CMS.debug("TKSRemoteRequestHandler: computeRandomData(): ends.");
+
+            return new TKSComputeRandomDataResponse(response);
+        } else {
+            CMS.debug("TKSRemoteRequestHandler: computeRandomData(): no response content.");
+            throw new EBaseException("TKSRemoteRequestHandler: computeRandomData(): no response content.");
+        }
+    }
+
+    /*
+     * encryptData
+     *
+     * Usage Example:
+     *   TKSRemoteRequestHandler tksReq = new TKSRemoteRequestHandler("tks1");
+     *   TKSEncryptDataResponse responseObj =
+     *     tksReq.encryptData(
+     *      dataSize)
+     *  - on success return, one can say
+     *    TPSBuffer value = responseObj.getEncryptedData();
+     *      to get response param value encrypted data
+     *
+     * @param cuid token cuid
+     * @param version keyInfo
+     * @param inData data to be encrypted
+     * @return response TKSEncryptDataResponse class object
+     */
+    public TKSEncryptDataResponse encryptData(
+            TPSBuffer cuid,
+            TPSBuffer version,
+            TPSBuffer inData)
+            throws EBaseException {
+        CMS.debug("TKSRemoteRequestHandler: encryptData(): begins.");
+
+        TPSSubsystem subsystem =
+                (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+        IConfigStore conf = subsystem.getConfigStore();
+
+        String keySet =
+                conf.getString("connector." + connid + "keySet", "defKeySet");
+
+        CMS.debug("TKSRemoteRequestHandler: encryptData(): sending request to tks.");
+        HttpConnector conn =
+                (HttpConnector) subsystem.getConnectionManager().getConnector(connid);
+        HttpResponse resp =
+                conn.send("encryptData",
+                        IRemoteRequest.TOKEN_DATA + "=" + Util.specialEncode(inData) +
+                                "&" + IRemoteRequest.TOKEN_CUID + "=" + Util.specialEncode(cuid) +
+                                "&" + IRemoteRequest.TOKEN_KEYINFO + "=" + Util.specialEncode(version) +
+                                "&" + IRemoteRequest.TOKEN_KEYSET + "=" + keySet);
+
+        String content = resp.getContent();
+
+        if (content != null && !content.equals("")) {
+            Hashtable<String, Object> response =
+                    parseResponse(content);
+
+            /*
+             * When a value is not found in response, keep going so we know
+             * what else is missing
+             */
+            String value = null;
+            Integer ist = new Integer(IRemoteRequest.RESPONSE_STATUS_NOT_FOUND);
+            value = (String) response.get(IRemoteRequest.RESPONSE_STATUS);
+            if (value == null) {
+                CMS.debug("TKSRemoteRequestHandler: encryptData(): status not found.");
+            } else {
+                CMS.debug("TKSRemoteRequestHandler: encryptData(): got status = " + value);
+                ist = Integer.parseInt(value);
+                response.put(IRemoteRequest.RESPONSE_STATUS, ist);
+            }
+
+            value = (String) response.get(IRemoteRequest.TKS_RESPONSE_EncryptedData);
+            if (value == null) {
+                CMS.debug("TKSRemoteRequestHandler: encryptData(): response missing name-value pair for: " +
+                        IRemoteRequest.TKS_RESPONSE_EncryptedData);
+            } else {
+                CMS.debug("TKSRemoteRequestHandler: encryptData(): got IRemoteRequest.TKS_RESPONSE_EncryptedData = ");
+                response.put(IRemoteRequest.TKS_RESPONSE_EncryptedData, Util.specialDecode(value));
+            }
+            CMS.debug("TKSRemoteRequestHandler: encryptData(): ends.");
+
+            return new TKSEncryptDataResponse(response);
+        } else {
+            CMS.debug("TKSRemoteRequestHandler: encryptData(): no response content.");
+            throw new EBaseException("TKSRemoteRequestHandler: encryptData(): no response content.");
+        }
+    }
+}
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/TKSResponse.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/TKSResponse.java
new file mode 100644
index 0000000..37269c7
--- /dev/null
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/TKSResponse.java
@@ -0,0 +1,40 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.cms;
+
+import java.util.Hashtable;
+
+import org.dogtagpki.server.connector.IRemoteRequest;
+
+/**
+ * TKSResponse is the base class for TKS remote requests
+ *
+ */
+public abstract class TKSResponse
+{
+    protected Hashtable<String, Object> nameValTable;
+
+    public int getStatus() {
+        Integer iValue = (Integer) nameValTable.get(IRemoteRequest.RESPONSE_STATUS);
+        if (iValue == null)
+            return IRemoteRequest.RESPONSE_STATUS_NOT_FOUND;
+        else
+            return iValue.intValue();
+    }
+}
-- 
1.8.4.2

