From 9f28cce9d36dde56ec6e75a47387bbfe4f3dacf4 Mon Sep 17 00:00:00 2001
From: Jack Magne <jmagne@dhcp-16-213.sjc.redhat.com>
Date: Wed, 2 Apr 2014 19:10:51 -0700
Subject: [PATCH] Further progress Format operation.

1. Read applet into memory to prepare to write to token.
2. With tpsclient create secure channel by implementing Initialize Update and ExternalAuthenticate messages.
3. Support for MAC and encryption for messages going on after secure channel has been created.
4. Implemented method to remove an aid file or instance from the token.
5. Added some symkey methods to allow TPS to manipulate session keys.

Have not tried this with real token as of yet. The tpsclient does verify of the MAC coming from the server and decrypts encrypted messages. Decrypted messages have to be correct for the MAC verification to work.
Next step will be to add the phone home servlet to the TPS and give it a try with a real token and esc.
---
 .../src/org/dogtagpki/tps/TPSConnection.java       |  25 +-
 base/common/src/org/dogtagpki/tps/apdu/APDU.java   |  58 ++-
 .../src/org/dogtagpki/tps/apdu/APDUResponse.java   |  16 +-
 .../src/org/dogtagpki/tps/apdu/DeleteFile.java     |  11 +-
 .../dogtagpki/tps/apdu/ExternalAuthenticate.java   |  65 ++-
 .../org/dogtagpki/tps/apdu/InitializeUpdate.java   |  17 +-
 .../src/org/dogtagpki/tps/main/TPSBuffer.java      |  17 +-
 base/common/src/org/dogtagpki/tps/main/Util.java   | 155 ++++++-
 base/symkey/src/com/netscape/symkey/SessionKey.cpp | 189 +++++++++
 .../symkey/src/com/netscape/symkey/SessionKey.java | 122 +++---
 base/symkey/src/com/netscape/symkey/SymKey.cpp     | 101 ++++-
 base/symkey/src/com/netscape/symkey/SymKey.h       |   1 +
 .../server/tps/channel/SecureChannel.java          | 172 +++++++-
 .../tps/cms/TKSComputeRandomDataResponse.java      |   3 +-
 .../server/tps/cms/TKSRemoteRequestHandler.java    |  23 +-
 .../org/dogtagpki/server/tps/engine/TPSEngine.java |  53 ++-
 .../server/tps/processor/TPSProcessor.java         | 463 ++++++++++++++++++++-
 17 files changed, 1376 insertions(+), 115 deletions(-)

