From d7238a685f09fd5cad02ca72df3a9c343f9f6db3 Mon Sep 17 00:00:00 2001
From: Jack Magne <jmagne@dhcp-16-213.sjc.redhat.com>
Date: Thu, 7 Aug 2014 11:03:09 -0700
Subject: [PATCH] Implement enrollment with server side keygen.

This patch implements server side keygen when so configured in the CS.cfg.

1. In this case, the encryption cert's private key is generated on the KRA and archived by the KRA.
2. The private key is then injected onto the token.
3. This will allows us to later implement certificate recovery.
4. Fixed some minor issues discovered with the code that interfaces with the TKS and DRM.
5. Final certificate tested to work with Relyea's "SmartCard" utility to perform legal crypto operations.
---
 .../src/org/dogtagpki/tps/main/TPSBuffer.java      |  19 +
 .../server/tps/channel/SecureChannel.java          |  48 ++-
 .../server/tps/cms/KRARemoteRequestHandler.java    |  69 +--
 .../tps/cms/TKSComputeSessionKeyResponse.java      |   4 +
 .../org/dogtagpki/server/tps/engine/TPSEngine.java |  71 +++-
 .../server/tps/processor/TPSEnrollProcessor.java   | 468 +++++++++++++++------
 .../server/tps/processor/TPSProcessor.java         |  60 ++-
 7 files changed, 564 insertions(+), 175 deletions(-)

diff --git a/base/common/src/org/dogtagpki/tps/main/TPSBuffer.java b/base/common/src/org/dogtagpki/tps/main/TPSBuffer.java
index 242f082..d71bb5d 100644
--- a/base/common/src/org/dogtagpki/tps/main/TPSBuffer.java
+++ b/base/common/src/org/dogtagpki/tps/main/TPSBuffer.java
@@ -309,6 +309,25 @@ public class TPSBuffer {
         return result.toString();
     }
 
+    public String toPlainHexString() {
+
+        final String HEX_DIGITS = "0123456789ABCDEF";
+
+        StringBuffer result = new StringBuffer(buf.length * 2);
+
+        for (int i = 0; i < buf.length; i++)
+        {
+            char c = (char) buf[i];
+
+            result.append(HEX_DIGITS.charAt((c & 0xF0) >> 4));
+            result.append(HEX_DIGITS.charAt(c & 0x0F));
+
+        }
+
+        return result.toString();
+
+    }
+
     public int getIntFrom1Byte(int offset) {
 
         if (offset < 0 || offset >= (this.size())) {
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/channel/SecureChannel.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/channel/SecureChannel.java
index affdddd..7c3a01b 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/channel/SecureChannel.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/channel/SecureChannel.java
@@ -29,6 +29,7 @@ import org.dogtagpki.tps.apdu.ExternalAuthenticateAPDU;
 import org.dogtagpki.tps.apdu.ExternalAuthenticateAPDU.SecurityLevel;
 import org.dogtagpki.tps.apdu.GenerateKeyAPDU;
 import org.dogtagpki.tps.apdu.GenerateKeyECCAPDU;
+import org.dogtagpki.tps.apdu.ImportKeyEncAPDU;
 import org.dogtagpki.tps.apdu.InstallAppletAPDU;
 import org.dogtagpki.tps.apdu.InstallLoadAPDU;
 import org.dogtagpki.tps.apdu.LifecycleAPDU;
@@ -91,7 +92,7 @@ public class SecureChannel {
         this.sessionKey = sessionKey;
         this.encSessionKey = encSessionKey;
         this.drmDesKey = drmDesKey;
-        this.kekDesKey = kekDesKey;
+        this.setKekDesKey(kekDesKey);
         this.keyCheck = keyCheck;
         this.keyDiversificationData = keyDiversificationData;
         this.cardChallenge = cardChallenge;
@@ -996,4 +997,49 @@ public class SecureChannel {
 
     }
 
+    public TPSBuffer getDRMWrappedDesKey() {
+        return drmDesKey;
+    }
+
+    public void setDRMWrappedDesKey(TPSBuffer drmDesKey) {
+        this.drmDesKey = drmDesKey;
+    }
+
+    public TPSBuffer getKeyCheck() {
+        return keyCheck;
+    }
+
+    public void setKeyCheck(TPSBuffer theKeyCheck) {
+        this.keyCheck = theKeyCheck;
+    }
+
+    public void importKeyEnc(int pe1, int pe2, TPSBuffer data) throws TPSException, IOException {
+
+        CMS.debug("SecureChannel.importKeyEnc entering...");
+
+        if(data == null) {
+            throw new TPSException("SecureChannel.importKeyEnc: Invalid input data!",TPSStatus.STATUS_ERROR_MAC_CERT_PDU);
+        }
+
+        ImportKeyEncAPDU importKeyEnc = new ImportKeyEncAPDU((byte)pe1,(byte) pe2, data);
+
+        computeAPDU(importKeyEnc);
+
+        APDUResponse response = processor.handleAPDURequest(importKeyEnc);
+
+        if (!response.checkResult()) {
+            throw new TPSException("SecureChannel.importKeyEnc: failed to import private key!",
+                    TPSStatus.STATUS_ERROR_MAC_CERT_PDU);
+        }
+
+    }
+
+    public TPSBuffer getKekDesKey() {
+        return kekDesKey;
+    }
+
+    public void setKekDesKey(TPSBuffer kekDesKey) {
+        this.kekDesKey = kekDesKey;
+    }
+
 }
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/KRARemoteRequestHandler.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/KRARemoteRequestHandler.java
index 3a80e8d..87388ff 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/KRARemoteRequestHandler.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/KRARemoteRequestHandler.java
@@ -77,6 +77,7 @@ public class KRARemoteRequestHandler extends RemoteRequestHandler
                 (HttpConnector) subsystem.getConnectionManager().getConnector(connid);
         CMS.debug("KRARemoteRequestHandler: serverSideKeyGen(): sending request to CA");
         HttpResponse resp;
+        String request;
         if (isECC) {
             String eckeycurve;
             if (keysize == 521) {
@@ -92,35 +93,51 @@ public class KRARemoteRequestHandler extends RemoteRequestHandler
                 eckeycurve = "nistp256";
             }
 
+            request = IRemoteRequest.KRA_KEYGEN_Archive + "=" +
+            archive +
+            "&" + IRemoteRequest.TOKEN_CUID + "=" +
+            cuid +
+            "&" + IRemoteRequest.KRA_UserId + "=" +
+            userid +
+            "&" + IRemoteRequest.KRA_KEYGEN_KeyType + "=" +
+            "EC" +
+            "&" + IRemoteRequest.KRA_KEYGEN_EC_KeyCurve + "=" +
+            eckeycurve +
+            "&" + IRemoteRequest.KRA_Trans_DesKey + "=" +
+            sDesKey;
+
+           CMS.debug("KRARemoteRequestHandler: outgoing request for ECC: " + request);
+
             resp =
                     conn.send("GenerateKeyPair",
-                            IRemoteRequest.KRA_KEYGEN_Archive + "=" +
-                                    archive +
-                                    "&" + IRemoteRequest.TOKEN_CUID + "=" +
-                                    cuid +
-                                    "&" + IRemoteRequest.KRA_UserId + "=" +
-                                    userid +
-                                    "&" + IRemoteRequest.KRA_KEYGEN_KeyType + "=" +
-                                    "EC" +
-                                    "&" + IRemoteRequest.KRA_KEYGEN_EC_KeyCurve + "=" +
-                                    eckeycurve +
-                                    "&" + IRemoteRequest.KRA_Trans_DesKey + "=" +
-                                    sDesKey);
+                            request);
         } else { // RSA
+
+            request = IRemoteRequest.KRA_KEYGEN_Archive + "=" +
+                    archive +
+                    "&" + IRemoteRequest.TOKEN_CUID + "=" +
+                    cuid +
+                    "&" + IRemoteRequest.KRA_UserId + "=" +
+                    userid +
+                    "&" + IRemoteRequest.KRA_KEYGEN_KeyType + "=" +
+                    "RSA" +
+                    "&" + IRemoteRequest.KRA_KEYGEN_KeySize + "=" +
+                    keysize +
+                    "&" + IRemoteRequest.KRA_Trans_DesKey + "=" +
+                    sDesKey;
+
+            CMS.debug("KRARemoteRequestHandler: outgoing request for RSA: " + request);
+
             resp =
                     conn.send("GenerateKeyPair",
-                            IRemoteRequest.KRA_KEYGEN_Archive + "=" +
-                                    archive +
-                                    "&" + IRemoteRequest.TOKEN_CUID + "=" +
-                                    cuid +
-                                    "&" + IRemoteRequest.KRA_UserId + "=" +
-                                    userid +
-                                    "&" + IRemoteRequest.KRA_KEYGEN_KeyType + "=" +
-                                    "RSA" +
-                                    "&" + IRemoteRequest.KRA_KEYGEN_KeySize + "=" +
-                                    keysize +
-                                    "&" + IRemoteRequest.KRA_Trans_DesKey + "=" +
-                                    sDesKey);
+                            request);
+        }
+
+        //For some reason the send method can return null and not throw an exception.
+        // Check here;
+
+        if(resp == null) {
+            throw new EBaseException("KRARemoteRequestHandler: serverSideKeyGen(): No response object returned from connection.");
         }
 
         String content = resp.getContent();
