>From c657e2f16f4dba5e64c35311cc2a7db83a6d7299 Mon Sep 17 00:00:00 2001
From: Christina Fu <cfu@redhat.com>
Date: Wed, 11 Jun 2014 18:15:06 -0700
Subject: [PATCH] ticket #941 Part1 TPS Rewrite: Enrollment, Recovery,
 KeyRecovery, revoke/unrevoke processor

---
 .../src/org/dogtagpki/tps/msg/BeginOpMsg.java      |   4 +-
 .../cms/servlet/profile/ProfileSubmitServlet.java  |   7 +-
 .../dogtagpki/server/connector/IRemoteRequest.java |   8 +-
 .../server/tps/cms/CAEnrollCertResponse.java       |  18 +-
 .../server/tps/cms/CARemoteRequestHandler.java     | 106 ++++----
 .../server/tps/cms/CARenewCertResponse.java        |  12 +-
 .../server/tps/cms/TKSRemoteRequestHandler.java    |  10 +-
 .../org/dogtagpki/server/tps/engine/TPSEngine.java |  27 +-
 .../server/tps/processor/TPSEnrollProcessor.java   | 288 +++++++++++++++++++--
 .../server/tps/processor/TPSProcessor.java         |   4 +-
 10 files changed, 371 insertions(+), 113 deletions(-)

diff --git a/base/common/src/org/dogtagpki/tps/msg/BeginOpMsg.java b/base/common/src/org/dogtagpki/tps/msg/BeginOpMsg.java
index 250e5c0380312509293bb4c8d18a26671bef8f44..376392c85defaecc1958045e98f7357078f67efe 100644
--- a/base/common/src/org/dogtagpki/tps/msg/BeginOpMsg.java
+++ b/base/common/src/org/dogtagpki/tps/msg/BeginOpMsg.java
@@ -51,8 +51,10 @@ public class BeginOpMsg extends TPSMessage {
         if (extName == null)
             return result;
 
-        return extensions.get(extName);
+        if (extensions != null)
+            result = extensions.get(extName);
 
+        return result;
     }
 
 }