diff --git a/base/common/src/org/dogtagpki/tps/TPSConnection.java b/base/common/src/org/dogtagpki/tps/TPSConnection.java
index 442d28d..64f8cb9 100644
--- a/base/common/src/org/dogtagpki/tps/TPSConnection.java
+++ b/base/common/src/org/dogtagpki/tps/TPSConnection.java
@@ -53,12 +53,14 @@ public class TPSConnection {
 
         // read the first parameter
         while ((b = in.read()) >= 0) {
-            char c = (char)b;
-            if (c == '&') break;
+            char c = (char) b;
+            if (c == '&')
+                break;
             sb.append(c);
         }
 
-        if (b < 0) throw new IOException("Unexpected end of stream");
+        if (b < 0)
+            throw new IOException("Unexpected end of stream");
 
         // parse message size
         String nvp = sb.toString();
@@ -68,19 +70,20 @@ public class TPSConnection {
         sb.append('&');
 
         // read the rest of message
-        for (int i=0; i<size; i++) {
+        for (int i = 0; i < size; i++) {
 
             b = in.read();
-            if (b < 0) throw new IOException("Unexpected end of stream");
+            if (b < 0)
+                throw new IOException("Unexpected end of stream");
 
-            char c = (char)b;
+            char c = (char) b;
             sb.append(c);
         }
 
         CMS.debug("TPSMessage.read: Reading:  " + sb.toString());
 
         // parse the entire message
-        return  TPSMessage.createMessage(sb.toString());
+        return TPSMessage.createMessage(sb.toString());
     }
 
     public void write(TPSMessage message) throws IOException {
@@ -88,7 +91,6 @@ public class TPSConnection {
 
         CMS.debug("TPSMessage.write: Writing: " + s);
 
-
         if (chunked) {
             // send message length + EOL
             out.print(Integer.toHexString(s.length()));
@@ -98,11 +100,18 @@ public class TPSConnection {
         // send message
         out.print(s);
 
+        /*
+         *
+         * Right now, tpsclient is counting the final crlf as part of the message and ruining the MAC calculations
+         * For now do this and figure out later how to handle this for both tpsclient and esc.
+         *
         if (chunked) {
             // send EOL
             out.print("\r\n");
         }
 
+        */
+
         out.flush();
     }
 }
diff --git a/base/common/src/org/dogtagpki/tps/apdu/APDU.java b/base/common/src/org/dogtagpki/tps/apdu/APDU.java
index c4f2c17..f01f5d5 100644
--- a/base/common/src/org/dogtagpki/tps/apdu/APDU.java
+++ b/base/common/src/org/dogtagpki/tps/apdu/APDU.java
@@ -19,6 +19,9 @@ package org.dogtagpki.tps.apdu;
 
 import org.dogtagpki.tps.main.TPSBuffer;
 import org.dogtagpki.tps.main.Util;
+import org.mozilla.jss.pkcs11.PK11SymKey;
+
+import com.netscape.certsrv.base.EBaseException;
 
 public abstract class APDU {
 
@@ -140,8 +143,59 @@ public abstract class APDU {
         return encoding;
     }
 
-    public void getDataToMAC(TPSBuffer data) {
-        //ToDO
+    public TPSBuffer getDataToMAC() {
+        TPSBuffer mac = new TPSBuffer();
+
+        mac.add(cla);
+        mac.add(ins);
+        mac.add(p1);
+        mac.add(p2);
+        mac.add((byte) (data.size() + 8));
+        mac.add(data);
+
+        return mac;
+    }
+
+    public void encryptData(PK11SymKey encKey) throws EBaseException {
+
+        if (encKey == null) {
+            throw new EBaseException("APDU.secureData: No input encrytion session key!");
+        }
+
+        int padNeeded = 0;
+
+        TPSBuffer dataToEnc = null;
+        TPSBuffer padding = null;
+        TPSBuffer dataEncrypted = null;
+
+        dataToEnc = new TPSBuffer();
+        dataToEnc.add((byte) data.size());
+        dataToEnc.add(data);
+
+        int dataSize = dataToEnc.size();
+        int rem = dataSize % 8;
+
+        if (rem == 0) {
+            padNeeded = 0;
+        } else if (dataSize < 8) {
+            padNeeded = 8 - dataSize;
+        } else {
+            padNeeded = 8 - rem;
+        }
+
+        if (padNeeded > 0) {
+            dataToEnc.add((byte) 0x80);
+            padNeeded--;
+
+            if (padNeeded > 0) {
+                padding = new TPSBuffer(padNeeded);
+                dataToEnc.add(padding);
+            }
+        }
+
+        dataEncrypted = Util.encryptData(dataToEnc, encKey);
+
+        data.set(dataEncrypted);
     }
 
     public Type getType() {
diff --git a/base/common/src/org/dogtagpki/tps/apdu/APDUResponse.java b/base/common/src/org/dogtagpki/tps/apdu/APDUResponse.java
index ef25cd2..9376a1f 100644
--- a/base/common/src/org/dogtagpki/tps/apdu/APDUResponse.java
+++ b/base/common/src/org/dogtagpki/tps/apdu/APDUResponse.java
@@ -88,7 +88,7 @@ public class APDUResponse extends APDU {
     }
 
     //Get the two byte apdu return code
-    byte[] getResultBytes() {
+    public byte[] getResultCodeBytes() {
         byte[] result = new byte[2];
 
         result[0] = getSW1();
@@ -96,6 +96,20 @@ public class APDUResponse extends APDU {
         return result;
     }
 
+    public TPSBuffer getResultDataNoCode() {
+
+        //Result code will be 2 bytes at the end.
+        TPSBuffer theData = getData();
+
+        TPSBuffer result = null;
+        int len = theData.size();
+        if (len > 2) {
+            result = theData.substr(0, len - 2);
+        }
+
+        return result;
+    }
+
     public static void main(String args[]) {
 
         APDUResponse resp = new APDUResponse();
diff --git a/base/common/src/org/dogtagpki/tps/apdu/DeleteFile.java b/base/common/src/org/dogtagpki/tps/apdu/DeleteFile.java
index 475207d..194799e 100644
--- a/base/common/src/org/dogtagpki/tps/apdu/DeleteFile.java
+++ b/base/common/src/org/dogtagpki/tps/apdu/DeleteFile.java
@@ -21,12 +21,11 @@ import org.dogtagpki.tps.main.TPSBuffer;
 
 public class DeleteFile extends APDU {
 
-    public DeleteFile( TPSBuffer aid) {
+    public DeleteFile(TPSBuffer aid) {
         setCLA((byte) 0x84);
-        setINS((byte)0xE4);
-        setP1((byte)0x00);
-        setP2((byte)0x00);
-
+        setINS((byte) 0xE4);
+        setP1((byte) 0x00);
+        setP2((byte) 0x00);
 
         TPSBuffer AIDTLV = new TPSBuffer();
 
@@ -43,7 +42,7 @@ public class DeleteFile extends APDU {
     public APDU.Type getType() {
         return APDU.Type.APDU_DELETE_FILE;
 
-     }
+    }
 
     public static void main(String[] args) {
         // TODO Auto-generated method stub
diff --git a/base/common/src/org/dogtagpki/tps/apdu/ExternalAuthenticate.java b/base/common/src/org/dogtagpki/tps/apdu/ExternalAuthenticate.java
index d1337b8..798c730 100644
--- a/base/common/src/org/dogtagpki/tps/apdu/ExternalAuthenticate.java
+++ b/base/common/src/org/dogtagpki/tps/apdu/ExternalAuthenticate.java
@@ -21,14 +21,21 @@ import org.dogtagpki.tps.main.TPSBuffer;
 
 public class ExternalAuthenticate extends APDU {
 
-    public ExternalAuthenticate(TPSBuffer theData, byte securityLevel) {
+    public enum SecurityLevel {
+        SECURE_MSG_ANY,
+        SECURE_MSG_MAC,
+        SECURE_MSG_NONE, // not yet supported
+        SECURE_MSG_MAC_ENC,
 
+    }
+
+    public ExternalAuthenticate(TPSBuffer theData, SecurityLevel securityLevel) {
         setCLA((byte) 0x84);
         setINS((byte) 0x82);
 
-        setP1(securityLevel);
+        setP1(securityLevelToByte(securityLevel));
+        setP2((byte) 0x0);
 
-        setP2((byte) 0x00);
         setData(theData);
     }
 
@@ -43,6 +50,58 @@ public class ExternalAuthenticate extends APDU {
         return APDU.Type.APDU_EXTERNAL_AUTHENTICATE;
     }
 
+    public static byte securityLevelToByte(SecurityLevel level) {
+        byte result = 0;
+
+        switch (level) {
+        case SECURE_MSG_ANY:
+            result = 0;
+            break;
+        case SECURE_MSG_MAC:
+            result = 1;
+            break;
+        case SECURE_MSG_NONE:
+            result = 2;
+            break;
+        case SECURE_MSG_MAC_ENC:
+            result = 3;
+            break;
+
+        default:
+            result = 0;
+            break;
+
+        }
+
+        return result;
+    }
+
+    public static SecurityLevel byteToSecurityLevel(byte level) {
+
+        SecurityLevel result = SecurityLevel.SECURE_MSG_ANY;
+
+        switch (level) {
+
+        case 0:
+            result = SecurityLevel.SECURE_MSG_ANY;
+            break;
+        case 1:
+            result = SecurityLevel.SECURE_MSG_MAC;
+            break;
+        case 2:
+            result = SecurityLevel.SECURE_MSG_NONE;
+            break;
+        case 3:
+            result = SecurityLevel.SECURE_MSG_MAC_ENC;
+            break;
+        default:
+            result = SecurityLevel.SECURE_MSG_ANY;
+            break;
+        }
+
+        return result;
+    }
+
     public static void main(String[] args) {
         // TODO Auto-generated method stub
 
diff --git a/base/common/src/org/dogtagpki/tps/apdu/InitializeUpdate.java b/base/common/src/org/dogtagpki/tps/apdu/InitializeUpdate.java
index 4016b96..e6e8fba 100644
--- a/base/common/src/org/dogtagpki/tps/apdu/InitializeUpdate.java
+++ b/base/common/src/org/dogtagpki/tps/apdu/InitializeUpdate.java
@@ -29,6 +29,7 @@ public class InitializeUpdate extends APDU {
      * Constructs Initialize Update APDU.
      */
     public InitializeUpdate(byte key_version, byte key_index, TPSBuffer theData) {
+        setCLA((byte) 0x80);
         setINS((byte) 0x50);
         setP1(key_version);
         setP2(key_index);
@@ -47,16 +48,16 @@ public class InitializeUpdate extends APDU {
 
     public TPSBuffer getEncoding()
     {
-        TPSBuffer data = new TPSBuffer();
+        TPSBuffer theData = new TPSBuffer();
 
-        data.add(cla);
-        data.add(ins);
-        data.add(p1);
-        data.add(p2);
-        data.add((byte) data.size());
-        data.add(data);
+        theData.add(cla);
+        theData.add(ins);
+        theData.add(p1);
+        theData.add(p2);
+        theData.add((byte) data.size());
+        theData.add(data);
 
-        return data;
+        return theData;
     } /* Encode */
 
 }
diff --git a/base/common/src/org/dogtagpki/tps/main/TPSBuffer.java b/base/common/src/org/dogtagpki/tps/main/TPSBuffer.java
index 1df8716..03ec460 100644
--- a/base/common/src/org/dogtagpki/tps/main/TPSBuffer.java
+++ b/base/common/src/org/dogtagpki/tps/main/TPSBuffer.java
@@ -95,13 +95,20 @@ public class TPSBuffer {
     }
 
     public byte at(int i) {
-        if (i < 0 || i > size()) {
+        if (i < 0 || i >= size()) {
             return 0x0;
         }
 
         return buf[i];
     }
 
+    public void setAt(int i, byte value) {
+        if (i < 0 || i >= size())
+            return;
+
+        buf[i] = value;
+    }
+
     /**
      * Returns true if the two buffers are the same length and contain
      * the same byte at each offset.
@@ -126,6 +133,13 @@ public class TPSBuffer {
         addBytes(addBytes);
     }
 
+    public void set(TPSBuffer newContents) {
+        if (newContents == null)
+            return;
+
+        buf = newContents.toBytesArray();
+    }
+
     /**
      * Append operators.
      */
@@ -233,6 +247,7 @@ public class TPSBuffer {
 
             result.append(HEX_DIGITS.charAt((c & 0xF0) >> 4));
             result.append(HEX_DIGITS.charAt(c & 0x0F));
+            result.append("%");
 
         }
 
diff --git a/base/common/src/org/dogtagpki/tps/main/Util.java b/base/common/src/org/dogtagpki/tps/main/Util.java
index aba6c6e..8fa2488 100644
--- a/base/common/src/org/dogtagpki/tps/main/Util.java
+++ b/base/common/src/org/dogtagpki/tps/main/Util.java
@@ -23,23 +23,30 @@ package org.dogtagpki.tps.main;
 import java.io.UnsupportedEncodingException;
 import java.net.URLDecoder;
 import java.net.URLEncoder;
+import java.security.spec.AlgorithmParameterSpec;
 
-import com.netscape.cmsutil.util.Utils;
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.crypto.Cipher;
+import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.crypto.EncryptionAlgorithm;
+import org.mozilla.jss.crypto.IVParameterSpec;
+import org.mozilla.jss.pkcs11.PK11SymKey;
 
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.cmsutil.util.Utils;
 
 public class Util {
 
     public Util() {
     }
 
-    public static byte[]  str2ByteArray (String s)  {
+    public static byte[] str2ByteArray(String s) {
         int len = s.length() / 2;
 
+        byte[] ret = new byte[len];
 
-        byte[]  ret = new byte[len];
-
-        for (int i = 0; i < len; i ++) {
-               ret[i] =  (byte) ((byte) Util.hexToBin(s.charAt(i*2)) * 16 +  Util.hexToBin(s.charAt(i*2+1)));
+        for (int i = 0; i < len; i++) {
+            ret[i] = (byte) ((byte) Util.hexToBin(s.charAt(i * 2)) * 16 + Util.hexToBin(s.charAt(i * 2 + 1)));
         }
 
         return ret;
@@ -127,13 +134,147 @@ public class Util {
         return result.toString();
     }
 
+    public static String specialURLEncode(byte data[]) {
+        StringBuffer sb = new StringBuffer();
+        for (int i = 0; i < data.length; i++) {
+            sb.append("#");
+            if ((data[i] & 0xff) < 16) {
+                sb.append("0");
+            }
+            sb.append(Integer.toHexString((data[i] & 0xff)));
+        }
+
+        return sb.toString().toUpperCase();
+    }
+
     public static String specialEncode(TPSBuffer data) {
         return Utils.SpecialEncode(data.toBytesArray());
     }
 
+    public static TPSBuffer computeMAC(PK11SymKey symKey, TPSBuffer input, TPSBuffer icv) throws EBaseException {
+        TPSBuffer output = null;
+        TPSBuffer result = null;
+
+        int inputLen = input.size();
+
+        if (symKey == null || input == null || icv == null || icv.size() != 8) {
+            throw new EBaseException("Util.computeMAC: invalid input data!");
+        }
+
+        TPSBuffer macPad = new TPSBuffer(8);
+        macPad.setAt(0, (byte) 0x80);
+
+        CryptoToken token = null;
+
+        try {
+
+            token = CryptoManager.getInstance().getInternalKeyStorageToken();
+
+            Cipher cipher = token.getCipherContext(EncryptionAlgorithm.DES3_ECB);
+            result = new TPSBuffer(icv);
+
+            /* Process whole blocks */
+            int inputOffset = 0;
+            while (inputLen >= 8)
+            {
+                for (int i = 0; i < 8; i++)
+                {
+                    //Xor implicitly converts bytes to ints, we convert answer back to byte.
+                    byte a = (byte) (result.at(i) ^ input.at(inputOffset + i));
+                    result.setAt(i, a);
+                }
+                cipher.initEncrypt(symKey);
+                byte[] ciphResult = cipher.doFinal(result.toBytesArray());
+
+                if (ciphResult.length != result.size()) {
+                    throw new EBaseException("Invalid cipher in Util.computeMAC");
+                }
+
+                result = new TPSBuffer(ciphResult);
+
+                inputLen -= 8;
+                inputOffset += 8;
+            }
+
+            /*
+             * Fold in remaining data (if any)
+             * Set i to number of bytes processed
+             */
+            int i = 0;
+            for (i = 0; i < inputLen; i++)
+            {
+                byte a = (byte) (result.at(i) ^ input.at(i + inputOffset));
+                result.setAt(i, a);
+            }
+
+            /*
+             * Fill remainder of last block. There
+             * will be at least one byte handled here.
+             */
+
+            //Start at the beginning of macPad
+            // Keep going with i in result where we left off.
+            int padOffset = 0;
+            while (i < 8)
+            {
+                byte a = (byte) (result.at(i) ^ macPad.at(padOffset++));
+                result.setAt(i, a);
+                i++;
+            }
+
+            cipher.initEncrypt(symKey);
+            byte[] ciphResultFinal = cipher.doFinal(result.toBytesArray());
+
+            if (ciphResultFinal.length != result.size()) {
+                throw new EBaseException("Invalid cipher in Util.computeMAC");
+            }
+
+            output = new TPSBuffer(ciphResultFinal);
+
+        } catch (Exception e) {
+            throw new EBaseException("Util.computeMAC: Cryptographic problem encountered! " + e.toString());
+        }
+
+        return output;
+    }
+
     public static TPSBuffer specialDecode(String str) {
-        byte[] data = Utils.SpecialDecode(str);
+        byte[] data = uriDecodeFromHex(str);
         TPSBuffer tbuf = new TPSBuffer(data);
         return tbuf;
     }
+
+    public static TPSBuffer encryptData(TPSBuffer dataToEnc, PK11SymKey encKey) throws EBaseException {
+
+        TPSBuffer encrypted = null;
+        if (encKey == null || dataToEnc == null) {
+            throw new EBaseException("Util.encryptData: called with no sym key or no data!");
+        }
+
+        CryptoToken token = null;
+        try {
+
+            token = CryptoManager.getInstance().getInternalKeyStorageToken();
+            Cipher cipher = token.getCipherContext(EncryptionAlgorithm.DES3_CBC);
+
+            AlgorithmParameterSpec algSpec = null;
+
+            int len = EncryptionAlgorithm.DES3_CBC.getIVLength();
+            byte[] iv = new byte[len]; // Assume iv set to 0's as in current TPS
+
+            algSpec = new IVParameterSpec(iv);
+            cipher.initEncrypt(encKey, algSpec);
+
+            byte[] encryptedBytes = cipher.doFinal(dataToEnc.toBytesArray());
+
+            encrypted = new TPSBuffer(encryptedBytes);
+
+        } catch (Exception e) {
+            throw new EBaseException("Util.encryptData: problem encrypting data: " + e.toString());
+        }
+
+        return encrypted;
+
+    }
+
 }
diff --git a/base/symkey/src/com/netscape/symkey/SessionKey.cpp b/base/symkey/src/com/netscape/symkey/SessionKey.cpp
index 0878e26..a200487 100644
--- a/base/symkey/src/com/netscape/symkey/SessionKey.cpp
+++ b/base/symkey/src/com/netscape/symkey/SessionKey.cpp
@@ -1843,6 +1843,195 @@ finish:
     return handleBA;
 }
 
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/*
+ * Class:     com_netscape_cms_servlet_tks_UnwrapSessionKeyWithSharedSecret
+ * Method:    UnwrapSessionKeyWithSharedSecret 
+ * Signature: ([B[B[B[B)[B
+ */
+    JNIEXPORT jobject JNICALL
+        Java_com_netscape_symkey_SessionKey_
+        (JNIEnv*, jclass, jstring, jobject,jbyteArray);
+#ifdef __cplusplus
+}
+#endif
+extern "C" JNIEXPORT jobject JNICALL
+Java_com_netscape_symkey_SessionKey_UnwrapSessionKeyWithSharedSecret
+(JNIEnv* env, jclass this2, jstring tokenName, jobject sharedSecretKey,jbyteArray sessionKeyBA)
+{
+    jobject keyObj = NULL;
+    PK11SymKey *sessionKey = NULL;
+    PK11SymKey *sharedSecret = NULL;
+    PK11SymKey *finalKey = NULL;
+    PK11SlotInfo *slot = NULL;
+    char *tokenNameChars = NULL;
+    PRStatus  r = PR_FAILURE;
+    int sessionKeyLen = 0;
+    jbyte *sessionKeyBytes = NULL;
+    SECItem *SecParam = PK11_ParamFromIV(CKM_DES3_ECB, NULL);
+    SECItem wrappedItem = {siBuffer , NULL, 0 };
+
+    PR_fprintf(PR_STDOUT,"In SessionKey.UnwrapSessionKeyWithSharedSecret!\n");
+
+    if(tokenName == NULL || sharedSecretKey == NULL || sessionKeyBA == NULL) {
+        goto loser;
+    }
+
+    if (tokenName)
+    {
+        tokenNameChars = (char *)(env)->GetStringUTFChars(tokenName, NULL);
+        if ( tokenNameChars && !strcmp(tokenNameChars, "internal")) {
+            slot = PK11_GetInternalSlot();
+        } else {
+            slot = ReturnSlot(tokenNameChars);
+        }
+
+        PR_fprintf(PR_STDOUT,"SessionKey.UnwrapSessionKeyWithSharedSecret  slot %p  name %s tokenName %s  \n",slot, PK11_GetSlotName(slot), PK11_GetTokenName(slot));
+        (env)->ReleaseStringUTFChars(tokenName, (const char *)tokenNameChars);
+    }
+
+    if(slot == NULL) {
+        goto loser;
+    }
+
+    sessionKeyBytes = (jbyte *)(env)->GetByteArrayElements(sessionKeyBA, NULL);
+    sessionKeyLen = (env)->GetArrayLength(sessionKeyBA); 
+
+    if(sessionKeyBytes == NULL) {
+        goto loser;
+    }
+
+    r = JSS_PK11_getSymKeyPtr(env, sharedSecretKey, &sharedSecret);
+
+    if (r != PR_SUCCESS) {
+        PR_fprintf(PR_STDOUT,"SessionKey: UnwrapSessionKeyWithSharedSecret Unable to get input shared secret sym key! \n"); 
+        goto loser;
+    }
+
+    wrappedItem.data = (unsigned char *) sessionKeyBytes;
+    wrappedItem.len =  sessionKeyLen;
+
+    sessionKey = PK11_UnwrapSymKey(sharedSecret,
+                          CKM_DES3_ECB,SecParam, &wrappedItem,
+                          CKM_DES3_ECB,
+                          CKA_UNWRAP,
+                          16);
+
+    PR_fprintf(PR_STDOUT,"SessionKey: UnwrapSessionKeyWithSharedSecret symKey: %p \n",sessionKey);
+
+    if(sessionKey == NULL) {
+         PR_fprintf(PR_STDOUT,"SessionKey:UnwrapSessionKeyWithSharedSecret  Error unwrapping a session key! \n");
+         goto loser;
+    }
+
+    // Done to be compat with current system. Current TPS does this.
+    finalKey = CreateDesKey24Bit(slot, sessionKey);
+
+    if(finalKey == NULL) {
+          PR_fprintf(PR_STDOUT,"SessionKey:UnwrapSessionKeyWithSharedSecret Error final unwrapped key! \n");
+          goto loser;
+
+    }
+
+     /* wrap the sesssion in java object. */
+    keyObj = JSS_PK11_wrapSymKey(env, &finalKey, NULL);
+
+loser:
+
+    if ( slot != NULL ) {
+       PK11_FreeSlot( slot);
+       slot = NULL;
+    }
+
+    if ( sessionKeyBA != NULL) {
+        (env)->ReleaseByteArrayElements( sessionKeyBA, sessionKeyBytes, 0);
+    }
+
+    if(sessionKey) {
+        PK11_FreeSymKey(sessionKey);
+        sessionKey = NULL; 
+    }
+
+    // Don't free finalKey ptr because wrapping routine takes that out of our hands.
+
+    return keyObj;
+}
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/*
+ * Class:     com_netscape_cms_servlet_tks_GetSymKeyByName
+ * Method:    GetSymKeyByName
+ * Signature: ([B[B[B[B)[B
+ */
+    JNIEXPORT jobject JNICALL
+        Java_com_netscape_symkey_SessionKey_GetSymKeyByName
+        (JNIEnv*, jclass, jstring, jstring);
+#ifdef __cplusplus
+}
+#endif
+extern "C" JNIEXPORT jobject JNICALL
+Java_com_netscape_symkey_SessionKey_GetSymKeyByName
+(JNIEnv* env, jclass this2, jstring tokenName, jstring keyName)
+{
+
+    jobject keyObj = NULL;
+    PK11SymKey *key = NULL;
+    char *tokenNameChars = NULL;
+    char *keyNameChars = NULL;
+    PK11SlotInfo *slot = NULL;
+    CK_OBJECT_HANDLE keyhandle = 0;
+
+    PR_fprintf(PR_STDOUT,"In SessionKey GetSymKeyByName!\n");
+
+    if (keyName) {
+        keyNameChars = (char *)(env)->GetStringUTFChars(keyName,NULL);
+    }
+
+    if (tokenName)
+    {
+        tokenNameChars = (char *)(env)->GetStringUTFChars(tokenName, NULL);
+        if ( tokenNameChars && !strcmp(tokenNameChars, "internal")) {
+            slot = PK11_GetInternalSlot();
+        } else {
+            slot = ReturnSlot(tokenNameChars);
+        }
+
+        PR_fprintf(PR_STDOUT,"SessionKey: GetSymKeyByName slot %p  name %s tokenName %s keyName %s \n",slot, PK11_GetSlotName(slot), PK11_GetTokenName(slot),keyNameChars);
+        (env)->ReleaseStringUTFChars(tokenName, (const char *)tokenNameChars);
+    }
+
+    if(slot == NULL)
+        goto finish;
+
+    key = ReturnSymKey( slot, keyNameChars);
+
+    PR_fprintf(PR_STDOUT,"SessionKey: GetSymKeyByName returned key %p \n",key);
+    if (key == NULL) {
+        goto finish;
+    }
+
+    /* wrap the symkey in java object. */
+    keyObj = JSS_PK11_wrapSymKey(env, &key, NULL);
+
+finish:
+
+    if (keyName) {
+        (env)->ReleaseStringUTFChars(keyName, (const char *)keyNameChars);
+    }
+
+    if(slot) {
+        PK11_FreeSlot(slot);
+        slot = NULL;
+    }
+
+    return keyObj;
+}
 
 #ifdef __cplusplus
 extern "C"
diff --git a/base/symkey/src/com/netscape/symkey/SessionKey.java b/base/symkey/src/com/netscape/symkey/SessionKey.java
index 47f9385..56782aa 100644
--- a/base/symkey/src/com/netscape/symkey/SessionKey.java
+++ b/base/symkey/src/com/netscape/symkey/SessionKey.java
@@ -75,47 +75,47 @@ public class SessionKey {
     public static native byte[] ComputeKeyCheck(PK11SymKey desKey); /* byte data[] ); */
 
     public static native byte[] ComputeSessionKey(String tokenName,
-                                                   String keyName,
-                                                   byte[] card_challenge,
-                                                   byte[] host_challenge,
-                                                   byte[] keyInfo,
-                                                   byte[] CUID,
-                                                   byte[] macKeyArray,
-                                                   String useSoftToken,
-                                                   String keySet,
-                                                   String sharedSecretKeyName);
+            String keyName,
+            byte[] card_challenge,
+            byte[] host_challenge,
+            byte[] keyInfo,
+            byte[] CUID,
+            byte[] macKeyArray,
+            String useSoftToken,
+            String keySet,
+            String sharedSecretKeyName);
 
     public static native byte[] ComputeEncSessionKey(String tokenName,
-                                                      String keyName,
-                                                      byte[] card_challenge,
-                                                      byte[] host_challenge,
-                                                      byte[] keyInfo,
-                                                      byte[] CUID,
-                                                      byte[] encKeyArray,
-                                                      String useSoftToken,
-                                                      String keySet);
+            String keyName,
+            byte[] card_challenge,
+            byte[] host_challenge,
+            byte[] keyInfo,
+            byte[] CUID,
+            byte[] encKeyArray,
+            String useSoftToken,
+            String keySet);
 
     public static native PK11SymKey ComputeKekSessionKey(String tokenName,
-                                                          String keyName,
-                                                          byte[] card_challenge,
-                                                          byte[] host_challenge,
-                                                          byte[] keyInfo,
-                                                          byte[] CUID,
-                                                          byte[] kekKeyArray,
-                                                          String useSoftToken,
-                                                          String keySet);
+            String keyName,
+            byte[] card_challenge,
+            byte[] host_challenge,
+            byte[] keyInfo,
+            byte[] CUID,
+            byte[] kekKeyArray,
+            String useSoftToken,
+            String keySet);
 
     public static native PK11SymKey ComputeKekKey(String tokenName,
-                                                   String keyName,
-                                                   byte[] card_challenge,
-                                                   byte[] host_challenge,
-                                                   byte[] keyInfo,
-                                                   byte[] CUID,
-                                                   byte[] kekKeyArray,
-                                                   String useSoftToken, String keySet);
+            String keyName,
+            byte[] card_challenge,
+            byte[] host_challenge,
+            byte[] keyInfo,
+            byte[] CUID,
+            byte[] kekKeyArray,
+            String useSoftToken, String keySet);
 
     public static native byte[] ECBencrypt(PK11SymKey key,
-                                            PK11SymKey desKey); //byte[] data );
+            PK11SymKey desKey); //byte[] data );
 
     public static native PK11SymKey GenerateSymkey(String tokenName);
 
@@ -126,42 +126,52 @@ public class SessionKey {
     // public static native PK11SymKey bytes2PK11SymKey( byte[] symKeyBytes );
 
     public static native byte[] ComputeCryptogram(String tokenName,
-                                                   String keyName,
-                                                   byte[] card_challenge,
-                                                   byte[] host_challenge,
-                                                   byte[] keyInfo,
-                                                   byte[] CUID,
-                                                   int type,
-                                                   byte[] authKeyArray,
-                                                   String useSoftToken, String keySet);
+            String keyName,
+            byte[] card_challenge,
+            byte[] host_challenge,
+            byte[] keyInfo,
+            byte[] CUID,
+            int type,
+            byte[] authKeyArray,
+            String useSoftToken, String keySet);
 
     public static native byte[] EncryptData(String tokenName,
-                                             String keyName,
-                                             byte[] in,
-                                             byte[] keyInfo,
-                                             byte[] CUID,
-                                             byte[] kekKeyArray,
-                                             String useSoftToken, String keySet);
+            String keyName,
+            byte[] in,
+            byte[] keyInfo,
+            byte[] CUID,
+            byte[] kekKeyArray,
+            String useSoftToken, String keySet);
 
     public static native byte[] DiversifyKey(String tokenName,
-                                              String newTokenName,
-                                              String oldMasterKeyName,
-                                              String newMasterKeyName,
-                                              String keyInfo,
-                                              byte[] CUIDValue,
-                                              byte[] kekKeyArray,
-                                              String useSoftToken, String keySet);
+            String newTokenName,
+            String oldMasterKeyName,
+            String newMasterKeyName,
+            String keyInfo,
+            byte[] CUIDValue,
+            byte[] kekKeyArray,
+            String useSoftToken, String keySet);
 
     // internal calls from config TKS keys tab
     public static native String GenMasterKey(String token,
-                                              String keyName);
+            String keyName);
 
     public static native String DeleteSymmetricKey(String token,
-                                                    String keyName);
+            String keyName);
 
     public static native String ListSymmetricKeys(String token);
 
     //  set when called from the config TKS tab to create master key
     //  get when called from the RA to create session key
     public static native void SetDefaultPrefix(String masterPrefix);
+
+    // Functions that the TPS may use during processing to manipulate sym keys in such a way not available in JSS
+
+    // Return a names Sym Key, in this case will be the shared secret in practice.
+    public static native PK11SymKey GetSymKeyByName(String tokenName, String keyName);
+
+    // TKS sends over the session key(s) wrapped with shared secret. TPS now does this unwrapping and creates the session keys
+    // with functionality only available now in NSS. This is all to preserve exact functional parity with the current TKS.
+    public static native PK11SymKey UnwrapSessionKeyWithSharedSecret(String tokenName, PK11SymKey sharedSecret,
+            byte[] sessionKeyArray);
 }
diff --git a/base/symkey/src/com/netscape/symkey/SymKey.cpp b/base/symkey/src/com/netscape/symkey/SymKey.cpp
index c300d1a..5f5e403 100644
--- a/base/symkey/src/com/netscape/symkey/SymKey.cpp
+++ b/base/symkey/src/com/netscape/symkey/SymKey.cpp
@@ -140,7 +140,7 @@ PK11SymKey * ReturnSymKey( PK11SlotInfo *slot, char *keyname)
 
     pwdata.source   = secuPWData::PW_NONE;
     pwdata.data     = (char *) NULL;
-    PR_fprintf(PR_STDOUT,"In ReturnSymKey name %s \n",keyname);
+    PR_fprintf(PR_STDOUT,"In ReturnSymKey name %s slot %p \n",keyname, slot);
     if (keyname == NULL)
     {
         goto cleanup;
@@ -153,17 +153,20 @@ PK11SymKey * ReturnSymKey( PK11SlotInfo *slot, char *keyname)
     firstSymKey = PK11_ListFixedKeysInSlot( slot , NULL, ( void *) &pwdata );
     /* scan through the symmetric key list for a key matching our nickname */
     sk = firstSymKey;
+    PR_fprintf(PR_STDOUT,"SymKey first sk %p: \n",sk);
     while( sk != NULL )
     {
         /* get the nickname of this symkey */
         name = PK11_GetSymKeyNickname( sk );
 
+        PR_fprintf(PR_STDOUT,"SymKey in list: name %s \n",name);
         /* if the name matches, make a 'copy' of it */
         if ( name != NULL && !strcmp( keyname, name ))
         {
             if (foundSymKey == NULL)
             {
                 foundSymKey = PK11_ReferenceSymKey(sk);
+                PR_fprintf(PR_STDOUT,"Found SymKey in list: name %s \n",name);
             }
             PORT_Free(name);
         }
@@ -186,6 +189,102 @@ PK11SymKey * ReturnSymKey( PK11SlotInfo *slot, char *keyname)
     return foundSymKey;
 }
 
+PK11SymKey *CreateDesKey24Bit(PK11SlotInfo *slot, PK11SymKey *origKey) {
+
+    PK11SymKey *newKey = NULL;
+
+    CK_OBJECT_HANDLE keyhandle = 0;
+    PK11SymKey *firstEight = NULL;
+    PK11SymKey *concatKey = NULL;
+    PK11SymKey *internalOrigKey = NULL;
+    CK_ULONG bitPosition = 0;
+    SECItem paramsItem = { siBuffer, NULL, 0 };
+
+    PK11SlotInfo *internal = PK11_GetInternalSlot();
+    if (  slot == NULL || origKey == NULL || internal == NULL )
+        goto loser;
+
+    PR_fprintf(PR_STDOUT,"In SessionKey CreateDesKey24Bit!\n");
+
+    if( internal != slot ) {  //Make sure we do this on the NSS Generic Crypto services because concatanation
+        PR_fprintf(PR_STDOUT,"CreateDesKey24Bit! Input key not on internal slot!\n");
+        internalOrigKey = PK11_MoveSymKey( internal, CKA_ENCRYPT, 0, PR_FALSE, origKey );
+        if(internalOrigKey == NULL) {
+            PR_fprintf(PR_STDOUT,"CreateDesKey24Bit! Can't move input key to internal!\n");
+            goto loser;
+        }
+    }
+
+     // Extract first eight bytes from generated key into another key.
+    bitPosition = 0;
+    paramsItem.data = (CK_BYTE *) &bitPosition;
+    paramsItem.len = sizeof bitPosition;
+
+
+    if ( internalOrigKey)
+        firstEight = PK11_Derive(internalOrigKey, CKM_EXTRACT_KEY_FROM_KEY, &paramsItem, CKA_ENCRYPT , CKA_DERIVE, EIGHT_BYTES);
+    else
+        firstEight = PK11_Derive(origKey, CKM_EXTRACT_KEY_FROM_KEY, &paramsItem, CKA_ENCRYPT , CKA_DERIVE, EIGHT_BYTES);
+
+    if (firstEight  == NULL ) {
+        PR_fprintf(PR_STDOUT,"CreateDesKey24Bit! Can't extract first 8 bits of input key!\n");
+        goto loser;
+    }
+
+     //Concatenate 8 byte key to the end of the original key, giving new 24 byte key
+    keyhandle = PK11_GetSymKeyHandle(firstEight);
+
+    paramsItem.data=(unsigned char *) &keyhandle;
+    paramsItem.len=sizeof(keyhandle);
+
+    if ( internalOrigKey ) {
+        concatKey = PK11_Derive ( internalOrigKey , CKM_CONCATENATE_BASE_AND_KEY , &paramsItem ,CKM_DES3_ECB , CKA_DERIVE , 0);
+    } else {
+        concatKey = PK11_Derive ( origKey , CKM_CONCATENATE_BASE_AND_KEY , &paramsItem ,CKM_DES3_ECB , CKA_DERIVE , 0);
+    }
+        
+    if ( concatKey == NULL ) {
+         PR_fprintf(PR_STDOUT,"CreateDesKey24Bit: error concatenating 8 bytes on end of key.");
+        goto loser;
+    }   
+        
+    //Make sure we move this to the proper token, in case it got moved by NSS
+    //during the derive phase.
+        
+    newKey =  PK11_MoveSymKey ( slot, CKA_ENCRYPT, 0, PR_FALSE, concatKey);
+    
+    if ( newKey == NULL ) {
+       PR_fprintf(PR_STDOUT,"CreateDesKey24Bit: error moving key to original slot.");
+    }   
+
+loser:
+
+
+    if ( concatKey != NULL ) {
+        PK11_FreeSymKey( concatKey );
+        concatKey = NULL;
+    }
+
+    if ( firstEight != NULL ) {
+        PK11_FreeSymKey ( firstEight );
+        firstEight = NULL;
+    }
+
+    if ( internalOrigKey != NULL ) {
+       PK11_FreeSymKey ( internalOrigKey );
+       internalOrigKey = NULL;
+    }
+
+    //Caller will free the slot input slot object
+
+    if ( internal != NULL ) {
+       PK11_FreeSlot( internal);
+       internal = NULL;
+    }
+
+    return newKey; 
+}
+
 
 extern "C" JNIEXPORT jstring
 JNICALL Java_com_netscape_symkey_SessionKey_DeleteKey(JNIEnv * env, jclass this2, jstring tokenName, jstring keyName)
diff --git a/base/symkey/src/com/netscape/symkey/SymKey.h b/base/symkey/src/com/netscape/symkey/SymKey.h
index 5a53d48..c801e43 100644
--- a/base/symkey/src/com/netscape/symkey/SymKey.h
+++ b/base/symkey/src/com/netscape/symkey/SymKey.h
@@ -47,6 +47,7 @@ PK11SlotInfo *ReturnSlot(char *tokenNameChars);
 PK11SymKey *ComputeCardKey(PK11SymKey *masterKey, unsigned char *data, PK11SlotInfo *slot);
 PK11SymKey *CreateUnWrappedSymKeyOnToken( PK11SlotInfo *slot, PK11SymKey * unWrappingKey, BYTE *keyToBeUnWrapped, int sizeOfKeyToBeUnWrapped, PRBool isPerm);
 PK11SymKey *ReturnDeveloperSymKey(PK11SlotInfo *slot, char *keyType, char *keySet, Buffer &inputKey);
+PK11SymKey *CreateDesKey24Bit(PK11SlotInfo *slot, PK11SymKey *origKey);
 
 char *GetSharedSecretKeyName(char *newKeyName);
 
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 6ebb93b..a1cdddf 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
@@ -17,22 +17,178 @@
 // --- END COPYRIGHT BLOCK ---
 package org.dogtagpki.server.tps.channel;
 
+import java.io.IOException;
+
+import org.dogtagpki.server.tps.processor.TPSProcessor;
+import org.dogtagpki.tps.apdu.APDU;
+import org.dogtagpki.tps.apdu.APDUResponse;
+import org.dogtagpki.tps.apdu.DeleteFile;
+import org.dogtagpki.tps.apdu.ExternalAuthenticate;
+import org.dogtagpki.tps.apdu.ExternalAuthenticate.SecurityLevel;
+import org.dogtagpki.tps.main.TPSBuffer;
+import org.dogtagpki.tps.main.TPSException;
+import org.dogtagpki.tps.main.Util;
+import org.dogtagpki.tps.msg.EndOp.TPSStatus;
+import org.mozilla.jss.pkcs11.PK11SymKey;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+
 public class SecureChannel {
 
-   public enum SecurityLevel {
-        SECURE_MSG_ANY ,
-        SECURE_MSG_MAC ,
-        SECURE_MSG_NONE , // not yet supported
-        SECURE_MSG_MAC_ENC
-    }
+    // Have not written all code to use all of these as of yet.
+
+    private TPSProcessor processor;
+    private PK11SymKey sessionKey;
+    private PK11SymKey encSessionKey;
+    private TPSBuffer drmDesKey;
+    private TPSBuffer kekDesKey;
+    private TPSBuffer keyCheck;
+    private TPSBuffer keyDiversificationData;
+    private TPSBuffer cardChallenge;
+    private TPSBuffer cardCryptogram;
+    private TPSBuffer hostChallenge;
+    private TPSBuffer hostCryptogram;
+    private TPSBuffer icv;
+    private SecurityLevel secLevel;
+
+    public SecureChannel(TPSProcessor processor, PK11SymKey sessionKey, PK11SymKey encSessionKey, TPSBuffer drmDesKey,
+            TPSBuffer kekDesKey, TPSBuffer keyCheck, TPSBuffer keyDiversificationData, TPSBuffer cardChallenge,
+            TPSBuffer cardCryptogram, TPSBuffer hostChallenge, TPSBuffer hostCryptogram) throws TPSException {
 
-    public SecureChannel() {
+        if (processor == null || sessionKey == null | encSessionKey == null || keyDiversificationData == null
+                || cardChallenge == null || cardCryptogram == null || hostChallenge == null || hostCryptogram == null) {
+            throw new TPSException("SecureChannel.SecureChannel: Invalid data in constructor!",
+                    TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+        }
+
+        this.processor = processor;
+        this.sessionKey = sessionKey;
+        this.encSessionKey = encSessionKey;
+        this.drmDesKey = drmDesKey;
+        this.kekDesKey = kekDesKey;
+        this.keyCheck = keyCheck;
+        this.keyDiversificationData = keyDiversificationData;
+        this.cardChallenge = cardChallenge;
+        this.cardCryptogram = cardCryptogram;
+        this.hostChallenge = hostChallenge;
+        this.hostCryptogram = hostCryptogram;
+        this.icv = new TPSBuffer(8);
+
+        this.secLevel = SecurityLevel.SECURE_MSG_MAC_ENC;
+        //ToDo: Write method that reads this from the config
 
     }
 
     public static void main(String[] args) {
-        // TODO Auto-generated method stub
+    }
+
+    public void externalAuthenticate() throws TPSException, IOException {
+
+        CMS.debug("SecureChannel.externalAuthenticate: entering.");
+
+        ExternalAuthenticate externalAuth = new ExternalAuthenticate(hostCryptogram,
+                secLevel);
+
+        computeAPDUMac(externalAuth);
+
+        APDUResponse response = processor.handleAPDURequest(externalAuth);
+
+        if (!response.checkResult()) {
+            throw new TPSException("SecureChannel.eternalAuthenticate. Failed to external authenticate to token.",
+                    TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+        }
+
+        CMS.debug("SecureChannel.externalAuthenticate: Successfully completed, exiting ...");
+
+    }
+
+    //This method computes the mac AND encryption if needed.
+    private void computeAPDU(APDU apdu) throws TPSException {
+
+        CMS.debug("SecureChannel.computeAPDU: entering..");
+
+        if (apdu == null) {
+            throw new TPSException("SecureChannel.computeAPDU: bad input apdu!",
+                    TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+        }
+
+        computeAPDUMac(apdu);
+
+        if (secLevel == SecurityLevel.SECURE_MSG_MAC_ENC) {
+            try {
+                // CMS.debug("SecureChannel.computeAPDU: Before encryption data value: " + apdu.getData().toHexString());
+                apdu.encryptData(encSessionKey);
+                // CMS.debug("SecureChannel.computeAPDU: After encryption data value: " + apdu.getData().toHexString());
+            } catch (EBaseException e) {
+                throw new TPSException("SecureChannel.computeAPDU: Can't encrypt outgoing data! " + e);
+            }
+
+            CMS.debug("SecureChannel.computeAPDU: Successfully encrypted apdu data.");
+        }
+    }
+
+    // This method computes MAC only.
+    private void computeAPDUMac(APDU apdu) throws TPSException {
+        TPSBuffer newMac = null;
+        TPSBuffer data = null;
+
+        if (apdu == null) {
+            throw new TPSException("SecureChannel.computeAPDUMac: bad input apdu!",
+                    TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+        }
+
+        data = apdu.getDataToMAC();
+
+        CMS.debug("SecureChannel.computeAPDUMac: data To MAC: " + data.toHexString());
+
+        try {
+            newMac = Util.computeMAC(sessionKey, data, icv);
+        } catch (EBaseException e) {
+            CMS.debug("SecureChannel.compuatAPDUMac: Can't compute mac. " + e);
+            throw new TPSException("SecureChannel.compuatAPDUMac: Can't compute mac.",
+                    TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+        }
+
+        CMS.debug("SecureChannel.computeAPDUMac: computed MAC: " + newMac.toHexString());
+
+        apdu.setMAC(newMac);
+
+        icv.set(newMac);
+    }
+
+    public void deleteFileX(TPSBuffer aid) throws TPSException, IOException {
+        CMS.debug("SecureChannel.deleteFileX: entering...");
+        if (aid == null) {
+            throw new TPSException("SecureChannel.deleteFileX: no input aid!");
+        }
+
+        DeleteFile deleteFile = new DeleteFile(aid);
+
+        computeAPDU(deleteFile);
+
+        processor.handleAPDURequest(deleteFile);
+
+    }
+
+    public TPSBuffer getKeyDiversificationData() {
+        return keyDiversificationData;
+    }
+
+    public TPSBuffer getCardChallenge() {
+        return cardChallenge;
+    }
+
+    public TPSBuffer getHostChallenge() {
+        return hostChallenge;
+    }
+
+    public TPSBuffer getHostCryptogram() {
+        return hostCryptogram;
+    }
 
+    public TPSBuffer getCardCryptogram() {
+        return cardCryptogram;
     }
 
 }
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/TKSComputeRandomDataResponse.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/TKSComputeRandomDataResponse.java
index e601238..58cc5d0 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/TKSComputeRandomDataResponse.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/TKSComputeRandomDataResponse.java
@@ -35,6 +35,7 @@ public class TKSComputeRandomDataResponse extends TKSResponse
     }
 
     public TPSBuffer getRandomData() {
-        return (TPSBuffer) nameValTable.get(IRemoteRequest.TKS_RESPONSE_RandomData);
+        byte [] random = (byte[]) nameValTable.get(IRemoteRequest.TKS_RESPONSE_RandomData);
+        return new TPSBuffer(random);
     }
 }
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 5aad056..5352cab 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
@@ -95,15 +95,22 @@ public class TKSRemoteRequestHandler extends RemoteRequestHandler
         CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): sending request to tks.");
         HttpConnector conn =
                 (HttpConnector) subsystem.getConnectionManager().getConnector(connid);
+
+        String requestString = IRemoteRequest.SERVER_SIDE_KEYGEN + "=" + serverKeygen +
+                "&" + IRemoteRequest.TOKEN_CUID + "=" + Util.specialURLEncode(cuid.toBytesArray()) +
+                "&" + IRemoteRequest.TOKEN_CARD_CHALLENGE + "=" + Util.specialURLEncode(card_challenge.toBytesArray()) +
+                "&" + IRemoteRequest.TOKEN_HOST_CHALLENGE + "=" + Util.specialURLEncode(host_challenge.toBytesArray()) +
+                "&" + IRemoteRequest.TOKEN_KEYINFO + "=" + Util.specialURLEncode(keyInfo.toBytesArray()) +
+                "&" + IRemoteRequest.TOKEN_CARD_CRYPTOGRAM + "="
+                + Util.specialURLEncode(card_cryptogram.toBytesArray()) +
+                "&" + IRemoteRequest.TOKEN_KEYSET + "=" + keySet;
+
+        CMS.debug("TKSRemoteRequestHandler.computeSessionKey: outgoing message: " + requestString);
+
         HttpResponse resp =
                 conn.send("computeSessionKey",
-                        IRemoteRequest.SERVER_SIDE_KEYGEN + "=" + serverKeygen +
-                                "&" + IRemoteRequest.TOKEN_CUID + "=" + Util.specialEncode(cuid) +
-                                "&" + IRemoteRequest.TOKEN_CARD_CHALLENGE + "=" + Util.specialEncode(card_challenge) +
-                                "&" + IRemoteRequest.TOKEN_HOST_CHALLENGE + "=" + Util.specialEncode(host_challenge) +
-                                "&" + IRemoteRequest.TOKEN_KEYINFO + "=" + Util.specialEncode(keyInfo) +
-                                "&" + IRemoteRequest.TOKEN_CARD_CRYPTOGRAM + "=" + Util.specialEncode(card_cryptogram) +
-                                "&" + IRemoteRequest.TOKEN_KEYSET + "=" + keySet);
+                        requestString
+                        );
 
         String content = resp.getContent();
 
@@ -338,7 +345,7 @@ public class TKSRemoteRequestHandler extends RemoteRequestHandler
             } else {
                 CMS.debug("TKSRemoteRequestHandler: computeRandomData(): got IRemoteRequest.TKS_RESPONSE_RandomData = "
                         + value);
-                response.put(IRemoteRequest.TKS_RESPONSE_RandomData, Util.specialDecode(value));
+                response.put(IRemoteRequest.TKS_RESPONSE_RandomData, Util.uriDecodeFromHex(value));
             }
             CMS.debug("TKSRemoteRequestHandler: computeRandomData(): ends.");
 
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 548e0ca..5e78616 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,6 +17,15 @@
 // --- END COPYRIGHT BLOCK ---
 package org.dogtagpki.server.tps.engine;
 
+import org.dogtagpki.server.tps.cms.TKSComputeSessionKeyResponse;
+import org.dogtagpki.server.tps.cms.TKSRemoteRequestHandler;
+import org.dogtagpki.tps.main.TPSBuffer;
+import org.dogtagpki.tps.main.TPSException;
+import org.dogtagpki.tps.msg.EndOp.TPSStatus;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+
 public class TPSEngine {
 
     public static final String CFG_DEBUG_ENABLE = "logging.debug.enable";
@@ -67,6 +76,13 @@ public class TPSEngine {
     public static final String CFG_ALLOW_NO_APPLET = "update.applet.emptyToken.enable";
     public static final String CFG_APPLET_UPDATE_REQUIRED_VERSION = "update.applet.requiredVersion";
     public static final String CFG_APPLET_DIRECTORY = "update.applet.directory";
+    public static final String CFG_APPLET_EXTENSION = "general.applet_ext";
+
+    public static final String CFG_CHANNEL_BLOCK_SIZE = "channel.blockSize";
+    public static final String CFG_CHANNEL_INSTANCE_SIZE = "channel.instanceSize";
+    public static final String CFG_CHANNEL_DEFKEY_VERSION = "channel.defKeyVersion";
+    public static final String CFG_CHANNEL_APPLET_MEMORY_SIZE = "channel.appletMemorySize";
+    public static final String CFG_CHANNEL_DEFKEY_INDEX = "channel.defKeyIndex";
 
     /* default values */
     public static final String CFG_DEF_CARDMGR_INSTANCE_AID = "A0000000030000";
@@ -75,7 +91,11 @@ public class TPSEngine {
     public static final String CFG_DEF_NETKEY_OLD_INSTANCE_AID = "A00000000101";
     public static final String CFG_DEF_NETKEY_OLD_FILE_AID = "A000000001";
     public static final String CFG_DEF_APPLET_SO_PIN = "000000000000";
-    public static final String CFG_ENABLED="Enabled";
+    public static final String CFG_ENABLED = "Enabled";
+
+    public static final int CFG_CHANNEL_DEF_BLOCK_SIZE = 242;
+    public static final int CFG_CHANNEL_DEF_INSTANCE_SIZE = 1800;
+    public static final int CFG_CHANNEL_DEF_APPLET_MEMORY_SIZE = 5000;
 
     /* External reg values */
 
@@ -99,6 +119,37 @@ public class TPSEngine {
         return rc;
     }
 
+    public TKSComputeSessionKeyResponse computeSessionKey(TPSBuffer cuid,
+            TPSBuffer keyInfo,
+            TPSBuffer card_challenge,
+            TPSBuffer host_challenge,
+            TPSBuffer card_cryptogram,
+
+            String connId) throws TPSException {
+
+        CMS.debug("TPSEngine.computeSessionKey");
+
+        TKSRemoteRequestHandler tks = new TKSRemoteRequestHandler(connId);
+
+        TKSComputeSessionKeyResponse resp = null;
+        try {
+            resp = tks.computeSessionKey(cuid, keyInfo, card_challenge, card_cryptogram, host_challenge);
+        } catch (EBaseException e) {
+            throw new TPSException("SecureChannel.computeSessionKey: Error computing session key!" + e,
+                    TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+        }
+
+        int status = resp.getStatus();
+        if (status != 0) {
+            CMS.debug("SecureChannel.computeSessionKey: Non zero status result: " + status);
+            throw new TPSException("SecureChannel.computeSessionKey: invalid returned status: " + status);
+
+        }
+
+        return resp;
+
+    }
+
     public boolean isTokenPresent(String cuid) {
         boolean present = false;
 
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 90c1a64..215eb05 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
@@ -18,17 +18,25 @@
 package org.dogtagpki.server.tps.processor;
 
 import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.Map;
 
 import org.dogtagpki.server.tps.TPSSession;
 import org.dogtagpki.server.tps.TPSSubsystem;
-import org.dogtagpki.server.tps.channel.SecureChannel.SecurityLevel;
+import org.dogtagpki.server.tps.channel.SecureChannel;
+import org.dogtagpki.server.tps.cms.TKSComputeRandomDataResponse;
+import org.dogtagpki.server.tps.cms.TKSComputeSessionKeyResponse;
+import org.dogtagpki.server.tps.cms.TKSRemoteRequestHandler;
 import org.dogtagpki.server.tps.engine.TPSEngine;
 import org.dogtagpki.tps.apdu.APDU;
 import org.dogtagpki.tps.apdu.APDUResponse;
+import org.dogtagpki.tps.apdu.ExternalAuthenticate.SecurityLevel;
 import org.dogtagpki.tps.apdu.GetData;
 import org.dogtagpki.tps.apdu.GetStatus;
 import org.dogtagpki.tps.apdu.GetVersion;
+import org.dogtagpki.tps.apdu.InitializeUpdate;
 import org.dogtagpki.tps.apdu.Select;
 import org.dogtagpki.tps.main.TPSBuffer;
 import org.dogtagpki.tps.main.TPSException;
@@ -36,11 +44,14 @@ import org.dogtagpki.tps.msg.BeginOp;
 import org.dogtagpki.tps.msg.EndOp.TPSStatus;
 import org.dogtagpki.tps.msg.TokenPDURequest;
 import org.dogtagpki.tps.msg.TokenPDUResponse;
+import org.mozilla.jss.CryptoManager.NotInitializedException;
+import org.mozilla.jss.pkcs11.PK11SymKey;
 
 import com.netscape.certsrv.apps.CMS;
 import com.netscape.certsrv.base.EBaseException;
 import com.netscape.certsrv.base.EPropertyNotFound;
 import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.symkey.SessionKey;
 
 public class TPSProcessor {
 
@@ -51,6 +62,13 @@ public class TPSProcessor {
     public static final int CPLC_MSN_INDEX = 41;
     public static final int CPLC_MSN_SIZE = 4;
 
+    public static final int INIT_UPDATE_DATA_SIZE = 28;
+    public static final int DIVERSIFICATION_DATA_SIZE = 10;
+    public static final int CARD_CRYPTOGRAM_OFFSET = 20;
+    public static final int CARD_CRYPTOGRAM_SIZE = 8;
+    public static final int CARD_CHALLENGE_OFFSET = 12;
+    public static final int CARD_CHALLENGE_SIZE = 8;
+
     private boolean isExternalReg;
 
     private TPSSession session;
@@ -166,7 +184,7 @@ public class TPSProcessor {
         return handleAPDURequest(get_status_apdu).getData();
     }
 
-    protected APDUResponse handleAPDURequest(APDU apdu) throws IOException, TPSException {
+    public APDUResponse handleAPDURequest(APDU apdu) throws IOException, TPSException {
 
         if (apdu == null) {
             throw new TPSException("TPSProcessor.handleAPDURequest: invalid incoming apdu!");
@@ -244,16 +262,244 @@ public class TPSProcessor {
 
     }
 
+    TPSBuffer computeRandomData(int dataSize, String connId) throws TPSException {
+
+        TKSRemoteRequestHandler tks = new TKSRemoteRequestHandler(connId);
+
+        TKSComputeRandomDataResponse data = null;
+
+        try {
+            data = tks.computeRandomData(dataSize);
+        } catch (EBaseException e) {
+            throw new TPSException("TPSProcessor.computeRandomData: Erorr getting random data from TKS!",
+                    TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+        }
+
+        int status = data.getStatus();
+
+        if (status != 0) {
+            throw new TPSException("TPSProcessor.computeRandomData: Erorr getting random data from TKS!",
+                    TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+        }
+
+        return data.getRandomData();
+    }
+
+    protected TPSBuffer initializeUpdate(byte keyVersion, byte keyIndex, TPSBuffer randomData) throws IOException,
+            TPSException {
+
+        CMS.debug("In TPS_Processor.initializeUpdate.");
+        InitializeUpdate initUpdate = new InitializeUpdate(keyVersion, keyIndex, randomData);
+
+        APDUResponse resp = handleAPDURequest(initUpdate);
+
+        if (!resp.checkResult()) {
+            CMS.debug("TPSProcessor.initializeUpdate: Failed intializeUpdate!");
+            throw new TPSException("TPSBuffer.initializeUpdate: Failed initializeUpdate!",
+                    TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+
+        }
+
+        TPSBuffer data = resp.getResultDataNoCode();
+
+        if (data.size() != INIT_UPDATE_DATA_SIZE) {
+            throw new TPSException("TPSBuffer.initializeUpdate: Invalid response from token!",
+                    TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+        }
+
+        return data;
+
+    }
+
+    protected SecureChannel setupSecureChannel(byte keyVersion, byte keyIndex, SecurityLevel securityLevel,
+            String connId)
+            throws IOException, TPSException {
+
+        //Assume generating host challenge on TKS, we no longer support not involving the TKS.
+
+        TPSBuffer randomData = computeRandomData(8, connId);
+        CMS.debug("TPSProcessor.setupSecureChannel: obtained randomData: " + randomData.toHexString());
+
+        TPSBuffer initUpdateResp = initializeUpdate(keyVersion, keyIndex, randomData);
+
+        TPSBuffer key_diversification_data = initUpdateResp.substr(0, DIVERSIFICATION_DATA_SIZE);
+        CMS.debug("TPSProcessor.setupSecureChannel: diversification data: " + key_diversification_data.toHexString());
+
+        TPSBuffer key_info_data = initUpdateResp.substr(DIVERSIFICATION_DATA_SIZE, 2);
+        CMS.debug("TPSProcessor.setupSecureChannel: key info data: " + key_info_data.toHexString());
+
+        TPSBuffer card_cryptogram = initUpdateResp.substr(CARD_CRYPTOGRAM_OFFSET, CARD_CRYPTOGRAM_SIZE);
+        CMS.debug("TPSProcessor.setupSecureChannel: card cryptogram: " + card_cryptogram.toHexString());
+
+        TPSBuffer card_challenge = initUpdateResp.substr(CARD_CHALLENGE_OFFSET, CARD_CHALLENGE_SIZE);
+        CMS.debug("TPSProcessor.setupSecureChannel: card challenge: " + card_challenge.toHexString());
+
+        SecureChannel channel = null;
+
+        try {
+            channel = generateSecureChannel(connId, key_diversification_data, key_info_data, card_challenge,
+                    card_cryptogram,
+                    randomData);
+        } catch (EBaseException e) {
+            throw new TPSException("TPSProcessor.setupSecureChannel: Can't set up secure channel: " + e,
+                    TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+        }
+
+        return channel;
+
+    }
+
+    protected SecureChannel generateSecureChannel(String connId, TPSBuffer keyDiversificationData,
+            TPSBuffer keyInfoData, TPSBuffer cardChallenge, TPSBuffer cardCryptogram, TPSBuffer hostChallenge)
+            throws EBaseException, TPSException {
+
+        CMS.debug("TPSProcessor.generateSecureChannel: entering..");
+
+        TPSEngine engine = getTPSEngine();
+
+        SecureChannel channel = null;
+        TPSBuffer hostCryptogram = null;
+
+        TKSComputeSessionKeyResponse resp = engine.computeSessionKey(keyDiversificationData, keyInfoData,
+                cardChallenge, hostChallenge, cardCryptogram,
+                connId);
+
+        hostCryptogram = resp.getHostCryptogram();
+
+        if (hostCryptogram == null) {
+            new TPSException("TPSProcessor.generateSecureChannel: No host cryptogram returned from token!",
+                    TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+
+        }
+
+        PK11SymKey sharedSecret = null;
+
+        try {
+            sharedSecret = getSharedSecretTransportKey(connId);
+        } catch (Exception e) {
+            CMS.debug(e);
+            throw new TPSException("TPSProcessor.generateSecureChannel: Can't get shared secret key!: " + e,
+                    TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+        }
+
+        PK11SymKey sessionKey = null;
+        PK11SymKey encSessionKey = null;
+        String tokenName = "Internal Key Storage Token";
+
+        try {
+            TPSBuffer sessionKeyWrapped = resp.getSessionKey();
+            TPSBuffer encSessionKeyWrapped = resp.getEncSessionKey();
+
+            sessionKey = SessionKey.UnwrapSessionKeyWithSharedSecret(tokenName, sharedSecret,
+                    sessionKeyWrapped.toBytesArray());
+
+            if (sessionKey == null) {
+                CMS.debug("TPSProcessor.generateSecureChannel: Can't extract session key!");
+                throw new TPSException("TPSProcessor.generateSecureChannel: Can't extract session key!",
+                        TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+            }
+            CMS.debug("TPSProcessor.generateSecureChannel: retrieved session key: " + sessionKey);
+
+            encSessionKey = SessionKey.UnwrapSessionKeyWithSharedSecret(tokenName, sharedSecret,
+                    encSessionKeyWrapped.toBytesArray());
+
+            if (encSessionKey == null) {
+                CMS.debug("TPSProcessor.generateSecureChannel: Can't extract enc session key!");
+                throw new TPSException("TPSProcessor.generateSecureChannel: Can't extract enc session key!",
+                        TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+            }
+
+            CMS.debug("TPSProcessor.generateSecureChannel: retrieved enc session key: " + encSessionKey);
+        } catch (Exception e) {
+            CMS.debug(e);
+            e.printStackTrace();
+            throw new TPSException("TPSProcessor.generateSecureChannel: Problem extracting session keys! " + e,
+                    TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+        }
+
+        TPSBuffer drmDesKey = null;
+        TPSBuffer kekDesKey = null;
+        TPSBuffer keyCheck = null;
+
+        if (checkServerSideKeyGen(connId)) {
+            //ToDo handle server side keygen.
+
+        }
+
+        channel = new SecureChannel(this, sessionKey, encSessionKey, drmDesKey,
+                kekDesKey, keyCheck, keyDiversificationData, cardChallenge,
+                cardCryptogram, hostChallenge, hostCryptogram);
+
+        return channel;
+    }
+
     protected String upgradeApplet(String operation, String new_version, SecurityLevel securityLevel,
-            Map<String, String> extensions, int startProgress, int endProgress) throws TPSException {
+            Map<String, String> extensions, String connId, int startProgress, int endProgress) throws IOException,
+            TPSException {
 
         String newVersion = null;
         boolean appletUpgraded = false;
+        String NetKeyAID = null;
+        String NetKeyPAID = null;
+
+        IConfigStore configStore = CMS.getConfigStore();
+
+        try {
+            //These defaults are well known, it is safe to use them.
+
+            NetKeyAID = configStore.getString(TPSEngine.CFG_APPLET_NETKEY_INSTANCE_AID,
+                    TPSEngine.CFG_DEF_NETKEY_INSTANCE_AID);
+            CMS.debug("In TPS_Processor.upgradeApplet. CardManagerAID: " + " NetKeyAID: " + NetKeyAID);
+            NetKeyPAID = configStore.getString(TPSEngine.CFG_APPLET_NETKEY_FILE_AID, TPSEngine.CFG_DEF_NETKEY_FILE_AID);
+
+        } catch (EBaseException e1) {
+            CMS.debug("TPS_Processor.upgradeApplet: Internal Error obtaining mandatory config values. Error: " + e1);
+            throw new TPSException("TPS error getting config values from config store.",
+                    TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+        }
+
+        TPSBuffer netkeyAIDBuff = new TPSBuffer(NetKeyAID);
+        TPSBuffer netkeyPAIDBuff = new TPSBuffer(NetKeyPAID);
+
+        //Not all of these used yet, but will be
+        //ToDo
+        int channelBlockSize = getChannelBlockSize();
+        int channelInstanceSize = getChannelInstanceSize();
+        int channelAppletMemSize = getAppletMemorySize();
+        int defKeyVersion = getChannelDefKeyVersion();
+        int defKeyIndex = getChannelDefKeyIndex();
+        byte[] appletData = null;
 
         String directory = getAppletDirectory(operation);
 
         CMS.debug("TPSProcessor.upgradeApplet: applet target directory: " + directory);
 
+        String appletFileExt = getAppletExtension();
+
+        String appletFilePath = directory + "/" + new_version + "." + appletFileExt;
+
+        CMS.debug("TPSProcessor.upgradeApplet: targe applet file name: " + appletFilePath);
+
+        //Not ready to use this yet.
+        //ToDo
+
+        appletData = getAppletFileData(appletFilePath);
+
+        APDUResponse select = selectApplet((byte) 0x04, (byte) 0x00, netkeyAIDBuff);
+
+        if (!select.checkResult()) {
+            throw new TPSException("TPSProcessor.format: Can't selelect the card manager!");
+        }
+
+        SecureChannel channel = setupSecureChannel((byte) defKeyVersion, (byte) defKeyIndex, securityLevel, connId);
+
+        channel.externalAuthenticate();
+        channel.deleteFileX(netkeyAIDBuff);
+        channel.deleteFileX(netkeyPAIDBuff);
+
+        // Next step will be to load the applet file to token.
+        // ToDo:
+
         //ToDo actually finish this later.
         if (appletUpgraded == false) {
             throw new TPSException("TPSProcessor.upgradeApplet: Error upgrading applet",
@@ -263,6 +509,32 @@ public class TPSProcessor {
         return newVersion;
     }
 
+    protected byte[] getAppletFileData(String appletFilePath) throws IOException, TPSException {
+
+        if (appletFilePath == null) {
+            throw new TPSException("TPSProcessor.getAppletFileData: Invalid applet file name.",
+                    TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+        }
+
+        byte[] contents = null;
+        try {
+            Path path = Paths.get(appletFilePath);
+            contents = Files.readAllBytes(path);
+
+        } catch (IOException e) {
+            CMS.debug("TPSProcessor.getAppletFileData: IOException " + e);
+            throw e;
+        } catch (Exception e) {
+            CMS.debug("PSProcessor.getAppletFileData: Exception: " + e);
+            throw new TPSException("TPSProcessor.getAppletFileData: Exception: " + e,
+                    TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+        }
+
+        CMS.debug("TPSProcessor.getAppletFileData: data: " + contents);
+
+        return contents;
+    }
+
     protected void format(BeginOp message) throws TPSException, IOException {
 
         IConfigStore configStore = CMS.getConfigStore();
@@ -376,8 +648,10 @@ public class TPSProcessor {
 
         SecurityLevel secLevel = SecurityLevel.SECURE_MSG_MAC_ENC;
 
+        String tksConnId = "tks1";
+
         String newKeyVersion = upgradeApplet(TPSEngine.OP_FORMAT_PREFIX, appletRequiredVersion, secLevel,
-                message.getExtensions(),
+                message.getExtensions(), tksConnId,
                 10, 90);
 
         CMS.debug("TPSProcessor.format: upgraded aplet version: " + newKeyVersion);
@@ -405,6 +679,22 @@ public class TPSProcessor {
 
     }
 
+    boolean checkServerSideKeyGen(String connId) throws TPSException {
+
+        boolean result;
+        IConfigStore configStore = CMS.getConfigStore();
+
+        String profileConfig = "conn." + connId + "." + ".serverKeygen";
+
+        try {
+            result = configStore.getBoolean(profileConfig, false);
+        } catch (EBaseException e) {
+            throw new TPSException("TPSProcessor: checkServerSideKeyGen: Internal error obtaining config value!");
+        }
+
+        return result;
+    }
+
     void checkAllowNoAppletToken(String operation) throws TPSException {
         boolean allow = true;
         IConfigStore configStore = CMS.getConfigStore();
@@ -470,6 +760,23 @@ public class TPSProcessor {
 
     }
 
+    protected String getAppletExtension() throws TPSException {
+        IConfigStore configStore = CMS.getConfigStore();
+        String extension = null;
+        String extensionConfig = TPSEngine.CFG_APPLET_EXTENSION;
+
+        try {
+            extension = configStore.getString(extensionConfig, "ijc");
+        } catch (EBaseException e) {
+            throw new TPSException("TPSProcessor.getAppletExtension: Internal error finding config value.");
+
+        }
+
+        CMS.debug("TPSProcessor.getAppletExtension: returning: " + extension);
+
+        return extension;
+    }
+
     protected String getAppletDirectory(String operation) throws TPSException {
 
         IConfigStore configStore = CMS.getConfigStore();
@@ -492,6 +799,146 @@ public class TPSProcessor {
         return directory;
     }
 
+    protected int getChannelBlockSize() throws TPSException {
+        IConfigStore configStore = CMS.getConfigStore();
+        int blockSize = 0;
+        try {
+            blockSize = configStore.getInteger(TPSEngine.CFG_CHANNEL_BLOCK_SIZE, TPSEngine.CFG_CHANNEL_DEF_BLOCK_SIZE);
+
+        } catch (EBaseException e) {
+            throw new TPSException("TPSProcessor.getChannelBlockSize: Internal error finding config value: " + e,
+                    TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+
+        }
+
+        CMS.debug("TPSProcess.getChannelBlockSize: returning: " + blockSize);
+        return blockSize;
+
+    }
+
+    protected int getChannelInstanceSize() throws TPSException {
+        IConfigStore configStore = CMS.getConfigStore();
+        int instanceSize = 0;
+        try {
+            instanceSize = configStore.getInteger(TPSEngine.CFG_CHANNEL_INSTANCE_SIZE,
+                    TPSEngine.CFG_CHANNEL_DEF_INSTANCE_SIZE);
+
+        } catch (EBaseException e) {
+            throw new TPSException("TPSProcessor.getChannelInstanceSize: Internal error finding config value: " + e,
+                    TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+
+        }
+
+        CMS.debug("TPSProcess.getChannelInstanceSize: returning: " + instanceSize);
+
+        return instanceSize;
+
+    }
+
+    protected int getAppletMemorySize() throws TPSException {
+        IConfigStore configStore = CMS.getConfigStore();
+        int memSize = 0;
+        try {
+            memSize = configStore.getInteger(TPSEngine.CFG_CHANNEL_APPLET_MEMORY_SIZE,
+                    TPSEngine.CFG_CHANNEL_DEF_APPLET_MEMORY_SIZE);
+
+        } catch (EBaseException e) {
+            throw new TPSException("TPSProcessor.getAppletMemorySize: Internal error finding config value: " + e,
+                    TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+
+        }
+        CMS.debug("TPSProcess.getAppletMemorySize: returning: " + memSize);
+
+        return memSize;
+    }
+
+    protected int getChannelDefKeyVersion() throws TPSException {
+        IConfigStore configStore = CMS.getConfigStore();
+        int ver = 0;
+        try {
+            ver = configStore.getInteger(TPSEngine.CFG_CHANNEL_DEFKEY_VERSION, 0x0);
+
+        } catch (EBaseException e) {
+            throw new TPSException("TPSProcessor.getChannelDefKeyVersion: Internal error finding config value: " + e,
+                    TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+
+        }
+
+        CMS.debug("TPSProcessor.getChannelDefKeyVersion: " + ver);
+
+        return ver;
+
+    }
+
+    protected int getChannelDefKeyIndex() throws TPSException {
+        IConfigStore configStore = CMS.getConfigStore();
+        int index = 0;
+        try {
+            index = configStore.getInteger(TPSEngine.CFG_CHANNEL_DEFKEY_INDEX, 0x0);
+
+        } catch (EBaseException e) {
+            throw new TPSException("TPSProcessor.getChannelDefKeyVersion: Internal error finding config value: " + e,
+                    TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+
+        }
+
+        CMS.debug("TPSProcessor.getChannelDefKeyIndex: " + index);
+
+        return index;
+
+    }
+
+    protected PK11SymKey getSharedSecretTransportKey(String connId) throws TPSException, NotInitializedException {
+
+        IConfigStore configStore = CMS.getConfigStore();
+        String sharedSecretName = null;
+        try {
+            String configName = "conn." + connId + ".tksSharedSymKeyName";
+            sharedSecretName = configStore.getString(configName, "sharedSecret");
+
+        } catch (EBaseException e) {
+            throw new TPSException("TPSProcessor.getSharedSecretTransportKey: Internal error finding config value: "
+                    + e,
+                    TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+
+        }
+
+        CMS.debug("TPSProcessor.getSharedSecretTransportKey: calculated key name: " + sharedSecretName);
+
+        String symmKeys = null;
+        boolean keyPresent = false;
+        try {
+            symmKeys = SessionKey.ListSymmetricKeys("internal");
+            CMS.debug("TPSProcessor.getSharedSecretTransportKey: symmKeys List: " + symmKeys);
+        } catch (Exception e) {
+            // TODO Auto-generated catch block
+            CMS.debug(e);
+        }
+
+        for (String keyName : symmKeys.split(",")) {
+            if (sharedSecretName.equals(keyName)) {
+                CMS.debug("TPSProcessor.getSharedSecret: shared secret key found!");
+                keyPresent = true;
+                break;
+            }
+
+        }
+
+        if (!keyPresent) {
+            throw new TPSException("TPSProcessor.getSharedSecret: Can't find shared secret!",
+                    TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+        }
+
+        // We know for now that shared secret is on this token
+        String tokenName = "Internal Key Storage Token";
+        PK11SymKey sharedSecret = SessionKey.GetSymKeyByName(tokenName, sharedSecretName);
+
+        CMS.debug("TPSProcessor.getSharedSecret: SymKey returns: " + sharedSecret);
+
+        return sharedSecret;
+
+    }
+
     public boolean getIsExternalReg() {
         return isExternalReg;
     }
@@ -755,6 +1202,14 @@ public class TPSProcessor {
 
     }
 
+    public TPSEngine getTPSEngine() {
+        TPSSubsystem subsystem =
+                (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+
+        return subsystem.getEngine();
+
+    }
+
     public static void main(String[] args) {
     }
 
-- 
1.8.3.1