@@ -138,6 +155,10 @@ public class KRARemoteRequestHandler extends RemoteRequestHandler
             Integer ist = new Integer(IRemoteRequest.RESPONSE_STATUS_NOT_FOUND);
             String value = (String) response.get(IRemoteRequest.RESPONSE_STATUS);
 
+            if(value == null) {
+                throw new EBaseException("KRARemoteRequestHandler: serverSideKeyGen(): Invalide status returned!");
+            }
+
             CMS.debug("KRARemoteRequestHandler: serverSideKeyGen(): got status = " + value);
             ist = Integer.parseInt(value);
             if (ist != 0) {
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
index 7657c21..2fe3825 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/TKSComputeSessionKeyResponse.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/TKSComputeSessionKeyResponse.java
@@ -58,4 +58,8 @@ public class TKSComputeSessionKeyResponse extends RemoteResponse
     public TPSBuffer getHostCryptogram() {
         return (TPSBuffer) nameValTable.get(IRemoteRequest.TKS_RESPONSE_HostCryptogram);
     }
+
+    public TPSBuffer getKekWrappedDesKey() {
+        return (TPSBuffer) nameValTable.get(IRemoteRequest.TKS_RESPONSE_KEK_DesKey);
+    }
 }
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 989608d..f06f11f 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
@@ -17,11 +17,14 @@
 // --- END COPYRIGHT BLOCK ---
 package org.dogtagpki.server.tps.engine;
 
+import org.dogtagpki.server.tps.cms.KRARemoteRequestHandler;
+import org.dogtagpki.server.tps.cms.KRAServerSideKeyGenResponse;
 import org.dogtagpki.server.tps.cms.TKSComputeSessionKeyResponse;
 import org.dogtagpki.server.tps.cms.TKSCreateKeySetDataResponse;
 import org.dogtagpki.server.tps.cms.TKSRemoteRequestHandler;
 import org.dogtagpki.tps.main.TPSBuffer;
 import org.dogtagpki.tps.main.TPSException;
+import org.dogtagpki.tps.main.Util;
 import org.dogtagpki.tps.msg.EndOpMsg.TPSStatus;
 
 import com.netscape.certsrv.apps.CMS;