diff --git a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitServlet.java b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitServlet.java
index 0153ca6bb71d051b855de55fac7409dd663ff0ce..3f8d4c4791ed3fa49b1e0f3af68b62eba207de0c 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitServlet.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitServlet.java
@@ -308,11 +308,14 @@ public class ProfileSubmitServlet extends ProfileServlet {
                         if (outputNames != null) {
                             while (outputNames.hasMoreElements()) {
                                 String outputName = outputNames.nextElement();
-                                if (!outputName.equals("b64_cert") && !outputName.equals("pkcs7"))
+                                if (!outputName.equals("b64_cert") &&
+                                    !outputName.equals("der") &&
+                                    !outputName.equals("pkcs7"))
                                     continue;
                                 try {
                                     String outputValue = profileOutput.getValue(outputName, locale, reqs[i]);
-                                    if (outputName.equals("b64_cert")) {
+                                    if (outputName.equals("b64_cert") ||
+                                        outputName.equals("der")) {
                                         String ss = Cert.normalizeCertStrAndReq(outputValue);
                                         outputValue = Cert.stripBrackets(ss);
                                         byte[] bcode = CMS.AtoB(outputValue);
diff --git a/base/server/cms/src/org/dogtagpki/server/connector/IRemoteRequest.java b/base/server/cms/src/org/dogtagpki/server/connector/IRemoteRequest.java
index d6978e0cf1240a24c9ebbf8250e4add0d684d338..103aece028a6afc44a21caf54d6ec4e66d9dd5b9 100644
--- a/base/server/cms/src/org/dogtagpki/server/connector/IRemoteRequest.java
+++ b/base/server/cms/src/org/dogtagpki/server/connector/IRemoteRequest.java
@@ -82,10 +82,10 @@ public interface IRemoteRequest {
 
     // CA response params
     public static final String CA_OP = "op";
-    public static final String CA_RESPONSE_RenewedCertificate_x509 = "X509Certificate";
-    public static final String CA_RESPONSE_RenewedCertificate_b64 = "b64";
-    public static final String CA_RESPONSE_RenewedCertificate_SubjectDN = "SubjectDN";
-    public static final String CA_RESPONSE_RenewedCertificate_serial = "serialno";
+    public static final String CA_RESPONSE_Certificate_x509 = "X509Certificate";
+    public static final String CA_RESPONSE_Certificate_b64 = "b64";
+    public static final String CA_RESPONSE_Certificate_SubjectDN = "SubjectDN";
+    public static final String CA_RESPONSE_Certificate_serial = "serialno";
 
     // KRA request params
     public static final String KRA_UserId = "userid";
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/CAEnrollCertResponse.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/CAEnrollCertResponse.java
index 7e2a29834a4094881c34306912954053bf2fe6e7..9c83e08429149672d89ac05e3b47fe9df6bebf88 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/CAEnrollCertResponse.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/CAEnrollCertResponse.java
@@ -18,7 +18,7 @@
 
 package org.dogtagpki.server.tps.cms;
 
-import java.security.cert.X509Certificate;
+import netscape.security.x509.X509CertImpl;
 import java.util.Hashtable;
 
 import org.dogtagpki.server.connector.IRemoteRequest;
@@ -34,19 +34,19 @@ public class CAEnrollCertResponse extends RemoteResponse
         nameValTable = ht;
     }
 
-    public String getRenewedCertB64() {
-        return (String) nameValTable.get(IRemoteRequest.CA_RESPONSE_RenewedCertificate_b64);
+    public String getCertB64() {
+        return (String) nameValTable.get(IRemoteRequest.CA_RESPONSE_Certificate_b64);
     }
 
-    public String getRenewedCertSerialHex() {
-        return (String) nameValTable.get(IRemoteRequest.CA_RESPONSE_RenewedCertificate_serial);
+    public String getCertSerialHex() {
+        return (String) nameValTable.get(IRemoteRequest.CA_RESPONSE_Certificate_serial);
     }
 
-    public String getRenewedCertSubjectDN() {
-        return (String) nameValTable.get(IRemoteRequest.CA_RESPONSE_RenewedCertificate_SubjectDN);
+    public String getCertSubjectDN() {
+        return (String) nameValTable.get(IRemoteRequest.CA_RESPONSE_Certificate_SubjectDN);
     }
 
-    public X509Certificate getRenewedCert() {
-        return (X509Certificate) nameValTable.get(IRemoteRequest.CA_RESPONSE_RenewedCertificate_x509);
+    public X509CertImpl getCert() {
+        return (X509CertImpl) nameValTable.get(IRemoteRequest.CA_RESPONSE_Certificate_x509);
     }
 }
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/CARemoteRequestHandler.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/CARemoteRequestHandler.java
index 097e01551f9405c5dc25749ff548259535f28115..aa5cb542b6205194a3114dcd0023467682ec5761 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/CARemoteRequestHandler.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/CARemoteRequestHandler.java
@@ -21,9 +21,8 @@ package org.dogtagpki.server.tps.cms;
 import java.io.IOException;
 import java.math.BigInteger;
 import java.security.cert.CertificateException;
-import java.util.List;
 import java.util.Hashtable;
-import java.util.Iterator;
+import java.util.List;
 
 import netscape.security.x509.AuthorityKeyIdentifierExtension;
 import netscape.security.x509.KeyIdentifier;
@@ -34,6 +33,7 @@ import netscape.security.x509.X509CertImpl;
 
 import org.dogtagpki.server.connector.IRemoteRequest;
 import org.dogtagpki.server.tps.TPSSubsystem;
+import org.dogtagpki.server.tps.engine.TPSEngine;
 import org.dogtagpki.tps.main.TPSBuffer;
 import org.dogtagpki.tps.main.Util;
 import org.mozilla.jss.CryptoManager;
@@ -46,6 +46,7 @@ import com.netscape.certsrv.base.EPropertyNotFound;
 import com.netscape.certsrv.base.IConfigStore;
 import com.netscape.cmscore.connector.HttpConnector;
 import com.netscape.cmsutil.http.HttpResponse;
+import com.netscape.cmsutil.util.Utils;
 import com.netscape.cmsutil.xml.XMLObject;
 
 /**
@@ -67,11 +68,6 @@ public class CARemoteRequestHandler extends RemoteRequestHandler
     /**
      * enrollCertificate enrolls a certificate in the CA
      *
-     * TODO: certificate and key structures conversion
-     * to be covered by ticket #941 once we have
-     * dependency such as secure channel in place
-     * for better testing
-     *
      * @param pubKeybuf public key for enrollment
      * @param uid uid for enrollment
      * @param cuid token id
@@ -81,7 +77,9 @@ public class CARemoteRequestHandler extends RemoteRequestHandler
     public CAEnrollCertResponse enrollCertificate(
             TPSBuffer pubKeybuf,
             String uid,
-            String cuid)
+            String cuid,
+            String tokenType,
+            String keyType)
             throws EBaseException {
 
         CMS.debug("CARemoteRequestHandler: enrollCertificate(): begins.");
@@ -90,19 +88,23 @@ public class CARemoteRequestHandler extends RemoteRequestHandler
         }
 
         IConfigStore conf = CMS.getConfigStore();
-        /*
-         * TODO: obtain the profile name from current session when available.
-         *   Hard-code to "userKey" for now
-         */
         String profileId =
-                conf.getString("op.enroll.userKey.keyGen.signing.ca.profileId",
-                        "caTokenUserSigningKeyEnrollment");
+                conf.getString(TPSEngine.OP_ENROLL_PREFIX + "." +
+                        tokenType + ".keyGen." +
+                        keyType + ".ca.profileId");
 
         TPSSubsystem subsystem =
                 (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
         HttpConnector conn =
                 (HttpConnector) subsystem.getConnectionManager().getConnector(connid);
         CMS.debug("CARemoteRequestHandler: enrollCertificate(): sending request to CA");
+        String encodedPubKey = null;
+        try {
+            encodedPubKey = Util.uriEncode(CMS.BtoA(pubKeybuf.toBytesArray()));
+        } catch (Exception e) {
+            CMS.debug("CARemoteRequestHandler: enrollCertificate(): uriEncode of pubkey failed: " + e);
+            throw new EBaseException("CARemoteRequestHandler: enrollCertificate(): uriEncode of pubkey failed: " + e);
+        }
         HttpResponse resp =
                 conn.send("enrollment",
                         IRemoteRequest.GET_XML + "=" +
@@ -112,7 +114,7 @@ public class CARemoteRequestHandler extends RemoteRequestHandler
                                 "&" + IRemoteRequest.CA_ENROLL_screenname + "=" +
                                 uid +
                                 "&" + IRemoteRequest.CA_ENROLL_publickey + "=" +
-                                Util.specialEncode(pubKeybuf) +
+                                encodedPubKey +
                                 "&" + IRemoteRequest.CA_ProfileId + "=" +
                                 profileId);
 
@@ -150,36 +152,36 @@ public class CARemoteRequestHandler extends RemoteRequestHandler
             value = xmlResponse.getValue("SubjectDN");
             if (value == null) {
                 CMS.debug("CARemoteRequestHandler:: enrollCertificate(): response missing name-value pair for: " +
-                        IRemoteRequest.CA_RESPONSE_RenewedCertificate_SubjectDN);
+                        IRemoteRequest.CA_RESPONSE_Certificate_SubjectDN);
             } else {
-                CMS.debug("CARemoteRequestHandler:: enrollCertificate(): got IRemoteRequest.CA_RESPONSE_RenewedCertificate_SubjectDN = "
+                CMS.debug("CARemoteRequestHandler:: enrollCertificate(): got IRemoteRequest.CA_RESPONSE_Certificate_SubjectDN = "
                         + value);
-                response.put(IRemoteRequest.CA_RESPONSE_RenewedCertificate_SubjectDN, value);
+                response.put(IRemoteRequest.CA_RESPONSE_Certificate_SubjectDN, value);
             }
 
-            value = xmlResponse.getValue(IRemoteRequest.CA_RESPONSE_RenewedCertificate_serial);
+            value = xmlResponse.getValue(IRemoteRequest.CA_RESPONSE_Certificate_serial);
             if (value == null) {
                 CMS.debug("CARemoteRequestHandler:: enrollCertificate(): response missing name-value pair for: " +
-                        IRemoteRequest.CA_RESPONSE_RenewedCertificate_serial);
+                        IRemoteRequest.CA_RESPONSE_Certificate_serial);
             } else {
-                CMS.debug("CARemoteRequestHandler:: enrollCertificate(): got IRemoteRequest.CA_RESPONSE_RenewedCertificate_serial = 0x"
+                CMS.debug("CARemoteRequestHandler:: enrollCertificate(): got IRemoteRequest.CA_RESPONSE_Certificate_serial = 0x"
                         + value);
-                response.put(IRemoteRequest.CA_RESPONSE_RenewedCertificate_serial, value);
+                response.put(IRemoteRequest.CA_RESPONSE_Certificate_serial, value);
             }
 
-            value = xmlResponse.getValue(IRemoteRequest.CA_RESPONSE_RenewedCertificate_b64);
+            value = xmlResponse.getValue(IRemoteRequest.CA_RESPONSE_Certificate_b64);
             if (value == null) {
                 CMS.debug("CARemoteRequestHandler:: enrollCertificate(): response missing name-value pair for: " +
-                        IRemoteRequest.CA_RESPONSE_RenewedCertificate_b64);
+                        IRemoteRequest.CA_RESPONSE_Certificate_b64);
             } else {
-                CMS.debug("CARemoteRequestHandler:: enrollCertificate(): got IRemoteRequest.CA_RESPONSE_RenewedCertificate_b64 = "
-                        + value);
-                response.put(IRemoteRequest.CA_RESPONSE_RenewedCertificate_b64, value);
                 try {
-                    X509Certificate newCert = (X509Certificate) new X509CertImpl(CMS.AtoB(value));
-                    response.put(IRemoteRequest.CA_RESPONSE_RenewedCertificate_x509, newCert);
+                    CMS.debug("CARemoteRequestHandler:: enrollCertificate(): got IRemoteRequest.CA_RESPONSE_Certificate_b64 = "
+                            + value);
+                    response.put(IRemoteRequest.CA_RESPONSE_Certificate_b64, value);
+                    X509CertImpl newCert = new X509CertImpl(Utils.base64decode(value));
+                    response.put(IRemoteRequest.CA_RESPONSE_Certificate_x509, newCert);
                     CMS.debug("CARemoteRequestHandler: enrollCertificate(): new cert parsed successfully");
-                } catch (CertificateException e) {
+                } catch (Exception e) {
                     // we don't exit.  Keep going.
                     CMS.debug("CARemoteRequestHandler: enrollCertificate(): exception:" + e);
                 }
@@ -199,7 +201,10 @@ public class CARemoteRequestHandler extends RemoteRequestHandler
      * @param serialno the serial number of the cert to be renewed
      * @return CARenewCertResponse
      */
-    public CARenewCertResponse renewCertificate(BigInteger serialno)
+    public CARenewCertResponse renewCertificate(
+            BigInteger serialno,
+            String tokenType,
+            String keyType)
             throws EBaseException {
 
         CMS.debug("CARemoteRequestHandler: renewCertificate(): begins.");
@@ -209,13 +214,10 @@ public class CARemoteRequestHandler extends RemoteRequestHandler
 
         IConfigStore conf = CMS.getConfigStore();
 
-        /*
-         * TODO: obtain the profile name from current session when available.
-         *   Hard-code to "userKey" for now
-         */
         String profileId =
-                conf.getString("op.enroll.userKey.renewal.signing.ca.profileId",
-                        "caTokenUserEncryptionKeyRenewal");
+                conf.getString(TPSEngine.OP_ENROLL_PREFIX + "." +
+                        tokenType + ".renewal." +
+                        keyType + ".ca.profileId");
 
         TPSSubsystem subsystem =
                 (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
@@ -261,34 +263,34 @@ public class CARemoteRequestHandler extends RemoteRequestHandler
             value = xmlResponse.getValue("SubjectDN");
             if (value == null) {
                 CMS.debug("CARemoteRequestHandler:: renewCertificate(): response missing name-value pair for: " +
-                        IRemoteRequest.CA_RESPONSE_RenewedCertificate_SubjectDN);
+                        IRemoteRequest.CA_RESPONSE_Certificate_SubjectDN);
             } else {
-                CMS.debug("CARemoteRequestHandler:: renewCertificate(): got IRemoteRequest.CA_RESPONSE_RenewedCertificate_SubjectDN = "
+                CMS.debug("CARemoteRequestHandler:: renewCertificate(): got IRemoteRequest.CA_RESPONSE_Certificate_SubjectDN = "
                         + value);
-                response.put(IRemoteRequest.CA_RESPONSE_RenewedCertificate_SubjectDN, value);
+                response.put(IRemoteRequest.CA_RESPONSE_Certificate_SubjectDN, value);
             }
 
-            value = xmlResponse.getValue(IRemoteRequest.CA_RESPONSE_RenewedCertificate_serial);
+            value = xmlResponse.getValue(IRemoteRequest.CA_RESPONSE_Certificate_serial);
             if (value == null) {
                 CMS.debug("CARemoteRequestHandler:: renewCertificate(): response missing name-value pair for: " +
-                        IRemoteRequest.CA_RESPONSE_RenewedCertificate_serial);
+                        IRemoteRequest.CA_RESPONSE_Certificate_serial);
             } else {
-                CMS.debug("CARemoteRequestHandler:: renewCertificate(): got IRemoteRequest.CA_RESPONSE_RenewedCertificate_serial = 0x"
+                CMS.debug("CARemoteRequestHandler:: renewCertificate(): got IRemoteRequest.CA_RESPONSE_Certificate_serial = 0x"
                         + value);
-                response.put(IRemoteRequest.CA_RESPONSE_RenewedCertificate_serial, value);
+                response.put(IRemoteRequest.CA_RESPONSE_Certificate_serial, value);
             }
 
-            value = xmlResponse.getValue(IRemoteRequest.CA_RESPONSE_RenewedCertificate_b64);
+            value = xmlResponse.getValue(IRemoteRequest.CA_RESPONSE_Certificate_b64);
             if (value == null) {
                 CMS.debug("CARemoteRequestHandler:: renewCertificate(): response missing name-value pair for: " +
-                        IRemoteRequest.CA_RESPONSE_RenewedCertificate_b64);
+                        IRemoteRequest.CA_RESPONSE_Certificate_b64);
             } else {
-                CMS.debug("CARemoteRequestHandler:: renewCertificate(): got IRemoteRequest.CA_RESPONSE_RenewedCertificate_b64 = "
+                CMS.debug("CARemoteRequestHandler:: renewCertificate(): got IRemoteRequest.CA_RESPONSE_Certificate_b64 = "
                         + value);
-                response.put(IRemoteRequest.CA_RESPONSE_RenewedCertificate_b64, value);
+                response.put(IRemoteRequest.CA_RESPONSE_Certificate_b64, value);
                 try {
-                    X509Certificate newCert = (X509Certificate) new X509CertImpl(CMS.AtoB(value));
-                    response.put(IRemoteRequest.CA_RESPONSE_RenewedCertificate_x509, newCert);
+                    X509CertImpl newCert = new X509CertImpl(Utils.base64decode(value));
+                    response.put(IRemoteRequest.CA_RESPONSE_Certificate_x509, newCert);
                     CMS.debug("CARemoteRequestHandler: renewCertificate(): new cert parsed successfully");
                 } catch (CertificateException e) {
                     // we don't exit.  Keep going.
@@ -496,7 +498,7 @@ public class CARemoteRequestHandler extends RemoteRequestHandler
         if (exception == null) {
             throw new EBaseException("revokeFromOtherCA: signing ca not found");
         } else {
-            throw new EBaseException (exception.toString());
+            throw new EBaseException(exception.toString());
         }
     }
 
@@ -640,7 +642,7 @@ public class CARemoteRequestHandler extends RemoteRequestHandler
             caSkiString = getCaSki(connid);
             certAkiString = getCertAkiString(cert);
         } catch (Exception e) {
-            CMS.debug("CARemoteRequestHandler: revokeCertificate() exception:"+e);
+            CMS.debug("CARemoteRequestHandler: revokeCertificate() exception:" + e);
             skipMatch = true;
         }
         if (!skipMatch) {
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/CARenewCertResponse.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/CARenewCertResponse.java
index cf7f87774624c3b4d37a16554d0381689b362ad2..bb9ebbb44d658afe0773c9c8b88285abbdea3cce 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/CARenewCertResponse.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/CARenewCertResponse.java
@@ -18,7 +18,7 @@
 
 package org.dogtagpki.server.tps.cms;
 
-import java.security.cert.X509Certificate;
+import netscape.security.x509.X509CertImpl;
 import java.util.Hashtable;
 
 import org.dogtagpki.server.connector.IRemoteRequest;
@@ -35,18 +35,18 @@ public class CARenewCertResponse extends RemoteResponse
     }
 
     public String getRenewedCertB64() {
-        return (String) nameValTable.get(IRemoteRequest.CA_RESPONSE_RenewedCertificate_b64);
+        return (String) nameValTable.get(IRemoteRequest.CA_RESPONSE_Certificate_b64);
     }
 
     public String getRenewedCertSerialHex() {
-        return (String) nameValTable.get(IRemoteRequest.CA_RESPONSE_RenewedCertificate_serial);
+        return (String) nameValTable.get(IRemoteRequest.CA_RESPONSE_Certificate_serial);
     }
 
     public String getRenewedCertSubjectDN() {
-        return (String) nameValTable.get(IRemoteRequest.CA_RESPONSE_RenewedCertificate_SubjectDN);
+        return (String) nameValTable.get(IRemoteRequest.CA_RESPONSE_Certificate_SubjectDN);
     }
 
-    public X509Certificate getRenewedCert() {
-        return (X509Certificate) nameValTable.get(IRemoteRequest.CA_RESPONSE_RenewedCertificate_x509);
+    public X509CertImpl getRenewedCert() {
+        return (X509CertImpl) nameValTable.get(IRemoteRequest.CA_RESPONSE_Certificate_x509);
     }
 }
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
index 0aff29b92cea2f3df11caa47f41007c394423735..3c371a45e95683ea50db630680faebd71bb175c3 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/TKSRemoteRequestHandler.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/TKSRemoteRequestHandler.java
@@ -79,7 +79,8 @@ public class TKSRemoteRequestHandler extends RemoteRequestHandler
             TPSBuffer keyInfo,
             TPSBuffer card_challenge,
             TPSBuffer card_cryptogram,
-            TPSBuffer host_challenge)
+            TPSBuffer host_challenge,
+            String tokenType)
             throws EBaseException {
 
         CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): begins.");
@@ -90,12 +91,9 @@ public class TKSRemoteRequestHandler extends RemoteRequestHandler
 
         IConfigStore conf = CMS.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",
+                conf.getBoolean("op.enroll." +
+                tokenType + ".keyGen.encryption.serverKeygen.enable",
                         false);
         String keySet =
                 conf.getString("connector." + connid + "keySet", "defKeySet");
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/engine/TPSEngine.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/engine/TPSEngine.java
index 2d6b09e86c96a55659aef5b1b740a98f55f94964..a854b020dcb033e9b265e7e56b9c17b79f81eff6 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/engine/TPSEngine.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/engine/TPSEngine.java
@@ -29,13 +29,12 @@ import com.netscape.certsrv.base.EBaseException;
 public class TPSEngine {
 
     public enum RA_Algs {
-        ALG_RSA ,
-        ALG_RSA_CRT ,
-        ALG_DSA ,
-        ALG_EC_F2M ,
+        ALG_RSA,
+        ALG_RSA_CRT,
+        ALG_DSA,
+        ALG_EC_F2M,
         ALG_EC_FP
-};
-
+    };
 
     public static final String CFG_DEBUG_ENABLE = "logging.debug.enable";
     public static final String CFG_DEBUG_FILENAME = "logging.debug.filename";
@@ -116,7 +115,6 @@ public class TPSEngine {
     public static final String CFG_KEYGEN_KEYTYPE_VALUE = "keyGen.keyType.value";
     public static final String CFG_SERVER_KEYGEN_ENABLE = "serverKeygen.enable";
 
-
     /* External reg values */
 
     public static final String CFG_EXTERNAL_REG = "externalReg";
@@ -155,8 +153,8 @@ public class TPSEngine {
             TPSBuffer card_challenge,
             TPSBuffer host_challenge,
             TPSBuffer card_cryptogram,
-
-            String connId) throws TPSException {
+            String connId,
+            String tokenType) throws TPSException {
 
         CMS.debug("TPSEngine.computeSessionKey");
 
@@ -165,7 +163,7 @@ public class TPSEngine {
         TKSComputeSessionKeyResponse resp = null;
         try {
             tks = new TKSRemoteRequestHandler(connId);
-            resp = tks.computeSessionKey(cuid, keyInfo, card_challenge, card_cryptogram, host_challenge);
+            resp = tks.computeSessionKey(cuid, keyInfo, card_challenge, card_cryptogram, host_challenge, tokenType);
         } catch (EBaseException e) {
             throw new TPSException("SecureChannel.computeSessionKey: Error computing session key!" + e,
                     TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
@@ -203,7 +201,7 @@ public class TPSEngine {
 
         boolean isECC = false;
 
-        if(algEnum == RA_Algs.ALG_EC_F2M || algEnum == RA_Algs.ALG_EC_FP) {
+        if (algEnum == RA_Algs.ALG_EC_F2M || algEnum == RA_Algs.ALG_EC_FP) {
             isECC = true;
         }
 
@@ -216,7 +214,7 @@ public class TPSEngine {
 
         RA_Algs def = RA_Algs.ALG_RSA;
 
-        switch(alg) {
+        switch (alg) {
 
         case 1:
             return RA_Algs.ALG_RSA;
@@ -230,12 +228,11 @@ public class TPSEngine {
         case 5:
             return RA_Algs.ALG_EC_FP;
 
-            default:
-                return def;
+        default:
+            return def;
 
         }
 
-
     }
 
 }
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java
index ae7b5c61e70434621b69d1886e90f2603e53ee03..69bc15cb9fd00738a27f12078b5d72ee4778ca0f 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java
@@ -1,11 +1,20 @@
 package org.dogtagpki.server.tps.processor;
 
 import java.io.IOException;
+import java.security.InvalidKeyException;
+import java.security.PublicKey;
 import java.util.zip.DataFormatException;
 
+import netscape.security.provider.RSAPublicKey;
+//import org.mozilla.jss.pkcs11.PK11ECPublicKey;
+import netscape.security.util.BigInt;
+import netscape.security.x509.X509CertImpl;
+
 import org.dogtagpki.server.tps.TPSSession;
 import org.dogtagpki.server.tps.authentication.TPSAuthenticator;
 import org.dogtagpki.server.tps.channel.SecureChannel;
+import org.dogtagpki.server.tps.cms.CAEnrollCertResponse;
+import org.dogtagpki.server.tps.cms.CARemoteRequestHandler;
 import org.dogtagpki.server.tps.engine.TPSEngine;
 import org.dogtagpki.server.tps.main.ObjectSpec;
 import org.dogtagpki.server.tps.main.PKCS11Obj;
@@ -152,7 +161,9 @@ public class TPSEnrollProcessor extends TPSProcessor {
                     userCred = requestUserId(TPSEngine.ENROLL_OP, appletInfo.getCUIDString(), userAuth,
                             beginMsg.getExtensions());
                     authToken = authenticateUser(TPSEngine.ENROLL_OP, userAuth, userCred);
-                    CMS.debug("TPSEnrollProcessor.checkAndAuthenticateUser: auth passed: userid: " + authToken.get("userid"));
+                    CMS.debug("TPSEnrollProcessor.checkAndAuthenticateUser: auth passed: userid: "
+                            + authToken.get("userid"));
+                    userid = authToken.getInString("userid");
                 } catch (Exception e) {
                     // all exceptions are considered login failure
                     CMS.debug("TPSEnrollProcessor.checkAndAuthenticateUser:: authentication exception thrown: " + e);
@@ -160,7 +171,8 @@ public class TPSEnrollProcessor extends TPSProcessor {
                             TPSStatus.STATUS_ERROR_LOGIN);
                 }
             } else {
-                throw new TPSException("TPSEnrollProcessor.checkAndAuthenticateUser: TPS enrollment must have authentication enabled.",
+                throw new TPSException(
+                        "TPSEnrollProcessor.checkAndAuthenticateUser: TPS enrollment must have authentication enabled.",
                         TPSStatus.STATUS_ERROR_LOGIN);
 
             }
@@ -267,6 +279,7 @@ public class TPSEnrollProcessor extends TPSProcessor {
     private void generateCertificates(EnrolledCertsInfo certsInfo, SecureChannel channel, AppletInfo aInfo)
             throws TPSException, IOException {
 
+        CMS.debug("TPSProcess.generateCertificates: begins ");
         if (certsInfo == null || aInfo == null) {
             throw new TPSException("TPSEnrollProcessor.generateCertificates: Bad Input data!",
                     TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
@@ -284,6 +297,7 @@ public class TPSEnrollProcessor extends TPSProcessor {
             generateCertificate(certsInfo, channel, aInfo, keyType);
         }
 
+        CMS.debug("TPSProcess.generateCertificates: ends ");
     }
 
     private void generateCertificate(EnrolledCertsInfo certsInfo, SecureChannel channel, AppletInfo aInfo,
@@ -488,38 +502,263 @@ public class TPSEnrollProcessor extends TPSProcessor {
             byte[] iobytes = { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff };
             TPSBuffer iobuf = new TPSBuffer(iobytes);
 
-            TPSBuffer public_key = channel.readObject(iobuf, 0, size);
+            TPSBuffer public_key_blob = channel.readObject(iobuf, 0, size);
 
-            parsePublicKeyInfo(public_key);
+            PublicKey parsedPubKey = parsePublicKeyBlob(public_key_blob, isECC);
+            byte[] parsedPubKey_ba = parsedPubKey.getEncoded();
+
+            // enrollment begins
+            CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: enrollment begins");
+            try {
+                String caConnID = getCAConnectorID();
+                CARemoteRequestHandler caRH = new CARemoteRequestHandler(caConnID);
+                TPSBuffer encodedParsedPubKey = new TPSBuffer(parsedPubKey_ba);
+                AppletInfo appletInfo = getAppletInfo();
+                CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: userid =" + userid + ", cuid="
+                        + appletInfo.getCUIDString());
+                CAEnrollCertResponse caEnrollResp = caRH.enrollCertificate(encodedParsedPubKey, userid,
+                        appletInfo.getCUIDString(), getSelectedTokenType(),
+                        cEnrollInfo.getKeyType());
+                String retCertB64 = caEnrollResp.getCertB64();
+                if (retCertB64 != null)
+                    CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: new cert b64 =" + retCertB64);
+                else {
+                    CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: new cert b64 not found");
+                    throw new TPSException("TPSEnrollProcessor.enrollOneCertificate: new cert b64 not found",
+                            TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+                }
+                X509CertImpl x509Cert = caEnrollResp.getCert();
+                if (x509Cert != null)
+                    CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: new cert retrieved");
+                else {
+                    CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: new cert not found");
+                    throw new TPSException("TPSEnrollProcessor.enrollOneCertificate: new cert not found",
+                            TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+                }
+            } catch (EBaseException e) {
+                CMS.debug("TPSEnrollProcessor.enrollOneCertificate::" + e);
+                throw new TPSException("TPSEnrollProcessor.enrollOneCertificate: Exception thrown: " + e,
+                        TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+            }
+            CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: enrollment ends");
 
             //ToDo: Finish the rest of this
 
         }
 
         statusUpdate(cEnrollInfo.getEndProgressValue(), "PROGRESS_ENROLL_CERT");
+        CMS.debug("TPSEnrollProcessor.enrollOneCertificate ends");
 
     }
 
-    //We don't know what to return for this as of yet, make it void for now.
-    private void parsePublicKeyInfo(TPSBuffer public_key) throws TPSException {
+    /**
+     * Extracts information from the public key blob and verify proof.
+     *
+     * Muscle Key Blob Format (RSA Public Key)
+     * ---------------------------------------
+     *
+     * The key generation operation places the newly generated key into
+     * the output buffer encoding in the standard Muscle key blob format.
+     * For an RSA key the data is as follows:
+     *
+     * Byte Encoding (0 for plaintext)
+     *
+     * Byte Key Type (1 for RSA public)
+     *
+     * Short Key Length (1024 û high byte first)
+     *
+     * Short Modulus Length
+     *
+     * Byte[] Modulus
+     *
+     * Short Exponent Length
+     *
+     * Byte[] Exponent
+     *
+     *
+     * ECC KeyBlob Format (ECC Public Key)
+     * ----------------------------------
+     *
+     * Byte Encoding (0 for plaintext)
+     *
+     * Byte Key Type (10 for ECC public)
+     *
+     * Short Key Length (256, 384, 521 high byte first)
+     *
+     * Byte[] Key (W)
+     *
+     *
+     * Signature Format (Proof)
+     * ---------------------------------------
+     *
+     * The key generation operation creates a proof-of-location for the
+     * newly generated key. This proof is a signature computed with the
+     * new private key using the RSA-with-MD5 signature algorithm. The
+     * signature is computed over the Muscle Key Blob representation of
+     * the new public key and the challenge sent in the key generation
+     * request. These two data fields are concatenated together to form
+     * the input to the signature, without any other data or length fields.
+     *
+     * Byte[] Key Blob Data
+     *
+     * Byte[] Challenge
+     *
+     *
+     * Key Generation Result
+     * ---------------------------------------
+     *
+     * The key generation command puts the key blob and the signature (proof)
+     * into the output buffer using the following format:
+     *
+     * Short Length of the Key Blob
+     *
+     * Byte[] Key Blob Data
+     *
+     * Short Length of the Proof
+     *
+     * Byte[] Proof (Signature) Data
+     *
+     * @param blob the publickey blob to be parsed
+     * @param challenge the challenge generated by TPS
+     *
+     ******/
+    private PublicKey parsePublicKeyBlob(
+            TPSBuffer public_key_blob,
+            /* TPSBuffer challenge,*/
+            boolean isECC)
+            throws TPSException {
+        PublicKey parsedPubKey = null;
 
-        if (public_key == null) {
-            throw new TPSException("TPSEnrollProcessor.parsePublicKeyBlob: Bad input data!",
+        if (public_key_blob == null /*|| challenge == null*/) {
+            throw new TPSException(
+                    "TPSEnrollProcessor.parsePublicKeyBlob: Bad input data! Missing public_key_blob or challenge",
                     TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
         }
 
-        CMS.debug("TPSEnrollProcessor.enrollOneCertificate: public key returned from token: "
-                + public_key.toHexString());
+        CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob: public key blob from token to parse: "
+                + public_key_blob.toHexString());
+        /*
+         * decode blob into structures
+         */
 
-        TPSBuffer pKeyBlob = public_key.substr(2);
-        //Check for bad blob here:
+        // offset to the beginning of the public key length.  should be 0
+        int pkeyb_len_offset = 0;
 
-        if (pKeyBlob == null) {
-            throw new TPSException("TPSEnrollProcessor.parsePublicKeyBlob: Bad input data!",
+        /*
+         * now, convert lengths
+         */
+        // 1st, keyblob length
+        /*
+                byte len0 = public_key_blob.at(pkeyb_len_offset);
+                byte len1 = public_key_blob.at(pkeyb_len_offset + 1);
+                int pkeyb_len = (len0 << 8) | (len1 & 0xFF);
+        */
+        int pkeyb_len = public_key_blob.getIntFrom2Bytes(pkeyb_len_offset);
+        CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob: pkeyb_len = " +
+                pkeyb_len + ", isECC: " + isECC);
+        // public key blob
+        TPSBuffer pkeyb = public_key_blob.substr(pkeyb_len_offset + 2, pkeyb_len);
+        if (pkeyb == null) {
+            CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob: pkeyb null ");
+            throw new TPSException("TPSEnrollProcessor.parsePublicKeyBlob: Bad input data! pkeyb null",
                     TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
         }
+        CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob: pkeyb = "
+                + pkeyb.toHexString());
 
-        //ToDo: finish this
+        //  2nd, proof blob length
+        int proofb_len_offset = pkeyb_len_offset + 2 + pkeyb_len;
+        /*
+                len0 = public_key_blob.at(proofb_len_offset);
+                len1 = public_key_blob.at(proofb_len_offset + 1);
+                int proofb_len = (len0 << 8 | len1 & 0xFF);
+        */
+        int proofb_len = public_key_blob.getIntFrom2Bytes(proofb_len_offset);
+        // proof blob
+        TPSBuffer proofb = public_key_blob.substr(proofb_len_offset + 2, proofb_len);
+        if (proofb == null) {
+            CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob: proofb null ");
+            throw new TPSException("TPSEnrollProcessor.parsePublicKeyBlob: Bad input data! proofb null",
+                    TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+        }
+        CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob: proofb = "
+                + proofb.toHexString());
+
+        // convert pkeyb to pkey
+        // 1 byte encoding, 1 byte key type, 2 bytes key length, then the key
+        int pkey_offset = 4;
+        /*
+                len0 = pkeyb.at(pkey_offset);
+                len1 = pkeyb.at(pkey_offset + 1);
+        */
+        if (!isECC) {
+            //            int mod_len = len0 << 8 | len1 & 0xFF;
+            int mod_len = pkeyb.getIntFrom2Bytes(pkey_offset);
+            CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob: mod_len= " + mod_len);
+            /*
+                        len0 = pkeyb.at(pkey_offset + 2 + mod_len);
+                        len1 = pkeyb.at(pkey_offset + 2 + mod_len + 1);
+                        int exp_len = len0 << 8 | len1 & 0xFF;
+            */
+            int exp_len = pkeyb.getIntFrom2Bytes(pkey_offset + 2 + mod_len);
+            CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob: exp_len= " + exp_len);
+
+            TPSBuffer modb = pkeyb.substr(pkey_offset + 2, mod_len);
+            if (modb == null) {
+                CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob: modb null ");
+                throw new TPSException("TPSEnrollProcessor.parsePublicKeyBlob: Bad input data! modb null",
+                        TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+            }
+            CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob: modb= "
+                    + modb.toHexString());
+            TPSBuffer expb = pkeyb.substr(pkey_offset + 2 + mod_len + 2, exp_len);
+
+            if (expb == null) {
+                CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob: expb null ");
+                throw new TPSException("TPSEnrollProcessor.parsePublicKeyBlob: Bad input data! expb null",
+                        TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+            }
+            CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob: expb= "
+                    + expb.toHexString());
+            BigInt modb_bi = new BigInt(modb.toBytesArray());
+            BigInt expb_bi = new BigInt(expb.toBytesArray());
+            try {
+                RSAPublicKey rsa_pub_key = new RSAPublicKey(modb_bi, expb_bi);
+                CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob: public key blob converted to RSAPublicKey");
+                if (rsa_pub_key != null) {
+                    parsedPubKey = rsa_pub_key;
+                }
+            } catch (InvalidKeyException e) {
+                CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob:InvalidKeyException thrown");
+                throw new TPSException("TPSEnrollProcessor.parsePublicKeyBlob: Exception thrown: " + e,
+                        TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+            }
+        } else {
+            // TODO: handle ECC
+        }
+
+        // TODO: challenge verification
+
+        // sanity-check parsedPubKey before return
+        if (parsedPubKey == null) {
+            CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob: parsedPubKey null");
+            throw new TPSException(
+                    "TPSEnrollProcessor.parsePublicKeyBlob: parsedPubKey null.",
+                    TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+        } else {
+            CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob: parsedPubKey not null");
+        }
+        byte[] parsedPubKey_ba = parsedPubKey.getEncoded();
+        if (parsedPubKey_ba == null) {
+            CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob: parsedPubKey_ba null");
+            throw new TPSException(
+                    "TPSEnrollProcessor.parsePublicKeyBlob: parsedPubKey encoding failure.",
+                    TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+        } else {
+            CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob: parsedPubKey getEncoded not null");
+        }
+
+        return parsedPubKey;
     }
 
     private boolean checkForServerSideKeyGen(CertEnrollInfo cInfo) throws TPSException {
@@ -610,7 +849,6 @@ public class TPSEnrollProcessor extends TPSProcessor {
     }
 
     protected int getNumberCertsToEnroll() throws TPSException {
-
         IConfigStore configStore = CMS.getConfigStore();
         int keyTypeNum = 0;
         try {
@@ -636,6 +874,24 @@ public class TPSEnrollProcessor extends TPSProcessor {
         return keyTypeNum;
     }
 
+    protected String getCAConnectorID() throws TPSException {
+        IConfigStore configStore = CMS.getConfigStore();
+        String id = null;
+
+        String config = "op." + currentTokenOperation + "." + selectedTokenType + ".ca.conn";
+
+        try {
+            id = configStore.getString(config, "ca1");
+        } catch (EBaseException e) {
+            throw new TPSException("TPSEnrollProcessor.getCAConnectorID: Internal error finding config value.");
+
+        }
+
+        CMS.debug("TPSEnrollProcessor.getCAConectorID: returning: " + id);
+
+        return id;
+    }
+
     public static void main(String[] args) {
     }
 
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSProcessor.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
index df312d1edf7418a0d2ee2a7c80620a37afc74faf..98e4d4885cb157c4738ba3c46082bb697b8c2c3e 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
@@ -423,7 +423,7 @@ public class TPSProcessor {
 
         TKSComputeSessionKeyResponse resp = engine.computeSessionKey(keyDiversificationData, keyInfoData,
                 cardChallenge, hostChallenge, cardCryptogram,
-                connId);
+                connId, getSelectedTokenType());
 
         hostCryptogram = resp.getHostCryptogram();
 
@@ -874,7 +874,7 @@ public class TPSProcessor {
                 throw new TPSException("TPS error getting config values from config store.",
                         TPSStatus.STATUS_ERROR_MISCONFIGURATION);
             }
-            if (isAuthRequired && ! skipAuth) {
+            if (isAuthRequired && !skipAuth) {
                 try {
                     TPSAuthenticator userAuth =
                             getAuthentication(TPSEngine.OP_FORMAT_PREFIX, tokenType);
-- 
1.8.4.2