@@ -112,9 +115,12 @@ public class TPSEngine {
     public static final int CFG_CHANNEL_DEF_APPLET_MEMORY_SIZE = 5000;
 
     /* token enrollment values */
+    public static final String CFG_KEYGEN_ENCRYPTION = "keyGen.encryption";
     public static final String CFG_KEYGEN_KEYTYPE_NUM = "keyGen.keyType.num";
     public static final String CFG_KEYGEN_KEYTYPE_VALUE = "keyGen.keyType.value";
     public static final String CFG_SERVER_KEYGEN_ENABLE = "serverKeygen.enable";
+    public static final String CFG_SERVER_KEY_ARCHIVAL = "serverKeygen.archive";
+    public static final String CFG_DRM_CONNECTOR = "serverKeygen.drm.conn";
 
     /* External reg values */
 
@@ -219,22 +225,23 @@ public class TPSEngine {
         int status = resp.getStatus();
         if (status != 0) {
             CMS.debug("TPSEngine.createKeySetData: Non zero status result: " + status);
-            throw new TPSException("TPSEngine.computeSessionKey: invalid returned status: " + status, TPSStatus.STATUS_ERROR_KEY_CHANGE_OVER);
+            throw new TPSException("TPSEngine.computeSessionKey: invalid returned status: " + status,
+                    TPSStatus.STATUS_ERROR_KEY_CHANGE_OVER);
 
         }
 
         TPSBuffer keySetData = resp.getKeySetData();
 
-        if(keySetData == null) {
+        if (keySetData == null) {
             CMS.debug("TPSEngine.createKeySetData: No valid key set data returned.");
-            throw new TPSException("TPSEngine.createKeySetData: No valid key set data returned.", TPSStatus.STATUS_ERROR_KEY_CHANGE_OVER);
+            throw new TPSException("TPSEngine.createKeySetData: No valid key set data returned.",
+                    TPSStatus.STATUS_ERROR_KEY_CHANGE_OVER);
 
         }
 
         return keySetData;
     }
 
-
     public static void main(String[] args) {
 
     }
@@ -284,4 +291,60 @@ public class TPSEngine {
 
     }
 
+    public KRAServerSideKeyGenResponse serverSideKeyGen(int keySize, String cuid, String userid, String drmConnId,
+            TPSBuffer wrappedDesKey,
+            boolean archive,
+            boolean isECC) throws TPSException {
+
+        CMS.debug("TPSEngine.serverSideKeyGen entering... keySize: " + keySize + " cuid: " + cuid + " userid: "
+                + userid + " drConnId: " + drmConnId + " wrappedDesKey: " + wrappedDesKey + " archive: " + archive
+                + " isECC: " + isECC);
+
+        if (cuid == null || userid == null || drmConnId == null || wrappedDesKey == null) {
+            throw new TPSException("TPSEngine.serverSideKeyGen: Invalid input data!",
+                    TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+        }
+
+        KRARemoteRequestHandler kra = null;
+        KRAServerSideKeyGenResponse resp = null;
+
+        try {
+            kra = new KRARemoteRequestHandler(drmConnId);
+
+            resp = kra.serverSideKeyGen(isECC, keySize, cuid, userid,
+                    Util.specialURLEncode(wrappedDesKey), archive);
+
+        } catch (EBaseException e) {
+            throw new TPSException("TPSEngine.serverSideKeyGen: Problem creating KRARemoteRequestHandler! "
+                    + e.toString());
+        }
+
+        int status = resp.getStatus();
+
+        if (status != 0) {
+            throw new TPSException("TPSEngine.serverSideKeyGen: Bad status from server: " + status,
+                    TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+        }
+
+        if (resp.getPublicKey() == null) {
+            throw new TPSException("TPSEngine.serverSideKeyGen: invalid public key from server! ",
+                    TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+        }
+
+        if (resp.getWrappedPrivKey() == null) {
+            throw new TPSException("TPSEngine.serverSideKeyGen: invalid private key from server! ",
+                    TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+
+        }
+
+        if (resp.getIVParam() == null) {
+            throw new TPSException("TPSEngine.serverSideKeyGen: invalid iv vector from server!",
+                    TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+        }
+
+        //We return this resonse we know that all the data is present and can be accessed
+        return resp;
+
+    }
+
 }
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 432fd1c..9bc831b 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
@@ -3,7 +3,6 @@ package org.dogtagpki.server.tps.processor;
 import java.io.IOException;
 import java.security.InvalidKeyException;
 import java.security.NoSuchAlgorithmException;
-import java.security.PublicKey;
 import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Random;
@@ -21,6 +20,7 @@ import org.dogtagpki.server.tps.channel.SecureChannel;
 import org.dogtagpki.server.tps.channel.SecureChannel.TokenKeyType;
 import org.dogtagpki.server.tps.cms.CAEnrollCertResponse;
 import org.dogtagpki.server.tps.cms.CARemoteRequestHandler;
+import org.dogtagpki.server.tps.cms.KRAServerSideKeyGenResponse;
 import org.dogtagpki.server.tps.dbs.ActivityDatabase;
 import org.dogtagpki.server.tps.dbs.TokenRecord;
 import org.dogtagpki.server.tps.engine.TPSEngine;
@@ -29,9 +29,13 @@ import org.dogtagpki.server.tps.main.PKCS11Obj;
 import org.dogtagpki.tps.apdu.ExternalAuthenticateAPDU.SecurityLevel;
 import org.dogtagpki.tps.main.TPSBuffer;
 import org.dogtagpki.tps.main.TPSException;
+import org.dogtagpki.tps.main.Util;
 import org.dogtagpki.tps.msg.BeginOpMsg;
 import org.dogtagpki.tps.msg.EndOpMsg.TPSStatus;
 import org.mozilla.jss.asn1.InvalidBERException;
+import org.mozilla.jss.crypto.InvalidKeyFormatException;
+import org.mozilla.jss.pkcs11.PK11PubKey;
+import org.mozilla.jss.pkcs11.PK11RSAPublicKey;
 import org.mozilla.jss.pkix.primitive.SubjectPublicKeyInfo;
 
 import com.netscape.certsrv.apps.CMS;
@@ -100,20 +104,20 @@ public class TPSEnrollProcessor extends TPSProcessor {
 
             TokenStatus newState = TokenStatus.ACTIVE;
             // Check for transition to ACTIVE status.
-            if(!tps.tdb.isTransitionAllowed(tokenRecord, newState )) {
+            if (!tps.tdb.isTransitionAllowed(tokenRecord, newState)) {
                 CMS.debug("TPSEnrollProcessor.enroll: token transition disallowed " +
                         tokenRecord.getTokenStatus() +
                         " to " + newState);
-                auditMsg = "Operation for CUID "+appletInfo.getCUIDhexStringPlain()+
+                auditMsg = "Operation for CUID " + appletInfo.getCUIDhexStringPlain() +
                         " Disabled, illegal transition attempted " + tokenRecord.getTokenStatus() +
                         " to " + newState;
                 tps.tdb.tdbActivity(tps, ActivityDatabase.OP_ENROLLMENT, tokenRecord, session.getIpAddress(),
-                            auditMsg, "failure");
+                        auditMsg, "failure");
 
                 throw new TPSException(auditMsg,
                         TPSStatus.STATUS_ERROR_DISABLED_TOKEN);
             } else {
-                CMS.debug("TPSPEnrollrocessor.enroll: token transition allowed "+
+                CMS.debug("TPSPEnrollrocessor.enroll: token transition allowed " +
                         tokenRecord.getTokenStatus() +
                         " to " + newState);
             }
@@ -126,7 +130,6 @@ public class TPSEnrollProcessor extends TPSProcessor {
         }
         checkAndAuthenticateUser(appletInfo, tokenType);
 
-
         if (do_force_format) {
             CMS.debug("TPSEnrollProcessor.enroll: About to force format first due to policy.");
             //We will skip the auth step inside of format
@@ -173,9 +176,9 @@ public class TPSEnrollProcessor extends TPSProcessor {
             tps.tdb.tdbUpdateTokenEntry(tps, tokenRecord);
             tps.tdb.tdbActivity(tps, ActivityDatabase.OP_ENROLLMENT, tokenRecord, session.getIpAddress(),
                     successMsg, "success");
-        } catch (Exception e){
+        } catch (Exception e) {
             String failMsg = "update token failure";
-            auditMsg =  failMsg + ":" + e.toString();
+            auditMsg = failMsg + ":" + e.toString();
             tps.tdb.tdbActivity(tps, ActivityDatabase.OP_ENROLLMENT, tokenRecord, session.getIpAddress(),
                     failMsg, "failure");
             throw new TPSException(auditMsg);
@@ -226,7 +229,8 @@ public class TPSEnrollProcessor extends TPSProcessor {
         channel.setLifeycleState((byte) 0x0f);
 
         auditMsg = "enroll operation succeeded";
-        tps.tdb.tdbActivity(tps, ActivityDatabase.OP_ENROLLMENT, tokenRecord, session.getIpAddress(), auditMsg, "success");
+        tps.tdb.tdbActivity(tps, ActivityDatabase.OP_ENROLLMENT, tokenRecord, session.getIpAddress(), auditMsg,
+                "success");
         //nothing to do here; log it and continue
         CMS.debug(auditMsg);
 
@@ -301,7 +305,7 @@ public class TPSEnrollProcessor extends TPSProcessor {
             IConfigStore configStore = CMS.getConfigStore();
 
             TPSSubsystem tps =
-                (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+                    (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
             //TPSSession session = getSession();
             boolean isAuthRequired;
             try {
@@ -319,7 +323,7 @@ public class TPSEnrollProcessor extends TPSProcessor {
                             getAuthentication(TPSEngine.OP_ENROLL_PREFIX, tokenType);
                     userCred = requestUserId(TPSEngine.ENROLL_OP, appletInfo.getCUIDhexString(), userAuth,
                             beginMsg.getExtensions());
-                    userid = (String)userCred.get(userAuth.getAuthCredName());
+                    userid = (String) userCred.get(userAuth.getAuthCredName());
                     CMS.debug("TPSEnrollProcessor.checkAndAuthenticateUser: userCred (attempted) userid=" + userid);
                     // initialize userid first for logging purposes in case authentication fails
                     tokenRecord.setUserID(userid);
@@ -334,10 +338,10 @@ public class TPSEnrollProcessor extends TPSProcessor {
                     CMS.debug("TPSEnrollProcessor.checkAndAuthenticateUser:: authentication exception thrown: " + e);
                     String msg = "TPS error user authentication failed:" + e;
                     tps.tdb.tdbActivity(tps, ActivityDatabase.OP_ENROLLMENT, tokenRecord, session.getIpAddress(),
-                           msg, "failure");
+                            msg, "failure");
 
                     throw new TPSException(msg,
-                             TPSStatus.STATUS_ERROR_LOGIN);
+                            TPSStatus.STATUS_ERROR_LOGIN);
                 }
             } else {
                 throw new TPSException(
@@ -435,9 +439,24 @@ public class TPSEnrollProcessor extends TPSProcessor {
             securityLevel = SecurityLevel.SECURE_MSG_MAC_ENC;
 
         if (checkForAppletUpdateEnabled()) {
-            String targetAppletVersion = checkForAppletUpgrade("op."+currentTokenOperation);
-            upgradeApplet("op."+currentTokenOperation, targetAppletVersion, securityLevel, getBeginMessage().getExtensions(),
-                    tksConnId, 5, 12);
+
+            String targetAppletVersion = checkForAppletUpgrade("op." + currentTokenOperation);
+            targetAppletVersion = targetAppletVersion.toLowerCase();
+
+            String currentAppletVersion = formatCurrentAppletVersion(appletInfo);
+
+            CMS.debug("TPSEnrollProcessor.checkAndUpgradeApplet: currentAppletVersion: " + currentAppletVersion
+                    + " targetAppletVersion: " + targetAppletVersion);
+
+            if (targetAppletVersion.compareTo(currentAppletVersion) != 0) {
+
+                CMS.debug("TPSEnrollProessor.checkAndUpgradeApplet: Upgrading applet to : " + targetAppletVersion);
+                upgradeApplet("op." + currentTokenOperation, targetAppletVersion, securityLevel, getBeginMessage()
+                        .getExtensions(),
+                        tksConnId, 5, 12);
+            } else {
+                CMS.debug("TPSEnrollProcessor.checkAndUpgradeApplet: applet already at correct version.");
+            }
         }
 
     }
@@ -547,7 +566,7 @@ public class TPSEnrollProcessor extends TPSProcessor {
             throws TPSException, IOException {
 
         CMS.debug("TPSProcess.generateCertificates: begins ");
-        if (certsInfo == null || aInfo == null) {
+        if (certsInfo == null || aInfo == null || channel == null) {
             throw new TPSException("TPSEnrollProcessor.generateCertificates: Bad Input data!",
                     TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
         }
@@ -562,7 +581,6 @@ public class TPSEnrollProcessor extends TPSProcessor {
             String keyType = getConfiguredKeyType(i);
             certsInfo.setCurrentCertIndex(i);
             generateCertificate(certsInfo, channel, aInfo, keyType);
-            channel = setupSecureChannel();
         }
 
         CMS.debug("TPSProcess.generateCertificates: ends ");
@@ -615,7 +633,7 @@ public class TPSEnrollProcessor extends TPSProcessor {
 
         CMS.debug("TPSEnrollProcessor.generateCertificate: entering ...");
 
-        if (certsInfo == null || aInfo == null) {
+        if (certsInfo == null || aInfo == null || channel == null || aInfo == null) {
             throw new TPSException("TPSEnrollProcessor.generateCertificate: Bad Input data!",
                     TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
         }
@@ -749,11 +767,12 @@ public class TPSEnrollProcessor extends TPSProcessor {
     }
 
     private void enrollOneCertificate(EnrolledCertsInfo certsInfo, CertEnrollInfo cEnrollInfo, AppletInfo aInfo,
-            SecureChannel channel) throws TPSException, IOException {
+            SecureChannel channel)
+            throws TPSException, IOException {
 
         CMS.debug("TPSEnrollProcessor.enrollOneCertificate: entering ...");
 
-        if (certsInfo == null || aInfo == null || cEnrollInfo == null) {
+        if (certsInfo == null || aInfo == null || cEnrollInfo == null || channel == null) {
             throw new TPSException("TPSEnrollProcessor.enrollOneCertificate: Bad Input data!",
                     TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
         }
@@ -785,12 +804,42 @@ public class TPSEnrollProcessor extends TPSProcessor {
 
         }
 
+        TPSBuffer public_key_blob = null;
+        KRAServerSideKeyGenResponse ssKeyGenResponse = null;
+        RSAPublicKey parsedPubKey = null;
+        PK11PubKey parsedPK11PubKey = null;
+        byte[] parsedPubKey_ba = null;
+
+        //SecureChannel channel = setupSecureChannel();
         if (serverSideKeyGen) {
             //Handle server side keyGen
 
+            CMS.debug("TPSEnrollProcessor.enrollOneCertificate: about to generate the private key on the server.");
+            boolean archive = checkForServerKeyArchival(cEnrollInfo);
+            String drmConnId = getDRMConnectorID();
+
+            ssKeyGenResponse = getTPSEngine().serverSideKeyGen(cEnrollInfo.getKeySize(),
+                    aInfo.getCUIDhexStringPlain(), userid, drmConnId, channel.getDRMWrappedDesKey(), archive, isECC);
+
+            String publicKeyStr = ssKeyGenResponse.getPublicKey();
+            CMS.debug("TPSEnrollProcessor.enrollOneCertificate: public key string from server: " + publicKeyStr);
+            public_key_blob = new TPSBuffer(Utils.base64decode(publicKeyStr));
+
+            try {
+                parsedPK11PubKey = PK11RSAPublicKey.fromSPKI(public_key_blob.toBytesArray());
+
+            } catch (InvalidKeyFormatException e) {
+                CMS.debug("TPSEnrollProcessor.enrollOneCertificate, can't create public key object from server side key generated public key blob!");
+                throw new TPSException(
+                        "TPSEnrollProcessor.enrollOneCertificate, can't create public key object from server side key generated public key blob!",
+                        TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+            }
+
+            parsedPubKey_ba = parsedPK11PubKey.getEncoded();
+
         } else {
             //Handle token side keyGen
-            CMS.debug("TPSEnrollProcessor.enrollOneCertificate: about to generate the keys on the token.");
+            CMS.debug("TPSEnrollProcessor.enrollOneCertificate: about to generate the private key on the token.");
 
             int algorithm = 0x80;
 
@@ -811,149 +860,263 @@ public class TPSEnrollProcessor extends TPSProcessor {
             byte[] iobytes = { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff };
             TPSBuffer iobuf = new TPSBuffer(iobytes);
 
-            TPSBuffer public_key_blob = channel.readObject(iobuf, 0, size);
+            public_key_blob = channel.readObject(iobuf, 0, size);
 
-            PublicKey parsedPubKey = parsePublicKeyBlob(public_key_blob, isECC);
-            byte[] parsedPubKey_ba = parsedPubKey.getEncoded();
+            parsedPubKey = parsePublicKeyBlob(public_key_blob, isECC);
 
-            // 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();
-                selectCoolKeyApplet();
-                CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: userid =" + userid + ", cuid="
-                        + appletInfo.getCUIDhexString());
-                CAEnrollCertResponse caEnrollResp = caRH.enrollCertificate(encodedParsedPubKey, userid,
-                        appletInfo.getCUIDhexString(), getSelectedTokenType(),
-                        cEnrollInfo.getKeyType());
-                String retCertB64 = caEnrollResp.getCertB64();
-
-                CMS.debug("TPSEnrollProcessor.enrollOneCertificate: retCertB64: " + retCertB64);
-
-                byte[] cert_bytes = Utils.base64decode(retCertB64);
-
-                TPSBuffer cert_bytes_buf = new TPSBuffer(cert_bytes);
-                CMS.debug("TPSEnrollProcessor.enrollOneCertificate: retCertB64: " + cert_bytes_buf.toHexString());
-
-                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);
-                }
+            parsedPubKey_ba = parsedPubKey.getEncoded();
+        }
 
-                certsInfo.addCertificate(x509Cert);
-                certsInfo.addKType(cEnrollInfo.getKeyType());
-                certsInfo.addOrigin(aInfo.getCUIDhexString());
+        // enrollment begins
+        CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: enrollment begins");
+        try {
+            String caConnID = getCAConnectorID();
+            CARemoteRequestHandler caRH = new CARemoteRequestHandler(caConnID);
+            TPSBuffer encodedParsedPubKey = new TPSBuffer(parsedPubKey_ba);
+
+            // selectCoolKeyApplet();
+            CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: userid =" + userid + ", cuid="
+                    + aInfo.getCUIDhexString());
+            CAEnrollCertResponse caEnrollResp = caRH.enrollCertificate(encodedParsedPubKey, userid,
+                    aInfo.getCUIDhexString(), getSelectedTokenType(),
+                    cEnrollInfo.getKeyType());
+            String retCertB64 = caEnrollResp.getCertB64();
+
+            CMS.debug("TPSEnrollProcessor.enrollOneCertificate: retCertB64: " + retCertB64);
+
+            byte[] cert_bytes = Utils.base64decode(retCertB64);
+
+            TPSBuffer cert_bytes_buf = new TPSBuffer(cert_bytes);
+            CMS.debug("TPSEnrollProcessor.enrollOneCertificate: retCertB64: " + cert_bytes_buf.toHexString());
+
+            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);
+            }
 
-                SubjectPublicKeyInfo publicKeyInfo = null;
-                try {
+            certsInfo.addCertificate(x509Cert);
+            certsInfo.addKType(cEnrollInfo.getKeyType());
+            certsInfo.addOrigin(aInfo.getCUIDhexString());
+
+            SubjectPublicKeyInfo publicKeyInfo = null;
+            try {
+                if (serverSideKeyGen) {
+                    publicKeyInfo = new SubjectPublicKeyInfo(parsedPK11PubKey);
+                } else {
                     publicKeyInfo = new SubjectPublicKeyInfo(parsedPubKey);
-                } catch (InvalidBERException e) {
-                    CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: cant get publicKeyInfo object.");
-                    throw new TPSException("TPSEnrollProcessor.enrollOneCertificate: can't get publcKeyInfo object.",
-                            TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
                 }
+            } catch (InvalidBERException e) {
+                CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: cant get publicKeyInfo object.");
+                throw new TPSException("TPSEnrollProcessor.enrollOneCertificate: can't get publcKeyInfo object.",
+                        TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+            }
+
+            //Create label ToDo: Do this the correct way later
 
-                //Create label ToDo: Do this the correct way later
+            String label = buildCertificateLabel(cEnrollInfo, aInfo);
+            CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: cert label: " + label);
 
-                String label = buildCertificateLabel(cEnrollInfo, aInfo);
-                CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: cert label: " + label);
+            TPSBuffer keyid = new TPSBuffer(makeKeyIDFromPublicKeyInfo(publicKeyInfo.getEncoded()));
 
-                TPSBuffer keyid = new TPSBuffer(makeKeyIDFromPublicKeyInfo(publicKeyInfo.getEncoded()));
+            TPSBuffer modulus = null;
+            TPSBuffer exponent = null;
 
-                RSAPublicKey rsaPubKey = (RSAPublicKey) parsedPubKey;
-                TPSBuffer modulus = new TPSBuffer(rsaPubKey.getModulus().toByteArray());
-                TPSBuffer exponent = new TPSBuffer(rsaPubKey.getPublicExponent().toByteArray());
+            if (serverSideKeyGen) {
+                modulus = new TPSBuffer(((PK11RSAPublicKey) parsedPK11PubKey).getModulus().toByteArray());
+                exponent = new TPSBuffer(((PK11RSAPublicKey) parsedPK11PubKey).getPublicExponent().toByteArray());
 
-                //Write cert to the token
+            } else {
+                modulus = new TPSBuffer(parsedPubKey.getModulus().toByteArray());
+                exponent = new TPSBuffer(parsedPubKey.getPublicExponent().toByteArray());
+            }
 
-                long l1, l2;
-                long objid;
-                PKCS11Obj pkcs11Obj = certsInfo.getPKCS11Obj();
+            //Write cert to the token
 
-                String certId = cEnrollInfo.getCertId();
+            long l1, l2;
+            long objid;
+            PKCS11Obj pkcs11Obj = certsInfo.getPKCS11Obj();
 
-                l1 = (certId.charAt(0) & 0xff) << 24;
-                l2 = (certId.charAt(1) & 0xff) << 16;
-                objid = l1 + l2;
+            String certId = cEnrollInfo.getCertId();
 
-                CMS.debug("TPSEnrollProcess.enrollOneCertificate:  cert objid long: " + objid);
+            l1 = (certId.charAt(0) & 0xff) << 24;
+            l2 = (certId.charAt(1) & 0xff) << 16;
+            objid = l1 + l2;
 
-                ObjectSpec certObjSpec = ObjectSpec.parseFromTokenData(objid, new TPSBuffer(cert_bytes));
-                pkcs11Obj.addObjectSpec(certObjSpec);
+            CMS.debug("TPSEnrollProcess.enrollOneCertificate:  cert objid long: " + objid);
 
-                String certAttrId = cEnrollInfo.getCertAttrId();
+            ObjectSpec certObjSpec = ObjectSpec.parseFromTokenData(objid, new TPSBuffer(cert_bytes));
+            pkcs11Obj.addObjectSpec(certObjSpec);
 
-                TPSBuffer certAttrsBuffer = channel.createPKCS11CertAttrsBuffer(cEnrollInfo.getKeyTypeEnum(),
-                        certAttrId, label, keyid);
+            String certAttrId = cEnrollInfo.getCertAttrId();
 
-                l1 = (certAttrId.charAt(0) & 0xff) << 24;
-                l2 = (certAttrId.charAt(1) & 0xff) << 16;
-                objid = l1 + l2;
+            TPSBuffer certAttrsBuffer = channel.createPKCS11CertAttrsBuffer(cEnrollInfo.getKeyTypeEnum(),
+                    certAttrId, label, keyid);
 
-                CMS.debug("TPSEnrollProcess.enrollOneCertificate:  cert attr objid long: " + objid);
-                ObjectSpec certAttrObjSpec = ObjectSpec.parseFromTokenData(objid, certAttrsBuffer);
-                pkcs11Obj.addObjectSpec(certAttrObjSpec);
+            l1 = (certAttrId.charAt(0) & 0xff) << 24;
+            l2 = (certAttrId.charAt(1) & 0xff) << 16;
+            objid = l1 + l2;
 
-                //Add the pri key attrs object
+            CMS.debug("TPSEnrollProcess.enrollOneCertificate:  cert attr objid long: " + objid);
+            ObjectSpec certAttrObjSpec = ObjectSpec.parseFromTokenData(objid, certAttrsBuffer);
+            pkcs11Obj.addObjectSpec(certAttrObjSpec);
 
-                String priKeyAttrId = cEnrollInfo.getPrivateKeyAttrId();
+            //Add the pri key attrs object
 
-                l1 = (priKeyAttrId.charAt(0) & 0xff) << 24;
-                l2 = (priKeyAttrId.charAt(1) & 0xff) << 16;
+            String priKeyAttrId = cEnrollInfo.getPrivateKeyAttrId();
 
-                objid = l1 + l2;
+            l1 = (priKeyAttrId.charAt(0) & 0xff) << 24;
+            l2 = (priKeyAttrId.charAt(1) & 0xff) << 16;
 
-                CMS.debug("TPSEnrollProcess.enrollOneCertificate: pri key objid long: " + objid);
+            objid = l1 + l2;
 
-                TPSBuffer privKeyAttrsBuffer = channel.createPKCS11PriKeyAttrsBuffer(priKeyAttrId, label, keyid,
-                        modulus, cEnrollInfo.getKeyTypePrefix());
+            CMS.debug("TPSEnrollProcess.enrollOneCertificate: pri key objid long: " + objid);
 
-                ObjectSpec priKeyObjSpec = ObjectSpec.parseFromTokenData(objid, privKeyAttrsBuffer);
-                pkcs11obj.addObjectSpec(priKeyObjSpec);
+            TPSBuffer privKeyAttrsBuffer = channel.createPKCS11PriKeyAttrsBuffer(priKeyAttrId, label, keyid,
+                    modulus, cEnrollInfo.getKeyTypePrefix());
 
-                // Now add the public key object
+            ObjectSpec priKeyObjSpec = ObjectSpec.parseFromTokenData(objid, privKeyAttrsBuffer);
+            pkcs11obj.addObjectSpec(priKeyObjSpec);
 
-                String pubKeyAttrId = cEnrollInfo.getPublicKeyAttrId();
+            // Now add the public key object
 
-                l1 = (pubKeyAttrId.charAt(0) & 0xff) << 24;
-                l2 = (pubKeyAttrId.charAt(1) & 0xff) << 16;
+            String pubKeyAttrId = cEnrollInfo.getPublicKeyAttrId();
 
-                objid = l1 + l2;
-                CMS.debug("TPSEnrollProcess.enrollOneCertificate: pub key objid long: " + objid);
+            l1 = (pubKeyAttrId.charAt(0) & 0xff) << 24;
+            l2 = (pubKeyAttrId.charAt(1) & 0xff) << 16;
 
-                TPSBuffer pubKeyAttrsBuffer = channel.createPKCS11PublicKeyAttrsBuffer(pubKeyAttrId, label, keyid,
-                        modulus, exponent, cEnrollInfo.getKeyTypePrefix());
-                ObjectSpec pubKeyObjSpec = ObjectSpec.parseFromTokenData(objid, pubKeyAttrsBuffer);
-                pkcs11obj.addObjectSpec(pubKeyObjSpec);
+            objid = l1 + l2;
+            CMS.debug("TPSEnrollProcess.enrollOneCertificate: pub key objid long: " + objid);
 
-            } 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");
+            TPSBuffer pubKeyAttrsBuffer = channel.createPKCS11PublicKeyAttrsBuffer(pubKeyAttrId, label, keyid,
+                    modulus, exponent, cEnrollInfo.getKeyTypePrefix());
+            ObjectSpec pubKeyObjSpec = ObjectSpec.parseFromTokenData(objid, pubKeyAttrsBuffer);
+            pkcs11obj.addObjectSpec(pubKeyObjSpec);
+
+        } catch (EBaseException e) {
+            CMS.debug("TPSEnrollProcessor.enrollOneCertificate::" + e);
+            throw new TPSException("TPSEnrollProcessor.enrollOneCertificate: Exception thrown: " + e,
+                    TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+        }
+
+        if (serverSideKeyGen) {
+            //Handle injection of private key onto token
+            CMS.debug("TPSEnrollProcessor.enrollOneCertificate: About to inject private key");
+
+            // SecureChannel newChannel = setupSecureChannel();
+            importPrivateKeyPKCS8(ssKeyGenResponse, cEnrollInfo, channel, isECC);
 
         }
 
+        CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: enrollment ends");
+
         statusUpdate(cEnrollInfo.getEndProgressValue(), "PROGRESS_ENROLL_CERT");
         CMS.debug("TPSEnrollProcessor.enrollOneCertificate ends");
 
     }
 
+    private void importPrivateKeyPKCS8(KRAServerSideKeyGenResponse ssKeyGenResponse, CertEnrollInfo cEnrollInfo,
+            SecureChannel channel,
+            boolean isECC) throws TPSException, IOException {
+
+        CMS.debug("TPSEnrollProcessor.importprivateKeyPKCS8 entering..");
+        if (ssKeyGenResponse == null || cEnrollInfo == null || channel == null) {
+            throw new TPSException("TPSEnrollProcessor.importPrivateKeyPKCS8: invalid input data!",
+                    TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+        }
+
+        byte[] objid = {
+                (byte) 0xFF,
+                0x00,
+                (byte) 0xFF,
+                (byte) 0xF3 };
+
+        byte keytype = 0x09; //RSAPKCS8Pair
+
+        String wrappedPrivKeyStr = ssKeyGenResponse.getWrappedPrivKey();
+        int keysize = cEnrollInfo.getKeySize();
+
+        TPSBuffer privKeyBlob = new TPSBuffer();
+
+        privKeyBlob.add((byte) 0x1); // encryption
+        privKeyBlob.add(keytype);
+        privKeyBlob.add((byte) (keysize / 256));
+        privKeyBlob.add((byte) (keysize % 256));
+
+        TPSBuffer privKeyBuff = new TPSBuffer(Util.uriDecodeFromHex(wrappedPrivKeyStr));
+        privKeyBlob.add(privKeyBuff);
+
+        CMS.debug("TPSEnrollProcessor.importprivateKeyPKCS8 privKeyBlob: " + privKeyBlob.toHexString());
+
+        byte[] perms = { 0x40,
+                0x00,
+                0x40,
+                0x00,
+                0x40,
+                0x00 };
+
+        TPSBuffer objIdBuff = new TPSBuffer(objid);
+
+        channel.createObject(objIdBuff, new TPSBuffer(perms), privKeyBlob.size());
+
+        channel.writeObject(objIdBuff, privKeyBlob);
+
+        TPSBuffer keyCheck = channel.getKeyCheck();
+
+        CMS.debug("TPSEnrollProcessor.importprivateKeyPKCS8 : keyCheck: " + keyCheck.toHexString());
+
+        String ivParams = ssKeyGenResponse.getIVParam();
+        CMS.debug("TPSEnrollProcessor.importprivateKeyPKCS8: ivParams: " + ivParams);
+        TPSBuffer ivParamsBuff = new TPSBuffer(Util.uriDecodeFromHex(ivParams));
+
+        if (ivParamsBuff.size() == 0) {
+            throw new TPSException("TPSEnrollProcessor.importPrivateKeyPKCS8: invalid iv vector!",
+                    TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+
+        }
+
+        TPSBuffer kekWrappedDesKey = channel.getKekDesKey();
+
+        if (kekWrappedDesKey != null)
+            CMS.debug("TPSEnrollProcessor.importPrivateKeyPKCS8: keyWrappedDesKey: " + kekWrappedDesKey.toHexString());
+        else
+            CMS.debug("TPSEnrollProcessor.iportPrivateKeyPKC8: null kekWrappedDesKey!");
+
+        byte alg = (byte) 0x80;
+        if (kekWrappedDesKey == null || kekWrappedDesKey.size() > 0) {
+            alg = (byte) 0x81;
+        }
+
+        TPSBuffer data = new TPSBuffer();
+
+        data.add(objIdBuff);
+        data.add(alg);
+        data.add((byte) kekWrappedDesKey.size());
+        data.add(kekWrappedDesKey);
+        data.add((byte) keyCheck.size());
+        data.add(keyCheck);
+        data.add((byte) ivParamsBuff.size());
+        data.add(ivParamsBuff);
+
+        int pe1 = (cEnrollInfo.getKeyUser() << 4) + cEnrollInfo.getPrivateKeyNumber();
+        int pe2 = (cEnrollInfo.getKeyUsage() << 4) + cEnrollInfo.getPublicKeyNumber();
+
+        channel.importKeyEnc(pe1, pe2, data);
+
+        CMS.debug("TPSEnrollProcessor.importprivateKeyPKCS8 successful, leaving...");
+
+    }
+
     private String buildCertificateLabel(CertEnrollInfo cEnrollInfo, AppletInfo ainfo) throws TPSException {
 
         CMS.debug("TPSEnrollProcessor.buildCertificateLabel");
@@ -1071,12 +1234,12 @@ public class TPSEnrollProcessor extends TPSProcessor {
      * @param challenge the challenge generated by TPS
      *
      ******/
-    private PublicKey parsePublicKeyBlob(
+    private RSAPublicKey parsePublicKeyBlob(
             TPSBuffer public_key_blob,
             /* TPSBuffer challenge,*/
             boolean isECC)
             throws TPSException {
-        PublicKey parsedPubKey = null;
+        RSAPublicKey parsedPubKey = null;
 
         if (public_key_blob == null /*|| challenge == null*/) {
             throw new TPSException(
@@ -1237,6 +1400,33 @@ public class TPSEnrollProcessor extends TPSProcessor {
 
     }
 
+    private boolean checkForServerKeyArchival(CertEnrollInfo cInfo) throws TPSException {
+
+        if (cInfo == null) {
+            throw new TPSException("TPSEnrollProcessor.checkForServerKeyArchival: invalid cert info.",
+                    TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+        }
+        IConfigStore configStore = CMS.getConfigStore();
+        boolean serverKeyArchival = false;
+
+        try {
+            String configValue = cInfo.getKeyTypePrefix() + "." + TPSEngine.CFG_SERVER_KEY_ARCHIVAL;
+            CMS.debug("TPSEnrollProcessor.checkForServerKeyArchival: config: " + configValue);
+            serverKeyArchival = configStore.getBoolean(
+                    configValue, false);
+
+        } catch (EBaseException e) {
+            throw new TPSException(
+                    "TPSEnrollProcessor.checkForServerKeyArchival: Internal error finding config value: " + e,
+                    TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+        }
+
+        CMS.debug("TPSProcess.checkForServerKeyArchival: returning: " + serverKeyArchival);
+
+        return serverKeyArchival;
+
+    }
+
     private boolean checkForObjectOverwrite(CertEnrollInfo cInfo) throws TPSException {
 
         if (cInfo == null) {
@@ -1297,6 +1487,26 @@ public class TPSEnrollProcessor extends TPSProcessor {
 
     }
 
+    private String getDRMConnectorID() throws TPSException {
+        IConfigStore configStore = CMS.getConfigStore();
+        String id = null;
+
+        String config = "op." + currentTokenOperation + "." + selectedTokenType + "." + TPSEngine.CFG_KEYGEN_ENCRYPTION
+                + "." + TPSEngine.CFG_DRM_CONNECTOR;
+
+        CMS.debug("TPSEnrollProcessor.getDRMConnectorID: config value: " + config);
+        try {
+            id = configStore.getString(config, "kra1");
+        } catch (EBaseException e) {
+            throw new TPSException("TPSProcessor.getDRMConnectorID: Internal error finding config value.");
+
+        }
+
+        CMS.debug("TPSProcessor.getDRMConectorID: returning: " + id);
+
+        return id;
+    }
+
     protected int getNumberCertsToEnroll() throws TPSException {
         IConfigStore configStore = CMS.getConfigStore();
         int keyTypeNum = 0;
@@ -1346,7 +1556,7 @@ public class TPSEnrollProcessor extends TPSProcessor {
         final String alg = "SHA1";
 
         if (publicKeyInfo == null) {
-            throw new TPSException("TPSEnrollProcessor.makeKeyFromPublicKeyInfo: invalid input data",
+            throw new TPSException("TPSEnrollProcessor.makeKeyIDFromPublicKeyInfo: invalid input data",
                     TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
         }
 
@@ -1358,7 +1568,7 @@ public class TPSEnrollProcessor extends TPSProcessor {
         try {
             mozillaDigest = java.security.MessageDigest.getInstance(alg);
         } catch (NoSuchAlgorithmException e) {
-            throw new TPSException("TPSEnrollProcessor.makeKeyFromPublicKeyInfo: " + e,
+            throw new TPSException("TPSEnrollProcessor.makeKeyIDFromPublicKeyInfo: " + e,
                     TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
         }
 
@@ -1375,7 +1585,7 @@ public class TPSEnrollProcessor extends TPSProcessor {
 
         keyID = new TPSBuffer(mozillaDigestOut);
 
-        CMS.debug("TPSEnrollProcessor.makeKeyFromPublicKeyInfo: " + keyID.toHexString());
+        CMS.debug("TPSEnrollProcessor.makeKeyIDFromPublicKeyInfo: " + keyID.toHexString());
 
         return keyID;
     }
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 9a2a25c..94cab4a 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
@@ -142,7 +142,7 @@ public class TPSProcessor {
         if (theTokenType == null) {
             throw new NullPointerException("TPSProcessor.setSelectedTokenType: Attempt to set invalid null token type!");
         }
-        CMS.debug("TPS_Processor.setSelectedTokenType: tokenType="+
+        CMS.debug("TPS_Processor.setSelectedTokenType: tokenType=" +
                 theTokenType);
         selectedTokenType = theTokenType;
 
@@ -520,7 +520,14 @@ public class TPSProcessor {
         TPSBuffer kekDesKey = null;
         TPSBuffer keyCheck = null;
 
+        drmDesKey = resp.getDRM_Trans_DesKey();
+        keyCheck = resp.getKeyCheck();
+        kekDesKey = resp.getKekWrappedDesKey();
+
         if (checkServerSideKeyGen(connId)) {
+
+            CMS.debug("TPSProcessor.generateSecureChannel: drmDesKey: " + drmDesKey + " kekDesKey : " + kekDesKey
+                    + " keyCheck: " + keyCheck);
             //ToDo handle server side keygen.
 
         }
@@ -673,13 +680,13 @@ public class TPSProcessor {
                 (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
         TPSAuthenticator authInst =
                 subsystem.getAuthenticationManager().getAuthInstance(authId);
-        String authCredNameConf = "auths.instance."+ authId + ".authCredName";
+        String authCredNameConf = "auths.instance." + authId + ".authCredName";
         CMS.debug("TPSProcessor.getAuthentication: getting config: " +
                 authCredNameConf);
         String authCredName = configStore.getString(authCredNameConf);
         if (authCredName == null) {
-            auditMsg = "TPSProcessor.getAuthentication: config param not found:"+ authCredNameConf;
-           CMS.debug(auditMsg);
+            auditMsg = "TPSProcessor.getAuthentication: config param not found:" + authCredNameConf;
+            CMS.debug(auditMsg);
             throw new EBaseException(auditMsg);
         }
         authInst.setAuthCredName(authCredName);
@@ -812,7 +819,7 @@ public class TPSProcessor {
         String[] requiredCreds = auth.getAuthManager().getRequiredCreds();
         for (String cred : requiredCreds) {
             String name = auth.getCredMap(cred, extendedLogin);
-            CMS.debug("TPSProcessor.mapCredFromMsgResponse: cred="+cred+ " &name="+
+            CMS.debug("TPSProcessor.mapCredFromMsgResponse: cred=" + cred + " &name=" +
                     name);
             login.set(cred, response.get(name));
         }
@@ -935,7 +942,8 @@ public class TPSProcessor {
             CMS.debug("TPSProcessor.createTokenRecord: failed getting applet version:" + e + " ... continue");
         }
         if (build_id != null) {
-            tokenRecord.setAppletID(Integer.toHexString(app_major_version) + "." + Integer.toHexString(app_minor_version) + "."+
+            tokenRecord.setAppletID(Integer.toHexString(app_major_version) + "."
+                    + Integer.toHexString(app_minor_version) + "." +
                     build_id.toHexStringPlain());
         }
 
@@ -1003,7 +1011,7 @@ public class TPSProcessor {
                 tps.tdb.tdbActivity(tps, ActivityDatabase.OP_FORMAT, tokenRecord, session.getIpAddress(),
                         auditMsg, "failure");
 
-                throw new TPSException(auditMsg,TPSStatus.STATUS_ERROR_MISCONFIGURATION);
+                throw new TPSException(auditMsg, TPSStatus.STATUS_ERROR_MISCONFIGURATION);
             }
             CMS.debug("TPSProcessor.format: calculated tokenType: " + tokenType);
         }
@@ -1046,7 +1054,7 @@ public class TPSProcessor {
                     auditMsg = "authentication failed, status = STATUS_ERROR_LOGIN";
 
                     tps.tdb.tdbActivity(tps, ActivityDatabase.OP_FORMAT, tokenRecord, session.getIpAddress(),
-                                auditMsg, "failure");
+                            auditMsg, "failure");
 
                     throw new TPSException(auditMsg,
                             TPSStatus.STATUS_ERROR_LOGIN);
@@ -1067,11 +1075,11 @@ public class TPSProcessor {
             CMS.debug("TPSProcessor.format: token exists");
             TokenStatus newState = TokenStatus.UNINITIALIZED;
             // Check for transition to 0/UNINITIALIZED status.
-            if(!tps.tdb.isTransitionAllowed(tokenRecord, newState )) {
+            if (!tps.tdb.isTransitionAllowed(tokenRecord, newState)) {
                 CMS.debug("TPSProcessor.format: token transition disallowed " +
                         tokenRecord.getTokenStatus() +
                         " to " + newState);
-                auditMsg = "Operation for CUID "+appletInfo.getCUIDhexStringPlain()+
+                auditMsg = "Operation for CUID " + appletInfo.getCUIDhexStringPlain() +
                         " Disabled, illegal transition attempted " + tokenRecord.getTokenStatus() +
                         " to " + newState;
 
@@ -1081,7 +1089,7 @@ public class TPSProcessor {
                 throw new TPSException(auditMsg,
                         TPSStatus.STATUS_ERROR_DISABLED_TOKEN);
             } else {
-                CMS.debug("TPSProcessor.format: token transition allowed "+
+                CMS.debug("TPSProcessor.format: token transition allowed " +
                         tokenRecord.getTokenStatus() +
                         " to " + newState);
             }
@@ -1135,7 +1143,7 @@ public class TPSProcessor {
             String successMsg = "update token success";
             tps.tdb.tdbActivity(tps, ActivityDatabase.OP_FORMAT, tokenRecord, session.getIpAddress(),
                     successMsg, "success");
-        } catch (Exception e){
+        } catch (Exception e) {
             String failMsg = "update token failure";
             auditMsg = failMsg + ":" + e.toString();
             tps.tdb.tdbActivity(tps, ActivityDatabase.OP_FORMAT, tokenRecord, session.getIpAddress(),
@@ -1414,9 +1422,9 @@ public class TPSProcessor {
 
         IConfigStore configStore = CMS.getConfigStore();
 
-        String appletUpdate = "op."+ currentTokenOperation + "." + selectedTokenType + "."
+        String appletUpdate = "op." + currentTokenOperation + "." + selectedTokenType + "."
                 + TPSEngine.CFG_UPDATE_APPLET_ENABLE;
-        CMS.debug("TPSProcessor.checkForAppletUpdateEnabled: getting config: "+ appletUpdate);
+        CMS.debug("TPSProcessor.checkForAppletUpdateEnabled: getting config: " + appletUpdate);
         try {
             enabled = configStore.getBoolean(appletUpdate, false);
         } catch (EBaseException e) {
@@ -1425,7 +1433,7 @@ public class TPSProcessor {
                     TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
 
         }
-        CMS.debug("TPSProcessor.checkForAppletUpdateEnabled: returning "+ enabled);
+        CMS.debug("TPSProcessor.checkForAppletUpdateEnabled: returning " + enabled);
         return enabled;
     }
 
@@ -1435,7 +1443,7 @@ public class TPSProcessor {
 
         String appletRequiredConfig = operation + "." + selectedTokenType + "."
                 + TPSEngine.CFG_APPLET_UPDATE_REQUIRED_VERSION;
-        CMS.debug("TPSProcessor.checkForAppletUpgrade: getting config: "+ appletRequiredConfig);
+        CMS.debug("TPSProcessor.checkForAppletUpgrade: getting config: " + appletRequiredConfig);
         try {
             requiredVersion = configStore.getString(appletRequiredConfig, null);
         } catch (EBaseException e) {
@@ -1459,7 +1467,7 @@ public class TPSProcessor {
 
         IConfigStore configStore = CMS.getConfigStore();
 
-        String unknownConfig = "op."+ operation + "." + TPSEngine.CFG_ALLOW_UNKNOWN_TOKEN;
+        String unknownConfig = "op." + operation + "." + TPSEngine.CFG_ALLOW_UNKNOWN_TOKEN;
 
         try {
             allow = configStore.getBoolean(unknownConfig, true);
@@ -2115,6 +2123,24 @@ public class TPSProcessor {
 
     }
 
+    protected String formatCurrentAppletVersion(AppletInfo aInfo) throws TPSException, IOException {
+
+        if (aInfo == null) {
+            throw new TPSException("TPSProcessor.formatCurrentAppletVersion: ", TPSStatus.STATUS_ERROR_CONTACT_ADMIN);
+        }
+
+        TPSBuffer build_id = getAppletVersion();
+        String build_idStr = build_id.toHexStringPlain();
+
+        String finalVersion = aInfo.getAppMajorVersion() + "." + aInfo.getAppMinorVersion() + "." + build_idStr;
+
+        finalVersion = finalVersion.toLowerCase();
+        CMS.debug("TPSProcessor.formatCurrentAppletVersion: returing: " + finalVersion);
+
+        return finalVersion;
+
+    }
+
     public static void main(String[] args) {
     }
 
-- 
1.8.3.1

